Compare commits

...

50 Commits

Author SHA1 Message Date
Preston Van Loon
dc5ed7a80e Update deposit contract default value for topaz (#5431)
* Update for topaz
* Update block number for deposit contract
2020-04-14 23:00:36 +00:00
terence tsao
cb045dd0e3 Align code base to v0.11 (#5127)
* 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 commit 3ec2a0f9e0.

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 commit df9a534826.

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
* Revert "Remove deprecated parameters (#5249)" (#5276)

This reverts commit 7d17c9ac34.
* 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 commit 47e5a2cf96.
* 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 commit e5aef1686e.
* 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 commit a8d32d504a.
* 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 commit bbcd895db5.

* Revert "Remove keystore keymanager from validator (#5236)"

This reverts commit 46008770c1.

* Revert "Update eth2 wallet keymanager (#4984)"

This reverts commit 7f7ef43f21.

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
2020-04-14 20:27:03 +00:00
Victor Farazdagi
748d513c62 proper error checking and type assertions (#5424)
* proper error checking and type assertions
2020-04-14 16:41:09 +00:00
terence tsao
3b9a03d517 State service clean up - better cold state getter (#5393)
* Update load cold states by root and slot

* Update cold tests

* Add a way to recover state summary

* Short circuit slot 0 to return genesis state

* Short circuit if there's no block in DB

* Fixed test

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-04-13 11:32:02 -05:00
Preston Van Loon
d5ddd012bc Enforce error handling and checking type assertions (#5403)
* Enforce error handling and checking type assertions
* Reference issue #5404 in the TODO message
* doc description
* Merge branch 'master' into errcheck
* fix tests and address @nisdas feedbacK
* gaz
* fix docker image
2020-04-13 04:11:09 +00:00
terence tsao
a85bf9305d Fixed a bug in ActivatedValidatorIndices (#5400) 2020-04-12 16:20:50 -07:00
Preston Van Loon
c76034147e Set ssz cache enabled by default (#5398)
* Set ssz cache enabled by default
* gofmt
2020-04-12 21:33:26 +00:00
Ivan Martinez
d8c57541e4 Validator client cleanup (#5389)
* Validator client status optimizations
* Reorder WaitForSync
* Change log to switch case
* Show activation epoch
* Change sync timing to half slot, inaccurate previously
* Merge branch 'master' into validator-imporve
2020-04-12 02:05:23 +00:00
Jim McDonald
28a9adc49b Add missing block fields to log (#5394) 2020-04-11 16:04:05 -07:00
terence tsao
e59721f264 State service clean up - better migration (#5391) 2020-04-11 13:54:19 -07:00
Ivan Martinez
40f7b258eb Add log-file flag to bootnode (#5392)
* Add log-file flag to bootnode
* Merge branch 'master' into bootnode-add-logfile
2020-04-11 20:12:48 +00:00
Preston Van Loon
8c9ae8e3bf Use state validator index map (#5383)
* remove validator index tracking from DB

* Builds production code path

* tests build

* fix tests

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-04-11 14:47:22 -05:00
Nishant Das
29f43190fc Revert "Validator client improvements" (#5388)
* Revert "Validator client improvements (#5300)"

This reverts commit 06db5f6471.
2020-04-11 03:31:01 +00:00
Preston Van Loon
b69c76c879 Remove next slot requirement for processing attestations (#5384)
* Remove next slot requirement for processing attestations
2020-04-11 00:12:47 +00:00
Preston Van Loon
ca0912e5d8 Add probot no-response configuration (#5382)
* Add probot no-response configuration
* use existing label Need-Info
2020-04-10 21:32:34 +00:00
Preston Van Loon
2e570d7427 Update CODEOWNERS (#5379)
* Update CODEOWNERS
2020-04-10 19:30:13 +00:00
Preston Van Loon
973a0a89b5 Update state root cache to fuzz in parallel (#5364)
* Update state root cache to fuzz in parallel

* confirmed arrays passing

Co-authored-by: rauljordan <raul@prysmaticlabs.com>
2020-04-10 13:12:59 -05:00
terence tsao
1d8b207d7c Fix incorrect proposer slashing domain calculation (#5369)
* StartSlot != SlotToEpoch
* Merge refs/heads/master into fix-proposer-slashing
2020-04-10 00:19:13 +00:00
Preston Van Loon
7a5010ecea Add roughtime static code analysis and fix all violations (#5370)
* Add roughtime static code analysis and fix all violations
* Merge branch 'master' into enforce-roughtime
2020-04-09 23:35:42 +00:00
Raul Jordan
7b8bad35e7 update readme (#5368) 2020-04-09 17:22:44 -05:00
Preston Van Loon
fa435d39bb Update bazel to 3.0.0 (#5363)
* Update bazel to 3.0.0
* Merge branch 'master' into update-bazelversion
2020-04-09 21:00:34 +00:00
Ivan Martinez
159ef3d702 Add cache to Eth1 RPC functions (#5347)
* ADd cache to other function and add comment

* Add cache for eth1data

* Fix test

* Reset cache before test

* Move cache to beacon node end

* Add metrics

* Disable blocktimebyheight cache

* Fix time
2020-04-09 14:29:09 -05:00
Ivan Martinez
06db5f6471 Validator client improvements (#5300)
* Look into what makes the validator client slow
* Comment
* Refactor status function to be cleaner
* Use timings from params
* Improve coverage
* Remove unneeded lock in chainstart
* Reorganize validator logging
* Merge branch 'master' of https://github.com/prysmaticlabs/prysm into optimize-validator
* cleanup
* Fix bug
* Undo depositbypukey changes
* Merge branch 'master' of https://github.com/prysmaticlabs/prysm into optimize-validator
* Fix deposit cache
* Fix multiple status test
* Merge branch 'master' of https://github.com/prysmaticlabs/prysm into optimize-validator
* Remove logs
* Remove unused import
* Add comment
* comment
* Remove comments
* Merge branch 'master' into optimize-validator
* Undo time change for activation
* Merge branch 'optimize-validator' of https://github.com/0xKiwi/Prysm into optimize-validator
* Fix check for sync
* Change value back to half slot
* comment
* Rephrase logs
* Merge branch 'master' into optimize-validator
2020-04-08 14:41:00 +00:00
terence tsao
a7bee79988 Use the config value (#5342) 2020-04-07 20:11:19 -05:00
Preston Van Loon
0fff07a93b Create CODEOWNERS (#5330)
* Create CODEOWNERS
* Move codeowners file to proper location
2020-04-07 03:22:43 +00:00
Preston Van Loon
70e64be8d6 Remove old cross compile starlark rules (#5329)
* Add buildbuddy BES (#5325)

* Add buildbuddy BES
* Merge branch 'master' of github.com:prysmaticlabs/prysm
* remove old cross compile rules
2020-04-07 03:01:20 +00:00
Preston Van Loon
33ffa34ea7 Use less goroutines in validator runner (#5328)
* Add buildbuddy BES (#5325)

* Add buildbuddy BES
* Use less goroutines when running validator
* per-role based goroutines
* Merge branch 'master' into validator-issue-4702
2020-04-07 01:34:01 +00:00
Preston Van Loon
bcebf63cab Add buildbuddy BES (#5325)
* Add buildbuddy BES
2020-04-07 00:54:21 +00:00
terence tsao
d6f7d67ee9 Interop batch save validator indices (#5320)
* Batch save indices

* Update beacon-chain/interop-cold-start/service.go

Co-Authored-By: shayzluf <thezluf@gmail.com>

* Update beacon-chain/interop-cold-start/service.go

Co-Authored-By: shayzluf <thezluf@gmail.com>

* Update service.go

Co-authored-by: shayzluf <thezluf@gmail.com>
2020-04-06 13:40:42 -05:00
Chris Hobcroft
b7afc90266 Fixed typo in stdout log (#5317)
"Round robin**g** sync request failed"

changed to

"Round robin sync request failed"
2020-04-06 20:34:24 +08:00
Ivan Martinez
4b64a75c77 Remove unused validator protos (#5304)
* Remove unneeded protos

* Remove unused api point

* Gazelle

* Fix visibility

* Rename

* Change type

* Use iota for validator role
2020-04-06 11:24:24 +08:00
Ivan Martinez
fcf131412f Fix cluster in bazel and remove unused file (#5316)
* Fix cluster vazel

* remove unneeded file
2020-04-06 10:23:05 +08:00
Mattia
279dd5ac8d fix broken links in readme (#5313)
* fix broken links in readme

Activating a validator is referencing a broken link. This commit points to the new location of the documentation.
* Merge branch 'master' into master
2020-04-05 20:19:36 +00:00
Jim McDonald
c7a4fcd098 Reduce noise in validator logs (#5307)
* Reduce number of info-level messages on start of validator

* Test service, not log entry

* Gazelle

Co-authored-by: Nishant Das <nishdas93@gmail.com>
Co-authored-by: Ivan Martinez <ivanthegreatdev@gmail.com>
2020-04-05 15:36:18 -04:00
Ivan Martinez
07753189fd Remove unused slashing protos (#5308) 2020-04-05 12:50:52 -04:00
terence tsao
e162d27634 Save init synced cached blocks to db (#5309) 2020-04-04 16:25:04 -07:00
Victor Farazdagi
f440c815f9 Init sync update highest slot (#5298)
* updates highest slot before wrapping up
* more verbose error message
* error w/o stack
* revert back
2020-04-04 17:11:38 +03:00
Preston Van Loon
9aac572c21 Update @terencechain public key. (#5301)
* Update @terencechain public key.
2020-04-03 22:01:44 +00:00
Preston Van Loon
7bdd1355b8 Add maligned struct static check (#5296)
* Add maligned static check
* Add file, oops
* lint
2020-04-03 05:09:15 +00:00
Preston Van Loon
477b014bd1 Set a max limit for decoding ssz objects from p2p (#5295)
* Set a max limit for decoding ssz objects from p2p
2020-04-02 23:51:54 +00:00
terence tsao
ec7f7aebdc Clear init sync blocks on the correct line (#5294)
* Add disable-init-sync-batch-save-blocks
* Fix test
* Remove flag
* Merge branch 'master' into disable-init-sync-batch-save
* Quick fix
* Quick fix
* Merge branch 'master' of github.com:prysmaticlabs/prysm into disable-init-sync-batch-save
* Merge branch 'disable-init-sync-batch-save' of github.com:prysmaticlabs/prysm into disable-init-sync-batch-save
* Clear init sync blocks at the right place
2020-04-02 22:27:51 +00:00
terence tsao
3544ed2818 Invert init-sync-batch-save-blocks flag for v0.11 (#5293) 2020-04-02 14:46:14 -07:00
Victor Farazdagi
b43e43b4a9 Init sync release queue (#5286)
* fix naming slot -> epoch

* better handling of long periods w/o finality

* bazel

* fixes issue with pointer goint to far ahead

* adds func comment

* hides original sync behind --disable-init-sync-queue

* adds func comment

* deprecated

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2020-04-02 11:06:32 -05:00
Victor Farazdagi
c26a492225 Init sync optimizations (#5284)
* fix naming slot -> epoch
* better handling of long periods w/o finality
* fixes issue with pointer going too far ahead
2020-04-02 06:54:05 +03:00
shayzluf
0df12261a1 slasher retrieve and cache validator public key (#5220)
* cache and retrieval of validator public keys

* fix comments

* fix comment

* fix variables

* gaz

* ivan feedback fixes

* goimports

* fix test

* comments on in line slice update

Co-authored-by: terence tsao <terence@prysmaticlabs.com>
2020-04-02 06:08:23 +03:00
Raul Jordan
f385a1dea6 Release Skip Slot Cache to All (#5280)
* no more skip slot cache

* imports

* deprecated

* fix flakeyness

* disable in e2e

* build

* fix viz

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-04-01 19:09:54 -07:00
Preston Van Loon
8376fb36ca Enable slashing protection in validator by default (#5278)
* Invert slashing protection validator flags for issue #5267
* remove from e2e flags
* Make error level
* Merge refs/heads/master into flip-propose
2020-04-01 23:17:32 +00:00
Jim McDonald
02b238bda2 Add latch for proposer warnings (#5258)
Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: Ivan Martinez <ivanthegreatdev@gmail.com>
2020-04-01 17:28:02 -05:00
Ivan Martinez
3dd5576e33 Improvement, flake fixes (#5263) 2020-04-01 10:23:23 -05:00
terence tsao
df9a534826 Regen historical states for new-state-mgmt compatibility (#5261) 2020-03-31 16:54:24 -07:00
491 changed files with 14845 additions and 12508 deletions

View File

@@ -15,7 +15,7 @@ run --host_force_python=PY2
# Network sandboxing only works on linux.
--experimental_sandbox_default_allow_network=false
# Use minimal protobufs at runtime
# Use mainnet protobufs at runtime
run --define ssz=mainnet
test --define ssz=mainnet
build --define ssz=mainnet

View File

@@ -1 +1 @@
2.1.1
3.0.0

View File

@@ -46,3 +46,6 @@ build --flaky_test_attempts=5
# Enable kafka for CI tests only.
test --define kafka_enabled=true
build --bes_backend=grpcs://builds.prylabs.net:1985
build --bes_results_url=https://builds.prylabs.net/invocation/

5
.github/CODEOWNERS vendored Normal file
View File

@@ -0,0 +1,5 @@
# Automatically require code review from core-team.
* @prysmaticlabs/core-team
# Starlark code owners
*.bzl @prestonvanloon

13
.github/no-response.yml vendored Normal file
View File

@@ -0,0 +1,13 @@
# Configuration for probot-no-response - https://github.com/probot/no-response
# Number of days of inactivity before an Issue is closed for lack of response
daysUntilClose: 14
# Label requiring a response
responseRequiredLabel: Need-Info
# Comment to post when closing an Issue for lack of response. Set to `false` to disable
closeComment: >
This issue has been automatically closed because there has been no response
to our request for more information from the original author. With only the
information that is currently in the issue, we don't have enough information
to take action. Please reach out if you have or find the answers we need so
that we can investigate further.

View File

@@ -4,23 +4,23 @@ Hash: SHA512
Contact: mailto:security@prysmaticlabs.com
Encryption: openpgp4fpr:0AE0051D647BA3C1A917AF4072E33E4DF1A5036E
Encryption: openpgp4fpr:341396BAFACC28C5082327F889725027FC8EC0D4
Encryption: openpgp4fpr:8B7814F1B221A8E8AA465FC7BDBF744ADE1A0033
Encryption: openpgp4fpr:FEE44615A19049DF0CA0C2735E2B7E5734DFADCB
Preferred-Languages: en
Canonical: https://github.com/prysmaticlabs/prysm/tree/master/.well-known/security.txt
-----BEGIN PGP SIGNATURE-----
iQIzBAEBCgAdFiEECuAFHWR7o8GpF69AcuM+TfGlA24FAlzi0WgACgkQcuM+TfGl
A241pw/+Ks3Hxx8eGbjRIeuncuK811FkCiofNJS+MY2p4W2/tIrk48DtLRx8/k5L
Dh1QyypZsqUgofrK7PbGVdEin6oEb2jYbTWUarAVTbhlsUdM4YcxwpgmGVslW7+C
Hm8wMasQZhCkFfakzhfKX5hIQoFaFI/OvtVKIQsodP8dAieCDaGmtfq1Bs1LgFqi
KrpeEdC2XbBQs33ADheC5SdGT1mnatP3VX8cOhLsfoPksYgTSpwK0clkoWs1eZOQ
l1ImfW/FJCpSndBWgBR503ZgaU3Ic+5qxmAIuUP4chl0DFRMlPFEM5OWC6JkkCOd
5kKrXGRmrhgtQg+pA3zqJnFItRj7gxPBA/ypxCkKPrLEkRvbdpdZEl5vAlYkeBL6
iKSLHnMswGKldiYxy7ofam5bM3myhYYNFb25boV5pRptrnoUmWOACHioBGQHwWNt
B0XktD0j7+pCCiJyyYxmOnElsk/Y/u4Tv5pYWvfFuxTF2XOg+P/EH64AIFLWgB1U
VnITxhakxqejCBxZkuVCFNSzt+TXG0NS9EIj/UOYBY+wxrBZ62ITjdA16RS/3n3z
DuIDtxOOwUumbOO32+a5zIb+ARmnocYJviI7FuENb01/U6qb+nm9hQI6oIpSCNsv
Pb4O/ZlOx70U/7mt4Xn/dTKH9bnKOOVhOw00KJWFfAce73AVnLA=
=Uhqg
iQIzBAEBCgAdFiEECuAFHWR7o8GpF69AcuM+TfGlA24FAl6HrcwACgkQcuM+TfGl
A26voQ/8DFB5wUHP0uyY8k7FGbxhLzSeImxomnUHJaUGfdczbCdYPMEHc9zI1iZP
6LRiy9wS6qhqj/GSKVwvDPr+ZymXuV3L22GOP2lRhl7Z9Mm21ZJNOcoQBFOZnyHu
DAy9HeTmeuJxYkf8weqZYXyzEoKJBDmfuWmEFjrtMcFXUfT3aJn1E2A/AQdcVQIC
9L+iGWwFwjsPhcfaMuwcB7QMheDO6KSB7XPPCbrZ036Np8UTZ4qbZ5y73tlfkcOc
tYTrMSPtS4eNutiDOP5Np36cLzRtNpm/BziAK+7ZKiYY0HI5h9IkCTLO4x2UmAMX
sPoeaAB5z2QLIwmU9J2NhJrwiNMGTpJ+0bowy8U4cgzAX20CXVjRqGhy+cir8Ewg
DjEGjWINUw6W0yzJp0mKSKzuOhdTTmzIYBeMBsyce+pgN1KGFCxeIwxGxyJzADdw
mYQdljRXn4yEYP/KEpu/F2o8L4ptRO2jZWKvTvdzSSGGSyKyF4HsIRJ7m98DaB6S
0oGq1KpbKKTbQi5g8UShGV2gPeMCs5ZIIqK2b/cRzUet18aUuofLmR4lkKZa9yEG
rbzuJq/gB2vgQwExUEgVQ3/DfVc+y80e3YZ5s+rzV0vbLxl4Gh4yExpLo7hRf9iY
EFvMzH+BEEb5VfCwByZyV1BmesZVIosr7K6UmVtPe0bZGvv3uIg=
=5qpD
-----END PGP SIGNATURE-----

View File

@@ -4,7 +4,6 @@ load("@com_github_atlassian_bazel_tools//goimports:def.bzl", "goimports")
load("@io_kubernetes_build//defs:run_in_workspace.bzl", "workspace_binary")
load("@io_bazel_rules_go//go:def.bzl", "nogo")
load("@graknlabs_bazel_distribution//common:rules.bzl", "assemble_targz", "assemble_versioned")
load("//tools:binary_targets.bzl", "binary_targets", "determine_targets")
prefix = "github.com/prysmaticlabs/prysm"
@@ -104,40 +103,17 @@ nogo(
"@org_golang_x_tools//go/analysis/passes/assign:go_tool_library",
"@org_golang_x_tools//go/analysis/passes/inspect:go_tool_library",
"@org_golang_x_tools//go/analysis/passes/asmdecl:go_tool_library",
"//tools/analyzers/maligned:go_tool_library",
"//tools/analyzers/roughtime:go_tool_library",
"//tools/analyzers/errcheck:go_tool_library",
],
)
assemble_versioned(
name = "assemble-versioned-all",
tags = ["manual"],
targets = [
":assemble-{}-{}-targz".format(
pair[0],
pair[1],
)
for pair in binary_targets
],
version_file = "//:VERSION",
)
common_files = {
"//:LICENSE.md": "LICENSE.md",
"//:README.md": "README.md",
}
[assemble_targz(
name = "assemble-{}-{}-targz".format(
pair[0],
pair[1],
),
additional_files = determine_targets(pair, common_files),
output_filename = "prysm-{}-{}".format(
pair[0],
pair[1],
),
tags = ["manual"],
) for pair in binary_targets]
toolchain(
name = "built_cmake_toolchain",
toolchain = "@rules_foreign_cc//tools/build_defs/native_tools:built_cmake",

223
README.md
View File

@@ -1,232 +1,17 @@
# Prysm: An Ethereum 2.0 Client Written in Go
[![Build status](https://badge.buildkite.com/b555891daf3614bae4284dcf365b2340cefc0089839526f096.svg?branch=master)](https://buildkite.com/prysmatic-labs/prysm)
[![ETH2.0_Spec_Version 0.9.3](https://img.shields.io/badge/ETH2.0%20Spec%20Version-v0.9.3-blue.svg)](https://github.com/ethereum/eth2.0-specs/tree/v0.9.3)
[![ETH2.0_Spec_Version 0.11.1](https://img.shields.io/badge/ETH2.0%20Spec%20Version-v0.11.1-blue.svg)](https://github.com/ethereum/eth2.0-specs/tree/v0.11.1)
[![Discord](https://user-images.githubusercontent.com/7288322/34471967-1df7808a-efbb-11e7-9088-ed0b04151291.png)](https://discord.gg/KSA7rPr)
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/prysmaticlabs/geth-sharding?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
This is the core repository for Prysm, a [Golang](https://golang.org/) implementation of the Ethereum 2.0 client specifications developed by [Prysmatic Labs](https://prysmaticlabs.com).
### Need assistance?
A more detailed set of installation and usage instructions as well as breakdowns of each individual component are available in the [official documentation portal](https://docs.prylabs.network). If you still have questions, feel free to stop by either our [Discord](https://discord.gg/KSA7rPr) or [Gitter](https://gitter.im/prysmaticlabs/geth-sharding?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) and a member of the team or our community will be happy to assist you.
### Getting Started
A detailed set of installation and usage instructions as well as breakdowns of each individual component are available in the [official documentation portal](https://docs.prylabs.network). If you still have questions, feel free to stop by either our [Discord](https://discord.gg/KSA7rPr) or [Gitter](https://gitter.im/prysmaticlabs/geth-sharding?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) and a member of the team or our community will be happy to assist you.
### Come join the testnet!
Participation is now open to the public for our Ethereum 2.0 phase 0 testnet release. Visit [prylabs.net](https://prylabs.net) for more information on the project or to sign up as a validator on the network.
# Table of Contents
- [Dependencies](#dependencies)
- [Installation](#installing-prysm)
- [Build via Docker](#build-via-docker)
- [Build via Bazel](#build-via-bazel)
- [Connecting to the public testnet: running a beacon node](#connecting-to-the-testnet-running-a-beacon-node)
- [Running via Docker](#running-via-docker)
- [Running via Bazel](#running-via-bazel)
- [Staking ETH: running a validator client](#staking-eth-running-a-validator-client)
- [Activating your validator: depositing 3.2 Goerli ETH](#activating-your-validator-depositing-32-gerli-eth)
- [Starting the validator with Bazel](#starting-the-validator-with-bazel)
- [Setting up a local ETH2 development chain](#setting-up-a-local-eth2-development-chain)
- [Installation and dependencies](#installation-and-dependencies)
- [Running a local beacon node and validator client](#running-a-local-beacon-node-and-validator-client)
- [Testing Prysm](#testing-prysm)
- [Contributing](#contributing)
- [License](#license)
## Dependencies
Prysm can be installed either with Docker **\(recommended\)** or using our build tool, Bazel. The below instructions include sections for performing both.
#### **For Docker installations:**
* The latest release of [Docker](https://docs.docker.com/install/)
#### **For Bazel installations:**
* The latest release of [Bazel](https://docs.bazel.build/versions/master/install.html)
* The latest release of `cmake`
* The latest release of `git`
* A modern UNIX operating system \(macOS included\)
## Installing Prysm
### Build via Docker
1. Ensure you are running the most recent version of Docker by issuing the command:
```text
docker -v
```
2. To pull the Prysm images, issue the following commands:
```text
docker pull gcr.io/prysmaticlabs/prysm/validator:latest
docker pull gcr.io/prysmaticlabs/prysm/beacon-chain:latest
```
This process will also install any related dependencies.
### Build via Bazel
1. Open a terminal window. Ensure you are running the most recent version of Bazel by issuing the command:
```text
bazel version
```
2. Clone Prysm's [main repository](https://github.com/prysmaticlabs/prysm) and enter the directory:
```text
git clone https://github.com/prysmaticlabs/prysm
cd prysm
```
3. Build both the beacon chain node and the validator client:
```text
bazel build //beacon-chain:beacon-chain
bazel build //validator:validator
```
Bazel will automatically pull and install any dependencies as well, including Go and necessary compilers.
## Connecting to the testnet: running a beacon node
Below are instructions for initialising a beacon node and connecting to the public testnet. To further understand the role that the beacon node plays in Prysm, see [this section of the documentation.](https://docs.prylabs.network/docs/how-prysm-works/architecture-overview/)
**NOTE:** It is recommended to open up port 13000 on your local router to improve connectivity and receive more peers from the network. To do so, navigate to `192.168.0.1` in your browser and login if required. Follow along with the interface to modify your routers firewall settings. When this task is completed, append the parameter`--p2p-host-ip=$(curl -s ident.me)` to your selected beacon startup command presented in this section to use the newly opened port.
### Running via Docker
#### **Docker on Linux/macOS:**
To start your beacon node, issue the following command:
```text
docker run -it -v $HOME/prysm:/data -p 4000:4000 -p 13000:13000 --name beacon-node \
gcr.io/prysmaticlabs/prysm/beacon-chain:latest \
--datadir=/data
```
The beacon node can be halted by either using `Ctrl+c` or with the command:
```text
docker stop beacon-node
```
To restart the beacon node, issue the following command:
```text
docker start -ai beacon-node
```
To delete a corrupted container, issue the following command:
```text
docker rm beacon-node
```
To recreate a deleted container and refresh the chain database, issue the start command with an additional `--clear-db` parameter:
```text
docker run -it -v $HOME/prysm:/data -p 4000:4000 -p 13000:13000 --name beacon-node \
gcr.io/prysmaticlabs/prysm/beacon-chain:latest \
--datadir=/data \
--clear-db
```
#### **Docker on Windows:**
1. You will need to 'share' the local drive you wish to mount to \(e.g. C:\).
1. Enter Docker settings \(right click the tray icon\)
2. Click 'Shared Drives'
3. Select a drive to share
4. Click 'Apply'
2. You will next need to create a directory named `/prysm/` within your selected shared Drive. This folder will be used as a local data directory for Beacon Node chain data as well as account and keystore information required by the validator. Docker will **not** create this directory if it does not exist already. For the purposes of these instructions, it is assumed that `C:` is your prior-selected shared Drive.
3. To run the beacon node, issue the following command:
```text
docker run -it -v c:/prysm/:/data -p 4000:4000 -p 13000:13000 --name beacon-node gcr.io/prysmaticlabs/prysm/beacon-chain:latest --datadir=/data --clear-db
```
### Running via Bazel
To start your Beacon Node with Bazel, issue the following command:
```text
bazel run //beacon-chain -- --clear-db --datadir=$HOME/prysm
```
This will sync up the beacon node with the latest head block in the network.
**NOTE:** The beacon node must be **completely synced** before attempting to initialise a validator client, otherwise the validator will not be able to complete the deposit and **funds will lost**.
## Staking ETH: Running a validator client
Once your beacon node is up, the chain will be waiting for you to deposit 3.2 Goerli ETH into a [validator deposit contract](https://docs.prylabs.network/docs/how-prysm-works/validator-deposit-contract) in order to activate your validator \(discussed in the section below\). First though, you will need to create this validator and connect to this node to participate in consensus.
Each validator represents 3.2 Goerli ETH being staked in the system, and it is possible to spin up as many as you desire in order to have more stake in the network.
### Activating your validator: depositing 3.2 Göerli ETH
To begin setting up a validator, follow the instructions found on [prylabs.net](https://prylabs.net) to use the Göerli ETH faucet and make a deposit. For step-by-step assistance with the deposit page, see the [Activating a Validator ](https://docs.prylabs.network/docs/activating-a-validator)section of this documentation.
It will take a while for the nodes in the network to process a deposit. Once the node is active, the validator will immediately begin performing its responsibilities.
In your validator client, you will be able to frequently see your validator balance as it goes up over time. Note that, should your node ever go offline for a long period, a validator will start gradually losing its deposit until it is removed from the network entirely.
**Congratulations, you are now running Ethereum 2.0 Phase 0!**
## Setting up a local ETH2 development chain
This section outlines the process of setting up Prysm for local testing with other Ethereum 2.0 client implementations. See the [INTEROP.md](https://github.com/prysmaticlabs/prysm/blob/master/INTEROP.md) file for advanced configuration options. For more background information on interoperability development, see [this blog post](https://blog.ethereum.org/2019/09/19/eth2-interop-in-review/).
### Installation and dependencies
To begin setting up a local ETH2 development chain, follow the **Bazel** instructions found in the [dependencies](https://github.com/prysmaticlabs/prysm#dependencies) and [installation](https://github.com/prysmaticlabs/prysm#installation) sections respectively.
### Running a local beacon node and validator client
The example below will generate a beacon genesis state and initiate Prysm with 64 validators with the genesis time set to your machines UNIX time.
Open up two terminal windows. In the first, issue the command:
```text
bazel run //beacon-chain -- \
--custom-genesis-delay=0 \
--bootstrap-node= \
--deposit-contract $(curl https://prylabs.net/contract) \
--clear-db \
--interop-num-validators 64 \
--interop-eth1data-votes
```
Wait a moment for the beacon chain to start. In the other terminal, issue the command:
```text
bazel run //validator -- --keymanager=interop --keymanageropts='{"keys":64}'
```
This command will kickstart the system with your 64 validators performing their duties accordingly.
## Testing Prysm
To run the unit tests of our system, issue the command:
```text
bazel test //...
```
To run our linter, make sure you have [golangci-lint](https://github.com/golangci/golangci-lint) installed and then issue the command:
```text
golangci-lint run
```
Participation is now open to the public for our Ethereum 2.0 phase 0 testnet release. Visit [prylabs.net](https://prylabs.net) for more information on the project or to sign up as a validator on the network. You can visualize the nodes in the network on [eth2stats.io](https://eth2stats.io), explore validator rewards/penalties via Bitfly's block explorer: [beaconcha.in](https://beaconcha.in), and follow the latest blocks added to the chain on [Etherscan](https://beacon.etherscan.io).
## Contributing
Want to get involved? Check out our [Contribution Guide](https://docs.prylabs.network/docs/contribute/contribution-guidelines/) to learn more!

View File

@@ -197,8 +197,8 @@ filegroup(
visibility = ["//visibility:public"],
)
""",
sha256 = "72c6ee3c20d19736b1203f364a6eb0ddee2c173073e20bee2beccd288fdc42be",
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.9.4/general.tar.gz",
sha256 = "b90221d87b3b4cb17d7f195f8852f5dd8fec1cf623d42443b97bdb5a216ae61d",
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.11.1/general.tar.gz",
)
http_archive(
@@ -213,8 +213,8 @@ filegroup(
visibility = ["//visibility:public"],
)
""",
sha256 = "a3cc860a3679f6f62ee57b65677a9b48a65fdebb151cdcbf50f23852632845ef",
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.9.4/minimal.tar.gz",
sha256 = "316b227c0198f55872e46d601a578afeac88aab36ed38e3f01af753e98db156f",
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.11.1/minimal.tar.gz",
)
http_archive(
@@ -229,8 +229,8 @@ filegroup(
visibility = ["//visibility:public"],
)
""",
sha256 = "8fc1b6220973ca30fa4ddc4ed24d66b1719abadca8bedb5e06c3bd9bc0df28e9",
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.9.4/mainnet.tar.gz",
sha256 = "b9c52f60293bcc1acfd4f8ab7ddf8bf8222ddd6a105e93d384542d1396e1b07a",
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.11.1/mainnet.tar.gz",
)
http_archive(
@@ -933,8 +933,8 @@ go_repository(
go_repository(
name = "com_github_google_gofuzz",
importpath = "github.com/google/gofuzz",
sum = "h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=",
version = "v1.0.0",
sum = "h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=",
version = "v1.1.0",
)
go_repository(
@@ -1305,7 +1305,7 @@ go_repository(
go_repository(
name = "com_github_prysmaticlabs_ethereumapis",
commit = "62fd1d2ec119bc93b0473fde17426c63a85197ed",
commit = "6607cc86ddb7c78acfe3b1f0dfb115489a96d46d",
importpath = "github.com/prysmaticlabs/ethereumapis",
patch_args = ["-p1"],
patches = [
@@ -1639,6 +1639,14 @@ go_repository(
version = "v1.20.0",
)
go_repository(
name = "com_github_wealdtech_eth2_signer_api",
build_file_proto_mode = "disable_global",
importpath = "github.com/wealdtech/eth2-signer-api",
sum = "h1:fqJYjKwG/FeUAJYYiZblIP6agiz3WWB+Hxpw85Fnr5I=",
version = "v1.0.1",
)
go_repository(
name = "com_github_prysmaticlabs_prombbolt",
importpath = "github.com/prysmaticlabs/prombbolt",
@@ -1656,3 +1664,10 @@ go_repository(
sum = "h1:GWsU1WjSE2rtvyTYGcndqmPPkQkBNV7pEuZdnGtwtu4=",
version = "v0.0.0-20200321040036-d43e30eacb43",
)
go_repository(
name = "org_golang_x_mod",
importpath = "golang.org/x/mod",
sum = "h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=",
version = "v0.2.0",
)

View File

@@ -1,7 +1,7 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library", "go_test")
load("@io_bazel_rules_docker//go:image.bzl", "go_image")
load("@io_bazel_rules_docker//container:container.bzl", "container_bundle")
load("//tools:binary_targets.bzl", "binary_targets", "go_image_alpine", "go_image_debug")
load("//tools:go_image.bzl", "go_image_alpine", "go_image_debug")
load("@io_bazel_rules_docker//contrib:push-all.bzl", "docker_push")
go_library(
@@ -144,15 +144,3 @@ go_test(
"@in_gopkg_urfave_cli_v2//:go_default_library",
],
)
[go_binary(
name = "beacon-chain-{}-{}".format(
pair[0],
pair[1],
),
embed = [":go_default_library"],
goarch = pair[1],
goos = pair[0],
tags = ["manual"],
visibility = ["//visibility:public"],
) for pair in binary_targets]

View File

@@ -39,7 +39,6 @@ go_test(
"//shared/testutil:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
],

View File

@@ -147,7 +147,11 @@ func (s *Service) run(ctx context.Context) {
select {
case event := <-stateChannel:
if event.Type == statefeed.BlockProcessed {
data := event.Data.(*statefeed.BlockProcessedData)
data, ok := event.Data.(*statefeed.BlockProcessedData)
if !ok {
log.Error("Event feed data is not type *statefeed.BlockProcessedData")
continue
}
log.WithField("headRoot", fmt.Sprintf("%#x", data.BlockRoot)).Debug("Received block processed event")
headState, err := s.headFetcher.HeadState(ctx)
if err != nil {

View File

@@ -9,7 +9,6 @@ import (
"github.com/gogo/protobuf/proto"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/go-bitfield"
mock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute"
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
@@ -34,10 +33,8 @@ func TestArchiverService_ReceivesBlockProcessedEvent(t *testing.T) {
hook := logTest.NewGlobal()
svc, beaconDB := setupService(t)
defer dbutil.TeardownDB(t, beaconDB)
st, err := stateTrie.InitializeFromProto(&pb.BeaconState{
Slot: 1,
})
if err != nil {
st := testutil.NewBeaconState()
if err := st.SetSlot(1); err != nil {
t.Fatal(err)
}
svc.headFetcher = &mock.ChainService{
@@ -61,10 +58,8 @@ func TestArchiverService_OnlyArchiveAtEpochEnd(t *testing.T) {
svc, beaconDB := setupService(t)
defer dbutil.TeardownDB(t, beaconDB)
// The head state is NOT an epoch end.
st, err := stateTrie.InitializeFromProto(&pb.BeaconState{
Slot: params.BeaconConfig().SlotsPerEpoch - 2,
})
if err != nil {
st := testutil.NewBeaconState()
if err := st.SetSlot(params.BeaconConfig().SlotsPerEpoch - 2); err != nil {
t.Fatal(err)
}
svc.headFetcher = &mock.ChainService{
@@ -317,8 +312,8 @@ func TestArchiverService_SavesActivatedValidatorChanges(t *testing.T) {
if retrieved == nil {
t.Fatal("Retrieved indices are nil")
}
if !reflect.DeepEqual(retrieved.Activated, []uint64{4, 5}) {
t.Errorf("Wanted indices 4 5 activated, received %v", retrieved.Activated)
if len(retrieved.Activated) != 98 {
t.Error("Did not get wanted active length")
}
testutil.AssertLogsContain(t, hook, "Successfully archived")
}
@@ -433,18 +428,20 @@ func setupState(validatorCount uint64) (*stateTrie.BeaconState, error) {
// We initialize a head state that has attestations from participated
// validators in a simulated fashion.
return stateTrie.InitializeFromProto(&pb.BeaconState{
Slot: (2 * params.BeaconConfig().SlotsPerEpoch) - 1,
Validators: validators,
Balances: balances,
BlockRoots: make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot),
Slashings: []uint64{0, 1e9, 1e9},
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
CurrentEpochAttestations: atts,
FinalizedCheckpoint: &ethpb.Checkpoint{},
JustificationBits: bitfield.Bitvector4{0x00},
CurrentJustifiedCheckpoint: &ethpb.Checkpoint{},
})
st := testutil.NewBeaconState()
if err := st.SetSlot((2 * params.BeaconConfig().SlotsPerEpoch) - 1); err != nil {
return nil, err
}
if err := st.SetValidators(validators); err != nil {
return nil, err
}
if err := st.SetBalances(balances); err != nil {
return nil, err
}
if err := st.SetCurrentEpochAttestations(atts); err != nil {
return nil, err
}
return st, nil
}
func setupService(t *testing.T) (*Service, db.Database) {

View File

@@ -5,7 +5,9 @@ import (
"testing"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
)
func TestHeadSlot_DataRace(t *testing.T) {
@@ -15,10 +17,9 @@ func TestHeadSlot_DataRace(t *testing.T) {
beaconDB: db,
}
go func() {
s.saveHead(
context.Background(),
[32]byte{},
)
if err := s.saveHead(context.Background(), [32]byte{}, ); err != nil {
t.Fatal(err)
}
}()
s.HeadSlot()
}
@@ -29,12 +30,12 @@ func TestHeadRoot_DataRace(t *testing.T) {
s := &Service{
beaconDB: db,
head: &head{root: [32]byte{'A'}},
stateGen: stategen.New(db, cache.NewStateSummaryCache()),
}
go func() {
s.saveHead(
context.Background(),
[32]byte{},
)
if err := s.saveHead(context.Background(), [32]byte{}, ); err != nil {
t.Fatal(err)
}
}()
if _, err := s.HeadRoot(context.Background()); err != nil {
t.Fatal(err)
@@ -47,14 +48,16 @@ func TestHeadBlock_DataRace(t *testing.T) {
s := &Service{
beaconDB: db,
head: &head{block: &ethpb.SignedBeaconBlock{}},
stateGen: stategen.New(db, cache.NewStateSummaryCache()),
}
go func() {
s.saveHead(
context.Background(),
[32]byte{},
)
if err := s.saveHead(context.Background(), [32]byte{}, ); err != nil {
t.Fatal(err)
}
}()
s.HeadBlock(context.Background())
if _, err := s.HeadBlock(context.Background()); err != nil {
t.Fatal(err)
}
}
func TestHeadState_DataRace(t *testing.T) {
@@ -62,12 +65,14 @@ func TestHeadState_DataRace(t *testing.T) {
defer testDB.TeardownDB(t, db)
s := &Service{
beaconDB: db,
stateGen: stategen.New(db, cache.NewStateSummaryCache()),
}
go func() {
s.saveHead(
context.Background(),
[32]byte{},
)
if err := s.saveHead(context.Background(), [32]byte{}, ); err != nil {
t.Fatal(err)
}
}()
s.HeadState(context.Background())
if _, err := s.HeadState(context.Background()); err != nil {
t.Fatal(err)
}
}

View File

@@ -128,7 +128,10 @@ func TestPrevJustifiedCheckpt_GenesisRootOk(t *testing.T) {
func TestHeadSlot_CanRetrieve(t *testing.T) {
c := &Service{}
s, _ := state.InitializeFromProto(&pb.BeaconState{})
s, err := state.InitializeFromProto(&pb.BeaconState{})
if err != nil {
t.Fatal(err)
}
c.head = &head{slot: 100, state: s}
if c.HeadSlot() != 100 {
t.Errorf("Wanted head slot: %d, got: %d", 100, c.HeadSlot())
@@ -145,7 +148,10 @@ func TestHeadRoot_CanRetrieve(t *testing.T) {
func TestHeadBlock_CanRetrieve(t *testing.T) {
b := &ethpb.SignedBeaconBlock{Block: &ethpb.BeaconBlock{Slot: 1}}
s, _ := state.InitializeFromProto(&pb.BeaconState{})
s, err := state.InitializeFromProto(&pb.BeaconState{})
if err != nil {
t.Fatal(err)
}
c := &Service{}
c.head = &head{block: b, state: s}
@@ -160,7 +166,7 @@ func TestHeadBlock_CanRetrieve(t *testing.T) {
}
func TestHeadState_CanRetrieve(t *testing.T) {
s, err := state.InitializeFromProto(&pb.BeaconState{Slot: 2})
s, err := state.InitializeFromProto(&pb.BeaconState{Slot: 2, GenesisValidatorsRoot: params.BeaconConfig().ZeroHash[:]})
if err != nil {
t.Fatal(err)
}
@@ -170,7 +176,7 @@ func TestHeadState_CanRetrieve(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(s.InnerStateUnsafe(), headState.InnerStateUnsafe()) {
if !proto.Equal(s.InnerStateUnsafe(), headState.InnerStateUnsafe()) {
t.Error("incorrect head state received")
}
}

View File

@@ -59,7 +59,7 @@ func (s *Service) saveHead(ctx context.Context, headRoot [32]byte) error {
// If the head state is not available, just return nil.
// There's nothing to cache
if featureconfig.Get().NewStateMgmt {
if !featureconfig.Get().DisableNewStateMgmt {
if !s.stateGen.StateSummaryExists(ctx, headRoot) {
return nil
}
@@ -81,7 +81,7 @@ func (s *Service) saveHead(ctx context.Context, headRoot [32]byte) error {
// Get the new head state from cached state or DB.
var newHeadState *state.BeaconState
if featureconfig.Get().NewStateMgmt {
if !featureconfig.Get().DisableNewStateMgmt {
newHeadState, err = s.stateGen.StateByRoot(ctx, headRoot)
if err != nil {
return errors.Wrap(err, "could not retrieve head state in DB")
@@ -121,7 +121,7 @@ func (s *Service) saveHeadNoDB(ctx context.Context, b *ethpb.SignedBeaconBlock,
var headState *state.BeaconState
var err error
if featureconfig.Get().NewStateMgmt {
if !featureconfig.Get().DisableNewStateMgmt {
headState, err = s.stateGen.StateByRoot(ctx, r)
if err != nil {
return errors.Wrap(err, "could not retrieve head state in DB")

View File

@@ -9,8 +9,8 @@ import (
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/go-ssz"
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/testutil"
)
func TestSaveHead_Same(t *testing.T) {
@@ -44,10 +44,24 @@ func TestSaveHead_Different(t *testing.T) {
newHeadBlock := &ethpb.BeaconBlock{Slot: 1}
newHeadSignedBlock := &ethpb.SignedBeaconBlock{Block: newHeadBlock}
service.beaconDB.SaveBlock(context.Background(), newHeadSignedBlock)
newRoot, _ := ssz.HashTreeRoot(newHeadBlock)
headState, _ := state.InitializeFromProto(&pb.BeaconState{Slot: 1})
service.beaconDB.SaveState(context.Background(), headState, newRoot)
if err := service.beaconDB.SaveBlock(context.Background(), newHeadSignedBlock); err != nil {
t.Fatal(err)
}
newRoot, err := ssz.HashTreeRoot(newHeadBlock)
if err != nil {
t.Fatal(err)
}
headState := testutil.NewBeaconState()
if err := headState.SetSlot(1); err != nil {
t.Fatal(err)
}
if err := service.beaconDB.SaveStateSummary(context.Background(), &pb.StateSummary{Slot: 1, Root: newRoot[:]}); err != nil {
t.Fatal(err)
}
if err := service.beaconDB.SaveState(context.Background(), headState, newRoot); err != nil {
t.Fatal(err)
}
if err := service.saveHead(context.Background(), newRoot); err != nil {
t.Fatal(err)
}

View File

@@ -170,16 +170,22 @@ func (s *Service) generateState(ctx context.Context, startRoot [32]byte, endRoot
return nil, err
}
if preState == nil {
return nil, errors.New("finalized state does not exist in db")
}
var endBlock *ethpb.SignedBeaconBlock
if featureconfig.Get().InitSyncBatchSaveBlocks && s.hasInitSyncBlock(endRoot) {
if err := s.beaconDB.SaveBlocks(ctx, s.getInitSyncBlocks()); err != nil {
preState, err = s.stateGen.StateByRoot(ctx, startRoot)
if err != nil {
return nil, err
}
s.clearInitSyncBlocks()
if preState == nil {
return nil, errors.New("finalized state does not exist in db")
}
}
if err := s.beaconDB.SaveBlocks(ctx, s.getInitSyncBlocks()); err != nil {
return nil, err
}
var endBlock *ethpb.SignedBeaconBlock
if !featureconfig.Get().NoInitSyncBatchSaveBlocks && s.hasInitSyncBlock(endRoot) {
endBlock = s.getInitSyncBlock(endRoot)
s.clearInitSyncBlocks()
} else {
endBlock, err = s.beaconDB.Block(ctx, endRoot)
if err != nil {

View File

@@ -30,10 +30,15 @@ func TestFilterBoundaryCandidates_FilterCorrect(t *testing.T) {
if err != nil {
t.Fatal(err)
}
st, _ := stateTrie.InitializeFromProtoUnsafe(&pb.BeaconState{})
st, err := stateTrie.InitializeFromProtoUnsafe(&pb.BeaconState{})
if err != nil {
t.Fatal(err)
}
for i := uint64(0); i < 500; i++ {
st.SetSlot(i)
if err := st.SetSlot(i); err != nil {
t.Fatal(err)
}
root := [32]byte{}
copy(root[:], bytesutil.Bytes32(i))
service.initSyncState[root] = st.Copy()
@@ -43,14 +48,18 @@ func TestFilterBoundaryCandidates_FilterCorrect(t *testing.T) {
}
lastIndex := len(service.boundaryRoots) - 1
for i := uint64(500); i < 2000; i++ {
st.SetSlot(i)
if err := st.SetSlot(i); err != nil {
t.Fatal(err)
}
root := [32]byte{}
copy(root[:], bytesutil.Bytes32(i))
service.initSyncState[root] = st.Copy()
}
// Set current state.
latestSlot := helpers.RoundUpToNearestEpoch(2000)
st.SetSlot(latestSlot)
if err := st.SetSlot(latestSlot); err != nil {
t.Fatal(err)
}
lastRoot := [32]byte{}
copy(lastRoot[:], bytesutil.Bytes32(latestSlot))
@@ -85,10 +94,15 @@ func TestFilterBoundaryCandidates_HandleSkippedSlots(t *testing.T) {
if err != nil {
t.Fatal(err)
}
st, _ := stateTrie.InitializeFromProtoUnsafe(&pb.BeaconState{})
st, err := stateTrie.InitializeFromProtoUnsafe(&pb.BeaconState{})
if err != nil {
t.Fatal(err)
}
for i := uint64(0); i < 500; i++ {
st.SetSlot(i)
if err := st.SetSlot(i); err != nil {
t.Fatal(err)
}
root := [32]byte{}
copy(root[:], bytesutil.Bytes32(i))
service.initSyncState[root] = st.Copy()
@@ -98,7 +112,9 @@ func TestFilterBoundaryCandidates_HandleSkippedSlots(t *testing.T) {
}
lastIndex := len(service.boundaryRoots) - 1
for i := uint64(500); i < 2000; i++ {
st.SetSlot(i)
if err := st.SetSlot(i); err != nil {
t.Fatal(err)
}
root := [32]byte{}
copy(root[:], bytesutil.Bytes32(i))
// save only for offsetted slots
@@ -108,7 +124,9 @@ func TestFilterBoundaryCandidates_HandleSkippedSlots(t *testing.T) {
}
// Set current state.
latestSlot := helpers.RoundUpToNearestEpoch(2000)
st.SetSlot(latestSlot)
if err := st.SetSlot(latestSlot); err != nil {
t.Fatal(err)
}
lastRoot := [32]byte{}
copy(lastRoot[:], bytesutil.Bytes32(latestSlot))
@@ -150,10 +168,15 @@ func TestPruneOldStates_AlreadyFinalized(t *testing.T) {
if err != nil {
t.Fatal(err)
}
st, _ := stateTrie.InitializeFromProtoUnsafe(&pb.BeaconState{})
st, err := stateTrie.InitializeFromProtoUnsafe(&pb.BeaconState{})
if err != nil {
t.Fatal(err)
}
for i := uint64(100); i < 200; i++ {
st.SetSlot(i)
if err := st.SetSlot(i); err != nil {
t.Fatal(err)
}
root := [32]byte{}
copy(root[:], bytesutil.Bytes32(i))
service.initSyncState[root] = st.Copy()
@@ -184,10 +207,15 @@ func TestPruneNonBoundary_CanPrune(t *testing.T) {
if err != nil {
t.Fatal(err)
}
st, _ := stateTrie.InitializeFromProtoUnsafe(&pb.BeaconState{})
st, err := stateTrie.InitializeFromProtoUnsafe(&pb.BeaconState{})
if err != nil {
t.Fatal(err)
}
for i := uint64(0); i < 2000; i++ {
st.SetSlot(i)
if err := st.SetSlot(i); err != nil {
t.Fatal(err)
}
root := [32]byte{}
copy(root[:], bytesutil.Bytes32(i))
service.initSyncState[root] = st.Copy()
@@ -223,19 +251,28 @@ func TestGenerateState_CorrectlyGenerated(t *testing.T) {
if err != nil {
t.Fatal(err)
}
beaconState.SetLatestBlockHeader(&ethpb.BeaconBlockHeader{
err = beaconState.SetLatestBlockHeader(&ethpb.BeaconBlockHeader{
Slot: genesisBlock.Block.Slot,
ParentRoot: genesisBlock.Block.ParentRoot,
StateRoot: params.BeaconConfig().ZeroHash[:],
BodyRoot: bodyRoot[:],
})
beaconState.SetSlashings(make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector))
if err != nil {
t.Fatal(err)
}
if err := beaconState.SetSlashings(make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector)); err != nil {
t.Fatal(err)
}
cp := beaconState.CurrentJustifiedCheckpoint()
mockRoot := [32]byte{}
copy(mockRoot[:], "hello-world")
cp.Root = mockRoot[:]
beaconState.SetCurrentJustifiedCheckpoint(cp)
beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{})
if err := beaconState.SetCurrentJustifiedCheckpoint(cp); err != nil {
t.Fatal(err)
}
if err := beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{}); err != nil {
t.Fatal(err)
}
err = db.SaveBlock(context.Background(), genesisBlock)
if err != nil {
t.Fatal(err)

View File

@@ -19,6 +19,8 @@ func logStateTransitionData(b *ethpb.BeaconBlock) {
"attestations": len(b.Body.Attestations),
"deposits": len(b.Body.Deposits),
"attesterSlashings": len(b.Body.AttesterSlashings),
"proposerSlashings": len(b.Body.ProposerSlashings),
"voluntaryExits": len(b.Body.VoluntaryExits),
}).Info("Finished applying state transition")
}

View File

@@ -3,7 +3,6 @@ package blockchain
import (
"context"
"fmt"
"time"
"github.com/pkg/errors"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
@@ -11,6 +10,7 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/flags"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/roughtime"
"go.opencensus.io/trace"
)
@@ -93,12 +93,12 @@ func (s *Service) onAttestation(ctx context.Context, a *ethpb.Attestation) ([]ui
genesisTime := baseState.GenesisTime()
// Verify attestation target is from current epoch or previous epoch.
if err := s.verifyAttTargetEpoch(ctx, genesisTime, uint64(time.Now().Unix()), tgt); err != nil {
if err := s.verifyAttTargetEpoch(ctx, genesisTime, uint64(roughtime.Now().Unix()), tgt); err != nil {
return nil, err
}
// Verify Attestations cannot be from future epochs.
if err := helpers.VerifySlotTime(genesisTime, tgtSlot); err != nil {
if err := helpers.VerifySlotTime(genesisTime, tgtSlot, helpers.TimeShiftTolerance); err != nil {
return nil, errors.Wrap(err, "could not verify attestation target slot")
}
@@ -108,7 +108,7 @@ func (s *Service) onAttestation(ctx context.Context, a *ethpb.Attestation) ([]ui
}
// Verify attestations can only affect the fork choice of subsequent slots.
if err := helpers.VerifySlotTime(genesisTime, a.Data.Slot+1); err != nil {
if err := helpers.VerifySlotTime(genesisTime, a.Data.Slot, helpers.TimeShiftTolerance); err != nil {
return nil, err
}
@@ -125,6 +125,16 @@ func (s *Service) onAttestation(ctx context.Context, a *ethpb.Attestation) ([]ui
}
}
if indexedAtt.AttestingIndices == nil {
return nil, errors.New("nil attesting indices")
}
if a.Data == nil {
return nil, errors.New("nil att data")
}
if a.Data.Target == nil {
return nil, errors.New("nil att target")
}
// Update forkchoice store with the new attestation for updating weight.
s.forkChoiceStore.ProcessAttestation(ctx, indexedAtt.AttestingIndices, bytesutil.ToBytes32(a.Data.BeaconBlockRoot), a.Data.Target.Epoch)

View File

@@ -32,7 +32,7 @@ func (s *Service) getAttPreState(ctx context.Context, c *ethpb.Checkpoint) (*sta
}
var baseState *stateTrie.BeaconState
if featureconfig.Get().NewStateMgmt {
if !featureconfig.Get().DisableNewStateMgmt {
baseState, err = s.stateGen.StateByRoot(ctx, bytesutil.ToBytes32(c.Root))
if err != nil {
return nil, errors.Wrapf(err, "could not get pre state for slot %d", helpers.StartSlot(c.Epoch))
@@ -123,21 +123,25 @@ func (s *Service) verifyAttestation(ctx context.Context, baseState *stateTrie.Be
}
indexedAtt := attestationutil.ConvertToIndexed(ctx, a, committee)
if err := blocks.VerifyIndexedAttestation(ctx, baseState, indexedAtt); err != nil {
if err == blocks.ErrSigFailedToVerify {
if err == helpers.ErrSigFailedToVerify {
// When sig fails to verify, check if there's a differences in committees due to
// different seeds.
var aState *stateTrie.BeaconState
var err error
if featureconfig.Get().NewStateMgmt {
if !featureconfig.Get().DisableNewStateMgmt {
aState, err = s.stateGen.StateByRoot(ctx, bytesutil.ToBytes32(a.Data.BeaconBlockRoot))
return nil, err
if err != nil {
return nil, err
}
} else {
aState, err = s.beaconDB.State(ctx, bytesutil.ToBytes32(a.Data.BeaconBlockRoot))
if err != nil {
return nil, err
}
}
aState, err = s.beaconDB.State(ctx, bytesutil.ToBytes32(a.Data.BeaconBlockRoot))
if err != nil {
return nil, err
if aState == nil {
return nil, fmt.Errorf("nil state for block root %#x", a.Data.BeaconBlockRoot)
}
epoch := helpers.SlotToEpoch(a.Data.Slot)
origSeed, err := helpers.Seed(baseState, epoch, params.BeaconConfig().DomainBeaconAttester)
if err != nil {

View File

@@ -2,18 +2,19 @@ package blockchain
import (
"context"
"reflect"
"strings"
"testing"
"github.com/gogo/protobuf/proto"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"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"
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
@@ -25,7 +26,11 @@ func TestStore_OnAttestation(t *testing.T) {
db := testDB.SetupDB(t)
defer testDB.TeardownDB(t, db)
cfg := &Config{BeaconDB: db, ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}
cfg := &Config{
BeaconDB: db,
ForkChoiceStore: protoarray.New(0, 0, [32]byte{}),
StateGen: stategen.New(db, cache.NewStateSummaryCache()),
}
service, err := NewService(ctx, cfg)
if err != nil {
t.Fatal(err)
@@ -40,15 +45,21 @@ func TestStore_OnAttestation(t *testing.T) {
if err := db.SaveBlock(ctx, BlkWithOutState); err != nil {
t.Fatal(err)
}
BlkWithOutStateRoot, _ := ssz.HashTreeRoot(BlkWithOutState.Block)
BlkWithOutStateRoot, err := ssz.HashTreeRoot(BlkWithOutState.Block)
if err != nil {
t.Fatal(err)
}
BlkWithStateBadAtt := &ethpb.SignedBeaconBlock{Block: &ethpb.BeaconBlock{Slot: 1}}
if err := db.SaveBlock(ctx, BlkWithStateBadAtt); err != nil {
t.Fatal(err)
}
BlkWithStateBadAttRoot, _ := ssz.HashTreeRoot(BlkWithStateBadAtt.Block)
BlkWithStateBadAttRoot, err := ssz.HashTreeRoot(BlkWithStateBadAtt.Block)
if err != nil {
t.Fatal(err)
}
s, err := beaconstate.InitializeFromProto(&pb.BeaconState{})
s := testutil.NewBeaconState()
if err := s.SetSlot(100 * params.BeaconConfig().SlotsPerEpoch); err != nil {
t.Fatal(err)
}
@@ -60,15 +71,19 @@ func TestStore_OnAttestation(t *testing.T) {
if err := db.SaveBlock(ctx, BlkWithValidState); err != nil {
t.Fatal(err)
}
BlkWithValidStateRoot, _ := ssz.HashTreeRoot(BlkWithValidState.Block)
s, _ = stateTrie.InitializeFromProto(&pb.BeaconState{
Fork: &pb.Fork{
Epoch: 0,
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
},
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
})
BlkWithValidStateRoot, err := ssz.HashTreeRoot(BlkWithValidState.Block)
if err != nil {
t.Fatal(err)
}
s = testutil.NewBeaconState()
if err := s.SetFork(&pb.Fork{
Epoch: 0,
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
}); err != nil {
t.Fatal(err)
}
if err := service.beaconDB.SaveState(ctx, s, BlkWithValidStateRoot); err != nil {
t.Fatal(err)
}
@@ -99,7 +114,7 @@ func TestStore_OnAttestation(t *testing.T) {
a: &ethpb.Attestation{Data: &ethpb.AttestationData{Target: &ethpb.Checkpoint{Root: BlkWithOutStateRoot[:]}}},
s: &pb.BeaconState{},
wantErr: true,
wantErrString: "pre state of target block 0 does not exist",
wantErrString: "could not get pre state for slot 0: unknown boundary state",
},
{
name: "process attestation doesn't match current epoch",
@@ -129,15 +144,17 @@ func TestStore_SaveCheckpointState(t *testing.T) {
ctx := context.Background()
db := testDB.SetupDB(t)
defer testDB.TeardownDB(t, db)
params.UseDemoBeaconConfig()
cfg := &Config{BeaconDB: db}
cfg := &Config{
BeaconDB: db,
StateGen: stategen.New(db, cache.NewStateSummaryCache()),
}
service, err := NewService(ctx, cfg)
if err != nil {
t.Fatal(err)
}
s, _ := stateTrie.InitializeFromProto(&pb.BeaconState{
s, err := stateTrie.InitializeFromProto(&pb.BeaconState{
Fork: &pb.Fork{
Epoch: 0,
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
@@ -150,18 +167,30 @@ func TestStore_SaveCheckpointState(t *testing.T) {
JustificationBits: []byte{0},
Slashings: make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector),
FinalizedCheckpoint: &ethpb.Checkpoint{Root: bytesutil.PadTo([]byte{'A'}, 32)},
Validators: []*ethpb.Validator{{PublicKey: bytesutil.PadTo([]byte("foo"), 48)}},
Balances: []uint64{0},
})
if err != nil {
t.Fatal(err)
}
r := [32]byte{'g'}
if err := service.beaconDB.SaveState(ctx, s, r); err != nil {
t.Fatal(err)
}
service.justifiedCheckpt = &ethpb.Checkpoint{Root: r[:]}
service.bestJustifiedCheckpt = &ethpb.Checkpoint{Root: r[:]}
service.finalizedCheckpt = &ethpb.Checkpoint{Root: r[:]}
service.prevFinalizedCheckpt = &ethpb.Checkpoint{Root: r[:]}
r = bytesutil.ToBytes32([]byte{'A'})
cp1 := &ethpb.Checkpoint{Epoch: 1, Root: bytesutil.PadTo([]byte{'A'}, 32)}
service.beaconDB.SaveState(ctx, s, bytesutil.ToBytes32([]byte{'A'}))
if err := service.beaconDB.SaveState(ctx, s, bytesutil.ToBytes32([]byte{'A'})); err != nil {
t.Fatal(err)
}
if err := service.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{Root: bytesutil.PadTo([]byte{'A'}, 32)}); err != nil {
t.Fatal(err)
}
s1, err := service.getAttPreState(ctx, cp1)
if err != nil {
t.Fatal(err)
@@ -171,7 +200,12 @@ func TestStore_SaveCheckpointState(t *testing.T) {
}
cp2 := &ethpb.Checkpoint{Epoch: 2, Root: bytesutil.PadTo([]byte{'B'}, 32)}
service.beaconDB.SaveState(ctx, s, bytesutil.ToBytes32([]byte{'B'}))
if err := service.beaconDB.SaveState(ctx, s, bytesutil.ToBytes32([]byte{'B'})); err != nil {
t.Fatal(err)
}
if err := service.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{Root: bytesutil.PadTo([]byte{'B'}, 32)}); err != nil {
t.Fatal(err)
}
s2, err := service.getAttPreState(ctx, cp2)
if err != nil {
t.Fatal(err)
@@ -204,13 +238,20 @@ func TestStore_SaveCheckpointState(t *testing.T) {
t.Errorf("Wanted state slot: %d, got: %d", 2*params.BeaconConfig().SlotsPerEpoch, s2.Slot())
}
s.SetSlot(params.BeaconConfig().SlotsPerEpoch + 1)
if err := s.SetSlot(params.BeaconConfig().SlotsPerEpoch + 1); err != nil {
t.Fatal(err)
}
service.justifiedCheckpt = &ethpb.Checkpoint{Root: r[:]}
service.bestJustifiedCheckpt = &ethpb.Checkpoint{Root: r[:]}
service.finalizedCheckpt = &ethpb.Checkpoint{Root: r[:]}
service.prevFinalizedCheckpt = &ethpb.Checkpoint{Root: r[:]}
cp3 := &ethpb.Checkpoint{Epoch: 1, Root: bytesutil.PadTo([]byte{'C'}, 32)}
service.beaconDB.SaveState(ctx, s, bytesutil.ToBytes32([]byte{'C'}))
if err := service.beaconDB.SaveState(ctx, s, bytesutil.ToBytes32([]byte{'C'})); err != nil {
t.Fatal(err)
}
if err := service.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{Root: bytesutil.PadTo([]byte{'C'}, 32)}); err != nil {
t.Fatal(err)
}
s3, err := service.getAttPreState(ctx, cp3)
if err != nil {
t.Fatal(err)
@@ -225,7 +266,10 @@ func TestStore_UpdateCheckpointState(t *testing.T) {
db := testDB.SetupDB(t)
defer testDB.TeardownDB(t, db)
cfg := &Config{BeaconDB: db}
cfg := &Config{
BeaconDB: db,
StateGen: stategen.New(db, cache.NewStateSummaryCache()),
}
service, err := NewService(ctx, cfg)
if err != nil {
t.Fatal(err)
@@ -233,9 +277,13 @@ func TestStore_UpdateCheckpointState(t *testing.T) {
epoch := uint64(1)
baseState, _ := testutil.DeterministicGenesisState(t, 1)
baseState.SetSlot(epoch * params.BeaconConfig().SlotsPerEpoch)
if err := baseState.SetSlot(epoch * params.BeaconConfig().SlotsPerEpoch); err != nil {
t.Fatal(err)
}
checkpoint := &ethpb.Checkpoint{Epoch: epoch}
service.beaconDB.SaveState(ctx, baseState, bytesutil.ToBytes32(checkpoint.Root))
if err := service.beaconDB.SaveState(ctx, baseState, bytesutil.ToBytes32(checkpoint.Root)); err != nil {
t.Fatal(err)
}
returned, err := service.getAttPreState(ctx, checkpoint)
if err != nil {
t.Fatal(err)
@@ -254,7 +302,9 @@ func TestStore_UpdateCheckpointState(t *testing.T) {
epoch = uint64(2)
newCheckpoint := &ethpb.Checkpoint{Epoch: epoch}
service.beaconDB.SaveState(ctx, baseState, bytesutil.ToBytes32(newCheckpoint.Root))
if err := service.beaconDB.SaveState(ctx, baseState, bytesutil.ToBytes32(newCheckpoint.Root)); err != nil {
t.Fatal(err)
}
returned, err = service.getAttPreState(ctx, newCheckpoint)
if err != nil {
t.Fatal(err)
@@ -271,7 +321,7 @@ func TestStore_UpdateCheckpointState(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(returned, cached) {
if !proto.Equal(returned.InnerStateUnsafe(), cached.InnerStateUnsafe()) {
t.Error("Incorrectly cached base state")
}
}
@@ -366,11 +416,17 @@ func TestVerifyBeaconBlock_futureBlock(t *testing.T) {
}
b := &ethpb.SignedBeaconBlock{Block: &ethpb.BeaconBlock{Slot: 2}}
service.beaconDB.SaveBlock(ctx, b)
r, _ := ssz.HashTreeRoot(b.Block)
if err := service.beaconDB.SaveBlock(ctx, b); err != nil {
t.Fatal(err)
}
r, err := ssz.HashTreeRoot(b.Block)
if err != nil {
t.Fatal(err)
}
d := &ethpb.AttestationData{Slot: 1, BeaconBlockRoot: r[:]}
if err := service.verifyBeaconBlock(ctx, d); !strings.Contains(err.Error(), "could not process attestation for future block") {
err = service.verifyBeaconBlock(ctx, d)
if err == nil || !strings.Contains(err.Error(), "could not process attestation for future block") {
t.Error("Did not receive the wanted error")
}
}
@@ -387,8 +443,13 @@ func TestVerifyBeaconBlock_OK(t *testing.T) {
}
b := &ethpb.SignedBeaconBlock{Block: &ethpb.BeaconBlock{Slot: 2}}
service.beaconDB.SaveBlock(ctx, b)
r, _ := ssz.HashTreeRoot(b.Block)
if err := service.beaconDB.SaveBlock(ctx, b); err != nil {
t.Fatal(err)
}
r, err := ssz.HashTreeRoot(b.Block)
if err != nil {
t.Fatal(err)
}
d := &ethpb.AttestationData{Slot: 2, BeaconBlockRoot: r[:]}
if err := service.verifyBeaconBlock(ctx, d); err != nil {

View File

@@ -69,7 +69,6 @@ func (s *Service) onBlock(ctx context.Context, signed *ethpb.SignedBeaconBlock)
if err != nil {
return nil, err
}
preStateValidatorCount := preState.NumValidators()
root, err := stateutil.BlockRoot(b)
if err != nil {
@@ -93,7 +92,7 @@ func (s *Service) onBlock(ctx context.Context, signed *ethpb.SignedBeaconBlock)
return nil, errors.Wrapf(err, "could not insert block %d to fork choice store", b.Slot)
}
if featureconfig.Get().NewStateMgmt {
if !featureconfig.Get().DisableNewStateMgmt {
if err := s.stateGen.SaveState(ctx, root, postState); err != nil {
return nil, errors.Wrap(err, "could not save state")
}
@@ -112,11 +111,18 @@ func (s *Service) onBlock(ctx context.Context, signed *ethpb.SignedBeaconBlock)
// Update finalized check point. Prune the block cache and helper caches on every new finalized epoch.
if postState.FinalizedCheckpointEpoch() > s.finalizedCheckpt.Epoch {
if !featureconfig.Get().NoInitSyncBatchSaveBlocks {
if err := s.beaconDB.SaveBlocks(ctx, s.getInitSyncBlocks()); err != nil {
return nil, err
}
s.clearInitSyncBlocks()
}
if err := s.beaconDB.SaveFinalizedCheckpoint(ctx, postState.FinalizedCheckpoint()); err != nil {
return nil, errors.Wrap(err, "could not save finalized checkpoint")
}
if !featureconfig.Get().NewStateMgmt {
if featureconfig.Get().DisableNewStateMgmt {
startSlot := helpers.StartSlot(s.prevFinalizedCheckpt.Epoch)
endSlot := helpers.StartSlot(s.finalizedCheckpt.Epoch)
if endSlot > startSlot {
@@ -130,7 +136,9 @@ func (s *Service) onBlock(ctx context.Context, signed *ethpb.SignedBeaconBlock)
// Prune proto array fork choice nodes, all nodes before finalized check point will
// be pruned.
s.forkChoiceStore.Prune(ctx, fRoot)
if err := s.forkChoiceStore.Prune(ctx, fRoot); err != nil {
return nil, errors.Wrap(err, "could not prune proto array fork choice nodes")
}
s.prevFinalizedCheckpt = s.finalizedCheckpt
s.finalizedCheckpt = postState.FinalizedCheckpoint()
@@ -139,7 +147,7 @@ func (s *Service) onBlock(ctx context.Context, signed *ethpb.SignedBeaconBlock)
return nil, errors.Wrap(err, "could not save new justified")
}
if featureconfig.Get().NewStateMgmt {
if !featureconfig.Get().DisableNewStateMgmt {
fRoot := bytesutil.ToBytes32(postState.FinalizedCheckpoint().Root)
fBlock, err := s.beaconDB.Block(ctx, fRoot)
if err != nil {
@@ -151,11 +159,6 @@ func (s *Service) onBlock(ctx context.Context, signed *ethpb.SignedBeaconBlock)
}
}
// Update validator indices in database as needed.
if err := s.saveNewValidators(ctx, preStateValidatorCount, postState); err != nil {
return nil, errors.Wrap(err, "could not save new validators")
}
// Epoch boundary bookkeeping such as logging epoch summaries.
if postState.Slot() >= s.nextEpochBoundarySlot {
logEpochData(postState)
@@ -209,7 +212,6 @@ func (s *Service) onBlockInitialSyncStateTransition(ctx context.Context, signed
return nil
}
preStateValidatorCount := preState.NumValidators()
postState, err := state.ExecuteStateTransitionNoVerifyAttSigs(ctx, preState, signed)
if err != nil {
return errors.Wrap(err, "could not execute state transition")
@@ -219,7 +221,7 @@ func (s *Service) onBlockInitialSyncStateTransition(ctx context.Context, signed
if err != nil {
return errors.Wrapf(err, "could not get signing root of block %d", b.Slot)
}
if featureconfig.Get().InitSyncBatchSaveBlocks {
if !featureconfig.Get().NoInitSyncBatchSaveBlocks {
s.saveInitSyncBlock(root, signed)
} else {
if err := s.beaconDB.SaveBlock(ctx, signed); err != nil {
@@ -231,7 +233,7 @@ func (s *Service) onBlockInitialSyncStateTransition(ctx context.Context, signed
return errors.Wrapf(err, "could not insert block %d to fork choice store", b.Slot)
}
if featureconfig.Get().NewStateMgmt {
if !featureconfig.Get().DisableNewStateMgmt {
if err := s.stateGen.SaveState(ctx, root, postState); err != nil {
return errors.Wrap(err, "could not save state")
}
@@ -266,7 +268,7 @@ func (s *Service) onBlockInitialSyncStateTransition(ctx context.Context, signed
// Update finalized check point. Prune the block cache and helper caches on every new finalized epoch.
if postState.FinalizedCheckpointEpoch() > s.finalizedCheckpt.Epoch {
if !featureconfig.Get().NewStateMgmt {
if featureconfig.Get().DisableNewStateMgmt {
startSlot := helpers.StartSlot(s.prevFinalizedCheckpt.Epoch)
endSlot := helpers.StartSlot(s.finalizedCheckpt.Epoch)
if endSlot > startSlot {
@@ -281,7 +283,7 @@ func (s *Service) onBlockInitialSyncStateTransition(ctx context.Context, signed
}
}
if featureconfig.Get().InitSyncBatchSaveBlocks {
if !featureconfig.Get().NoInitSyncBatchSaveBlocks {
if err := s.beaconDB.SaveBlocks(ctx, s.getInitSyncBlocks()); err != nil {
return err
}
@@ -299,7 +301,7 @@ func (s *Service) onBlockInitialSyncStateTransition(ctx context.Context, signed
return errors.Wrap(err, "could not save new justified")
}
if featureconfig.Get().NewStateMgmt {
if !featureconfig.Get().DisableNewStateMgmt {
fRoot := bytesutil.ToBytes32(postState.FinalizedCheckpoint().Root)
fBlock, err := s.beaconDB.Block(ctx, fRoot)
if err != nil {
@@ -311,12 +313,7 @@ func (s *Service) onBlockInitialSyncStateTransition(ctx context.Context, signed
}
}
// Update validator indices in database as needed.
if err := s.saveNewValidators(ctx, preStateValidatorCount, postState); err != nil {
return errors.Wrap(err, "could not save new validators")
}
if !featureconfig.Get().NewStateMgmt {
if featureconfig.Get().DisableNewStateMgmt {
numOfStates := len(s.boundaryRoots)
if numOfStates > initialSyncCacheSize {
if err = s.persistCachedStates(ctx, numOfStates); err != nil {
@@ -341,7 +338,7 @@ func (s *Service) onBlockInitialSyncStateTransition(ctx context.Context, signed
return err
}
if !featureconfig.Get().NewStateMgmt && helpers.IsEpochStart(postState.Slot()) {
if featureconfig.Get().DisableNewStateMgmt && helpers.IsEpochStart(postState.Slot()) {
if err := s.beaconDB.SaveState(ctx, postState, root); err != nil {
return errors.Wrap(err, "could not save state")
}

View File

@@ -16,7 +16,6 @@ import (
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/roughtime"
"github.com/prysmaticlabs/prysm/shared/traceutil"
"github.com/sirupsen/logrus"
"go.opencensus.io/trace"
)
@@ -39,7 +38,7 @@ func (s *Service) getBlockPreState(ctx context.Context, b *ethpb.BeaconBlock) (*
}
// Verify block slot time is not from the feature.
if err := helpers.VerifySlotTime(preState.GenesisTime(), b.Slot); err != nil {
if err := helpers.VerifySlotTime(preState.GenesisTime(), b.Slot, helpers.TimeShiftTolerance); err != nil {
return nil, err
}
@@ -61,8 +60,12 @@ func (s *Service) verifyBlkPreState(ctx context.Context, b *ethpb.BeaconBlock) (
ctx, span := trace.StartSpan(ctx, "chainService.verifyBlkPreState")
defer span.End()
if featureconfig.Get().NewStateMgmt {
preState, err := s.stateGen.StateByRoot(ctx, bytesutil.ToBytes32(b.ParentRoot))
if !featureconfig.Get().DisableNewStateMgmt {
parentRoot := bytesutil.ToBytes32(b.ParentRoot)
if !s.stateGen.StateSummaryExists(ctx, parentRoot) {
return nil, errors.New("provided block root does not have block saved in the db")
}
preState, err := s.stateGen.StateByRoot(ctx, parentRoot)
if err != nil {
return nil, errors.Wrapf(err, "could not get pre state for slot %d", b.Slot)
}
@@ -141,28 +144,6 @@ func (s *Service) verifyBlkFinalizedSlot(b *ethpb.BeaconBlock) error {
return nil
}
// saveNewValidators saves newly added validator indices from the state to db.
// Does nothing if validator count has not changed.
func (s *Service) saveNewValidators(ctx context.Context, preStateValidatorCount int, postState *stateTrie.BeaconState) error {
postStateValidatorCount := postState.NumValidators()
if preStateValidatorCount != postStateValidatorCount {
indices := make([]uint64, 0)
pubKeys := make([][48]byte, 0)
for i := preStateValidatorCount; i < postStateValidatorCount; i++ {
indices = append(indices, uint64(i))
pubKeys = append(pubKeys, postState.PubkeyAtIndex(uint64(i)))
}
if err := s.beaconDB.SaveValidatorIndices(ctx, pubKeys, indices); err != nil {
return errors.Wrapf(err, "could not save activated validators: %v", indices)
}
log.WithFields(logrus.Fields{
"indices": indices,
"totalValidatorCount": postStateValidatorCount - preStateValidatorCount,
}).Trace("Validator indices saved in DB")
}
return nil
}
// rmStatesOlderThanLastFinalized deletes the states in db since last finalized check point.
func (s *Service) rmStatesOlderThanLastFinalized(ctx context.Context, startSlot uint64, endSlot uint64) error {
ctx, span := trace.StartSpan(ctx, "forkchoice.rmStatesBySlots")
@@ -232,7 +213,7 @@ func (s *Service) shouldUpdateCurrentJustified(ctx context.Context, newJustified
var newJustifiedBlockSigned *ethpb.SignedBeaconBlock
justifiedRoot := bytesutil.ToBytes32(newJustifiedCheckpt.Root)
var err error
if featureconfig.Get().InitSyncBatchSaveBlocks && s.hasInitSyncBlock(justifiedRoot) {
if !featureconfig.Get().NoInitSyncBatchSaveBlocks && s.hasInitSyncBlock(justifiedRoot) {
newJustifiedBlockSigned = s.getInitSyncBlock(justifiedRoot)
} else {
newJustifiedBlockSigned, err = s.beaconDB.Block(ctx, justifiedRoot)
@@ -250,7 +231,7 @@ func (s *Service) shouldUpdateCurrentJustified(ctx context.Context, newJustified
}
var justifiedBlockSigned *ethpb.SignedBeaconBlock
cachedJustifiedRoot := bytesutil.ToBytes32(s.justifiedCheckpt.Root)
if featureconfig.Get().InitSyncBatchSaveBlocks && s.hasInitSyncBlock(cachedJustifiedRoot) {
if !featureconfig.Get().NoInitSyncBatchSaveBlocks && s.hasInitSyncBlock(cachedJustifiedRoot) {
justifiedBlockSigned = s.getInitSyncBlock(cachedJustifiedRoot)
} else {
justifiedBlockSigned, err = s.beaconDB.Block(ctx, cachedJustifiedRoot)
@@ -288,7 +269,7 @@ func (s *Service) updateJustified(ctx context.Context, state *stateTrie.BeaconSt
s.justifiedCheckpt = cpt
}
if !featureconfig.Get().NewStateMgmt {
if featureconfig.Get().DisableNewStateMgmt {
justifiedRoot := bytesutil.ToBytes32(cpt.Root)
justifiedState := s.initSyncState[justifiedRoot]
@@ -394,7 +375,7 @@ func (s *Service) ancestor(ctx context.Context, root []byte, slot uint64) ([]byt
return nil, errors.Wrap(err, "could not get ancestor block")
}
if featureconfig.Get().InitSyncBatchSaveBlocks && s.hasInitSyncBlock(bytesutil.ToBytes32(root)) {
if !featureconfig.Get().NoInitSyncBatchSaveBlocks && s.hasInitSyncBlock(bytesutil.ToBytes32(root)) {
signed = s.getInitSyncBlock(bytesutil.ToBytes32(root))
}

View File

@@ -9,12 +9,14 @@ import (
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/go-ssz"
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/db"
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
@@ -26,7 +28,10 @@ func TestStore_OnBlock(t *testing.T) {
db := testDB.SetupDB(t)
defer testDB.TeardownDB(t, db)
cfg := &Config{BeaconDB: db}
cfg := &Config{
BeaconDB: db,
StateGen: stategen.New(db, cache.NewStateSummaryCache()),
}
service, err := NewService(ctx, cfg)
if err != nil {
t.Fatal(err)
@@ -41,10 +46,7 @@ func TestStore_OnBlock(t *testing.T) {
if err != nil {
t.Error(err)
}
st, err := stateTrie.InitializeFromProtoUnsafe(&pb.BeaconState{})
if err != nil {
t.Fatal(err)
}
st := testutil.NewBeaconState()
if err := service.beaconDB.SaveState(ctx, st.Copy(), validGenesisRoot); err != nil {
t.Fatal(err)
}
@@ -60,10 +62,16 @@ func TestStore_OnBlock(t *testing.T) {
if err != nil {
t.Error(err)
}
if err := service.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{Slot: st.Slot(), Root: randomParentRoot[:]}); err != nil {
t.Fatal(err)
}
if err := service.beaconDB.SaveState(ctx, st.Copy(), randomParentRoot); err != nil {
t.Fatal(err)
}
randomParentRoot2 := roots[1]
if err := service.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{Slot: st.Slot(), Root: randomParentRoot2[:]}); err != nil {
t.Fatal(err)
}
if err := service.beaconDB.SaveState(ctx, st.Copy(), bytesutil.ToBytes32(randomParentRoot2)); err != nil {
t.Fatal(err)
}
@@ -110,45 +118,13 @@ func TestStore_OnBlock(t *testing.T) {
service.finalizedCheckpt.Root = roots[0]
_, err := service.onBlock(ctx, &ethpb.SignedBeaconBlock{Block: tt.blk})
if !strings.Contains(err.Error(), tt.wantErrString) {
if err == nil || !strings.Contains(err.Error(), tt.wantErrString) {
t.Errorf("Store.OnBlock() error = %v, wantErr = %v", err, tt.wantErrString)
}
})
}
}
func TestStore_SaveNewValidators(t *testing.T) {
ctx := context.Background()
db := testDB.SetupDB(t)
defer testDB.TeardownDB(t, db)
cfg := &Config{BeaconDB: db}
service, err := NewService(ctx, cfg)
if err != nil {
t.Fatal(err)
}
preCount := 2 // validators 0 and validators 1
s, _ := stateTrie.InitializeFromProto(&pb.BeaconState{Validators: []*ethpb.Validator{
{PublicKey: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
{PublicKey: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}},
{PublicKey: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2}},
{PublicKey: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3}},
}})
if err := service.saveNewValidators(ctx, preCount, s); err != nil {
t.Fatal(err)
}
if !db.HasValidatorIndex(ctx, []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2}) {
t.Error("Wanted validator saved in db")
}
if !db.HasValidatorIndex(ctx, []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3}) {
t.Error("Wanted validator saved in db")
}
if db.HasValidatorIndex(ctx, []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}) {
t.Error("validator not suppose to be saved in db")
}
}
func TestRemoveStateSinceLastFinalized(t *testing.T) {
ctx := context.Background()
db := testDB.SetupDB(t)
@@ -176,7 +152,10 @@ func TestRemoveStateSinceLastFinalized(t *testing.T) {
if err != nil {
t.Fatal(err)
}
s, _ := stateTrie.InitializeFromProto(&pb.BeaconState{Slot: uint64(i)})
s := testutil.NewBeaconState()
if err := s.SetSlot(uint64(i)); err != nil {
t.Fatal(err)
}
if err := service.beaconDB.SaveState(ctx, s, r); err != nil {
t.Fatal(err)
}
@@ -249,9 +228,15 @@ func TestRemoveStateSinceLastFinalized_EmptyStartSlot(t *testing.T) {
}
lastJustifiedBlk := &ethpb.SignedBeaconBlock{Block: &ethpb.BeaconBlock{ParentRoot: []byte{'G'}}}
lastJustifiedRoot, _ := ssz.HashTreeRoot(lastJustifiedBlk.Block)
lastJustifiedRoot, err := ssz.HashTreeRoot(lastJustifiedBlk.Block)
if err != nil {
t.Fatal(err)
}
newJustifiedBlk := &ethpb.SignedBeaconBlock{Block: &ethpb.BeaconBlock{Slot: 1, ParentRoot: lastJustifiedRoot[:]}}
newJustifiedRoot, _ := ssz.HashTreeRoot(newJustifiedBlk.Block)
newJustifiedRoot, err := ssz.HashTreeRoot(newJustifiedBlk.Block)
if err != nil {
t.Fatal(err)
}
if err := service.beaconDB.SaveBlock(ctx, newJustifiedBlk); err != nil {
t.Fatal(err)
}
@@ -284,9 +269,15 @@ func TestShouldUpdateJustified_ReturnFalse(t *testing.T) {
t.Fatal(err)
}
lastJustifiedBlk := &ethpb.SignedBeaconBlock{Block: &ethpb.BeaconBlock{ParentRoot: []byte{'G'}}}
lastJustifiedRoot, _ := ssz.HashTreeRoot(lastJustifiedBlk.Block)
lastJustifiedRoot, err := ssz.HashTreeRoot(lastJustifiedBlk.Block)
if err != nil {
t.Fatal(err)
}
newJustifiedBlk := &ethpb.SignedBeaconBlock{Block: &ethpb.BeaconBlock{ParentRoot: lastJustifiedRoot[:]}}
newJustifiedRoot, _ := ssz.HashTreeRoot(newJustifiedBlk.Block)
newJustifiedRoot, err := ssz.HashTreeRoot(newJustifiedBlk.Block)
if err != nil {
t.Fatal(err)
}
if err := service.beaconDB.SaveBlock(ctx, newJustifiedBlk); err != nil {
t.Fatal(err)
}
@@ -307,21 +298,32 @@ func TestShouldUpdateJustified_ReturnFalse(t *testing.T) {
}
}
func TestCachedPreState_CanGetFromCache(t *testing.T) {
func TestCachedPreState_CanGetFromStateSummary(t *testing.T) {
ctx := context.Background()
db := testDB.SetupDB(t)
defer testDB.TeardownDB(t, db)
cfg := &Config{BeaconDB: db}
cfg := &Config{
BeaconDB: db,
StateGen: stategen.New(db, cache.NewStateSummaryCache()),
}
service, err := NewService(ctx, cfg)
if err != nil {
t.Fatal(err)
}
s, _ := stateTrie.InitializeFromProto(&pb.BeaconState{Slot: 1})
s, err := stateTrie.InitializeFromProto(&pb.BeaconState{Slot: 1, GenesisValidatorsRoot: params.BeaconConfig().ZeroHash[:]})
if err != nil {
t.Fatal(err)
}
r := [32]byte{'A'}
b := &ethpb.BeaconBlock{Slot: 1, ParentRoot: r[:]}
service.initSyncState[r] = s
if err := service.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{Slot: 1, Root: r[:]}); err != nil {
t.Fatal(err)
}
if err := service.stateGen.SaveState(ctx, r, s); err != nil {
t.Fatal(err)
}
received, err := service.verifyBlkPreState(ctx, b)
if err != nil {
@@ -337,7 +339,10 @@ func TestCachedPreState_CanGetFromDB(t *testing.T) {
db := testDB.SetupDB(t)
defer testDB.TeardownDB(t, db)
cfg := &Config{BeaconDB: db}
cfg := &Config{
BeaconDB: db,
StateGen: stategen.New(db, cache.NewStateSummaryCache()),
}
service, err := NewService(ctx, cfg)
if err != nil {
t.Fatal(err)
@@ -348,19 +353,27 @@ func TestCachedPreState_CanGetFromDB(t *testing.T) {
service.finalizedCheckpt = &ethpb.Checkpoint{Root: r[:]}
_, err = service.verifyBlkPreState(ctx, b)
wanted := "pre state of slot 1 does not exist"
wanted := "provided block root does not have block saved in the db"
if err.Error() != wanted {
t.Error("Did not get wanted error")
}
s, _ := stateTrie.InitializeFromProto(&pb.BeaconState{Slot: 1})
service.beaconDB.SaveState(ctx, s, r)
s, err := stateTrie.InitializeFromProto(&pb.BeaconState{Slot: 1})
if err != nil {
t.Fatal(err)
}
if err := service.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{Slot: 1, Root: r[:]}); err != nil {
t.Fatal(err)
}
if err := service.stateGen.SaveState(ctx, r, s); err != nil {
t.Fatal(err)
}
received, err := service.verifyBlkPreState(ctx, b)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(s, received) {
if s.Slot() != received.Slot() {
t.Error("cached state not the same")
}
}
@@ -378,16 +391,27 @@ func TestSaveInitState_CanSaveDelete(t *testing.T) {
for i := uint64(0); i < 64; i++ {
b := &ethpb.BeaconBlock{Slot: i}
s, _ := stateTrie.InitializeFromProto(&pb.BeaconState{Slot: i})
r, _ := ssz.HashTreeRoot(b)
s := testutil.NewBeaconState()
if err := s.SetSlot(i); err != nil {
t.Fatal(err)
}
r, err := ssz.HashTreeRoot(b)
if err != nil {
t.Fatal(err)
}
service.initSyncState[r] = s
}
// Set finalized root as slot 32
finalizedRoot, _ := ssz.HashTreeRoot(&ethpb.BeaconBlock{Slot: 32})
s, _ := stateTrie.InitializeFromProto(&pb.BeaconState{FinalizedCheckpoint: &ethpb.Checkpoint{
Epoch: 1, Root: finalizedRoot[:]}})
finalizedRoot, err := ssz.HashTreeRoot(&ethpb.BeaconBlock{Slot: 32})
if err != nil {
t.Fatal(err)
}
s := testutil.NewBeaconState()
if err := s.SetFinalizedCheckpoint(&ethpb.Checkpoint{
Epoch: 1, Root: finalizedRoot[:]}); err != nil {
t.Fatal(err)
}
if err := service.saveInitState(ctx, s); err != nil {
t.Fatal(err)
}
@@ -423,17 +447,17 @@ func TestUpdateJustified_CouldUpdateBest(t *testing.T) {
}
service.justifiedCheckpt = &ethpb.Checkpoint{Root: []byte{'A'}}
service.bestJustifiedCheckpt = &ethpb.Checkpoint{Root: []byte{'A'}}
st, err := stateTrie.InitializeFromProtoUnsafe(&pb.BeaconState{})
if err != nil {
t.Fatal(err)
}
st := testutil.NewBeaconState()
service.initSyncState[r] = st.Copy()
if err := db.SaveState(ctx, st.Copy(), r); err != nil {
t.Fatal(err)
}
// Could update
s, _ := stateTrie.InitializeFromProto(&pb.BeaconState{CurrentJustifiedCheckpoint: &ethpb.Checkpoint{Epoch: 1, Root: r[:]}})
s := testutil.NewBeaconState()
if err := s.SetCurrentJustifiedCheckpoint(&ethpb.Checkpoint{Epoch: 1, Root: r[:]}); err != nil {
t.Fatal(err)
}
if err := service.updateJustified(context.Background(), s); err != nil {
t.Fatal(err)
}
@@ -465,10 +489,16 @@ func TestFilterBlockRoots_CanFilter(t *testing.T) {
}
fBlock := &ethpb.BeaconBlock{}
fRoot, _ := ssz.HashTreeRoot(fBlock)
fRoot, err := ssz.HashTreeRoot(fBlock)
if err != nil {
t.Fatal(err)
}
hBlock := &ethpb.BeaconBlock{Slot: 1}
headRoot, _ := ssz.HashTreeRoot(hBlock)
st, _ := stateTrie.InitializeFromProtoUnsafe(&pb.BeaconState{})
headRoot, err := ssz.HashTreeRoot(hBlock)
if err != nil {
t.Fatal(err)
}
st := testutil.NewBeaconState()
if err := service.beaconDB.SaveBlock(ctx, &ethpb.SignedBeaconBlock{Block: fBlock}); err != nil {
t.Fatal(err)
}
@@ -511,10 +541,12 @@ func TestPersistCache_CanSave(t *testing.T) {
if err != nil {
t.Fatal(err)
}
st, _ := stateTrie.InitializeFromProtoUnsafe(&pb.BeaconState{})
st := testutil.NewBeaconState()
for i := uint64(0); i < initialSyncCacheSize; i++ {
st.SetSlot(i)
if err := st.SetSlot(i); err != nil {
t.Fatal(err)
}
root := [32]byte{}
copy(root[:], bytesutil.Bytes32(i))
service.initSyncState[root] = st.Copy()
@@ -563,7 +595,8 @@ func TestFillForkChoiceMissingBlocks_CanSave(t *testing.T) {
if err != nil {
t.Error(err)
}
st, _ := stateTrie.InitializeFromProtoUnsafe(&pb.BeaconState{})
st := testutil.NewBeaconState()
if err := service.beaconDB.SaveState(ctx, st.Copy(), validGenesisRoot); err != nil {
t.Fatal(err)
}
@@ -617,7 +650,8 @@ func TestFillForkChoiceMissingBlocks_FilterFinalized(t *testing.T) {
if err != nil {
t.Error(err)
}
st, _ := stateTrie.InitializeFromProtoUnsafe(&pb.BeaconState{})
st := testutil.NewBeaconState()
if err := service.beaconDB.SaveState(ctx, st.Copy(), validGenesisRoot); err != nil {
t.Fatal(err)
}
@@ -627,12 +661,18 @@ func TestFillForkChoiceMissingBlocks_FilterFinalized(t *testing.T) {
if err := service.beaconDB.SaveBlock(ctx, b63); err != nil {
t.Fatal(err)
}
r63, _ := ssz.HashTreeRoot(b63.Block)
r63, err := ssz.HashTreeRoot(b63.Block)
if err != nil {
t.Fatal(err)
}
b64 := &ethpb.SignedBeaconBlock{Block: &ethpb.BeaconBlock{Slot: 64, ParentRoot: r63[:]}}
if err := service.beaconDB.SaveBlock(ctx, b64); err != nil {
t.Fatal(err)
}
r64, _ := ssz.HashTreeRoot(b64.Block)
r64, err := ssz.HashTreeRoot(b64.Block)
if err != nil {
t.Fatal(err)
}
b65 := &ethpb.SignedBeaconBlock{Block: &ethpb.BeaconBlock{Slot: 65, ParentRoot: r64[:]}}
if err := service.beaconDB.SaveBlock(ctx, b65); err != nil {
t.Fatal(err)
@@ -661,25 +701,47 @@ func TestFillForkChoiceMissingBlocks_FilterFinalized(t *testing.T) {
// (B1, and B3 are all from the same slots)
func blockTree1(db db.Database, genesisRoot []byte) ([][]byte, error) {
b0 := &ethpb.BeaconBlock{Slot: 0, ParentRoot: genesisRoot}
r0, _ := ssz.HashTreeRoot(b0)
b1 := &ethpb.BeaconBlock{Slot: 1, ParentRoot: r0[:]}
r1, _ := ssz.HashTreeRoot(b1)
b3 := &ethpb.BeaconBlock{Slot: 3, ParentRoot: r0[:]}
r3, _ := ssz.HashTreeRoot(b3)
b4 := &ethpb.BeaconBlock{Slot: 4, ParentRoot: r3[:]}
r4, _ := ssz.HashTreeRoot(b4)
b5 := &ethpb.BeaconBlock{Slot: 5, ParentRoot: r4[:]}
r5, _ := ssz.HashTreeRoot(b5)
b6 := &ethpb.BeaconBlock{Slot: 6, ParentRoot: r4[:]}
r6, _ := ssz.HashTreeRoot(b6)
b7 := &ethpb.BeaconBlock{Slot: 7, ParentRoot: r5[:]}
r7, _ := ssz.HashTreeRoot(b7)
b8 := &ethpb.BeaconBlock{Slot: 8, ParentRoot: r6[:]}
r8, _ := ssz.HashTreeRoot(b8)
st, err := stateTrie.InitializeFromProtoUnsafe(&pb.BeaconState{})
r0, err := ssz.HashTreeRoot(b0)
if err != nil {
return nil, err
}
b1 := &ethpb.BeaconBlock{Slot: 1, ParentRoot: r0[:]}
r1, err := ssz.HashTreeRoot(b1)
if err != nil {
return nil, err
}
b3 := &ethpb.BeaconBlock{Slot: 3, ParentRoot: r0[:]}
r3, err := ssz.HashTreeRoot(b3)
if err != nil {
return nil, err
}
b4 := &ethpb.BeaconBlock{Slot: 4, ParentRoot: r3[:]}
r4, err := ssz.HashTreeRoot(b4)
if err != nil {
return nil, err
}
b5 := &ethpb.BeaconBlock{Slot: 5, ParentRoot: r4[:]}
r5, err := ssz.HashTreeRoot(b5)
if err != nil {
return nil, err
}
b6 := &ethpb.BeaconBlock{Slot: 6, ParentRoot: r4[:]}
r6, err := ssz.HashTreeRoot(b6)
if err != nil {
return nil, err
}
b7 := &ethpb.BeaconBlock{Slot: 7, ParentRoot: r5[:]}
r7, err := ssz.HashTreeRoot(b7)
if err != nil {
return nil, err
}
b8 := &ethpb.BeaconBlock{Slot: 8, ParentRoot: r6[:]}
r8, err := ssz.HashTreeRoot(b8)
if err != nil {
return nil, err
}
st := testutil.NewBeaconState()
for _, b := range []*ethpb.BeaconBlock{b0, b1, b3, b4, b5, b6, b7, b8} {
if err := db.SaveBlock(context.Background(), &ethpb.SignedBeaconBlock{Block: b}); err != nil {
return nil, err

View File

@@ -3,7 +3,6 @@ package blockchain
import (
"context"
"fmt"
"time"
"github.com/pkg/errors"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
@@ -13,6 +12,7 @@ import (
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/featureconfig"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/roughtime"
"github.com/prysmaticlabs/prysm/shared/slotutil"
"github.com/sirupsen/logrus"
"go.opencensus.io/trace"
@@ -91,7 +91,7 @@ func (s *Service) processAttestation(subscribedToStateEvents chan struct{}) {
atts := s.attPool.ForkchoiceAttestations()
for _, a := range atts {
var hasState bool
if featureconfig.Get().NewStateMgmt {
if !featureconfig.Get().DisableNewStateMgmt {
hasState = s.stateGen.StateSummaryExists(ctx, bytesutil.ToBytes32(a.Data.BeaconBlockRoot))
} else {
hasState = s.beaconDB.HasState(ctx, bytesutil.ToBytes32(a.Data.BeaconBlockRoot)) && s.beaconDB.HasState(ctx, bytesutil.ToBytes32(a.Data.Target.Root))
@@ -127,7 +127,7 @@ func (s *Service) processAttestation(subscribedToStateEvents chan struct{}) {
// This verifies the epoch of input checkpoint is within current epoch and previous epoch
// with respect to current time. Returns true if it's within, false if it's not.
func (s *Service) verifyCheckpointEpoch(c *ethpb.Checkpoint) bool {
now := uint64(time.Now().Unix())
now := uint64(roughtime.Now().Unix())
genesisTime := uint64(s.genesisTime.Unix())
currentSlot := (now - genesisTime) / params.BeaconConfig().SecondsPerSlot
currentEpoch := helpers.SlotToEpoch(currentSlot)

View File

@@ -140,7 +140,7 @@ func (s *Service) Start() {
}
if beaconState == nil {
if featureconfig.Get().NewStateMgmt {
if !featureconfig.Get().DisableNewStateMgmt {
beaconState, err = s.stateGen.StateByRoot(ctx, bytesutil.ToBytes32(cp.Root))
if err != nil {
log.Fatalf("Could not fetch beacon state by root: %v", err)
@@ -181,7 +181,7 @@ func (s *Service) Start() {
s.prevFinalizedCheckpt = stateTrie.CopyCheckpoint(finalizedCheckpoint)
s.resumeForkChoice(justifiedCheckpoint, finalizedCheckpoint)
if !featureconfig.Get().NewStateMgmt {
if featureconfig.Get().DisableNewStateMgmt {
if finalizedCheckpoint.Epoch > 1 {
if err := s.pruneGarbageState(ctx, helpers.StartSlot(finalizedCheckpoint.Epoch)-params.BeaconConfig().SlotsPerEpoch); err != nil {
log.WithError(err).Warn("Could not prune old states")
@@ -192,7 +192,8 @@ func (s *Service) Start() {
s.stateNotifier.StateFeed().Send(&feed.Event{
Type: statefeed.Initialized,
Data: &statefeed.InitializedData{
StartTime: s.genesisTime,
StartTime: s.genesisTime,
GenesisValidatorsRoot: beaconState.GenesisValidatorRoot(),
},
})
} else {
@@ -210,7 +211,11 @@ func (s *Service) Start() {
select {
case event := <-stateChannel:
if event.Type == statefeed.ChainStarted {
data := event.Data.(*statefeed.ChainStartedData)
data, ok := event.Data.(*statefeed.ChainStartedData)
if !ok {
log.Error("event data is not type *statefeed.ChainStartedData")
return
}
log.WithField("starttime", data.StartTime).Debug("Received chain start event")
s.processChainStartTime(ctx, data.StartTime)
return
@@ -233,13 +238,15 @@ func (s *Service) Start() {
// deposit contract, initializes the beacon chain's state, and kicks off the beacon chain.
func (s *Service) processChainStartTime(ctx context.Context, genesisTime time.Time) {
preGenesisState := s.chainStartFetcher.PreGenesisState()
if err := s.initializeBeaconChain(ctx, genesisTime, preGenesisState, s.chainStartFetcher.ChainStartEth1Data()); err != nil {
initializedState, err := s.initializeBeaconChain(ctx, genesisTime, preGenesisState, s.chainStartFetcher.ChainStartEth1Data())
if err != nil {
log.Fatalf("Could not initialize beacon chain: %v", err)
}
s.stateNotifier.StateFeed().Send(&feed.Event{
Type: statefeed.Initialized,
Data: &statefeed.InitializedData{
StartTime: genesisTime,
StartTime: genesisTime,
GenesisValidatorsRoot: initializedState.GenesisValidatorRoot(),
},
})
}
@@ -251,7 +258,7 @@ func (s *Service) initializeBeaconChain(
ctx context.Context,
genesisTime time.Time,
preGenesisState *stateTrie.BeaconState,
eth1data *ethpb.Eth1Data) error {
eth1data *ethpb.Eth1Data) (*stateTrie.BeaconState, error) {
_, span := trace.StartSpan(context.Background(), "beacon-chain.Service.initializeBeaconChain")
defer span.End()
s.genesisTime = genesisTime
@@ -259,11 +266,11 @@ func (s *Service) initializeBeaconChain(
genesisState, err := state.OptimizedGenesisBeaconState(unixTime, preGenesisState, eth1data)
if err != nil {
return errors.Wrap(err, "could not initialize genesis state")
return nil, errors.Wrap(err, "could not initialize genesis state")
}
if err := s.saveGenesisData(ctx, genesisState); err != nil {
return errors.Wrap(err, "could not save genesis data")
return nil, errors.Wrap(err, "could not save genesis data")
}
log.Info("Initialized beacon chain genesis state")
@@ -273,15 +280,15 @@ func (s *Service) initializeBeaconChain(
// Update committee shuffled indices for genesis epoch.
if err := helpers.UpdateCommitteeCache(genesisState, 0 /* genesis epoch */); err != nil {
return err
return nil, err
}
if err := helpers.UpdateProposerIndicesInCache(genesisState, 0 /* genesis epoch */); err != nil {
return err
return nil, err
}
s.opsService.SetGenesisTime(genesisState.GenesisTime())
return nil
return genesisState, nil
}
// Stop the blockchain service's main event loop and associated goroutines.
@@ -305,18 +312,6 @@ func (s *Service) ClearCachedStates() {
s.initSyncState = map[[32]byte]*stateTrie.BeaconState{}
}
// This gets called when beacon chain is first initialized to save validator indices and public keys in db.
func (s *Service) saveGenesisValidators(ctx context.Context, state *stateTrie.BeaconState) error {
pubkeys := make([][48]byte, state.NumValidators())
indices := make([]uint64, state.NumValidators())
for i := 0; i < state.NumValidators(); i++ {
pubkeys[i] = state.PubkeyAtIndex(uint64(i))
indices[i] = uint64(i)
}
return s.beaconDB.SaveValidatorIndices(ctx, pubkeys, indices)
}
// This gets called when beacon chain is first initialized to save genesis data (state, block, and more) in db.
func (s *Service) saveGenesisData(ctx context.Context, genesisState *stateTrie.BeaconState) error {
stateRoot, err := genesisState.HashTreeRoot(ctx)
@@ -332,7 +327,7 @@ func (s *Service) saveGenesisData(ctx context.Context, genesisState *stateTrie.B
if err := s.beaconDB.SaveBlock(ctx, genesisBlk); err != nil {
return errors.Wrap(err, "could not save genesis block")
}
if featureconfig.Get().NewStateMgmt {
if !featureconfig.Get().DisableNewStateMgmt {
if err := s.stateGen.SaveState(ctx, genesisBlkRoot, genesisState); err != nil {
return errors.Wrap(err, "could not save genesis state")
}
@@ -353,9 +348,6 @@ func (s *Service) saveGenesisData(ctx context.Context, genesisState *stateTrie.B
if err := s.beaconDB.SaveGenesisBlockRoot(ctx, genesisBlkRoot); err != nil {
return errors.Wrap(err, "could save genesis block root")
}
if err := s.saveGenesisValidators(ctx, genesisState); err != nil {
return errors.Wrap(err, "could not save genesis validators")
}
genesisCheckpoint := &ethpb.Checkpoint{Root: genesisBlkRoot[:]}
@@ -423,7 +415,7 @@ func (s *Service) initializeChainInfo(ctx context.Context) error {
}
finalizedRoot := bytesutil.ToBytes32(finalized.Root)
var finalizedState *stateTrie.BeaconState
if featureconfig.Get().NewStateMgmt {
if !featureconfig.Get().DisableNewStateMgmt {
finalizedRoot = s.beaconDB.LastArchivedIndexRoot(ctx)
finalizedState, err = s.stateGen.Resume(ctx)
if err != nil {
@@ -468,6 +460,10 @@ func (s *Service) pruneGarbageState(ctx context.Context, slot uint64) error {
return err
}
if err := s.beaconDB.SaveLastArchivedIndex(ctx, 0); err != nil {
return err
}
return nil
}

View File

@@ -21,13 +21,11 @@ func TestChainService_SaveHead_DataRace(t *testing.T) {
beaconDB: db,
}
go func() {
s.saveHead(
context.Background(),
[32]byte{},
)
if err := s.saveHead(context.Background(), [32]byte{}, ); err != nil {
t.Fatal(err)
}
}()
s.saveHead(
context.Background(),
[32]byte{},
)
if err := s.saveHead(context.Background(), [32]byte{}, ); err != nil {
t.Fatal(err)
}
}

View File

@@ -3,7 +3,6 @@ package blockchain
import (
"bytes"
"context"
"encoding/hex"
"io/ioutil"
"reflect"
"testing"
@@ -13,6 +12,7 @@ import (
"github.com/gogo/protobuf/proto"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
ssz "github.com/prysmaticlabs/go-ssz"
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
b "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
@@ -27,6 +27,7 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
protodb "github.com/prysmaticlabs/prysm/proto/beacon/db"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/event"
@@ -145,12 +146,10 @@ func setupBeaconChain(t *testing.T, beaconDB db.Database) *Service {
P2p: &mockBroadcaster{},
StateNotifier: &mockBeaconNode{},
AttPool: attestations.NewPool(),
StateGen: stategen.New(beaconDB, cache.NewStateSummaryCache()),
ForkChoiceStore: protoarray.New(0, 0, params.BeaconConfig().ZeroHash),
OpsService: opsService,
}
if err != nil {
t.Fatalf("could not register blockchain service: %v", err)
}
chainService, err := NewService(ctx, cfg)
if err != nil {
@@ -232,8 +231,8 @@ func TestChainStartStop_Initialized(t *testing.T) {
if err := db.SaveBlock(ctx, genesisBlk); err != nil {
t.Fatal(err)
}
s, err := beaconstate.InitializeFromProto(&pb.BeaconState{Slot: 1})
if err != nil {
s := testutil.NewBeaconState()
if err := s.SetSlot(1); err != nil {
t.Fatal(err)
}
if err := db.SaveState(ctx, s, blkRoot); err != nil {
@@ -273,7 +272,10 @@ func TestChainService_InitializeBeaconChain(t *testing.T) {
// Set up 10 deposits pre chain start for validators to register
count := uint64(10)
deposits, _, _ := testutil.DeterministicDepositsAndKeys(count)
deposits, _, err := testutil.DeterministicDepositsAndKeys(count)
if err != nil {
t.Fatal(err)
}
trie, _, err := testutil.DepositTrieFromDeposits(deposits)
if err != nil {
t.Fatal(err)
@@ -283,31 +285,23 @@ func TestChainService_InitializeBeaconChain(t *testing.T) {
if err != nil {
t.Fatal(err)
}
genState.SetEth1Data(&ethpb.Eth1Data{
err = genState.SetEth1Data(&ethpb.Eth1Data{
DepositRoot: hashTreeRoot[:],
DepositCount: uint64(len(deposits)),
})
genState, err = b.ProcessDeposits(ctx, genState, &ethpb.BeaconBlockBody{Deposits: deposits})
if err != nil {
t.Fatal(err)
for _, deposit := range deposits {
genState, err = b.ProcessPreGenesisDeposit(ctx, genState, deposit)
if err != nil {
t.Fatal(err)
}
}
if err := bc.initializeBeaconChain(ctx, time.Unix(0, 0), genState, &ethpb.Eth1Data{
if _, err := bc.initializeBeaconChain(ctx, time.Unix(0, 0), genState, &ethpb.Eth1Data{
DepositRoot: hashTreeRoot[:],
}); err != nil {
t.Fatal(err)
}
s, err := bc.beaconDB.State(ctx, bc.headRoot())
if err != nil {
t.Fatal(err)
}
for _, v := range s.Validators() {
if !db.HasValidatorIndex(ctx, v.PublicKey) {
t.Errorf("Validator %s missing from db", hex.EncodeToString(v.PublicKey))
}
}
if _, err := bc.HeadState(ctx); err != nil {
t.Error(err)
}
@@ -342,14 +336,23 @@ func TestChainService_InitializeChainInfo(t *testing.T) {
finalizedSlot := params.BeaconConfig().SlotsPerEpoch*2 + 1
headBlock := &ethpb.SignedBeaconBlock{Block: &ethpb.BeaconBlock{Slot: finalizedSlot, ParentRoot: genesisRoot[:]}}
headState, err := beaconstate.InitializeFromProto(&pb.BeaconState{Slot: finalizedSlot})
headState := testutil.NewBeaconState()
if err := headState.SetSlot(finalizedSlot); err != nil {
t.Fatal(err)
}
if err := headState.SetGenesisValidatorRoot(params.BeaconConfig().ZeroHash[:]); err != nil {
t.Fatal(err)
}
headRoot, err := ssz.HashTreeRoot(headBlock.Block)
if err != nil {
t.Fatal(err)
}
headRoot, _ := ssz.HashTreeRoot(headBlock.Block)
if err := db.SaveState(ctx, headState, headRoot); err != nil {
t.Fatal(err)
}
if err := db.SaveState(ctx, headState, genesisRoot); err != nil {
t.Fatal(err)
}
if err := db.SaveBlock(ctx, headBlock); err != nil {
t.Fatal(err)
}
@@ -362,7 +365,7 @@ func TestChainService_InitializeChainInfo(t *testing.T) {
if err := db.SaveBlock(ctx, headBlock); err != nil {
t.Fatal(err)
}
c := &Service{beaconDB: db}
c := &Service{beaconDB: db, stateGen: stategen.New(db, cache.NewStateSummaryCache())}
if err := c.initializeChainInfo(ctx); err != nil {
t.Fatal(err)
}
@@ -401,12 +404,18 @@ func TestChainService_SaveHeadNoDB(t *testing.T) {
ctx := context.Background()
s := &Service{
beaconDB: db,
stateGen: stategen.New(db, cache.NewStateSummaryCache()),
}
b := &ethpb.SignedBeaconBlock{Block: &ethpb.BeaconBlock{Slot: 1}}
r, _ := ssz.HashTreeRoot(b)
state := &pb.BeaconState{}
newState, err := beaconstate.InitializeFromProto(state)
s.beaconDB.SaveState(ctx, newState, r)
r, err := ssz.HashTreeRoot(b)
if err != nil {
t.Fatal(err)
}
newState := testutil.NewBeaconState()
if err := s.stateGen.SaveState(ctx, r, newState); err != nil {
t.Fatal(err)
}
if err := s.saveHeadNoDB(ctx, b, r); err != nil {
t.Fatal(err)
}
@@ -437,9 +446,8 @@ func TestChainService_PruneOldStates(t *testing.T) {
if err != nil {
t.Fatal(err)
}
state := &pb.BeaconState{Slot: uint64(i)}
newState, err := beaconstate.InitializeFromProto(state)
if err != nil {
newState := testutil.NewBeaconState()
if err := newState.SetSlot(uint64(i)); err != nil {
t.Fatal(err)
}
if err := s.beaconDB.SaveState(ctx, newState, r); err != nil {
@@ -479,9 +487,15 @@ func TestHasBlock_ForkChoiceAndDB(t *testing.T) {
beaconDB: db,
}
block := &ethpb.SignedBeaconBlock{Block: &ethpb.BeaconBlock{Body: &ethpb.BeaconBlockBody{}}}
r, _ := ssz.HashTreeRoot(block.Block)
r, err := ssz.HashTreeRoot(block.Block)
if err != nil {
t.Fatal(err)
}
bs := &pb.BeaconState{FinalizedCheckpoint: &ethpb.Checkpoint{}, CurrentJustifiedCheckpoint: &ethpb.Checkpoint{}}
state, _ := beaconstate.InitializeFromProto(bs)
state, err := beaconstate.InitializeFromProto(bs)
if err != nil {
t.Fatal(err)
}
if err := s.insertBlockToForkChoiceStore(ctx, block.Block, r, state); err != nil {
t.Fatal(err)
}
@@ -506,7 +520,10 @@ func BenchmarkHasBlockDB(b *testing.B) {
if err := s.beaconDB.SaveBlock(ctx, block); err != nil {
b.Fatal(err)
}
r, _ := ssz.HashTreeRoot(block.Block)
r, err := ssz.HashTreeRoot(block.Block)
if err != nil {
b.Fatal(err)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
@@ -526,9 +543,15 @@ func BenchmarkHasBlockForkChoiceStore(b *testing.B) {
beaconDB: db,
}
block := &ethpb.SignedBeaconBlock{Block: &ethpb.BeaconBlock{Body: &ethpb.BeaconBlockBody{}}}
r, _ := ssz.HashTreeRoot(block.Block)
r, err := ssz.HashTreeRoot(block.Block)
if err != nil {
b.Fatal(err)
}
bs := &pb.BeaconState{FinalizedCheckpoint: &ethpb.Checkpoint{}, CurrentJustifiedCheckpoint: &ethpb.Checkpoint{}}
state, _ := beaconstate.InitializeFromProto(bs)
state, err := beaconstate.InitializeFromProto(bs)
if err != nil {
b.Fatal(err)
}
if err := s.insertBlockToForkChoiceStore(ctx, block.Block, r, state); err != nil {
b.Fatal(err)
}

View File

@@ -41,6 +41,7 @@ go_test(
"attestation_data_test.go",
"checkpoint_state_test.go",
"committee_fuzz_test.go",
"committee_ids_test.go",
"committee_test.go",
"eth1_data_test.go",
"feature_flag_test.go",

View File

@@ -148,7 +148,10 @@ func (c *AttestationCache) Put(ctx context.Context, req *ethpb.AttestationDataRe
}
func wrapperToKey(i interface{}) (string, error) {
w := i.(*attestationReqResWrapper)
w, ok := i.(*attestationReqResWrapper)
if !ok {
return "", errors.New("key is not of type *attestationReqResWrapper")
}
if w == nil {
return "", errors.New("nil wrapper")
}

View File

@@ -4,10 +4,12 @@ import (
"reflect"
"testing"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/gogo/protobuf/proto"
"github.com/prysmaticlabs/prysm/shared/params"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/hashutil"
)
@@ -48,7 +50,8 @@ func TestCheckpointStateCache_StateByCheckpoint(t *testing.T) {
cp1 := &ethpb.Checkpoint{Epoch: 1, Root: bytesutil.PadTo([]byte{'A'}, 32)}
st, err := stateTrie.InitializeFromProto(&pb.BeaconState{
Slot: 64,
GenesisValidatorsRoot: params.BeaconConfig().ZeroHash[:],
Slot: 64,
})
if err != nil {
t.Fatal(err)
@@ -72,7 +75,7 @@ func TestCheckpointStateCache_StateByCheckpoint(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(state.InnerStateUnsafe(), info1.State.InnerStateUnsafe()) {
if !proto.Equal(state.InnerStateUnsafe(), info1.State.InnerStateUnsafe()) {
t.Error("incorrectly cached state")
}

View File

@@ -4,39 +4,82 @@ import (
"sync"
lru "github.com/hashicorp/golang-lru"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/sliceutil"
)
type committeeIDs struct {
cache *lru.Cache
lock sync.RWMutex
attester *lru.Cache
attesterLock sync.RWMutex
aggregator *lru.Cache
aggregatorLock sync.RWMutex
}
// CommitteeIDs for attestations.
// CommitteeIDs for attester and aggregator.
var CommitteeIDs = newCommitteeIDs()
func newCommitteeIDs() *committeeIDs {
cache, err := lru.New(8)
// Given a node can calculate committee assignments of current epoch and next epoch.
// Max size is set to 2 epoch length.
cacheSize := int(params.BeaconConfig().MaxCommitteesPerSlot * params.BeaconConfig().SlotsPerEpoch * 2)
attesterCache, err := lru.New(cacheSize)
if err != nil {
panic(err)
}
return &committeeIDs{cache: cache}
}
// AddIDs to the cache for attestation committees by epoch.
func (t *committeeIDs) AddIDs(indices []uint64, epoch uint64) {
t.lock.Lock()
defer t.lock.Unlock()
val, exists := t.cache.Get(epoch)
if exists {
indices = sliceutil.UnionUint64(append(indices, val.([]uint64)...))
aggregatorCache, err := lru.New(cacheSize)
if err != nil {
panic(err)
}
t.cache.Add(epoch, indices)
return &committeeIDs{attester: attesterCache, aggregator: aggregatorCache}
}
// GetIDs from the cache for attestation committees by epoch.
func (t *committeeIDs) GetIDs(epoch uint64) []uint64 {
val, exists := t.cache.Get(epoch)
// AddAttesterCommiteeID adds committee ID for subscribing subnet for the attester of a given slot.
func (c *committeeIDs) AddAttesterCommiteeID(slot uint64, committeeID uint64) {
c.attesterLock.Lock()
defer c.attesterLock.Unlock()
ids := []uint64{committeeID}
val, exists := c.attester.Get(slot)
if exists {
ids = sliceutil.UnionUint64(append(val.([]uint64), ids...))
}
c.attester.Add(slot, ids)
}
// GetAttesterCommitteeIDs gets the committee ID for subscribing subnet for attester of the slot.
func (c *committeeIDs) GetAttesterCommitteeIDs(slot uint64) []uint64 {
c.attesterLock.RLock()
defer c.attesterLock.RUnlock()
val, exists := c.attester.Get(slot)
if !exists {
return nil
}
if v, ok := val.([]uint64); ok {
return v
}
return nil
}
// AddAggregatorCommiteeID adds committee ID for subscribing subnet for the aggregator of a given slot.
func (c *committeeIDs) AddAggregatorCommiteeID(slot uint64, committeeID uint64) {
c.aggregatorLock.Lock()
defer c.aggregatorLock.Unlock()
ids := []uint64{committeeID}
val, exists := c.aggregator.Get(slot)
if exists {
ids = sliceutil.UnionUint64(append(val.([]uint64), ids...))
}
c.aggregator.Add(slot, ids)
}
// GetAggregatorCommitteeIDs gets the committee ID for subscribing subnet for aggregator of the slot.
func (c *committeeIDs) GetAggregatorCommitteeIDs(slot uint64) []uint64 {
c.aggregatorLock.RLock()
defer c.aggregatorLock.RUnlock()
val, exists := c.aggregator.Get(slot)
if !exists {
return []uint64{}
}

View File

@@ -0,0 +1,56 @@
package cache
import (
"reflect"
"testing"
)
func TestCommitteeIDCache_RoundTrip(t *testing.T) {
c := newCommitteeIDs()
slot := uint64(100)
committeeIDs := c.GetAggregatorCommitteeIDs(slot)
if len(committeeIDs) != 0 {
t.Errorf("Empty cache returned an object: %v", committeeIDs)
}
c.AddAggregatorCommiteeID(slot, 1)
res := c.GetAggregatorCommitteeIDs(slot)
if !reflect.DeepEqual(res, []uint64{1}) {
t.Error("Expected equal value to return from cache")
}
c.AddAggregatorCommiteeID(slot, 2)
res = c.GetAggregatorCommitteeIDs(slot)
if !reflect.DeepEqual(res, []uint64{1, 2}) {
t.Error("Expected equal value to return from cache")
}
c.AddAggregatorCommiteeID(slot, 3)
res = c.GetAggregatorCommitteeIDs(slot)
if !reflect.DeepEqual(res, []uint64{1, 2, 3}) {
t.Error("Expected equal value to return from cache")
}
committeeIDs = c.GetAttesterCommitteeIDs(slot)
if len(committeeIDs) != 0 {
t.Errorf("Empty cache returned an object: %v", committeeIDs)
}
c.AddAttesterCommiteeID(slot, 11)
res = c.GetAttesterCommitteeIDs(slot)
if !reflect.DeepEqual(res, []uint64{11}) {
t.Error("Expected equal value to return from cache")
}
c.AddAttesterCommiteeID(slot, 22)
res = c.GetAttesterCommitteeIDs(slot)
if !reflect.DeepEqual(res, []uint64{11, 22}) {
t.Error("Expected equal value to return from cache")
}
c.AddAttesterCommiteeID(slot, 33)
res = c.GetAttesterCommitteeIDs(slot)
if !reflect.DeepEqual(res, []uint64{11, 22, 33}) {
t.Error("Expected equal value to return from cache")
}
}

View File

@@ -177,14 +177,17 @@ func TestCommitteeCache_CanRotate(t *testing.T) {
func TestCommitteeCacheOutOfRange(t *testing.T) {
cache := NewCommitteesCache()
seed := bytesutil.ToBytes32([]byte("foo"))
cache.CommitteeCache.Add(&Committees{
err := cache.CommitteeCache.Add(&Committees{
CommitteeCount: 1,
Seed: seed,
ShuffledIndices: []uint64{0},
SortedIndices: []uint64{},
ProposerIndices: []uint64{},
})
_, err := cache.Committee(0, seed, math.MaxUint64) // Overflow!
if err != nil {
t.Error(err)
}
_, err = cache.Committee(0, seed, math.MaxUint64) // Overflow!
if err == nil {
t.Fatal("Did not fail as expected")
}

View File

@@ -14,8 +14,12 @@ var (
// trim the FIFO queue to the maxSize.
func trim(queue *cache.FIFO, maxSize int) {
for s := len(queue.ListKeys()); s > maxSize; s-- {
// #nosec G104 popProcessNoopFunc never returns an error
_, _ = queue.Pop(popProcessNoopFunc)
_, err := queue.Pop(popProcessNoopFunc)
if err != nil {
// popProcessNoopFunc never returns an error, but we handle this anyway to make linter
// happy.
return
}
}
}

View File

@@ -125,7 +125,10 @@ func (c *Eth1DataVoteCache) IncrementEth1DataVote(eth1DataHash [32]byte) (uint64
eth1DataVoteCacheHit.Inc()
eInfo, _ := obj.(*Eth1DataVote)
eInfo, ok := obj.(*Eth1DataVote)
if !ok {
return 0, errors.New("cached value is not of type *Eth1DataVote")
}
eInfo.VoteCount++
if err := c.eth1DataVoteCache.Add(eInfo); err != nil {

View File

@@ -74,8 +74,11 @@ func TestEth1DataVoteCache_CanIncrement(t *testing.T) {
if err != nil {
t.Fatal(err)
}
_, _ = cache.IncrementEth1DataVote(eInfo.Eth1DataHash)
count, _ := cache.IncrementEth1DataVote(eInfo.Eth1DataHash)
_, err = cache.IncrementEth1DataVote(eInfo.Eth1DataHash)
if err != nil {
t.Error(err)
}
count, err := cache.IncrementEth1DataVote(eInfo.Eth1DataHash)
if count != 58 {
t.Errorf(

View File

@@ -10,7 +10,6 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/shared/featureconfig"
"go.opencensus.io/trace"
)
@@ -30,6 +29,7 @@ var (
type SkipSlotCache struct {
cache *lru.Cache
lock sync.RWMutex
disabled bool // Allow for programmatic toggling of the cache, useful during initial sync.
inProgress map[uint64]bool
}
@@ -45,12 +45,22 @@ func NewSkipSlotCache() *SkipSlotCache {
}
}
// Enable the skip slot cache.
func (c *SkipSlotCache) Enable() {
c.disabled = false
}
// Disable the skip slot cache.
func (c *SkipSlotCache) Disable() {
c.disabled = true
}
// Get waits for any in progress calculation to complete before returning a
// cached response, if any.
func (c *SkipSlotCache) Get(ctx context.Context, slot uint64) (*stateTrie.BeaconState, error) {
ctx, span := trace.StartSpan(ctx, "skipSlotCache.Get")
defer span.End()
if !featureconfig.Get().EnableSkipSlotsCache {
if c.disabled {
// Return a miss result if cache is not enabled.
skipSlotCacheMiss.Inc()
return nil, nil
@@ -97,7 +107,7 @@ func (c *SkipSlotCache) Get(ctx context.Context, slot uint64) (*stateTrie.Beacon
// MarkInProgress a request so that any other similar requests will block on
// Get until MarkNotInProgress is called.
func (c *SkipSlotCache) MarkInProgress(slot uint64) error {
if !featureconfig.Get().EnableSkipSlotsCache {
if c.disabled {
return nil
}
@@ -114,7 +124,7 @@ func (c *SkipSlotCache) MarkInProgress(slot uint64) error {
// MarkNotInProgress will release the lock on a given request. This should be
// called after put.
func (c *SkipSlotCache) MarkNotInProgress(slot uint64) error {
if !featureconfig.Get().EnableSkipSlotsCache {
if c.disabled {
return nil
}
@@ -127,7 +137,7 @@ func (c *SkipSlotCache) MarkNotInProgress(slot uint64) error {
// Put the response in the cache.
func (c *SkipSlotCache) Put(ctx context.Context, slot uint64, state *stateTrie.BeaconState) error {
if !featureconfig.Get().EnableSkipSlotsCache {
if c.disabled {
return nil
}

View File

@@ -8,15 +8,11 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/featureconfig"
)
func TestSkipSlotCache_RoundTrip(t *testing.T) {
ctx := context.Background()
c := cache.NewSkipSlotCache()
fc := featureconfig.Get()
fc.EnableSkipSlotsCache = true
featureconfig.Init(fc)
state, err := c.Get(ctx, 5)
if err != nil {

View File

@@ -42,6 +42,7 @@ go_test(
srcs = [
"block_operations_fuzz_test.go",
"block_operations_test.go",
"block_regression_test.go",
"block_test.go",
"eth1_data_test.go",
],
@@ -49,6 +50,7 @@ go_test(
deps = [
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/stateutil:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//shared/attestationutil:go_default_library",
"//shared/bls:go_default_library",

View File

@@ -35,50 +35,8 @@ var log = logrus.WithField("prefix", "blocks")
var eth1DataCache = cache.NewEth1DataVoteCache()
// ErrSigFailedToVerify returns when a signature of a block object(ie attestation, slashing, exit... etc)
// failed to verify.
var ErrSigFailedToVerify = errors.New("signature did not verify")
func verifySigningRoot(obj interface{}, pub []byte, signature []byte, domain uint64) error {
publicKey, err := bls.PublicKeyFromBytes(pub)
if err != nil {
return errors.Wrap(err, "could not convert bytes to public key")
}
sig, err := bls.SignatureFromBytes(signature)
if err != nil {
return errors.Wrap(err, "could not convert bytes to signature")
}
root, err := ssz.HashTreeRoot(obj)
if err != nil {
return errors.Wrap(err, "could not get signing root")
}
if !sig.Verify(root[:], publicKey, domain) {
return ErrSigFailedToVerify
}
return nil
}
func verifyBlockRoot(blk *ethpb.BeaconBlock, pub []byte, signature []byte, domain uint64) error {
publicKey, err := bls.PublicKeyFromBytes(pub)
if err != nil {
return errors.Wrap(err, "could not convert bytes to public key")
}
sig, err := bls.SignatureFromBytes(signature)
if err != nil {
return errors.Wrap(err, "could not convert bytes to signature")
}
root, err := stateutil.BlockRoot(blk)
if err != nil {
return errors.Wrap(err, "could not get signing root")
}
if !sig.Verify(root[:], publicKey, domain) {
return ErrSigFailedToVerify
}
return nil
}
// Deprecated: This method uses deprecated ssz.SigningRoot.
func verifyDepositDataSigningRoot(obj *ethpb.Deposit_Data, pub []byte, signature []byte, domain uint64) error {
func verifyDepositDataSigningRoot(obj *ethpb.Deposit_Data, pub []byte, signature []byte, domain []byte) error {
publicKey, err := bls.PublicKeyFromBytes(pub)
if err != nil {
return errors.Wrap(err, "could not convert bytes to public key")
@@ -91,13 +49,21 @@ func verifyDepositDataSigningRoot(obj *ethpb.Deposit_Data, pub []byte, signature
if err != nil {
return errors.Wrap(err, "could not get signing root")
}
if !sig.Verify(root[:], publicKey, domain) {
return ErrSigFailedToVerify
sigRoot := &pb.SigningRoot{
ObjectRoot: root[:],
Domain: domain,
}
ctrRoot, err := ssz.HashTreeRoot(sigRoot)
if err != nil {
return errors.Wrap(err, "could not get container root")
}
if !sig.Verify(ctrRoot[:], publicKey) {
return helpers.ErrSigFailedToVerify
}
return nil
}
func verifySignature(signedData []byte, pub []byte, signature []byte, domain uint64) error {
func verifySignature(signedData []byte, pub []byte, signature []byte, domain []byte) error {
publicKey, err := bls.PublicKeyFromBytes(pub)
if err != nil {
return errors.Wrap(err, "could not convert bytes to public key")
@@ -106,8 +72,16 @@ func verifySignature(signedData []byte, pub []byte, signature []byte, domain uin
if err != nil {
return errors.Wrap(err, "could not convert bytes to signature")
}
if !sig.Verify(signedData, publicKey, domain) {
return ErrSigFailedToVerify
ctr := &pb.SigningRoot{
ObjectRoot: signedData,
Domain: domain,
}
root, err := ssz.HashTreeRoot(ctr)
if err != nil {
return errors.Wrap(err, "could not hash container")
}
if !sig.Verify(root[:], publicKey) {
return helpers.ErrSigFailedToVerify
}
return nil
}
@@ -119,7 +93,7 @@ func verifySignature(signedData []byte, pub []byte, signature []byte, domain uin
// 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:
// if state.eth1_data_votes.count(body.eth1_data) * 2 > EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH:
// state.latest_eth1_data = body.eth1_data
func ProcessEth1DataInBlock(beaconState *stateTrie.BeaconState, block *ethpb.BeaconBlock) (*stateTrie.BeaconState, error) {
if beaconState == nil {
@@ -170,7 +144,6 @@ func Eth1DataHasEnoughSupport(beaconState *stateTrie.BeaconState, data *ethpb.Et
if err != nil {
return false, errors.Wrap(err, "could not retrieve eth1 data vote cache")
}
}
if voteCount == 0 {
for _, vote := range beaconState.Eth1DataVotes() {
@@ -193,7 +166,8 @@ func Eth1DataHasEnoughSupport(beaconState *stateTrie.BeaconState, data *ethpb.Et
// If 50+% majority converged on the same eth1data, then it has enough support to update the
// state.
return voteCount*2 > params.BeaconConfig().SlotsPerEth1VotingPeriod, nil
support := params.BeaconConfig().EpochsPerEth1VotingPeriod * params.BeaconConfig().SlotsPerEpoch
return voteCount*2 > support, nil
}
// ProcessBlockHeader validates a block by its header.
@@ -203,6 +177,8 @@ func Eth1DataHasEnoughSupport(beaconState *stateTrie.BeaconState, data *ethpb.Et
// def process_block_header(state: BeaconState, block: BeaconBlock) -> None:
// # Verify that the slots match
// assert block.slot == state.slot
// # Verify that proposer index is the correct index
// assert block.proposer_index == get_beacon_proposer_index(state)
// # Verify that the parent matches
// assert block.parent_root == signing_root(state.latest_block_header)
// # Save current block as the new latest block
@@ -227,28 +203,29 @@ func ProcessBlockHeader(
return nil, err
}
idx, err := helpers.BeaconProposerIndex(beaconState)
if err != nil {
return nil, err
}
proposer, err := beaconState.ValidatorAtIndex(idx)
if err != nil {
return nil, err
}
// Verify proposer signature.
currentEpoch := helpers.SlotToEpoch(beaconState.Slot())
domain, err := helpers.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainBeaconProposer)
if err != nil {
if err := VerifyBlockHeaderSignature(beaconState, block); err != nil {
return nil, err
}
if err := verifyBlockRoot(block.Block, proposer.PublicKey, block.Signature, domain); err != nil {
return nil, ErrSigFailedToVerify
}
return beaconState, nil
}
// VerifyBlockHeaderSignature verifies the proposer signature of a beacon block.
func VerifyBlockHeaderSignature(beaconState *stateTrie.BeaconState, block *ethpb.SignedBeaconBlock) error {
proposer, err := beaconState.ValidatorAtIndex(block.Block.ProposerIndex)
if err != nil {
return err
}
currentEpoch := helpers.SlotToEpoch(beaconState.Slot())
domain, err := helpers.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainBeaconProposer, beaconState.GenesisValidatorRoot())
if err != nil {
return err
}
return helpers.VerifySigningRoot(block.Block, proposer.PublicKey, block.Signature, domain)
}
// ProcessBlockHeaderNoVerify validates a block by its header but skips proposer
// signature verification.
//
@@ -259,6 +236,8 @@ func ProcessBlockHeader(
// def process_block_header(state: BeaconState, block: BeaconBlock) -> None:
// # Verify that the slots match
// assert block.slot == state.slot
// # Verify that proposer index is the correct index
// assert block.proposer_index == get_beacon_proposer_index(state)
// # Verify that the parent matches
// assert block.parent_root == signing_root(state.latest_block_header)
// # Save current block as the new latest block
@@ -280,7 +259,14 @@ func ProcessBlockHeaderNoVerify(
return nil, errors.New("nil block")
}
if beaconState.Slot() != block.Slot {
return nil, fmt.Errorf("state slot: %d is different then block slot: %d", beaconState.Slot(), block.Slot)
return nil, fmt.Errorf("state slot: %d is different than block slot: %d", beaconState.Slot(), block.Slot)
}
idx, err := helpers.BeaconProposerIndex(beaconState)
if err != nil {
return nil, err
}
if block.ProposerIndex != idx {
return nil, fmt.Errorf("proposer index: %d is different than calculated: %d", block.ProposerIndex, idx)
}
parentRoot, err := stateutil.BlockHeaderRoot(beaconState.LatestBlockHeader())
if err != nil {
@@ -293,10 +279,6 @@ func ProcessBlockHeaderNoVerify(
block.ParentRoot, parentRoot)
}
idx, err := helpers.BeaconProposerIndex(beaconState)
if err != nil {
return nil, err
}
proposer, err := beaconState.ValidatorAtIndex(idx)
if err != nil {
return nil, err
@@ -310,10 +292,11 @@ func ProcessBlockHeaderNoVerify(
return nil, err
}
if err := beaconState.SetLatestBlockHeader(&ethpb.BeaconBlockHeader{
Slot: block.Slot,
ParentRoot: block.ParentRoot,
StateRoot: params.BeaconConfig().ZeroHash[:],
BodyRoot: bodyRoot[:],
Slot: block.Slot,
ProposerIndex: block.ProposerIndex,
ParentRoot: block.ParentRoot,
StateRoot: params.BeaconConfig().ZeroHash[:],
BodyRoot: bodyRoot[:],
}); err != nil {
return nil, err
}
@@ -353,7 +336,7 @@ func ProcessRandao(
buf := make([]byte, 32)
binary.LittleEndian.PutUint64(buf, currentEpoch)
domain, err := helpers.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainRandao)
domain, err := helpers.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainRandao, beaconState.GenesisValidatorRoot())
if err != nil {
return nil, err
}
@@ -434,51 +417,51 @@ func ProcessProposerSlashings(
if slashing == nil {
return nil, errors.New("nil proposer slashings in block body")
}
if int(slashing.ProposerIndex) >= beaconState.NumValidators() {
return nil, fmt.Errorf("invalid proposer index given in slashing %d", slashing.ProposerIndex)
}
if err = VerifyProposerSlashing(beaconState, slashing); err != nil {
return nil, errors.Wrapf(err, "could not verify proposer slashing %d", idx)
}
beaconState, err = v.SlashValidator(
beaconState, slashing.ProposerIndex, 0, /* proposer is whistleblower */
beaconState, slashing.Header_1.Header.ProposerIndex, 0, /* proposer is whistleblower */
)
if err != nil {
return nil, errors.Wrapf(err, "could not slash proposer index %d", slashing.ProposerIndex)
return nil, errors.Wrapf(err, "could not slash proposer index %d", slashing.Header_1.Header.ProposerIndex)
}
}
return beaconState, nil
}
// VerifyProposerSlashing verifies that the data provided fro slashing is valid.
// VerifyProposerSlashing verifies that the data provided from slashing is valid.
func VerifyProposerSlashing(
beaconState *stateTrie.BeaconState,
slashing *ethpb.ProposerSlashing,
) error {
proposer, err := beaconState.ValidatorAtIndex(slashing.ProposerIndex)
if err != nil {
return err
}
if slashing.Header_1 == nil || slashing.Header_1.Header == nil || slashing.Header_2 == nil || slashing.Header_2.Header == nil {
return errors.New("nil header cannot be verified")
}
if slashing.Header_1.Header.Slot != slashing.Header_2.Header.Slot {
return fmt.Errorf("mismatched header slots, received %d == %d", slashing.Header_1.Header.Slot, slashing.Header_2.Header.Slot)
}
if slashing.Header_1.Header.ProposerIndex != slashing.Header_2.Header.ProposerIndex {
return fmt.Errorf("mismatched indices, received %d == %d", slashing.Header_1.Header.ProposerIndex, slashing.Header_2.Header.ProposerIndex)
}
if proto.Equal(slashing.Header_1, slashing.Header_2) {
return errors.New("expected slashing headers to differ")
}
proposer, err := beaconState.ValidatorAtIndex(slashing.Header_1.Header.ProposerIndex)
if err != nil {
return err
}
if !helpers.IsSlashableValidator(proposer, helpers.SlotToEpoch(beaconState.Slot())) {
return fmt.Errorf("validator with key %#x is not slashable", proposer.PublicKey)
}
// Using headerEpoch1 here because both of the headers should have the same epoch.
domain, err := helpers.Domain(beaconState.Fork(), helpers.StartSlot(slashing.Header_1.Header.Slot), params.BeaconConfig().DomainBeaconProposer)
domain, err := helpers.Domain(beaconState.Fork(), helpers.SlotToEpoch(slashing.Header_1.Header.Slot), params.BeaconConfig().DomainBeaconProposer, beaconState.GenesisValidatorRoot())
if err != nil {
return err
}
headers := []*ethpb.SignedBeaconBlockHeader{slashing.Header_1, slashing.Header_2}
for _, header := range headers {
if err := verifySigningRoot(header.Header, proposer.PublicKey, header.Signature, domain); err != nil {
if err := helpers.VerifySigningRoot(header.Header, proposer.PublicKey, header.Signature, domain); err != nil {
return errors.Wrap(err, "could not verify beacon block header")
}
}
@@ -596,7 +579,7 @@ func slashableAttesterIndices(slashing *ethpb.AttesterSlashing) []uint64 {
return nil
}
indices1 := slashing.Attestation_1.AttestingIndices
indices2 := slashing.Attestation_1.AttestingIndices
indices2 := slashing.Attestation_2.AttestingIndices
return sliceutil.IntersectionUint64(indices1, indices2)
}
@@ -827,30 +810,25 @@ func VerifyIndexedAttestation(ctx context.Context, beaconState *stateTrie.Beacon
return errors.New("attesting indices is not uniquely sorted")
}
domain, err := helpers.Domain(beaconState.Fork(), indexedAtt.Data.Target.Epoch, params.BeaconConfig().DomainBeaconAttester)
domain, err := helpers.Domain(beaconState.Fork(), indexedAtt.Data.Target.Epoch, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorRoot())
if err != nil {
return err
}
var pubkey *bls.PublicKey
pubkeys := []*bls.PublicKey{}
if len(indices) > 0 {
pubkeyAtIdx := beaconState.PubkeyAtIndex(indices[0])
pubkey, err = bls.PublicKeyFromBytes(pubkeyAtIdx[:])
if err != nil {
return errors.Wrap(err, "could not deserialize validator public key")
}
for i := 1; i < len(indices); i++ {
pubkeyAtIdx = beaconState.PubkeyAtIndex(indices[i])
for i := 0; i < len(indices); i++ {
pubkeyAtIdx := beaconState.PubkeyAtIndex(indices[i])
pk, err := bls.PublicKeyFromBytes(pubkeyAtIdx[:])
if err != nil {
return errors.Wrap(err, "could not deserialize validator public key")
}
pubkey.Aggregate(pk)
pubkeys = append(pubkeys, pk)
}
}
messageHash, err := ssz.HashTreeRoot(indexedAtt.Data)
messageHash, err := helpers.ComputeSigningRoot(indexedAtt.Data, domain)
if err != nil {
return errors.Wrap(err, "could not tree hash att data")
return errors.Wrap(err, "could not get signing root of object")
}
sig, err := bls.SignatureFromBytes(indexedAtt.Signature)
@@ -859,8 +837,8 @@ func VerifyIndexedAttestation(ctx context.Context, beaconState *stateTrie.Beacon
}
voted := len(indices) > 0
if voted && !sig.Verify(messageHash[:], pubkey, domain) {
return ErrSigFailedToVerify
if voted && !sig.FastAggregateVerify(pubkeys, messageHash) {
return helpers.ErrSigFailedToVerify
}
return nil
}
@@ -1002,7 +980,10 @@ func ProcessDeposit(
index, ok := beaconState.ValidatorIndexByPubkey(bytesutil.ToBytes48(pubKey))
numVals := beaconState.NumValidators()
if !ok {
domain := bls.ComputeDomain(params.BeaconConfig().DomainDeposit)
domain, err := helpers.ComputeDomain(params.BeaconConfig().DomainDeposit, nil, nil)
if err != nil {
return nil, err
}
depositSig := deposit.Data.Signature
if err := verifyDepositDataSigningRoot(deposit.Data, pubKey, depositSig, domain); err != nil {
// Ignore this error as in the spec pseudo code.
@@ -1112,7 +1093,7 @@ func ProcessVoluntaryExits(
if err != nil {
return nil, err
}
if err := VerifyExit(val, beaconState.Slot(), beaconState.Fork(), exit); err != nil {
if err := VerifyExit(val, beaconState.Slot(), beaconState.Fork(), exit, beaconState.GenesisValidatorRoot()); err != nil {
return nil, errors.Wrapf(err, "could not verify exit %d", idx)
}
beaconState, err = v.InitiateValidatorExit(beaconState, exit.Exit.ValidatorIndex)
@@ -1163,7 +1144,7 @@ func ProcessVoluntaryExitsNoVerify(
// # Verify signature
// domain = get_domain(state, DOMAIN_VOLUNTARY_EXIT, exit.epoch)
// assert bls_verify(validator.pubkey, signing_root(exit), exit.signature, domain)
func VerifyExit(validator *ethpb.Validator, currentSlot uint64, fork *pb.Fork, signed *ethpb.SignedVoluntaryExit) error {
func VerifyExit(validator *ethpb.Validator, currentSlot uint64, fork *pb.Fork, signed *ethpb.SignedVoluntaryExit, genesisRoot []byte) error {
if signed == nil || signed.Exit == nil {
return errors.New("nil exit")
}
@@ -1190,12 +1171,12 @@ func VerifyExit(validator *ethpb.Validator, currentSlot uint64, fork *pb.Fork, s
validator.ActivationEpoch+params.BeaconConfig().PersistentCommitteePeriod,
)
}
domain, err := helpers.Domain(fork, exit.Epoch, params.BeaconConfig().DomainVoluntaryExit)
domain, err := helpers.Domain(fork, exit.Epoch, params.BeaconConfig().DomainVoluntaryExit, genesisRoot)
if err != nil {
return err
}
if err := verifySigningRoot(exit, validator.PublicKey, signed.Signature, domain); err != nil {
return ErrSigFailedToVerify
if err := helpers.VerifySigningRoot(exit, validator.PublicKey, signed.Signature, domain); err != nil {
return helpers.ErrSigFailedToVerify
}
return nil
}

View File

@@ -4,12 +4,11 @@ import (
"context"
"testing"
fuzz "github.com/google/gofuzz"
eth "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
fuzz "github.com/google/gofuzz"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
//"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
@@ -25,8 +24,13 @@ func TestFuzzProcessAttestationNoVerify_10000(t *testing.T) {
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(att)
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
_, _ = ProcessAttestationNoVerify(ctx, s, att)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
if err != nil {
t.Log(err)
}
if _, err = ProcessAttestationNoVerify(ctx, s, att); err != nil {
t.Log(err)
}
}
}
@@ -39,33 +43,13 @@ func TestFuzzProcessBlockHeader_10000(t *testing.T) {
fuzzer.Fuzz(state)
fuzzer.Fuzz(block)
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
_, _ = ProcessBlockHeader(s, block)
}
}
func TestFuzzverifySigningRoot_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &ethereum_beacon_p2p_v1.BeaconState{}
pubkey := [48]byte{}
sig := [96]byte{}
domain := [4]byte{}
p := []byte{}
s := []byte{}
d := uint64(0)
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(&pubkey)
fuzzer.Fuzz(&sig)
fuzzer.Fuzz(&domain)
fuzzer.Fuzz(state)
fuzzer.Fuzz(&p)
fuzzer.Fuzz(&s)
fuzzer.Fuzz(&d)
domain := bytesutil.FromBytes4(domain[:])
verifySigningRoot(state, pubkey[:], sig[:], domain)
verifySigningRoot(state, p, s, d)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
if err != nil {
t.Log(err)
}
if _, err = ProcessBlockHeader(s, block); err != nil {
t.Log(err)
}
}
}
@@ -77,7 +61,7 @@ func TestFuzzverifyDepositDataSigningRoot_10000(t *testing.T) {
domain := [4]byte{}
p := []byte{}
s := []byte{}
d := uint64(0)
d := []byte{}
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(&ba)
fuzzer.Fuzz(&pubkey)
@@ -86,9 +70,13 @@ func TestFuzzverifyDepositDataSigningRoot_10000(t *testing.T) {
fuzzer.Fuzz(&p)
fuzzer.Fuzz(&s)
fuzzer.Fuzz(&d)
domain := bytesutil.FromBytes4(domain[:])
verifySignature(ba, pubkey[:], sig[:], domain)
verifySignature(ba, p, s, d)
if err := verifySignature(ba, pubkey[:], sig[:], domain[:]); err != nil {
t.Log(err)
}
if err := verifySignature(ba, p, s, d); err != nil {
t.Log(err)
}
}
}
@@ -126,10 +114,15 @@ func TestFuzzEth1DataHasEnoughSupport_10000(t *testing.T) {
for i := 0; i < 100000; i++ {
fuzzer.Fuzz(eth1data)
fuzzer.Fuzz(&stateVotes)
s, _ := beaconstate.InitializeFromProto(&ethereum_beacon_p2p_v1.BeaconState{
s, err := beaconstate.InitializeFromProto(&ethereum_beacon_p2p_v1.BeaconState{
Eth1DataVotes: stateVotes,
})
Eth1DataHasEnoughSupport(s, eth1data)
if err != nil {
t.Log(err)
}
if _, err := Eth1DataHasEnoughSupport(s, eth1data); err != nil {
t.Log(err)
}
}
}
@@ -142,8 +135,13 @@ func TestFuzzProcessBlockHeaderNoVerify_10000(t *testing.T) {
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(block)
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
_, _ = ProcessBlockHeaderNoVerify(s, block)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
if err != nil {
t.Log(err)
}
if _, err = ProcessBlockHeaderNoVerify(s, block); err != nil {
t.Log(err)
}
}
}
@@ -155,7 +153,10 @@ func TestFuzzProcessRandao_10000(t *testing.T) {
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(blockBody)
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
if err != nil {
t.Log(err)
}
r, err := ProcessRandao(s, blockBody)
if err != nil && r != nil {
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, blockBody)
@@ -171,7 +172,10 @@ func TestFuzzProcessRandaoNoVerify_10000(t *testing.T) {
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(blockBody)
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
if err != nil {
t.Log(err)
}
r, err := ProcessRandaoNoVerify(s, blockBody)
if err != nil && r != nil {
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, blockBody)
@@ -187,7 +191,10 @@ func TestFuzzProcessProposerSlashings_10000(t *testing.T) {
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(blockBody)
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
if err != nil {
t.Log(err)
}
r, err := ProcessProposerSlashings(ctx, s, blockBody)
if err != nil && r != nil {
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, blockBody)
@@ -202,8 +209,13 @@ func TestFuzzVerifyProposerSlashing_10000(t *testing.T) {
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(proposerSlashing)
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
VerifyProposerSlashing(s, proposerSlashing)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
if err != nil {
t.Log(err)
}
if err := VerifyProposerSlashing(s, proposerSlashing); err != nil {
t.Log(err)
}
}
}
@@ -215,7 +227,10 @@ func TestFuzzProcessAttesterSlashings_10000(t *testing.T) {
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(blockBody)
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
if err != nil {
t.Log(err)
}
r, err := ProcessAttesterSlashings(ctx, s, blockBody)
if err != nil && r != nil {
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, blockBody)
@@ -231,8 +246,13 @@ func TestFuzzVerifyAttesterSlashing_10000(t *testing.T) {
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(attesterSlashing)
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
VerifyAttesterSlashing(ctx, s, attesterSlashing)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
if err != nil {
t.Log(err)
}
if err := VerifyAttesterSlashing(ctx, s, attesterSlashing); err != nil {
t.Log(err)
}
}
}
@@ -266,7 +286,10 @@ func TestFuzzProcessAttestations_10000(t *testing.T) {
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(blockBody)
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
if err != nil {
t.Log(err)
}
r, err := ProcessAttestations(ctx, s, blockBody)
if err != nil && r != nil {
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, blockBody)
@@ -282,7 +305,10 @@ func TestFuzzProcessAttestationsNoVerify_10000(t *testing.T) {
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(blockBody)
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
if err != nil {
t.Log(err)
}
r, err := ProcessAttestationsNoVerify(ctx, s, blockBody)
if err != nil && r != nil {
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, blockBody)
@@ -298,7 +324,10 @@ func TestFuzzProcessAttestation_10000(t *testing.T) {
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(attestation)
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
if err != nil {
t.Log(err)
}
r, err := ProcessAttestation(ctx, s, attestation)
if err != nil && r != nil {
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, attestation)
@@ -314,8 +343,13 @@ func TestFuzzVerifyIndexedAttestationn_10000(t *testing.T) {
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(idxAttestation)
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
VerifyIndexedAttestation(ctx, s, idxAttestation)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
if err != nil {
t.Log(err)
}
if err := VerifyIndexedAttestation(ctx, s, idxAttestation); err != nil {
t.Log(err)
}
}
}
@@ -327,8 +361,13 @@ func TestFuzzVerifyAttestation_10000(t *testing.T) {
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(attestation)
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
VerifyAttestation(ctx, s, attestation)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
if err != nil {
t.Log(err)
}
if err := VerifyAttestation(ctx, s, attestation); err != nil {
t.Log(err)
}
}
}
@@ -340,7 +379,10 @@ func TestFuzzProcessDeposits_10000(t *testing.T) {
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(blockBody)
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
if err != nil {
t.Log(err)
}
r, err := ProcessDeposits(ctx, s, blockBody)
if err != nil && r != nil {
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, blockBody)
@@ -357,7 +399,10 @@ func TestFuzzProcessPreGenesisDeposit_10000(t *testing.T) {
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(deposit)
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
if err != nil {
t.Log(err)
}
r, err := ProcessPreGenesisDeposit(ctx, s, deposit)
if err != nil && r != nil {
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, deposit)
@@ -373,7 +418,10 @@ func TestFuzzProcessDeposit_10000(t *testing.T) {
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(deposit)
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
if err != nil {
t.Log(err)
}
r, err := ProcessDeposit(s, deposit)
if err != nil && r != nil {
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, deposit)
@@ -388,8 +436,13 @@ func TestFuzzverifyDeposit_10000(t *testing.T) {
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(deposit)
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
verifyDeposit(s, deposit)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
if err != nil {
t.Log(err)
}
if err := verifyDeposit(s, deposit); err != nil {
t.Log(err)
}
}
}
@@ -401,7 +454,10 @@ func TestFuzzProcessVoluntaryExits_10000(t *testing.T) {
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(blockBody)
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
if err != nil {
t.Log(err)
}
r, err := ProcessVoluntaryExits(ctx, s, blockBody)
if err != nil && r != nil {
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, blockBody)
@@ -416,7 +472,10 @@ func TestFuzzProcessVoluntaryExitsNoVerify_10000(t *testing.T) {
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(blockBody)
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
if err != nil {
t.Log(err)
}
r, err := ProcessVoluntaryExitsNoVerify(s, blockBody)
if err != nil && r != nil {
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, blockBody)
@@ -436,6 +495,8 @@ func TestFuzzVerifyExit_10000(t *testing.T) {
fuzzer.Fuzz(val)
fuzzer.Fuzz(fork)
fuzzer.Fuzz(&slot)
VerifyExit(val, slot, fork, ve)
if err := VerifyExit(val, slot, fork, ve, params.BeaconConfig().ZeroHash[:]); err != nil {
t.Log(err)
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,113 @@
package blocks_test
import (
"context"
"testing"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
)
func TestProcessAttesterSlashings_RegressionSlashableIndices(t *testing.T) {
testutil.ResetCache()
beaconState, privKeys := testutil.DeterministicGenesisState(t, 5500)
for _, vv := range beaconState.Validators() {
vv.WithdrawableEpoch = 1 * params.BeaconConfig().SlotsPerEpoch
}
// This set of indices is very similar to the one from our sapphire testnet
// when close to 100 validators were incorrectly slashed. The set is from 0 -5500,
// instead of 55000 as it would take too long to generate a state.
setA := []uint64{21, 92, 236, 244, 281, 321, 510, 524,
538, 682, 828, 858, 913, 920, 922, 959, 1176, 1207,
1222, 1229, 1354, 1394, 1436, 1454, 1510, 1550,
1552, 1576, 1645, 1704, 1842, 1967, 2076, 2111, 2134, 2307,
2343, 2354, 2417, 2524, 2532, 2555, 2740, 2749, 2759, 2762,
2800, 2809, 2824, 2987, 3110, 3125, 3559, 3583, 3599, 3608,
3657, 3685, 3723, 3756, 3759, 3761, 3820, 3826, 3979, 4030,
4141, 4170, 4205, 4247, 4257, 4479, 4492, 4569, 5091,
}
// Only 2800 is the slashable index.
setB := []uint64{1361, 1438, 2383, 2800}
expectedSlashedVal := 2800
root1 := [32]byte{'d', 'o', 'u', 'b', 'l', 'e', '1'}
att1 := &ethpb.IndexedAttestation{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0},
Target: &ethpb.Checkpoint{Epoch: 0, Root: root1[:]},
},
AttestingIndices: setA,
}
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)
}
aggSigs := []*bls.Signature{}
for _, index := range setA {
sig := privKeys[index].Sign(signingRoot[:])
aggSigs = append(aggSigs, sig)
}
aggregateSig := bls.AggregateSignatures(aggSigs)
att1.Signature = aggregateSig.Marshal()[:]
root2 := [32]byte{'d', 'o', 'u', 'b', 'l', 'e', '2'}
att2 := &ethpb.IndexedAttestation{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0},
Target: &ethpb.Checkpoint{Epoch: 0, Root: root2[:]},
},
AttestingIndices: setB,
}
signingRoot, err = helpers.ComputeSigningRoot(att2.Data, domain)
if err != nil {
t.Errorf("Could not get signing root of beacon block header: %v", err)
}
aggSigs = []*bls.Signature{}
for _, index := range setB {
sig := privKeys[index].Sign(signingRoot[:])
aggSigs = append(aggSigs, sig)
}
aggregateSig = bls.AggregateSignatures(aggSigs)
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 := &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
AttesterSlashings: slashings,
},
}
newState, err := blocks.ProcessAttesterSlashings(context.Background(), beaconState, block.Body)
if err != nil {
t.Fatal(err)
}
newRegistry := newState.Validators()
if !newRegistry[expectedSlashedVal].Slashed {
t.Errorf("Validator with index %d was not slashed despite performing a double vote", expectedSlashedVal)
}
for idx, val := range newRegistry {
if val.Slashed && idx != expectedSlashedVal {
t.Errorf("validator with index: %d was unintentionally slashed", idx)
}
}
}

View File

@@ -11,6 +11,17 @@ import (
"github.com/prysmaticlabs/prysm/shared/params"
)
func FakeDeposits(n int) []*ethpb.Eth1Data {
deposits := make([]*ethpb.Eth1Data, n)
for i := 0; i < n; i++ {
deposits[i] = &ethpb.Eth1Data{
DepositCount: 1,
DepositRoot: []byte("root"),
}
}
return deposits
}
func TestEth1DataHasEnoughSupport(t *testing.T) {
tests := []struct {
stateVotes []*ethpb.Eth1Data
@@ -19,21 +30,7 @@ func TestEth1DataHasEnoughSupport(t *testing.T) {
votingPeriodLength uint64
}{
{
stateVotes: []*ethpb.Eth1Data{
{
DepositCount: 1,
DepositRoot: []byte("root"),
}, {
DepositCount: 1,
DepositRoot: []byte("root"),
}, {
DepositCount: 1,
DepositRoot: []byte("root"),
}, {
DepositCount: 1,
DepositRoot: []byte("root"),
},
},
stateVotes: FakeDeposits(4 * int(params.BeaconConfig().SlotsPerEpoch)),
data: &ethpb.Eth1Data{
DepositCount: 1,
DepositRoot: []byte("root"),
@@ -41,21 +38,7 @@ func TestEth1DataHasEnoughSupport(t *testing.T) {
hasSupport: true,
votingPeriodLength: 7,
}, {
stateVotes: []*ethpb.Eth1Data{
{
DepositCount: 1,
DepositRoot: []byte("root"),
}, {
DepositCount: 1,
DepositRoot: []byte("root"),
}, {
DepositCount: 1,
DepositRoot: []byte("root"),
}, {
DepositCount: 1,
DepositRoot: []byte("root"),
},
},
stateVotes: FakeDeposits(4 * int(params.BeaconConfig().SlotsPerEpoch)),
data: &ethpb.Eth1Data{
DepositCount: 1,
DepositRoot: []byte("root"),
@@ -63,21 +46,7 @@ func TestEth1DataHasEnoughSupport(t *testing.T) {
hasSupport: false,
votingPeriodLength: 8,
}, {
stateVotes: []*ethpb.Eth1Data{
{
DepositCount: 1,
DepositRoot: []byte("root"),
}, {
DepositCount: 1,
DepositRoot: []byte("root"),
}, {
DepositCount: 1,
DepositRoot: []byte("root"),
}, {
DepositCount: 1,
DepositRoot: []byte("root"),
},
},
stateVotes: FakeDeposits(4 * int(params.BeaconConfig().SlotsPerEpoch)),
data: &ethpb.Eth1Data{
DepositCount: 1,
DepositRoot: []byte("root"),
@@ -90,12 +59,15 @@ func TestEth1DataHasEnoughSupport(t *testing.T) {
for i, tt := range tests {
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
c := params.BeaconConfig()
c.SlotsPerEth1VotingPeriod = tt.votingPeriodLength
c.EpochsPerEth1VotingPeriod = tt.votingPeriodLength
params.OverrideBeaconConfig(c)
s, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
s, err := beaconstate.InitializeFromProto(&pb.BeaconState{
Eth1DataVotes: tt.stateVotes,
})
if err != nil {
t.Fatal(err)
}
result, err := blocks.Eth1DataHasEnoughSupport(s, tt.data)
if err != nil {
t.Fatal(err)
@@ -103,8 +75,7 @@ func TestEth1DataHasEnoughSupport(t *testing.T) {
if result != tt.hasSupport {
t.Errorf(
"blocks.Eth1DataHasEnoughSupport(%+v, %+v) = %t, wanted %t",
s,
"blocks.Eth1DataHasEnoughSupport(%+v) = %t, wanted %t",
tt.data,
result,
tt.hasSupport,

View File

@@ -21,6 +21,10 @@ import (
"gopkg.in/d4l3k/messagediff.v1"
)
func init() {
state.SkipSlotCache.Disable()
}
func runBlockProcessingTest(t *testing.T, config string) {
if err := spectest.SetConfig(config); err != nil {
t.Fatal(err)
@@ -94,8 +98,8 @@ func runBlockProcessingTest(t *testing.T, config string) {
t.Fatalf("Failed to unmarshal: %v", err)
}
if !proto.Equal(beaconState.CloneInnerState(), postBeaconState) {
diff, _ := messagediff.PrettyDiff(beaconState.CloneInnerState(), postBeaconState)
if !proto.Equal(beaconState.InnerStateUnsafe(), postBeaconState) {
diff, _ := messagediff.PrettyDiff(beaconState.InnerStateUnsafe(), postBeaconState)
t.Log(diff)
t.Fatal("Post state does not match expected")
}

View File

@@ -194,15 +194,18 @@ func ProcessSlashings(state *stateTrie.BeaconState) (*stateTrie.BeaconState, err
// current_epoch = get_current_epoch(state)
// next_epoch = Epoch(current_epoch + 1)
// # Reset eth1 data votes
// if (state.slot + 1) % SLOTS_PER_ETH1_VOTING_PERIOD == 0:
// if next_epoch % EPOCHS_PER_ETH1_VOTING_PERIOD == 0:
// state.eth1_data_votes = []
// # Update effective balances with hysteresis
// for index, validator in enumerate(state.validators):
// balance = state.balances[index]
// HALF_INCREMENT = EFFECTIVE_BALANCE_INCREMENT // 2
// if balance < validator.effective_balance or validator.effective_balance + 3 * HALF_INCREMENT < balance:
// validator.effective_balance = min(balance - balance % EFFECTIVE_BALANCE_INCREMENT, MAX_EFFECTIVE_BALANCE)
// # Set active index root
// HYSTERESIS_INCREMENT = EFFECTIVE_BALANCE_INCREMENT // HYSTERESIS_QUOTIENT
// DOWNWARD_THRESHOLD = HYSTERESIS_INCREMENT * HYSTERESIS_DOWNWARD_MULTIPLIER
// UPWARD_THRESHOLD = HYSTERESIS_INCREMENT * HYSTERESIS_UPWARD_MULTIPLIER
// if (
// balance + DOWNWARD_THRESHOLD < validator.effective_balance
// or validator.effective_balance + UPWARD_THRESHOLD < balance
// ):
// index_epoch = Epoch(next_epoch + ACTIVATION_EXIT_DELAY)
// index_root_position = index_epoch % EPOCHS_PER_HISTORICAL_VECTOR
// indices_list = List[ValidatorIndex, VALIDATOR_REGISTRY_LIMIT](get_active_validator_indices(state, index_epoch))
@@ -228,7 +231,7 @@ func ProcessFinalUpdates(state *stateTrie.BeaconState) (*stateTrie.BeaconState,
nextEpoch := currentEpoch + 1
// Reset ETH1 data votes.
if (state.Slot()+1)%params.BeaconConfig().SlotsPerEth1VotingPeriod == 0 {
if nextEpoch%params.BeaconConfig().EpochsPerEth1VotingPeriod == 0 {
if err := state.SetEth1DataVotes([]*ethpb.Eth1Data{}); err != nil {
return nil, err
}
@@ -244,8 +247,11 @@ func ProcessFinalUpdates(state *stateTrie.BeaconState) (*stateTrie.BeaconState,
return false, fmt.Errorf("validator index exceeds validator length in state %d >= %d", idx, len(state.Balances()))
}
balance := bals[idx]
halfInc := params.BeaconConfig().EffectiveBalanceIncrement / 2
if balance < val.EffectiveBalance || val.EffectiveBalance+3*halfInc < balance {
hysteresisInc := params.BeaconConfig().EffectiveBalanceIncrement / params.BeaconConfig().HysteresisQuotient
downwardThreshold := hysteresisInc * params.BeaconConfig().HysteresisDownwardMultiplier
upwardThreshold := hysteresisInc * params.BeaconConfig().HysteresisUpwardMultiplier
if balance+downwardThreshold < val.EffectiveBalance || val.EffectiveBalance+upwardThreshold < balance {
val.EffectiveBalance = params.BeaconConfig().MaxEffectiveBalance
if val.EffectiveBalance > balance-balance%params.BeaconConfig().EffectiveBalanceIncrement {
val.EffectiveBalance = balance - balance%params.BeaconConfig().EffectiveBalanceIncrement
@@ -351,7 +357,11 @@ func unslashedAttestingIndices(state *stateTrie.BeaconState, atts []*pb.PendingA
sort.Slice(setIndices, func(i, j int) bool { return setIndices[i] < setIndices[j] })
// Remove the slashed validator indices.
for i := 0; i < len(setIndices); i++ {
if v, _ := state.ValidatorAtIndex(setIndices[i]); v != nil && v.Slashed {
v, err := state.ValidatorAtIndex(setIndices[i])
if err != nil {
return nil, errors.Wrap(err, "failed to look up validator")
}
if v != nil && v.Slashed {
setIndices = append(setIndices[:i], setIndices[i+1:]...)
}
}

View File

@@ -18,6 +18,9 @@ func TestFuzzFinalUpdates_10000(t *testing.T) {
if err != nil {
t.Fatal(err)
}
_, _ = ProcessFinalUpdates(s)
_, err = ProcessFinalUpdates(s)
if err != nil {
t.Log(err)
}
}
}

View File

@@ -63,7 +63,9 @@ func TestUnslashedAttestingIndices_CanSortAndFilter(t *testing.T) {
slashedValidator := indices[0]
validators = state.Validators()
validators[slashedValidator].Slashed = true
state.SetValidators(validators)
if err = state.SetValidators(validators); err != nil {
t.Fatal(err)
}
indices, err = unslashedAttestingIndices(state, atts)
if err != nil {
t.Fatal(err)
@@ -311,25 +313,38 @@ func TestProcessFinalUpdates_CanProcess(t *testing.T) {
s := buildState(params.BeaconConfig().SlotsPerHistoricalRoot-1, params.BeaconConfig().SlotsPerEpoch)
ce := helpers.CurrentEpoch(s)
ne := ce + 1
s.SetEth1DataVotes([]*ethpb.Eth1Data{})
if err := s.SetEth1DataVotes([]*ethpb.Eth1Data{}); err != nil {
t.Fatal(err)
}
balances := s.Balances()
balances[0] = 29 * 1e9
s.SetBalances(balances)
balances[0] = 31.75 * 1e9
balances[1] = 31.74 * 1e9
if err := s.SetBalances(balances); err != nil {
t.Fatal(err)
}
slashings := s.Slashings()
slashings[ce] = 0
s.SetSlashings(slashings)
if err := s.SetSlashings(slashings); err != nil {
t.Fatal(err)
}
mixes := s.RandaoMixes()
mixes[ce] = []byte{'A'}
s.SetRandaoMixes(mixes)
if err := s.SetRandaoMixes(mixes); err != nil {
t.Fatal(err)
}
newS, err := ProcessFinalUpdates(s)
if err != nil {
t.Fatal(err)
}
// Verify effective balance is correctly updated.
if newS.Validators()[0].EffectiveBalance != 29*1e9 {
if newS.Validators()[0].EffectiveBalance != params.BeaconConfig().MaxEffectiveBalance {
t.Errorf("effective balance incorrectly updated, got %d", s.Validators()[0].EffectiveBalance)
}
if newS.Validators()[1].EffectiveBalance != 31*1e9 {
t.Errorf("effective balance incorrectly updated, got %d", s.Validators()[1].EffectiveBalance)
}
// Verify slashed balances correctly updated.
if newS.Slashings()[ce] != newS.Slashings()[ne] {
@@ -339,7 +354,7 @@ func TestProcessFinalUpdates_CanProcess(t *testing.T) {
}
// Verify randao is correctly updated in the right position.
if mix, _ := newS.RandaoMixAtIndex(ne); bytes.Equal(mix, params.BeaconConfig().ZeroHash[:]) {
if mix, err := newS.RandaoMixAtIndex(ne); err != nil || bytes.Equal(mix, params.BeaconConfig().ZeroHash[:]) {
t.Error("latest RANDAO still zero hashes")
}

View File

@@ -74,13 +74,17 @@ func TestUpdateBalance(t *testing.T) {
func TestSameHead(t *testing.T) {
beaconState, _ := testutil.DeterministicGenesisState(t, 100)
beaconState.SetSlot(1)
if err := beaconState.SetSlot(1); err != nil {
t.Fatal(err)
}
att := &ethpb.Attestation{Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 0}}}
r := [32]byte{'A'}
br := beaconState.BlockRoots()
br[0] = r[:]
beaconState.SetBlockRoots(br)
if err := beaconState.SetBlockRoots(br); err != nil {
t.Fatal(err)
}
att.Data.BeaconBlockRoot = r[:]
same, err := precompute.SameHead(beaconState, &pb.PendingAttestation{Data: att.Data})
if err != nil {
@@ -102,13 +106,17 @@ func TestSameHead(t *testing.T) {
func TestSameTarget(t *testing.T) {
beaconState, _ := testutil.DeterministicGenesisState(t, 100)
beaconState.SetSlot(1)
if err := beaconState.SetSlot(1); err != nil {
t.Fatal(err)
}
att := &ethpb.Attestation{Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 0}}}
r := [32]byte{'A'}
br := beaconState.BlockRoots()
br[0] = r[:]
beaconState.SetBlockRoots(br)
if err := beaconState.SetBlockRoots(br); err != nil {
t.Fatal(err)
}
att.Data.Target.Root = r[:]
same, err := precompute.SameTarget(beaconState, &pb.PendingAttestation{Data: att.Data}, 0)
if err != nil {
@@ -130,13 +138,17 @@ func TestSameTarget(t *testing.T) {
func TestAttestedPrevEpoch(t *testing.T) {
beaconState, _ := testutil.DeterministicGenesisState(t, 100)
beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch)
if err := beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch); err != nil {
t.Fatal(err)
}
att := &ethpb.Attestation{Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 0}}}
r := [32]byte{'A'}
br := beaconState.BlockRoots()
br[0] = r[:]
beaconState.SetBlockRoots(br)
if err := beaconState.SetBlockRoots(br); err != nil {
t.Fatal(err)
}
att.Data.Target.Root = r[:]
att.Data.BeaconBlockRoot = r[:]
votedEpoch, votedTarget, votedHead, err := precompute.AttestedPrevEpoch(beaconState, &pb.PendingAttestation{Data: att.Data})
@@ -156,14 +168,18 @@ func TestAttestedPrevEpoch(t *testing.T) {
func TestAttestedCurrentEpoch(t *testing.T) {
beaconState, _ := testutil.DeterministicGenesisState(t, 100)
beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch + 1)
if err := beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch + 1); err != nil {
t.Fatal(err)
}
att := &ethpb.Attestation{Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 1}}}
r := [32]byte{'A'}
br := beaconState.BlockRoots()
br[params.BeaconConfig().SlotsPerEpoch] = r[:]
beaconState.SetBlockRoots(br)
if err := beaconState.SetBlockRoots(br); err != nil {
t.Fatal(err)
}
att.Data.Target.Root = r[:]
att.Data.BeaconBlockRoot = r[:]
votedEpoch, votedTarget, err := precompute.AttestedCurrentEpoch(beaconState, &pb.PendingAttestation{Data: att.Data})
@@ -184,7 +200,9 @@ func TestProcessAttestations(t *testing.T) {
validators := uint64(64)
beaconState, _ := testutil.DeterministicGenesisState(t, validators)
beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch)
if err := beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch); err != nil {
t.Fatal(err)
}
bf := []byte{0xff}
att1 := &ethpb.Attestation{Data: &ethpb.AttestationData{
@@ -199,18 +217,26 @@ func TestProcessAttestations(t *testing.T) {
br := beaconState.BlockRoots()
newRt := [32]byte{'B'}
br[0] = newRt[:]
beaconState.SetBlockRoots(br)
if err := beaconState.SetBlockRoots(br); err != nil {
t.Fatal(err)
}
att2.Data.Target.Root = rt[:]
att2.Data.BeaconBlockRoot = newRt[:]
beaconState.SetPreviousEpochAttestations([]*pb.PendingAttestation{{Data: att1.Data, AggregationBits: bf}})
beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{{Data: att2.Data, AggregationBits: bf}})
err := beaconState.SetPreviousEpochAttestations([]*pb.PendingAttestation{{Data: att1.Data, AggregationBits: bf}})
if err != nil {
t.Fatal(err)
}
err = beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{{Data: att2.Data, AggregationBits: bf}})
if err != nil {
t.Fatal(err)
}
vp := make([]*precompute.Validator, validators)
for i := 0; i < len(vp); i++ {
vp[i] = &precompute.Validator{CurrentEpochEffectiveBalance: 100}
}
bp := &precompute.Balance{}
vp, bp, err := precompute.ProcessAttestations(context.Background(), beaconState, vp, bp)
vp, bp, err = precompute.ProcessAttestations(context.Background(), beaconState, vp, bp)
if err != nil {
t.Fatal(err)
}

View File

@@ -3,6 +3,7 @@ package precompute
import (
"context"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/shared/params"
@@ -12,7 +13,7 @@ import (
// New gets called at the beginning of process epoch cycle to return
// pre computed instances of validators attesting records and total
// balances attested in an epoch.
func New(ctx context.Context, state *stateTrie.BeaconState) ([]*Validator, *Balance) {
func New(ctx context.Context, state *stateTrie.BeaconState) ([]*Validator, *Balance, error) {
ctx, span := trace.StartSpan(ctx, "precomputeEpoch.New")
defer span.End()
vp := make([]*Validator, state.NumValidators())
@@ -21,7 +22,7 @@ func New(ctx context.Context, state *stateTrie.BeaconState) ([]*Validator, *Bala
currentEpoch := helpers.CurrentEpoch(state)
prevEpoch := helpers.PrevEpoch(state)
state.ReadFromEveryValidator(func(idx int, val *stateTrie.ReadOnlyValidator) error {
if err := state.ReadFromEveryValidator(func(idx int, val *stateTrie.ReadOnlyValidator) error {
// Was validator withdrawable or slashed
withdrawable := currentEpoch >= val.WithdrawableEpoch()
p := &Validator{
@@ -46,6 +47,8 @@ func New(ctx context.Context, state *stateTrie.BeaconState) ([]*Validator, *Bala
vp[idx] = p
return nil
})
return vp, bp
}); err != nil {
return nil, nil, errors.Wrap(err, "failed to initialize precompute")
}
return vp, bp, nil
}

View File

@@ -31,7 +31,10 @@ func TestNew(t *testing.T) {
t.Fatal(err)
}
e := params.BeaconConfig().FarFutureEpoch
v, b := precompute.New(context.Background(), s)
v, b, err := precompute.New(context.Background(), s)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(v[0], &precompute.Validator{IsSlashed: true, CurrentEpochEffectiveBalance: 100,
InclusionDistance: e, InclusionSlot: e}) {
t.Error("Incorrect validator 0 status")

View File

@@ -83,7 +83,9 @@ func attestationDelta(state *stateTrie.BeaconState, bp *Balance, v *Validator) (
// Process source reward / penalty
if v.IsPrevEpochAttester && !v.IsSlashed {
r += br * bp.PrevEpochAttesters / bp.CurrentEpoch
inc := params.BeaconConfig().EffectiveBalanceIncrement
rewardNumerator := br * bp.PrevEpochAttesters / inc
r += rewardNumerator / (bp.CurrentEpoch / inc)
proposerReward := br / params.BeaconConfig().ProposerRewardQuotient
maxAtteserReward := br - proposerReward
r += maxAtteserReward / v.InclusionDistance
@@ -93,14 +95,18 @@ func attestationDelta(state *stateTrie.BeaconState, bp *Balance, v *Validator) (
// Process target reward / penalty
if v.IsPrevEpochTargetAttester && !v.IsSlashed {
r += br * bp.PrevEpochTargetAttesters / bp.CurrentEpoch
inc := params.BeaconConfig().EffectiveBalanceIncrement
rewardNumerator := br * bp.PrevEpochAttesters / inc
r += rewardNumerator / (bp.CurrentEpoch / inc)
} else {
p += br
}
// Process head reward / penalty
if v.IsPrevEpochHeadAttester && !v.IsSlashed {
r += br * bp.PrevEpochHeadAttesters / bp.CurrentEpoch
inc := params.BeaconConfig().EffectiveBalanceIncrement
rewardNumerator := br * bp.PrevEpochAttesters / inc
r += rewardNumerator / (bp.CurrentEpoch / inc)
} else {
p += br
}

View File

@@ -35,7 +35,10 @@ func TestProcessRewardsAndPenaltiesPrecompute(t *testing.T) {
t.Fatal(err)
}
vp, bp := New(context.Background(), state)
vp, bp, err := New(context.Background(), state)
if err != nil {
t.Error(err)
}
vp, bp, err = ProcessAttestations(context.Background(), state, vp, bp)
if err != nil {
t.Fatal(err)
@@ -88,7 +91,10 @@ func TestAttestationDeltaPrecompute(t *testing.T) {
t.Fatal(err)
}
vp, bp := New(context.Background(), state)
vp, bp, err := New(context.Background(), state)
if err != nil {
t.Error(err)
}
vp, bp, err = ProcessAttestations(context.Background(), state, vp, bp)
if err != nil {
t.Fatal(err)
@@ -173,7 +179,10 @@ func TestAttestationDeltas_ZeroEpoch(t *testing.T) {
t.Fatal(err)
}
vp, bp := New(context.Background(), state)
vp, bp, err := New(context.Background(), state)
if err != nil {
t.Error(err)
}
vp, bp, err = ProcessAttestations(context.Background(), state, vp, bp)
if err != nil {
t.Fatal(err)

View File

@@ -28,8 +28,11 @@ func runJustificationAndFinalizationTests(t *testing.T, config string) {
func processJustificationAndFinalizationPrecomputeWrapper(t *testing.T, state *state.BeaconState) (*state.BeaconState, error) {
ctx := context.Background()
vp, bp := precompute.New(ctx, state)
_, bp, err := precompute.ProcessAttestations(ctx, state, vp, bp)
vp, bp, err := precompute.New(ctx, state)
if err != nil {
t.Fatal(err)
}
_, bp, err = precompute.ProcessAttestations(ctx, state, vp, bp)
if err != nil {
t.Fatal(err)
}

View File

@@ -37,8 +37,11 @@ func processSlashingsWrapper(t *testing.T, state *beaconstate.BeaconState) (*bea
func processSlashingsPrecomputeWrapper(t *testing.T, state *beaconstate.BeaconState) (*beaconstate.BeaconState, error) {
ctx := context.Background()
vp, bp := precompute.New(ctx, state)
_, bp, err := precompute.ProcessAttestations(ctx, state, vp, bp)
vp, bp, err := precompute.New(ctx, state)
if err != nil {
t.Fatal(err)
}
_, bp, err = precompute.ProcessAttestations(ctx, state, vp, bp)
if err != nil {
t.Fatal(err)
}

View File

@@ -31,4 +31,6 @@ type ChainStartedData struct {
type InitializedData struct {
// StartTime is the time at which the chain started.
StartTime time.Time
// GenesisValidatorsRoot represents ssz.HashTreeRoot(state.validators).
GenesisValidatorsRoot []byte
}

View File

@@ -9,6 +9,7 @@ go_library(
"randao.go",
"rewards_penalties.go",
"shuffle.go",
"signing_root.go",
"slot_epoch.go",
"validators.go",
],
@@ -17,9 +18,12 @@ go_library(
"//beacon-chain:__subpackages__",
"//shared/benchutil/benchmark_files:__subpackages__",
"//shared/testutil:__pkg__",
"//shared/keystore:__pkg__",
"//shared/interop:__pkg__",
"//slasher:__subpackages__",
"//tools:__subpackages__",
"//validator:__subpackages__",
"//endtoend/evaluators:__pkg__",
],
deps = [
"//beacon-chain/cache:go_default_library",
@@ -48,6 +52,7 @@ go_test(
"randao_test.go",
"rewards_penalties_test.go",
"shuffle_test.go",
"signing_root_test.go",
"slot_epoch_test.go",
"validators_test.go",
],
@@ -64,6 +69,7 @@ go_test(
"//shared/params:go_default_library",
"//shared/sliceutil:go_default_library",
"//shared/testutil:go_default_library",
"@com_github_google_gofuzz//:go_default_library",
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
"@com_github_prysmaticlabs_go_ssz//:go_default_library",

View File

@@ -5,7 +5,6 @@ import (
"github.com/pkg/errors"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/go-ssz"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/hashutil"
@@ -124,15 +123,15 @@ func AggregateAttestation(a1 *ethpb.Attestation, a2 *ethpb.Attestation) (*ethpb.
// domain = get_domain(state, DOMAIN_BEACON_ATTESTER, compute_epoch_at_slot(slot))
// return bls_sign(privkey, hash_tree_root(slot), domain)
func SlotSignature(state *stateTrie.BeaconState, slot uint64, privKey *bls.SecretKey) (*bls.Signature, error) {
d, err := Domain(state.Fork(), CurrentEpoch(state), params.BeaconConfig().DomainBeaconAttester)
d, err := Domain(state.Fork(), CurrentEpoch(state), params.BeaconConfig().DomainBeaconAttester, state.GenesisValidatorRoot())
if err != nil {
return nil, err
}
s, err := ssz.HashTreeRoot(slot)
s, err := ComputeSigningRoot(slot, d)
if err != nil {
return nil, err
}
return privKey.Sign(s[:], d), nil
return privKey.Sign(s[:]), nil
}
// IsAggregator returns true if the signature is from the input validator. The committee

View File

@@ -202,7 +202,7 @@ func TestAggregateAttestations(t *testing.T) {
atts := make([]*ethpb.Attestation, len(bl))
for i, b := range bl {
sk := bls.RandKey()
sig := sk.Sign([]byte("dummy_test_data"), 0 /*domain*/)
sig := sk.Sign([]byte("dummy_test_data"))
atts[i] = &ethpb.Attestation{
AggregationBits: b,
Data: nil,
@@ -240,7 +240,7 @@ func TestAggregateAttestations(t *testing.T) {
func TestSlotSignature_Verify(t *testing.T) {
priv := bls.RandKey()
pub := priv.PublicKey()
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{
Fork: &pb.Fork{
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
@@ -248,6 +248,9 @@ func TestSlotSignature_Verify(t *testing.T) {
},
Slot: 100,
})
if err != nil {
t.Fatal(err)
}
slot := uint64(101)
sig, err := helpers.SlotSignature(state, slot, priv)
@@ -255,12 +258,15 @@ func TestSlotSignature_Verify(t *testing.T) {
t.Fatal(err)
}
domain, err := helpers.Domain(state.Fork(), helpers.CurrentEpoch(state), params.BeaconConfig().DomainBeaconAttester)
domain, err := helpers.Domain(state.Fork(), helpers.CurrentEpoch(state), params.BeaconConfig().DomainBeaconAttester, state.GenesisValidatorRoot())
if err != nil {
t.Fatal(err)
}
msg, _ := ssz.HashTreeRoot(slot)
if !sig.Verify(msg[:], pub, domain) {
msg, err := helpers.ComputeSigningRoot(slot, domain)
if err != nil {
t.Fatal(err)
}
if !sig.Verify(msg[:], pub) {
t.Error("Could not verify slot signature")
}
}
@@ -272,7 +278,7 @@ func TestIsAggregator_True(t *testing.T) {
if err != nil {
t.Fatal(err)
}
sig := privKeys[0].Sign([]byte{}, 0)
sig := privKeys[0].Sign([]byte{'A'})
agg, err := helpers.IsAggregator(uint64(len(committee)), sig.Marshal())
if err != nil {
t.Fatal(err)
@@ -291,7 +297,7 @@ func TestIsAggregator_False(t *testing.T) {
if err != nil {
t.Fatal(err)
}
sig := privKeys[0].Sign([]byte{}, 0)
sig := privKeys[0].Sign([]byte{'A'})
agg, err := helpers.IsAggregator(uint64(len(committee)), sig.Marshal())
if err != nil {
t.Fatal(err)
@@ -304,11 +310,11 @@ func TestIsAggregator_False(t *testing.T) {
func TestAggregateSignature_True(t *testing.T) {
pubkeys := make([]*bls.PublicKey, 0, 100)
atts := make([]*ethpb.Attestation, 0, 100)
msg := []byte("hello")
msg := bytesutil.ToBytes32([]byte("hello"))
for i := 0; i < 100; i++ {
priv := bls.RandKey()
pub := priv.PublicKey()
sig := priv.Sign(msg[:], 0)
sig := priv.Sign(msg[:])
pubkeys = append(pubkeys, pub)
att := &ethpb.Attestation{Signature: sig.Marshal()}
atts = append(atts, att)
@@ -317,7 +323,7 @@ func TestAggregateSignature_True(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if !aggSig.VerifyAggregateCommon(pubkeys, bytesutil.ToBytes32(msg), 0) {
if !aggSig.FastAggregateVerify(pubkeys, msg) {
t.Error("Signature did not verify")
}
}
@@ -329,7 +335,7 @@ func TestAggregateSignature_False(t *testing.T) {
for i := 0; i < 100; i++ {
priv := bls.RandKey()
pub := priv.PublicKey()
sig := priv.Sign(msg[:], 0)
sig := priv.Sign(msg[:])
pubkeys = append(pubkeys, pub)
att := &ethpb.Attestation{Signature: sig.Marshal()}
atts = append(atts, att)
@@ -338,7 +344,7 @@ func TestAggregateSignature_False(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if aggSig.VerifyAggregateCommon(pubkeys, bytesutil.ToBytes32(msg), 0) {
if aggSig.FastAggregateVerify(pubkeys, bytesutil.ToBytes32(msg)) {
t.Error("Signature not suppose to verify")
}
}

View File

@@ -58,7 +58,10 @@ func TestBlockRootAtSlot_CorrectBlockRoot(t *testing.T) {
for i, tt := range tests {
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
s.Slot = tt.stateSlot
state, _ := beaconstate.InitializeFromProto(s)
state, err := beaconstate.InitializeFromProto(s)
if err != nil {
t.Fatal(err)
}
wantedSlot := tt.slot
result, err := helpers.BlockRootAtSlot(state, wantedSlot)
if err != nil {
@@ -111,8 +114,11 @@ func TestBlockRootAtSlot_OutOfBounds(t *testing.T) {
}
for _, tt := range tests {
state.Slot = tt.stateSlot
s, _ := beaconstate.InitializeFromProto(state)
_, err := helpers.BlockRootAtSlot(s, tt.slot)
s, err := beaconstate.InitializeFromProto(state)
if err != nil {
t.Fatal(err)
}
_, err = helpers.BlockRootAtSlot(s, tt.slot)
if err == nil {
t.Errorf("Expected error %s, got nil", tt.expectedErr)
}

View File

@@ -181,7 +181,10 @@ type CommitteeAssignmentContainer struct {
// 2. Compute all committees.
// 3. Determine the attesting slot for each committee.
// 4. Construct a map of validator indices pointing to the respective committees.
func CommitteeAssignments(state *stateTrie.BeaconState, epoch uint64) (map[uint64]*CommitteeAssignmentContainer, map[uint64]uint64, error) {
func CommitteeAssignments(
state *stateTrie.BeaconState,
epoch uint64,
) (map[uint64]*CommitteeAssignmentContainer, map[uint64][]uint64, error) {
nextEpoch := NextEpoch(state)
if epoch > nextEpoch {
return nil, nil, fmt.Errorf(
@@ -191,9 +194,11 @@ func CommitteeAssignments(state *stateTrie.BeaconState, epoch uint64) (map[uint6
)
}
// Track which slot has which proposer.
// We determine the slots in which proposers are supposed to act.
// Some validators may need to propose multiple times per epoch, so
// we use a map of proposer idx -> []slot to keep track of this possibility.
startSlot := StartSlot(epoch)
proposerIndexToSlot := make(map[uint64]uint64)
proposerIndexToSlots := make(map[uint64][]uint64)
for slot := startSlot; slot < startSlot+params.BeaconConfig().SlotsPerEpoch; slot++ {
if err := state.SetSlot(slot); err != nil {
return nil, nil, err
@@ -202,7 +207,7 @@ func CommitteeAssignments(state *stateTrie.BeaconState, epoch uint64) (map[uint6
if err != nil {
return nil, nil, errors.Wrapf(err, "could not check proposer at slot %d", state.Slot())
}
proposerIndexToSlot[i] = slot
proposerIndexToSlots[i] = append(proposerIndexToSlots[i], slot)
}
activeValidatorIndices, err := ActiveValidatorIndices(state, epoch)
@@ -235,85 +240,7 @@ func CommitteeAssignments(state *stateTrie.BeaconState, epoch uint64) (map[uint6
}
}
return validatorIndexToCommittee, proposerIndexToSlot, nil
}
// CommitteeAssignment is used to query committee assignment from
// current and previous epoch.
//
// Deprecated: Consider using CommitteeAssignments, especially when computing more than one
// validator assignment as this method is O(n^2) in computational complexity. This method exists to
// ensure spec definition conformance and otherwise should probably not be used.
//
// Spec pseudocode definition:
// def get_committee_assignment(state: BeaconState,
// epoch: Epoch,
// validator_index: ValidatorIndex
// ) -> Optional[Tuple[Sequence[ValidatorIndex], CommitteeIndex, Slot]]:
// """
// Return the committee assignment in the ``epoch`` for ``validator_index``.
// ``assignment`` returned is a tuple of the following form:
// * ``assignment[0]`` is the list of validators in the committee
// * ``assignment[1]`` is the index to which the committee is assigned
// * ``assignment[2]`` is the slot at which the committee is assigned
// Return None if no assignment.
// """
// next_epoch = get_current_epoch(state) + 1
// assert epoch <= next_epoch
//
// start_slot = compute_start_slot_at_epoch(epoch)
// for slot in range(start_slot, start_slot + SLOTS_PER_EPOCH):
// for index in range(get_committee_count_at_slot(state, Slot(slot))):
// committee = get_beacon_committee(state, Slot(slot), CommitteeIndex(index))
// if validator_index in committee:
// return committee, CommitteeIndex(index), Slot(slot)
// return None
func CommitteeAssignment(
state *stateTrie.BeaconState,
epoch uint64,
validatorIndex uint64,
) ([]uint64, uint64, uint64, uint64, error) {
nextEpoch := NextEpoch(state)
if epoch > nextEpoch {
return nil, 0, 0, 0, fmt.Errorf(
"epoch %d can't be greater than next epoch %d",
epoch, nextEpoch)
}
// Track which slot has which proposer.
startSlot := StartSlot(epoch)
proposerIndexToSlot := make(map[uint64]uint64)
for slot := startSlot; slot < startSlot+params.BeaconConfig().SlotsPerEpoch; slot++ {
if err := state.SetSlot(slot); err != nil {
return nil, 0, 0, 0, err
}
i, err := BeaconProposerIndex(state)
if err != nil {
return nil, 0, 0, 0, errors.Wrapf(err, "could not check proposer at slot %d", state.Slot())
}
proposerIndexToSlot[i] = slot
}
activeValidatorIndices, err := ActiveValidatorIndices(state, epoch)
if err != nil {
return nil, 0, 0, 0, err
}
for slot := startSlot; slot < startSlot+params.BeaconConfig().SlotsPerEpoch; slot++ {
countAtSlot := SlotCommitteeCount(uint64(len(activeValidatorIndices)))
for i := uint64(0); i < countAtSlot; i++ {
committee, err := BeaconCommitteeFromState(state, slot, i)
if err != nil {
return nil, 0, 0, 0, errors.Wrapf(err, "could not get crosslink committee at slot %d", slot)
}
for _, v := range committee {
if validatorIndex == v {
proposerSlot, _ := proposerIndexToSlot[v]
return committee, i, slot, proposerSlot, nil
}
}
}
}
return []uint64{}, 0, 0, 0, fmt.Errorf("validator with index %d not found in assignments", validatorIndex)
return validatorIndexToCommittee, proposerIndexToSlots, nil
}
// VerifyBitfieldLength verifies that a bitfield length matches the given committee size.
@@ -354,12 +281,14 @@ func ShuffledIndices(state *stateTrie.BeaconState, epoch uint64) ([]uint64, erro
}
indices := make([]uint64, 0, state.NumValidators())
state.ReadFromEveryValidator(func(idx int, val *stateTrie.ReadOnlyValidator) error {
if err := state.ReadFromEveryValidator(func(idx int, val *stateTrie.ReadOnlyValidator) error {
if IsActiveValidatorUsingTrie(val, epoch) {
indices = append(indices, uint64(idx))
}
return nil
})
}); err != nil {
return nil, err
}
return UnshuffleList(indices, seed)
}
@@ -407,7 +336,6 @@ func UpdateCommitteeCache(state *stateTrie.BeaconState, epoch uint64) error {
// UpdateProposerIndicesInCache updates proposer indices entry of the committee cache.
func UpdateProposerIndicesInCache(state *stateTrie.BeaconState, epoch uint64) error {
indices, err := ActiveValidatorIndices(state, epoch)
if err != nil {
return nil

View File

@@ -4,7 +4,6 @@ import (
"fmt"
"reflect"
"strconv"
"strings"
"testing"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
@@ -96,11 +95,14 @@ func TestAttestationParticipants_NoCommitteeCache(t *testing.T) {
}
}
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{
Slot: params.BeaconConfig().SlotsPerEpoch,
Validators: validators,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
})
if err != nil {
t.Fatal(err)
}
attestationData := &ethpb.AttestationData{}
@@ -157,10 +159,13 @@ func TestAttestationParticipants_EmptyBitfield(t *testing.T) {
}
}
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{
Validators: validators,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
})
if err != nil {
t.Fatal(err)
}
attestationData := &ethpb.AttestationData{Target: &ethpb.Checkpoint{}}
committee, err := BeaconCommitteeFromState(state, attestationData.Slot, attestationData.CommitteeIndex)
@@ -168,10 +173,6 @@ func TestAttestationParticipants_EmptyBitfield(t *testing.T) {
t.Fatal(err)
}
indices := attestationutil.AttestingIndices(bitfield.NewBitlist(128), committee)
if err != nil {
t.Fatalf("attesting indices failed: %v", err)
}
if len(indices) != 0 {
t.Errorf("Attesting indices are non-zero despite an empty bitfield being provided; Size %d", len(indices))
}
@@ -191,148 +192,6 @@ func TestVerifyBitfieldLength_OK(t *testing.T) {
}
}
func TestCommitteeAssignment_CanRetrieve(t *testing.T) {
ClearCache()
// Initialize test with 128 validators, each slot and each index gets 2 validators.
validators := make([]*ethpb.Validator, 2*params.BeaconConfig().SlotsPerEpoch)
for i := 0; i < len(validators); i++ {
validators[i] = &ethpb.Validator{
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
}
}
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
Validators: validators,
Slot: params.BeaconConfig().SlotsPerEpoch,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
})
tests := []struct {
index uint64
slot uint64
committee []uint64
committeeIndex uint64
isProposer bool
proposerSlot uint64
}{
{
index: 0,
slot: 78,
committee: []uint64{0, 38},
committeeIndex: 0,
isProposer: false,
},
{
index: 1,
slot: 71,
committee: []uint64{1, 4},
committeeIndex: 0,
isProposer: true,
proposerSlot: 79,
},
{
index: 11,
slot: 90,
committee: []uint64{31, 11},
committeeIndex: 0,
isProposer: false,
},
}
for i, tt := range tests {
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
committee, committeeIndex, slot, proposerSlot, err := CommitteeAssignment(state, tt.slot/params.BeaconConfig().SlotsPerEpoch, tt.index)
if err != nil {
t.Fatalf("failed to execute NextEpochCommitteeAssignment: %v", err)
}
if committeeIndex != tt.committeeIndex {
t.Errorf("wanted committeeIndex %d, got committeeIndex %d for validator index %d",
tt.committeeIndex, committeeIndex, tt.index)
}
if slot != tt.slot {
t.Errorf("wanted slot %d, got slot %d for validator index %d",
tt.slot, slot, tt.index)
}
if proposerSlot != tt.proposerSlot {
t.Errorf("wanted proposer slot %d, got proposer slot %d for validator index %d",
tt.proposerSlot, proposerSlot, tt.index)
}
if !reflect.DeepEqual(committee, tt.committee) {
t.Errorf("wanted committee %v, got committee %v for validator index %d",
tt.committee, committee, tt.index)
}
if proposerSlot != tt.proposerSlot {
t.Errorf("wanted proposer slot slot %d, got slot %d for validator index %d",
tt.slot, slot, tt.index)
}
})
}
}
func TestCommitteeAssignment_CantFindValidator(t *testing.T) {
ClearCache()
validators := make([]*ethpb.Validator, 1)
for i := 0; i < len(validators); i++ {
validators[i] = &ethpb.Validator{
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
}
}
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
Validators: validators,
Slot: params.BeaconConfig().SlotsPerEpoch,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
})
index := uint64(10000)
_, _, _, _, err := CommitteeAssignment(state, 1, index)
if err != nil && !strings.Contains(err.Error(), "not found in assignments") {
t.Errorf("Wanted 'not found in assignments', received %v", err)
}
}
// Test helpers.CommitteeAssignments against the results of helpers.CommitteeAssignment by validator
// index. Warning: this test is a bit slow!
func TestCommitteeAssignments_AgreesWithSpecDefinitionMethod(t *testing.T) {
ClearCache()
// Initialize test with 256 validators, each slot and each index gets 4 validators.
validators := make([]*ethpb.Validator, 4*params.BeaconConfig().SlotsPerEpoch)
for i := 0; i < len(validators); i++ {
validators[i] = &ethpb.Validator{
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
}
}
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
Validators: validators,
Slot: params.BeaconConfig().SlotsPerEpoch,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
})
// Test for 2 epochs.
for epoch := uint64(0); epoch < 2; epoch++ {
state, _ := beaconstate.InitializeFromProto(state.CloneInnerState())
assignments, proposers, err := CommitteeAssignments(state, epoch)
if err != nil {
t.Fatal(err)
}
for i := uint64(0); int(i) < len(validators); i++ {
committee, committeeIndex, slot, proposerSlot, err := CommitteeAssignment(state, epoch, i)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(committee, assignments[i].Committee) {
t.Errorf("Computed different committees for validator %d", i)
}
if committeeIndex != assignments[i].CommitteeIndex {
t.Errorf("Computed different committee index for validator %d", i)
}
if slot != assignments[i].AttesterSlot {
t.Errorf("Computed different attesting slot for validator %d", i)
}
if proposerSlot != proposers[i] {
t.Errorf("Computed different proposing slot for validator %d", i)
}
}
}
}
func TestCommitteeAssignments_CanRetrieve(t *testing.T) {
// Initialize test with 256 validators, each slot and each index gets 4 validators.
validators := make([]*ethpb.Validator, 4*params.BeaconConfig().SlotsPerEpoch)
@@ -348,11 +207,14 @@ func TestCommitteeAssignments_CanRetrieve(t *testing.T) {
}
}
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{
Validators: validators,
Slot: 2 * params.BeaconConfig().SlotsPerEpoch, // epoch 2
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
})
if err != nil {
t.Fatal(err)
}
tests := []struct {
index uint64
@@ -395,7 +257,7 @@ func TestCommitteeAssignments_CanRetrieve(t *testing.T) {
for i, tt := range tests {
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
ClearCache()
validatorIndexToCommittee, proposerIndexToSlot, err := CommitteeAssignments(state, SlotToEpoch(tt.slot))
validatorIndexToCommittee, proposerIndexToSlots, err := CommitteeAssignments(state, SlotToEpoch(tt.slot))
if err != nil {
t.Fatalf("failed to determine CommitteeAssignments: %v", err)
}
@@ -408,9 +270,9 @@ func TestCommitteeAssignments_CanRetrieve(t *testing.T) {
t.Errorf("wanted slot %d, got slot %d for validator index %d",
tt.slot, cac.AttesterSlot, tt.index)
}
if proposerIndexToSlot[tt.index] != tt.proposerSlot {
if len(proposerIndexToSlots[tt.index]) > 0 && proposerIndexToSlots[tt.index][0] != tt.proposerSlot {
t.Errorf("wanted proposer slot %d, got proposer slot %d for validator index %d",
tt.proposerSlot, proposerIndexToSlot[tt.index], tt.index)
tt.proposerSlot, proposerIndexToSlots[tt.index][0], tt.index)
}
if !reflect.DeepEqual(cac.Committee, tt.committee) {
t.Errorf("wanted committee %v, got committee %v for validator index %d",
@@ -429,10 +291,13 @@ func TestVerifyAttestationBitfieldLengths_OK(t *testing.T) {
}
}
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{
Validators: validators,
RandaoMixes: activeRoots,
})
if err != nil {
t.Fatal(err)
}
tests := []struct {
attestation *ethpb.Attestation
@@ -506,7 +371,9 @@ func TestVerifyAttestationBitfieldLengths_OK(t *testing.T) {
for i, tt := range tests {
ClearCache()
state.SetSlot(tt.stateSlot)
if err := state.SetSlot(tt.stateSlot); err != nil {
t.Fatal(err)
}
err := VerifyAttestationBitfieldLengths(state, tt.attestation)
if tt.verificationFailure {
if err == nil {
@@ -655,10 +522,13 @@ func BenchmarkComputeCommittee3000000_WithPreCache(b *testing.B) {
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
}
}
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{
Validators: validators,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
})
if err != nil {
b.Fatal(err)
}
epoch := CurrentEpoch(state)
indices, err := ActiveValidatorIndices(state, epoch)
@@ -692,10 +562,13 @@ func BenchmarkComputeCommittee128000_WithOutPreCache(b *testing.B) {
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
}
}
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{
Validators: validators,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
})
if err != nil {
b.Fatal(err)
}
epoch := CurrentEpoch(state)
indices, err := ActiveValidatorIndices(state, epoch)
@@ -730,10 +603,13 @@ func BenchmarkComputeCommittee1000000_WithOutCache(b *testing.B) {
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
}
}
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{
Validators: validators,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
})
if err != nil {
b.Fatal(err)
}
epoch := CurrentEpoch(state)
indices, err := ActiveValidatorIndices(state, epoch)
@@ -768,10 +644,13 @@ func BenchmarkComputeCommittee4000000_WithOutCache(b *testing.B) {
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
}
}
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{
Validators: validators,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
})
if err != nil {
b.Fatal(err)
}
epoch := CurrentEpoch(state)
indices, err := ActiveValidatorIndices(state, epoch)
@@ -812,11 +691,14 @@ func TestBeaconCommitteeFromState_UpdateCacheForPreviousEpoch(t *testing.T) {
}
}
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{
Slot: params.BeaconConfig().SlotsPerEpoch,
Validators: validators,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
})
if err != nil {
t.Fatal(err)
}
if _, err := BeaconCommitteeFromState(state, 1 /* previous epoch */, 0); err != nil {
t.Fatal(err)
@@ -844,10 +726,13 @@ func TestPrecomputeProposerIndices_Ok(t *testing.T) {
}
}
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{
Validators: validators,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
})
if err != nil {
t.Fatal(err)
}
indices, err := ActiveValidatorIndices(state, 0)
if err != nil {

View File

@@ -18,7 +18,10 @@ func TestRandaoMix_OK(t *testing.T) {
binary.LittleEndian.PutUint64(intInBytes, uint64(i))
randaoMixes[i] = intInBytes
}
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{RandaoMixes: randaoMixes})
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{RandaoMixes: randaoMixes})
if err != nil {
t.Fatal(err)
}
tests := []struct {
epoch uint64
randaoMix []byte
@@ -37,7 +40,9 @@ func TestRandaoMix_OK(t *testing.T) {
},
}
for _, test := range tests {
state.SetSlot((test.epoch + 1) * params.BeaconConfig().SlotsPerEpoch)
if err := state.SetSlot((test.epoch + 1) * params.BeaconConfig().SlotsPerEpoch); err != nil {
t.Fatal(err)
}
mix, err := RandaoMix(state, test.epoch)
if err != nil {
t.Fatal(err)
@@ -56,7 +61,10 @@ func TestRandaoMix_CopyOK(t *testing.T) {
binary.LittleEndian.PutUint64(intInBytes, uint64(i))
randaoMixes[i] = intInBytes
}
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{RandaoMixes: randaoMixes})
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{RandaoMixes: randaoMixes})
if err != nil {
t.Fatal(err)
}
tests := []struct {
epoch uint64
randaoMix []byte
@@ -75,7 +83,9 @@ func TestRandaoMix_CopyOK(t *testing.T) {
},
}
for _, test := range tests {
state.SetSlot((test.epoch + 1) * params.BeaconConfig().SlotsPerEpoch)
if err := state.SetSlot((test.epoch + 1) * params.BeaconConfig().SlotsPerEpoch); err != nil {
t.Fatal(err)
}
mix, err := RandaoMix(state, test.epoch)
if err != nil {
t.Fatal(err)
@@ -101,9 +111,13 @@ func TestGenerateSeed_OK(t *testing.T) {
randaoMixes[i] = intInBytes
}
slot := 10 * params.BeaconConfig().MinSeedLookahead * params.BeaconConfig().SlotsPerEpoch
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{
RandaoMixes: randaoMixes,
Slot: slot})
Slot: slot,
})
if err != nil {
t.Fatal(err)
}
got, err := Seed(state, 10, params.BeaconConfig().DomainBeaconAttester)
if err != nil {

View File

@@ -2,6 +2,7 @@ package helpers
import (
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/shared/params"
)
// TotalBalance returns the total amount at stake in Gwei
@@ -10,9 +11,10 @@ import (
// Spec pseudocode definition:
// def get_total_balance(state: BeaconState, indices: Set[ValidatorIndex]) -> Gwei:
// """
// Return the combined effective balance of the ``indices``. (1 Gwei minimum to avoid divisions by zero.)
// Return the combined effective balance of the ``indices``.
// ``EFFECTIVE_BALANCE_INCREMENT`` Gwei minimum to avoid divisions by zero.
// """
// return Gwei(max(1, sum([state.validators[index].effective_balance for index in indices])))
// return Gwei(max(EFFECTIVE_BALANCE_INCREMENT, sum([state.validators[index].effective_balance for index in indices])))
func TotalBalance(state *stateTrie.BeaconState, indices []uint64) uint64 {
total := uint64(0)
@@ -24,9 +26,9 @@ func TotalBalance(state *stateTrie.BeaconState, indices []uint64) uint64 {
total += val.EffectiveBalance()
}
// Return 1 Gwei minimum to avoid divisions by zero
// Return EFFECTIVE_BALANCE_INCREMENT to avoid divisions by zero.
if total == 0 {
return 1
return params.BeaconConfig().EffectiveBalanceIncrement
}
return total
@@ -43,12 +45,14 @@ func TotalBalance(state *stateTrie.BeaconState, indices []uint64) uint64 {
// return get_total_balance(state, set(get_active_validator_indices(state, get_current_epoch(state))))
func TotalActiveBalance(state *stateTrie.BeaconState) (uint64, error) {
total := uint64(0)
state.ReadFromEveryValidator(func(idx int, val *stateTrie.ReadOnlyValidator) error {
if err := state.ReadFromEveryValidator(func(idx int, val *stateTrie.ReadOnlyValidator) error {
if IsActiveValidatorUsingTrie(val, SlotToEpoch(state.Slot())) {
total += val.EffectiveBalance()
}
return nil
})
}); err != nil {
return 0, err
}
return total, nil
}

View File

@@ -10,10 +10,13 @@ import (
)
func TestTotalBalance_OK(t *testing.T) {
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{Validators: []*ethpb.Validator{
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{Validators: []*ethpb.Validator{
{EffectiveBalance: 27 * 1e9}, {EffectiveBalance: 28 * 1e9},
{EffectiveBalance: 32 * 1e9}, {EffectiveBalance: 40 * 1e9},
}})
if err != nil {
t.Fatal(err)
}
balance := TotalBalance(state, []uint64{0, 1, 2, 3})
wanted := state.Validators()[0].EffectiveBalance + state.Validators()[1].EffectiveBalance +
@@ -24,11 +27,14 @@ func TestTotalBalance_OK(t *testing.T) {
}
}
func TestTotalBalance_ReturnsOne(t *testing.T) {
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{Validators: []*ethpb.Validator{}})
func TestTotalBalance_ReturnsEffectiveBalanceIncrement(t *testing.T) {
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{Validators: []*ethpb.Validator{}})
if err != nil {
t.Fatal(err)
}
balance := TotalBalance(state, []uint64{})
wanted := uint64(1)
wanted := params.BeaconConfig().EffectiveBalanceIncrement
if balance != wanted {
t.Errorf("Incorrect TotalBalance. Wanted: %d, got: %d", wanted, balance)
@@ -36,7 +42,7 @@ func TestTotalBalance_ReturnsOne(t *testing.T) {
}
func TestTotalActiveBalance_OK(t *testing.T) {
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{Validators: []*ethpb.Validator{
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{Validators: []*ethpb.Validator{
{
EffectiveBalance: 32 * 1e9,
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
@@ -54,6 +60,9 @@ func TestTotalActiveBalance_OK(t *testing.T) {
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
},
}})
if err != nil {
t.Fatal(err)
}
balance, err := TotalActiveBalance(state)
if err != nil {
@@ -79,7 +88,10 @@ func TestGetBalance_OK(t *testing.T) {
{i: 2, b: []uint64{0, 0, 0}},
}
for _, test := range tests {
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{Balances: test.b})
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{Balances: test.b})
if err != nil {
t.Fatal(err)
}
if state.Balances()[test.i] != test.b[test.i] {
t.Errorf("Incorrect Validator balance. Wanted: %d, got: %d", test.b[test.i], state.Balances()[test.i])
}
@@ -98,11 +110,14 @@ func TestIncreaseBalance_OK(t *testing.T) {
{i: 2, b: []uint64{27 * 1e9, 28 * 1e9, 32 * 1e9}, nb: 33 * 1e9, eb: 65 * 1e9},
}
for _, test := range tests {
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{
Validators: []*ethpb.Validator{
{EffectiveBalance: 4}, {EffectiveBalance: 4}, {EffectiveBalance: 4}},
Balances: test.b,
})
if err != nil {
t.Fatal(err)
}
if err := IncreaseBalance(state, test.i, test.nb); err != nil {
t.Fatal(err)
}
@@ -125,11 +140,14 @@ func TestDecreaseBalance_OK(t *testing.T) {
{i: 3, b: []uint64{27 * 1e9, 28 * 1e9, 1, 28 * 1e9}, nb: 28 * 1e9, eb: 0},
}
for _, test := range tests {
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{
Validators: []*ethpb.Validator{
{EffectiveBalance: 4}, {EffectiveBalance: 4}, {EffectiveBalance: 4}, {EffectiveBalance: 3}},
Balances: test.b,
})
if err != nil {
t.Fatal(err)
}
if err := DecreaseBalance(state, test.i, test.nb); err != nil {
t.Fatal(err)
}

View File

@@ -101,7 +101,9 @@ func BenchmarkShuffledIndex(b *testing.B) {
for _, listSize := range listSizes {
b.Run(fmt.Sprintf("ShuffledIndex_%d", listSize), func(ib *testing.B) {
for i := uint64(0); i < uint64(ib.N); i++ {
ShuffledIndex(i%listSize, listSize, seed)
if _, err := ShuffledIndex(i%listSize, listSize, seed); err != nil {
b.Error(err)
}
}
})
}
@@ -115,7 +117,9 @@ func BenchmarkIndexComparison(b *testing.B) {
for i := 0; i < ib.N; i++ {
// Simulate a list-shuffle by running shuffle-index listSize times.
for j := uint64(0); j < listSize; j++ {
ShuffledIndex(j, listSize, seed)
if _, err := ShuffledIndex(j, listSize, seed); err != nil {
b.Error(err)
}
}
}
})
@@ -132,7 +136,9 @@ func BenchmarkShuffleList(b *testing.B) {
}
b.Run(fmt.Sprintf("ShuffleList_%d", listSize), func(ib *testing.B) {
for i := 0; i < ib.N; i++ {
ShuffleList(testIndices, seed)
if _, err := ShuffleList(testIndices, seed); err != nil {
b.Error(err)
}
}
})
}

View File

@@ -0,0 +1,146 @@
package helpers
import (
"github.com/pkg/errors"
"github.com/prysmaticlabs/go-ssz"
p2ppb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
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/params"
)
// ForkVersionByteLength length of fork version byte array.
const ForkVersionByteLength = 4
// DomainByteLength length of domain byte array.
const DomainByteLength = 4
// ErrSigFailedToVerify returns when a signature of a block object(ie attestation, slashing, exit... etc)
// failed to verify.
var ErrSigFailedToVerify = errors.New("signature did not verify")
// ComputeSigningRoot computes the root of the object by calculating the root of the object domain tree.
//
// Spec pseudocode definition:
// def compute_signing_root(ssz_object: SSZObject, domain: Domain) -> Root:
// """
// Return the signing root of an object by calculating the root of the object-domain tree.
// """
// domain_wrapped_object = SigningRoot(
// object_root=hash_tree_root(ssz_object),
// domain=domain,
// )
// return hash_tree_root(domain_wrapped_object)
func ComputeSigningRoot(object interface{}, domain []byte) ([32]byte, error) {
objRoot, err := ssz.HashTreeRoot(object)
if err != nil {
return [32]byte{}, err
}
container := &p2ppb.SigningRoot{
ObjectRoot: objRoot[:],
Domain: domain,
}
return ssz.HashTreeRoot(container)
}
// VerifySigningRoot verifies the signing root of an object given it's public key, signature and domain.
func VerifySigningRoot(obj interface{}, pub []byte, signature []byte, domain []byte) error {
publicKey, err := bls.PublicKeyFromBytes(pub)
if err != nil {
return errors.Wrap(err, "could not convert bytes to public key")
}
sig, err := bls.SignatureFromBytes(signature)
if err != nil {
return errors.Wrap(err, "could not convert bytes to signature")
}
root, err := ComputeSigningRoot(obj, domain)
if err != nil {
return errors.Wrap(err, "could not compute signing root")
}
if !sig.Verify(root[:], publicKey) {
return ErrSigFailedToVerify
}
return nil
}
// ComputeDomain returns the domain version for BLS private key to sign and verify with a zeroed 4-byte
// array as the fork version.
//
// def compute_domain(domain_type: DomainType, fork_version: Version=None, genesis_validators_root: Root=None) -> Domain:
// """
// Return the domain for the ``domain_type`` and ``fork_version``.
// """
// if fork_version is None:
// fork_version = GENESIS_FORK_VERSION
// if genesis_validators_root is None:
// genesis_validators_root = Root() # all bytes zero by default
// fork_data_root = compute_fork_data_root(fork_version, genesis_validators_root)
// return Domain(domain_type + fork_data_root[:28])
func ComputeDomain(domainType [DomainByteLength]byte, forkVersion []byte, genesisValidatorsRoot []byte) ([]byte, error) {
if forkVersion == nil {
forkVersion = params.BeaconConfig().GenesisForkVersion
}
if genesisValidatorsRoot == nil {
genesisValidatorsRoot = params.BeaconConfig().ZeroHash[:]
}
forkBytes := [ForkVersionByteLength]byte{}
copy(forkBytes[:], forkVersion)
forkDataRoot, err := computeForkDataRoot(forkBytes[:], genesisValidatorsRoot)
if err != nil {
return nil, err
}
return domain(domainType, forkDataRoot[:]), nil
}
// This returns the bls domain given by the domain type and fork data root.
func domain(domainType [DomainByteLength]byte, forkDataRoot []byte) []byte {
b := []byte{}
b = append(b, domainType[:4]...)
b = append(b, forkDataRoot[:28]...)
return b
}
// this returns the 32byte fork data root for the ``current_version`` and ``genesis_validators_root``.
// This is used primarily in signature domains to avoid collisions across forks/chains.
//
// Spec pseudocode definition:
// def compute_fork_data_root(current_version: Version, genesis_validators_root: Root) -> Root:
// """
// Return the 32-byte fork data root for the ``current_version`` and ``genesis_validators_root``.
// This is used primarily in signature domains to avoid collisions across forks/chains.
// """
// return hash_tree_root(ForkData(
// current_version=current_version,
// genesis_validators_root=genesis_validators_root,
// ))
func computeForkDataRoot(version []byte, root []byte) ([32]byte, error) {
r, err := ssz.HashTreeRoot(&pb.ForkData{
CurrentVersion: version,
GenesisValidatorsRoot: root,
})
if err != nil {
return [32]byte{}, err
}
return r, nil
}
// ComputeForkDigest returns the fork for the current version and genesis validator root
//
// Spec pseudocode definition:
// def compute_fork_digest(current_version: Version, genesis_validators_root: Root) -> ForkDigest:
// """
// Return the 4-byte fork digest for the ``current_version`` and ``genesis_validators_root``.
// This is a digest primarily used for domain separation on the p2p layer.
// 4-bytes suffices for practical separation of forks/chains.
// """
// return ForkDigest(compute_fork_data_root(current_version, genesis_validators_root)[:4])
func ComputeForkDigest(version []byte, genesisValidatorsRoot []byte) ([4]byte, error) {
dataRoot, err := computeForkDataRoot(version, genesisValidatorsRoot)
if err != nil {
return [4]byte{}, nil
}
return bytesutil.ToBytes4(dataRoot[:]), nil
}

View File

@@ -0,0 +1,86 @@
package helpers
import (
"bytes"
"testing"
fuzz "github.com/google/gofuzz"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
ethereum_beacon_p2p_v1 "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/params"
)
func TestSigningRoot_ComputeOK(t *testing.T) {
emptyBlock := &ethpb.BeaconBlock{}
_, err := ComputeSigningRoot(emptyBlock, []byte{'T', 'E', 'S', 'T'})
if err != nil {
t.Errorf("Could not compute signing root of block: %v", err)
}
}
func TestComputeDomain_OK(t *testing.T) {
tests := []struct {
epoch uint64
domainType [4]byte
domain []byte
}{
{epoch: 1, domainType: [4]byte{4, 0, 0, 0}, domain: []byte{4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
{epoch: 2, domainType: [4]byte{4, 0, 0, 0}, domain: []byte{4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
{epoch: 2, domainType: [4]byte{5, 0, 0, 0}, domain: []byte{5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
{epoch: 3, domainType: [4]byte{4, 0, 0, 0}, domain: []byte{4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
{epoch: 3, domainType: [4]byte{5, 0, 0, 0}, domain: []byte{5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
}
for _, tt := range tests {
if !bytes.Equal(domain(tt.domainType, params.BeaconConfig().ZeroHash[:]), tt.domain) {
t.Errorf("wanted domain version: %d, got: %d", tt.domain, domain(tt.domainType, params.BeaconConfig().ZeroHash[:]))
}
}
}
func TestComputeForkDigest_OK(t *testing.T) {
tests := []struct {
version []byte
root [32]byte
result [4]byte
}{
{version: []byte{'A', 'B', 'C', 'D'}, root: [32]byte{'i', 'o', 'p'}, result: [4]byte{0x69, 0x5c, 0x26, 0x47}},
{version: []byte{'i', 'm', 'n', 'a'}, root: [32]byte{'z', 'a', 'b'}, result: [4]byte{0x1c, 0x38, 0x84, 0x58}},
{version: []byte{'b', 'w', 'r', 't'}, root: [32]byte{'r', 'd', 'c'}, result: [4]byte{0x83, 0x34, 0x38, 0x88}},
}
for _, tt := range tests {
digest, err := ComputeForkDigest(tt.version, tt.root[:])
if err != nil {
t.Error(err)
}
if digest != tt.result {
t.Errorf("wanted domain version: %#x, got: %#x", digest, tt.result)
}
}
}
func TestFuzzverifySigningRoot_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &ethereum_beacon_p2p_v1.BeaconState{}
pubkey := [48]byte{}
sig := [96]byte{}
domain := [4]byte{}
p := []byte{}
s := []byte{}
d := []byte{}
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(&pubkey)
fuzzer.Fuzz(&sig)
fuzzer.Fuzz(&domain)
fuzzer.Fuzz(state)
fuzzer.Fuzz(&p)
fuzzer.Fuzz(&s)
fuzzer.Fuzz(&d)
if err := VerifySigningRoot(state, pubkey[:], sig[:], domain[:]); err != nil {
t.Log(err)
}
if err := VerifySigningRoot(state, p, s, d); err != nil {
t.Log(err)
}
}
}

View File

@@ -89,15 +89,17 @@ func SlotsSinceEpochStarts(slot uint64) uint64 {
return slot - StartSlot(SlotToEpoch(slot))
}
// Allow for slots "from the future" within a certain tolerance.
const timeShiftTolerance = 10 // ms
// TimeShiftTolerance specifies the tolerance threshold for slots "from the future".
const TimeShiftTolerance = 500 * time.Millisecond // ms
// VerifySlotTime validates the input slot is not from the future.
func VerifySlotTime(genesisTime uint64, slot uint64) error {
slotTime := genesisTime + slot*params.BeaconConfig().SecondsPerSlot
currentTime := uint64(roughtime.Now().Unix())
if slotTime > currentTime+timeShiftTolerance {
return fmt.Errorf("could not process slot from the future, slot time %d > current time %d", slotTime, currentTime)
func VerifySlotTime(genesisTime uint64, slot uint64, timeTolerance time.Duration) error {
// denominate everything in milliseconds
slotTime := 1000 * (genesisTime + slot*params.BeaconConfig().SecondsPerSlot)
currentTime := 1000 * uint64(roughtime.Now().Unix())
tolerance := uint64(timeTolerance.Milliseconds())
if slotTime > currentTime+tolerance {
return fmt.Errorf("could not process slot from the future, slot time(ms) %d > current time(ms) %d", slotTime, currentTime)
}
return nil
}

View File

@@ -38,7 +38,10 @@ func TestCurrentEpoch_OK(t *testing.T) {
{slot: 200, epoch: 6},
}
for _, tt := range tests {
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{Slot: tt.slot})
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{Slot: tt.slot})
if err != nil {
t.Fatal(err)
}
if tt.epoch != CurrentEpoch(state) {
t.Errorf("CurrentEpoch(%d) = %d, wanted: %d", state.Slot(), CurrentEpoch(state), tt.epoch)
}
@@ -55,7 +58,10 @@ func TestPrevEpoch_OK(t *testing.T) {
{slot: 2 * params.BeaconConfig().SlotsPerEpoch, epoch: 1},
}
for _, tt := range tests {
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{Slot: tt.slot})
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{Slot: tt.slot})
if err != nil {
t.Fatal(err)
}
if tt.epoch != PrevEpoch(state) {
t.Errorf("PrevEpoch(%d) = %d, wanted: %d", state.Slot(), PrevEpoch(state), tt.epoch)
}
@@ -74,7 +80,10 @@ func TestNextEpoch_OK(t *testing.T) {
{slot: 200, epoch: 200/params.BeaconConfig().SlotsPerEpoch + 1},
}
for _, tt := range tests {
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{Slot: tt.slot})
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{Slot: tt.slot})
if err != nil {
t.Fatal(err)
}
if tt.epoch != NextEpoch(state) {
t.Errorf("NextEpoch(%d) = %d, wanted: %d", state.Slot(), NextEpoch(state), tt.epoch)
}

View File

@@ -74,12 +74,14 @@ func ActiveValidatorIndices(state *stateTrie.BeaconState, epoch uint64) ([]uint6
return activeIndices, nil
}
var indices []uint64
state.ReadFromEveryValidator(func(idx int, val *stateTrie.ReadOnlyValidator) error {
if err := state.ReadFromEveryValidator(func(idx int, val *stateTrie.ReadOnlyValidator) error {
if IsActiveValidatorUsingTrie(val, epoch) {
indices = append(indices, uint64(idx))
}
return nil
})
}); err != nil {
return nil, err
}
if err := UpdateCommitteeCache(state, epoch); err != nil {
return nil, errors.Wrap(err, "could not update committee cache")
@@ -92,12 +94,14 @@ func ActiveValidatorIndices(state *stateTrie.BeaconState, epoch uint64) ([]uint6
// at the given epoch.
func ActiveValidatorCount(state *stateTrie.BeaconState, epoch uint64) (uint64, error) {
count := uint64(0)
state.ReadFromEveryValidator(func(idx int, val *stateTrie.ReadOnlyValidator) error {
if err := state.ReadFromEveryValidator(func(idx int, val *stateTrie.ReadOnlyValidator) error {
if IsActiveValidatorUsingTrie(val, epoch) {
count++
}
return nil
})
}); err != nil {
return 0, err
}
return count, nil
}
@@ -231,18 +235,16 @@ func ComputeProposerIndex(validators []*ethpb.Validator, activeIndices []uint64,
// Domain returns the domain version for BLS private key to sign and verify.
//
// Spec pseudocode definition:
// def get_domain(state: BeaconState,
// domain_type: int,
// message_epoch: Epoch=None) -> int:
// def get_domain(state: BeaconState, domain_type: DomainType, epoch: Epoch=None) -> Domain:
// """
// Return the signature domain (fork version concatenated with domain type) of a message.
// """
// epoch = get_current_epoch(state) if message_epoch is None else message_epoch
// epoch = get_current_epoch(state) if epoch is None else epoch
// fork_version = state.fork.previous_version if epoch < state.fork.epoch else state.fork.current_version
// return bls_domain(domain_type, fork_version)
func Domain(fork *pb.Fork, epoch uint64, domainType [bls.DomainByteLength]byte) (uint64, error) {
// return compute_domain(domain_type, fork_version, state.genesis_validators_root)
func Domain(fork *pb.Fork, epoch uint64, domainType [bls.DomainByteLength]byte, genesisRoot []byte) ([]byte, error) {
if fork == nil {
return 0, errors.New("nil fork or domain type")
return []byte{}, errors.New("nil fork or domain type")
}
var forkVersion []byte
if epoch < fork.Epoch {
@@ -251,11 +253,11 @@ func Domain(fork *pb.Fork, epoch uint64, domainType [bls.DomainByteLength]byte)
forkVersion = fork.CurrentVersion
}
if len(forkVersion) != 4 {
return 0, errors.New("fork version length is not 4 byte")
return []byte{}, errors.New("fork version length is not 4 byte")
}
var forkVersionArray [4]byte
copy(forkVersionArray[:], forkVersion[:4])
return bls.Domain(domainType, forkVersionArray), nil
return ComputeDomain(domainType, forkVersionArray[:], genesisRoot)
}
// IsEligibleForActivationQueue checks if the validator is eligible to

View File

@@ -1,6 +1,7 @@
package helpers
import (
"bytes"
"reflect"
"testing"
@@ -128,11 +129,14 @@ func TestBeaconProposerIndex_OK(t *testing.T) {
}
}
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{
Validators: validators,
Slot: 0,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
})
if err != nil {
t.Fatal(err)
}
tests := []struct {
slot uint64
@@ -162,7 +166,9 @@ func TestBeaconProposerIndex_OK(t *testing.T) {
for _, tt := range tests {
ClearCache()
state.SetSlot(tt.slot)
if err := state.SetSlot(tt.slot); err != nil {
t.Fatal(err)
}
result, err := BeaconProposerIndex(state)
if err != nil {
t.Errorf("Failed to get shard and committees at slot: %v", err)
@@ -205,11 +211,14 @@ func TestChurnLimit_OK(t *testing.T) {
}
}
beaconState, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
beaconState, err := beaconstate.InitializeFromProto(&pb.BeaconState{
Slot: 1,
Validators: validators,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
})
if err != nil {
t.Fatal(err)
}
validatorCount, err := ActiveValidatorCount(beaconState, CurrentEpoch(beaconState))
if err != nil {
t.Fatal(err)
@@ -235,22 +244,22 @@ func TestDomain_OK(t *testing.T) {
}
tests := []struct {
epoch uint64
domainType uint64
version uint64
domainType [4]byte
result []byte
}{
{epoch: 1, domainType: 4, version: 144115188075855876},
{epoch: 2, domainType: 4, version: 144115188075855876},
{epoch: 2, domainType: 5, version: 144115188075855877},
{epoch: 3, domainType: 4, version: 216172782113783812},
{epoch: 3, domainType: 5, version: 216172782113783813},
{epoch: 1, domainType: bytesutil.ToBytes4(bytesutil.Bytes4(4)), result: bytesutil.ToBytes(947067381421703172, 32)},
{epoch: 2, domainType: bytesutil.ToBytes4(bytesutil.Bytes4(4)), result: bytesutil.ToBytes(947067381421703172, 32)},
{epoch: 2, domainType: bytesutil.ToBytes4(bytesutil.Bytes4(5)), result: bytesutil.ToBytes(947067381421703173, 32)},
{epoch: 3, domainType: bytesutil.ToBytes4(bytesutil.Bytes4(4)), result: bytesutil.ToBytes(9369798235163459588, 32)},
{epoch: 3, domainType: bytesutil.ToBytes4(bytesutil.Bytes4(5)), result: bytesutil.ToBytes(9369798235163459589, 32)},
}
for _, tt := range tests {
domain, err := Domain(state.Fork, tt.epoch, bytesutil.ToBytes4(bytesutil.Bytes4(tt.domainType)))
domain, err := Domain(state.Fork, tt.epoch, tt.domainType, nil)
if err != nil {
t.Fatal(err)
}
if domain != tt.version {
t.Errorf("wanted domain version: %d, got: %d", tt.version, domain)
if !bytes.Equal(domain[:8], tt.result[:8]) {
t.Errorf("wanted domain version: %d, got: %d", tt.result, domain)
}
}
}
@@ -404,7 +413,10 @@ func TestActiveValidatorIndices(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s, _ := beaconstate.InitializeFromProto(tt.args.state)
s, err := beaconstate.InitializeFromProto(tt.args.state)
if err != nil {
t.Fatal(err)
}
got, err := ActiveValidatorIndices(s, tt.args.epoch)
if (err != nil) != tt.wantErr {
t.Errorf("ActiveValidatorIndices() error = %v, wantErr %v", err, tt.wantErr)
@@ -588,7 +600,10 @@ func TestIsIsEligibleForActivation(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s, _ := beaconstate.InitializeFromProto(tt.state)
s, err := beaconstate.InitializeFromProto(tt.state)
if err != nil {
t.Fatal(err)
}
if got := IsEligibleForActivation(s, tt.validator); got != tt.want {
t.Errorf("IsEligibleForActivation() = %v, want %v", got, tt.want)
}

View File

@@ -16,6 +16,7 @@ go_library(
"//shared/testutil:__pkg__",
"//tools/benchmark-files-gen:__pkg__",
"//tools/genesis-state-gen:__pkg__",
"//endtoend:__pkg__",
],
deps = [
"//beacon-chain/cache:go_default_library",
@@ -34,6 +35,7 @@ go_library(
"@com_github_pkg_errors//:go_default_library",
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@io_opencensus_go//trace:go_default_library",
],
)
@@ -55,10 +57,10 @@ go_test(
"//beacon-chain/core/blocks:go_default_library",
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/stateutil:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//shared/attestationutil:go_default_library",
"//shared/bls:go_default_library",
"//shared/featureconfig:go_default_library",
"//shared/hashutil:go_default_library",
"//shared/params:go_default_library",
"//shared/testutil:go_default_library",

View File

@@ -27,9 +27,14 @@ func TestBenchmarkExecuteStateTransition(t *testing.T) {
t.Fatal(err)
}
if _, err := state.ExecuteStateTransition(context.Background(), beaconState, block); err != nil {
oldSlot := beaconState.Slot()
beaconState, err = state.ExecuteStateTransition(context.Background(), beaconState, block)
if err != nil {
t.Fatalf("failed to process block, benchmarks will fail: %v", err)
}
if oldSlot == beaconState.Slot() {
t.Fatal("Expected slots to be different")
}
}
func BenchmarkExecuteStateTransition_FullBlock(b *testing.B) {
@@ -69,11 +74,15 @@ func BenchmarkExecuteStateTransition_WithCache(b *testing.B) {
// We have to reset slot back to last epoch to hydrate cache. Since
// some attestations in block are from previous epoch
currentSlot := beaconState.Slot()
beaconState.SetSlot(beaconState.Slot() - params.BeaconConfig().SlotsPerEpoch)
if err := beaconState.SetSlot(beaconState.Slot() - params.BeaconConfig().SlotsPerEpoch); err != nil {
b.Fatal(err)
}
if err := helpers.UpdateCommitteeCache(beaconState, helpers.CurrentEpoch(beaconState)); err != nil {
b.Fatal(err)
}
beaconState.SetSlot(currentSlot)
if err := beaconState.SetSlot(currentSlot); err != nil {
b.Fatal(err)
}
// Run the state transition once to populate the cache.
if _, err := state.ExecuteStateTransition(context.Background(), beaconState, block); err != nil {
b.Fatalf("failed to process block, benchmarks will fail: %v", err)
@@ -98,11 +107,15 @@ func BenchmarkProcessEpoch_2FullEpochs(b *testing.B) {
// We have to reset slot back to last epoch to hydrate cache. Since
// some attestations in block are from previous epoch
currentSlot := beaconState.Slot()
beaconState.SetSlot(beaconState.Slot() - params.BeaconConfig().SlotsPerEpoch)
if err := beaconState.SetSlot(beaconState.Slot() - params.BeaconConfig().SlotsPerEpoch); err != nil {
b.Fatal(err)
}
if err := helpers.UpdateCommitteeCache(beaconState, helpers.CurrentEpoch(beaconState)); err != nil {
b.Fatal(err)
}
beaconState.SetSlot(currentSlot)
if err := beaconState.SetSlot(currentSlot); err != nil {
b.Fatal(err)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {

View File

@@ -4,8 +4,8 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
)
// skipSlotCache exists for the unlikely scenario that is a large gap between the head state and
// SkipSlotCache exists for the unlikely scenario that is a large gap between the head state and
// the current slot. If the beacon chain were ever to be stalled for several epochs, it may be
// difficult or impossible to compute the appropriate beacon state for assignments within a
// reasonable amount of time.
var skipSlotCache = cache.NewSkipSlotCache()
var SkipSlotCache = cache.NewSkipSlotCache()

View File

@@ -7,26 +7,22 @@ import (
"github.com/prysmaticlabs/go-ssz"
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/shared/featureconfig"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
)
func TestSkipSlotCache_OK(t *testing.T) {
state.SkipSlotCache.Enable()
defer state.SkipSlotCache.Disable()
bState, privs := testutil.DeterministicGenesisState(t, params.MinimalSpecConfig().MinGenesisActiveValidatorCount)
originalState, _ := beaconstate.InitializeFromProto(bState.CloneInnerState())
originalState, err := beaconstate.InitializeFromProto(bState.CloneInnerState())
if err != nil {
t.Fatal(err)
}
blkCfg := testutil.DefaultBlockGenConfig()
blkCfg.NumAttestations = 1
cfg := featureconfig.Get()
cfg.EnableSkipSlotsCache = true
featureconfig.Init(cfg)
defer func() {
cfg.EnableSkipSlotsCache = false
featureconfig.Init(cfg)
}()
// First transition will be with an empty cache, so the cache becomes populated
// with the state
blk, err := testutil.GenerateFullBlock(bState, privs, blkCfg, originalState.Slot()+10)

View File

@@ -15,6 +15,10 @@ import (
"gopkg.in/d4l3k/messagediff.v1"
)
func init() {
state.SkipSlotCache.Disable()
}
func runSlotProcessingTests(t *testing.T, config string) {
if err := spectest.SetConfig(config); err != nil {
t.Fatal(err)

View File

@@ -12,6 +12,7 @@ import (
"github.com/prysmaticlabs/go-ssz"
b "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
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/params"
"github.com/prysmaticlabs/prysm/shared/trieutil"
@@ -137,10 +138,16 @@ func OptimizedGenesisBeaconState(genesisTime uint64, preState *stateTrie.BeaconS
slashings := make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector)
genesisValidatorsRoot, err := stateutil.ValidatorRegistryRoot(preState.Validators())
if err != nil {
return nil, errors.Wrapf(err, "could not hash tree root genesis validators %v", err)
}
state := &pb.BeaconState{
// Misc fields.
Slot: 0,
GenesisTime: genesisTime,
Slot: 0,
GenesisTime: genesisTime,
GenesisValidatorsRoot: genesisValidatorsRoot[:],
Fork: &pb.Fork{
PreviousVersion: params.BeaconConfig().GenesisForkVersion,

View File

@@ -9,6 +9,8 @@ import (
)
func TestGenesisBeaconState_1000(t *testing.T) {
SkipSlotCache.Disable()
defer SkipSlotCache.Enable()
fuzzer := fuzz.NewWithSeed(0)
fuzzer.NilChance(0.1)
deposits := make([]*ethpb.Deposit, 300000)
@@ -29,6 +31,8 @@ func TestGenesisBeaconState_1000(t *testing.T) {
}
func TestOptimizedGenesisBeaconState_1000(t *testing.T) {
SkipSlotCache.Disable()
defer SkipSlotCache.Enable()
fuzzer := fuzz.NewWithSeed(0)
fuzzer.NilChance(0.1)
var genesisTime uint64
@@ -49,6 +53,8 @@ func TestOptimizedGenesisBeaconState_1000(t *testing.T) {
}
func TestIsValidGenesisState_100000(t *testing.T) {
SkipSlotCache.Disable()
defer SkipSlotCache.Enable()
fuzzer := fuzz.NewWithSeed(0)
fuzzer.NilChance(0.1)
var chainStartDepositCount, currentTime uint64

View File

@@ -42,7 +42,10 @@ func TestGenesisBeaconState_OK(t *testing.T) {
}
genesisTime := uint64(99999)
deposits, _, _ := testutil.DeterministicDepositsAndKeys(uint64(depositsForChainStart))
deposits, _, err := testutil.DeterministicDepositsAndKeys(uint64(depositsForChainStart))
if err != nil {
t.Fatal(err)
}
eth1Data, err := testutil.DeterministicEth1Data(len(deposits))
if err != nil {
t.Fatal(err)
@@ -68,10 +71,18 @@ func TestGenesisBeaconState_OK(t *testing.T) {
if len(newState.Validators()) != depositsForChainStart {
t.Error("Validators was not correctly initialized")
}
if v, _ := newState.ValidatorAtIndex(0); v.ActivationEpoch != 0 {
v, err := newState.ValidatorAtIndex(0)
if err != nil {
t.Fatal(err)
}
if v.ActivationEpoch != 0 {
t.Error("Validators was not correctly initialized")
}
if v, _ := newState.ValidatorAtIndex(0); v.ActivationEligibilityEpoch != 0 {
v, err = newState.ValidatorAtIndex(0)
if err != nil {
t.Fatal(err)
}
if v.ActivationEligibilityEpoch != 0 {
t.Error("Validators was not correctly initialized")
}
if len(newState.Balances()) != depositsForChainStart {
@@ -82,7 +93,11 @@ func TestGenesisBeaconState_OK(t *testing.T) {
if len(newState.RandaoMixes()) != latestRandaoMixesLength {
t.Error("Length of RandaoMixes was not correctly initialized")
}
if mix, _ := newState.RandaoMixAtIndex(0); !bytes.Equal(mix, eth1Data.BlockHash) {
mix, err := newState.RandaoMixAtIndex(0)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(mix, eth1Data.BlockHash) {
t.Error("RandaoMixes was not correctly initialized")
}
@@ -130,7 +145,10 @@ func TestGenesisBeaconState_OK(t *testing.T) {
}
func TestGenesisState_HashEquality(t *testing.T) {
deposits, _, _ := testutil.DeterministicDepositsAndKeys(100)
deposits, _, err := testutil.DeterministicDepositsAndKeys(100)
if err != nil {
t.Fatal(err)
}
state1, err := state.GenesisBeaconState(deposits, 0, &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Error(err)

View File

@@ -21,6 +21,7 @@ import (
"github.com/prysmaticlabs/prysm/shared/mathutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/traceutil"
"github.com/sirupsen/logrus"
"go.opencensus.io/trace"
)
@@ -274,7 +275,7 @@ func ProcessSlots(ctx context.Context, state *stateTrie.BeaconState, slot uint64
key := state.Slot()
// Restart from cached value, if one exists.
cachedState, err := skipSlotCache.Get(ctx, key)
cachedState, err := SkipSlotCache.Get(ctx, key)
if err != nil {
return nil, err
}
@@ -283,8 +284,8 @@ func ProcessSlots(ctx context.Context, state *stateTrie.BeaconState, slot uint64
highestSlot = cachedState.Slot()
state = cachedState
}
if err := skipSlotCache.MarkInProgress(key); err == cache.ErrAlreadyInProgress {
cachedState, err = skipSlotCache.Get(ctx, key)
if err := SkipSlotCache.MarkInProgress(key); err == cache.ErrAlreadyInProgress {
cachedState, err = SkipSlotCache.Get(ctx, key)
if err != nil {
return nil, err
}
@@ -295,14 +296,21 @@ func ProcessSlots(ctx context.Context, state *stateTrie.BeaconState, slot uint64
} else if err != nil {
return nil, err
}
defer skipSlotCache.MarkNotInProgress(key)
defer func() {
if err := SkipSlotCache.MarkNotInProgress(key); err != nil {
traceutil.AnnotateError(span, err)
logrus.WithError(err).Error("Failed to mark skip slot no longer in progress")
}
}()
for state.Slot() < slot {
if ctx.Err() != nil {
traceutil.AnnotateError(span, ctx.Err())
// Cache last best value.
if highestSlot < state.Slot() {
skipSlotCache.Put(ctx, key, state)
if err := SkipSlotCache.Put(ctx, key, state); err != nil {
logrus.WithError(err).Error("Failed to put skip slot cache value")
}
}
return nil, ctx.Err()
}
@@ -318,11 +326,17 @@ func ProcessSlots(ctx context.Context, state *stateTrie.BeaconState, slot uint64
return nil, errors.Wrap(err, "could not process epoch with optimizations")
}
}
state.SetSlot(state.Slot() + 1)
if err := state.SetSlot(state.Slot() + 1); err != nil {
traceutil.AnnotateError(span, err)
return nil, errors.Wrap(err, "failed to increment state slot")
}
}
if highestSlot < state.Slot() {
skipSlotCache.Put(ctx, key, state)
if err := SkipSlotCache.Put(ctx, key, state); err != nil {
logrus.WithError(err).Error("Failed to put skip slot cache value")
traceutil.AnnotateError(span, err)
}
}
return state, nil
@@ -605,8 +619,11 @@ func ProcessEpochPrecompute(ctx context.Context, state *stateTrie.BeaconState) (
if state == nil {
return nil, errors.New("nil state")
}
vp, bp := precompute.New(ctx, state)
vp, bp, err := precompute.ProcessAttestations(ctx, state, vp, bp)
vp, bp, err := precompute.New(ctx, state)
if err != nil {
return nil, err
}
vp, bp, err = precompute.ProcessAttestations(ctx, state, vp, bp)
if err != nil {
return nil, err
}

View File

@@ -10,6 +10,8 @@ import (
)
func TestFuzzExecuteStateTransition_1000(t *testing.T) {
SkipSlotCache.Disable()
defer SkipSlotCache.Enable()
ctx := context.Background()
state := &stateTrie.BeaconState{}
sb := &ethpb.SignedBeaconBlock{}
@@ -26,6 +28,8 @@ func TestFuzzExecuteStateTransition_1000(t *testing.T) {
}
func TestFuzzExecuteStateTransitionNoVerifyAttSigs_1000(t *testing.T) {
SkipSlotCache.Disable()
defer SkipSlotCache.Enable()
ctx := context.Background()
state := &stateTrie.BeaconState{}
sb := &ethpb.SignedBeaconBlock{}
@@ -42,6 +46,8 @@ func TestFuzzExecuteStateTransitionNoVerifyAttSigs_1000(t *testing.T) {
}
func TestFuzzCalculateStateRoot_1000(t *testing.T) {
SkipSlotCache.Disable()
defer SkipSlotCache.Enable()
ctx := context.Background()
state := &stateTrie.BeaconState{}
sb := &ethpb.SignedBeaconBlock{}
@@ -58,6 +64,8 @@ func TestFuzzCalculateStateRoot_1000(t *testing.T) {
}
func TestFuzzProcessSlot_1000(t *testing.T) {
SkipSlotCache.Disable()
defer SkipSlotCache.Enable()
ctx := context.Background()
state := &stateTrie.BeaconState{}
fuzzer := fuzz.NewWithSeed(0)
@@ -72,6 +80,8 @@ func TestFuzzProcessSlot_1000(t *testing.T) {
}
func TestFuzzProcessSlots_1000(t *testing.T) {
SkipSlotCache.Disable()
defer SkipSlotCache.Enable()
ctx := context.Background()
state := &stateTrie.BeaconState{}
slot := uint64(0)
@@ -88,6 +98,8 @@ func TestFuzzProcessSlots_1000(t *testing.T) {
}
func TestFuzzProcessBlock_1000(t *testing.T) {
SkipSlotCache.Disable()
defer SkipSlotCache.Enable()
ctx := context.Background()
state := &stateTrie.BeaconState{}
sb := &ethpb.SignedBeaconBlock{}
@@ -104,6 +116,8 @@ func TestFuzzProcessBlock_1000(t *testing.T) {
}
func TestFuzzProcessBlockNoVerifyAttSigs_1000(t *testing.T) {
SkipSlotCache.Disable()
defer SkipSlotCache.Enable()
ctx := context.Background()
state := &stateTrie.BeaconState{}
sb := &ethpb.SignedBeaconBlock{}
@@ -120,6 +134,8 @@ func TestFuzzProcessBlockNoVerifyAttSigs_1000(t *testing.T) {
}
func TestFuzzProcessOperations_1000(t *testing.T) {
SkipSlotCache.Disable()
defer SkipSlotCache.Enable()
ctx := context.Background()
state := &stateTrie.BeaconState{}
bb := &ethpb.BeaconBlockBody{}
@@ -136,6 +152,8 @@ func TestFuzzProcessOperations_1000(t *testing.T) {
}
func TestFuzzprocessOperationsNoVerify_1000(t *testing.T) {
SkipSlotCache.Disable()
defer SkipSlotCache.Enable()
ctx := context.Background()
state := &stateTrie.BeaconState{}
bb := &ethpb.BeaconBlockBody{}
@@ -152,6 +170,8 @@ func TestFuzzprocessOperationsNoVerify_1000(t *testing.T) {
}
func TestFuzzverifyOperationLengths_10000(t *testing.T) {
SkipSlotCache.Disable()
defer SkipSlotCache.Enable()
state := &stateTrie.BeaconState{}
bb := &ethpb.BeaconBlockBody{}
fuzzer := fuzz.NewWithSeed(0)
@@ -159,11 +179,15 @@ func TestFuzzverifyOperationLengths_10000(t *testing.T) {
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(bb)
verifyOperationLengths(state, bb)
if err := verifyOperationLengths(state, bb); err != nil {
t.Log(err)
}
}
}
func TestFuzzCanProcessEpoch_10000(t *testing.T) {
SkipSlotCache.Disable()
defer SkipSlotCache.Enable()
state := &stateTrie.BeaconState{}
fuzzer := fuzz.NewWithSeed(0)
fuzzer.NilChance(0.1)
@@ -174,6 +198,8 @@ func TestFuzzCanProcessEpoch_10000(t *testing.T) {
}
func TestFuzzProcessEpochPrecompute_1000(t *testing.T) {
SkipSlotCache.Disable()
defer SkipSlotCache.Enable()
ctx := context.Background()
state := &stateTrie.BeaconState{}
fuzzer := fuzz.NewWithSeed(0)
@@ -188,6 +214,8 @@ func TestFuzzProcessEpochPrecompute_1000(t *testing.T) {
}
func TestFuzzProcessBlockForStateRoot_1000(t *testing.T) {
SkipSlotCache.Disable()
defer SkipSlotCache.Enable()
ctx := context.Background()
state := &stateTrie.BeaconState{}
sb := &ethpb.SignedBeaconBlock{}

View File

@@ -15,6 +15,7 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
beaconstate "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"
@@ -25,6 +26,10 @@ import (
"github.com/sirupsen/logrus"
)
func init() {
state.SkipSlotCache.Disable()
}
func TestExecuteStateTransition_IncorrectSlot(t *testing.T) {
base := &pb.BeaconState{
Slot: 5,
@@ -39,7 +44,8 @@ func TestExecuteStateTransition_IncorrectSlot(t *testing.T) {
},
}
want := "expected state.slot"
if _, err := state.ExecuteStateTransition(context.Background(), beaconState, block); !strings.Contains(err.Error(), want) {
_, err = state.ExecuteStateTransition(context.Background(), beaconState, block)
if err == nil || !strings.Contains(err.Error(), want) {
t.Errorf("Expected %s, received %v", want, err)
}
}
@@ -51,33 +57,46 @@ func TestExecuteStateTransition_FullProcess(t *testing.T) {
DepositCount: 100,
DepositRoot: []byte{2},
}
beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch - 1)
if err := beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch - 1); err != nil {
t.Fatal(err)
}
e := beaconState.Eth1Data()
e.DepositCount = 100
beaconState.SetEth1Data(e)
beaconState.SetLatestBlockHeader(&ethpb.BeaconBlockHeader{Slot: beaconState.Slot()})
beaconState.SetEth1DataVotes([]*ethpb.Eth1Data{eth1Data})
if err := beaconState.SetEth1Data(e); err != nil {
t.Fatal(err)
}
if err := beaconState.SetLatestBlockHeader(&ethpb.BeaconBlockHeader{Slot: beaconState.Slot()}); err != nil {
t.Fatal(err)
}
if err := beaconState.SetEth1DataVotes([]*ethpb.Eth1Data{eth1Data}); err != nil {
t.Fatal(err)
}
oldMix, err := beaconState.RandaoMixAtIndex(1)
if err != nil {
t.Fatal(err)
}
parentRoot, err := ssz.HashTreeRoot(beaconState.LatestBlockHeader())
parentRoot, err := stateutil.BlockHeaderRoot(beaconState.LatestBlockHeader())
if err != nil {
t.Error(err)
}
beaconState.SetSlot(beaconState.Slot() + 1)
if err := beaconState.SetSlot(beaconState.Slot() + 1); err != nil {
t.Fatal(err)
}
epoch := helpers.CurrentEpoch(beaconState)
randaoReveal, err := testutil.RandaoReveal(beaconState, epoch, privKeys)
if err != nil {
t.Fatal(err)
}
beaconState.SetSlot(beaconState.Slot() - 1)
if err := beaconState.SetSlot(beaconState.Slot() - 1); err != nil {
t.Fatal(err)
}
block := &ethpb.SignedBeaconBlock{
Block: &ethpb.BeaconBlock{
Slot: beaconState.Slot() + 1,
ParentRoot: parentRoot[:],
ProposerIndex: 74,
Slot: beaconState.Slot() + 1,
ParentRoot: parentRoot[:],
Body: &ethpb.BeaconBlockBody{
RandaoReveal: randaoReveal,
Eth1Data: eth1Data,
@@ -107,7 +126,11 @@ func TestExecuteStateTransition_FullProcess(t *testing.T) {
t.Errorf("Unexpected Slot number, expected: 64, received: %d", beaconState.Slot())
}
if mix, _ := beaconState.RandaoMixAtIndex(1); bytes.Equal(mix, oldMix) {
mix, err := beaconState.RandaoMixAtIndex(1)
if err != nil {
t.Fatal(err)
}
if bytes.Equal(mix, oldMix) {
t.Errorf("Did not expect new and old randao mix to equal, %#x == %#x", mix, oldMix)
}
}
@@ -125,21 +148,25 @@ func TestProcessBlock_IncorrectProposerSlashing(t *testing.T) {
}
block.Block.Body.ProposerSlashings = []*ethpb.ProposerSlashing{slashing}
blockRoot, err := ssz.HashTreeRoot(block.Block)
if err != nil {
if err := beaconState.SetSlot(beaconState.Slot() + 1); err != nil {
t.Fatal(err)
}
beaconState.SetSlot(beaconState.Slot() + 1)
proposerIdx, err := helpers.BeaconProposerIndex(beaconState)
if err != nil {
t.Fatal(err)
}
beaconState.SetSlot(beaconState.Slot() - 1)
domain, err := helpers.Domain(beaconState.Fork(), helpers.CurrentEpoch(beaconState), params.BeaconConfig().DomainBeaconProposer)
if err := beaconState.SetSlot(beaconState.Slot() - 1); err != nil {
t.Fatal(err)
}
domain, err := helpers.Domain(beaconState.Fork(), helpers.CurrentEpoch(beaconState), params.BeaconConfig().DomainBeaconProposer, beaconState.GenesisValidatorRoot())
if err != nil {
t.Fatal(err)
}
sig := privKeys[proposerIdx].Sign(blockRoot[:], domain)
root, err := helpers.ComputeSigningRoot(block.Block, domain)
if err != nil {
t.Fatal(err)
}
sig := privKeys[proposerIdx].Sign(root[:])
block.Signature = sig.Marshal()
beaconState, err = state.ProcessSlots(context.Background(), beaconState, 1)
@@ -147,7 +174,8 @@ func TestProcessBlock_IncorrectProposerSlashing(t *testing.T) {
t.Fatal(err)
}
want := "could not process block proposer slashing"
if _, err := state.ProcessBlock(context.Background(), beaconState, block); !strings.Contains(err.Error(), want) {
_, err = state.ProcessBlock(context.Background(), beaconState, block)
if err == nil || !strings.Contains(err.Error(), want) {
t.Errorf("Expected %s, received %v", want, err)
}
}
@@ -168,21 +196,25 @@ func TestProcessBlock_IncorrectProcessBlockAttestations(t *testing.T) {
t.Fatal(err)
}
block.Block.Body.Attestations = []*ethpb.Attestation{att}
blockRoot, err := ssz.HashTreeRoot(block.Block)
if err != nil {
if err := beaconState.SetSlot(beaconState.Slot() + 1); err != nil {
t.Fatal(err)
}
beaconState.SetSlot(beaconState.Slot() + 1)
proposerIdx, err := helpers.BeaconProposerIndex(beaconState)
if err != nil {
t.Fatal(err)
}
beaconState.SetSlot(beaconState.Slot() - 1)
domain, err := helpers.Domain(beaconState.Fork(), helpers.CurrentEpoch(beaconState), params.BeaconConfig().DomainBeaconProposer)
if err := beaconState.SetSlot(beaconState.Slot() - 1); err != nil {
t.Fatal(err)
}
domain, err := helpers.Domain(beaconState.Fork(), helpers.CurrentEpoch(beaconState), params.BeaconConfig().DomainBeaconProposer, beaconState.GenesisValidatorRoot())
if err != nil {
t.Fatal(err)
}
sig := privKeys[proposerIdx].Sign(blockRoot[:], domain)
root, err := helpers.ComputeSigningRoot(block.Block, domain)
if err != nil {
t.Fatal(err)
}
sig := privKeys[proposerIdx].Sign(root[:])
block.Signature = sig.Marshal()
beaconState, err = state.ProcessSlots(context.Background(), beaconState, 1)
@@ -191,7 +223,8 @@ func TestProcessBlock_IncorrectProcessBlockAttestations(t *testing.T) {
}
want := "could not process block attestations"
if _, err := state.ProcessBlock(context.Background(), beaconState, block); !strings.Contains(err.Error(), want) {
_, err = state.ProcessBlock(context.Background(), beaconState, block)
if err == nil || !strings.Contains(err.Error(), want) {
t.Errorf("Expected %s, received %v", want, err)
}
}
@@ -201,16 +234,17 @@ func TestProcessBlock_IncorrectProcessExits(t *testing.T) {
proposerSlashings := []*ethpb.ProposerSlashing{
{
ProposerIndex: 3,
Header_1: &ethpb.SignedBeaconBlockHeader{
Header: &ethpb.BeaconBlockHeader{
Slot: 1,
ProposerIndex: 3,
Slot: 1,
},
Signature: []byte("A"),
},
Header_2: &ethpb.SignedBeaconBlockHeader{
Header: &ethpb.BeaconBlockHeader{
Slot: 1,
ProposerIndex: 3,
Slot: 1,
},
Signature: []byte("B"),
},
@@ -238,7 +272,9 @@ func TestProcessBlock_IncorrectProcessExits(t *testing.T) {
for i := uint64(0); i < params.BeaconConfig().SlotsPerHistoricalRoot; i++ {
blockRoots = append(blockRoots, []byte{byte(i)})
}
beaconState.SetBlockRoots(blockRoots)
if err := beaconState.SetBlockRoots(blockRoots); err != nil {
t.Fatal(err)
}
blockAtt := &ethpb.Attestation{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0},
@@ -256,11 +292,14 @@ func TestProcessBlock_IncorrectProcessExits(t *testing.T) {
if err != nil {
t.Fatal(err)
}
beaconState.SetLatestBlockHeader(&ethpb.BeaconBlockHeader{
err = beaconState.SetLatestBlockHeader(&ethpb.BeaconBlockHeader{
Slot: genesisBlock.Block.Slot,
ParentRoot: genesisBlock.Block.ParentRoot,
BodyRoot: bodyRoot[:],
})
if err != nil {
t.Fatal(err)
}
parentRoot, err := ssz.HashTreeRoot(beaconState.LatestBlockHeader())
if err != nil {
t.Fatal(err)
@@ -282,11 +321,18 @@ func TestProcessBlock_IncorrectProcessExits(t *testing.T) {
},
},
}
beaconState.SetSlot(beaconState.Slot() + params.BeaconConfig().MinAttestationInclusionDelay)
err = beaconState.SetSlot(beaconState.Slot() + params.BeaconConfig().MinAttestationInclusionDelay)
if err != nil {
t.Fatal(err)
}
cp := beaconState.CurrentJustifiedCheckpoint()
cp.Root = []byte("hello-world")
beaconState.SetCurrentJustifiedCheckpoint(cp)
beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{})
if err := beaconState.SetCurrentJustifiedCheckpoint(cp); err != nil {
t.Fatal(err)
}
if err := beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{}); err != nil {
t.Fatal(err)
}
if _, err := state.ProcessBlock(context.Background(), beaconState, block); err == nil {
t.Error("Expected err, received nil")
}
@@ -299,29 +345,43 @@ func TestProcessBlock_PassesProcessingConditions(t *testing.T) {
if err != nil {
t.Fatal(err)
}
beaconState.SetLatestBlockHeader(&ethpb.BeaconBlockHeader{
err = beaconState.SetLatestBlockHeader(&ethpb.BeaconBlockHeader{
Slot: genesisBlock.Block.Slot,
ParentRoot: genesisBlock.Block.ParentRoot,
StateRoot: params.BeaconConfig().ZeroHash[:],
BodyRoot: bodyRoot[:],
})
beaconState.SetSlashings(make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector))
if err != nil {
t.Fatal(err)
}
err = beaconState.SetSlashings(make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector))
if err != nil {
t.Fatal(err)
}
cp := beaconState.CurrentJustifiedCheckpoint()
mockRoot := [32]byte{}
copy(mockRoot[:], "hello-world")
cp.Root = mockRoot[:]
beaconState.SetCurrentJustifiedCheckpoint(cp)
beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{})
if err := beaconState.SetCurrentJustifiedCheckpoint(cp); err != nil {
t.Fatal(err)
}
if err := beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{}); err != nil {
t.Fatal(err)
}
proposerSlashIdx := uint64(3)
slotsPerEpoch := params.BeaconConfig().SlotsPerEpoch
beaconState.SetSlot((params.BeaconConfig().PersistentCommitteePeriod * slotsPerEpoch) + params.BeaconConfig().MinAttestationInclusionDelay)
err = beaconState.SetSlot((params.BeaconConfig().PersistentCommitteePeriod * slotsPerEpoch) + params.BeaconConfig().MinAttestationInclusionDelay)
if err != nil {
t.Fatal(err)
}
currentEpoch := helpers.CurrentEpoch(beaconState)
domain, err := helpers.Domain(
beaconState.Fork(),
currentEpoch,
params.BeaconConfig().DomainBeaconProposer,
beaconState.GenesisValidatorRoot(),
)
if err != nil {
t.Fatal(err)
@@ -329,38 +389,41 @@ func TestProcessBlock_PassesProcessingConditions(t *testing.T) {
header1 := &ethpb.SignedBeaconBlockHeader{
Header: &ethpb.BeaconBlockHeader{
Slot: 1,
StateRoot: []byte("A"),
ProposerIndex: proposerSlashIdx,
Slot: 1,
StateRoot: []byte("A"),
},
}
signingRoot, err := ssz.HashTreeRoot(header1.Header)
root, err := helpers.ComputeSigningRoot(header1.Header, domain)
if err != nil {
t.Errorf("Could not get signing root of beacon block header: %v", err)
t.Fatal(err)
}
header1.Signature = privKeys[proposerSlashIdx].Sign(signingRoot[:], domain).Marshal()[:]
header1.Signature = privKeys[proposerSlashIdx].Sign(root[:]).Marshal()[:]
header2 := &ethpb.SignedBeaconBlockHeader{
Header: &ethpb.BeaconBlockHeader{
Slot: 1,
StateRoot: []byte("B"),
ProposerIndex: proposerSlashIdx,
Slot: 1,
StateRoot: []byte("B"),
},
}
signingRoot, err = ssz.HashTreeRoot(header2.Header)
root, err = helpers.ComputeSigningRoot(header2.Header, domain)
if err != nil {
t.Errorf("Could not get signing root of beacon block header: %v", err)
t.Fatal(err)
}
header2.Signature = privKeys[proposerSlashIdx].Sign(signingRoot[:], domain).Marshal()[:]
header2.Signature = privKeys[proposerSlashIdx].Sign(root[:]).Marshal()[:]
proposerSlashings := []*ethpb.ProposerSlashing{
{
ProposerIndex: proposerSlashIdx,
Header_1: header1,
Header_2: header2,
Header_1: header1,
Header_2: header2,
},
}
validators := beaconState.Validators()
validators[proposerSlashIdx].PublicKey = privKeys[proposerSlashIdx].PublicKey().Marshal()[:]
beaconState.SetValidators(validators)
if err := beaconState.SetValidators(validators); err != nil {
t.Fatal(err)
}
mockRoot2 := [32]byte{'A'}
att1 := &ethpb.IndexedAttestation{
@@ -369,16 +432,16 @@ func TestProcessBlock_PassesProcessingConditions(t *testing.T) {
Target: &ethpb.Checkpoint{Epoch: 0}},
AttestingIndices: []uint64{0, 1},
}
hashTreeRoot, err := ssz.HashTreeRoot(att1.Data)
if err != nil {
t.Error(err)
}
domain, err = helpers.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainBeaconAttester)
domain, err = helpers.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorRoot())
if err != nil {
t.Fatal(err)
}
sig0 := privKeys[0].Sign(hashTreeRoot[:], domain)
sig1 := privKeys[1].Sign(hashTreeRoot[:], domain)
hashTreeRoot, err := helpers.ComputeSigningRoot(att1.Data, domain)
if err != nil {
t.Error(err)
}
sig0 := privKeys[0].Sign(hashTreeRoot[:])
sig1 := privKeys[1].Sign(hashTreeRoot[:])
aggregateSig := bls.AggregateSignatures([]*bls.Signature{sig0, sig1})
att1.Signature = aggregateSig.Marshal()[:]
@@ -389,12 +452,13 @@ func TestProcessBlock_PassesProcessingConditions(t *testing.T) {
Target: &ethpb.Checkpoint{Epoch: 0}},
AttestingIndices: []uint64{0, 1},
}
hashTreeRoot, err = ssz.HashTreeRoot(att2.Data)
hashTreeRoot, err = helpers.ComputeSigningRoot(att2.Data, domain)
if err != nil {
t.Error(err)
}
sig0 = privKeys[0].Sign(hashTreeRoot[:], domain)
sig1 = privKeys[1].Sign(hashTreeRoot[:], domain)
sig0 = privKeys[0].Sign(hashTreeRoot[:])
sig1 = privKeys[1].Sign(hashTreeRoot[:])
aggregateSig = bls.AggregateSignatures([]*bls.Signature{sig0, sig1})
att2.Signature = aggregateSig.Marshal()[:]
@@ -409,7 +473,9 @@ func TestProcessBlock_PassesProcessingConditions(t *testing.T) {
for i := uint64(0); i < params.BeaconConfig().SlotsPerHistoricalRoot; i++ {
blockRoots = append(blockRoots, []byte{byte(i)})
}
beaconState.SetBlockRoots(blockRoots)
if err := beaconState.SetBlockRoots(blockRoots); err != nil {
t.Fatal(err)
}
aggBits := bitfield.NewBitlist(1)
aggBits.SetBitAt(0, true)
@@ -432,13 +498,13 @@ func TestProcessBlock_PassesProcessingConditions(t *testing.T) {
if err != nil {
t.Error(err)
}
hashTreeRoot, err = ssz.HashTreeRoot(blockAtt.Data)
hashTreeRoot, err = helpers.ComputeSigningRoot(blockAtt.Data, domain)
if err != nil {
t.Error(err)
}
sigs := make([]*bls.Signature, len(attestingIndices))
for i, indice := range attestingIndices {
sig := privKeys[indice].Sign(hashTreeRoot[:], domain)
sig := privKeys[indice].Sign(hashTreeRoot[:])
sigs[i] = sig
}
blockAtt.Signature = bls.AggregateSignatures(sigs).Marshal()[:]
@@ -449,17 +515,17 @@ func TestProcessBlock_PassesProcessingConditions(t *testing.T) {
Epoch: 0,
},
}
signingRoot, err = ssz.HashTreeRoot(exit.Exit)
if err != nil {
t.Errorf("Could not get signing root of beacon block header: %v", err)
}
domain, err = helpers.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainVoluntaryExit)
domain, err = helpers.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainVoluntaryExit, beaconState.GenesisValidatorRoot())
if err != nil {
t.Fatal(err)
}
exit.Signature = privKeys[exit.Exit.ValidatorIndex].Sign(signingRoot[:], domain).Marshal()[:]
signingRoot, err := helpers.ComputeSigningRoot(exit.Exit, domain)
if err != nil {
t.Errorf("Could not get signing root of beacon block header: %v", err)
}
exit.Signature = privKeys[exit.Exit.ValidatorIndex].Sign(signingRoot[:]).Marshal()[:]
parentRoot, err := ssz.HashTreeRoot(beaconState.LatestBlockHeader())
parentRoot, err := stateutil.BlockHeaderRoot(beaconState.LatestBlockHeader())
if err != nil {
t.Fatal(err)
}
@@ -470,8 +536,9 @@ func TestProcessBlock_PassesProcessingConditions(t *testing.T) {
}
block := &ethpb.SignedBeaconBlock{
Block: &ethpb.BeaconBlock{
ParentRoot: parentRoot[:],
Slot: beaconState.Slot(),
ParentRoot: parentRoot[:],
Slot: beaconState.Slot(),
ProposerIndex: 17,
Body: &ethpb.BeaconBlockBody{
RandaoReveal: randaoReveal,
ProposerSlashings: proposerSlashings,
@@ -497,15 +564,25 @@ func TestProcessBlock_PassesProcessingConditions(t *testing.T) {
t.Fatalf("Expected block to pass processing conditions: %v", err)
}
if v, _ := beaconState.ValidatorAtIndex(proposerSlashings[0].ProposerIndex); !v.Slashed {
t.Errorf("Expected validator at index %d to be slashed, received false", proposerSlashings[0].ProposerIndex)
v, err := beaconState.ValidatorAtIndex(proposerSlashings[0].Header_1.Header.ProposerIndex)
if err != nil {
t.Fatal(err)
}
if v, _ := beaconState.ValidatorAtIndex(1); !v.Slashed {
if !v.Slashed {
t.Errorf("Expected validator at index %d to be slashed, received false", proposerSlashings[0].Header_1.Header.ProposerIndex)
}
v, err = beaconState.ValidatorAtIndex(1)
if err != nil {
t.Fatal(err)
}
if !v.Slashed {
t.Error("Expected validator at index 1 to be slashed, received false")
}
v, _ := beaconState.ValidatorAtIndex(exit.Exit.ValidatorIndex)
v, err = beaconState.ValidatorAtIndex(exit.Exit.ValidatorIndex)
if err != nil {
t.Fatal(err)
}
received := v.ExitEpoch
wanted := params.BeaconConfig().FarFutureEpoch
if received == wanted {
@@ -527,6 +604,7 @@ func TestProcessEpochPrecompute_CanProcess(t *testing.T) {
FinalizedCheckpoint: &ethpb.Checkpoint{},
JustificationBits: bitfield.Bitvector4{0x00},
CurrentJustifiedCheckpoint: &ethpb.Checkpoint{},
Validators: []*ethpb.Validator{},
}
s, err := beaconstate.InitializeFromProto(base)
if err != nil {
@@ -590,16 +668,17 @@ func BenchmarkProcessBlk_65536Validators_FullBlock(b *testing.B) {
// Set up proposer slashing object for block
proposerSlashings := []*ethpb.ProposerSlashing{
{
ProposerIndex: 1,
Header_1: &ethpb.SignedBeaconBlockHeader{
Header: &ethpb.BeaconBlockHeader{
Slot: 0,
ProposerIndex: 1,
Slot: 0,
},
Signature: []byte("A"),
},
Header_2: &ethpb.SignedBeaconBlockHeader{
Header: &ethpb.BeaconBlockHeader{
Slot: 0,
ProposerIndex: 1,
Slot: 0,
},
Signature: []byte("B"),
},
@@ -652,11 +731,19 @@ func BenchmarkProcessBlk_65536Validators_FullBlock(b *testing.B) {
v[proposerIdx].PublicKey = priv.PublicKey().Marshal()
buf := make([]byte, 32)
binary.LittleEndian.PutUint64(buf, 0)
domain, err := helpers.Domain(s.Fork(), 0, params.BeaconConfig().DomainRandao)
domain, err := helpers.Domain(s.Fork(), 0, params.BeaconConfig().DomainRandao, s.GenesisValidatorRoot())
if err != nil {
b.Fatal(err)
}
epochSignature := priv.Sign(buf, domain)
ctr := &pb.SigningRoot{
ObjectRoot: buf,
Domain: domain,
}
root, err = ssz.HashTreeRoot(ctr)
if err != nil {
b.Fatal(err)
}
epochSignature := priv.Sign(root[:])
buf = []byte{params.BeaconConfig().BLSWithdrawalPrefixByte}
pubKey := []byte("A")
@@ -664,7 +751,9 @@ func BenchmarkProcessBlk_65536Validators_FullBlock(b *testing.B) {
buf = append(buf, hashed[:]...)
v[3].WithdrawalCredentials = buf
s.SetValidators(v)
if err := s.SetValidators(v); err != nil {
b.Fatal(err)
}
attestations := make([]*ethpb.Attestation, 128)
for i := 0; i < len(attestations); i++ {
@@ -709,10 +798,14 @@ func BenchmarkProcessBlk_65536Validators_FullBlock(b *testing.B) {
v := s.Validators()
v[1].Slashed = false
v[2].Slashed = false
s.SetValidators(v)
b := s.Balances()
b[3] += 2 * params.BeaconConfig().MinDepositAmount
s.SetBalances(b)
if err := s.SetValidators(v); err != nil {
b.Fatal(err)
}
balances := s.Balances()
balances[3] += 2 * params.BeaconConfig().MinDepositAmount
if err := s.SetBalances(balances); err != nil {
b.Fatal(err)
}
}
}
@@ -722,7 +815,9 @@ func TestProcessBlk_AttsBasedOnValidatorCount(t *testing.T) {
// Default at 256 validators, can raise this number with faster BLS.
validatorCount := uint64(256)
s, privKeys := testutil.DeterministicGenesisState(t, validatorCount)
s.SetSlot(params.BeaconConfig().SlotsPerEpoch)
if err := s.SetSlot(params.BeaconConfig().SlotsPerEpoch); err != nil {
t.Fatal(err)
}
bitCount := validatorCount / params.BeaconConfig().SlotsPerEpoch
aggBits := bitfield.NewBitlist(bitCount)
@@ -747,29 +842,36 @@ func TestProcessBlk_AttsBasedOnValidatorCount(t *testing.T) {
if err != nil {
t.Error(err)
}
domain, err := helpers.Domain(s.Fork(), 0, params.BeaconConfig().DomainBeaconAttester)
domain, err := helpers.Domain(s.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, s.GenesisValidatorRoot())
if err != nil {
t.Fatal(err)
}
sigs := make([]*bls.Signature, len(attestingIndices))
for i, indice := range attestingIndices {
hashTreeRoot, err := ssz.HashTreeRoot(att.Data)
hashTreeRoot, err := helpers.ComputeSigningRoot(att.Data, domain)
if err != nil {
t.Error(err)
}
sig := privKeys[indice].Sign(hashTreeRoot[:], domain)
sig := privKeys[indice].Sign(hashTreeRoot[:])
sigs[i] = sig
}
att.Signature = bls.AggregateSignatures(sigs).Marshal()[:]
atts[i] = att
}
epochSignature, _ := testutil.RandaoReveal(s, helpers.CurrentEpoch(s), privKeys)
parentRoot, _ := ssz.HashTreeRoot(s.LatestBlockHeader())
epochSignature, err := testutil.RandaoReveal(s, helpers.CurrentEpoch(s), privKeys)
if err != nil {
t.Fatal(err)
}
parentRoot, err := stateutil.BlockHeaderRoot(s.LatestBlockHeader())
if err != nil {
t.Fatal(err)
}
blk := &ethpb.SignedBeaconBlock{
Block: &ethpb.BeaconBlock{
Slot: s.Slot(),
ParentRoot: parentRoot[:],
ProposerIndex: 72,
Slot: s.Slot(),
ParentRoot: parentRoot[:],
Body: &ethpb.BeaconBlockBody{
Eth1Data: &ethpb.Eth1Data{},
RandaoReveal: epochSignature,
@@ -847,7 +949,7 @@ func TestProcessOperations_OverMaxProposerSlashings(t *testing.T) {
context.Background(),
&beaconstate.BeaconState{},
block.Body,
); !strings.Contains(err.Error(), want) {
); err == nil || !strings.Contains(err.Error(), want) {
t.Errorf("Expected %s, received %v", want, err)
}
}
@@ -866,7 +968,7 @@ func TestProcessOperations_OverMaxAttesterSlashings(t *testing.T) {
context.Background(),
&beaconstate.BeaconState{},
block.Body,
); !strings.Contains(err.Error(), want) {
); err == nil || !strings.Contains(err.Error(), want) {
t.Errorf("Expected %s, received %v", want, err)
}
}
@@ -884,7 +986,7 @@ func TestProcessOperations_OverMaxAttestations(t *testing.T) {
context.Background(),
&beaconstate.BeaconState{},
block.Body,
); !strings.Contains(err.Error(), want) {
); err == nil || !strings.Contains(err.Error(), want) {
t.Errorf("Expected %s, received %v", want, err)
}
}
@@ -903,7 +1005,7 @@ func TestProcessOperation_OverMaxVoluntaryExits(t *testing.T) {
context.Background(),
&beaconstate.BeaconState{},
block.Body,
); !strings.Contains(err.Error(), want) {
); err == nil || !strings.Contains(err.Error(), want) {
t.Errorf("Expected %s, received %v", want, err)
}
}
@@ -929,7 +1031,7 @@ func TestProcessOperations_IncorrectDeposits(t *testing.T) {
context.Background(),
s,
block.Body,
); !strings.Contains(err.Error(), want) {
); err == nil || !strings.Contains(err.Error(), want) {
t.Errorf("Expected %s, received %v", want, err)
}
}

View File

@@ -169,10 +169,9 @@ func SlashValidator(state *stateTrie.BeaconState, slashedIdx uint64, whistleBlow
// ActivatedValidatorIndices determines the indices activated during the given epoch.
func ActivatedValidatorIndices(epoch uint64, validators []*ethpb.Validator) []uint64 {
activations := make([]uint64, 0)
delayedActivationEpoch := helpers.ActivationExitEpoch(epoch)
for i := 0; i < len(validators); i++ {
val := validators[i]
if val.ActivationEpoch == delayedActivationEpoch {
if val.ActivationEpoch <= epoch && epoch < val.ExitEpoch {
activations = append(activations, uint64(i))
}
}

View File

@@ -223,16 +223,19 @@ func TestActivatedValidatorIndices(t *testing.T) {
Slot: 0,
Validators: []*ethpb.Validator{
{
ActivationEpoch: helpers.ActivationExitEpoch(0),
ActivationEpoch: 0,
ExitEpoch: 1,
},
{
ActivationEpoch: helpers.ActivationExitEpoch(0),
ActivationEpoch: 0,
ExitEpoch: 1,
},
{
ActivationEpoch: helpers.ActivationExitEpoch(5),
ActivationEpoch: 5,
},
{
ActivationEpoch: helpers.ActivationExitEpoch(0),
ActivationEpoch: 0,
ExitEpoch: 1,
},
},
},
@@ -254,7 +257,8 @@ func TestActivatedValidatorIndices(t *testing.T) {
Slot: 0,
Validators: []*ethpb.Validator{
{
ActivationEpoch: helpers.ActivationExitEpoch(0),
ActivationEpoch: 0,
ExitEpoch: 1,
},
},
},

View File

@@ -29,9 +29,6 @@ type ReadOnlyDatabase interface {
IsFinalizedBlock(ctx context.Context, blockRoot [32]byte) bool
HighestSlotBlocks(ctx context.Context) ([]*ethpb.SignedBeaconBlock, error)
HighestSlotBlocksBelow(ctx context.Context, slot uint64) ([]*ethpb.SignedBeaconBlock, error)
// Validator related methods.
ValidatorIndex(ctx context.Context, publicKey []byte) (uint64, bool, error)
HasValidatorIndex(ctx context.Context, publicKey []byte) bool
// State related methods.
State(ctx context.Context, blockRoot [32]byte) (*state.BeaconState, error)
GenesisState(ctx context.Context) (*state.BeaconState, error)
@@ -59,6 +56,7 @@ type ReadOnlyDatabase interface {
ArchivedPointRoot(ctx context.Context, index uint64) [32]byte
HasArchivedPoint(ctx context.Context, index uint64) bool
LastArchivedIndexRoot(ctx context.Context) [32]byte
LastArchivedIndex(ctx context.Context) (uint64, error)
// Deposit contract related handlers.
DepositContractAddress(ctx context.Context) ([]byte, error)
// Powchain operations.
@@ -80,10 +78,6 @@ type NoHeadAccessDatabase interface {
SaveBlock(ctx context.Context, block *eth.SignedBeaconBlock) error
SaveBlocks(ctx context.Context, blocks []*eth.SignedBeaconBlock) error
SaveGenesisBlockRoot(ctx context.Context, blockRoot [32]byte) error
// Validator related methods.
DeleteValidatorIndex(ctx context.Context, publicKey []byte) error
SaveValidatorIndex(ctx context.Context, publicKey []byte, validatorIdx uint64) error
SaveValidatorIndices(ctx context.Context, publicKeys [][48]byte, validatorIndices []uint64) error
// State related methods.
SaveState(ctx context.Context, state *state.BeaconState, blockRoot [32]byte) error
SaveStates(ctx context.Context, states []*state.BeaconState, blockRoots [][32]byte) error

View File

@@ -88,21 +88,6 @@ func (e Exporter) DeleteBlocks(ctx context.Context, blockRoots [][32]byte) error
return e.db.DeleteBlocks(ctx, blockRoots)
}
// ValidatorIndex -- passthrough.
func (e Exporter) ValidatorIndex(ctx context.Context, publicKey []byte) (uint64, bool, error) {
return e.db.ValidatorIndex(ctx, publicKey)
}
// HasValidatorIndex -- passthrough.
func (e Exporter) HasValidatorIndex(ctx context.Context, publicKey []byte) bool {
return e.db.HasValidatorIndex(ctx, publicKey)
}
// DeleteValidatorIndex -- passthrough.
func (e Exporter) DeleteValidatorIndex(ctx context.Context, publicKey []byte) error {
return e.db.DeleteValidatorIndex(ctx, publicKey)
}
// State -- passthrough.
func (e Exporter) State(ctx context.Context, blockRoot [32]byte) (*state.BeaconState, error) {
return e.db.State(ctx, blockRoot)
@@ -218,16 +203,6 @@ func (e Exporter) SaveGenesisBlockRoot(ctx context.Context, blockRoot [32]byte)
return e.db.SaveGenesisBlockRoot(ctx, blockRoot)
}
// SaveValidatorIndex -- passthrough.
func (e Exporter) SaveValidatorIndex(ctx context.Context, publicKey []byte, validatorIdx uint64) error {
return e.db.SaveValidatorIndex(ctx, publicKey, validatorIdx)
}
// SaveValidatorIndices -- passthrough.
func (e Exporter) SaveValidatorIndices(ctx context.Context, publicKeys [][48]byte, validatorIndices []uint64) error {
return e.db.SaveValidatorIndices(ctx, publicKeys, validatorIndices)
}
// SaveState -- passthrough.
func (e Exporter) SaveState(ctx context.Context, state *state.BeaconState, blockRoot [32]byte) error {
return e.db.SaveState(ctx, state, blockRoot)
@@ -377,3 +352,8 @@ func (e Exporter) HighestSlotStatesBelow(ctx context.Context, slot uint64) ([]*s
func (e Exporter) SaveLastArchivedIndex(ctx context.Context, index uint64) error {
return e.db.SaveLastArchivedIndex(ctx, index)
}
// LastArchivedIndex -- passthrough
func (e Exporter) LastArchivedIndex(ctx context.Context) (uint64, error) {
return e.db.LastArchivedIndex(ctx)
}

View File

@@ -8,7 +8,7 @@ go_library(
"attestations.go",
"backup.go",
"blocks.go",
"check_state.go",
"check_historical_state.go",
"checkpoint.go",
"deposit_contract.go",
"encoding.go",
@@ -16,18 +16,19 @@ go_library(
"kv.go",
"operations.go",
"powchain.go",
"regen_historical_states.go",
"schema.go",
"slashings.go",
"state.go",
"state_summary.go",
"utils.go",
"validators.go",
],
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/db/kv",
visibility = ["//beacon-chain:__subpackages__"],
deps = [
"//beacon-chain/cache:go_default_library",
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/core/state:go_default_library",
"//beacon-chain/db/filters:go_default_library",
"//beacon-chain/db/iface:go_default_library",
"//beacon-chain/state:go_default_library",
@@ -35,12 +36,14 @@ go_library(
"//proto/beacon/db:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//shared/bytesutil:go_default_library",
"//shared/cmd:go_default_library",
"//shared/featureconfig:go_default_library",
"//shared/params:go_default_library",
"//shared/sliceutil:go_default_library",
"//shared/traceutil:go_default_library",
"@com_github_dgraph_io_ristretto//:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_ferranbt_fastssz//:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"@com_github_golang_snappy//:go_default_library",
"@com_github_pkg_errors//:go_default_library",
@@ -71,13 +74,11 @@ go_test(
"slashings_test.go",
"state_summary_test.go",
"state_test.go",
"validators_test.go",
],
embed = [":go_default_library"],
deps = [
"//beacon-chain/cache:go_default_library",
"//beacon-chain/db/filters:go_default_library",
"//beacon-chain/state:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//proto/testing:go_default_library",
"//shared/bytesutil:go_default_library",
@@ -88,5 +89,6 @@ go_test(
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
"@in_gopkg_d4l3k_messagediff_v1//:go_default_library",
],
)

View File

@@ -6,6 +6,7 @@ import (
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
bolt "go.etcd.io/bbolt"
"go.opencensus.io/trace"
)
@@ -15,7 +16,7 @@ func (k *Store) ArchivedActiveValidatorChanges(ctx context.Context, epoch uint64
ctx, span := trace.StartSpan(ctx, "BeaconDB.ArchivedActiveValidatorChanges")
defer span.End()
buf := uint64ToBytes(epoch)
buf := bytesutil.Uint64ToBytes(epoch)
var target *pb.ArchivedActiveSetChanges
err := k.db.View(func(tx *bolt.Tx) error {
bkt := tx.Bucket(archivedValidatorSetChangesBucket)
@@ -33,7 +34,7 @@ func (k *Store) ArchivedActiveValidatorChanges(ctx context.Context, epoch uint64
func (k *Store) SaveArchivedActiveValidatorChanges(ctx context.Context, epoch uint64, changes *pb.ArchivedActiveSetChanges) error {
ctx, span := trace.StartSpan(ctx, "BeaconDB.SaveArchivedActiveValidatorChanges")
defer span.End()
buf := uint64ToBytes(epoch)
buf := bytesutil.Uint64ToBytes(epoch)
enc, err := encode(changes)
if err != nil {
return err
@@ -49,7 +50,7 @@ func (k *Store) ArchivedCommitteeInfo(ctx context.Context, epoch uint64) (*pb.Ar
ctx, span := trace.StartSpan(ctx, "BeaconDB.ArchivedCommitteeInfo")
defer span.End()
buf := uint64ToBytes(epoch)
buf := bytesutil.Uint64ToBytes(epoch)
var target *pb.ArchivedCommitteeInfo
err := k.db.View(func(tx *bolt.Tx) error {
bkt := tx.Bucket(archivedCommitteeInfoBucket)
@@ -67,7 +68,7 @@ func (k *Store) ArchivedCommitteeInfo(ctx context.Context, epoch uint64) (*pb.Ar
func (k *Store) SaveArchivedCommitteeInfo(ctx context.Context, epoch uint64, info *pb.ArchivedCommitteeInfo) error {
ctx, span := trace.StartSpan(ctx, "BeaconDB.SaveArchivedCommitteeInfo")
defer span.End()
buf := uint64ToBytes(epoch)
buf := bytesutil.Uint64ToBytes(epoch)
enc, err := encode(info)
if err != nil {
return err
@@ -83,7 +84,7 @@ func (k *Store) ArchivedBalances(ctx context.Context, epoch uint64) ([]uint64, e
ctx, span := trace.StartSpan(ctx, "BeaconDB.ArchivedBalances")
defer span.End()
buf := uint64ToBytes(epoch)
buf := bytesutil.Uint64ToBytes(epoch)
var target []uint64
err := k.db.View(func(tx *bolt.Tx) error {
bkt := tx.Bucket(archivedBalancesBucket)
@@ -101,7 +102,7 @@ func (k *Store) ArchivedBalances(ctx context.Context, epoch uint64) ([]uint64, e
func (k *Store) SaveArchivedBalances(ctx context.Context, epoch uint64, balances []uint64) error {
ctx, span := trace.StartSpan(ctx, "BeaconDB.SaveArchivedBalances")
defer span.End()
buf := uint64ToBytes(epoch)
buf := bytesutil.Uint64ToBytes(epoch)
enc := marshalBalances(balances)
return k.db.Update(func(tx *bolt.Tx) error {
bucket := tx.Bucket(archivedBalancesBucket)
@@ -114,7 +115,7 @@ func (k *Store) ArchivedValidatorParticipation(ctx context.Context, epoch uint64
ctx, span := trace.StartSpan(ctx, "BeaconDB.ArchivedValidatorParticipation")
defer span.End()
buf := uint64ToBytes(epoch)
buf := bytesutil.Uint64ToBytes(epoch)
var target *ethpb.ValidatorParticipation
err := k.db.View(func(tx *bolt.Tx) error {
bkt := tx.Bucket(archivedValidatorParticipationBucket)
@@ -132,7 +133,7 @@ func (k *Store) ArchivedValidatorParticipation(ctx context.Context, epoch uint64
func (k *Store) SaveArchivedValidatorParticipation(ctx context.Context, epoch uint64, part *ethpb.ValidatorParticipation) error {
ctx, span := trace.StartSpan(ctx, "BeaconDB.SaveArchivedValidatorParticipation")
defer span.End()
buf := uint64ToBytes(epoch)
buf := bytesutil.Uint64ToBytes(epoch)
enc, err := encode(part)
if err != nil {
return err

View File

@@ -38,22 +38,23 @@ func TestStore_ArchivedActiveValidatorChanges(t *testing.T) {
},
ProposerSlashings: []*ethpb.ProposerSlashing{
{
ProposerIndex: 1212,
Header_1: &ethpb.SignedBeaconBlockHeader{
Header: &ethpb.BeaconBlockHeader{
Slot: 10,
ParentRoot: someRoot[:],
StateRoot: someRoot[:],
BodyRoot: someRoot[:],
ProposerIndex: 1212,
Slot: 10,
ParentRoot: someRoot[:],
StateRoot: someRoot[:],
BodyRoot: someRoot[:],
},
Signature: make([]byte, 96),
},
Header_2: &ethpb.SignedBeaconBlockHeader{
Header: &ethpb.BeaconBlockHeader{
Slot: 10,
ParentRoot: someRoot[:],
StateRoot: someRoot[:],
BodyRoot: someRoot[:],
ProposerIndex: 1212,
Slot: 10,
ParentRoot: someRoot[:],
StateRoot: someRoot[:],
BodyRoot: someRoot[:],
},
Signature: make([]byte, 96),
},

View File

@@ -2,6 +2,7 @@ package kv
import (
"context"
"encoding/binary"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
bolt "go.etcd.io/bbolt"
@@ -15,7 +16,7 @@ func (k *Store) SaveArchivedPointRoot(ctx context.Context, blockRoot [32]byte, i
return k.db.Update(func(tx *bolt.Tx) error {
bucket := tx.Bucket(archivedIndexRootBucket)
return bucket.Put(uint64ToBytes(index), blockRoot[:])
return bucket.Put(bytesutil.Uint64ToBytes(index), blockRoot[:])
})
}
@@ -25,18 +26,35 @@ func (k *Store) SaveLastArchivedIndex(ctx context.Context, index uint64) error {
defer span.End()
return k.db.Update(func(tx *bolt.Tx) error {
bucket := tx.Bucket(archivedIndexRootBucket)
return bucket.Put(lastArchivedIndexKey, uint64ToBytes(index))
return bucket.Put(lastArchivedIndexKey, bytesutil.Uint64ToBytes(index))
})
}
// LastArchivedIndex from the db.
func (k *Store) LastArchivedIndex(ctx context.Context) (uint64, error) {
ctx, span := trace.StartSpan(ctx, "BeaconDB.LastArchivedIndex")
defer span.End()
var index uint64
err := k.db.Update(func(tx *bolt.Tx) error {
bucket := tx.Bucket(archivedIndexRootBucket)
b := bucket.Get(lastArchivedIndexKey)
if b == nil {
return nil
}
index = binary.LittleEndian.Uint64(b)
return nil
})
return index, err
}
// LastArchivedIndexRoot from the db.
func (k *Store) LastArchivedIndexRoot(ctx context.Context) [32]byte {
ctx, span := trace.StartSpan(ctx, "BeaconDB.LastArchivedIndexRoot")
defer span.End()
var blockRoot []byte
// #nosec G104. Always returns nil.
k.db.View(func(tx *bolt.Tx) error {
if err := k.db.View(func(tx *bolt.Tx) error {
bucket := tx.Bucket(archivedIndexRootBucket)
lastArchivedIndex := bucket.Get(lastArchivedIndexKey)
if lastArchivedIndex == nil {
@@ -44,7 +62,9 @@ func (k *Store) LastArchivedIndexRoot(ctx context.Context) [32]byte {
}
blockRoot = bucket.Get(lastArchivedIndex)
return nil
})
}); err != nil { // This view never returns an error, but we'll handle anyway for sanity.
panic(err)
}
return bytesutil.ToBytes32(blockRoot)
}
@@ -56,12 +76,13 @@ func (k *Store) ArchivedPointRoot(ctx context.Context, index uint64) [32]byte {
defer span.End()
var blockRoot []byte
// #nosec G104. Always returns nil.
k.db.View(func(tx *bolt.Tx) error {
if err := k.db.View(func(tx *bolt.Tx) error {
bucket := tx.Bucket(archivedIndexRootBucket)
blockRoot = bucket.Get(uint64ToBytes(index))
blockRoot = bucket.Get(bytesutil.Uint64ToBytes(index))
return nil
})
}); err != nil { // This view never returns an error, but we'll handle anyway for sanity.
panic(err)
}
return bytesutil.ToBytes32(blockRoot)
}
@@ -71,11 +92,12 @@ func (k *Store) HasArchivedPoint(ctx context.Context, index uint64) bool {
ctx, span := trace.StartSpan(ctx, "BeaconDB.HasArchivedPoint")
defer span.End()
var exists bool
// #nosec G104. Always returns nil.
k.db.View(func(tx *bolt.Tx) error {
if err := k.db.View(func(tx *bolt.Tx) error {
iBucket := tx.Bucket(archivedIndexRootBucket)
exists = iBucket.Get(uint64ToBytes(index)) != nil
exists = iBucket.Get(bytesutil.Uint64ToBytes(index)) != nil
return nil
})
}); err != nil { // This view never returns an error, but we'll handle anyway for sanity.
panic(err)
}
return exists
}

View File

@@ -30,6 +30,14 @@ func TestLastArchivedPoint_CanRetrieve(t *testing.T) {
db := setupDB(t)
defer teardownDB(t, db)
ctx := context.Background()
i, err := db.LastArchivedIndex(ctx)
if err != nil {
t.Fatal(err)
}
if i != 0 {
t.Error("Did not get correct index")
}
if err := db.SaveArchivedPointRoot(ctx, [32]byte{'A'}, 1); err != nil {
t.Fatal(err)
}
@@ -51,4 +59,12 @@ func TestLastArchivedPoint_CanRetrieve(t *testing.T) {
if db.LastArchivedIndexRoot(ctx) != [32]byte{'B'} {
t.Error("Did not get wanted root")
}
i, err = db.LastArchivedIndex(ctx)
if err != nil {
t.Fatal(err)
}
if i != 3 {
t.Error("Did not get correct index")
}
}

View File

@@ -9,6 +9,7 @@ import (
"github.com/prysmaticlabs/go-ssz"
"github.com/prysmaticlabs/prysm/beacon-chain/db/filters"
dbpb "github.com/prysmaticlabs/prysm/proto/beacon/db"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/sliceutil"
"github.com/prysmaticlabs/prysm/shared/traceutil"
bolt "go.etcd.io/bbolt"
@@ -82,12 +83,13 @@ func (k *Store) HasAttestation(ctx context.Context, attDataRoot [32]byte) bool {
ctx, span := trace.StartSpan(ctx, "BeaconDB.HasAttestation")
defer span.End()
exists := false
// #nosec G104. Always returns nil.
k.db.View(func(tx *bolt.Tx) error {
if err := k.db.View(func(tx *bolt.Tx) error {
bkt := tx.Bucket(attestationsBucket)
exists = bkt.Get(attDataRoot[:]) != nil
return nil
})
}); err != nil { // This view never returns an error, but we'll handle anyway for sanity.
panic(err)
}
return exists
}
@@ -244,7 +246,7 @@ func createAttestationIndicesFromData(attData *ethpb.AttestationData) map[string
indices := make([][]byte, 0)
if attData.Source != nil {
buckets = append(buckets, attestationSourceEpochIndicesBucket)
indices = append(indices, uint64ToBytes(attData.Source.Epoch))
indices = append(indices, bytesutil.Uint64ToBytes(attData.Source.Epoch))
if attData.Source.Root != nil && len(attData.Source.Root) > 0 {
buckets = append(buckets, attestationSourceRootIndicesBucket)
indices = append(indices, attData.Source.Root)
@@ -252,7 +254,7 @@ func createAttestationIndicesFromData(attData *ethpb.AttestationData) map[string
}
if attData.Target != nil {
buckets = append(buckets, attestationTargetEpochIndicesBucket)
indices = append(indices, uint64ToBytes(attData.Target.Epoch))
indices = append(indices, bytesutil.Uint64ToBytes(attData.Target.Epoch))
if attData.Target.Root != nil && len(attData.Target.Root) > 0 {
buckets = append(buckets, attestationTargetRootIndicesBucket)
indices = append(indices, attData.Target.Root)
@@ -280,19 +282,34 @@ func createAttestationIndicesFromFilters(f *filters.QueryFilter) (map[string][]b
for k, v := range f.Filters() {
switch k {
case filters.HeadBlockRoot:
headBlockRoot := v.([]byte)
headBlockRoot, ok := v.([]byte)
if !ok {
return nil, errors.New("headBlockRoot is not type []byte")
}
indicesByBucket[string(attestationHeadBlockRootBucket)] = headBlockRoot
case filters.SourceRoot:
sourceRoot := v.([]byte)
sourceRoot, ok := v.([]byte)
if !ok {
return nil, errors.New("sourceRoot is not type []byte")
}
indicesByBucket[string(attestationSourceRootIndicesBucket)] = sourceRoot
case filters.SourceEpoch:
sourceEpoch := v.(uint64)
indicesByBucket[string(attestationSourceEpochIndicesBucket)] = uint64ToBytes(sourceEpoch)
sourceEpoch, ok := v.(uint64)
if !ok {
return nil, errors.New("sourceEpoch is not type uint64")
}
indicesByBucket[string(attestationSourceEpochIndicesBucket)] = bytesutil.Uint64ToBytes(sourceEpoch)
case filters.TargetEpoch:
targetEpoch := v.(uint64)
indicesByBucket[string(attestationTargetEpochIndicesBucket)] = uint64ToBytes(targetEpoch)
targetEpoch, ok := v.(uint64)
if !ok {
return nil, errors.New("targetEpoch is not type uint64")
}
indicesByBucket[string(attestationTargetEpochIndicesBucket)] = bytesutil.Uint64ToBytes(targetEpoch)
case filters.TargetRoot:
targetRoot := v.([]byte)
targetRoot, ok := v.([]byte)
if !ok {
return nil, errors.New("targetRoot is not type []byte")
}
indicesByBucket[string(attestationTargetRootIndicesBucket)] = targetRoot
default:
return nil, fmt.Errorf("filter criterion %v not supported for attestations", k)

View File

@@ -300,7 +300,10 @@ func TestStore_DuplicatedAttestations_FiltersCorrectly(t *testing.T) {
t.Errorf("Expected %d attestations, received %d", 1, len(retrievedAtts))
}
att1 := proto.Clone(att).(*ethpb.Attestation)
att1, ok := proto.Clone(att).(*ethpb.Attestation)
if !ok {
t.Error("Entity is not of type *ethpb.Attestation")
}
att1.Data.Source.Epoch = 6
atts = []*ethpb.Attestation{att, att, att, att1, att1, att1}
if err := db.SaveAttestations(ctx, atts); err != nil {

View File

@@ -39,7 +39,11 @@ func (k *Store) Backup(ctx context.Context) error {
if err != nil {
panic(err)
}
defer copyDB.Close()
defer func() {
if err := copyDB.Close(); err != nil {
logrus.WithError(err).Error("Failed to close destination database")
}
}()
return k.db.View(func(tx *bolt.Tx) error {
return tx.ForEach(func(name []byte, b *bolt.Bucket) error {

View File

@@ -8,8 +8,7 @@ import (
eth "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/go-ssz"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/testutil"
)
func TestStore_Backup(t *testing.T) {
@@ -26,7 +25,7 @@ func TestStore_Backup(t *testing.T) {
if err != nil {
t.Fatal(err)
}
st, err := state.InitializeFromProto(&pb.BeaconState{})
st := testutil.NewBeaconState()
if err := db.SaveState(ctx, st, root); err != nil {
t.Fatal(err)
}

View File

@@ -120,12 +120,13 @@ func (k *Store) HasBlock(ctx context.Context, blockRoot [32]byte) bool {
return true
}
exists := false
// #nosec G104. Always returns nil.
k.db.View(func(tx *bolt.Tx) error {
if err := k.db.View(func(tx *bolt.Tx) error {
bkt := tx.Bucket(blocksBucket)
exists = bkt.Get(blockRoot[:]) != nil
return nil
})
}); err != nil { // This view never returns an error, but we'll handle anyway for sanity.
panic(err)
}
return exists
}
@@ -262,9 +263,12 @@ func (k *Store) SaveHeadBlockRoot(ctx context.Context, blockRoot [32]byte) error
ctx, span := trace.StartSpan(ctx, "BeaconDB.SaveHeadBlockRoot")
defer span.End()
return k.db.Update(func(tx *bolt.Tx) error {
if featureconfig.Get().NewStateMgmt {
if tx.Bucket(stateSummaryBucket).Get(blockRoot[:]) == nil && !k.stateSummaryCache.Has(blockRoot) {
return errors.New("no state summary found with head block root")
if !featureconfig.Get().DisableNewStateMgmt {
hasStateSummaryInCache := k.stateSummaryCache.Has(blockRoot)
hasStateSummaryInDB := tx.Bucket(stateSummaryBucket).Get(blockRoot[:]) != nil
hasStateInDB := tx.Bucket(stateBucket).Get(blockRoot[:]) != nil
if !(hasStateInDB || hasStateSummaryInDB || hasStateSummaryInCache) {
return errors.New("no state or state summary found with head block root")
}
} else {
if tx.Bucket(stateBucket).Get(blockRoot[:]) == nil {
@@ -590,7 +594,10 @@ func createBlockIndicesFromFilters(f *filters.QueryFilter) (map[string][]byte, e
for k, v := range f.Filters() {
switch k {
case filters.ParentRoot:
parentRoot := v.([]byte)
parentRoot, ok := v.([]byte)
if !ok {
return nil, errors.New("parent root is not []byte")
}
indicesByBucket[string(blockParentRootIndicesBucket)] = parentRoot
case filters.StartSlot:
case filters.EndSlot:

Some files were not shown because too many files have changed in this diff Show More