Compare commits

...

128 Commits

Author SHA1 Message Date
Victor Farazdagi
a069738c20 ETH2 Types: Slot (#8408)
* update shared/params

* update eth2-types deps

* update protobufs

* update shared/*

* fix testutil/state

* update beacon-chain/state

* update beacon-chain/db

* update tests

* fix test

* update beacon-chain/core

* update beacon-chain/blockchain

* update beacon-chain/cache

* beacon-chain/forkchoice

* update beacon-chain/operations

* update beacon-chain/p2p

* update beacon-chain/rpc

* update sync/initial-sync

* update deps

* update deps

* go fmt

* update beacon-chain/sync

* update endtoend/

* bazel build //beacon-chain - works w/o issues

* update slasher code

* udpate tools/

* update validator/

* update fastssz

* fix build

* fix test building

* update tests

* update ethereumapis deps

* fix tests

* update state/stategen

* fix build

* fix test

* add FarFutureSlot

* go imports

* Radek's suggestions

* Ivan's suggestions

* type conversions

* Nishant's suggestions

* add more tests to rpc_send_request

* fix test

* clean up

* fix conflicts

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
Co-authored-by: nisdas <nishdas93@gmail.com>
2021-02-16 07:45:34 +00:00
Preston Van Loon
aef5a7b428 Validator: Choose a reasonable cap for the attested target epochs slice (#8452)
* Choose a reasonable cap for the attested target epochs slice

* revert bazelrc

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-02-16 01:37:35 +00:00
terence tsao
4bed8d4ed4 Remove unused core functions (#8449)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-02-15 22:50:50 +00:00
ahadda5
f4a6b90e8b Mask credentials for logging (#8429)
* Added MaskCredentialsLogging to logutil, which masks the user info, path and query. It leaves the hostname and port untouched . Making it more secure during logging

* Added MaskCredentialsLogging to logutil, which masks the user info,path and query. It leaves the hostname and port untouched . Making it more secure during logging

* Added newline based on the PR checks

* Update shared/logutil/logutil.go

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>

* Update shared/logutil/logutil.go

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>

* Gazelle

* Update shared/logutil/logutil.go

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>

* Update shared/logutil/logutil.go

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>

* added unit tests

* updated one test case

* added logutil_test.go unit test cases

* Refactor validator subnet subscriptions to be non-blocking (#8319)

* Use response.NextEpochDuties for aggregator subnet subscriptions (credit: @KaanKC PR #8204). Make committee subnet subscriptions method non-blocking call

* Fix test

* Fix test

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
Co-authored-by: terence tsao <terence@prysmaticlabs.com>

* Add Ability to Specify All Public Keys When Exiting Validators (#8399)

* add programmatic voluntary exit

* add exit all flag

* test

* lint

* add multiple exits test

* fix test

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>

* Increase Validation Queue (#8431)

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>

* Validator: add a DEBUG log to show batch attestation save duration (#8432)

* Add a debug log to show duration

* Autofix issues in 1 file

Resolved issues in validator/db/kv/attester_protection.go via DeepSource Autofix

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
Co-authored-by: deepsource-autofix[bot] <62050782+deepsource-autofix[bot]@users.noreply.github.com>

* Add Mutex and Block Profiling (#8435)

* Implement GetStateRoot in the beacon API (#8402)

* update ethereumapis dependency

* span

* initial implementation

* introduce stategen Service interface and MockService

* Include AddStateForSlot function in the mock service

* return states from mock

* add GenesisState to POWChain mock

* populate roots in helper state

* initialize Slot when creating helper state

* tests

* code refactor - extract helper functions

* gzl

* use SetSlot in tests

* handle SetSlot error

* use new testutil's NewBeaconState

* gzl

* go mod tidy

* rename Service to StateManager

* move regex check to helper

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>

* On Block Cleanup (#8438)

* Beacon API: update GetStateRoot  (#8437)

* Address various feedbacks

* Gaz

* More nil check

* Update beacon-chain/rpc/beaconv1/state_test.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* Update beacon-chain/rpc/beaconv1/state_test.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* Update beacon-chain/rpc/beaconv1/state_test.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* Update beacon-chain/rpc/beaconv1/state_test.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* Update beacon-chain/rpc/beaconv1/state_test.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* qualifying my unix user ahaddad - no real changes to the files

* Update shared/logutil/logutil.go

* Update shared/logutil/logutil.go

* Update shared/logutil/logutil.go

* Update shared/logutil/logutil.go

* Update shared/logutil/logutil.go

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>
Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: Nishant Das <nishdas93@gmail.com>
Co-authored-by: deepsource-autofix[bot] <62050782+deepsource-autofix[bot]@users.noreply.github.com>
Co-authored-by: Radosław Kapka <rkapka@wp.pl>
2021-02-15 21:54:19 +00:00
Raul Jordan
36b6a71af4 Configurable DB Mmap Size for Beacon Node and Validator Client (#8448)
* add flag to beacon and validator

* gaz

* fuzz

* add dep viz

* add to tools
2021-02-15 20:29:47 +00:00
Raul Jordan
7c3827a9a4 add test (#8444) 2021-02-15 11:55:28 -06:00
Potuz
d17f210024 Log Block Processing Time (#8441)
* Log Block Processing Time instead of time in slot

* Restore timeSinceSlotStart

* Renamed fields

Co-authored-by: terence tsao <terence@prysmaticlabs.com>
2021-02-15 10:33:38 -06:00
terence tsao
28631e7791 Verify nil block helper (#8447) 2021-02-15 15:11:25 +00:00
terence tsao
28839fbab2 Use latest block header + slot as skip slot cache key (#8443) 2021-02-13 23:13:20 +00:00
Radosław Kapka
0716519be9 Fix error formatting inside fmt.Errorf (#8439)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-02-12 23:44:46 +00:00
terence tsao
068f758f49 Code inspect - clean ups (#8445) 2021-02-12 17:04:45 -06:00
Preston Van Loon
e2c5ae53e7 Validator: Safer pending attestation records flushing (#8433)
* Add a debug log to show duration

* merge from dev

* use safe pending attestation records struct

* fix build, use atomic bool

* Add deadline checks to CheckSlashableAttestation

* Go fmt

* Add test for in-progress log

* GoDocs

* Rename pending attestation records to queued attestation records

* rename and add commentary on log

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-02-12 20:19:01 +00:00
Preston Van Loon
473172ca8b Validator: Make read operation use db.view instead of db.update (#8434)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-02-12 19:06:58 +00:00
Radosław Kapka
47fdb3b99a Revert "Rename NewService to New (#8337)" (#8440)
* Revert "Rename `NewService` to `New` (#8337)"

This reverts commit d121b19145.

# Conflicts:
#	beacon-chain/sync/initial-sync/round_robin_test.go

* fix name in test

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-02-12 17:45:22 +00:00
terence tsao
143d3a3203 Process attestation: skip if forkchoice attestation count == 0 (#8436)
* Cont. if there's no fork choice attestations

* Comment

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: Victor Farazdagi <simple.square@gmail.com>
2021-02-12 17:11:42 +00:00
terence tsao
66471c2f13 Beacon API: update GetStateRoot (#8437)
* Address various feedbacks

* Gaz

* More nil check

* Update beacon-chain/rpc/beaconv1/state_test.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* Update beacon-chain/rpc/beaconv1/state_test.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* Update beacon-chain/rpc/beaconv1/state_test.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* Update beacon-chain/rpc/beaconv1/state_test.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* Update beacon-chain/rpc/beaconv1/state_test.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
2021-02-12 15:38:36 +00:00
Nishant Das
7f6b15271a On Block Cleanup (#8438) 2021-02-12 11:36:53 +00:00
Radosław Kapka
cbb0f1e11d Implement GetStateRoot in the beacon API (#8402)
* update ethereumapis dependency

* span

* initial implementation

* introduce stategen Service interface and MockService

* Include AddStateForSlot function in the mock service

* return states from mock

* add GenesisState to POWChain mock

* populate roots in helper state

* initialize Slot when creating helper state

* tests

* code refactor - extract helper functions

* gzl

* use SetSlot in tests

* handle SetSlot error

* use new testutil's NewBeaconState

* gzl

* go mod tidy

* rename Service to StateManager

* move regex check to helper

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-02-11 21:08:36 +00:00
Raul Jordan
25caa6d1be Add Mutex and Block Profiling (#8435) 2021-02-11 20:20:19 +00:00
Preston Van Loon
d551c8e1d0 Validator: add a DEBUG log to show batch attestation save duration (#8432)
* Add a debug log to show duration

* Autofix issues in 1 file

Resolved issues in validator/db/kv/attester_protection.go via DeepSource Autofix

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
Co-authored-by: deepsource-autofix[bot] <62050782+deepsource-autofix[bot]@users.noreply.github.com>
2021-02-11 18:27:35 +00:00
Nishant Das
2fd2bafdfa Increase Validation Queue (#8431)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-02-11 17:35:52 +00:00
Raul Jordan
e236dedc32 Add Ability to Specify All Public Keys When Exiting Validators (#8399)
* add programmatic voluntary exit

* add exit all flag

* test

* lint

* add multiple exits test

* fix test

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-02-11 16:50:16 +00:00
Preston Van Loon
7d2f7ae9e1 Refactor validator subnet subscriptions to be non-blocking (#8319)
* Use response.NextEpochDuties for aggregator subnet subscriptions (credit: @KaanKC PR #8204). Make committee subnet subscriptions method non-blocking call

* Fix test

* Fix test

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
Co-authored-by: terence tsao <terence@prysmaticlabs.com>
2021-02-11 16:09:17 +00:00
Nishant Das
ed9c69ec61 Use a Slim Base Image for our Cross-Build Toolchain Docker Image (#8425)
* change it to slim

* update

* Ran regenerate.sh

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
2021-02-11 03:03:15 +00:00
Ivan Martinez
b6a40094a6 Exclude unexported fields for protos in sszutils.DeepEqual (#8415)
* Fix deep equal

* Fixes

* gaz

* Fix test

* Add UnexportedOnly function

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-02-10 23:00:18 +00:00
terence tsao
de15d6d2c1 Some improvements to proposer cache (#8424)
* Revert to use input epoch

* Revert back to process epoch

* Use processed state

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-02-10 22:07:12 +00:00
Nishant Das
143cb142bc Make Individual Validators Immutable (#8397)
* initial POC

* clean up

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-02-10 20:52:45 +00:00
terence tsao
d3e93dd106 Process attestation: reduce checkpoint copies (#8409)
* Clean up process attestation

* Add matching getters

* Fix tests

* Update tests

* Fix test

* Remove read locks

* Typo

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-02-10 19:30:11 +00:00
terence tsao
56c5938898 Send feed faster with UpdateHeadTimely feature flag (#8422)
Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-02-10 18:26:23 +00:00
terence tsao
d44ab1ace5 Add timeSinceSlotStart field to "Synced new block..." log (#8420)
Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-02-10 17:24:40 +00:00
Nishant Das
ae028d9c1d Insert Finalized Deposits In Another Routine (#8405)
* chk

* terence's review

* add test

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-02-10 10:35:44 -06:00
Preston Van Loon
cbd01d4ff4 Provide TLS certificate to gRPC gateway (#8418)
* Provide TLS certificate to gRPC gateway

* Provide TLS certificate to gRPC gateway

* Provide TLS certificate to gRPC gateway

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-02-10 04:23:12 +00:00
Victor Farazdagi
65645face1 Update ethereumapis deps (#8417)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-02-10 03:33:33 +00:00
Ivan Martinez
cd3851c3d5 Add DeepSSZEqual and DeepNotSSZEqual (#8421) 2021-02-09 20:57:22 +00:00
terence tsao
2f98e6aaaf Update head per slot (#8381)
Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-02-09 17:24:48 +00:00
terence tsao
9afc9d92d9 Feature flag: update head timely (#8412)
* Feature flag: update head timely

* Move finalized imply justified up

* Fix resolve error

* Use invert feature flag

* Make diff easier to review

* Line

* Typo

* Fix condition

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-02-09 15:35:14 +00:00
Victor Farazdagi
a8e501b3cf ETH2 Types: Epoch (#8373)
* update deps

* update deps

* update protos/*

* update deps

* reset protos

* update protos

* update shared/params/config

* update protos

* update /shared

* update shared/slotutil and shared/testutil

* update beacon-chain/core/helpers

* updates beacon-chain/state

* update beacon-chain/forkchoice

* update beacon-chain/blockchain

* update beacon-chain/cache

* update beacon-chain/core

* update beacon-chain/db

* update beacon-chain/node

* update beacon-chain/p2p

* update beacon-chain/rpc

* update beacon-chain/sync

* go mod tidy

* make sure that beacon-chain build suceeds

* go fmt

* update e2e tests

* update slasher

* remove redundant alias

* update validator

* gazelle

* fix build errors in unit tests

* go fmt

* update deps

* update fuzz/BUILD.bazel

* fix unit tests

* more unit test fixes

* fix blockchain UTs

* more unit test fixes
2021-02-09 10:05:22 +00:00
Preston Van Loon
5727d4eb8a Update Herumi with a fix for older intel chips (#8413)
* Update Herumi with a fix for older intel chips. #8410

* Use the correct version of bls-eth-go-binary
2021-02-09 01:44:27 +00:00
terence tsao
fed65122fe Use EnableNextSlotStateCache few more places (#8398) 2021-02-08 13:11:21 -08:00
Radosław Kapka
86a9d4c6a4 Configurable testutil's BeaconState (#8407)
* Configurable testutil's BeaconState

* fix shared and fuzz tests

* return state copy

* use mainnet config values for default state

* handle error in block fuzz

* goimports

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-02-08 20:00:09 +00:00
Panagiotis Georgiadis
0a180dc662 Make a const instead of 3 'abc' occurences (#8406) 2021-02-08 17:08:29 +01:00
terence tsao
f9303ca2e4 Clean up unused functions (#8403)
* Clean ups

* Gazelle
2021-02-05 18:39:15 +00:00
terence tsao
4c25fe978a Update span names (#8394)
Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-02-04 20:23:50 +00:00
terence tsao
cf88afb287 Block validator buckets (#8395)
* Block validator buckets

* add more buckets to blocked collector list

Co-authored-by: rauljordan <raul@prysmaticlabs.com>
2021-02-04 03:30:09 +00:00
Victor Farazdagi
c97ea766ca Attestation aggregation: optimizations and benchmarks (#7938)
* profitablity tests

* cleanup benchmark

* fix deduplication function

* dedup: move method to atts list

* proper substring handling

* refactor validate method

* update benchmarks

* prepare proposer test

* remove redundant code

* reset test

* remove dedup from maxcover - moved to proposer

* remove redundant test

* remove lower level check for bit length

* optimize candidate validation on att aggregation

* restore test

* fix test

* fix test

* remove dedup functionality

* add benchmark

* optimize list usage

* Attestation aggregration: remove redundant dedup routine

* fix func call

* experiment with bitset based cover

* add benchmark

* samplem implementation using Bilist64

* add tests

* remove redundant code

* remove tmp comments

* unskip test

* update benchmarks

* gazelle

* process err

* optimized max-cover

* Max-cover: optimized implementation based on Bitlist64

* gazelle

* re-arrange overlaps check

* minor comments

* add Bitlists64WithMultipleBitSet

* update benchmarks

* gazelle

* add TestAggregateAttestations_rearrangeProcessedAttestations

* minor updates to rearrange method

* add link to design doc

* remove redundant methods

* simplify test

* add TestAggregateAttestations_aggregateAttestations

* fix issues

* fix assignment

* use ToBitlist(), ToBitlist64()

* fixes test

* benchmarks

* fix typo

* allow opt_max_cover opt-int flag

* update benchmarks

* reset e2e

* fix test

* enable opt_max_cover in e2e tests

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-02-04 00:58:33 +00:00
Preston Van Loon
e52a821f73 Validator testing library should be marked as testonly (#8392)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-02-03 23:16:41 +00:00
Nishant Das
d4f241d875 Add Custom Deadline for Slot Progression (#8388)
* use custom deadline

* revert

* preston's comment

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-02-03 21:39:54 +00:00
Preston Van Loon
48ae49765e Revert "Change sszutil DeepEqual to ignore unexported fields" (#8391)
* Revert "Change sszutil DeepEqual to ignore unexported (#8336)"

This reverts commit 8d986bd414.

* Add back tests, make tests have equal and non equal check

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-02-03 20:39:07 +00:00
Raul Jordan
afa5b5e790 Add Spans for Validator DB Methods (#8390)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-02-03 19:29:20 +00:00
Preston Van Loon
c5551ebebb Revert DEPENDENCIES.md change from #8257 (#8389) 2021-02-03 18:46:46 +00:00
terence tsao
616081fbdd Ran code inspect (#8387) 2021-02-03 10:59:17 -06:00
Victor Farazdagi
842bafb002 Update bitfield dependency (#8385) 2021-02-02 21:33:48 +00:00
Raul Jordan
953cc9733c Update Ethdo Keystore Deps (#8382)
* update ethdo deps

* revert workspace

* tidy
2021-02-02 19:05:47 +00:00
Raul Jordan
caac08df33 Add Batch Method for Reading Validator Proposing Histories (#8378)
* add in batch method

* add in new proposal history methods for efficiency and progress bars

* tests fixed to use the new methods

* add back get slot proposing history method

* add gaz
2021-02-02 15:53:12 +00:00
Radosław Kapka
3fd8c4c046 Implement GetGenesis in the beacon API (#8380)
* span

* initial implementation

* test wip

* set nanos to zero

* more testing

* gzl
2021-02-02 08:44:28 -06:00
Radosław Kapka
b5a82b9075 Display URLs for tracking exited validators (#8361)
* Display URLs for tracking exited validators

* extract displaying info to separate function

* fix URL comment

* extract config names

* gzl

* lowercase config names

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-02-01 19:00:06 +00:00
Nishant Das
c6e96204e8 Update Herumi BLS Library (#8377)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-02-01 18:31:48 +00:00
terence tsao
2456e6f34d Add missed feature flag usage (#8376)
Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-02-01 17:42:50 +00:00
Radosław Kapka
48ed506487 Ajust constructor names of nodes (#8362)
* clean up constructors for nodes

* resurrect validator client

* fix small naming issues

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-02-01 17:12:52 +00:00
Shay Zluf
4595789ac8 Make validator stable when beacon node goes offline (#8278)
* Make validator stable POC

* fix feedback raul and nishant

* fix wait till first iteration

* fix imports

* retry tests

* fix init

* test retry receive blocks

* remove redundant return statement

* terence feedback

* terence feedback

* remove log

* to check for context after fist call

* remove fatal

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-02-01 16:29:54 +00:00
Victor Farazdagi
d53fdcf781 Simplify expressions (#8370)
* Simplify expressions

* avoid escaping

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-02-01 15:14:36 +00:00
Victor Farazdagi
372dc47b64 Deprecate enableSyncBacktracking flag (#8371)
* Deprecate enableSyncBacktracking flag

* keep deprecated flags
2021-02-01 11:18:24 +00:00
pinglamb
82426abf5f Add canonical flag to ListBlocks API response (#8287)
* Add canonical flag to ListBlocks response

* Genesis is always canonical
2021-02-01 04:33:17 +00:00
terence tsao
f5f1284cef Remove unused feature flag config fields (#8363)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-01-30 15:16:31 +00:00
terence tsao
609418ecd3 Update README.md (#8366)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-01-30 14:28:27 +00:00
Radosław Kapka
f20c9122e8 Remove unused channel from Powchain Service (#8368)
* Remove unused header channel

* test fix

Co-authored-by: terence tsao <terence@prysmaticlabs.com>
2021-01-30 13:33:52 +00:00
Ivan Martinez
afc3b3168a Add Back Accounts Backup Validator RPC Functionality (#8367)
* Add Back Accounts Backup Validator RPC Functionality

This reverts commit a39db494eb.

* Fix
2021-01-29 18:30:44 -06:00
Victor Farazdagi
902c30e389 Update bitfield dependency (#8364) 2021-01-29 19:58:26 +00:00
terence tsao
3aaa98decf Next slot state caching (#8357)
* Add and use trailing slot state cache

* Remove comment

* Update comments

* Update comments

* Move it to background

* Warn is more appropiate

* Raul's comment

* Same strategy for proposer

* Own helper

* Minor touchups

* Tests

* Feature flag

* Gaz
2021-01-29 16:52:43 +00:00
Ivan Martinez
e592cd7a80 Add wallet file flag to edit-config command (#8360) 2021-01-29 09:32:15 +00:00
Nishant Das
b74dd967af Bind Discovery Using Neutral Network Version (#8359)
* fix it

* terence's review
2021-01-29 15:07:32 +08:00
Victor Farazdagi
d254f24a23 Update bitfield dependency (#8356) 2021-01-29 00:39:29 +00:00
Radosław Kapka
8d505e06bd Implement GetForkSchedule in the config API (#8345)
* span

* update ethereumapis

* implementation + tests

* typo

* fix variable shadowing

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-01-28 13:44:23 -06:00
Victor Farazdagi
09b1e06885 Max-cover: optimized implementation based on Bitlist64 (#8352)
* Max-cover: optimized implementation based on Bitlist64

* gazelle

* re-arrange overlaps check

* minor comments

* add Bitlists64WithMultipleBitSet

* update benchmarks

* gazelle

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-01-28 15:55:02 +00:00
Radosław Kapka
d9c451d547 Introduce helper function for adding context metadata from gRPC headers (#8354)
* implement helper

* use helper function everywhere

* add unit tests

* small cleanup of the helper

* small fixes

* gazellelelele

* fix helper tests
2021-01-28 08:58:32 -06:00
Radosław Kapka
e677b19d31 Implement GetSpec in the config API (#8328)
* Implement GetSpec in the config API

* extract map creation

* fix deepsource compliant

* Revert "fix deepsource compliant"

This reverts commit 0c99310cc9.

* use struct tags for api map keys

* remove log

* use spec tag

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-01-28 00:30:48 +00:00
terence tsao
2bf03d5cba Use strings builder for attester lock key (#8349)
* Use strings builder

* Handle error
2021-01-27 22:33:28 +00:00
terence tsao
0753636159 Add role based lock for validator (#8347) 2021-01-27 20:59:21 +00:00
terence tsao
b8037b0b50 Wait for one third before grabbing the lock (#8348) 2021-01-27 12:06:18 -06:00
Tushar Shah
2f063d0ddc process grpc header flag for exit (#8334)
* process grpc header flag for exit

* ran bazel //:gazelle

* Add regression test

* Re-run "bazel run //:gazelle"

* whitespace

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>

* gofmt

Co-authored-by: Danny Joyce <djoyce@bisontrails.co>
Co-authored-by: Danny Joyce <djoyahoy@users.noreply.github.com>
Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-01-27 13:12:48 +00:00
terence tsao
1cfae7e098 More blockchain pkg tests (#8343)
* Add more blockchain pkg tests

* Deepsource feedback

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-01-26 20:27:34 -06:00
terence tsao
91fe32a3d1 Handle subscriber error (#8341) 2021-01-26 13:56:24 -06:00
terence tsao
c0fda583e7 Update seen att slashing cache to use map (#8332)
* Hide beacon operation field if it's 0

* Use map as seen slashing cache

* Revert "Hide beacon operation field if it's 0"

This reverts commit 896fa11a0b.

* Rm unused code

* Gaz

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-01-26 17:24:34 +00:00
Nishant Das
9f62405a81 Update Prombolt Collector (#8339)
* update

* block big buckets

* add more buckets

* patch go.mod

* clean up

* Update beacon-chain/db/kv/kv.go

Co-authored-by: Victor Farazdagi <simple.square@gmail.com>
Co-authored-by: terence tsao <terence@prysmaticlabs.com>
2021-01-26 15:32:46 +00:00
terence tsao
d121b19145 Rename NewService to New (#8337)
* Hide beacon operation field if it's 0

* Rename NewSerivce to New

* Revert "Hide beacon operation field if it's 0"

This reverts commit 896fa11a0b.

* Fix NewServiceRegistry

* Update slasher/detection/service.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-01-26 10:26:57 +00:00
Radosław Kapka
a7345c1094 Implement GetDepositContract in the config API (#8316)
* Add funnction to retrieve deposit contract's address from powchain

* change bytes.Equal to assert.DeepEqual

* add DepositContractAddress to mocks

* Extract powchain info to a separate struct

* span

* Revert "Extract powchain info to a separate struct"

This reverts commit e01dd5222b.

* implementation + test

* use the correct hexutil library

* read contract address from configuration

* return ETH1 chain ID instead of fork version

* gzl (I hate you)

* remove unused ChainInfoFetcher

Co-authored-by: terence tsao <terence@prysmaticlabs.com>
2021-01-26 09:37:22 +00:00
Victor Farazdagi
db79481c21 Update bitfield dependency (#8338) 2021-01-26 08:35:16 +00:00
Ivan Martinez
8d986bd414 Change sszutil DeepEqual to ignore unexported (#8336) 2021-01-25 17:52:41 -06:00
Radosław Kapka
c827672a30 Rename non-generated files ending with '_mock' (#8317)
* rename *_mock files

* bzl

* rename faulty_mock_powchain

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-01-25 22:30:55 +00:00
terence tsao
d5ec248691 Rename getter functions to be idiomatic (#8320)
* Rename getter functions

* Rename new

* Radek's feedback

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-01-25 21:27:30 +00:00
Nishant Das
b2d6012371 Fix IPV6 binding for Beacon Node (#8326)
Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-01-25 20:10:41 +00:00
Radosław Kapka
d21365b882 Remove test assertion that reads a package-level variable (#8329)
* remove checking value of shared variable

* fix deepsource compliant

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-01-25 18:27:59 +00:00
Nishant Das
1c43ea9e69 Update the Toolchain Registration (#8322)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-01-25 16:46:27 +00:00
Radosław Kapka
fc8dc21aa2 Cancel node context after StopAll (#8289)
* cancel node context after StopAll

* build fix

* cancel in validator

Co-authored-by: Victor Farazdagi <simple.square@gmail.com>
Co-authored-by: terence tsao <terence@prysmaticlabs.com>
2021-01-25 09:57:21 -06:00
Nishant Das
7f5ffb7dd1 Fix Deadlock in Runtime (#8321)
* fix deadlock

* fix

* Satisfy Deepsource

* fmt
2021-01-25 11:01:55 +08:00
Raul Jordan
92932ae58e [Feature] - Slashing Interchange Support (#8024)
* Change LowestSignedProposal to Also Return a Boolean for Slashing Protection (#8020)

* amend to use bools

* ineff assign

* comment

* Update `LowestSignedTargetEpoch` to include exists (#8004)

* Replace highest with lowerest

* Update validator/db/kv/attestation_history_v2.go

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>

* Update validator/db/kv/attestation_history_v2.go

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>

* Invert equality for saveLowestSourceTargetToDB

* Add eip checks to ensure epochs cant be lower than db ones

* Should be less than equal to

* Check if epoch exists in DB getters

* Revert run time checks

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>

* Export Attesting History for Slashing Interchange Standard (#8027)

* added in att history checks

* logic for export

* export return nil

* test for export atts

* round trip passes first try!

* rem println

* fix up tests

* pass test

* Validate Proposers Are Not Slashable With Regard to Data Within Slasher Interchange JSON (#8031)

* filter slashable blocks and atts in same json stub

* add filter blocks func

* add test for filtering out the bad public keys

* Export Slashing Protection History Via CLI (#8040)

* include cli entrypoint for history exports

* builds properly

* test to confirm we export the data as expected

* abstract helpers properly

* full test suite

* gaz

* better errors

* marshal ident

* Add the additional eip-3076 attestation checks (#7966)

* Replace highest with lowerest

* Update validator/db/kv/attestation_history_v2.go

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>

* Update validator/db/kv/attestation_history_v2.go

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>

* Invert equality for saveLowestSourceTargetToDB

* Add eip checks to ensure epochs cant be lower than db ones

* Should be less than equal to

* Check if epoch exists in DB getters

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>

* Add EIP-3076 Invariants for Proposer Slashing Protection (#8067)

* add invariant for proposer protection

* write different test cases

* pass tests

* Add EIP-3076 Interchange JSON CLI command to validator (#7880)

* Import JSON CLI

* CLI impotr

* f

* Begin adding new commands in slashing protection

* Move testing helpers to separate packae

* Add command for importing slashing protection JSONs

* fix import cycle

* fix test

* Undo cleaning changes

* Improvements

* Add better prompts

* Fix prompt

* Fix

* Fix

* Fix

* Fix conflict

* Fix

* Fixes

* Fixes

* Fix exported func

* test func

* Fixes

* fix test

* simplify import and standardize with export

* add round trip test

* true integration test works

* fix up comments

* logrus

* better error

* fix build

* build fix

* Update validator/slashing-protection/cli_export.go

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>

* Update validator/slashing-protection/cli_import.go

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>

* fmt

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>

* Filter Slashable Attester Public Keys in Slashing Interchange Import (#8051)

* filter slashable attesters from the same JSON

* builds

* fix up initially broken test

* circular dep

* import fix

* giz

* added in attesting history package

* add test for filter slashable attester keys

* pass tests

* Save Slashable Keys to Disk in the Validator Client (#8082)

* begin db funcs

* add in test and bucket

* gaz

* rem changes to import

* ineff assign

* add godoc

* Properly Handle Duplicate Public Key Entries in Slashing Interchange Imports (#8089)

* Prevent Blacklisted Public Keys from Slashing Protection Imports from Having Duties at Runtime (#8084)

* tests on update duties

* ensure the slashable public keys are filtered out from update duties via test

* begin test

* attempt test

* rename for better context

* pass tests

* deep source

* ensure tests pass

* Check for Signing Root Mismatch When Submitting Proposals and Importing Proposals in Slashing Interchange (#8085)

* flexible signing root

* add test

* add tests

* fix test

* Preston's comments

* res tests

* ensure we consider the case for minimum proposals

* pass test

* tests passing

* rem unused code

* Set Empty Epochs in Between Attestations as FAR_FUTURE_EPOCH in Attesting History (#8113)

* set target data

* all tests passing

* ineff assign

* signing root

* Add Slashing Interchange, EIP-3076, Spec Tests to Prysm (#7858)

* Add interchange test framework

* add checks for attestations

* Import genesis root if necessary

* flexible signing root

* add test

* Sync

* fix up test build

* only 3 failing tests now

* two failing

* attempting to debug problems in conformity tests

* include latest changes

* protect test in validator/client passing

* pass tests

* imports

* spec tests passing with bazel

* gh archive link to spectests using tar.gz suffix

* rev

* rev more comment changes

* fix sha

* godoc

* add back save

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>

* Implement Migration for Unattested Epochs in Attesting History Database (#8121)

* migrate attesting history backbone done

* begin migration logic

* implement migration logic

* migration test

* add test

* migration logic

* bazel

* migration to its own file

* Handle empty blocks and attestations in interchange json and sort interchange json by public key (#8132)

* Handle empty blocks and attestations in interchange json

* add test

* sort json

* easier empty arrays

* pass test

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>

* builds

* more tests finally build

* Align Slashing Interchange With Optimized Slashing Protection (#8268)

* attestation history should account for multiple targets per source

* attempt at some fixes

* attempt some test fixes

* experimenting with sorting

* only one more failing test

* tests now pass

* slash protect tests passing

* only few tests now failing

* only spec tests failing now

* spec tests passing

* all tests passing

* helper function for verifying double votes

* use helper

* gaz

* deep source

* tests fixed

* expect specific number of times for domain data calls

* final comments

* Batch Save Imported EIP-3076 Attestations (#8304)

* optimize save

* test added

* add test for sad path

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>

* revert bad find replace

* add comment to db func

Co-authored-by: terence tsao <terence@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
Co-authored-by: Ivan Martinez <ivanthegreatdev@gmail.com>
Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
Co-authored-by: Shay Zluf <thezluf@gmail.com>
2021-01-22 17:12:22 -06:00
Radosław Kapka
8ffb95bd9d Allow dynamic key reloading when having inactive keys (imported & derived) (#8119)
* restart waiting for activation on key change

* test fixes

* wiat for activation comments

* regression test

* log fatal when validator cast fails

* derived keymanager

* review comments

* add buffer to channel

* simplify key refetch logic

* reload keys into empty wallet

* removed warning on wallet creation

* add empty line

* export AccountsKeystoreRepresentation type

* unit test for handleAccountsChanged

* test ctx cancellation

* add missing mockRemoteKeymanager interface function

* gazelle

* gzl

* fix panic inside goroutine during runner tests

* rename error message variables

* Update validator/accounts/accounts_list_test.go

* reorder imports

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
2021-01-22 20:21:34 +00:00
terence tsao
229abed848 Test for processAttestations (#8312)
* Add a test for processAttestations

* Log should not contrain could not process attestation...

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-01-22 18:08:16 +00:00
terence tsao
c5e9b1ec9e Refactor verifyAttestationIndices method (#8309)
* Refactor verifyAttestationIndices

* Conflict

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-01-22 17:15:49 +00:00
Radosław Kapka
7842fd9da6 Replace bytes.Equal with assert.DeepEqual in tests (#8318)
* beacon chain

* format imports

* Update beacon-chain/db/kv/migration_archived_index_test.go

Co-authored-by: Victor Farazdagi <simple.square@gmail.com>

* Update beacon-chain/db/kv/migration_block_slot_index_test.go

Co-authored-by: Victor Farazdagi <simple.square@gmail.com>

* remove unused imports

* Update beacon-chain/core/state/skip_slot_cache_test.go

Co-authored-by: Victor Farazdagi <simple.square@gmail.com>

* Update beacon-chain/core/state/skip_slot_cache_test.go

Co-authored-by: Victor Farazdagi <simple.square@gmail.com>

* Update beacon-chain/core/state/skip_slot_cache_test.go

Co-authored-by: Victor Farazdagi <simple.square@gmail.com>

* Update beacon-chain/core/state/skip_slot_cache_test.go

Co-authored-by: Victor Farazdagi <simple.square@gmail.com>

* Update beacon-chain/db/kv/migration_archived_index_test.go

Co-authored-by: Victor Farazdagi <simple.square@gmail.com>

* Update beacon-chain/db/kv/migration_block_slot_index_test.go

Co-authored-by: Victor Farazdagi <simple.square@gmail.com>

Co-authored-by: Victor Farazdagi <simple.square@gmail.com>
2021-01-22 15:15:40 +00:00
Victor Farazdagi
75fc3b045b Max-cover: minor optimizations (#8311)
* Max-cover: minor optimizations

* fix test
2021-01-22 20:10:50 +08:00
Nishant Das
50e5b1b4f5 fix deposit index metrics (#8315) 2021-01-22 19:11:02 +08:00
Preston Van Loon
33e266388f GetDuties: Refactor assignment status to deduplicate status computation (#8313) 2021-01-21 14:22:05 -08:00
terence tsao
2586be29ac Refactor on_attestation return signature (#8310)
* Update func on_attestation's return signature

* Add return
2021-01-21 18:38:51 +00:00
Radosław Kapka
9cc1438ea9 Peer count node api (#8306)
Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-01-21 16:16:56 +00:00
Victor Farazdagi
6e643aca12 Attestation aggregation: baseline benchmark (#8308)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-01-21 14:29:17 +00:00
Nishant Das
cc5a847eeb update to v1.15.7 (#8307) 2021-01-21 21:27:57 +08:00
Raul Jordan
241322a7c1 Safe Math for ETH1 Batch Headers Request (#8253)
* batch request underflow checks

* Update beacon-chain/powchain/service.go

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>

* return error

* Update beacon-chain/powchain/service.go

Co-authored-by: Nishant Das <nishdas93@gmail.com>

* test

* Apply suggestions from code review

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>

Co-authored-by: Nishant Das <nishdas93@gmail.com>
Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-01-21 09:19:44 +00:00
Victor Farazdagi
d697b0b2e5 Update bitfield dependency (#8305) 2021-01-21 08:28:57 +00:00
Preston Van Loon
9ec4f727c6 Remove unnecessary state copy (#8303) 2021-01-20 20:00:01 -06:00
terence tsao
ffcadcf184 Rm forkchoice attestation verification (#8301)
* Rm fork choice attestation sig verification

* Unit test

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-01-20 21:46:13 +00:00
Ivan Martinez
7c59615ae2 Remove go-ssz entirely from prysm (#8257)
* Add DepositSigningData

* gaz

* Add to ssz tests

* Rename to DepositMessage

* Remove deprecated comment

* Remove return

* Fixes from review

* Fixes

* Remove some of gossz

* Remove go-ssz entirely

* Remove unneeded file

* Fix runtime with ssztypes

* Add back ssz files

* Fix formatting

* tidy

* Remove go-ssz from static

* tidy again

* Add tests

* Change to sig

* Fix test

* fx

* Fix visiblity

* Revert "Remove unneeded file"

This reverts commit d66fcda929.

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-01-20 21:03:46 +00:00
Preston Van Loon
d6cccc18c3 verifyDepositDataWithDomain: Use helpers.ComputeSigningRoot (#8302) 2021-01-20 20:30:58 +00:00
terence tsao
befe8d88b8 Remove duplicated target root check for fork choice attestation (#8277)
* Rm redundant target root check for fork choice attestation

* Comments

* Revert back verifyBeaconBlock

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-01-20 18:27:10 +00:00
Radosław Kapka
153737803a Implement ListPeers in the node API (#8288)
* add span

* update ethereumapis

* align server with ethereumapis

* benchmark

* naive implementation

* rename two status functions

* new Inbound and Outbound status functions

* tests

* 'enr:' prefix

* refactoring

* gzl

* case when one filter is empty

* empty filter condition fix

* deepsource

* rename getPeer to peerInfo

* bring back correct version of ethereumapis

* go mod tidy
2021-01-20 15:52:33 +00:00
Radosław Kapka
4b14fa4317 Better receiver names in validator and slasher modules (#8296)
* validator

* slasher

* rename db to s for store

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-01-20 14:39:07 +00:00
Victor Farazdagi
27847ee2fe Update bitfield dependency (#8299) 2021-01-20 13:39:54 +00:00
terence tsao
578dabe27c Remove duplicated LMD FFG check for fork choice attestation (#8276)
* Rm redundant lmd<->ffg check for fork choice attestation

* Comments

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: Nishant Das <nishdas93@gmail.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-01-20 10:19:43 +00:00
Victor Farazdagi
ed2c0a3e5e Update bitfield dependency (#8295) 2021-01-20 06:55:53 +00:00
terence tsao
5d841874f7 Return error on AttestingIndices bitfield length check (#8285)
* Return error on committee len check

* AttestingIndices unit test

* Add equality check

* Fixing more tests

* Fix rest of the tests

* Fix invalid bit length test

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-01-20 03:00:52 +00:00
terence tsao
ab9d596a5f Update fastssz (#8291)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-01-19 23:48:22 +00:00
terence tsao
084e5bd020 Add test TestStore_OnAttestation_Ok (#8293)
* Add test TestStore_OnAttestation_Ok

* Handle errors

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-01-19 23:10:10 +00:00
terence tsao
bc2c206832 Add verify slot target epoch function and apply all (#8273)
* Add verify slot target epoch function and apply all

* Fix TestProcessAttestationsNoVerify_IncorrectSlotTargetEpoch

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-01-19 21:41:44 +00:00
Preston Van Loon
655a7e98c3 Stamp binaries by default (#8292) 2021-01-19 20:43:30 +00:00
Radosław Kapka
f89fd67952 Better receiver names in beacon chain module (#8286) 2021-01-19 13:21:32 +00:00
Nishant Das
20b836d038 Add Initial Support For Gossip Scoring Service (#8275)
* checkpoint progress

* gaz

* fix

* add it in

* Update beacon-chain/p2p/pubsub.go

* fmt

* reformat imports

Co-authored-by: Victor Farazdagi <simple.square@gmail.com>
2021-01-19 12:13:08 +00:00
Preston Van Loon
b33a8eb59f Revert "Use remote cache in CI" (#8281)
This reverts commit 8b6abcbf0c.
2021-01-19 01:55:00 +00:00
Preston Van Loon
8b6abcbf0c Use remote cache in CI (#8280)
* Use remote cache in CI

* Update .buildkite-bazelrc

* Update .buildkite-bazelrc
2021-01-18 22:22:37 +00:00
671 changed files with 16718 additions and 7518 deletions

View File

@@ -17,9 +17,12 @@ test --host_force_python=PY2
run --host_force_python=PY2
# Networking is blocked for tests by default, add "requires-network" tag to your test if networking
# is required within the sandbox. This flag is no longer experimental after 0.29.0.
# Network sandboxing only works on linux.
--experimental_sandbox_default_allow_network=false
# is required within the sandbox. Network sandboxing only works on linux.
build --sandbox_default_allow_network=false
# Stamp binaries with git information
build --workspace_status_command=./scripts/workspace_status.sh
build --stamp
# Use mainnet protobufs at runtime
run --define ssz=mainnet
@@ -48,8 +51,6 @@ build:blst_enabled --define blst_enabled=true
build:blst_enabled --define gotags=blst_enabled
# Release flags
build:release --workspace_status_command=./scripts/workspace_status.sh
build:release --stamp
build:release --compilation_mode=opt
build:release --config=llvm

View File

@@ -5,7 +5,7 @@
[![ETH2.0_Spec_Version 1.0.0](https://img.shields.io/badge/ETH2.0%20Spec%20Version-v1.0.0-blue.svg)](https://github.com/ethereum/eth2.0-specs/tree/v1.0.0)
[![Discord](https://user-images.githubusercontent.com/7288322/34471967-1df7808a-efbb-11e7-9088-ed0b04151291.png)](https://discord.gg/CTYGPUJ)
This is the core repository for Prysm, a [Golang](https://golang.org/) implementation of the Ethereum 2.0 specification, developed by [Prysmatic Labs](https://prysmaticlabs.com).
This is the core repository for Prysm, a [Golang](https://golang.org/) implementation of the [Ethereum 2.0](https://ethereum.org/en/eth2/) specification, developed by [Prysmatic Labs](https://prysmaticlabs.com). See the [Changelog](https://github.com/prysmaticlabs/prysm/releases) for details of the latest releases and upcoming breaking changes.
### Getting Started
@@ -13,15 +13,15 @@ A detailed set of installation and usage instructions as well as breakdowns of e
### Staking on Mainnet
To participate in staking, you can join the [official eth2 launchpad](https://launchpad.ethereum.org). The launchpad is the only recommended way to become a validator on mainnet. 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 [beaconscan](https://beaconscan.com).
To participate in staking, you can join the [official eth2 launchpad](https://launchpad.ethereum.org). The launchpad is the only recommended way to become a validator on mainnet. You can explore validator rewards/penalties via Bitfly's block explorer: [beaconcha.in](https://beaconcha.in), and follow the latest blocks added to the chain on [beaconscan](https://beaconscan.com).
## Contributing
### Branches
Prysm maintains two permanent branches:
* master: This points to the latest stable release. It is ideal for most users.
* develop: This is used for development, it contains the latest PRs. Developers should base their PRs on this branch.
* [master](https://github.com/prysmaticlabs/prysm/tree/master): This points to the latest stable release. It is ideal for most users.
* [develop](https://github.com/prysmaticlabs/prysm/tree/develop): This is used for development, it contains the latest PRs. Developers should base their PRs on this branch.
### Guide
Want to get involved? Check out our [Contribution Guide](https://docs.prylabs.network/docs/contribute/contribution-guidelines/) to learn more!

View File

@@ -89,10 +89,10 @@ http_archive(
# nogo check fails for certain third_party dependencies.
"//third_party:io_bazel_rules_go.patch",
],
sha256 = "81eff5df9077783b18e93d0c7ff990d8ad7a3b8b3ca5b785e1c483aacdb342d7",
sha256 = "dbf5a9ef855684f84cac2e7ae7886c5a001d4f66ae23f6904da0faaaef0d61fc",
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.24.9/rules_go-v0.24.9.tar.gz",
"https://github.com/bazelbuild/rules_go/releases/download/v0.24.9/rules_go-v0.24.9.tar.gz",
"https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.24.11/rules_go-v0.24.11.tar.gz",
"https://github.com/bazelbuild/rules_go/releases/download/v0.24.11/rules_go-v0.24.11.tar.gz",
],
)
@@ -156,7 +156,7 @@ load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_depe
go_rules_dependencies()
go_register_toolchains(
go_version = "1.15.6",
go_version = "1.15.7",
nogo = "@//:nogo",
)
@@ -210,6 +210,21 @@ http_archive(
url = "https://github.com/kubernetes/repo-infra/archive/6537f2101fb432b679f3d103ee729dd8ac5d30a0.tar.gz",
)
http_archive(
name = "eip3076_spec_tests",
build_file_content = """
filegroup(
name = "test_data",
srcs = glob([
"**/*.json",
]),
visibility = ["//visibility:public"],
)
""",
sha256 = "91434d5fd5e1c6eb7b0174fed2afe25e09bddf00e1e4c431db931b2cee4e7773",
url = "https://github.com/eth2-clients/slashing-protection-interchange-tests/archive/b8413ca42dc92308019d0d4db52c87e9e125c4e9.tar.gz",
)
http_archive(
name = "eth2_spec_tests_general",
build_file_content = """
@@ -363,10 +378,6 @@ load("//:deps.bzl", "prysm_deps")
# gazelle:repository_macro deps.bzl%prysm_deps
prysm_deps()
load("@com_github_prysmaticlabs_go_ssz//:deps.bzl", "go_ssz_dependencies")
go_ssz_dependencies()
load("@prysm//third_party/herumi:herumi.bzl", "bls_dependencies")
bls_dependencies()

View File

@@ -59,6 +59,7 @@ go_library(
"@com_github_pkg_errors//:go_default_library",
"@com_github_prometheus_client_golang//prometheus:go_default_library",
"@com_github_prometheus_client_golang//prometheus/promauto:go_default_library",
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@io_opencensus_go//trace:go_default_library",
@@ -116,7 +117,6 @@ go_test(
"@com_github_ethereum_go_ethereum//core/types:go_default_library",
"@com_github_gogo_protobuf//proto: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",
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
"@in_gopkg_d4l3k_messagediff_v1//:go_default_library",
@@ -165,7 +165,6 @@ go_test(
"@com_github_ethereum_go_ethereum//core/types:go_default_library",
"@com_github_gogo_protobuf//proto: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",
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
"@org_golang_x_net//context:go_default_library",

View File

@@ -4,15 +4,15 @@ import (
"context"
"time"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"go.opencensus.io/trace"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
"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/params"
"go.opencensus.io/trace"
)
// ChainInfoFetcher defines a common interface for methods in blockchain service which
@@ -27,7 +27,7 @@ type ChainInfoFetcher interface {
// TimeFetcher retrieves the Eth2 data that's related to time.
type TimeFetcher interface {
GenesisTime() time.Time
CurrentSlot() uint64
CurrentSlot() types.Slot
}
// GenesisFetcher retrieves the eth2 data related to its genesis.
@@ -38,12 +38,12 @@ type GenesisFetcher interface {
// HeadFetcher defines a common interface for methods in blockchain service which
// directly retrieves head related data.
type HeadFetcher interface {
HeadSlot() uint64
HeadSlot() types.Slot
HeadRoot(ctx context.Context) ([]byte, error)
HeadBlock(ctx context.Context) (*ethpb.SignedBeaconBlock, error)
HeadState(ctx context.Context) (*state.BeaconState, error)
HeadValidatorsIndices(ctx context.Context, epoch uint64) ([]uint64, error)
HeadSeed(ctx context.Context, epoch uint64) ([32]byte, error)
HeadValidatorsIndices(ctx context.Context, epoch types.Epoch) ([]uint64, error)
HeadSeed(ctx context.Context, epoch types.Epoch) ([32]byte, error)
HeadGenesisValidatorRoot() [32]byte
HeadETH1Data() *ethpb.Eth1Data
ProtoArrayStore() *protoarray.Store
@@ -96,7 +96,7 @@ func (s *Service) PreviousJustifiedCheckpt() *ethpb.Checkpoint {
}
// HeadSlot returns the slot of the head of the chain.
func (s *Service) HeadSlot() uint64 {
func (s *Service) HeadSlot() types.Slot {
s.headLock.RLock()
defer s.headLock.RUnlock()
@@ -167,7 +167,7 @@ func (s *Service) HeadState(ctx context.Context) (*state.BeaconState, error) {
}
// HeadValidatorsIndices returns a list of active validator indices from the head view of a given epoch.
func (s *Service) HeadValidatorsIndices(ctx context.Context, epoch uint64) ([]uint64, error) {
func (s *Service) HeadValidatorsIndices(ctx context.Context, epoch types.Epoch) ([]uint64, error) {
s.headLock.RLock()
defer s.headLock.RUnlock()
@@ -178,7 +178,7 @@ func (s *Service) HeadValidatorsIndices(ctx context.Context, epoch uint64) ([]ui
}
// HeadSeed returns the seed from the head view of a given epoch.
func (s *Service) HeadSeed(ctx context.Context, epoch uint64) ([32]byte, error) {
func (s *Service) HeadSeed(ctx context.Context, epoch types.Epoch) ([32]byte, error) {
s.headLock.RLock()
defer s.headLock.RUnlock()

View File

@@ -6,6 +6,7 @@ import (
"time"
"github.com/gogo/protobuf/proto"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
@@ -106,7 +107,7 @@ func TestHeadSlot_CanRetrieve(t *testing.T) {
s, err := state.InitializeFromProto(&pb.BeaconState{})
require.NoError(t, err)
c.head = &head{slot: 100, state: s}
assert.Equal(t, uint64(100), c.HeadSlot())
assert.Equal(t, types.Slot(100), c.HeadSlot())
}
func TestHeadRoot_CanRetrieve(t *testing.T) {

View File

@@ -6,6 +6,7 @@ import (
"fmt"
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
@@ -20,7 +21,7 @@ import (
// This defines the current chain service's view of head.
type head struct {
slot uint64 // current head slot.
slot types.Slot // current head slot.
root [32]byte // current head root.
block *ethpb.SignedBeaconBlock // current head block.
state *stateTrie.BeaconState // current head state.
@@ -148,6 +149,9 @@ func (s *Service) saveHead(ctx context.Context, headRoot [32]byte) error {
// root in DB. With the inception of initial-sync-cache-state flag, it uses finalized
// check point as anchors to resume sync therefore head is no longer needed to be saved on per slot basis.
func (s *Service) saveHeadNoDB(ctx context.Context, b *ethpb.SignedBeaconBlock, r [32]byte, hs *stateTrie.BeaconState) error {
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
return err
}
cachedHeadRoot, err := s.HeadRoot(ctx)
if err != nil {
return errors.Wrap(err, "could not get head root from cache")
@@ -156,10 +160,6 @@ func (s *Service) saveHeadNoDB(ctx context.Context, b *ethpb.SignedBeaconBlock,
return nil
}
if b == nil || b.Block == nil {
return errors.New("cannot save nil head block")
}
s.setHeadInitialSync(r, stateTrie.CopySignedBeaconBlock(b), hs)
return nil
}
@@ -196,7 +196,7 @@ func (s *Service) setHeadInitialSync(root [32]byte, block *ethpb.SignedBeaconBlo
// This returns the head slot.
// This is a lock free version.
func (s *Service) headSlot() uint64 {
func (s *Service) headSlot() types.Slot {
return s.head.slot
}
@@ -234,14 +234,6 @@ func (s *Service) headGenesisValidatorRoot() [32]byte {
return bytesutil.ToBytes32(s.head.state.GenesisValidatorRoot())
}
// HasHeadState returns true if head state exists.
func (s *Service) HasHeadState() bool {
s.headLock.RLock()
defer s.headLock.RUnlock()
return s.hasHeadState()
}
// Returns true if head state exists.
// This is the lock free version.
func (s *Service) hasHeadState() bool {

View File

@@ -5,6 +5,7 @@ import (
"context"
"testing"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
@@ -22,7 +23,7 @@ func TestSaveHead_Same(t *testing.T) {
service.head = &head{slot: 0, root: r}
require.NoError(t, service.saveHead(context.Background(), r))
assert.Equal(t, uint64(0), service.headSlot(), "Head did not stay the same")
assert.Equal(t, types.Slot(0), service.headSlot(), "Head did not stay the same")
assert.Equal(t, r, service.headRoot(), "Head did not stay the same")
}
@@ -41,19 +42,18 @@ func TestSaveHead_Different(t *testing.T) {
require.NoError(t, service.beaconDB.SaveBlock(context.Background(), newHeadSignedBlock))
newRoot, err := newHeadBlock.HashTreeRoot()
require.NoError(t, err)
headState := testutil.NewBeaconState()
headState, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, headState.SetSlot(1))
require.NoError(t, service.beaconDB.SaveStateSummary(context.Background(), &pb.StateSummary{Slot: 1, Root: newRoot[:]}))
require.NoError(t, service.beaconDB.SaveState(context.Background(), headState, newRoot))
require.NoError(t, service.saveHead(context.Background(), newRoot))
assert.Equal(t, uint64(1), service.HeadSlot(), "Head did not change")
assert.Equal(t, types.Slot(1), service.HeadSlot(), "Head did not change")
cachedRoot, err := service.HeadRoot(context.Background())
require.NoError(t, err)
if !bytes.Equal(cachedRoot, newRoot[:]) {
t.Error("Head did not change")
}
assert.DeepEqual(t, cachedRoot, newRoot[:], "Head did not change")
assert.DeepEqual(t, newHeadSignedBlock, service.headBlock(), "Head did not change")
assert.DeepEqual(t, headState.CloneInnerState(), service.headState(ctx).CloneInnerState(), "Head did not change")
}
@@ -76,13 +76,14 @@ func TestSaveHead_Different_Reorg(t *testing.T) {
require.NoError(t, service.beaconDB.SaveBlock(context.Background(), newHeadSignedBlock))
newRoot, err := newHeadBlock.HashTreeRoot()
require.NoError(t, err)
headState := testutil.NewBeaconState()
headState, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, headState.SetSlot(1))
require.NoError(t, service.beaconDB.SaveStateSummary(context.Background(), &pb.StateSummary{Slot: 1, Root: newRoot[:]}))
require.NoError(t, service.beaconDB.SaveState(context.Background(), headState, newRoot))
require.NoError(t, service.saveHead(context.Background(), newRoot))
assert.Equal(t, uint64(1), service.HeadSlot(), "Head did not change")
assert.Equal(t, types.Slot(1), service.HeadSlot(), "Head did not change")
cachedRoot, err := service.HeadRoot(context.Background())
require.NoError(t, err)

View File

@@ -21,7 +21,8 @@ func TestService_TreeHandler(t *testing.T) {
ctx := context.Background()
beaconDB := testDB.SetupDB(t)
headState := testutil.NewBeaconState()
headState, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, headState.SetBalances([]uint64{params.BeaconConfig().GweiPerEth}))
cfg := &Config{
BeaconDB: beaconDB,

View File

@@ -3,10 +3,12 @@ package blockchain
import (
"encoding/hex"
"fmt"
"time"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/timeutils"
"github.com/sirupsen/logrus"
)
@@ -23,13 +25,20 @@ func logStateTransitionData(b *ethpb.BeaconBlock) {
}).Info("Finished applying state transition")
}
func logBlockSyncStatus(block *ethpb.BeaconBlock, blockRoot [32]byte, finalized *ethpb.Checkpoint) {
func logBlockSyncStatus(block *ethpb.BeaconBlock, blockRoot [32]byte, finalized *ethpb.Checkpoint, receivedTime time.Time, genesisTime uint64) error {
startTime, err := helpers.SlotToTime(genesisTime, block.Slot)
if err != nil {
return err
}
log.WithFields(logrus.Fields{
"slot": block.Slot,
"slotInEpoch": block.Slot % params.BeaconConfig().SlotsPerEpoch,
"block": fmt.Sprintf("0x%s...", hex.EncodeToString(blockRoot[:])[:8]),
"epoch": helpers.SlotToEpoch(block.Slot),
"finalizedEpoch": finalized.Epoch,
"finalizedRoot": fmt.Sprintf("0x%s...", hex.EncodeToString(finalized.Root)[:8]),
"slot": block.Slot,
"slotInEpoch": block.Slot % params.BeaconConfig().SlotsPerEpoch,
"block": fmt.Sprintf("0x%s...", hex.EncodeToString(blockRoot[:])[:8]),
"epoch": helpers.SlotToEpoch(block.Slot),
"finalizedEpoch": finalized.Epoch,
"finalizedRoot": fmt.Sprintf("0x%s...", hex.EncodeToString(finalized.Root)[:8]),
"sinceSlotStartTime": timeutils.Now().Sub(startTime),
"chainServiceProcessedTime": timeutils.Now().Sub(receivedTime),
}).Info("Synced new block")
return nil
}

View File

@@ -5,6 +5,7 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
@@ -108,7 +109,7 @@ var (
)
// reportSlotMetrics reports slot related metrics.
func reportSlotMetrics(stateSlot, headSlot, clockSlot uint64, finalizedCheckpoint *ethpb.Checkpoint) {
func reportSlotMetrics(stateSlot, headSlot, clockSlot types.Slot, finalizedCheckpoint *ethpb.Checkpoint) {
clockTimeSlot.Set(float64(clockSlot))
beaconSlot.Set(float64(stateSlot))
beaconHeadSlot.Set(float64(headSlot))
@@ -120,7 +121,7 @@ func reportSlotMetrics(stateSlot, headSlot, clockSlot uint64, finalizedCheckpoin
// reportEpochMetrics reports epoch related metrics.
func reportEpochMetrics(ctx context.Context, postState, headState *stateTrie.BeaconState) error {
currentEpoch := postState.Slot() / params.BeaconConfig().SlotsPerEpoch
currentEpoch := types.Epoch(postState.Slot() / params.BeaconConfig().SlotsPerEpoch)
// Validator instances
pendingInstances := 0

View File

@@ -4,23 +4,39 @@ import (
"context"
"testing"
eth "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
)
func TestReportEpochMetrics_BadHeadState(t *testing.T) {
s := testutil.NewBeaconState()
h := testutil.NewBeaconState()
s, err := testutil.NewBeaconState()
require.NoError(t, err)
h, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, h.SetValidators(nil))
err := reportEpochMetrics(context.Background(), s, h)
err = reportEpochMetrics(context.Background(), s, h)
require.ErrorContains(t, "failed to initialize precompute: nil validators in state", err)
}
func TestReportEpochMetrics_BadAttestation(t *testing.T) {
s := testutil.NewBeaconState()
h := testutil.NewBeaconState()
s, err := testutil.NewBeaconState()
require.NoError(t, err)
h, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, h.SetCurrentEpochAttestations([]*pb.PendingAttestation{{InclusionDelay: 0}}))
err := reportEpochMetrics(context.Background(), s, h)
err = reportEpochMetrics(context.Background(), s, h)
require.ErrorContains(t, "attestation with inclusion delay of 0", err)
}
func TestReportEpochMetrics_SlashedValidatorOutOfBound(t *testing.T) {
h, _ := testutil.DeterministicGenesisState(t, 1)
v, err := h.ValidatorAtIndex(0)
require.NoError(t, err)
v.Slashed = true
require.NoError(t, h.UpdateValidatorAtIndex(0, v))
require.NoError(t, h.SetCurrentEpochAttestations([]*pb.PendingAttestation{{InclusionDelay: 1, Data: testutil.HydrateAttestationData(&eth.AttestationData{})}}))
err = reportEpochMetrics(context.Background(), h, h)
require.ErrorContains(t, "slot 0 out of bounds", err)
}

View File

@@ -2,25 +2,21 @@ package blockchain
import (
"context"
"fmt"
"github.com/pkg/errors"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/shared/attestationutil"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/timeutils"
"go.opencensus.io/trace"
)
// ErrTargetRootNotInDB returns when the target block root of an attestation cannot be found in the
// beacon database.
var ErrTargetRootNotInDB = errors.New("target root does not exist in db")
// onAttestation is called whenever an attestation is received, verifies the attestation is valid and saves
// it to the DB. As a stateless function, this does not hold nor delay attestation based on the spec descriptions.
// The delay is handled by the caller in `processAttestation`.
// The delay is handled by the caller in `processAttestations`.
//
// Spec pseudocode definition:
// def on_attestation(store: Store, attestation: Attestation) -> None:
@@ -40,73 +36,68 @@ var ErrTargetRootNotInDB = errors.New("target root does not exist in db")
//
// # Update latest messages for attesting indices
// update_latest_messages(store, indexed_attestation.attesting_indices, attestation)
// TODO(#6072): This code path is highly untested. Requires comprehensive tests and simpler refactoring.
func (s *Service) onAttestation(ctx context.Context, a *ethpb.Attestation) ([]uint64, error) {
func (s *Service) onAttestation(ctx context.Context, a *ethpb.Attestation) error {
ctx, span := trace.StartSpan(ctx, "blockChain.onAttestation")
defer span.End()
if a == nil {
return nil, errors.New("nil attestation")
if err := helpers.ValidateNilAttestation(a); err != nil {
return err
}
if a.Data == nil {
return nil, errors.New("nil attestation.Data field")
if err := helpers.ValidateSlotTargetEpoch(a.Data); err != nil {
return err
}
if a.Data.Target == nil {
return nil, errors.New("nil attestation.Data.Target field")
}
tgt := stateTrie.CopyCheckpoint(a.Data.Target)
if helpers.SlotToEpoch(a.Data.Slot) != a.Data.Target.Epoch {
return nil, fmt.Errorf("data slot is not in the same epoch as target %d != %d", helpers.SlotToEpoch(a.Data.Slot), a.Data.Target.Epoch)
}
// Verify beacon node has seen the target block before.
if !s.hasBlock(ctx, bytesutil.ToBytes32(tgt.Root)) {
return nil, ErrTargetRootNotInDB
}
// Note that target root check is ignored here because it was performed in sync's validation pipeline:
// validate_aggregate_proof.go and validate_beacon_attestation.go
// If missing target root were to fail in this method, it would have just failed in `getAttPreState`.
// Retrieve attestation's data beacon block pre state. Advance pre state to latest epoch if necessary and
// save it to the cache.
baseState, err := s.getAttPreState(ctx, tgt)
if err != nil {
return nil, err
return err
}
genesisTime := baseState.GenesisTime()
// Verify attestation target is from current epoch or previous epoch.
if err := s.verifyAttTargetEpoch(ctx, genesisTime, uint64(timeutils.Now().Unix()), tgt); err != nil {
return nil, err
return err
}
// Verify attestation beacon block is known and not from the future.
if err := s.verifyBeaconBlock(ctx, a.Data); err != nil {
return nil, errors.Wrap(err, "could not verify attestation beacon block")
return errors.Wrap(err, "could not verify attestation beacon block")
}
// Verify LMG GHOST and FFG votes are consistent with each other.
if err := s.verifyLMDFFGConsistent(ctx, a.Data.Target.Epoch, a.Data.Target.Root, a.Data.BeaconBlockRoot); err != nil {
return nil, errors.Wrap(err, "could not verify attestation beacon block")
}
// Note that LMG GHOST and FFG consistency check is ignored because it was performed in sync's validation pipeline:
// validate_aggregate_proof.go and validate_beacon_attestation.go
// Verify attestations can only affect the fork choice of subsequent slots.
if err := helpers.VerifySlotTime(genesisTime, a.Data.Slot+1, params.BeaconNetworkConfig().MaximumGossipClockDisparity); err != nil {
return nil, err
return err
}
// Use the target state to validate attestation and calculate the committees.
indexedAtt, err := s.verifyAttestation(ctx, baseState, a)
// Use the target state to verify attesting indices are valid.
committee, err := helpers.BeaconCommitteeFromState(baseState, a.Data.Slot, a.Data.CommitteeIndex)
if err != nil {
return nil, err
return err
}
indexedAtt, err := attestationutil.ConvertToIndexed(ctx, a, committee)
if err != nil {
return err
}
if err := attestationutil.IsValidAttestationIndices(ctx, indexedAtt); err != nil {
return err
}
if indexedAtt.AttestingIndices == nil {
return nil, errors.New("nil attesting indices")
}
// Note that signature verification is ignored here because it was performed in sync's validation pipeline:
// validate_aggregate_proof.go and validate_beacon_attestation.go
// We assume trusted attestation in this function has verified signature.
// 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)
return indexedAtt.AttestingIndices, nil
return nil
}

View File

@@ -1,19 +1,18 @@
package blockchain
import (
"bytes"
"context"
"fmt"
"strconv"
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
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/beacon-chain/core/state"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/shared/attestationutil"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/featureconfig"
"github.com/prysmaticlabs/prysm/shared/mputil"
"github.com/prysmaticlabs/prysm/shared/params"
)
@@ -22,7 +21,7 @@ import (
func (s *Service) getAttPreState(ctx context.Context, c *ethpb.Checkpoint) (*stateTrie.BeaconState, error) {
// Use a multilock to allow scoped holding of a mutex by a checkpoint root + epoch
// allowing us to behave smarter in terms of how this function is used concurrently.
epochKey := strconv.FormatUint(c.Epoch, 10 /* base 10 */)
epochKey := strconv.FormatUint(uint64(c.Epoch), 10 /* base 10 */)
lock := mputil.NewMultilock(string(c.Root) + epochKey)
lock.Lock()
defer lock.Unlock()
@@ -44,10 +43,16 @@ func (s *Service) getAttPreState(ctx context.Context, c *ethpb.Checkpoint) (*sta
return nil, err
}
if epochStartSlot > baseState.Slot() {
baseState = baseState.Copy()
baseState, err = state.ProcessSlots(ctx, baseState, epochStartSlot)
if err != nil {
return nil, errors.Wrapf(err, "could not process slots up to epoch %d", c.Epoch)
if featureconfig.Get().EnableNextSlotStateCache {
baseState, err = state.ProcessSlotsUsingNextSlotCache(ctx, baseState, c.Root, epochStartSlot)
if err != nil {
return nil, errors.Wrapf(err, "could not process slots up to epoch %d", c.Epoch)
}
} else {
baseState, err = state.ProcessSlots(ctx, baseState, epochStartSlot)
if err != nil {
return nil, errors.Wrapf(err, "could not process slots up to epoch %d", c.Epoch)
}
}
if err := s.checkpointStateCache.AddCheckpointState(c, baseState); err != nil {
return nil, errors.Wrap(err, "could not saved checkpoint state to cache")
@@ -72,9 +77,9 @@ func (s *Service) getAttPreState(ctx context.Context, c *ethpb.Checkpoint) (*sta
// verifyAttTargetEpoch validates attestation is from the current or previous epoch.
func (s *Service) verifyAttTargetEpoch(_ context.Context, genesisTime, nowTime uint64, c *ethpb.Checkpoint) error {
currentSlot := (nowTime - genesisTime) / params.BeaconConfig().SecondsPerSlot
currentSlot := types.Slot((nowTime - genesisTime) / params.BeaconConfig().SecondsPerSlot)
currentEpoch := helpers.SlotToEpoch(currentSlot)
var prevEpoch uint64
var prevEpoch types.Epoch
// Prevents previous epoch under flow
if currentEpoch > 1 {
prevEpoch = currentEpoch - 1
@@ -97,41 +102,11 @@ func (s *Service) verifyBeaconBlock(ctx context.Context, data *ethpb.Attestation
if b == nil && s.hasInitSyncBlock(r) {
b = s.getInitSyncBlock(r)
}
if b == nil || b.Block == nil {
return fmt.Errorf("beacon block %#x does not exist", bytesutil.Trunc(data.BeaconBlockRoot))
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
return err
}
if b.Block.Slot > data.Slot {
return fmt.Errorf("could not process attestation for future block, block.Slot=%d > attestation.Data.Slot=%d", b.Block.Slot, data.Slot)
}
return nil
}
// verifyLMDFFGConsistent verifies LMD GHOST and FFG votes are consistent with each other.
func (s *Service) verifyLMDFFGConsistent(ctx context.Context, ffgEpoch uint64, ffgRoot, lmdRoot []byte) error {
ffgSlot, err := helpers.StartSlot(ffgEpoch)
if err != nil {
return err
}
r, err := s.ancestor(ctx, lmdRoot, ffgSlot)
if err != nil {
return err
}
if !bytes.Equal(ffgRoot, r) {
return errors.New("FFG and LMD votes are not consistent")
}
return nil
}
// verifyAttestation validates input attestation is valid.
func (s *Service) verifyAttestation(ctx context.Context, baseState *stateTrie.BeaconState, a *ethpb.Attestation) (*ethpb.IndexedAttestation, error) {
committee, err := helpers.BeaconCommitteeFromState(baseState, a.Data.Slot, a.Data.CommitteeIndex)
if err != nil {
return nil, err
}
indexedAtt := attestationutil.ConvertToIndexed(ctx, a, committee)
if err := blocks.VerifyIndexedAttestation(ctx, baseState, indexedAtt); err != nil {
return nil, errors.Wrap(err, "could not verify indexed attestation")
}
return indexedAtt, nil
}

View File

@@ -5,6 +5,7 @@ import (
"testing"
"github.com/gogo/protobuf/proto"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
@@ -17,9 +18,10 @@ import (
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
"github.com/prysmaticlabs/prysm/shared/timeutils"
)
func TestStore_OnAttestation(t *testing.T) {
func TestStore_OnAttestation_ErrorConditions(t *testing.T) {
ctx := context.Background()
beaconDB := testDB.SetupDB(t)
@@ -31,7 +33,7 @@ func TestStore_OnAttestation(t *testing.T) {
service, err := NewService(ctx, cfg)
require.NoError(t, err)
_, err = blockTree1(beaconDB, []byte{'g'})
_, err = blockTree1(t, beaconDB, []byte{'g'})
require.NoError(t, err)
BlkWithOutState := testutil.NewBeaconBlock()
@@ -46,7 +48,8 @@ func TestStore_OnAttestation(t *testing.T) {
BlkWithStateBadAttRoot, err := BlkWithStateBadAtt.Block.HashTreeRoot()
require.NoError(t, err)
s := testutil.NewBeaconState()
s, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, s.SetSlot(100*params.BeaconConfig().SlotsPerEpoch))
require.NoError(t, service.beaconDB.SaveState(ctx, s, BlkWithStateBadAttRoot))
@@ -56,7 +59,8 @@ func TestStore_OnAttestation(t *testing.T) {
BlkWithValidStateRoot, err := BlkWithValidState.Block.HashTreeRoot()
require.NoError(t, err)
s = testutil.NewBeaconState()
s, err = testutil.NewBeaconState()
require.NoError(t, err)
err = s.SetFork(&pb.Fork{
Epoch: 0,
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
@@ -72,34 +76,29 @@ func TestStore_OnAttestation(t *testing.T) {
}{
{
name: "attestation's data slot not aligned with target vote",
a: &ethpb.Attestation{Data: &ethpb.AttestationData{Slot: params.BeaconConfig().SlotsPerEpoch, Target: &ethpb.Checkpoint{Root: make([]byte, 32)}}},
wantedErr: "data slot is not in the same epoch as target 1 != 0",
},
{
name: "attestation's target root not in db",
a: &ethpb.Attestation{Data: &ethpb.AttestationData{Target: &ethpb.Checkpoint{Root: bytesutil.PadTo([]byte{'A'}, 32)}}},
wantedErr: "target root does not exist in db",
a: testutil.HydrateAttestation(&ethpb.Attestation{Data: &ethpb.AttestationData{Slot: params.BeaconConfig().SlotsPerEpoch, Target: &ethpb.Checkpoint{Root: make([]byte, 32)}}}),
wantedErr: "slot 32 does not match target epoch 0",
},
{
name: "no pre state for attestations's target block",
a: &ethpb.Attestation{Data: &ethpb.AttestationData{Target: &ethpb.Checkpoint{Root: BlkWithOutStateRoot[:]}}},
a: testutil.HydrateAttestation(&ethpb.Attestation{Data: &ethpb.AttestationData{Target: &ethpb.Checkpoint{Root: BlkWithOutStateRoot[:]}}}),
wantedErr: "could not get pre state for epoch 0",
},
{
name: "process attestation doesn't match current epoch",
a: &ethpb.Attestation{Data: &ethpb.AttestationData{Slot: 100 * params.BeaconConfig().SlotsPerEpoch, Target: &ethpb.Checkpoint{Epoch: 100,
Root: BlkWithStateBadAttRoot[:]}}},
a: testutil.HydrateAttestation(&ethpb.Attestation{Data: &ethpb.AttestationData{Slot: 100 * params.BeaconConfig().SlotsPerEpoch, Target: &ethpb.Checkpoint{Epoch: 100,
Root: BlkWithStateBadAttRoot[:]}}}),
wantedErr: "target epoch 100 does not match current epoch",
},
{
name: "process nil attestation",
a: nil,
wantedErr: "nil attestation",
wantedErr: "attestation can't be nil",
},
{
name: "process nil field (a.Data) in attestation",
a: &ethpb.Attestation{},
wantedErr: "nil attestation.Data field",
wantedErr: "attestation's data can't be nil",
},
{
name: "process nil field (a.Target) in attestation",
@@ -112,13 +111,13 @@ func TestStore_OnAttestation(t *testing.T) {
AggregationBits: make([]byte, 1),
Signature: make([]byte, 96),
},
wantedErr: "nil attestation.Data.Target field",
wantedErr: "attestation's target can't be nil",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, err := service.onAttestation(ctx, tt.a)
err := service.onAttestation(ctx, tt.a)
if tt.wantedErr != "" {
assert.ErrorContains(t, tt.wantedErr, err)
} else {
@@ -128,6 +127,31 @@ func TestStore_OnAttestation(t *testing.T) {
}
}
func TestStore_OnAttestation_Ok(t *testing.T) {
ctx := context.Background()
beaconDB := testDB.SetupDB(t)
cfg := &Config{
BeaconDB: beaconDB,
ForkChoiceStore: protoarray.New(0, 0, [32]byte{}),
StateGen: stategen.New(beaconDB),
}
service, err := NewService(ctx, cfg)
require.NoError(t, err)
genesisState, pks := testutil.DeterministicGenesisState(t, 64)
require.NoError(t, genesisState.SetGenesisTime(uint64(timeutils.Now().Unix())-params.BeaconConfig().SecondsPerSlot))
require.NoError(t, service.saveGenesisData(ctx, genesisState))
att, err := testutil.GenerateAttestations(genesisState, pks, 1, 0, false)
require.NoError(t, err)
tRoot := bytesutil.ToBytes32(att[0].Data.Target.Root)
copied := genesisState.Copy()
copied, err = state.ProcessSlots(ctx, copied, 1)
require.NoError(t, err)
require.NoError(t, service.beaconDB.SaveState(ctx, copied, tRoot))
require.NoError(t, service.forkChoiceStore.ProcessBlock(ctx, 0, tRoot, tRoot, tRoot, 1, 1))
require.NoError(t, service.onAttestation(ctx, att[0]))
}
func TestStore_SaveCheckpointState(t *testing.T) {
ctx := context.Background()
beaconDB := testDB.SetupDB(t)
@@ -139,7 +163,8 @@ func TestStore_SaveCheckpointState(t *testing.T) {
service, err := NewService(ctx, cfg)
require.NoError(t, err)
s := testutil.NewBeaconState()
s, err := testutil.NewBeaconState()
require.NoError(t, err)
err = s.SetFinalizedCheckpoint(&ethpb.Checkpoint{Root: bytesutil.PadTo([]byte{'A'}, 32)})
require.NoError(t, err)
val := &ethpb.Validator{
@@ -210,19 +235,19 @@ func TestStore_UpdateCheckpointState(t *testing.T) {
service, err := NewService(ctx, cfg)
require.NoError(t, err)
epoch := uint64(1)
epoch := types.Epoch(1)
baseState, _ := testutil.DeterministicGenesisState(t, 1)
checkpoint := &ethpb.Checkpoint{Epoch: epoch, Root: bytesutil.PadTo([]byte("hi"), 32)}
require.NoError(t, service.beaconDB.SaveState(ctx, baseState, bytesutil.ToBytes32(checkpoint.Root)))
returned, err := service.getAttPreState(ctx, checkpoint)
require.NoError(t, err)
assert.Equal(t, returned.Slot(), checkpoint.Epoch*params.BeaconConfig().SlotsPerEpoch, "Incorrectly returned base state")
assert.Equal(t, params.BeaconConfig().SlotsPerEpoch.Mul(uint64(checkpoint.Epoch)), returned.Slot(), "Incorrectly returned base state")
cached, err := service.checkpointStateCache.StateByCheckpoint(checkpoint)
require.NoError(t, err)
assert.Equal(t, returned.Slot(), cached.Slot(), "State should have been cached")
epoch = uint64(2)
epoch = 2
newCheckpoint := &ethpb.Checkpoint{Epoch: epoch, Root: bytesutil.PadTo([]byte("bye"), 32)}
require.NoError(t, service.beaconDB.SaveState(ctx, baseState, bytesutil.ToBytes32(newCheckpoint.Root)))
returned, err = service.getAttPreState(ctx, newCheckpoint)
@@ -248,7 +273,7 @@ func TestAttEpoch_MatchPrevEpoch(t *testing.T) {
service, err := NewService(ctx, cfg)
require.NoError(t, err)
nowTime := params.BeaconConfig().SlotsPerEpoch * params.BeaconConfig().SecondsPerSlot
nowTime := uint64(params.BeaconConfig().SlotsPerEpoch) * params.BeaconConfig().SecondsPerSlot
require.NoError(t, service.verifyAttTargetEpoch(ctx, 0, nowTime, &ethpb.Checkpoint{Root: make([]byte, 32)}))
}
@@ -260,7 +285,7 @@ func TestAttEpoch_MatchCurrentEpoch(t *testing.T) {
service, err := NewService(ctx, cfg)
require.NoError(t, err)
nowTime := params.BeaconConfig().SlotsPerEpoch * params.BeaconConfig().SecondsPerSlot
nowTime := uint64(params.BeaconConfig().SlotsPerEpoch) * params.BeaconConfig().SecondsPerSlot
require.NoError(t, service.verifyAttTargetEpoch(ctx, 0, nowTime, &ethpb.Checkpoint{Epoch: 1}))
}
@@ -272,7 +297,7 @@ func TestAttEpoch_NotMatch(t *testing.T) {
service, err := NewService(ctx, cfg)
require.NoError(t, err)
nowTime := 2 * params.BeaconConfig().SlotsPerEpoch * params.BeaconConfig().SecondsPerSlot
nowTime := 2 * uint64(params.BeaconConfig().SlotsPerEpoch) * params.BeaconConfig().SecondsPerSlot
err = service.verifyAttTargetEpoch(ctx, 0, nowTime, &ethpb.Checkpoint{Root: make([]byte, 32)})
assert.ErrorContains(t, "target epoch 0 does not match current epoch 2 or prev epoch 1", err)
}
@@ -286,7 +311,7 @@ func TestVerifyBeaconBlock_NoBlock(t *testing.T) {
require.NoError(t, err)
d := testutil.HydrateAttestationData(&ethpb.AttestationData{})
assert.ErrorContains(t, "beacon block 0x000000000000 does not exist", service.verifyBeaconBlock(ctx, d))
assert.ErrorContains(t, "signed beacon block can't be nil", service.verifyBeaconBlock(ctx, d))
}
func TestVerifyBeaconBlock_futureBlock(t *testing.T) {
@@ -325,54 +350,6 @@ func TestVerifyBeaconBlock_OK(t *testing.T) {
assert.NoError(t, service.verifyBeaconBlock(ctx, d), "Did not receive the wanted error")
}
func TestVerifyLMDFFGConsistent_NotOK(t *testing.T) {
ctx := context.Background()
beaconDB := testDB.SetupDB(t)
cfg := &Config{BeaconDB: beaconDB, ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}
service, err := NewService(ctx, cfg)
require.NoError(t, err)
b32 := testutil.NewBeaconBlock()
b32.Block.Slot = 32
require.NoError(t, service.beaconDB.SaveBlock(ctx, b32))
r32, err := b32.Block.HashTreeRoot()
require.NoError(t, err)
b33 := testutil.NewBeaconBlock()
b33.Block.Slot = 33
b33.Block.ParentRoot = r32[:]
require.NoError(t, service.beaconDB.SaveBlock(ctx, b33))
r33, err := b33.Block.HashTreeRoot()
require.NoError(t, err)
wanted := "FFG and LMD votes are not consistent"
assert.ErrorContains(t, wanted, service.verifyLMDFFGConsistent(context.Background(), 1, []byte{'a'}, r33[:]))
}
func TestVerifyLMDFFGConsistent_OK(t *testing.T) {
ctx := context.Background()
beaconDB := testDB.SetupDB(t)
cfg := &Config{BeaconDB: beaconDB, ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}
service, err := NewService(ctx, cfg)
require.NoError(t, err)
b32 := testutil.NewBeaconBlock()
b32.Block.Slot = 32
require.NoError(t, service.beaconDB.SaveBlock(ctx, b32))
r32, err := b32.Block.HashTreeRoot()
require.NoError(t, err)
b33 := testutil.NewBeaconBlock()
b33.Block.Slot = 33
b33.Block.ParentRoot = r32[:]
require.NoError(t, service.beaconDB.SaveBlock(ctx, b33))
r33, err := b33.Block.HashTreeRoot()
require.NoError(t, err)
err = service.verifyLMDFFGConsistent(context.Background(), 1, r32[:], r33[:])
assert.NoError(t, err, "Could not verify LMD and FFG votes to be consistent")
}
func TestVerifyFinalizedConsistency_InconsistentRoot(t *testing.T) {
ctx := context.Background()
beaconDB := testDB.SetupDB(t)

View File

@@ -3,9 +3,12 @@ package blockchain
import (
"context"
"fmt"
"time"
"github.com/pkg/errors"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
@@ -18,8 +21,14 @@ import (
"go.opencensus.io/trace"
)
// A custom slot deadline for processing state slots in our cache.
const slotDeadline = 5 * time.Second
// A custom deadline for deposit trie insertion.
const depositDeadline = 20 * time.Second
// This defines size of the upper bound for initial sync block cache.
var initialSyncBlockCacheSize = 2 * params.BeaconConfig().SlotsPerEpoch
var initialSyncBlockCacheSize = uint64(2 * params.BeaconConfig().SlotsPerEpoch)
// onBlock is called when a gossip block is received. It runs regular state transition on the block.
// The block's signing root should be computed before calling this method to avoid redundant
@@ -101,6 +110,20 @@ func (s *Service) onBlock(ctx context.Context, signed *ethpb.SignedBeaconBlock,
return err
}
// Updating next slot state cache can happen in the background. It shouldn't block rest of the process.
if featureconfig.Get().EnableNextSlotStateCache {
go func() {
// Use a custom deadline here, since this method runs asynchronously.
// We ignore the parent method's context and instead create a new one
// with a custom deadline, therefore using the background context instead.
slotCtx, cancel := context.WithTimeout(context.Background(), slotDeadline)
defer cancel()
if err := state.UpdateNextSlotCache(slotCtx, blockRoot[:], postState); err != nil {
log.WithError(err).Debug("could not update next slot state cache")
}
}()
}
// Update justified check point.
if postState.CurrentJustifiedCheckpoint().Epoch > s.justifiedCheckpt.Epoch {
if err := s.updateJustified(ctx, postState); err != nil {
@@ -108,42 +131,56 @@ func (s *Service) onBlock(ctx context.Context, signed *ethpb.SignedBeaconBlock,
}
}
// Update finalized check point.
if postState.FinalizedCheckpointEpoch() > s.finalizedCheckpt.Epoch {
if err := s.beaconDB.SaveBlocks(ctx, s.getInitSyncBlocks()); err != nil {
return err
newFinalized := postState.FinalizedCheckpointEpoch() > s.finalizedCheckpt.Epoch
if featureconfig.Get().UpdateHeadTimely {
if newFinalized {
if err := s.finalizedImpliesNewJustified(ctx, postState); err != nil {
return errors.Wrap(err, "could not save new justified")
}
s.prevFinalizedCheckpt = s.finalizedCheckpt
s.finalizedCheckpt = postState.FinalizedCheckpoint()
}
s.clearInitSyncBlocks()
if err := s.updateHead(ctx, s.getJustifiedBalances()); err != nil {
log.WithError(err).Warn("Could not update head")
}
// Send notification of the processed block to the state feed.
s.stateNotifier.StateFeed().Send(&feed.Event{
Type: statefeed.BlockProcessed,
Data: &statefeed.BlockProcessedData{
Slot: signed.Block.Slot,
BlockRoot: blockRoot,
SignedBlock: signed,
Verified: true,
},
})
}
// Update finalized check point.
if newFinalized {
if err := s.updateFinalized(ctx, postState.FinalizedCheckpoint()); err != nil {
return err
}
fRoot := bytesutil.ToBytes32(postState.FinalizedCheckpoint().Root)
if err := s.forkChoiceStore.Prune(ctx, fRoot); err != nil {
return errors.Wrap(err, "could not prune proto array fork choice nodes")
}
if err := s.finalizedImpliesNewJustified(ctx, postState); err != nil {
return errors.Wrap(err, "could not save new justified")
}
// Update deposit cache.
finalizedState, err := s.stateGen.StateByRoot(ctx, fRoot)
if err != nil {
return errors.Wrap(err, "could not fetch finalized state")
}
// We update the cache up to the last deposit index in the finalized block's state.
// We can be confident that these deposits will be included in some block
// because the Eth1 follow distance makes such long-range reorgs extremely unlikely.
eth1DepositIndex := int64(finalizedState.Eth1Data().DepositCount - 1)
s.depositCache.InsertFinalizedDeposits(ctx, eth1DepositIndex)
if featureconfig.Get().EnablePruningDepositProofs {
// Deposit proofs are only used during state transition and can be safely removed to save space.
if err = s.depositCache.PruneProofs(ctx, eth1DepositIndex); err != nil {
return errors.Wrap(err, "could not prune deposit proofs")
if !featureconfig.Get().UpdateHeadTimely {
if err := s.finalizedImpliesNewJustified(ctx, postState); err != nil {
return errors.Wrap(err, "could not save new justified")
}
}
go func() {
// Use a custom deadline here, since this method runs asynchronously.
// We ignore the parent method's context and instead create a new one
// with a custom deadline, therefore using the background context instead.
depCtx, cancel := context.WithTimeout(context.Background(), depositDeadline)
defer cancel()
if err := s.insertFinalizedDeposits(depCtx, fRoot); err != nil {
log.WithError(err).Error("Could not insert finalized deposits.")
}
}()
}
defer reportAttestationInclusion(b)
@@ -341,7 +378,12 @@ func (s *Service) handleEpochBoundary(ctx context.Context, postState *stateTrie.
if err := helpers.UpdateCommitteeCache(postState, helpers.NextEpoch(postState)); err != nil {
return err
}
if err := helpers.UpdateProposerIndicesInCache(postState, helpers.NextEpoch(postState)); err != nil {
copied := postState.Copy()
copied, err := state.ProcessSlots(ctx, copied, copied.Slot()+1)
if err != nil {
return err
}
if err := helpers.UpdateProposerIndicesInCache(copied); err != nil {
return err
}
} else if postState.Slot() >= s.nextEpochBoundarySlot {
@@ -359,7 +401,7 @@ func (s *Service) handleEpochBoundary(ctx context.Context, postState *stateTrie.
if err := helpers.UpdateCommitteeCache(postState, helpers.CurrentEpoch(postState)); err != nil {
return err
}
if err := helpers.UpdateProposerIndicesInCache(postState, helpers.CurrentEpoch(postState)); err != nil {
if err := helpers.UpdateProposerIndicesInCache(postState); err != nil {
return err
}
}
@@ -382,7 +424,10 @@ func (s *Service) insertBlockAndAttestationsToForkChoiceStore(ctx context.Contex
if err != nil {
return err
}
indices := attestationutil.AttestingIndices(a.AggregationBits, committee)
indices, err := attestationutil.AttestingIndices(a.AggregationBits, committee)
if err != nil {
return err
}
s.forkChoiceStore.ProcessAttestation(ctx, indices, bytesutil.ToBytes32(a.Data.BeaconBlockRoot), a.Data.Target.Epoch)
}
return nil

View File

@@ -6,18 +6,20 @@ import (
"fmt"
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/shared/attestationutil"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/featureconfig"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/traceutil"
"go.opencensus.io/trace"
)
// CurrentSlot returns the current slot based on time.
func (s *Service) CurrentSlot() uint64 {
func (s *Service) CurrentSlot() types.Slot {
return helpers.CurrentSlot(uint64(s.genesisTime.Unix()))
}
@@ -230,9 +232,10 @@ func (s *Service) updateFinalized(ctx context.Context, cp *ethpb.Checkpoint) err
if err := s.beaconDB.SaveFinalizedCheckpoint(ctx, cp); err != nil {
return err
}
s.prevFinalizedCheckpt = s.finalizedCheckpt
s.finalizedCheckpt = cp
if !featureconfig.Get().UpdateHeadTimely {
s.prevFinalizedCheckpt = s.finalizedCheckpt
s.finalizedCheckpt = cp
}
fRoot := bytesutil.ToBytes32(cp.Root)
if err := s.stateGen.MigrateToCold(ctx, fRoot); err != nil {
@@ -254,7 +257,7 @@ func (s *Service) updateFinalized(ctx context.Context, cp *ethpb.Checkpoint) err
// else:
// # root is older than queried slot, thus a skip slot. Return most recent root prior to slot
// return root
func (s *Service) ancestor(ctx context.Context, root []byte, slot uint64) ([]byte, error) {
func (s *Service) ancestor(ctx context.Context, root []byte, slot types.Slot) ([]byte, error) {
ctx, span := trace.StartSpan(ctx, "blockChain.ancestor")
defer span.End()
@@ -275,7 +278,7 @@ func (s *Service) ancestor(ctx context.Context, root []byte, slot uint64) ([]byt
}
// This retrieves an ancestor root using fork choice store. The look up is looping through the a flat array structure.
func (s *Service) ancestorByForkChoiceStore(ctx context.Context, r [32]byte, slot uint64) ([]byte, error) {
func (s *Service) ancestorByForkChoiceStore(ctx context.Context, r [32]byte, slot types.Slot) ([]byte, error) {
ctx, span := trace.StartSpan(ctx, "blockChain.ancestorByForkChoiceStore")
defer span.End()
@@ -286,7 +289,7 @@ func (s *Service) ancestorByForkChoiceStore(ctx context.Context, r [32]byte, slo
}
// This retrieves an ancestor root using DB. The look up is recursively looking up DB. Slower than `ancestorByForkChoiceStore`.
func (s *Service) ancestorByDB(ctx context.Context, r [32]byte, slot uint64) ([]byte, error) {
func (s *Service) ancestorByDB(ctx context.Context, r [32]byte, slot types.Slot) ([]byte, error) {
ctx, span := trace.StartSpan(ctx, "blockChain.ancestorByDB")
defer span.End()
@@ -404,6 +407,30 @@ func (s *Service) fillInForkChoiceMissingBlocks(ctx context.Context, blk *ethpb.
return nil
}
// inserts finalized deposits into our finalized deposit trie.
func (s *Service) insertFinalizedDeposits(ctx context.Context, fRoot [32]byte) error {
ctx, span := trace.StartSpan(ctx, "blockChain.insertFinalizedDeposits")
defer span.End()
// Update deposit cache.
finalizedState, err := s.stateGen.StateByRoot(ctx, fRoot)
if err != nil {
return errors.Wrap(err, "could not fetch finalized state")
}
// We update the cache up to the last deposit index in the finalized block's state.
// We can be confident that these deposits will be included in some block
// because the Eth1 follow distance makes such long-range reorgs extremely unlikely.
eth1DepositIndex := int64(finalizedState.Eth1Data().DepositCount - 1)
s.depositCache.InsertFinalizedDeposits(ctx, eth1DepositIndex)
if featureconfig.Get().EnablePruningDepositProofs {
// Deposit proofs are only used during state transition and can be safely removed to save space.
if err = s.depositCache.PruneProofs(ctx, eth1DepositIndex); err != nil {
return errors.Wrap(err, "could not prune deposit proofs")
}
}
return nil
}
// The deletes input attestations from the attestation pool, so proposers don't include them in a block for the future.
func (s *Service) deletePoolAtts(atts []*ethpb.Attestation) error {
for _, att := range atts {

View File

@@ -3,10 +3,13 @@ package blockchain
import (
"context"
"fmt"
"math/big"
"strconv"
"testing"
"time"
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
@@ -19,6 +22,7 @@ import (
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/attestationutil"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/featureconfig"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
@@ -42,9 +46,10 @@ func TestStore_OnBlock(t *testing.T) {
assert.NoError(t, beaconDB.SaveBlock(ctx, genesis))
validGenesisRoot, err := genesis.Block.HashTreeRoot()
require.NoError(t, err)
st := testutil.NewBeaconState()
st, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, service.beaconDB.SaveState(ctx, st.Copy(), validGenesisRoot))
roots, err := blockTree1(beaconDB, validGenesisRoot[:])
roots, err := blockTree1(t, beaconDB, validGenesisRoot[:])
require.NoError(t, err)
random := testutil.NewBeaconBlock()
random.Block.Slot = 1
@@ -76,7 +81,7 @@ func TestStore_OnBlock(t *testing.T) {
blk: func() *ethpb.SignedBeaconBlock {
b := testutil.NewBeaconBlock()
b.Block.ParentRoot = randomParentRoot2
b.Block.Slot = params.BeaconConfig().FarFutureEpoch
b.Block.Slot = params.BeaconConfig().FarFutureSlot
return b
}(),
s: st.Copy(),
@@ -151,7 +156,7 @@ func TestStore_OnBlockBatch(t *testing.T) {
var blkRoots [][32]byte
var firstState *stateTrie.BeaconState
for i := 1; i < 10; i++ {
b, err := testutil.GenerateFullBlock(bState, keys, testutil.DefaultBlockGenConfig(), uint64(i))
b, err := testutil.GenerateFullBlock(bState, keys, testutil.DefaultBlockGenConfig(), types.Slot(i))
require.NoError(t, err)
bState, err = state.ExecuteStateTransition(ctx, bState, b)
require.NoError(t, err)
@@ -198,7 +203,7 @@ func TestRemoveStateSinceLastFinalized_EmptyStartSlot(t *testing.T) {
require.NoError(t, service.beaconDB.SaveBlock(ctx, newJustifiedBlk))
require.NoError(t, service.beaconDB.SaveBlock(ctx, lastJustifiedBlk))
diff := (params.BeaconConfig().SlotsPerEpoch - 1) * params.BeaconConfig().SecondsPerSlot
diff := params.BeaconConfig().SlotsPerEpoch.Sub(1).Mul(params.BeaconConfig().SecondsPerSlot)
service.genesisTime = time.Unix(time.Now().Unix()-int64(diff), 0)
service.justifiedCheckpt = &ethpb.Checkpoint{Root: lastJustifiedRoot[:]}
update, err = service.shouldUpdateCurrentJustified(ctx, &ethpb.Checkpoint{Root: newJustifiedRoot[:]})
@@ -226,7 +231,7 @@ func TestShouldUpdateJustified_ReturnFalse(t *testing.T) {
require.NoError(t, service.beaconDB.SaveBlock(ctx, newJustifiedBlk))
require.NoError(t, service.beaconDB.SaveBlock(ctx, lastJustifiedBlk))
diff := (params.BeaconConfig().SlotsPerEpoch - 1) * params.BeaconConfig().SecondsPerSlot
diff := params.BeaconConfig().SlotsPerEpoch.Sub(1).Mul(params.BeaconConfig().SecondsPerSlot)
service.genesisTime = time.Unix(time.Now().Unix()-int64(diff), 0)
service.justifiedCheckpt = &ethpb.Checkpoint{Root: lastJustifiedRoot[:]}
@@ -319,11 +324,13 @@ func TestUpdateJustified_CouldUpdateBest(t *testing.T) {
require.NoError(t, err)
service.justifiedCheckpt = &ethpb.Checkpoint{Root: []byte{'A'}}
service.bestJustifiedCheckpt = &ethpb.Checkpoint{Root: []byte{'A'}}
st := testutil.NewBeaconState()
st, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, beaconDB.SaveState(ctx, st.Copy(), r))
// Could update
s := testutil.NewBeaconState()
s, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, s.SetCurrentJustifiedCheckpoint(&ethpb.Checkpoint{Epoch: 1, Root: r[:]}))
require.NoError(t, service.updateJustified(context.Background(), s))
@@ -333,7 +340,7 @@ func TestUpdateJustified_CouldUpdateBest(t *testing.T) {
service.bestJustifiedCheckpt.Epoch = 2
require.NoError(t, service.updateJustified(context.Background(), s))
assert.Equal(t, uint64(2), service.bestJustifiedCheckpt.Epoch, "Incorrect justified epoch in service")
assert.Equal(t, types.Epoch(2), service.bestJustifiedCheckpt.Epoch, "Incorrect justified epoch in service")
}
func TestFillForkChoiceMissingBlocks_CanSave(t *testing.T) {
@@ -351,10 +358,11 @@ func TestFillForkChoiceMissingBlocks_CanSave(t *testing.T) {
require.NoError(t, beaconDB.SaveBlock(ctx, genesis))
validGenesisRoot, err := genesis.Block.HashTreeRoot()
require.NoError(t, err)
st := testutil.NewBeaconState()
st, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, service.beaconDB.SaveState(ctx, st.Copy(), validGenesisRoot))
roots, err := blockTree1(beaconDB, validGenesisRoot[:])
roots, err := blockTree1(t, beaconDB, validGenesisRoot[:])
require.NoError(t, err)
beaconState, _ := testutil.DeterministicGenesisState(t, 32)
@@ -388,10 +396,11 @@ func TestFillForkChoiceMissingBlocks_RootsMatch(t *testing.T) {
require.NoError(t, beaconDB.SaveBlock(ctx, genesis))
validGenesisRoot, err := genesis.Block.HashTreeRoot()
require.NoError(t, err)
st := testutil.NewBeaconState()
st, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, service.beaconDB.SaveState(ctx, st.Copy(), validGenesisRoot))
roots, err := blockTree1(beaconDB, validGenesisRoot[:])
roots, err := blockTree1(t, beaconDB, validGenesisRoot[:])
require.NoError(t, err)
beaconState, _ := testutil.DeterministicGenesisState(t, 32)
@@ -429,7 +438,8 @@ func TestFillForkChoiceMissingBlocks_FilterFinalized(t *testing.T) {
assert.NoError(t, beaconDB.SaveBlock(ctx, genesis))
validGenesisRoot, err := genesis.Block.HashTreeRoot()
assert.NoError(t, err)
st := testutil.NewBeaconState()
st, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, service.beaconDB.SaveState(ctx, st.Copy(), validGenesisRoot))
@@ -467,7 +477,7 @@ func TestFillForkChoiceMissingBlocks_FilterFinalized(t *testing.T) {
// B0 /- B5 - B7
// \- B3 - B4 - B6 - B8
// (B1, and B3 are all from the same slots)
func blockTree1(beaconDB db.Database, genesisRoot []byte) ([][]byte, error) {
func blockTree1(t *testing.T, beaconDB db.Database, genesisRoot []byte) ([][]byte, error) {
genesisRoot = bytesutil.PadTo(genesisRoot, 32)
b0 := testutil.NewBeaconBlock()
b0.Block.Slot = 0
@@ -525,7 +535,8 @@ func blockTree1(beaconDB db.Database, genesisRoot []byte) ([][]byte, error) {
if err != nil {
return nil, err
}
st := testutil.NewBeaconState()
st, err := testutil.NewBeaconState()
require.NoError(t, err)
for _, b := range []*ethpb.SignedBeaconBlock{b0, b1, b3, b4, b5, b6, b7, b8} {
beaconBlock := testutil.NewBeaconBlock()
@@ -554,7 +565,7 @@ func TestCurrentSlot_HandlesOverflow(t *testing.T) {
svc := Service{genesisTime: timeutils.Now().Add(1 * time.Hour)}
slot := svc.CurrentSlot()
require.Equal(t, uint64(0), slot, "Unexpected slot")
require.Equal(t, types.Slot(0), slot, "Unexpected slot")
}
func TestAncestorByDB_CtxErr(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
@@ -741,13 +752,15 @@ func TestFinalizedImpliesNewJustified(t *testing.T) {
},
}
for _, test := range tests {
beaconState := testutil.NewBeaconState()
beaconState, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(test.args.stateCheckPoint))
service, err := NewService(ctx, &Config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB), ForkChoiceStore: protoarray.New(0, 0, [32]byte{})})
require.NoError(t, err)
service.justifiedCheckpt = test.args.cachedCheckPoint
require.NoError(t, service.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{Root: bytesutil.PadTo(test.want.Root, 32)}))
genesisState := testutil.NewBeaconState()
genesisState, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, service.beaconDB.SaveState(ctx, genesisState, bytesutil.ToBytes32(test.want.Root)))
if test.args.diffFinalizedCheckPoint {
@@ -870,11 +883,11 @@ func TestUpdateJustifiedInitSync(t *testing.T) {
require.NoError(t, service.updateJustifiedInitSync(ctx, newCp))
assert.DeepEqual(t, currentCp, service.prevJustifiedCheckpt, "Incorrect previous justified checkpoint")
assert.DeepEqual(t, newCp, service.CurrentJustifiedCheckpt(), "Incorrect current justified checkpoint in cache")
assert.DeepSSZEqual(t, currentCp, service.prevJustifiedCheckpt, "Incorrect previous justified checkpoint")
assert.DeepSSZEqual(t, newCp, service.CurrentJustifiedCheckpt(), "Incorrect current justified checkpoint in cache")
cp, err := service.beaconDB.JustifiedCheckpoint(ctx)
require.NoError(t, err)
assert.DeepEqual(t, newCp, cp, "Incorrect current justified checkpoint in db")
assert.DeepSSZEqual(t, newCp, cp, "Incorrect current justified checkpoint in db")
}
func TestHandleEpochBoundary_BadMetrics(t *testing.T) {
@@ -883,7 +896,8 @@ func TestHandleEpochBoundary_BadMetrics(t *testing.T) {
service, err := NewService(ctx, cfg)
require.NoError(t, err)
s := testutil.NewBeaconState()
s, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, s.SetSlot(1))
service.head = &head{}
require.ErrorContains(t, "failed to initialize precompute: nil inner state", service.handleEpochBoundary(ctx, s))
@@ -925,7 +939,7 @@ func TestOnBlock_CanFinalize(t *testing.T) {
service.finalizedCheckpt = &ethpb.Checkpoint{Root: gRoot[:]}
testState := gs.Copy()
for i := uint64(1); i <= 4*params.BeaconConfig().SlotsPerEpoch; i++ {
for i := types.Slot(1); i <= 4*params.BeaconConfig().SlotsPerEpoch; i++ {
blk, err := testutil.GenerateFullBlock(testState, keys, testutil.DefaultBlockGenConfig(), i)
require.NoError(t, err)
r, err := blk.Block.HashTreeRoot()
@@ -934,6 +948,54 @@ func TestOnBlock_CanFinalize(t *testing.T) {
testState, err = service.stateGen.StateByRoot(ctx, r)
require.NoError(t, err)
}
require.Equal(t, uint64(3), service.CurrentJustifiedCheckpt().Epoch)
require.Equal(t, uint64(2), service.FinalizedCheckpt().Epoch)
require.Equal(t, types.Epoch(3), service.CurrentJustifiedCheckpt().Epoch)
require.Equal(t, types.Epoch(2), service.FinalizedCheckpt().Epoch)
}
func TestInsertFinalizedDeposits(t *testing.T) {
flags := featureconfig.Get()
flags.EnablePruningDepositProofs = true
reset := featureconfig.InitWithReset(flags)
defer reset()
ctx := context.Background()
beaconDB := testDB.SetupDB(t)
depositCache, err := depositcache.New()
require.NoError(t, err)
cfg := &Config{
BeaconDB: beaconDB,
StateGen: stategen.New(beaconDB),
ForkChoiceStore: protoarray.New(0, 0, [32]byte{}),
DepositCache: depositCache,
}
service, err := NewService(ctx, cfg)
require.NoError(t, err)
gs, _ := testutil.DeterministicGenesisState(t, 32)
require.NoError(t, service.saveGenesisData(ctx, gs))
gBlk, err := service.beaconDB.GenesisBlock(ctx)
require.NoError(t, err)
gRoot, err := gBlk.Block.HashTreeRoot()
require.NoError(t, err)
service.finalizedCheckpt = &ethpb.Checkpoint{Root: gRoot[:]}
gs = gs.Copy()
assert.NoError(t, gs.SetEth1Data(&ethpb.Eth1Data{DepositCount: 10}))
assert.NoError(t, service.stateGen.SaveState(ctx, [32]byte{'m', 'o', 'c', 'k'}, gs))
zeroSig := [96]byte{}
for i := uint64(0); i < uint64(4*params.BeaconConfig().SlotsPerEpoch); i++ {
root := []byte(strconv.Itoa(int(i)))
depositCache.InsertDeposit(ctx, &ethpb.Deposit{Data: &ethpb.Deposit_Data{
PublicKey: bytesutil.FromBytes48([48]byte{}),
WithdrawalCredentials: params.BeaconConfig().ZeroHash[:],
Amount: 0,
Signature: zeroSig[:],
}, Proof: [][]byte{root}}, 100+i, int64(i), bytesutil.ToBytes32(root))
}
assert.NoError(t, service.insertFinalizedDeposits(ctx, [32]byte{'m', 'o', 'c', 'k'}))
fDeposits := depositCache.FinalizedDeposits(ctx)
assert.Equal(t, 9, int(fDeposits.MerkleTrieIndex), "Finalized deposits not inserted correctly")
deps := depositCache.AllDeposits(ctx, big.NewInt(109))
for _, d := range deps {
assert.DeepEqual(t, [][]byte(nil), d.Proof, "Proofs are not empty")
}
}

View File

@@ -35,16 +35,10 @@ func (s *Service) ReceiveAttestationNoPubsub(ctx context.Context, att *ethpb.Att
ctx, span := trace.StartSpan(ctx, "beacon-chain.blockchain.ReceiveAttestationNoPubsub")
defer span.End()
_, err := s.onAttestation(ctx, att)
if err != nil {
if err := s.onAttestation(ctx, att); err != nil {
return errors.Wrap(err, "could not process attestation")
}
if err := s.updateHead(ctx, s.getJustifiedBalances()); err != nil {
log.Warnf("Resolving fork due to new attestation: %v", err)
return nil
}
return nil
}
@@ -62,7 +56,18 @@ func (s *Service) AttestationPreState(ctx context.Context, att *ethpb.Attestatio
// VerifyLmdFfgConsistency verifies that attestation's LMD and FFG votes are consistency to each other.
func (s *Service) VerifyLmdFfgConsistency(ctx context.Context, a *ethpb.Attestation) error {
return s.verifyLMDFFGConsistent(ctx, a.Data.Target.Epoch, a.Data.Target.Root, a.Data.BeaconBlockRoot)
targetSlot, err := helpers.StartSlot(a.Data.Target.Epoch)
if err != nil {
return err
}
r, err := s.ancestor(ctx, a.Data.BeaconBlockRoot, targetSlot)
if err != nil {
return err
}
if !bytes.Equal(a.Data.Target.Root, r) {
return errors.New("FFG and LMD votes are not consistent")
}
return nil
}
// VerifyFinalizedConsistency verifies input root is consistent with finalized store.
@@ -91,8 +96,8 @@ func (s *Service) VerifyFinalizedConsistency(ctx context.Context, root []byte) e
return nil
}
// This processes attestations from the attestation pool to account for validator votes and fork choice.
func (s *Service) processAttestation(subscribedToStateEvents chan struct{}) {
// This routine processes fork choice attestations from the pool to account for validator votes and fork choice.
func (s *Service) processAttestationsRoutine(subscribedToStateEvents chan struct{}) {
// Wait for state to be initialized.
stateChannel := make(chan *feed.Event, 1)
stateSub := s.stateNotifier.StateFeed().Subscribe(stateChannel)
@@ -108,47 +113,59 @@ func (s *Service) processAttestation(subscribedToStateEvents chan struct{}) {
log.Warn("Genesis time received, now available to process attestations")
}
st := slotutil.GetSlotTicker(s.genesisTime, params.BeaconConfig().SecondsPerSlot)
st := slotutil.NewSlotTicker(s.genesisTime, params.BeaconConfig().SecondsPerSlot)
for {
select {
case <-s.ctx.Done():
return
case <-st.C():
ctx := s.ctx
atts := s.attPool.ForkchoiceAttestations()
for _, a := range atts {
// Based on the spec, don't process the attestation until the subsequent slot.
// This delays consideration in the fork choice until their slot is in the past.
// https://github.com/ethereum/eth2.0-specs/blob/dev/specs/phase0/fork-choice.md#validate_on_attestation
nextSlot := a.Data.Slot + 1
if err := helpers.VerifySlotTime(uint64(s.genesisTime.Unix()), nextSlot, params.BeaconNetworkConfig().MaximumGossipClockDisparity); err != nil {
continue
}
hasState := s.beaconDB.HasStateSummary(ctx, bytesutil.ToBytes32(a.Data.BeaconBlockRoot))
hasBlock := s.hasBlock(ctx, bytesutil.ToBytes32(a.Data.BeaconBlockRoot))
if !(hasState && hasBlock) {
continue
}
if err := s.attPool.DeleteForkchoiceAttestation(a); err != nil {
log.WithError(err).Error("Could not delete fork choice attestation in pool")
}
if !helpers.VerifyCheckpointEpoch(a.Data.Target, s.genesisTime) {
continue
}
if err := s.ReceiveAttestationNoPubsub(ctx, a); err != nil {
log.WithFields(logrus.Fields{
"slot": a.Data.Slot,
"committeeIndex": a.Data.CommitteeIndex,
"beaconBlockRoot": fmt.Sprintf("%#x", bytesutil.Trunc(a.Data.BeaconBlockRoot)),
"targetRoot": fmt.Sprintf("%#x", bytesutil.Trunc(a.Data.Target.Root)),
"aggregationCount": a.AggregationBits.Count(),
}).WithError(err).Warn("Could not receive attestation in chain service")
}
// Continue when there's no fork choice attestation, there's nothing to process and update head.
// This covers the condition when the node is still initial syncing to the head of the chain.
if s.attPool.ForkchoiceAttestationCount() == 0 {
continue
}
s.processAttestations(s.ctx)
if err := s.updateHead(s.ctx, s.getJustifiedBalances()); err != nil {
log.Warnf("Resolving fork due to new attestation: %v", err)
}
}
}
}
// This processes fork choice attestations from the pool to account for validator votes and fork choice.
func (s *Service) processAttestations(ctx context.Context) {
atts := s.attPool.ForkchoiceAttestations()
for _, a := range atts {
// Based on the spec, don't process the attestation until the subsequent slot.
// This delays consideration in the fork choice until their slot is in the past.
// https://github.com/ethereum/eth2.0-specs/blob/dev/specs/phase0/fork-choice.md#validate_on_attestation
nextSlot := a.Data.Slot + 1
if err := helpers.VerifySlotTime(uint64(s.genesisTime.Unix()), nextSlot, params.BeaconNetworkConfig().MaximumGossipClockDisparity); err != nil {
continue
}
hasState := s.beaconDB.HasStateSummary(ctx, bytesutil.ToBytes32(a.Data.BeaconBlockRoot))
hasBlock := s.hasBlock(ctx, bytesutil.ToBytes32(a.Data.BeaconBlockRoot))
if !(hasState && hasBlock) {
continue
}
if err := s.attPool.DeleteForkchoiceAttestation(a); err != nil {
log.WithError(err).Error("Could not delete fork choice attestation in pool")
}
if !helpers.VerifyCheckpointEpoch(a.Data.Target, s.genesisTime) {
continue
}
if err := s.ReceiveAttestationNoPubsub(ctx, a); err != nil {
log.WithFields(logrus.Fields{
"slot": a.Data.Slot,
"committeeIndex": a.Data.CommitteeIndex,
"beaconBlockRoot": fmt.Sprintf("%#x", bytesutil.Trunc(a.Data.BeaconBlockRoot)),
"targetRoot": fmt.Sprintf("%#x", bytesutil.Trunc(a.Data.Target.Root)),
"aggregationCount": a.AggregationBits.Count(),
}).WithError(err).Warn("Could not process attestation for fork choice")
}
}
}

View File

@@ -5,11 +5,20 @@ import (
"testing"
"time"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"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"
"github.com/prysmaticlabs/prysm/beacon-chain/operations/attestations"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
"github.com/prysmaticlabs/prysm/shared/timeutils"
logTest "github.com/sirupsen/logrus/hooks/test"
)
func TestAttestationCheckPtState_FarFutureSlot(t *testing.T) {
@@ -19,7 +28,94 @@ func TestAttestationCheckPtState_FarFutureSlot(t *testing.T) {
chainService := setupBeaconChain(t, beaconDB)
chainService.genesisTime = time.Now()
e := helpers.MaxSlotBuffer/params.BeaconConfig().SlotsPerEpoch + 1
e := types.Epoch(helpers.MaxSlotBuffer/uint64(params.BeaconConfig().SlotsPerEpoch) + 1)
_, err := chainService.AttestationPreState(context.Background(), &ethpb.Attestation{Data: &ethpb.AttestationData{Target: &ethpb.Checkpoint{Epoch: e}}})
require.ErrorContains(t, "exceeds max allowed value relative to the local clock", err)
}
func TestVerifyLMDFFGConsistent_NotOK(t *testing.T) {
ctx := context.Background()
beaconDB := testDB.SetupDB(t)
cfg := &Config{BeaconDB: beaconDB, ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}
service, err := NewService(ctx, cfg)
require.NoError(t, err)
b32 := testutil.NewBeaconBlock()
b32.Block.Slot = 32
require.NoError(t, service.beaconDB.SaveBlock(ctx, b32))
r32, err := b32.Block.HashTreeRoot()
require.NoError(t, err)
b33 := testutil.NewBeaconBlock()
b33.Block.Slot = 33
b33.Block.ParentRoot = r32[:]
require.NoError(t, service.beaconDB.SaveBlock(ctx, b33))
r33, err := b33.Block.HashTreeRoot()
require.NoError(t, err)
wanted := "FFG and LMD votes are not consistent"
a := testutil.NewAttestation()
a.Data.Target.Epoch = 1
a.Data.Target.Root = []byte{'a'}
a.Data.BeaconBlockRoot = r33[:]
require.ErrorContains(t, wanted, service.VerifyLmdFfgConsistency(context.Background(), a))
}
func TestVerifyLMDFFGConsistent_OK(t *testing.T) {
ctx := context.Background()
beaconDB := testDB.SetupDB(t)
cfg := &Config{BeaconDB: beaconDB, ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}
service, err := NewService(ctx, cfg)
require.NoError(t, err)
b32 := testutil.NewBeaconBlock()
b32.Block.Slot = 32
require.NoError(t, service.beaconDB.SaveBlock(ctx, b32))
r32, err := b32.Block.HashTreeRoot()
require.NoError(t, err)
b33 := testutil.NewBeaconBlock()
b33.Block.Slot = 33
b33.Block.ParentRoot = r32[:]
require.NoError(t, service.beaconDB.SaveBlock(ctx, b33))
r33, err := b33.Block.HashTreeRoot()
require.NoError(t, err)
a := testutil.NewAttestation()
a.Data.Target.Epoch = 1
a.Data.Target.Root = r32[:]
a.Data.BeaconBlockRoot = r33[:]
err = service.VerifyLmdFfgConsistency(context.Background(), a)
require.NoError(t, err, "Could not verify LMD and FFG votes to be consistent")
}
func TestProcessAttestations_Ok(t *testing.T) {
hook := logTest.NewGlobal()
ctx := context.Background()
beaconDB := testDB.SetupDB(t)
cfg := &Config{
BeaconDB: beaconDB,
ForkChoiceStore: protoarray.New(0, 0, [32]byte{}),
StateGen: stategen.New(beaconDB),
AttPool: attestations.NewPool(),
}
service, err := NewService(ctx, cfg)
service.genesisTime = timeutils.Now().Add(-1 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second)
require.NoError(t, err)
genesisState, pks := testutil.DeterministicGenesisState(t, 64)
require.NoError(t, genesisState.SetGenesisTime(uint64(timeutils.Now().Unix())-params.BeaconConfig().SecondsPerSlot))
require.NoError(t, service.saveGenesisData(ctx, genesisState))
atts, err := testutil.GenerateAttestations(genesisState, pks, 1, 0, false)
require.NoError(t, err)
tRoot := bytesutil.ToBytes32(atts[0].Data.Target.Root)
copied := genesisState.Copy()
copied, err = state.ProcessSlots(ctx, copied, 1)
require.NoError(t, err)
require.NoError(t, service.beaconDB.SaveState(ctx, copied, tRoot))
require.NoError(t, service.forkChoiceStore.ProcessBlock(ctx, 0, tRoot, tRoot, tRoot, 1, 1))
require.NoError(t, service.attPool.SaveForkchoiceAttestations(atts))
service.processAttestations(ctx)
require.Equal(t, 0, len(service.attPool.ForkchoiceAttestations()))
require.LogsDoNotContain(t, hook, "Could not process attestation for fork choice")
}

View File

@@ -4,18 +4,21 @@ import (
"context"
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/shared/featureconfig"
"github.com/prysmaticlabs/prysm/shared/timeutils"
"github.com/prysmaticlabs/prysm/shared/traceutil"
"github.com/sirupsen/logrus"
"go.opencensus.io/trace"
)
// This defines how many epochs since finality the run time will begin to save hot state on to the DB.
var epochsSinceFinalitySaveHotStateDB = 100
var epochsSinceFinalitySaveHotStateDB = types.Epoch(100)
// BlockReceiver interface defines the methods of chain service receive and processing new blocks.
type BlockReceiver interface {
@@ -33,6 +36,7 @@ type BlockReceiver interface {
func (s *Service) ReceiveBlock(ctx context.Context, block *ethpb.SignedBeaconBlock, blockRoot [32]byte) error {
ctx, span := trace.StartSpan(ctx, "blockChain.ReceiveBlock")
defer span.End()
receivedTime := timeutils.Now()
blockCopy := stateTrie.CopySignedBeaconBlock(block)
// Apply state transition on the new block.
@@ -43,21 +47,22 @@ func (s *Service) ReceiveBlock(ctx context.Context, block *ethpb.SignedBeaconBlo
}
// Update and save head block after fork choice.
if err := s.updateHead(ctx, s.getJustifiedBalances()); err != nil {
log.WithError(err).Warn("Could not update head")
if !featureconfig.Get().UpdateHeadTimely {
if err := s.updateHead(ctx, s.getJustifiedBalances()); err != nil {
log.WithError(err).Warn("Could not update head")
}
// Send notification of the processed block to the state feed.
s.stateNotifier.StateFeed().Send(&feed.Event{
Type: statefeed.BlockProcessed,
Data: &statefeed.BlockProcessedData{
Slot: blockCopy.Block.Slot,
BlockRoot: blockRoot,
SignedBlock: blockCopy,
Verified: true,
},
})
}
// Send notification of the processed block to the state feed.
s.stateNotifier.StateFeed().Send(&feed.Event{
Type: statefeed.BlockProcessed,
Data: &statefeed.BlockProcessedData{
Slot: blockCopy.Block.Slot,
BlockRoot: blockRoot,
SignedBlock: blockCopy,
Verified: true,
},
})
// Handle post block operations such as attestations and exits.
if err := s.handlePostBlockOperations(blockCopy.Block); err != nil {
return err
@@ -72,8 +77,9 @@ func (s *Service) ReceiveBlock(ctx context.Context, block *ethpb.SignedBeaconBlo
reportSlotMetrics(blockCopy.Block.Slot, s.HeadSlot(), s.CurrentSlot(), s.finalizedCheckpt)
// Log block sync status.
logBlockSyncStatus(blockCopy.Block, blockRoot, s.finalizedCheckpt)
if err := logBlockSyncStatus(blockCopy.Block, blockRoot, s.finalizedCheckpt, receivedTime, uint64(s.genesisTime.Unix())); err != nil {
return err
}
// Log state transition data.
logStateTransitionData(blockCopy.Block)
@@ -197,12 +203,12 @@ func (s *Service) handlePostBlockOperations(b *ethpb.BeaconBlock) error {
func (s *Service) checkSaveHotStateDB(ctx context.Context) error {
currentEpoch := helpers.SlotToEpoch(s.CurrentSlot())
// Prevent `sinceFinality` going underflow.
var sinceFinality uint64
var sinceFinality types.Epoch
if currentEpoch > s.finalizedCheckpt.Epoch {
sinceFinality = currentEpoch - s.finalizedCheckpt.Epoch
}
if sinceFinality >= uint64(epochsSinceFinalitySaveHotStateDB) {
if sinceFinality >= epochsSinceFinalitySaveHotStateDB {
s.stateGen.EnableSaveHotStateToDB(ctx)
return nil
}

View File

@@ -6,6 +6,7 @@ import (
"testing"
"time"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
blockchainTesting "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
@@ -25,7 +26,7 @@ func TestService_ReceiveBlock(t *testing.T) {
ctx := context.Background()
genesis, keys := testutil.DeterministicGenesisState(t, 64)
genFullBlock := func(t *testing.T, conf *testutil.BlockGenConfig, slot uint64) *ethpb.SignedBeaconBlock {
genFullBlock := func(t *testing.T, conf *testutil.BlockGenConfig, slot types.Slot) *ethpb.SignedBeaconBlock {
blk, err := testutil.GenerateFullBlock(genesis, keys, conf, slot)
assert.NoError(t, err)
return blk
@@ -202,7 +203,7 @@ func TestService_ReceiveBlockInitialSync(t *testing.T) {
ctx := context.Background()
genesis, keys := testutil.DeterministicGenesisState(t, 64)
genFullBlock := func(t *testing.T, conf *testutil.BlockGenConfig, slot uint64) *ethpb.SignedBeaconBlock {
genFullBlock := func(t *testing.T, conf *testutil.BlockGenConfig, slot types.Slot) *ethpb.SignedBeaconBlock {
blk, err := testutil.GenerateFullBlock(genesis, keys, conf, slot)
assert.NoError(t, err)
return blk
@@ -223,8 +224,8 @@ func TestService_ReceiveBlockInitialSync(t *testing.T) {
block: genFullBlock(t, testutil.DefaultBlockGenConfig(), 2 /*slot*/),
},
check: func(t *testing.T, s *Service) {
assert.Equal(t, uint64(2), s.head.state.Slot(), "Incorrect head state slot")
assert.Equal(t, uint64(2), s.head.block.Block.Slot, "Incorrect head block slot")
assert.Equal(t, types.Slot(2), s.head.state.Slot(), "Incorrect head state slot")
assert.Equal(t, types.Slot(2), s.head.block.Block.Slot, "Incorrect head block slot")
},
},
{
@@ -283,7 +284,7 @@ func TestService_ReceiveBlockBatch(t *testing.T) {
ctx := context.Background()
genesis, keys := testutil.DeterministicGenesisState(t, 64)
genFullBlock := func(t *testing.T, conf *testutil.BlockGenConfig, slot uint64) *ethpb.SignedBeaconBlock {
genFullBlock := func(t *testing.T, conf *testutil.BlockGenConfig, slot types.Slot) *ethpb.SignedBeaconBlock {
blk, err := testutil.GenerateFullBlock(genesis, keys, conf, slot)
assert.NoError(t, err)
return blk
@@ -304,8 +305,8 @@ func TestService_ReceiveBlockBatch(t *testing.T) {
block: genFullBlock(t, testutil.DefaultBlockGenConfig(), 2 /*slot*/),
},
check: func(t *testing.T, s *Service) {
assert.Equal(t, uint64(2), s.head.state.Slot(), "Incorrect head state slot")
assert.Equal(t, uint64(2), s.head.block.Block.Slot, "Incorrect head block slot")
assert.Equal(t, types.Slot(2), s.head.state.Slot(), "Incorrect head state slot")
assert.Equal(t, types.Slot(2), s.head.block.Block.Slot, "Incorrect head block slot")
},
},
{
@@ -379,7 +380,7 @@ func TestCheckSaveHotStateDB_Enabling(t *testing.T) {
hook := logTest.NewGlobal()
s, err := NewService(context.Background(), &Config{StateGen: stategen.New(beaconDB)})
require.NoError(t, err)
st := params.BeaconConfig().SlotsPerEpoch * uint64(epochsSinceFinalitySaveHotStateDB)
st := params.BeaconConfig().SlotsPerEpoch.Mul(uint64(epochsSinceFinalitySaveHotStateDB))
s.genesisTime = time.Now().Add(time.Duration(-1*int64(st)*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second)
s.finalizedCheckpt = &ethpb.Checkpoint{}

View File

@@ -11,6 +11,7 @@ import (
"time"
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
@@ -66,7 +67,7 @@ type Service struct {
bestJustifiedCheckpt *ethpb.Checkpoint
finalizedCheckpt *ethpb.Checkpoint
prevFinalizedCheckpt *ethpb.Checkpoint
nextEpochBoundarySlot uint64
nextEpochBoundarySlot types.Slot
boundaryRoots [][32]byte
checkpointStateCache *cache.CheckpointStateCache
stateGen *stategen.State
@@ -75,7 +76,7 @@ type Service struct {
initSyncBlocksLock sync.RWMutex
justifiedBalances []uint64
justifiedBalancesLock sync.RWMutex
wsEpoch uint64
wsEpoch types.Epoch
wsRoot []byte
wsVerified bool
}
@@ -96,7 +97,7 @@ type Config struct {
OpsService *attestations.Service
StateGen *stategen.State
WspBlockRoot []byte
WspEpoch uint64
WspEpoch types.Epoch
}
// NewService instantiates a new block service instance that will
@@ -263,7 +264,7 @@ func (s *Service) Start() {
}()
}
go s.processAttestation(attestationProcessorSubscribed)
go s.processAttestationsRoutine(attestationProcessorSubscribed)
}
// processChainStartTime initializes a series of deposits from the ChainStart deposits in the eth1
@@ -323,7 +324,7 @@ func (s *Service) initializeBeaconChain(
if err := helpers.UpdateCommitteeCache(genesisState, 0 /* genesis epoch */); err != nil {
return nil, err
}
if err := helpers.UpdateProposerIndicesInCache(genesisState, 0 /* genesis epoch */); err != nil {
if err := helpers.UpdateProposerIndicesInCache(genesisState); err != nil {
return nil, err
}
@@ -458,7 +459,7 @@ func (s *Service) initializeChainInfo(ctx context.Context) error {
return errors.Wrap(err, "could not retrieve head block")
}
headEpoch := helpers.SlotToEpoch(headBlock.Block.Slot)
var epochsSinceFinality uint64
var epochsSinceFinality types.Epoch
if headEpoch > finalized.Epoch {
epochsSinceFinality = headEpoch - finalized.Epoch
}

View File

@@ -12,6 +12,8 @@ import (
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"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"
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
"github.com/prysmaticlabs/prysm/beacon-chain/db"
@@ -131,7 +133,8 @@ func TestChainStartStop_Initialized(t *testing.T) {
blkRoot, err := genesisBlk.Block.HashTreeRoot()
require.NoError(t, err)
require.NoError(t, beaconDB.SaveBlock(ctx, genesisBlk))
s := testutil.NewBeaconState()
s, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, s.SetSlot(1))
require.NoError(t, beaconDB.SaveState(ctx, s, blkRoot))
require.NoError(t, beaconDB.SaveHeadBlockRoot(ctx, blkRoot))
@@ -160,7 +163,8 @@ func TestChainStartStop_GenesisZeroHashes(t *testing.T) {
blkRoot, err := genesisBlk.Block.HashTreeRoot()
require.NoError(t, err)
require.NoError(t, beaconDB.SaveBlock(ctx, genesisBlk))
s := testutil.NewBeaconState()
s, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, beaconDB.SaveState(ctx, s, blkRoot))
require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, blkRoot))
require.NoError(t, beaconDB.SaveJustifiedCheckpoint(ctx, &ethpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]}))
@@ -228,7 +232,8 @@ func TestChainService_CorrectGenesisRoots(t *testing.T) {
blkRoot, err := genesisBlk.Block.HashTreeRoot()
require.NoError(t, err)
require.NoError(t, beaconDB.SaveBlock(ctx, genesisBlk))
s := testutil.NewBeaconState()
s, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, s.SetSlot(0))
require.NoError(t, beaconDB.SaveState(ctx, s, blkRoot))
require.NoError(t, beaconDB.SaveHeadBlockRoot(ctx, blkRoot))
@@ -259,7 +264,8 @@ func TestChainService_InitializeChainInfo(t *testing.T) {
headBlock := testutil.NewBeaconBlock()
headBlock.Block.Slot = finalizedSlot
headBlock.Block.ParentRoot = bytesutil.PadTo(genesisRoot[:], 32)
headState := testutil.NewBeaconState()
headState, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, headState.SetSlot(finalizedSlot))
require.NoError(t, headState.SetGenesisValidatorRoot(params.BeaconConfig().ZeroHash[:]))
headRoot, err := headBlock.Block.HashTreeRoot()
@@ -299,7 +305,8 @@ func TestChainService_InitializeChainInfo_SetHeadAtGenesis(t *testing.T) {
headBlock := testutil.NewBeaconBlock()
headBlock.Block.Slot = finalizedSlot
headBlock.Block.ParentRoot = bytesutil.PadTo(genesisRoot[:], 32)
headState := testutil.NewBeaconState()
headState, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, headState.SetSlot(finalizedSlot))
require.NoError(t, headState.SetGenesisValidatorRoot(params.BeaconConfig().ZeroHash[:]))
headRoot, err := headBlock.Block.HashTreeRoot()
@@ -351,7 +358,8 @@ func TestChainService_InitializeChainInfo_HeadSync(t *testing.T) {
require.NoError(t, err)
require.NoError(t, beaconDB.SaveBlock(ctx, headBlock))
headState := testutil.NewBeaconState()
headState, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, headState.SetSlot(headBlock.Block.Slot))
require.NoError(t, headState.SetGenesisValidatorRoot(params.BeaconConfig().ZeroHash[:]))
require.NoError(t, beaconDB.SaveState(ctx, headState, genesisRoot))
@@ -408,7 +416,8 @@ func TestChainService_SaveHeadNoDB(t *testing.T) {
blk.Block.Slot = 1
r, err := blk.HashTreeRoot()
require.NoError(t, err)
newState := testutil.NewBeaconState()
newState, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, s.stateGen.SaveState(ctx, r, newState))
require.NoError(t, s.saveHeadNoDB(ctx, blk, r, newState))
@@ -430,7 +439,8 @@ func TestHasBlock_ForkChoiceAndDB(t *testing.T) {
block := testutil.NewBeaconBlock()
r, err := block.Block.HashTreeRoot()
require.NoError(t, err)
beaconState := testutil.NewBeaconState()
beaconState, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, s.insertBlockAndAttestationsToForkChoiceStore(ctx, block.Block, r, beaconState))
assert.Equal(t, false, s.hasBlock(ctx, [32]byte{}), "Should not have block")
@@ -455,6 +465,20 @@ func TestServiceStop_SaveCachedBlocks(t *testing.T) {
require.Equal(t, true, s.beaconDB.HasBlock(ctx, r))
}
func TestProcessChainStartTime_ReceivedFeed(t *testing.T) {
beaconDB := testDB.SetupDB(t)
service := setupBeaconChain(t, beaconDB)
stateChannel := make(chan *feed.Event, 1)
stateSub := service.stateNotifier.StateFeed().Subscribe(stateChannel)
defer stateSub.Unsubscribe()
service.processChainStartTime(context.Background(), time.Now())
stateEvent := <-stateChannel
require.Equal(t, int(stateEvent.Type), statefeed.Initialized)
_, ok := stateEvent.Data.(*statefeed.InitializedData)
require.Equal(t, true, ok)
}
func BenchmarkHasBlockDB(b *testing.B) {
beaconDB := testDB.SetupDB(b)
ctx := context.Background()

View File

@@ -23,6 +23,7 @@ go_library(
"//shared/event:go_default_library",
"//shared/params:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
],

View File

@@ -9,6 +9,7 @@ import (
"time"
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute"
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
@@ -47,23 +48,23 @@ type ChainService struct {
ValidAttestation bool
ForkChoiceStore *protoarray.Store
VerifyBlkDescendantErr error
Slot *uint64 // Pointer because 0 is a useful value, so checking against it can be incorrect.
Slot *types.Slot // Pointer because 0 is a useful value, so checking against it can be incorrect.
}
// StateNotifier mocks the same method in the chain service.
func (ms *ChainService) StateNotifier() statefeed.Notifier {
if ms.stateNotifier == nil {
ms.stateNotifier = &MockStateNotifier{}
func (s *ChainService) StateNotifier() statefeed.Notifier {
if s.stateNotifier == nil {
s.stateNotifier = &MockStateNotifier{}
}
return ms.stateNotifier
return s.stateNotifier
}
// BlockNotifier mocks the same method in the chain service.
func (ms *ChainService) BlockNotifier() blockfeed.Notifier {
if ms.blockNotifier == nil {
ms.blockNotifier = &MockBlockNotifier{}
func (s *ChainService) BlockNotifier() blockfeed.Notifier {
if s.blockNotifier == nil {
s.blockNotifier = &MockBlockNotifier{}
}
return ms.blockNotifier
return s.blockNotifier
}
// MockBlockNotifier mocks the block notifier.
@@ -72,11 +73,11 @@ type MockBlockNotifier struct {
}
// BlockFeed returns a block feed.
func (msn *MockBlockNotifier) BlockFeed() *event.Feed {
if msn.feed == nil {
msn.feed = new(event.Feed)
func (mbn *MockBlockNotifier) BlockFeed() *event.Feed {
if mbn.feed == nil {
mbn.feed = new(event.Feed)
}
return msn.feed
return mbn.feed
}
// MockStateNotifier mocks the state notifier.
@@ -125,11 +126,11 @@ func (msn *MockStateNotifier) StateFeed() *event.Feed {
}
// OperationNotifier mocks the same method in the chain service.
func (ms *ChainService) OperationNotifier() opfeed.Notifier {
if ms.opNotifier == nil {
ms.opNotifier = &MockOperationNotifier{}
func (s *ChainService) OperationNotifier() opfeed.Notifier {
if s.opNotifier == nil {
s.opNotifier = &MockOperationNotifier{}
}
return ms.opNotifier
return s.opNotifier
}
// MockOperationNotifier mocks the operation notifier.
@@ -146,227 +147,227 @@ func (mon *MockOperationNotifier) OperationFeed() *event.Feed {
}
// ReceiveBlockInitialSync mocks ReceiveBlockInitialSync method in chain service.
func (ms *ChainService) ReceiveBlockInitialSync(ctx context.Context, block *ethpb.SignedBeaconBlock, _ [32]byte) error {
if ms.State == nil {
ms.State = &stateTrie.BeaconState{}
func (s *ChainService) ReceiveBlockInitialSync(ctx context.Context, block *ethpb.SignedBeaconBlock, _ [32]byte) error {
if s.State == nil {
s.State = &stateTrie.BeaconState{}
}
if !bytes.Equal(ms.Root, block.Block.ParentRoot) {
return errors.Errorf("wanted %#x but got %#x", ms.Root, block.Block.ParentRoot)
if !bytes.Equal(s.Root, block.Block.ParentRoot) {
return errors.Errorf("wanted %#x but got %#x", s.Root, block.Block.ParentRoot)
}
if err := ms.State.SetSlot(block.Block.Slot); err != nil {
if err := s.State.SetSlot(block.Block.Slot); err != nil {
return err
}
ms.BlocksReceived = append(ms.BlocksReceived, block)
s.BlocksReceived = append(s.BlocksReceived, block)
signingRoot, err := block.Block.HashTreeRoot()
if err != nil {
return err
}
if ms.DB != nil {
if err := ms.DB.SaveBlock(ctx, block); err != nil {
if s.DB != nil {
if err := s.DB.SaveBlock(ctx, block); err != nil {
return err
}
logrus.Infof("Saved block with root: %#x at slot %d", signingRoot, block.Block.Slot)
}
ms.Root = signingRoot[:]
ms.Block = block
s.Root = signingRoot[:]
s.Block = block
return nil
}
// ReceiveBlockBatch processes blocks in batches from initial-sync.
func (ms *ChainService) ReceiveBlockBatch(ctx context.Context, blks []*ethpb.SignedBeaconBlock, _ [][32]byte) error {
if ms.State == nil {
ms.State = &stateTrie.BeaconState{}
func (s *ChainService) ReceiveBlockBatch(ctx context.Context, blks []*ethpb.SignedBeaconBlock, _ [][32]byte) error {
if s.State == nil {
s.State = &stateTrie.BeaconState{}
}
for _, block := range blks {
if !bytes.Equal(ms.Root, block.Block.ParentRoot) {
return errors.Errorf("wanted %#x but got %#x", ms.Root, block.Block.ParentRoot)
if !bytes.Equal(s.Root, block.Block.ParentRoot) {
return errors.Errorf("wanted %#x but got %#x", s.Root, block.Block.ParentRoot)
}
if err := ms.State.SetSlot(block.Block.Slot); err != nil {
if err := s.State.SetSlot(block.Block.Slot); err != nil {
return err
}
ms.BlocksReceived = append(ms.BlocksReceived, block)
s.BlocksReceived = append(s.BlocksReceived, block)
signingRoot, err := block.Block.HashTreeRoot()
if err != nil {
return err
}
if ms.DB != nil {
if err := ms.DB.SaveBlock(ctx, block); err != nil {
if s.DB != nil {
if err := s.DB.SaveBlock(ctx, block); err != nil {
return err
}
logrus.Infof("Saved block with root: %#x at slot %d", signingRoot, block.Block.Slot)
}
ms.Root = signingRoot[:]
ms.Block = block
s.Root = signingRoot[:]
s.Block = block
}
return nil
}
// ReceiveBlock mocks ReceiveBlock method in chain service.
func (ms *ChainService) ReceiveBlock(ctx context.Context, block *ethpb.SignedBeaconBlock, _ [32]byte) error {
if ms.State == nil {
ms.State = &stateTrie.BeaconState{}
func (s *ChainService) ReceiveBlock(ctx context.Context, block *ethpb.SignedBeaconBlock, _ [32]byte) error {
if s.State == nil {
s.State = &stateTrie.BeaconState{}
}
if !bytes.Equal(ms.Root, block.Block.ParentRoot) {
return errors.Errorf("wanted %#x but got %#x", ms.Root, block.Block.ParentRoot)
if !bytes.Equal(s.Root, block.Block.ParentRoot) {
return errors.Errorf("wanted %#x but got %#x", s.Root, block.Block.ParentRoot)
}
if err := ms.State.SetSlot(block.Block.Slot); err != nil {
if err := s.State.SetSlot(block.Block.Slot); err != nil {
return err
}
ms.BlocksReceived = append(ms.BlocksReceived, block)
s.BlocksReceived = append(s.BlocksReceived, block)
signingRoot, err := block.Block.HashTreeRoot()
if err != nil {
return err
}
if ms.DB != nil {
if err := ms.DB.SaveBlock(ctx, block); err != nil {
if s.DB != nil {
if err := s.DB.SaveBlock(ctx, block); err != nil {
return err
}
logrus.Infof("Saved block with root: %#x at slot %d", signingRoot, block.Block.Slot)
}
ms.Root = signingRoot[:]
ms.Block = block
s.Root = signingRoot[:]
s.Block = block
return nil
}
// HeadSlot mocks HeadSlot method in chain service.
func (ms *ChainService) HeadSlot() uint64 {
if ms.State == nil {
func (s *ChainService) HeadSlot() types.Slot {
if s.State == nil {
return 0
}
return ms.State.Slot()
return s.State.Slot()
}
// HeadRoot mocks HeadRoot method in chain service.
func (ms *ChainService) HeadRoot(_ context.Context) ([]byte, error) {
if len(ms.Root) > 0 {
return ms.Root, nil
func (s *ChainService) HeadRoot(_ context.Context) ([]byte, error) {
if len(s.Root) > 0 {
return s.Root, nil
}
return make([]byte, 32), nil
}
// HeadBlock mocks HeadBlock method in chain service.
func (ms *ChainService) HeadBlock(context.Context) (*ethpb.SignedBeaconBlock, error) {
return ms.Block, nil
func (s *ChainService) HeadBlock(context.Context) (*ethpb.SignedBeaconBlock, error) {
return s.Block, nil
}
// HeadState mocks HeadState method in chain service.
func (ms *ChainService) HeadState(context.Context) (*stateTrie.BeaconState, error) {
return ms.State, nil
func (s *ChainService) HeadState(context.Context) (*stateTrie.BeaconState, error) {
return s.State, nil
}
// CurrentFork mocks HeadState method in chain service.
func (ms *ChainService) CurrentFork() *pb.Fork {
return ms.Fork
func (s *ChainService) CurrentFork() *pb.Fork {
return s.Fork
}
// FinalizedCheckpt mocks FinalizedCheckpt method in chain service.
func (ms *ChainService) FinalizedCheckpt() *ethpb.Checkpoint {
return ms.FinalizedCheckPoint
func (s *ChainService) FinalizedCheckpt() *ethpb.Checkpoint {
return s.FinalizedCheckPoint
}
// CurrentJustifiedCheckpt mocks CurrentJustifiedCheckpt method in chain service.
func (ms *ChainService) CurrentJustifiedCheckpt() *ethpb.Checkpoint {
return ms.CurrentJustifiedCheckPoint
func (s *ChainService) CurrentJustifiedCheckpt() *ethpb.Checkpoint {
return s.CurrentJustifiedCheckPoint
}
// PreviousJustifiedCheckpt mocks PreviousJustifiedCheckpt method in chain service.
func (ms *ChainService) PreviousJustifiedCheckpt() *ethpb.Checkpoint {
return ms.PreviousJustifiedCheckPoint
func (s *ChainService) PreviousJustifiedCheckpt() *ethpb.Checkpoint {
return s.PreviousJustifiedCheckPoint
}
// ReceiveAttestation mocks ReceiveAttestation method in chain service.
func (ms *ChainService) ReceiveAttestation(_ context.Context, _ *ethpb.Attestation) error {
func (s *ChainService) ReceiveAttestation(_ context.Context, _ *ethpb.Attestation) error {
return nil
}
// ReceiveAttestationNoPubsub mocks ReceiveAttestationNoPubsub method in chain service.
func (ms *ChainService) ReceiveAttestationNoPubsub(context.Context, *ethpb.Attestation) error {
func (s *ChainService) ReceiveAttestationNoPubsub(context.Context, *ethpb.Attestation) error {
return nil
}
// AttestationPreState mocks AttestationPreState method in chain service.
func (ms *ChainService) AttestationPreState(_ context.Context, _ *ethpb.Attestation) (*stateTrie.BeaconState, error) {
return ms.State, nil
func (s *ChainService) AttestationPreState(_ context.Context, _ *ethpb.Attestation) (*stateTrie.BeaconState, error) {
return s.State, nil
}
// HeadValidatorsIndices mocks the same method in the chain service.
func (ms *ChainService) HeadValidatorsIndices(_ context.Context, epoch uint64) ([]uint64, error) {
if ms.State == nil {
func (s *ChainService) HeadValidatorsIndices(_ context.Context, epoch types.Epoch) ([]uint64, error) {
if s.State == nil {
return []uint64{}, nil
}
return helpers.ActiveValidatorIndices(ms.State, epoch)
return helpers.ActiveValidatorIndices(s.State, epoch)
}
// HeadSeed mocks the same method in the chain service.
func (ms *ChainService) HeadSeed(_ context.Context, epoch uint64) ([32]byte, error) {
return helpers.Seed(ms.State, epoch, params.BeaconConfig().DomainBeaconAttester)
func (s *ChainService) HeadSeed(_ context.Context, epoch types.Epoch) ([32]byte, error) {
return helpers.Seed(s.State, epoch, params.BeaconConfig().DomainBeaconAttester)
}
// HeadETH1Data provides the current ETH1Data of the head state.
func (ms *ChainService) HeadETH1Data() *ethpb.Eth1Data {
return ms.ETH1Data
func (s *ChainService) HeadETH1Data() *ethpb.Eth1Data {
return s.ETH1Data
}
// ProtoArrayStore mocks the same method in the chain service.
func (ms *ChainService) ProtoArrayStore() *protoarray.Store {
return ms.ForkChoiceStore
func (s *ChainService) ProtoArrayStore() *protoarray.Store {
return s.ForkChoiceStore
}
// GenesisTime mocks the same method in the chain service.
func (ms *ChainService) GenesisTime() time.Time {
return ms.Genesis
func (s *ChainService) GenesisTime() time.Time {
return s.Genesis
}
// GenesisValidatorRoot mocks the same method in the chain service.
func (ms *ChainService) GenesisValidatorRoot() [32]byte {
return ms.ValidatorsRoot
func (s *ChainService) GenesisValidatorRoot() [32]byte {
return s.ValidatorsRoot
}
// CurrentSlot mocks the same method in the chain service.
func (ms *ChainService) CurrentSlot() uint64 {
if ms.Slot != nil {
return *ms.Slot
func (s *ChainService) CurrentSlot() types.Slot {
if s.Slot != nil {
return *s.Slot
}
return uint64(time.Now().Unix()-ms.Genesis.Unix()) / params.BeaconConfig().SecondsPerSlot
return types.Slot(uint64(time.Now().Unix()-s.Genesis.Unix()) / params.BeaconConfig().SecondsPerSlot)
}
// Participation mocks the same method in the chain service.
func (ms *ChainService) Participation(_ uint64) *precompute.Balance {
return ms.Balance
func (s *ChainService) Participation(_ uint64) *precompute.Balance {
return s.Balance
}
// IsValidAttestation always returns true.
func (ms *ChainService) IsValidAttestation(_ context.Context, _ *ethpb.Attestation) bool {
return ms.ValidAttestation
func (s *ChainService) IsValidAttestation(_ context.Context, _ *ethpb.Attestation) bool {
return s.ValidAttestation
}
// IsCanonical returns and determines whether a block with the provided root is part of
// the canonical chain.
func (ms *ChainService) IsCanonical(_ context.Context, r [32]byte) (bool, error) {
if ms.CanonicalRoots != nil {
_, ok := ms.CanonicalRoots[r]
func (s *ChainService) IsCanonical(_ context.Context, r [32]byte) (bool, error) {
if s.CanonicalRoots != nil {
_, ok := s.CanonicalRoots[r]
return ok, nil
}
return true, nil
}
// HasInitSyncBlock mocks the same method in the chain service.
func (ms *ChainService) HasInitSyncBlock(_ [32]byte) bool {
func (s *ChainService) HasInitSyncBlock(_ [32]byte) bool {
return false
}
// HeadGenesisValidatorRoot mocks HeadGenesisValidatorRoot method in chain service.
func (ms *ChainService) HeadGenesisValidatorRoot() [32]byte {
func (s *ChainService) HeadGenesisValidatorRoot() [32]byte {
return [32]byte{}
}
// VerifyBlkDescendant mocks VerifyBlkDescendant and always returns nil.
func (ms *ChainService) VerifyBlkDescendant(_ context.Context, _ [32]byte) error {
return ms.VerifyBlkDescendantErr
func (s *ChainService) VerifyBlkDescendant(_ context.Context, _ [32]byte) error {
return s.VerifyBlkDescendantErr
}
// VerifyLmdFfgConsistency mocks VerifyLmdFfgConsistency and always returns nil.
func (ms *ChainService) VerifyLmdFfgConsistency(_ context.Context, a *ethpb.Attestation) error {
func (s *ChainService) VerifyLmdFfgConsistency(_ context.Context, a *ethpb.Attestation) error {
if !bytes.Equal(a.Data.BeaconBlockRoot, a.Data.Target.Root) {
return errors.New("LMD and FFG miss matched")
}
@@ -374,8 +375,8 @@ func (ms *ChainService) VerifyLmdFfgConsistency(_ context.Context, a *ethpb.Atte
}
// VerifyFinalizedConsistency mocks VerifyFinalizedConsistency and always returns nil.
func (ms *ChainService) VerifyFinalizedConsistency(_ context.Context, r []byte) error {
if !bytes.Equal(r, ms.FinalizedCheckPoint.Root) {
func (s *ChainService) VerifyFinalizedConsistency(_ context.Context, r []byte) error {
if !bytes.Equal(r, s.FinalizedCheckPoint.Root) {
return errors.New("Root and finalized store are not consistent")
}
return nil

View File

@@ -4,6 +4,7 @@ import (
"context"
"testing"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
"github.com/prysmaticlabs/prysm/shared/testutil"
@@ -22,8 +23,8 @@ func TestService_VerifyWeakSubjectivityRoot(t *testing.T) {
wsVerified bool
wantErr bool
wsRoot [32]byte
wsEpoch uint64
finalizedEpoch uint64
wsEpoch types.Epoch
finalizedEpoch types.Epoch
errString string
name string
}{

View File

@@ -41,6 +41,7 @@ go_library(
"@com_github_patrickmn_go_cache//:go_default_library",
"@com_github_prometheus_client_golang//prometheus:go_default_library",
"@com_github_prometheus_client_golang//prometheus/promauto:go_default_library",
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
"@io_k8s_client_go//tools/cache:go_default_library",
"@io_opencensus_go//trace:go_default_library",
@@ -71,6 +72,7 @@ go_test(
"//shared/testutil/require:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"@com_github_google_gofuzz//:go_default_library",
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
],
)

View File

@@ -4,6 +4,7 @@ import (
"testing"
"github.com/gogo/protobuf/proto"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
@@ -60,8 +61,8 @@ func TestCheckpointStateCache_MaxSize(t *testing.T) {
require.NoError(t, err)
for i := uint64(0); i < uint64(maxCheckpointStateSize+100); i++ {
require.NoError(t, st.SetSlot(i))
require.NoError(t, c.AddCheckpointState(&ethpb.Checkpoint{Epoch: i, Root: make([]byte, 32)}, st))
require.NoError(t, st.SetSlot(types.Slot(i)))
require.NoError(t, c.AddCheckpointState(&ethpb.Checkpoint{Epoch: types.Epoch(i), Root: make([]byte, 32)}, st))
}
assert.Equal(t, maxCheckpointStateSize, len(c.cache.Keys()))

View File

@@ -8,6 +8,7 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/sliceutil"
"k8s.io/client-go/tools/cache"
@@ -55,7 +56,7 @@ func NewCommitteesCache() *CommitteeCache {
// Committee fetches the shuffled indices by slot and committee index. Every list of indices
// represent one committee. Returns true if the list exists with slot and committee index. Otherwise returns false, nil.
func (c *CommitteeCache) Committee(slot uint64, seed [32]byte, index uint64) ([]uint64, error) {
func (c *CommitteeCache) Committee(slot types.Slot, seed [32]byte, index uint64) ([]uint64, error) {
c.lock.RLock()
defer c.lock.RUnlock()
@@ -77,11 +78,11 @@ func (c *CommitteeCache) Committee(slot uint64, seed [32]byte, index uint64) ([]
}
committeeCountPerSlot := uint64(1)
if item.CommitteeCount/params.BeaconConfig().SlotsPerEpoch > 1 {
committeeCountPerSlot = item.CommitteeCount / params.BeaconConfig().SlotsPerEpoch
if item.CommitteeCount/uint64(params.BeaconConfig().SlotsPerEpoch) > 1 {
committeeCountPerSlot = item.CommitteeCount / uint64(params.BeaconConfig().SlotsPerEpoch)
}
indexOffSet := index + (slot%params.BeaconConfig().SlotsPerEpoch)*committeeCountPerSlot
indexOffSet := index + uint64(slot.ModSlot(params.BeaconConfig().SlotsPerEpoch).Mul(committeeCountPerSlot))
start, end := startEndIndices(item, indexOffSet)
if end > uint64(len(item.ShuffledIndices)) || end < start {

View File

@@ -3,6 +3,8 @@
// This file is used in fuzzer builds to bypass global committee caches.
package cache
import types "github.com/prysmaticlabs/eth2-types"
// FakeCommitteeCache is a struct with 1 queue for looking up shuffled indices list by seed.
type FakeCommitteeCache struct {
}
@@ -14,7 +16,7 @@ func NewCommitteesCache() *FakeCommitteeCache {
// Committee fetches the shuffled indices by slot and committee index. Every list of indices
// represent one committee. Returns true if the list exists with slot and committee index. Otherwise returns false, nil.
func (c *FakeCommitteeCache) Committee(slot uint64, seed [32]byte, index uint64) ([]uint64, error) {
func (c *FakeCommitteeCache) Committee(slot types.Slot, seed [32]byte, index uint64) ([]uint64, error) {
return nil, nil
}

View File

@@ -8,7 +8,7 @@ import (
var (
// maxCacheSize is 4x of the epoch length for additional cache padding.
// Requests should be only accessing committees within defined epoch length.
maxCacheSize = 4 * params.BeaconConfig().SlotsPerEpoch
maxCacheSize = uint64(4 * params.BeaconConfig().SlotsPerEpoch)
)
// trim the FIFO queue to the maxSize.

View File

@@ -6,6 +6,7 @@ import (
lru "github.com/hashicorp/golang-lru"
"github.com/patrickmn/go-cache"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/sliceutil"
)
@@ -25,7 +26,7 @@ var SubnetIDs = newSubnetIDs()
func newSubnetIDs() *subnetIDs {
// 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)
cacheSize := int(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().MaxCommitteesPerSlot * 2))
attesterCache, err := lru.New(cacheSize)
if err != nil {
panic(err)
@@ -34,31 +35,31 @@ func newSubnetIDs() *subnetIDs {
if err != nil {
panic(err)
}
epochDuration := time.Duration(params.BeaconConfig().SlotsPerEpoch * params.BeaconConfig().SecondsPerSlot)
epochDuration := time.Duration(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().SecondsPerSlot))
subLength := epochDuration * time.Duration(params.BeaconConfig().EpochsPerRandomSubnetSubscription)
persistentCache := cache.New(subLength*time.Second, epochDuration*time.Second)
return &subnetIDs{attester: attesterCache, aggregator: aggregatorCache, persistentSubnets: persistentCache}
}
// AddAttesterSubnetID adds the subnet index for subscribing subnet for the attester of a given slot.
func (c *subnetIDs) AddAttesterSubnetID(slot, subnetID uint64) {
c.attesterLock.Lock()
defer c.attesterLock.Unlock()
func (s *subnetIDs) AddAttesterSubnetID(slot types.Slot, subnetID uint64) {
s.attesterLock.Lock()
defer s.attesterLock.Unlock()
ids := []uint64{subnetID}
val, exists := c.attester.Get(slot)
val, exists := s.attester.Get(slot)
if exists {
ids = sliceutil.UnionUint64(append(val.([]uint64), ids...))
}
c.attester.Add(slot, ids)
s.attester.Add(slot, ids)
}
// GetAttesterSubnetIDs gets the subnet IDs for subscribed subnets for attesters of the slot.
func (c *subnetIDs) GetAttesterSubnetIDs(slot uint64) []uint64 {
c.attesterLock.RLock()
defer c.attesterLock.RUnlock()
func (s *subnetIDs) GetAttesterSubnetIDs(slot types.Slot) []uint64 {
s.attesterLock.RLock()
defer s.attesterLock.RUnlock()
val, exists := c.attester.Get(slot)
val, exists := s.attester.Get(slot)
if !exists {
return nil
}
@@ -69,24 +70,24 @@ func (c *subnetIDs) GetAttesterSubnetIDs(slot uint64) []uint64 {
}
// AddAggregatorSubnetID adds the subnet ID for subscribing subnet for the aggregator of a given slot.
func (c *subnetIDs) AddAggregatorSubnetID(slot, subnetID uint64) {
c.aggregatorLock.Lock()
defer c.aggregatorLock.Unlock()
func (s *subnetIDs) AddAggregatorSubnetID(slot types.Slot, subnetID uint64) {
s.aggregatorLock.Lock()
defer s.aggregatorLock.Unlock()
ids := []uint64{subnetID}
val, exists := c.aggregator.Get(slot)
val, exists := s.aggregator.Get(slot)
if exists {
ids = sliceutil.UnionUint64(append(val.([]uint64), ids...))
}
c.aggregator.Add(slot, ids)
s.aggregator.Add(slot, ids)
}
// GetAggregatorSubnetIDs gets the subnet IDs for subscribing subnet for aggregator of the slot.
func (c *subnetIDs) GetAggregatorSubnetIDs(slot uint64) []uint64 {
c.aggregatorLock.RLock()
defer c.aggregatorLock.RUnlock()
func (s *subnetIDs) GetAggregatorSubnetIDs(slot types.Slot) []uint64 {
s.aggregatorLock.RLock()
defer s.aggregatorLock.RUnlock()
val, exists := c.aggregator.Get(slot)
val, exists := s.aggregator.Get(slot)
if !exists {
return []uint64{}
}
@@ -95,11 +96,11 @@ func (c *subnetIDs) GetAggregatorSubnetIDs(slot uint64) []uint64 {
// GetPersistentSubnets retrieves the persistent subnet and expiration time of that validator's
// subscription.
func (c *subnetIDs) GetPersistentSubnets(pubkey []byte) ([]uint64, bool, time.Time) {
c.subnetsLock.RLock()
defer c.subnetsLock.RUnlock()
func (s *subnetIDs) GetPersistentSubnets(pubkey []byte) ([]uint64, bool, time.Time) {
s.subnetsLock.RLock()
defer s.subnetsLock.RUnlock()
id, duration, ok := c.persistentSubnets.GetWithExpiration(string(pubkey))
id, duration, ok := s.persistentSubnets.GetWithExpiration(string(pubkey))
if !ok {
return []uint64{}, ok, time.Time{}
}
@@ -108,11 +109,11 @@ func (c *subnetIDs) GetPersistentSubnets(pubkey []byte) ([]uint64, bool, time.Ti
// GetAllSubnets retrieves all the non-expired subscribed subnets of all the validators
// in the cache.
func (c *subnetIDs) GetAllSubnets() []uint64 {
c.subnetsLock.RLock()
defer c.subnetsLock.RUnlock()
func (s *subnetIDs) GetAllSubnets() []uint64 {
s.subnetsLock.RLock()
defer s.subnetsLock.RUnlock()
itemsMap := c.persistentSubnets.Items()
itemsMap := s.persistentSubnets.Items()
var committees []uint64
for _, v := range itemsMap {
@@ -126,9 +127,9 @@ func (c *subnetIDs) GetAllSubnets() []uint64 {
// AddPersistentCommittee adds the relevant committee for that particular validator along with its
// expiration period.
func (c *subnetIDs) AddPersistentCommittee(pubkey []byte, comIndex []uint64, duration time.Duration) {
c.subnetsLock.Lock()
defer c.subnetsLock.Unlock()
func (s *subnetIDs) AddPersistentCommittee(pubkey []byte, comIndex []uint64, duration time.Duration) {
s.subnetsLock.Lock()
defer s.subnetsLock.Unlock()
c.persistentSubnets.Set(string(pubkey), comIndex, duration)
s.persistentSubnets.Set(string(pubkey), comIndex, duration)
}

View File

@@ -3,13 +3,14 @@ package cache
import (
"testing"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
)
func TestSubnetIDsCache_RoundTrip(t *testing.T) {
c := newSubnetIDs()
slot := uint64(100)
slot := types.Slot(100)
committeeIDs := c.GetAggregatorSubnetIDs(slot)
assert.Equal(t, 0, len(committeeIDs), "Empty cache returned an object")

View File

@@ -40,6 +40,7 @@ go_library(
"//shared/trieutil:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@io_opencensus_go//trace:go_default_library",
@@ -69,6 +70,7 @@ go_test(
shard_count = 2,
deps = [
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/p2p/types:go_default_library",
"//beacon-chain/state:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//shared/aggregation:go_default_library",
@@ -83,6 +85,7 @@ go_test(
"//shared/trieutil:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"@com_github_google_gofuzz//:go_default_library",
"@com_github_prysmaticlabs_eth2_types//: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",

View File

@@ -1,7 +1,6 @@
package blocks
import (
"bytes"
"context"
"fmt"
@@ -23,8 +22,8 @@ func ProcessAttestations(
beaconState *stateTrie.BeaconState,
b *ethpb.SignedBeaconBlock,
) (*stateTrie.BeaconState, error) {
if b.Block == nil || b.Block.Body == nil {
return nil, errors.New("block and block body can't be nil")
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
return nil, err
}
var err error
@@ -85,8 +84,8 @@ func ProcessAttestationsNoVerifySignature(
beaconState *stateTrie.BeaconState,
b *ethpb.SignedBeaconBlock,
) (*stateTrie.BeaconState, error) {
if b.Block == nil || b.Block.Body == nil {
return nil, errors.New("block and block body can't be nil")
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
return nil, err
}
body := b.Block.Body
var err error
@@ -112,13 +111,8 @@ func ProcessAttestationNoVerifySignature(
if err := helpers.ValidateNilAttestation(att); err != nil {
return nil, err
}
currEpoch := helpers.SlotToEpoch(beaconState.Slot())
var prevEpoch uint64
if currEpoch == 0 {
prevEpoch = 0
} else {
prevEpoch = currEpoch - 1
}
currEpoch := helpers.CurrentEpoch(beaconState)
prevEpoch := helpers.PrevEpoch(beaconState)
data := att.Data
if data.Target.Epoch != prevEpoch && data.Target.Epoch != currEpoch {
return nil, fmt.Errorf(
@@ -128,8 +122,8 @@ func ProcessAttestationNoVerifySignature(
currEpoch,
)
}
if helpers.SlotToEpoch(data.Slot) != data.Target.Epoch {
return nil, fmt.Errorf("data slot is not in the same epoch as target %d != %d", helpers.SlotToEpoch(data.Slot), data.Target.Epoch)
if err := helpers.ValidateSlotTargetEpoch(att.Data); err != nil {
return nil, err
}
s := att.Data.Slot
@@ -175,40 +169,31 @@ func ProcessAttestationNoVerifySignature(
ProposerIndex: proposerIndex,
}
var ffgSourceEpoch uint64
var ffgSourceRoot []byte
var ffgTargetEpoch uint64
if data.Target.Epoch == currEpoch {
ffgSourceEpoch = beaconState.CurrentJustifiedCheckpoint().Epoch
ffgSourceRoot = beaconState.CurrentJustifiedCheckpoint().Root
ffgTargetEpoch = currEpoch
if !beaconState.MatchCurrentJustifiedCheckpoint(data.Source) {
return nil, errors.New("source check point not equal to current justified checkpoint")
}
if err := beaconState.AppendCurrentEpochAttestations(pendingAtt); err != nil {
return nil, err
}
} else {
ffgSourceEpoch = beaconState.PreviousJustifiedCheckpoint().Epoch
ffgSourceRoot = beaconState.PreviousJustifiedCheckpoint().Root
ffgTargetEpoch = prevEpoch
if !beaconState.MatchPreviousJustifiedCheckpoint(data.Source) {
return nil, errors.New("source check point not equal to previous justified checkpoint")
}
if err := beaconState.AppendPreviousEpochAttestations(pendingAtt); err != nil {
return nil, err
}
}
if data.Source.Epoch != ffgSourceEpoch {
return nil, fmt.Errorf("expected source epoch %d, received %d", ffgSourceEpoch, data.Source.Epoch)
}
if !bytes.Equal(data.Source.Root, ffgSourceRoot) {
return nil, fmt.Errorf("expected source root %#x, received %#x", ffgSourceRoot, data.Source.Root)
}
if data.Target.Epoch != ffgTargetEpoch {
return nil, fmt.Errorf("expected target epoch %d, received %d", ffgTargetEpoch, data.Target.Epoch)
}
// Verify attesting indices are correct.
committee, err := helpers.BeaconCommitteeFromState(beaconState, att.Data.Slot, att.Data.CommitteeIndex)
if err != nil {
return nil, err
}
indexedAtt := attestationutil.ConvertToIndexed(ctx, att, committee)
indexedAtt, err := attestationutil.ConvertToIndexed(ctx, att, committee)
if err != nil {
return nil, err
}
if err := attestationutil.IsValidAttestationIndices(ctx, indexedAtt); err != nil {
return nil, err
}
@@ -216,60 +201,6 @@ func ProcessAttestationNoVerifySignature(
return beaconState, nil
}
// VerifyAttestationsSignatures will verify the signatures of the provided attestations. This method performs
// a single BLS verification call to verify the signatures of all of the provided attestations. All
// of the provided attestations must have valid signatures or this method will return an error.
// This method does not determine which attestation signature is invalid, only that one or more
// attestation signatures were not valid.
func VerifyAttestationsSignatures(ctx context.Context, beaconState *stateTrie.BeaconState, b *ethpb.SignedBeaconBlock) error {
ctx, span := trace.StartSpan(ctx, "core.VerifyAttestationsSignatures")
defer span.End()
atts := b.Block.Body.Attestations
span.AddAttributes(trace.Int64Attribute("attestations", int64(len(atts))))
if len(atts) == 0 {
return nil
}
fork := beaconState.Fork()
gvr := beaconState.GenesisValidatorRoot()
dt := params.BeaconConfig().DomainBeaconAttester
// Split attestations by fork. Note: the signature domain will differ based on the fork.
var preForkAtts []*ethpb.Attestation
var postForkAtts []*ethpb.Attestation
for _, a := range atts {
if helpers.SlotToEpoch(a.Data.Slot) < fork.Epoch {
preForkAtts = append(preForkAtts, a)
} else {
postForkAtts = append(postForkAtts, a)
}
}
// Check attestations from before the fork.
if fork.Epoch > 0 { // Check to prevent underflow.
prevDomain, err := helpers.Domain(fork, fork.Epoch-1, dt, gvr)
if err != nil {
return err
}
if err := verifyAttestationsSigWithDomain(ctx, beaconState, preForkAtts, prevDomain); err != nil {
return err
}
} else if len(preForkAtts) > 0 {
// This is a sanity check that preForkAtts were not ignored when fork.Epoch == 0. This
// condition is not possible, but it doesn't hurt to check anyway.
return errors.New("some attestations were not verified from previous fork before genesis")
}
// Then check attestations from after the fork.
currDomain, err := helpers.Domain(fork, fork.Epoch, dt, gvr)
if err != nil {
return err
}
return verifyAttestationsSigWithDomain(ctx, beaconState, postForkAtts, currDomain)
}
// VerifyAttestationSignature converts and attestation into an indexed attestation and verifies
// the signature in that attestation.
func VerifyAttestationSignature(ctx context.Context, beaconState *stateTrie.BeaconState, att *ethpb.Attestation) error {
@@ -280,7 +211,10 @@ func VerifyAttestationSignature(ctx context.Context, beaconState *stateTrie.Beac
if err != nil {
return err
}
indexedAtt := attestationutil.ConvertToIndexed(ctx, att, committee)
indexedAtt, err := attestationutil.ConvertToIndexed(ctx, att, committee)
if err != nil {
return err
}
return VerifyIndexedAttestation(ctx, beaconState, indexedAtt)
}
@@ -323,23 +257,3 @@ func VerifyIndexedAttestation(ctx context.Context, beaconState *stateTrie.Beacon
}
return attestationutil.VerifyIndexedAttestationSig(ctx, indexedAtt, pubkeys, domain)
}
// Inner method to verify attestations. This abstraction allows for the domain to be provided as an
// argument.
func verifyAttestationsSigWithDomain(ctx context.Context, beaconState *stateTrie.BeaconState, atts []*ethpb.Attestation, domain []byte) error {
if len(atts) == 0 {
return nil
}
set, err := createAttestationSignatureSet(ctx, beaconState, atts, domain)
if err != nil {
return err
}
verify, err := set.Verify()
if err != nil {
return errors.Errorf("got error in multiple verification: %v", err)
}
if !verify {
return errors.New("one or more attestation signatures did not verify")
}
return nil
}

View File

@@ -5,6 +5,7 @@ import (
"fmt"
"testing"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/go-bitfield"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
@@ -103,22 +104,11 @@ func TestProcessAttestations_CurrentEpochFFGDataMismatches(t *testing.T) {
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(cfc))
require.NoError(t, beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{}))
want := fmt.Sprintf(
"expected source epoch %d, received %d",
helpers.CurrentEpoch(beaconState),
attestations[0].Data.Source.Epoch,
)
want := "source check point not equal to current justified checkpoint"
_, err := blocks.ProcessAttestations(context.Background(), beaconState, b)
assert.ErrorContains(t, want, err)
b.Block.Body.Attestations[0].Data.Source.Epoch = helpers.CurrentEpoch(beaconState)
b.Block.Body.Attestations[0].Data.Source.Root = []byte{}
want = fmt.Sprintf(
"expected source root %#x, received %#x",
beaconState.CurrentJustifiedCheckpoint().Root,
attestations[0].Data.Source.Root,
)
_, err = blocks.ProcessAttestations(context.Background(), beaconState, b)
assert.ErrorContains(t, want, err)
}
@@ -145,30 +135,19 @@ func TestProcessAttestations_PrevEpochFFGDataMismatches(t *testing.T) {
},
}
err := beaconState.SetSlot(beaconState.Slot() + params.BeaconConfig().SlotsPerEpoch + params.BeaconConfig().MinAttestationInclusionDelay)
err := beaconState.SetSlot(beaconState.Slot() + 2*params.BeaconConfig().SlotsPerEpoch)
require.NoError(t, err)
pfc := beaconState.PreviousJustifiedCheckpoint()
pfc.Root = []byte("hello-world")
require.NoError(t, beaconState.SetPreviousJustifiedCheckpoint(pfc))
require.NoError(t, beaconState.SetPreviousEpochAttestations([]*pb.PendingAttestation{}))
want := fmt.Sprintf(
"expected source epoch %d, received %d",
helpers.PrevEpoch(beaconState),
attestations[0].Data.Source.Epoch,
)
want := "source check point not equal to previous justified checkpoint"
_, err = blocks.ProcessAttestations(context.Background(), beaconState, b)
assert.ErrorContains(t, want, err)
b.Block.Body.Attestations[0].Data.Source.Epoch = helpers.PrevEpoch(beaconState)
b.Block.Body.Attestations[0].Data.Target.Epoch = helpers.CurrentEpoch(beaconState)
b.Block.Body.Attestations[0].Data.Target.Epoch = helpers.PrevEpoch(beaconState)
b.Block.Body.Attestations[0].Data.Source.Root = []byte{}
want = fmt.Sprintf(
"expected source root %#x, received %#x",
beaconState.CurrentJustifiedCheckpoint().Root,
attestations[0].Data.Source.Root,
)
_, err = blocks.ProcessAttestations(context.Background(), beaconState, b)
assert.ErrorContains(t, want, err)
}
@@ -226,7 +205,7 @@ func TestProcessAttestations_OK(t *testing.T) {
committee, err := helpers.BeaconCommitteeFromState(beaconState, att.Data.Slot, att.Data.CommitteeIndex)
require.NoError(t, err)
attestingIndices := attestationutil.AttestingIndices(att.AggregationBits, committee)
attestingIndices, err := attestationutil.AttestingIndices(att.AggregationBits, committee)
require.NoError(t, err)
sigs := make([]bls.Signature, len(attestingIndices))
for i, indice := range attestingIndices {
@@ -253,10 +232,9 @@ func TestProcessAggregatedAttestation_OverlappingBits(t *testing.T) {
Source: &ethpb.Checkpoint{Epoch: 0, Root: bytesutil.PadTo([]byte("hello-world"), 32)},
Target: &ethpb.Checkpoint{Epoch: 0, Root: bytesutil.PadTo([]byte("hello-world"), 32)},
})
aggBits1 := bitfield.NewBitlist(4)
aggBits1 := bitfield.NewBitlist(3)
aggBits1.SetBitAt(0, true)
aggBits1.SetBitAt(1, true)
aggBits1.SetBitAt(2, true)
att1 := &ethpb.Attestation{
Data: data,
AggregationBits: aggBits1,
@@ -269,7 +247,7 @@ func TestProcessAggregatedAttestation_OverlappingBits(t *testing.T) {
committee, err := helpers.BeaconCommitteeFromState(beaconState, att1.Data.Slot, att1.Data.CommitteeIndex)
require.NoError(t, err)
attestingIndices1 := attestationutil.AttestingIndices(att1.AggregationBits, committee)
attestingIndices1, err := attestationutil.AttestingIndices(att1.AggregationBits, committee)
require.NoError(t, err)
sigs := make([]bls.Signature, len(attestingIndices1))
for i, indice := range attestingIndices1 {
@@ -281,10 +259,9 @@ func TestProcessAggregatedAttestation_OverlappingBits(t *testing.T) {
}
att1.Signature = bls.AggregateSignatures(sigs).Marshal()
aggBits2 := bitfield.NewBitlist(4)
aggBits2 := bitfield.NewBitlist(3)
aggBits2.SetBitAt(1, true)
aggBits2.SetBitAt(2, true)
aggBits2.SetBitAt(3, true)
att2 := &ethpb.Attestation{
Data: data,
AggregationBits: aggBits2,
@@ -292,7 +269,7 @@ func TestProcessAggregatedAttestation_OverlappingBits(t *testing.T) {
committee, err = helpers.BeaconCommitteeFromState(beaconState, att2.Data.Slot, att2.Data.CommitteeIndex)
require.NoError(t, err)
attestingIndices2 := attestationutil.AttestingIndices(att2.AggregationBits, committee)
attestingIndices2, err := attestationutil.AttestingIndices(att2.AggregationBits, committee)
require.NoError(t, err)
sigs = make([]bls.Signature, len(attestingIndices2))
for i, indice := range attestingIndices2 {
@@ -333,7 +310,7 @@ func TestProcessAggregatedAttestation_NoOverlappingBits(t *testing.T) {
committee, err := helpers.BeaconCommitteeFromState(beaconState, att1.Data.Slot, att1.Data.CommitteeIndex)
require.NoError(t, err)
attestingIndices1 := attestationutil.AttestingIndices(att1.AggregationBits, committee)
attestingIndices1, err := attestationutil.AttestingIndices(att1.AggregationBits, committee)
require.NoError(t, err)
sigs := make([]bls.Signature, len(attestingIndices1))
for i, indice := range attestingIndices1 {
@@ -356,7 +333,7 @@ func TestProcessAggregatedAttestation_NoOverlappingBits(t *testing.T) {
committee, err = helpers.BeaconCommitteeFromState(beaconState, att2.Data.Slot, att2.Data.CommitteeIndex)
require.NoError(t, err)
attestingIndices2 := attestationutil.AttestingIndices(att2.AggregationBits, committee)
attestingIndices2, err := attestationutil.AttestingIndices(att2.AggregationBits, committee)
require.NoError(t, err)
sigs = make([]bls.Signature, len(attestingIndices2))
for i, indice := range attestingIndices2 {
@@ -389,7 +366,7 @@ func TestProcessAttestationsNoVerify_IncorrectSlotTargetEpoch(t *testing.T) {
Target: &ethpb.Checkpoint{Root: make([]byte, 32)},
},
})
wanted := fmt.Sprintf("data slot is not in the same epoch as target %d != %d", helpers.SlotToEpoch(att.Data.Slot), att.Data.Target.Epoch)
wanted := "slot 32 does not match target epoch 0"
_, err := blocks.ProcessAttestationNoVerifySignature(context.TODO(), beaconState, att)
assert.ErrorContains(t, wanted, err)
}
@@ -474,11 +451,11 @@ func TestConvertToIndexed_OK(t *testing.T) {
wantedAttestingIndices: []uint64{43, 47},
},
{
aggregationBitfield: bitfield.Bitlist{0x03},
aggregationBitfield: bitfield.Bitlist{0x05},
wantedAttestingIndices: []uint64{47},
},
{
aggregationBitfield: bitfield.Bitlist{0x01},
aggregationBitfield: bitfield.Bitlist{0x04},
wantedAttestingIndices: []uint64{},
},
}
@@ -498,13 +475,14 @@ func TestConvertToIndexed_OK(t *testing.T) {
committee, err := helpers.BeaconCommitteeFromState(state, attestation.Data.Slot, attestation.Data.CommitteeIndex)
require.NoError(t, err)
ia := attestationutil.ConvertToIndexed(context.Background(), attestation, committee)
ia, err := attestationutil.ConvertToIndexed(context.Background(), attestation, committee)
require.NoError(t, err)
assert.DeepEqual(t, wanted, ia, "Convert attestation to indexed attestation didn't result as wanted")
}
}
func TestVerifyIndexedAttestation_OK(t *testing.T) {
numOfValidators := 4 * params.BeaconConfig().SlotsPerEpoch
numOfValidators := uint64(params.BeaconConfig().SlotsPerEpoch.Mul(4))
validators := make([]*ethpb.Validator, numOfValidators)
_, keys, err := testutil.DeterministicDepositsAndKeys(numOfValidators)
require.NoError(t, err)
@@ -597,7 +575,7 @@ func TestValidateIndexedAttestation_AboveMaxLength(t *testing.T) {
indexedAtt1.AttestingIndices[i] = i
indexedAtt1.Data = &ethpb.AttestationData{
Target: &ethpb.Checkpoint{
Epoch: i,
Epoch: types.Epoch(i),
},
}
}
@@ -608,10 +586,10 @@ func TestValidateIndexedAttestation_AboveMaxLength(t *testing.T) {
}
func TestValidateIndexedAttestation_BadAttestationsSignatureSet(t *testing.T) {
beaconState, keys := testutil.DeterministicGenesisState(t, 1000)
beaconState, keys := testutil.DeterministicGenesisState(t, 128)
sig := keys[0].Sign([]byte{'t', 'e', 's', 't'})
list := bitfield.Bitlist{0b11111111}
list := bitfield.Bitlist{0b11111}
var atts []*ethpb.Attestation
for i := uint64(0); i < 1000; i++ {
atts = append(atts, &ethpb.Attestation{
@@ -629,7 +607,7 @@ func TestValidateIndexedAttestation_BadAttestationsSignatureSet(t *testing.T) {
assert.ErrorContains(t, want, err)
atts = []*ethpb.Attestation{}
list = bitfield.Bitlist{0b00000000}
list = bitfield.Bitlist{0b10000}
for i := uint64(0); i < 1000; i++ {
atts = append(atts, &ethpb.Attestation{
Data: &ethpb.AttestationData{
@@ -649,70 +627,9 @@ func TestValidateIndexedAttestation_BadAttestationsSignatureSet(t *testing.T) {
assert.ErrorContains(t, want, err)
}
func TestVerifyAttestations_VerifiesMultipleAttestations(t *testing.T) {
ctx := context.Background()
numOfValidators := 4 * params.BeaconConfig().SlotsPerEpoch
validators := make([]*ethpb.Validator, numOfValidators)
_, keys, err := testutil.DeterministicDepositsAndKeys(numOfValidators)
require.NoError(t, err)
for i := 0; i < len(validators); i++ {
validators[i] = &ethpb.Validator{
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
PublicKey: keys[i].PublicKey().Marshal(),
WithdrawalCredentials: make([]byte, 32),
}
}
st := testutil.NewBeaconState()
require.NoError(t, st.SetSlot(5))
require.NoError(t, st.SetValidators(validators))
comm1, err := helpers.BeaconCommitteeFromState(st, 1 /*slot*/, 0 /*committeeIndex*/)
require.NoError(t, err)
att1 := testutil.HydrateAttestation(&ethpb.Attestation{
AggregationBits: bitfield.NewBitlist(uint64(len(comm1))),
Data: &ethpb.AttestationData{
Slot: 1,
},
})
domain, err := helpers.Domain(st.Fork(), st.Fork().Epoch, params.BeaconConfig().DomainBeaconAttester, st.GenesisValidatorRoot())
require.NoError(t, err)
root, err := helpers.ComputeSigningRoot(att1.Data, domain)
require.NoError(t, err)
var sigs []bls.Signature
for i, u := range comm1 {
att1.AggregationBits.SetBitAt(uint64(i), true)
sigs = append(sigs, keys[u].Sign(root[:]))
}
att1.Signature = bls.AggregateSignatures(sigs).Marshal()
comm2, err := helpers.BeaconCommitteeFromState(st, 1 /*slot*/, 1 /*committeeIndex*/)
require.NoError(t, err)
att2 := testutil.HydrateAttestation(&ethpb.Attestation{
AggregationBits: bitfield.NewBitlist(uint64(len(comm2))),
Data: &ethpb.AttestationData{
Slot: 1,
CommitteeIndex: 1,
},
})
root, err = helpers.ComputeSigningRoot(att2.Data, domain)
require.NoError(t, err)
sigs = nil
for i, u := range comm2 {
att2.AggregationBits.SetBitAt(uint64(i), true)
sigs = append(sigs, keys[u].Sign(root[:]))
}
att2.Signature = bls.AggregateSignatures(sigs).Marshal()
b := testutil.NewBeaconBlock()
b.Block.Body.Attestations = []*ethpb.Attestation{att1, att2}
require.NoError(t, blocks.VerifyAttestationsSignatures(ctx, st, b))
}
func TestVerifyAttestations_HandlesPlannedFork(t *testing.T) {
// In this test, att1 is from the prior fork and att2 is from the new fork.
ctx := context.Background()
numOfValidators := 4 * params.BeaconConfig().SlotsPerEpoch
numOfValidators := uint64(params.BeaconConfig().SlotsPerEpoch.Mul(4))
validators := make([]*ethpb.Validator, numOfValidators)
_, keys, err := testutil.DeterministicDepositsAndKeys(numOfValidators)
require.NoError(t, err)
@@ -724,7 +641,8 @@ func TestVerifyAttestations_HandlesPlannedFork(t *testing.T) {
}
}
st := testutil.NewBeaconState()
st, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, st.SetSlot(35))
require.NoError(t, st.SetValidators(validators))
require.NoError(t, st.SetFork(&pb.Fork{
@@ -771,15 +689,11 @@ func TestVerifyAttestations_HandlesPlannedFork(t *testing.T) {
sigs = append(sigs, keys[u].Sign(root[:]))
}
att2.Signature = bls.AggregateSignatures(sigs).Marshal()
b := testutil.NewBeaconBlock()
b.Block.Body.Attestations = []*ethpb.Attestation{att1, att2}
require.NoError(t, blocks.VerifyAttestationsSignatures(ctx, st, b))
}
func TestRetrieveAttestationSignatureSet_VerifiesMultipleAttestations(t *testing.T) {
ctx := context.Background()
numOfValidators := 4 * params.BeaconConfig().SlotsPerEpoch
numOfValidators := uint64(params.BeaconConfig().SlotsPerEpoch.Mul(4))
validators := make([]*ethpb.Validator, numOfValidators)
_, keys, err := testutil.DeterministicDepositsAndKeys(numOfValidators)
require.NoError(t, err)
@@ -791,7 +705,8 @@ func TestRetrieveAttestationSignatureSet_VerifiesMultipleAttestations(t *testing
}
}
st := testutil.NewBeaconState()
st, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, st.SetSlot(5))
require.NoError(t, st.SetValidators(validators))

View File

@@ -38,8 +38,8 @@ func ProcessAttesterSlashings(
beaconState *stateTrie.BeaconState,
b *ethpb.SignedBeaconBlock,
) (*stateTrie.BeaconState, error) {
if b.Block == nil || b.Block.Body == nil {
return nil, errors.New("block and block body can't be nil")
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
return nil, err
}
body := b.Block.Body

View File

@@ -4,6 +4,7 @@ import (
"context"
"testing"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
@@ -43,7 +44,7 @@ func TestProcessAttesterSlashings_DataNotSlashable(t *testing.T) {
})}}
var registry []*ethpb.Validator
currentSlot := uint64(0)
currentSlot := types.Slot(0)
beaconState, err := stateTrie.InitializeFromProto(&pb.BeaconState{
Validators: registry,
@@ -62,7 +63,7 @@ func TestProcessAttesterSlashings_DataNotSlashable(t *testing.T) {
func TestProcessAttesterSlashings_IndexedAttestationFailedToVerify(t *testing.T) {
var registry []*ethpb.Validator
currentSlot := uint64(0)
currentSlot := types.Slot(0)
beaconState, err := stateTrie.InitializeFromProto(&pb.BeaconState{
Validators: registry,
@@ -98,7 +99,7 @@ func TestProcessAttesterSlashings_IndexedAttestationFailedToVerify(t *testing.T)
func TestProcessAttesterSlashings_AppliesCorrectStatus(t *testing.T) {
beaconState, privKeys := testutil.DeterministicGenesisState(t, 100)
for _, vv := range beaconState.Validators() {
vv.WithdrawableEpoch = 1 * params.BeaconConfig().SlotsPerEpoch
vv.WithdrawableEpoch = types.Epoch(params.BeaconConfig().SlotsPerEpoch)
}
att1 := testutil.HydrateIndexedAttestation(&ethpb.IndexedAttestation{

View File

@@ -5,6 +5,7 @@ import (
"testing"
fuzz "github.com/google/gofuzz"
types "github.com/prysmaticlabs/eth2-types"
eth "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
@@ -431,7 +432,7 @@ func TestFuzzVerifyExit_10000(t *testing.T) {
ve := &eth.SignedVoluntaryExit{}
val := stateTrie.ReadOnlyValidator{}
fork := &pb.Fork{}
var slot uint64
var slot types.Slot
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(ve)

View File

@@ -4,6 +4,7 @@ import (
"context"
"testing"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
@@ -18,7 +19,7 @@ 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
vv.WithdrawableEpoch = types.Epoch(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,

View File

@@ -70,8 +70,8 @@ func ProcessDeposits(
beaconState *stateTrie.BeaconState,
b *ethpb.SignedBeaconBlock,
) (*stateTrie.BeaconState, error) {
if b.Block == nil || b.Block.Body == nil {
return nil, errors.New("block and block body can't be nil")
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
return nil, err
}
deposits := b.Block.Body.Deposits
@@ -251,19 +251,11 @@ func verifyDepositDataWithDomain(ctx context.Context, deps []*ethpb.Deposit, dom
WithdrawalCredentials: dep.Data.WithdrawalCredentials,
Amount: dep.Data.Amount,
}
root, err := depositMessage.HashTreeRoot()
sr, err := helpers.ComputeSigningRoot(depositMessage, domain)
if err != nil {
return errors.Wrap(err, "could not get signing root")
return err
}
signingData := &pb.SigningData{
ObjectRoot: root[:],
Domain: domain,
}
ctrRoot, err := signingData.HashTreeRoot()
if err != nil {
return errors.Wrap(err, "could not get container root")
}
msgs[i] = ctrRoot
msgs[i] = sr
}
verify, err := bls.VerifyMultipleSignatures(sigs, msgs, pks)
if err != nil {

View File

@@ -4,6 +4,7 @@ import (
"context"
"testing"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
@@ -319,8 +320,8 @@ func TestPreGenesisDeposits_SkipInvalidDeposit(t *testing.T) {
val, err := newState.ValidatorAtIndex(uint64(i))
require.NoError(t, err)
require.Equal(t, params.BeaconConfig().MaxEffectiveBalance, val.EffectiveBalance, "unequal effective balance")
require.Equal(t, uint64(0), val.ActivationEpoch)
require.Equal(t, uint64(0), val.ActivationEligibilityEpoch)
require.Equal(t, types.Epoch(0), val.ActivationEpoch)
require.Equal(t, types.Epoch(0), val.ActivationEligibilityEpoch)
}
if newState.Eth1DepositIndex() != 100 {
t.Errorf(

View File

@@ -71,6 +71,6 @@ 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.
support := params.BeaconConfig().EpochsPerEth1VotingPeriod * params.BeaconConfig().SlotsPerEpoch
return voteCount*2 > support, nil
support := params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().EpochsPerEth1VotingPeriod))
return voteCount*2 > uint64(support), nil
}

View File

@@ -6,6 +6,7 @@ import (
"testing"
"github.com/gogo/protobuf/proto"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
@@ -33,10 +34,10 @@ func TestEth1DataHasEnoughSupport(t *testing.T) {
stateVotes []*ethpb.Eth1Data
data *ethpb.Eth1Data
hasSupport bool
votingPeriodLength uint64
votingPeriodLength types.Epoch
}{
{
stateVotes: FakeDeposits(4 * params.BeaconConfig().SlotsPerEpoch),
stateVotes: FakeDeposits(uint64(params.BeaconConfig().SlotsPerEpoch.Mul(4))),
data: &ethpb.Eth1Data{
DepositCount: 1,
DepositRoot: bytesutil.PadTo([]byte("root"), 32),
@@ -44,7 +45,7 @@ func TestEth1DataHasEnoughSupport(t *testing.T) {
hasSupport: true,
votingPeriodLength: 7,
}, {
stateVotes: FakeDeposits(4 * params.BeaconConfig().SlotsPerEpoch),
stateVotes: FakeDeposits(uint64(params.BeaconConfig().SlotsPerEpoch.Mul(4))),
data: &ethpb.Eth1Data{
DepositCount: 1,
DepositRoot: bytesutil.PadTo([]byte("root"), 32),
@@ -52,7 +53,7 @@ func TestEth1DataHasEnoughSupport(t *testing.T) {
hasSupport: false,
votingPeriodLength: 8,
}, {
stateVotes: FakeDeposits(4 * params.BeaconConfig().SlotsPerEpoch),
stateVotes: FakeDeposits(uint64(params.BeaconConfig().SlotsPerEpoch.Mul(4))),
data: &ethpb.Eth1Data{
DepositCount: 1,
DepositRoot: bytesutil.PadTo([]byte("root"), 32),
@@ -174,7 +175,7 @@ func TestProcessEth1Data_SetsCorrectly(t *testing.T) {
},
}
period := params.BeaconConfig().EpochsPerEth1VotingPeriod * params.BeaconConfig().SlotsPerEpoch
period := uint64(params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().EpochsPerEth1VotingPeriod)))
for i := uint64(0); i < period; i++ {
beaconState, err = blocks.ProcessEth1DataInBlock(context.Background(), beaconState, b)
require.NoError(t, err)

View File

@@ -5,6 +5,7 @@ import (
"fmt"
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
v "github.com/prysmaticlabs/prysm/beacon-chain/core/validators"
@@ -48,8 +49,8 @@ func ProcessVoluntaryExits(
beaconState *stateTrie.BeaconState,
b *ethpb.SignedBeaconBlock,
) (*stateTrie.BeaconState, error) {
if b.Block == nil || b.Block.Body == nil {
return nil, errors.New("block and block body can't be nil")
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
return nil, err
}
body := b.Block.Body
@@ -73,39 +74,6 @@ func ProcessVoluntaryExits(
return beaconState, nil
}
// ProcessVoluntaryExitsNoVerifySignature processes all the voluntary exits in
// a block body, without verifying their BLS signatures.
// This function is here to satisfy fuzz tests.
func ProcessVoluntaryExitsNoVerifySignature(
beaconState *stateTrie.BeaconState,
body *ethpb.BeaconBlockBody,
) (*stateTrie.BeaconState, error) {
exits := body.VoluntaryExits
for idx, exit := range exits {
if exit == nil || exit.Exit == nil {
return nil, errors.New("nil exit")
}
val, err := beaconState.ValidatorAtIndexReadOnly(exit.Exit.ValidatorIndex)
if err != nil {
return nil, err
}
if err := verifyExitConditions(val, beaconState.Slot(), exit.Exit); err != nil {
return nil, err
}
// Validate that fork and genesis root are valid.
_, err = helpers.Domain(beaconState.Fork(), exit.Exit.Epoch, params.BeaconConfig().DomainVoluntaryExit, beaconState.GenesisValidatorRoot())
if err != nil {
return nil, err
}
beaconState, err = v.InitiateValidatorExit(beaconState, exit.Exit.ValidatorIndex)
if err != nil {
return nil, errors.Wrapf(err, "failed to process voluntary exit at index %d", idx)
}
}
return beaconState, nil
}
// VerifyExitAndSignature implements the spec defined validation for voluntary exits.
//
// Spec pseudocode definition:
@@ -125,7 +93,7 @@ func ProcessVoluntaryExitsNoVerifySignature(
// # Verify signature
// domain = get_domain(state, DOMAIN_VOLUNTARY_EXIT, exit.epoch)
// assert bls_verify(validator.pubkey, signing_root(exit), exit.signature, domain)
func VerifyExitAndSignature(validator stateTrie.ReadOnlyValidator, currentSlot uint64, fork *pb.Fork, signed *ethpb.SignedVoluntaryExit, genesisRoot []byte) error {
func VerifyExitAndSignature(validator stateTrie.ReadOnlyValidator, currentSlot types.Slot, fork *pb.Fork, signed *ethpb.SignedVoluntaryExit, genesisRoot []byte) error {
if signed == nil || signed.Exit == nil {
return errors.New("nil exit")
}
@@ -161,7 +129,7 @@ func VerifyExitAndSignature(validator stateTrie.ReadOnlyValidator, currentSlot u
// assert get_current_epoch(state) >= exit.epoch
// # Verify the validator has been active long enough
// assert get_current_epoch(state) >= validator.activation_epoch + SHARD_COMMITTEE_PERIOD
func verifyExitConditions(validator stateTrie.ReadOnlyValidator, currentSlot uint64, exit *ethpb.VoluntaryExit) error {
func verifyExitConditions(validator stateTrie.ReadOnlyValidator, currentSlot types.Slot, exit *ethpb.VoluntaryExit) error {
currentEpoch := helpers.SlotToEpoch(currentSlot)
// Verify the validator is active.
if !helpers.IsActiveValidatorUsingTrie(validator, currentEpoch) {

View File

@@ -4,6 +4,7 @@ import (
"context"
"testing"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
@@ -16,73 +17,6 @@ import (
"github.com/prysmaticlabs/prysm/shared/testutil/require"
)
func TestProcessVoluntaryExits_ValidatorNotActive(t *testing.T) {
exits := []*ethpb.SignedVoluntaryExit{
{
Exit: &ethpb.VoluntaryExit{
ValidatorIndex: 0,
},
},
}
registry := []*ethpb.Validator{
{
ExitEpoch: 0,
},
}
state, err := stateTrie.InitializeFromProto(&pb.BeaconState{
Validators: registry,
})
require.NoError(t, err)
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
VoluntaryExits: exits,
},
}
want := "non-active validator cannot exit"
_, err = blocks.ProcessVoluntaryExits(context.Background(), state, b)
assert.ErrorContains(t, want, err)
// Check conformance of no verify method.
_, err = blocks.ProcessVoluntaryExitsNoVerifySignature(state, b.Block.Body)
assert.ErrorContains(t, want, err)
}
func TestProcessVoluntaryExits_InvalidExitEpoch(t *testing.T) {
exits := []*ethpb.SignedVoluntaryExit{
{
Exit: &ethpb.VoluntaryExit{
Epoch: 10,
},
},
}
registry := []*ethpb.Validator{
{
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
},
}
state, err := stateTrie.InitializeFromProto(&pb.BeaconState{
Validators: registry,
Slot: 0,
})
require.NoError(t, err)
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
VoluntaryExits: exits,
},
}
want := "expected current epoch >= exit epoch"
_, err = blocks.ProcessVoluntaryExits(context.Background(), state, b)
assert.ErrorContains(t, want, err)
// Check conformance of no verify method.
_, err = blocks.ProcessVoluntaryExitsNoVerifySignature(state, b.Block.Body)
assert.ErrorContains(t, want, err)
}
func TestProcessVoluntaryExits_NotActiveLongEnoughToExit(t *testing.T) {
exits := []*ethpb.SignedVoluntaryExit{
{
@@ -168,7 +102,7 @@ func TestProcessVoluntaryExits_AppliesCorrectStatus(t *testing.T) {
Slot: params.BeaconConfig().SlotsPerEpoch * 5,
})
require.NoError(t, err)
err = state.SetSlot(state.Slot() + (params.BeaconConfig().ShardCommitteePeriod * params.BeaconConfig().SlotsPerEpoch))
err = state.SetSlot(state.Slot() + params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().ShardCommitteePeriod)))
require.NoError(t, err)
priv, err := bls.RandKey()
@@ -188,21 +122,11 @@ func TestProcessVoluntaryExits_AppliesCorrectStatus(t *testing.T) {
},
}
stateCopy := state.Copy()
newState, err := blocks.ProcessVoluntaryExits(context.Background(), state, b)
require.NoError(t, err, "Could not process exits")
newRegistry := newState.Validators()
if newRegistry[0].ExitEpoch != helpers.ActivationExitEpoch(state.Slot()/params.BeaconConfig().SlotsPerEpoch) {
if newRegistry[0].ExitEpoch != helpers.ActivationExitEpoch(types.Epoch(state.Slot()/params.BeaconConfig().SlotsPerEpoch)) {
t.Errorf("Expected validator exit epoch to be %d, got %d",
helpers.ActivationExitEpoch(state.Slot()/params.BeaconConfig().SlotsPerEpoch), newRegistry[0].ExitEpoch)
}
// Check conformance with NoVerify Exit Method.
newState, err = blocks.ProcessVoluntaryExitsNoVerifySignature(stateCopy, b.Block.Body)
require.NoError(t, err, "Could not process exits")
newRegistry = newState.Validators()
if newRegistry[0].ExitEpoch != helpers.ActivationExitEpoch(stateCopy.Slot()/params.BeaconConfig().SlotsPerEpoch) {
t.Errorf("Expected validator exit epoch to be %d, got %d",
helpers.ActivationExitEpoch(stateCopy.Slot()/params.BeaconConfig().SlotsPerEpoch), newRegistry[0].ExitEpoch)
helpers.ActivationExitEpoch(types.Epoch(state.Slot()/params.BeaconConfig().SlotsPerEpoch)), newRegistry[0].ExitEpoch)
}
}

View File

@@ -7,16 +7,16 @@ import (
"github.com/gogo/protobuf/proto"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/sirupsen/logrus"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
p2ptypes "github.com/prysmaticlabs/prysm/beacon-chain/p2p/types"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
"github.com/sirupsen/logrus"
)
func init() {
@@ -34,7 +34,8 @@ func TestProcessBlockHeader_ImproperBlockSlot(t *testing.T) {
}
}
state := testutil.NewBeaconState()
state, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, state.SetSlot(10))
require.NoError(t, state.SetValidators(validators))
require.NoError(t, state.SetLatestBlockHeader(testutil.HydrateBeaconHeader(&ethpb.BeaconBlockHeader{
@@ -106,7 +107,8 @@ func TestProcessBlockHeader_DifferentSlots(t *testing.T) {
}
}
state := testutil.NewBeaconState()
state, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, state.SetValidators(validators))
require.NoError(t, state.SetSlot(10))
require.NoError(t, state.SetLatestBlockHeader(testutil.HydrateBeaconHeader(&ethpb.BeaconBlockHeader{
@@ -119,7 +121,8 @@ func TestProcessBlockHeader_DifferentSlots(t *testing.T) {
priv, err := bls.RandKey()
require.NoError(t, err)
blockSig, err := helpers.ComputeDomainAndSign(state, currentEpoch, []byte("hello"), params.BeaconConfig().DomainBeaconProposer, priv)
sszBytes := p2ptypes.SSZBytes("hello")
blockSig, err := helpers.ComputeDomainAndSign(state, currentEpoch, &sszBytes, params.BeaconConfig().DomainBeaconProposer, priv)
require.NoError(t, err)
validators[5896].PublicKey = priv.PublicKey().Marshal()
block := &ethpb.SignedBeaconBlock{
@@ -149,7 +152,8 @@ func TestProcessBlockHeader_PreviousBlockRootNotSignedRoot(t *testing.T) {
}
}
state := testutil.NewBeaconState()
state, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, state.SetValidators(validators))
require.NoError(t, state.SetSlot(10))
bh := state.LatestBlockHeader()
@@ -158,7 +162,8 @@ func TestProcessBlockHeader_PreviousBlockRootNotSignedRoot(t *testing.T) {
currentEpoch := helpers.CurrentEpoch(state)
priv, err := bls.RandKey()
require.NoError(t, err)
blockSig, err := helpers.ComputeDomainAndSign(state, currentEpoch, []byte("hello"), params.BeaconConfig().DomainBeaconProposer, priv)
sszBytes := p2ptypes.SSZBytes("hello")
blockSig, err := helpers.ComputeDomainAndSign(state, currentEpoch, &sszBytes, params.BeaconConfig().DomainBeaconProposer, priv)
require.NoError(t, err)
validators[5896].PublicKey = priv.PublicKey().Marshal()
pID, err := helpers.BeaconProposerIndex(state)
@@ -186,7 +191,8 @@ func TestProcessBlockHeader_SlashedProposer(t *testing.T) {
}
}
state := testutil.NewBeaconState()
state, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, state.SetValidators(validators))
require.NoError(t, state.SetSlot(10))
bh := state.LatestBlockHeader()
@@ -197,7 +203,8 @@ func TestProcessBlockHeader_SlashedProposer(t *testing.T) {
currentEpoch := helpers.CurrentEpoch(state)
priv, err := bls.RandKey()
require.NoError(t, err)
blockSig, err := helpers.ComputeDomainAndSign(state, currentEpoch, []byte("hello"), params.BeaconConfig().DomainBeaconProposer, priv)
sszBytes := p2ptypes.SSZBytes("hello")
blockSig, err := helpers.ComputeDomainAndSign(state, currentEpoch, &sszBytes, params.BeaconConfig().DomainBeaconProposer, priv)
require.NoError(t, err)
validators[12683].PublicKey = priv.PublicKey().Marshal()
@@ -226,7 +233,8 @@ func TestProcessBlockHeader_OK(t *testing.T) {
}
}
state := testutil.NewBeaconState()
state, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, state.SetValidators(validators))
require.NoError(t, state.SetSlot(10))
require.NoError(t, state.SetLatestBlockHeader(testutil.HydrateBeaconHeader(&ethpb.BeaconBlockHeader{
@@ -283,7 +291,8 @@ func TestBlockSignatureSet_OK(t *testing.T) {
}
}
state := testutil.NewBeaconState()
state, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, state.SetValidators(validators))
require.NoError(t, state.SetSlot(10))
require.NoError(t, state.SetLatestBlockHeader(testutil.HydrateBeaconHeader(&ethpb.BeaconBlockHeader{

View File

@@ -41,8 +41,8 @@ func ProcessProposerSlashings(
beaconState *stateTrie.BeaconState,
b *ethpb.SignedBeaconBlock,
) (*stateTrie.BeaconState, error) {
if b.Block == nil || b.Block.Body == nil {
return nil, errors.New("block and block body can't be nil")
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
return nil, err
}
body := b.Block.Body

View File

@@ -5,6 +5,7 @@ import (
"fmt"
"testing"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
@@ -21,7 +22,7 @@ import (
func TestProcessProposerSlashings_UnmatchedHeaderSlots(t *testing.T) {
testutil.ResetCache()
beaconState, _ := testutil.DeterministicGenesisState(t, 20)
currentSlot := uint64(0)
currentSlot := types.Slot(0)
slashings := []*ethpb.ProposerSlashing{
{
Header_1: &ethpb.SignedBeaconBlockHeader{
@@ -54,7 +55,7 @@ func TestProcessProposerSlashings_UnmatchedHeaderSlots(t *testing.T) {
func TestProcessProposerSlashings_SameHeaders(t *testing.T) {
testutil.ResetCache()
beaconState, _ := testutil.DeterministicGenesisState(t, 2)
currentSlot := uint64(0)
currentSlot := types.Slot(0)
slashings := []*ethpb.ProposerSlashing{
{
Header_1: &ethpb.SignedBeaconBlockHeader{
@@ -93,7 +94,7 @@ func TestProcessProposerSlashings_ValidatorNotSlashable(t *testing.T) {
WithdrawableEpoch: 0,
},
}
currentSlot := uint64(0)
currentSlot := types.Slot(0)
slashings := []*ethpb.ProposerSlashing{
{
Header_1: &ethpb.SignedBeaconBlockHeader{
@@ -186,7 +187,7 @@ func TestVerifyProposerSlashing(t *testing.T) {
}
beaconState, sks := testutil.DeterministicGenesisState(t, 2)
currentSlot := uint64(0)
currentSlot := types.Slot(0)
require.NoError(t, beaconState.SetSlot(currentSlot))
rand1, err := bls.RandKey()
require.NoError(t, err)

View File

@@ -30,10 +30,9 @@ func ProcessRandao(
beaconState *stateTrie.BeaconState,
b *ethpb.SignedBeaconBlock,
) (*stateTrie.BeaconState, error) {
if b.Block == nil || b.Block.Body == nil {
return nil, errors.New("block and block body can't be nil")
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
return nil, err
}
body := b.Block.Body
buf, proposerPub, domain, err := randaoSigningData(beaconState)
if err != nil {
@@ -67,7 +66,7 @@ func ProcessRandaoNoVerify(
// If block randao passed verification, we XOR the state's latest randao mix with the block's
// randao and update the state's corresponding latest randao mix value.
latestMixesLength := params.BeaconConfig().EpochsPerHistoricalVector
latestMixSlice, err := beaconState.RandaoMixAtIndex(currentEpoch % latestMixesLength)
latestMixSlice, err := beaconState.RandaoMixAtIndex(uint64(currentEpoch % latestMixesLength))
if err != nil {
return nil, err
}
@@ -78,7 +77,7 @@ func ProcessRandaoNoVerify(
for i, x := range blockRandaoReveal {
latestMixSlice[i] ^= x
}
if err := beaconState.UpdateRandaoMixesAtIndex(currentEpoch%latestMixesLength, latestMixSlice); err != nil {
if err := beaconState.UpdateRandaoMixesAtIndex(uint64(currentEpoch%latestMixesLength), latestMixSlice); err != nil {
return nil, err
}
return beaconState, nil

View File

@@ -1,11 +1,11 @@
package blocks_test
import (
"bytes"
"context"
"encoding/binary"
"testing"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
@@ -21,9 +21,9 @@ func TestProcessRandao_IncorrectProposerFailsVerification(t *testing.T) {
// We fetch the proposer's index as that is whom the RANDAO will be verified against.
proposerIdx, err := helpers.BeaconProposerIndex(beaconState)
require.NoError(t, err)
epoch := uint64(0)
epoch := types.Epoch(0)
buf := make([]byte, 32)
binary.LittleEndian.PutUint64(buf, epoch)
binary.LittleEndian.PutUint64(buf, uint64(epoch))
domain, err := helpers.Domain(beaconState.Fork(), epoch, params.BeaconConfig().DomainRandao, beaconState.GenesisValidatorRoot())
require.NoError(t, err)
root, err := (&pb.SigningData{ObjectRoot: buf, Domain: domain}).HashTreeRoot()
@@ -64,13 +64,7 @@ func TestProcessRandao_SignatureVerifiesAndUpdatesLatestStateMixes(t *testing.T)
require.NoError(t, err, "Unexpected error processing block randao")
currentEpoch := helpers.CurrentEpoch(beaconState)
mix := newState.RandaoMixes()[currentEpoch%params.BeaconConfig().EpochsPerHistoricalVector]
if bytes.Equal(mix, params.BeaconConfig().ZeroHash[:]) {
t.Errorf(
"Expected empty signature to be overwritten by randao reveal, received %v",
params.BeaconConfig().EmptySignature,
)
}
assert.DeepNotEqual(t, params.BeaconConfig().ZeroHash[:], mix, "Expected empty signature to be overwritten by randao reveal")
}
func TestRandaoSignatureSet_OK(t *testing.T) {

View File

@@ -15,7 +15,7 @@ import (
)
// retrieves the signature set from the raw data, public key,signature and domain provided.
func retrieveSignatureSet(signedData, pub, signature, domain []byte) (*bls.SignatureSet, error) {
func signatureSet(signedData, pub, signature, domain []byte) (*bls.SignatureSet, error) {
publicKey, err := bls.PublicKeyFromBytes(pub)
if err != nil {
return nil, errors.Wrap(err, "could not convert bytes to public key")
@@ -37,7 +37,7 @@ func retrieveSignatureSet(signedData, pub, signature, domain []byte) (*bls.Signa
// verifies the signature from the raw data, public key and domain provided.
func verifySignature(signedData, pub, signature, domain []byte) error {
set, err := retrieveSignatureSet(signedData, pub, signature, domain)
set, err := signatureSet(signedData, pub, signature, domain)
if err != nil {
return err
}
@@ -85,7 +85,7 @@ func BlockSignatureSet(beaconState *stateTrie.BeaconState, block *ethpb.SignedBe
return nil, err
}
proposerPubKey := proposer.PublicKey
return helpers.RetrieveBlockSignatureSet(block.Block, proposerPubKey, block.Signature, domain)
return helpers.BlockSignatureSet(block.Block, proposerPubKey, block.Signature, domain)
}
// RandaoSignatureSet retrieves the relevant randao specific signature set object
@@ -97,7 +97,7 @@ func RandaoSignatureSet(beaconState *stateTrie.BeaconState,
if err != nil {
return nil, err
}
set, err := retrieveSignatureSet(buf, proposerPub, body.RandaoReveal, domain)
set, err := signatureSet(buf, proposerPub, body.RandaoReveal, domain)
if err != nil {
return nil, err
}
@@ -114,7 +114,7 @@ func randaoSigningData(beaconState *stateTrie.BeaconState) ([]byte, []byte, []by
currentEpoch := helpers.SlotToEpoch(beaconState.Slot())
buf := make([]byte, 32)
binary.LittleEndian.PutUint64(buf, currentEpoch)
binary.LittleEndian.PutUint64(buf, uint64(currentEpoch))
domain, err := helpers.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainRandao, beaconState.GenesisValidatorRoot())
if err != nil {
@@ -138,7 +138,10 @@ func createAttestationSignatureSet(ctx context.Context, beaconState *stateTrie.B
if err != nil {
return nil, err
}
ia := attestationutil.ConvertToIndexed(ctx, a, c)
ia, err := attestationutil.ConvertToIndexed(ctx, a, c)
if err != nil {
return nil, err
}
if err := attestationutil.IsValidAttestationIndices(ctx, ia); err != nil {
return nil, err
}

View File

@@ -44,7 +44,6 @@ go_test(
"//shared/testutil/require:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
"@in_gopkg_d4l3k_messagediff_v1//:go_default_library",
"@io_bazel_rules_go//go/tools/bazel:go_default_library",
],
@@ -80,7 +79,6 @@ go_test(
"//shared/testutil/require:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
"@in_gopkg_d4l3k_messagediff_v1//:go_default_library",
"@io_bazel_rules_go//go/tools/bazel:go_default_library",
],

View File

@@ -37,6 +37,7 @@ go_test(
"//shared/testutil/require:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"@com_github_google_gofuzz//:go_default_library",
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
],

View File

@@ -175,17 +175,17 @@ func ProcessSlashings(state *stateTrie.BeaconState) (*stateTrie.BeaconState, err
// below equally.
increment := params.BeaconConfig().EffectiveBalanceIncrement
minSlashing := mathutil.Min(totalSlashing*params.BeaconConfig().ProportionalSlashingMultiplier, totalBalance)
err = state.ApplyToEveryValidator(func(idx int, val *ethpb.Validator) (bool, error) {
err = state.ApplyToEveryValidator(func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error) {
correctEpoch := (currentEpoch + exitLength/2) == val.WithdrawableEpoch
if val.Slashed && correctEpoch {
penaltyNumerator := val.EffectiveBalance / increment * minSlashing
penalty := penaltyNumerator / totalBalance * increment
if err := helpers.DecreaseBalance(state, uint64(idx), penalty); err != nil {
return false, err
return false, val, err
}
return true, nil
return true, val, nil
}
return false, nil
return false, val, nil
})
return state, err
}
@@ -249,23 +249,24 @@ func ProcessFinalUpdates(state *stateTrie.BeaconState) (*stateTrie.BeaconState,
bals := state.Balances()
// Update effective balances with hysteresis.
validatorFunc := func(idx int, val *ethpb.Validator) (bool, error) {
validatorFunc := func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error) {
if val == nil {
return false, fmt.Errorf("validator %d is nil in state", idx)
return false, nil, fmt.Errorf("validator %d is nil in state", idx)
}
if idx >= len(bals) {
return false, fmt.Errorf("validator index exceeds validator length in state %d >= %d", idx, len(state.Balances()))
return false, nil, fmt.Errorf("validator index exceeds validator length in state %d >= %d", idx, len(state.Balances()))
}
balance := bals[idx]
if balance+downwardThreshold < val.EffectiveBalance || val.EffectiveBalance+upwardThreshold < balance {
val.EffectiveBalance = maxEffBalance
if val.EffectiveBalance > balance-balance%effBalanceInc {
val.EffectiveBalance = balance - balance%effBalanceInc
newVal := stateTrie.CopyValidator(val)
newVal.EffectiveBalance = maxEffBalance
if newVal.EffectiveBalance > balance-balance%effBalanceInc {
newVal.EffectiveBalance = balance - balance%effBalanceInc
}
return true, nil
return true, newVal, nil
}
return false, nil
return false, val, nil
}
if err := state.ApplyToEveryValidator(validatorFunc); err != nil {
@@ -276,20 +277,20 @@ func ProcessFinalUpdates(state *stateTrie.BeaconState) (*stateTrie.BeaconState,
slashedExitLength := params.BeaconConfig().EpochsPerSlashingsVector
slashedEpoch := nextEpoch % slashedExitLength
slashings := state.Slashings()
if uint64(len(slashings)) != slashedExitLength {
if uint64(len(slashings)) != uint64(slashedExitLength) {
return nil, fmt.Errorf(
"state slashing length %d different than EpochsPerHistoricalVector %d",
len(slashings),
slashedExitLength,
)
}
if err := state.UpdateSlashingsAtIndex(slashedEpoch /* index */, 0 /* value */); err != nil {
if err := state.UpdateSlashingsAtIndex(uint64(slashedEpoch) /* index */, 0 /* value */); err != nil {
return nil, err
}
// Set RANDAO mix.
randaoMixLength := params.BeaconConfig().EpochsPerHistoricalVector
if uint64(state.RandaoMixesLength()) != randaoMixLength {
if uint64(state.RandaoMixesLength()) != uint64(randaoMixLength) {
return nil, fmt.Errorf(
"state randao length %d different than EpochsPerHistoricalVector %d",
state.RandaoMixesLength(),
@@ -300,13 +301,13 @@ func ProcessFinalUpdates(state *stateTrie.BeaconState) (*stateTrie.BeaconState,
if err != nil {
return nil, err
}
if err := state.UpdateRandaoMixesAtIndex(nextEpoch%randaoMixLength, mix); err != nil {
if err := state.UpdateRandaoMixesAtIndex(uint64(nextEpoch%randaoMixLength), mix); err != nil {
return nil, err
}
// Set historical root accumulator.
epochsPerHistoricalRoot := params.BeaconConfig().SlotsPerHistoricalRoot / params.BeaconConfig().SlotsPerEpoch
if nextEpoch%epochsPerHistoricalRoot == 0 {
epochsPerHistoricalRoot := params.BeaconConfig().SlotsPerHistoricalRoot.DivSlot(params.BeaconConfig().SlotsPerEpoch)
if nextEpoch.Mod(uint64(epochsPerHistoricalRoot)) == 0 {
historicalBatch := &pb.HistoricalBatch{
BlockRoots: state.BlockRoots(),
StateRoots: state.StateRoots(),
@@ -349,7 +350,10 @@ func UnslashedAttestingIndices(state *stateTrie.BeaconState, atts []*pb.PendingA
if err != nil {
return nil, err
}
attestingIndices := attestationutil.AttestingIndices(att.AggregationBits, committee)
attestingIndices, err := attestationutil.AttestingIndices(att.AggregationBits, committee)
if err != nil {
return nil, err
}
// Create a set for attesting indices
for _, index := range attestingIndices {
if !seen[index] {

View File

@@ -5,6 +5,7 @@ import (
"testing"
"github.com/gogo/protobuf/proto"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/go-bitfield"
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch"
@@ -25,7 +26,7 @@ func TestUnslashedAttestingIndices_CanSortAndFilter(t *testing.T) {
Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{Root: make([]byte, 32)},
Target: &ethpb.Checkpoint{Epoch: 0, Root: make([]byte, 32)},
},
AggregationBits: bitfield.Bitlist{0xFF, 0xFF, 0xFF},
AggregationBits: bitfield.Bitlist{0x00, 0xFF, 0xFF, 0xFF},
}
}
@@ -71,7 +72,7 @@ func TestUnslashedAttestingIndices_DuplicatedAttestations(t *testing.T) {
atts[i] = &pb.PendingAttestation{
Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{Root: make([]byte, 32)},
Target: &ethpb.Checkpoint{Epoch: 0}},
AggregationBits: bitfield.Bitlist{0xFF, 0xFF, 0xFF},
AggregationBits: bitfield.Bitlist{0x00, 0xFF, 0xFF, 0xFF},
}
}
@@ -109,7 +110,7 @@ func TestAttestingBalance_CorrectBalance(t *testing.T) {
Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Root: make([]byte, 32)},
Source: &ethpb.Checkpoint{Root: make([]byte, 32)},
Slot: uint64(i),
Slot: types.Slot(i),
},
AggregationBits: bitfield.Bitlist{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01},
@@ -262,7 +263,7 @@ func TestProcessSlashings_SlashedLess(t *testing.T) {
}
func TestProcessFinalUpdates_CanProcess(t *testing.T) {
s := buildState(t, params.BeaconConfig().SlotsPerHistoricalRoot-1, params.BeaconConfig().SlotsPerEpoch)
s := buildState(t, params.BeaconConfig().SlotsPerHistoricalRoot-1, uint64(params.BeaconConfig().SlotsPerEpoch))
ce := helpers.CurrentEpoch(s)
ne := ce + 1
require.NoError(t, s.SetEth1DataVotes([]*ethpb.Eth1Data{}))
@@ -288,7 +289,7 @@ func TestProcessFinalUpdates_CanProcess(t *testing.T) {
assert.Equal(t, newS.Slashings()[ce], newS.Slashings()[ne], "Unexpected slashed balance")
// Verify randao is correctly updated in the right position.
mix, err := newS.RandaoMixAtIndex(ne)
mix, err := newS.RandaoMixAtIndex(uint64(ne))
assert.NoError(t, err)
assert.DeepNotEqual(t, params.BeaconConfig().ZeroHash[:], mix, "latest RANDAO still zero hashes")
@@ -396,11 +397,11 @@ func TestProcessRegistryUpdates_ValidatorsEjected(t *testing.T) {
}
func TestProcessRegistryUpdates_CanExits(t *testing.T) {
e := uint64(5)
e := types.Epoch(5)
exitEpoch := helpers.ActivationExitEpoch(e)
minWithdrawalDelay := params.BeaconConfig().MinValidatorWithdrawabilityDelay
base := &pb.BeaconState{
Slot: e * params.BeaconConfig().SlotsPerEpoch,
Slot: params.BeaconConfig().SlotsPerEpoch.Mul(uint64(e)),
Validators: []*ethpb.Validator{
{
ExitEpoch: exitEpoch,
@@ -420,7 +421,7 @@ func TestProcessRegistryUpdates_CanExits(t *testing.T) {
}
}
func buildState(t testing.TB, slot, validatorCount uint64) *state.BeaconState {
func buildState(t testing.TB, slot types.Slot, validatorCount uint64) *state.BeaconState {
validators := make([]*ethpb.Validator, validatorCount)
for i := 0; i < len(validators); i++ {
validators[i] = &ethpb.Validator{
@@ -446,7 +447,8 @@ func buildState(t testing.TB, slot, validatorCount uint64) *state.BeaconState {
for i := 0; i < len(latestRandaoMixes); i++ {
latestRandaoMixes[i] = params.BeaconConfig().ZeroHash[:]
}
s := testutil.NewBeaconState()
s, err := testutil.NewBeaconState()
require.NoError(t, err)
if err := s.SetSlot(slot); err != nil {
t.Error(err)
}

View File

@@ -22,6 +22,7 @@ go_library(
"//shared/params:go_default_library",
"//shared/traceutil:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
"@io_opencensus_go//trace:go_default_library",
],
@@ -49,6 +50,7 @@ go_test(
"//shared/testutil/assert:go_default_library",
"//shared/testutil/require:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
],

View File

@@ -5,6 +5,7 @@ import (
"context"
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
@@ -47,7 +48,10 @@ func ProcessAttestations(
if err != nil {
return nil, nil, err
}
indices := attestationutil.AttestingIndices(a.AggregationBits, committee)
indices, err := attestationutil.AttestingIndices(a.AggregationBits, committee)
if err != nil {
return nil, nil, err
}
vp = UpdateValidator(vp, v, indices, a, a.Data.Slot)
}
@@ -103,7 +107,7 @@ func AttestedPrevEpoch(s *stateTrie.BeaconState, a *pb.PendingAttestation) (bool
}
// SameTarget returns true if attestation `a` attested to the same target block in state.
func SameTarget(state *stateTrie.BeaconState, a *pb.PendingAttestation, e uint64) (bool, error) {
func SameTarget(state *stateTrie.BeaconState, a *pb.PendingAttestation, e types.Epoch) (bool, error) {
r, err := helpers.BlockRoot(state, e)
if err != nil {
return false, err
@@ -127,7 +131,7 @@ func SameHead(state *stateTrie.BeaconState, a *pb.PendingAttestation) (bool, err
}
// UpdateValidator updates pre computed validator store.
func UpdateValidator(vp []*Validator, record *Validator, indices []uint64, a *pb.PendingAttestation, aSlot uint64) []*Validator {
func UpdateValidator(vp []*Validator, record *Validator, indices []uint64, a *pb.PendingAttestation, aSlot types.Slot) []*Validator {
inclusionSlot := aSlot + a.InclusionDelay
for _, i := range indices {

View File

@@ -5,6 +5,7 @@ import (
"testing"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/go-bitfield"
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
@@ -16,7 +17,7 @@ import (
)
func TestUpdateValidator_Works(t *testing.T) {
e := params.BeaconConfig().FarFutureEpoch
e := params.BeaconConfig().FarFutureSlot
vp := []*precompute.Validator{{}, {InclusionSlot: e}, {}, {InclusionSlot: e}, {}, {InclusionSlot: e}}
record := &precompute.Validator{IsCurrentEpochAttester: true, IsCurrentEpochTargetAttester: true,
IsPrevEpochAttester: true, IsPrevEpochTargetAttester: true, IsPrevEpochHeadAttester: true}
@@ -33,7 +34,7 @@ func TestUpdateValidator_Works(t *testing.T) {
}
func TestUpdateValidator_InclusionOnlyCountsPrevEpoch(t *testing.T) {
e := params.BeaconConfig().FarFutureEpoch
e := params.BeaconConfig().FarFutureSlot
vp := []*precompute.Validator{{InclusionSlot: e}}
record := &precompute.Validator{IsCurrentEpochAttester: true, IsCurrentEpochTargetAttester: true}
a := &pb.PendingAttestation{InclusionDelay: 1, ProposerIndex: 2}
@@ -149,11 +150,11 @@ func TestProcessAttestations(t *testing.T) {
params.UseMinimalConfig()
defer params.UseMainnetConfig()
validators := uint64(64)
validators := uint64(128)
beaconState, _ := testutil.DeterministicGenesisState(t, validators)
require.NoError(t, beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch))
bf := []byte{0xff}
c := helpers.SlotCommitteeCount(validators)
bf := bitfield.NewBitlist(c)
att1 := &ethpb.Attestation{Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 0}},
AggregationBits: bf}
@@ -183,7 +184,8 @@ func TestProcessAttestations(t *testing.T) {
committee, err := helpers.BeaconCommitteeFromState(beaconState, att1.Data.Slot, att1.Data.CommitteeIndex)
require.NoError(t, err)
indices := attestationutil.AttestingIndices(att1.AggregationBits, committee)
indices, err := attestationutil.AttestingIndices(att1.AggregationBits, committee)
require.NoError(t, err)
for _, i := range indices {
if !pVals[i].IsPrevEpochAttester {
t.Error("Not a prev epoch attester")
@@ -191,7 +193,8 @@ func TestProcessAttestations(t *testing.T) {
}
committee, err = helpers.BeaconCommitteeFromState(beaconState, att2.Data.Slot, att2.Data.CommitteeIndex)
require.NoError(t, err)
indices = attestationutil.AttestingIndices(att2.AggregationBits, committee)
indices, err = attestationutil.AttestingIndices(att2.AggregationBits, committee)
require.NoError(t, err)
for _, i := range indices {
assert.Equal(t, true, pVals[i].IsPrevEpochAttester, "Not a prev epoch attester")
assert.Equal(t, true, pVals[i].IsPrevEpochTargetAttester, "Not a prev epoch target attester")

View File

@@ -3,6 +3,7 @@ package precompute_test
import (
"testing"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/go-bitfield"
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute"
@@ -38,16 +39,16 @@ func TestProcessJustificationAndFinalizationPreCompute_ConsecutiveEpochs(t *test
}
state, err := beaconstate.InitializeFromProto(base)
require.NoError(t, err)
attestedBalance := 4 * e * 3 / 2
attestedBalance := 4 * uint64(e) * 3 / 2
b := &precompute.Balance{PrevEpochTargetAttested: attestedBalance}
newState, err := precompute.ProcessJustificationAndFinalizationPreCompute(state, b)
require.NoError(t, err)
rt := [32]byte{byte(64)}
assert.DeepEqual(t, rt[:], newState.CurrentJustifiedCheckpoint().Root, "Unexpected justified root")
assert.Equal(t, uint64(2), newState.CurrentJustifiedCheckpoint().Epoch, "Unexpected justified epoch")
assert.Equal(t, uint64(0), newState.PreviousJustifiedCheckpoint().Epoch, "Unexpected previous justified epoch")
assert.Equal(t, types.Epoch(2), newState.CurrentJustifiedCheckpoint().Epoch, "Unexpected justified epoch")
assert.Equal(t, types.Epoch(0), newState.PreviousJustifiedCheckpoint().Epoch, "Unexpected previous justified epoch")
assert.DeepEqual(t, params.BeaconConfig().ZeroHash[:], newState.FinalizedCheckpoint().Root, "Unexpected finalized root")
assert.Equal(t, uint64(0), newState.FinalizedCheckpointEpoch(), "Unexpected finalized epoch")
assert.Equal(t, types.Epoch(0), newState.FinalizedCheckpointEpoch(), "Unexpected finalized epoch")
}
func TestProcessJustificationAndFinalizationPreCompute_JustifyCurrentEpoch(t *testing.T) {
@@ -75,16 +76,16 @@ func TestProcessJustificationAndFinalizationPreCompute_JustifyCurrentEpoch(t *te
}
state, err := beaconstate.InitializeFromProto(base)
require.NoError(t, err)
attestedBalance := 4 * e * 3 / 2
attestedBalance := 4 * uint64(e) * 3 / 2
b := &precompute.Balance{PrevEpochTargetAttested: attestedBalance}
newState, err := precompute.ProcessJustificationAndFinalizationPreCompute(state, b)
require.NoError(t, err)
rt := [32]byte{byte(64)}
assert.DeepEqual(t, rt[:], newState.CurrentJustifiedCheckpoint().Root, "Unexpected current justified root")
assert.Equal(t, uint64(2), newState.CurrentJustifiedCheckpoint().Epoch, "Unexpected justified epoch")
assert.Equal(t, uint64(0), newState.PreviousJustifiedCheckpoint().Epoch, "Unexpected previous justified epoch")
assert.Equal(t, types.Epoch(2), newState.CurrentJustifiedCheckpoint().Epoch, "Unexpected justified epoch")
assert.Equal(t, types.Epoch(0), newState.PreviousJustifiedCheckpoint().Epoch, "Unexpected previous justified epoch")
assert.DeepEqual(t, params.BeaconConfig().ZeroHash[:], newState.FinalizedCheckpoint().Root)
assert.Equal(t, uint64(0), newState.FinalizedCheckpointEpoch(), "Unexpected finalized epoch")
assert.Equal(t, types.Epoch(0), newState.FinalizedCheckpointEpoch(), "Unexpected finalized epoch")
}
func TestProcessJustificationAndFinalizationPreCompute_JustifyPrevEpoch(t *testing.T) {
@@ -111,14 +112,14 @@ func TestProcessJustificationAndFinalizationPreCompute_JustifyPrevEpoch(t *testi
}
state, err := beaconstate.InitializeFromProto(base)
require.NoError(t, err)
attestedBalance := 4 * e * 3 / 2
attestedBalance := 4 * uint64(e) * 3 / 2
b := &precompute.Balance{PrevEpochTargetAttested: attestedBalance}
newState, err := precompute.ProcessJustificationAndFinalizationPreCompute(state, b)
require.NoError(t, err)
rt := [32]byte{byte(64)}
assert.DeepEqual(t, rt[:], newState.CurrentJustifiedCheckpoint().Root, "Unexpected current justified root")
assert.Equal(t, uint64(0), newState.PreviousJustifiedCheckpoint().Epoch, "Unexpected previous justified epoch")
assert.Equal(t, uint64(2), newState.CurrentJustifiedCheckpoint().Epoch, "Unexpected justified epoch")
assert.Equal(t, types.Epoch(0), newState.PreviousJustifiedCheckpoint().Epoch, "Unexpected previous justified epoch")
assert.Equal(t, types.Epoch(2), newState.CurrentJustifiedCheckpoint().Epoch, "Unexpected justified epoch")
assert.DeepEqual(t, params.BeaconConfig().ZeroHash[:], newState.FinalizedCheckpoint().Root)
assert.Equal(t, uint64(0), newState.FinalizedCheckpointEpoch(), "Unexpected finalized epoch")
assert.Equal(t, types.Epoch(0), newState.FinalizedCheckpointEpoch(), "Unexpected finalized epoch")
}

View File

@@ -45,8 +45,8 @@ func New(ctx context.Context, state *stateTrie.BeaconState) ([]*Validator, *Bala
}
// Set inclusion slot and inclusion distance to be max, they will be compared and replaced
// with the lower values
pVal.InclusionSlot = params.BeaconConfig().FarFutureEpoch
pVal.InclusionDistance = params.BeaconConfig().FarFutureEpoch
pVal.InclusionSlot = params.BeaconConfig().FarFutureSlot
pVal.InclusionDistance = params.BeaconConfig().FarFutureSlot
pValidators[idx] = pVal
return nil

View File

@@ -29,7 +29,7 @@ func TestNew(t *testing.T) {
},
})
require.NoError(t, err)
e := params.BeaconConfig().FarFutureEpoch
e := params.BeaconConfig().FarFutureSlot
v, b, err := precompute.New(context.Background(), s)
require.NoError(t, err)
assert.DeepEqual(t, &precompute.Validator{

View File

@@ -2,6 +2,7 @@ package precompute
import (
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/shared/mathutil"
@@ -68,7 +69,7 @@ func AttestationsDelta(state *stateTrie.BeaconState, pBal *Balance, vp []*Valida
return rewards, penalties, nil
}
func attestationDelta(pBal *Balance, v *Validator, prevEpoch, finalizedEpoch uint64) (uint64, uint64) {
func attestationDelta(pBal *Balance, v *Validator, prevEpoch, finalizedEpoch types.Epoch) (uint64, uint64) {
eligible := v.IsActivePrevEpoch || (v.IsSlashed && !v.IsWithdrawableCurrentEpoch)
if !eligible || pBal.ActiveCurrentEpoch == 0 {
return 0, 0
@@ -85,7 +86,7 @@ func attestationDelta(pBal *Balance, v *Validator, prevEpoch, finalizedEpoch uin
if v.IsPrevEpochAttester && !v.IsSlashed {
proposerReward := br / params.BeaconConfig().ProposerRewardQuotient
maxAttesterReward := br - proposerReward
r += maxAttesterReward / v.InclusionDistance
r += maxAttesterReward / uint64(v.InclusionDistance)
if isInInactivityLeak(prevEpoch, finalizedEpoch) {
// Since full base reward will be canceled out by inactivity penalty deltas,
@@ -139,7 +140,7 @@ func attestationDelta(pBal *Balance, v *Validator, prevEpoch, finalizedEpoch uin
// Equivalent to the following condition from the spec:
// `index not in get_unslashed_attesting_indices(state, matching_target_attestations)`
if !v.IsPrevEpochTargetAttester || v.IsSlashed {
p += vb * finalityDelay / params.BeaconConfig().InactivityPenaltyQuotient
p += vb * uint64(finalityDelay) / params.BeaconConfig().InactivityPenaltyQuotient
}
}
return r, p
@@ -182,7 +183,7 @@ func ProposersDelta(state *stateTrie.BeaconState, pBal *Balance, vp []*Validator
// Spec code:
// def is_in_inactivity_leak(state: BeaconState) -> bool:
// return get_finality_delay(state) > MIN_EPOCHS_TO_INACTIVITY_PENALTY
func isInInactivityLeak(prevEpoch, finalizedEpoch uint64) bool {
func isInInactivityLeak(prevEpoch, finalizedEpoch types.Epoch) bool {
return finalityDelay(prevEpoch, finalizedEpoch) > params.BeaconConfig().MinEpochsToInactivityPenalty
}
@@ -191,6 +192,6 @@ func isInInactivityLeak(prevEpoch, finalizedEpoch uint64) bool {
// Spec code:
// def get_finality_delay(state: BeaconState) -> uint64:
// return get_previous_epoch(state) - state.finalized_checkpoint.epoch
func finalityDelay(prevEpoch, finalizedEpoch uint64) uint64 {
func finalityDelay(prevEpoch, finalizedEpoch types.Epoch) types.Epoch {
return prevEpoch - finalizedEpoch
}

View File

@@ -4,6 +4,7 @@ import (
"context"
"testing"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/go-bitfield"
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch"
@@ -27,7 +28,7 @@ func TestProcessRewardsAndPenaltiesPrecompute(t *testing.T) {
Target: &ethpb.Checkpoint{Root: make([]byte, 32)},
Source: &ethpb.Checkpoint{Root: make([]byte, 32)},
},
AggregationBits: bitfield.Bitlist{0xC0, 0xC0, 0xC0, 0xC0, 0x01},
AggregationBits: bitfield.Bitlist{0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0x01},
InclusionDelay: 1,
}
}
@@ -70,7 +71,7 @@ func TestAttestationDeltaPrecompute(t *testing.T) {
},
BeaconBlockRoot: emptyRoot[:],
},
AggregationBits: bitfield.Bitlist{0xC0, 0xC0, 0xC0, 0xC0, 0x01},
AggregationBits: bitfield.Bitlist{0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x01},
InclusionDelay: 1,
}
}
@@ -91,7 +92,7 @@ func TestAttestationDeltaPrecompute(t *testing.T) {
// Add some variances to target and head balances.
// See: https://github.com/prysmaticlabs/prysm/issues/5593
bp.PrevEpochTargetAttested = bp.PrevEpochTargetAttested / 2
bp.PrevEpochTargetAttested /= 2
bp.PrevEpochHeadAttested = bp.PrevEpochHeadAttested * 2 / 3
rewards, penalties, err := AttestationsDelta(beaconState, bp, vp)
require.NoError(t, err)
@@ -112,7 +113,7 @@ func TestAttestationDeltaPrecompute(t *testing.T) {
// Base rewards for proposer and attesters working together getting attestation
// on chain in the fatest manner
proposerReward := base / params.BeaconConfig().ProposerRewardQuotient
wanted += (base-proposerReward)*params.BeaconConfig().MinAttestationInclusionDelay - 1
wanted += (base-proposerReward)*uint64(params.BeaconConfig().MinAttestationInclusionDelay) - 1
assert.Equal(t, wanted, rewards[i], "Unexpected reward balance for validator with index %d", i)
// Since all these validators attested, they shouldn't get penalized.
assert.Equal(t, uint64(0), penalties[i], "Unexpected penalty balance")
@@ -154,7 +155,7 @@ func TestAttestationDeltas_ZeroEpoch(t *testing.T) {
},
BeaconBlockRoot: emptyRoot[:],
},
AggregationBits: bitfield.Bitlist{0xC0, 0xC0, 0xC0, 0xC0, 0x01},
AggregationBits: bitfield.Bitlist{0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0x01},
InclusionDelay: 1,
}
}
@@ -217,7 +218,7 @@ func TestProcessRewardsAndPenaltiesPrecompute_SlashedInactivePenalty(t *testing.
Target: &ethpb.Checkpoint{Root: make([]byte, 32)},
Source: &ethpb.Checkpoint{Root: make([]byte, 32)},
},
AggregationBits: bitfield.Bitlist{0xC0, 0xC0, 0xC0, 0xC0, 0x01},
AggregationBits: bitfield.Bitlist{0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0x01},
InclusionDelay: 1,
}
}
@@ -248,13 +249,13 @@ func TestProcessRewardsAndPenaltiesPrecompute_SlashedInactivePenalty(t *testing.
penalty := 3 * base
proposerReward := base / params.BeaconConfig().ProposerRewardQuotient
penalty += params.BeaconConfig().BaseRewardsPerEpoch*base - proposerReward
penalty += vp[i].CurrentEpochEffectiveBalance * finalityDelay / params.BeaconConfig().InactivityPenaltyQuotient
penalty += vp[i].CurrentEpochEffectiveBalance * uint64(finalityDelay) / params.BeaconConfig().InactivityPenaltyQuotient
assert.Equal(t, penalty, penalties[i], "Unexpected slashed indices penalty balance")
assert.Equal(t, uint64(0), rewards[i], "Unexpected slashed indices reward balance")
}
}
func buildState(slot, validatorCount uint64) *pb.BeaconState {
func buildState(slot types.Slot, validatorCount uint64) *pb.BeaconState {
validators := make([]*ethpb.Validator, validatorCount)
for i := 0; i < len(validators); i++ {
validators[i] = &ethpb.Validator{
@@ -353,8 +354,8 @@ func TestFinalityDelay(t *testing.T) {
base.FinalizedCheckpoint = &ethpb.Checkpoint{Epoch: 3}
beaconState, err := state.InitializeFromProto(base)
require.NoError(t, err)
prevEpoch := uint64(0)
finalizedEpoch := uint64(0)
prevEpoch := types.Epoch(0)
finalizedEpoch := types.Epoch(0)
// Set values for each test case
setVal := func() {
prevEpoch = helpers.PrevEpoch(beaconState)
@@ -383,8 +384,8 @@ func TestIsInInactivityLeak(t *testing.T) {
base.FinalizedCheckpoint = &ethpb.Checkpoint{Epoch: 3}
beaconState, err := state.InitializeFromProto(base)
require.NoError(t, err)
prevEpoch := uint64(0)
finalizedEpoch := uint64(0)
prevEpoch := types.Epoch(0)
finalizedEpoch := types.Epoch(0)
// Set values for each test case
setVal := func() {
prevEpoch = helpers.PrevEpoch(beaconState)

View File

@@ -42,17 +42,17 @@ func ProcessSlashingsPrecompute(state *stateTrie.BeaconState, pBal *Balance) err
}
increment := params.BeaconConfig().EffectiveBalanceIncrement
validatorFunc := func(idx int, val *ethpb.Validator) (bool, error) {
validatorFunc := func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error) {
correctEpoch := epochToWithdraw == val.WithdrawableEpoch
if val.Slashed && correctEpoch {
penaltyNumerator := val.EffectiveBalance / increment * minSlashing
penalty := penaltyNumerator / pBal.ActiveCurrentEpoch * increment
if err := helpers.DecreaseBalance(state, uint64(idx), penalty); err != nil {
return false, err
return false, val, err
}
return true, nil
return true, val, nil
}
return false, nil
return false, val, nil
}
return state.ApplyToEveryValidator(validatorFunc)

View File

@@ -37,7 +37,6 @@ go_test(
"//shared/testutil/require:go_default_library",
"@com_github_ghodss_yaml//:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
"@in_gopkg_d4l3k_messagediff_v1//:go_default_library",
"@io_bazel_rules_go//go/tools/bazel:go_default_library",
],
@@ -71,7 +70,6 @@ go_test(
"//shared/testutil/require:go_default_library",
"@com_github_ghodss_yaml//:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
"@in_gopkg_d4l3k_messagediff_v1//:go_default_library",
"@io_bazel_rules_go//go/tools/bazel:go_default_library",
],

View File

@@ -1,5 +1,7 @@
package precompute
import types "github.com/prysmaticlabs/eth2-types"
// Validator stores the pre computation of individual validator's attesting records these records
// consist of attestation votes, block inclusion record. Pre computing and storing such record
// is essential for process epoch optimizations.
@@ -26,9 +28,9 @@ type Validator struct {
// CurrentEpochEffectiveBalance is how much effective balance this validator validator has current epoch.
CurrentEpochEffectiveBalance uint64
// InclusionSlot is the slot of when the attestation gets included in the chain.
InclusionSlot uint64
InclusionSlot types.Slot
// InclusionDistance is the distance between the assigned slot and this validator's attestation was included in block.
InclusionDistance uint64
InclusionDistance types.Slot
// ProposerIndex is the index of proposer at slot where this validator's attestation was included.
ProposerIndex uint64
// BeforeEpochTransitionBalance is the validator balance prior to epoch transition.

View File

@@ -35,7 +35,6 @@ go_test(
"//shared/testutil:go_default_library",
"//shared/testutil/require:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
"@in_gopkg_d4l3k_messagediff_v1//:go_default_library",
"@io_bazel_rules_go//go/tools/bazel:go_default_library",
],

View File

@@ -10,6 +10,7 @@ go_library(
visibility = ["//beacon-chain:__subpackages__"],
deps = [
"//shared/event:go_default_library",
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
],
)

View File

@@ -6,6 +6,7 @@ package state
import (
"time"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
)
@@ -26,7 +27,7 @@ const (
// BlockProcessedData is the data sent with BlockProcessed events.
type BlockProcessedData struct {
// Slot is the slot of the processed block.
Slot uint64
Slot types.Slot
// BlockRoot of the processed block.
BlockRoot [32]byte
// SignedBlock is the physical processed block.
@@ -58,7 +59,7 @@ type InitializedData struct {
// ReorgData is the data alongside a reorg event.
type ReorgData struct {
// NewSlot is the slot of new state after the reorg.
NewSlot uint64
NewSlot types.Slot
// OldSlot is the slot of the head state before the reorg.
OldSlot uint64
OldSlot types.Slot
}

View File

@@ -43,9 +43,9 @@ go_library(
"//shared/timeutils:go_default_library",
"@com_github_ferranbt_fastssz//:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_prysmaticlabs_eth2_types//: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",
],
)
@@ -79,6 +79,7 @@ go_test(
"//shared/testutil/require:go_default_library",
"//shared/timeutils:go_default_library",
"@com_github_google_gofuzz//:go_default_library",
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
],

View File

@@ -6,6 +6,7 @@ import (
"fmt"
"time"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/hashutil"
@@ -35,6 +36,15 @@ func ValidateNilAttestation(attestation *ethpb.Attestation) error {
return nil
}
// ValidateSlotTargetEpoch checks if attestation data's epoch matches target checkpoint's epoch.
// It is recommended to run `ValidateNilAttestation` first to ensure `data.Target` can't be nil.
func ValidateSlotTargetEpoch(data *ethpb.AttestationData) error {
if SlotToEpoch(data.Slot) != data.Target.Epoch {
return fmt.Errorf("slot %d does not match target epoch %d", data.Slot, data.Target.Epoch)
}
return nil
}
// IsAggregator returns true if the signature is from the input validator. The committee
// count is provided as an argument rather than imported implementation from spec. Having
// committee count as an argument allows cheaper computation at run time.
@@ -107,10 +117,10 @@ func ComputeSubnetForAttestation(activeValCount uint64, att *ethpb.Attestation)
// slots_since_epoch_start = attestation.data.slot % SLOTS_PER_EPOCH
// committees_since_epoch_start = get_committee_count_at_slot(state, attestation.data.slot) * slots_since_epoch_start
// return (committees_since_epoch_start + attestation.data.index) % ATTESTATION_SUBNET_COUNT
func ComputeSubnetFromCommitteeAndSlot(activeValCount, comIdx, attSlot uint64) uint64 {
func ComputeSubnetFromCommitteeAndSlot(activeValCount, comIdx uint64, attSlot types.Slot) uint64 {
slotSinceStart := SlotsSinceEpochStarts(attSlot)
comCount := SlotCommitteeCount(activeValCount)
commsSinceStart := comCount * slotSinceStart
commsSinceStart := uint64(slotSinceStart.Mul(comCount))
computedSubnet := (commsSinceStart + comIdx) % params.BeaconNetworkConfig().AttestationSubnetCount
return computedSubnet
}
@@ -126,7 +136,7 @@ func ComputeSubnetFromCommitteeAndSlot(activeValCount, comIdx, attSlot uint64) u
// invalid_attestation_slot = 101
// valid_attestation_slot = 98
// In the attestation must be within the range of 95 to 100 in the example above.
func ValidateAttestationTime(attSlot uint64, genesisTime time.Time) error {
func ValidateAttestationTime(attSlot types.Slot, genesisTime time.Time) error {
if err := ValidateSlotClock(attSlot, uint64(genesisTime.Unix())); err != nil {
return err
}
@@ -146,7 +156,7 @@ func ValidateAttestationTime(attSlot uint64, genesisTime time.Time) error {
// An attestation cannot be older than the current slot - attestation propagation slot range
// with a minor tolerance for peer clock disparity.
lowerBoundsSlot := uint64(0)
lowerBoundsSlot := types.Slot(0)
if currentSlot > params.BeaconNetworkConfig().AttestationPropagationSlotRange {
lowerBoundsSlot = currentSlot - params.BeaconNetworkConfig().AttestationPropagationSlotRange
}
@@ -173,10 +183,10 @@ func ValidateAttestationTime(attSlot uint64, genesisTime time.Time) error {
func VerifyCheckpointEpoch(c *ethpb.Checkpoint, genesis time.Time) bool {
now := uint64(timeutils.Now().Unix())
genesisTime := uint64(genesis.Unix())
currentSlot := (now - genesisTime) / params.BeaconConfig().SecondsPerSlot
currentSlot := types.Slot((now - genesisTime) / params.BeaconConfig().SecondsPerSlot)
currentEpoch := SlotToEpoch(currentSlot)
var prevEpoch uint64
var prevEpoch types.Epoch
if currentEpoch > 1 {
prevEpoch = currentEpoch - 1
}

View File

@@ -5,6 +5,7 @@ import (
"testing"
"time"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
@@ -131,7 +132,7 @@ func Test_ValidateAttestationTime(t *testing.T) {
}
type args struct {
attSlot uint64
attSlot types.Slot
genesisTime time.Time
}
tests := []struct {
@@ -219,7 +220,8 @@ func Test_ValidateAttestationTime(t *testing.T) {
func TestVerifyCheckpointEpoch_Ok(t *testing.T) {
// Genesis was 6 epochs ago exactly.
genesis := time.Now().Add(-1 * time.Second * time.Duration(params.BeaconConfig().SecondsPerSlot*params.BeaconConfig().SlotsPerEpoch*6))
offset := params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().SecondsPerSlot * 6)
genesis := time.Now().Add(-1 * time.Second * time.Duration(offset))
assert.Equal(t, true, helpers.VerifyCheckpointEpoch(&ethpb.Checkpoint{Epoch: 6}, genesis))
assert.Equal(t, true, helpers.VerifyCheckpointEpoch(&ethpb.Checkpoint{Epoch: 5}, genesis))
assert.Equal(t, false, helpers.VerifyCheckpointEpoch(&ethpb.Checkpoint{Epoch: 4}, genesis))
@@ -294,3 +296,44 @@ func TestValidateNilAttestation(t *testing.T) {
})
}
}
func TestValidateSlotTargetEpoch(t *testing.T) {
tests := []struct {
name string
attestation *ethpb.Attestation
errString string
}{
{
name: "incorrect slot",
attestation: &ethpb.Attestation{
Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 1},
Source: &ethpb.Checkpoint{},
},
AggregationBits: []byte{},
},
errString: "slot 0 does not match target epoch 1",
},
{
name: "good attestation",
attestation: &ethpb.Attestation{
Data: &ethpb.AttestationData{
Slot: 2 * params.BeaconConfig().SlotsPerEpoch,
Target: &ethpb.Checkpoint{Epoch: 2},
Source: &ethpb.Checkpoint{},
},
AggregationBits: []byte{},
},
errString: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.errString != "" {
require.ErrorContains(t, tt.errString, helpers.ValidateSlotTargetEpoch(tt.attestation.Data))
} else {
require.NoError(t, helpers.ValidateSlotTargetEpoch(tt.attestation.Data))
}
})
}
}

View File

@@ -1,13 +1,31 @@
package helpers
import (
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"math"
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/shared/params"
)
// VerifyNilBeaconBlock checks if any composite field of input signed beacon block is nil.
// Access to these nil fields will result in run time panic,
// it is recommended to run these checks as first line of defense.
func VerifyNilBeaconBlock(b *ethpb.SignedBeaconBlock) error {
if b == nil {
return errors.New("signed beacon block can't be nil")
}
if b.Block == nil {
return errors.New("beacon block can't be nil")
}
if b.Block.Body == nil {
return errors.New("beacon block body can't be nil")
}
return nil
}
// BlockRootAtSlot returns the block root stored in the BeaconState for a recent slot.
// It returns an error if the requested block root is not within the slot range.
//
@@ -18,23 +36,23 @@ import (
// """
// assert slot < state.slot <= slot + SLOTS_PER_HISTORICAL_ROOT
// return state.block_roots[slot % SLOTS_PER_HISTORICAL_ROOT]
func BlockRootAtSlot(state *stateTrie.BeaconState, slot uint64) ([]byte, error) {
func BlockRootAtSlot(state *stateTrie.BeaconState, slot types.Slot) ([]byte, error) {
if math.MaxUint64-slot < params.BeaconConfig().SlotsPerHistoricalRoot {
return []byte{}, errors.New("slot overflows uint64")
}
if slot >= state.Slot() || state.Slot() > slot+params.BeaconConfig().SlotsPerHistoricalRoot {
return []byte{}, errors.Errorf("slot %d out of bounds", slot)
}
return state.BlockRootAtIndex(slot % params.BeaconConfig().SlotsPerHistoricalRoot)
return state.BlockRootAtIndex(uint64(slot % params.BeaconConfig().SlotsPerHistoricalRoot))
}
// StateRootAtSlot returns the cached state root at that particular slot. If no state
// root has been cached it will return a zero-hash.
func StateRootAtSlot(state *stateTrie.BeaconState, slot uint64) ([]byte, error) {
func StateRootAtSlot(state *stateTrie.BeaconState, slot types.Slot) ([]byte, error) {
if slot >= state.Slot() || state.Slot() > slot+params.BeaconConfig().SlotsPerHistoricalRoot {
return []byte{}, errors.Errorf("slot %d out of bounds", slot)
}
return state.StateRootAtIndex(slot % params.BeaconConfig().SlotsPerHistoricalRoot)
return state.StateRootAtIndex(uint64(slot % params.BeaconConfig().SlotsPerHistoricalRoot))
}
// BlockRoot returns the block root stored in the BeaconState for epoch start slot.
@@ -45,7 +63,7 @@ func StateRootAtSlot(state *stateTrie.BeaconState, slot uint64) ([]byte, error)
// Return the block root at the start of a recent ``epoch``.
// """
// return get_block_root_at_slot(state, compute_start_slot_at_epoch(epoch))
func BlockRoot(state *stateTrie.BeaconState, epoch uint64) ([]byte, error) {
func BlockRoot(state *stateTrie.BeaconState, epoch types.Epoch) ([]byte, error) {
s, err := StartSlot(epoch)
if err != nil {
return nil, err

View File

@@ -5,6 +5,7 @@ import (
"math"
"testing"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
@@ -16,7 +17,7 @@ import (
func TestBlockRootAtSlot_CorrectBlockRoot(t *testing.T) {
var blockRoots [][]byte
for i := uint64(0); i < params.BeaconConfig().SlotsPerHistoricalRoot; i++ {
for i := uint64(0); i < uint64(params.BeaconConfig().SlotsPerHistoricalRoot); i++ {
blockRoots = append(blockRoots, []byte{byte(i)})
}
s := &pb.BeaconState{
@@ -24,8 +25,8 @@ func TestBlockRootAtSlot_CorrectBlockRoot(t *testing.T) {
}
tests := []struct {
slot uint64
stateSlot uint64
slot types.Slot
stateSlot types.Slot
expectedRoot [32]byte
}{
{
@@ -73,7 +74,7 @@ func TestBlockRootAtSlot_CorrectBlockRoot(t *testing.T) {
func TestBlockRootAtSlot_OutOfBounds(t *testing.T) {
var blockRoots [][]byte
for i := uint64(0); i < params.BeaconConfig().SlotsPerHistoricalRoot; i++ {
for i := uint64(0); i < uint64(params.BeaconConfig().SlotsPerHistoricalRoot); i++ {
blockRoots = append(blockRoots, []byte{byte(i)})
}
state := &pb.BeaconState{
@@ -81,8 +82,8 @@ func TestBlockRootAtSlot_OutOfBounds(t *testing.T) {
}
tests := []struct {
slot uint64
stateSlot uint64
slot types.Slot
stateSlot types.Slot
expectedErr string
}{
{

View File

@@ -8,6 +8,7 @@ import (
"sort"
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/go-bitfield"
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
@@ -38,7 +39,7 @@ var proposerIndicesCache = cache.NewProposerIndicesCache()
// len(get_active_validator_indices(state, epoch)) // SLOTS_PER_EPOCH // TARGET_COMMITTEE_SIZE,
// ))
func SlotCommitteeCount(activeValidatorCount uint64) uint64 {
var committeePerSlot = activeValidatorCount / params.BeaconConfig().SlotsPerEpoch / params.BeaconConfig().TargetCommitteeSize
var committeePerSlot = activeValidatorCount / uint64(params.BeaconConfig().SlotsPerEpoch) / params.BeaconConfig().TargetCommitteeSize
if committeePerSlot > params.BeaconConfig().MaxCommitteesPerSlot {
return params.BeaconConfig().MaxCommitteesPerSlot
@@ -67,7 +68,7 @@ func SlotCommitteeCount(activeValidatorCount uint64) uint64 {
// index=(slot % SLOTS_PER_EPOCH) * committees_per_slot + index,
// count=committees_per_slot * SLOTS_PER_EPOCH,
// )
func BeaconCommitteeFromState(state *stateTrie.BeaconState, slot, committeeIndex uint64) ([]uint64, error) {
func BeaconCommitteeFromState(state *stateTrie.BeaconState, slot types.Slot, committeeIndex uint64) ([]uint64, error) {
epoch := SlotToEpoch(slot)
seed, err := Seed(state, epoch, params.BeaconConfig().DomainBeaconAttester)
if err != nil {
@@ -93,7 +94,7 @@ func BeaconCommitteeFromState(state *stateTrie.BeaconState, slot, committeeIndex
// BeaconCommittee returns the crosslink committee of a given slot and committee index. The
// validator indices and seed are provided as an argument rather than a imported implementation
// from the spec definition. Having them as an argument allows for cheaper computation run time.
func BeaconCommittee(validatorIndices []uint64, seed [32]byte, slot, committeeIndex uint64) ([]uint64, error) {
func BeaconCommittee(validatorIndices []uint64, seed [32]byte, slot types.Slot, committeeIndex uint64) ([]uint64, error) {
indices, err := committeeCache.Committee(slot, seed, committeeIndex)
if err != nil {
return nil, errors.Wrap(err, "could not interface with committee cache")
@@ -104,8 +105,8 @@ func BeaconCommittee(validatorIndices []uint64, seed [32]byte, slot, committeeIn
committeesPerSlot := SlotCommitteeCount(uint64(len(validatorIndices)))
epochOffset := committeeIndex + (slot%params.BeaconConfig().SlotsPerEpoch)*committeesPerSlot
count := committeesPerSlot * params.BeaconConfig().SlotsPerEpoch
epochOffset := committeeIndex + uint64(slot.ModSlot(params.BeaconConfig().SlotsPerEpoch).Mul(committeesPerSlot))
count := committeesPerSlot * uint64(params.BeaconConfig().SlotsPerEpoch)
return ComputeCommittee(validatorIndices, seed, epochOffset, count)
}
@@ -154,7 +155,7 @@ func ComputeCommittee(
// CommitteeAssignmentContainer represents a committee, index, and attester slot for a given epoch.
type CommitteeAssignmentContainer struct {
Committee []uint64
AttesterSlot uint64
AttesterSlot types.Slot
CommitteeIndex uint64
}
@@ -167,8 +168,8 @@ type CommitteeAssignmentContainer struct {
// 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) {
epoch types.Epoch,
) (map[uint64]*CommitteeAssignmentContainer, map[uint64][]types.Slot, error) {
nextEpoch := NextEpoch(state)
if epoch > nextEpoch {
return nil, nil, fmt.Errorf(
@@ -185,7 +186,7 @@ func CommitteeAssignments(
if err != nil {
return nil, nil, err
}
proposerIndexToSlots := make(map[uint64][]uint64, params.BeaconConfig().SlotsPerEpoch)
proposerIndexToSlots := make(map[uint64][]types.Slot, params.BeaconConfig().SlotsPerEpoch)
// Proposal epochs do not have a look ahead, so we skip them over here.
validProposalEpoch := epoch < nextEpoch
for slot := startSlot; slot < startSlot+params.BeaconConfig().SlotsPerEpoch && validProposalEpoch; slot++ {
@@ -210,10 +211,10 @@ func CommitteeAssignments(
// Each slot in an epoch has a different set of committees. This value is derived from the
// active validator set, which does not change.
numCommitteesPerSlot := SlotCommitteeCount(uint64(len(activeValidatorIndices)))
validatorIndexToCommittee := make(map[uint64]*CommitteeAssignmentContainer, numCommitteesPerSlot*params.BeaconConfig().SlotsPerEpoch)
validatorIndexToCommittee := make(map[uint64]*CommitteeAssignmentContainer, params.BeaconConfig().SlotsPerEpoch.Mul(numCommitteesPerSlot))
// Compute all committees for all slots.
for i := uint64(0); i < params.BeaconConfig().SlotsPerEpoch; i++ {
for i := types.Slot(0); i < params.BeaconConfig().SlotsPerEpoch; i++ {
// Compute committees.
for j := uint64(0); j < numCommitteesPerSlot; j++ {
slot := startSlot + i
@@ -267,7 +268,7 @@ func VerifyAttestationBitfieldLengths(state *stateTrie.BeaconState, att *ethpb.A
// ShuffledIndices uses input beacon state and returns the shuffled indices of the input epoch,
// the shuffled indices then can be used to break up into committees.
func ShuffledIndices(state *stateTrie.BeaconState, epoch uint64) ([]uint64, error) {
func ShuffledIndices(state *stateTrie.BeaconState, epoch types.Epoch) ([]uint64, error) {
seed, err := Seed(state, epoch, params.BeaconConfig().DomainBeaconAttester)
if err != nil {
return nil, errors.Wrapf(err, "could not get seed for epoch %d", epoch)
@@ -289,8 +290,8 @@ func ShuffledIndices(state *stateTrie.BeaconState, epoch uint64) ([]uint64, erro
// UpdateCommitteeCache gets called at the beginning of every epoch to cache the committee shuffled indices
// list with committee index and epoch number. It caches the shuffled indices for current epoch and next epoch.
func UpdateCommitteeCache(state *stateTrie.BeaconState, epoch uint64) error {
for _, e := range []uint64{epoch, epoch + 1} {
func UpdateCommitteeCache(state *stateTrie.BeaconState, epoch types.Epoch) error {
for _, e := range []types.Epoch{epoch, epoch + 1} {
seed, err := Seed(state, e, params.BeaconConfig().DomainBeaconAttester)
if err != nil {
return err
@@ -318,7 +319,7 @@ func UpdateCommitteeCache(state *stateTrie.BeaconState, epoch uint64) error {
if err := committeeCache.AddCommitteeShuffledList(&cache.Committees{
ShuffledIndices: shuffledIndices,
CommitteeCount: count * params.BeaconConfig().SlotsPerEpoch,
CommitteeCount: uint64(params.BeaconConfig().SlotsPerEpoch.Mul(count)),
Seed: seed,
SortedIndices: sortedIndices,
}); err != nil {
@@ -330,15 +331,15 @@ 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 {
func UpdateProposerIndicesInCache(state *stateTrie.BeaconState) error {
// The cache uses the state root at the (current epoch - 2)'s slot as key. (e.g. for epoch 2, the key is root at slot 31)
// Which is the reason why we skip genesis epoch.
if epoch <= params.BeaconConfig().GenesisEpoch+params.BeaconConfig().MinSeedLookahead {
if CurrentEpoch(state) <= params.BeaconConfig().GenesisEpoch+params.BeaconConfig().MinSeedLookahead {
return nil
}
// Use state root from (current_epoch - 1 - lookahead))
wantedEpoch := PrevEpoch(state)
wantedEpoch := CurrentEpoch(state) - 1
if wantedEpoch >= params.BeaconConfig().MinSeedLookahead {
wantedEpoch -= params.BeaconConfig().MinSeedLookahead
}
@@ -363,7 +364,7 @@ func UpdateProposerIndicesInCache(state *stateTrie.BeaconState, epoch uint64) er
return nil
}
indices, err := ActiveValidatorIndices(state, epoch)
indices, err := ActiveValidatorIndices(state, CurrentEpoch(state))
if err != nil {
return err
}
@@ -398,8 +399,8 @@ func precomputeProposerIndices(state *stateTrie.BeaconState, activeIndices []uin
if err != nil {
return nil, err
}
for i := uint64(0); i < params.BeaconConfig().SlotsPerEpoch; i++ {
seedWithSlot := append(seed[:], bytesutil.Bytes8(slot+i)...)
for i := uint64(0); i < uint64(params.BeaconConfig().SlotsPerEpoch); i++ {
seedWithSlot := append(seed[:], bytesutil.Bytes8(uint64(slot)+i)...)
seedWithSlotHash := hashFunc(seedWithSlot)
index, err := ComputeProposerIndex(state, activeIndices, seedWithSlotHash)
if err != nil {

View File

@@ -6,6 +6,7 @@ import (
"strconv"
"testing"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/go-bitfield"
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
@@ -89,7 +90,7 @@ func TestVerifyBitfieldLength_OK(t *testing.T) {
func TestCommitteeAssignments_CannotRetrieveFutureEpoch(t *testing.T) {
ClearCache()
epoch := uint64(1)
epoch := types.Epoch(1)
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{
Slot: 0, // Epoch 0.
})
@@ -101,7 +102,7 @@ func TestCommitteeAssignments_CannotRetrieveFutureEpoch(t *testing.T) {
func TestCommitteeAssignments_NoProposerForSlot0(t *testing.T) {
validators := make([]*ethpb.Validator, 4*params.BeaconConfig().SlotsPerEpoch)
for i := 0; i < len(validators); i++ {
var activationEpoch uint64
var activationEpoch types.Epoch
if i >= len(validators)/2 {
activationEpoch = 3
}
@@ -131,7 +132,7 @@ func TestCommitteeAssignments_CanRetrieve(t *testing.T) {
validators := make([]*ethpb.Validator, 4*params.BeaconConfig().SlotsPerEpoch)
for i := 0; i < len(validators); i++ {
// First 2 epochs only half validators are activated.
var activationEpoch uint64
var activationEpoch types.Epoch
if i >= len(validators)/2 {
activationEpoch = 3
}
@@ -150,11 +151,11 @@ func TestCommitteeAssignments_CanRetrieve(t *testing.T) {
tests := []struct {
index uint64
slot uint64
slot types.Slot
committee []uint64
committeeIndex uint64
isProposer bool
proposerSlot uint64
proposerSlot types.Slot
}{
{
index: 0,
@@ -208,7 +209,7 @@ func TestCommitteeAssignments_CannotRetrieveFuture(t *testing.T) {
validators := make([]*ethpb.Validator, 4*params.BeaconConfig().SlotsPerEpoch)
for i := 0; i < len(validators); i++ {
// First 2 epochs only half validators are activated.
var activationEpoch uint64
var activationEpoch types.Epoch
if i >= len(validators)/2 {
activationEpoch = 3
}
@@ -249,17 +250,17 @@ func TestCommitteeAssignments_EverySlotHasMin1Proposer(t *testing.T) {
})
require.NoError(t, err)
ClearCache()
epoch := uint64(1)
epoch := types.Epoch(1)
_, proposerIndexToSlots, err := CommitteeAssignments(state, epoch)
require.NoError(t, err, "Failed to determine CommitteeAssignments")
slotsWithProposers := make(map[uint64]bool)
slotsWithProposers := make(map[types.Slot]bool)
for _, proposerSlots := range proposerIndexToSlots {
for _, slot := range proposerSlots {
slotsWithProposers[slot] = true
}
}
assert.Equal(t, params.BeaconConfig().SlotsPerEpoch, uint64(len(slotsWithProposers)), "Unexpected slots")
assert.Equal(t, uint64(params.BeaconConfig().SlotsPerEpoch), uint64(len(slotsWithProposers)), "Unexpected slots")
startSlot, err := StartSlot(epoch)
require.NoError(t, err)
endSlot, err := StartSlot(epoch + 1)
@@ -287,7 +288,7 @@ func TestVerifyAttestationBitfieldLengths_OK(t *testing.T) {
tests := []struct {
attestation *ethpb.Attestation
stateSlot uint64
stateSlot types.Slot
verificationFailure bool
}{
{
@@ -417,12 +418,12 @@ func TestUpdateCommitteeCache_CanUpdate(t *testing.T) {
require.NoError(t, err)
require.NoError(t, UpdateCommitteeCache(state, CurrentEpoch(state)))
epoch := uint64(1)
epoch := types.Epoch(1)
idx := uint64(1)
seed, err := Seed(state, epoch, params.BeaconConfig().DomainBeaconAttester)
require.NoError(t, err)
indices, err = committeeCache.Committee(epoch*params.BeaconConfig().SlotsPerEpoch, seed, idx)
indices, err = committeeCache.Committee(params.BeaconConfig().SlotsPerEpoch.Mul(uint64(epoch)), seed, idx)
require.NoError(t, err)
assert.Equal(t, params.BeaconConfig().TargetCommitteeSize, uint64(len(indices)), "Did not save correct indices lengths")
}
@@ -602,7 +603,7 @@ func BenchmarkComputeCommittee4000000_WithOutCache(b *testing.B) {
func TestBeaconCommitteeFromState_UpdateCacheForPreviousEpoch(t *testing.T) {
committeeSize := uint64(16)
validators := make([]*ethpb.Validator, committeeSize*params.BeaconConfig().SlotsPerEpoch)
validators := make([]*ethpb.Validator, params.BeaconConfig().SlotsPerEpoch.Mul(committeeSize))
for i := 0; i < len(validators); i++ {
validators[i] = &ethpb.Validator{
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
@@ -649,7 +650,7 @@ func TestPrecomputeProposerIndices_Ok(t *testing.T) {
var wantedProposerIndices []uint64
seed, err := Seed(state, 0, params.BeaconConfig().DomainBeaconProposer)
require.NoError(t, err)
for i := uint64(0); i < params.BeaconConfig().SlotsPerEpoch; i++ {
for i := uint64(0); i < uint64(params.BeaconConfig().SlotsPerEpoch); i++ {
seedWithSlot := append(seed[:], bytesutil.Bytes8(i)...)
seedWithSlotHash := hashutil.Hash(seedWithSlot)
index, err := ComputeProposerIndex(state, indices, seedWithSlotHash)
@@ -658,9 +659,3 @@ func TestPrecomputeProposerIndices_Ok(t *testing.T) {
}
assert.DeepEqual(t, wantedProposerIndices, proposerIndices, "Did not precompute proposer indices correctly")
}
func TestUpdateProposerIndicesInCache_SlotOutOfBound(t *testing.T) {
err := UpdateProposerIndicesInCache(&beaconstate.BeaconState{}, 2)
want := "out of bound"
require.ErrorContains(t, want, err)
}

View File

@@ -1,6 +1,7 @@
package helpers
import (
types "github.com/prysmaticlabs/eth2-types"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
@@ -17,7 +18,7 @@ import (
// """
// mix = get_randao_mix(state, Epoch(epoch + EPOCHS_PER_HISTORICAL_VECTOR - MIN_SEED_LOOKAHEAD - 1)) # Avoid underflow
// return hash(domain_type + int_to_bytes(epoch, length=8) + mix)
func Seed(state *stateTrie.BeaconState, epoch uint64, domain [bls.DomainByteLength]byte) ([32]byte, error) {
func Seed(state *stateTrie.BeaconState, epoch types.Epoch, domain [bls.DomainByteLength]byte) ([32]byte, error) {
// See https://github.com/ethereum/eth2.0-specs/pull/1296 for
// rationale on why offset has to look down by 1.
lookAheadEpoch := epoch + params.BeaconConfig().EpochsPerHistoricalVector -
@@ -27,7 +28,7 @@ func Seed(state *stateTrie.BeaconState, epoch uint64, domain [bls.DomainByteLeng
if err != nil {
return [32]byte{}, err
}
seed := append(domain[:], bytesutil.Bytes8(epoch)...)
seed := append(domain[:], bytesutil.Bytes8(uint64(epoch))...)
seed = append(seed, randaoMix...)
seed32 := hashutil.Hash(seed)
@@ -44,6 +45,6 @@ func Seed(state *stateTrie.BeaconState, epoch uint64, domain [bls.DomainByteLeng
// Return the randao mix at a recent ``epoch``.
// """
// return state.randao_mixes[epoch % EPOCHS_PER_HISTORICAL_VECTOR]
func RandaoMix(state *stateTrie.BeaconState, epoch uint64) ([]byte, error) {
return state.RandaoMixAtIndex(epoch % params.BeaconConfig().EpochsPerHistoricalVector)
func RandaoMix(state *stateTrie.BeaconState, epoch types.Epoch) ([]byte, error) {
return state.RandaoMixAtIndex(uint64(epoch % params.BeaconConfig().EpochsPerHistoricalVector))
}

View File

@@ -4,6 +4,7 @@ import (
"encoding/binary"
"testing"
types "github.com/prysmaticlabs/eth2-types"
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
@@ -22,7 +23,7 @@ func TestRandaoMix_OK(t *testing.T) {
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{RandaoMixes: randaoMixes})
require.NoError(t, err)
tests := []struct {
epoch uint64
epoch types.Epoch
randaoMix []byte
}{
{
@@ -39,7 +40,7 @@ func TestRandaoMix_OK(t *testing.T) {
},
}
for _, test := range tests {
require.NoError(t, state.SetSlot((test.epoch+1)*params.BeaconConfig().SlotsPerEpoch))
require.NoError(t, state.SetSlot(params.BeaconConfig().SlotsPerEpoch.Mul(uint64(test.epoch+1))))
mix, err := RandaoMix(state, test.epoch)
require.NoError(t, err)
assert.DeepEqual(t, test.randaoMix, mix, "Incorrect randao mix")
@@ -56,7 +57,7 @@ func TestRandaoMix_CopyOK(t *testing.T) {
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{RandaoMixes: randaoMixes})
require.NoError(t, err)
tests := []struct {
epoch uint64
epoch types.Epoch
randaoMix []byte
}{
{
@@ -73,10 +74,10 @@ func TestRandaoMix_CopyOK(t *testing.T) {
},
}
for _, test := range tests {
require.NoError(t, state.SetSlot((test.epoch+1)*params.BeaconConfig().SlotsPerEpoch))
require.NoError(t, state.SetSlot(params.BeaconConfig().SlotsPerEpoch.Mul(uint64(test.epoch+1))))
mix, err := RandaoMix(state, test.epoch)
require.NoError(t, err)
uniqueNumber := params.BeaconConfig().EpochsPerHistoricalVector + 1000
uniqueNumber := uint64(params.BeaconConfig().EpochsPerHistoricalVector.Add(1000))
binary.LittleEndian.PutUint64(mix, uniqueNumber)
for _, mx := range randaoMixes {
@@ -93,7 +94,7 @@ func TestGenerateSeed_OK(t *testing.T) {
binary.LittleEndian.PutUint64(intInBytes, uint64(i))
randaoMixes[i] = intInBytes
}
slot := 10 * params.BeaconConfig().MinSeedLookahead * params.BeaconConfig().SlotsPerEpoch
slot := params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().MinSeedLookahead * 10))
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{
RandaoMixes: randaoMixes,
Slot: slot,

View File

@@ -51,11 +51,11 @@ func TestSplitIndices_OK(t *testing.T) {
for i := uint64(0); i < numValidators; i++ {
l = append(l, i)
}
split := SplitIndices(l, params.BeaconConfig().SlotsPerEpoch)
assert.Equal(t, params.BeaconConfig().SlotsPerEpoch, uint64(len(split)), "Split list failed due to incorrect length")
split := SplitIndices(l, uint64(params.BeaconConfig().SlotsPerEpoch))
assert.Equal(t, uint64(params.BeaconConfig().SlotsPerEpoch), uint64(len(split)), "Split list failed due to incorrect length")
for _, s := range split {
assert.Equal(t, numValidators/params.BeaconConfig().SlotsPerEpoch, uint64(len(s)), "Split list failed due to incorrect length")
assert.Equal(t, numValidators/uint64(params.BeaconConfig().SlotsPerEpoch), uint64(len(s)), "Split list failed due to incorrect length")
}
}

View File

@@ -3,8 +3,8 @@ package helpers
import (
fssz "github.com/ferranbt/fastssz"
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
ethpb "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/bls"
@@ -23,7 +23,7 @@ const DomainByteLength = 4
var ErrSigFailedToVerify = errors.New("signature did not verify")
// ComputeDomainAndSign computes the domain and signing root and sign it using the passed in private key.
func ComputeDomainAndSign(st *state.BeaconState, epoch uint64, obj interface{}, domain [4]byte, key bls.SecretKey) ([]byte, error) {
func ComputeDomainAndSign(st *state.BeaconState, epoch types.Epoch, obj fssz.HashRoot, domain [4]byte, key bls.SecretKey) ([]byte, error) {
d, err := Domain(st.Fork(), epoch, domain, st.GenesisValidatorRoot())
if err != nil {
return nil, err
@@ -46,16 +46,8 @@ func ComputeDomainAndSign(st *state.BeaconState, epoch uint64, obj interface{},
// object_root=hash_tree_root(ssz_object),
// domain=domain,
// ))
func ComputeSigningRoot(object interface{}, domain []byte) ([32]byte, error) {
if object == nil {
return [32]byte{}, errors.New("cannot compute signing root of nil")
}
return signingData(func() ([32]byte, error) {
if v, ok := object.(fssz.HashRoot); ok {
return v.HashTreeRoot()
}
return ssz.HashTreeRoot(object)
}, domain)
func ComputeSigningRoot(object fssz.HashRoot, domain []byte) ([32]byte, error) {
return signingData(object.HashTreeRoot, domain)
}
// Computes the signing data by utilising the provided root function and then
@@ -73,7 +65,7 @@ func signingData(rootFunc func() ([32]byte, error), domain []byte) ([32]byte, er
}
// ComputeDomainVerifySigningRoot computes domain and verifies signing root of an object given the beacon state, validator index and signature.
func ComputeDomainVerifySigningRoot(st *state.BeaconState, index, epoch uint64, obj interface{}, domain [4]byte, sig []byte) error {
func ComputeDomainVerifySigningRoot(st *state.BeaconState, index uint64, epoch types.Epoch, obj fssz.HashRoot, domain [4]byte, sig []byte) error {
v, err := st.ValidatorAtIndex(index)
if err != nil {
return err
@@ -86,7 +78,7 @@ func ComputeDomainVerifySigningRoot(st *state.BeaconState, index, epoch uint64,
}
// VerifySigningRoot verifies the signing root of an object given it's public key, signature and domain.
func VerifySigningRoot(obj interface{}, pub, signature, domain []byte) error {
func VerifySigningRoot(obj fssz.HashRoot, pub, signature, domain []byte) error {
publicKey, err := bls.PublicKeyFromBytes(pub)
if err != nil {
return errors.Wrap(err, "could not convert bytes to public key")
@@ -107,7 +99,7 @@ func VerifySigningRoot(obj interface{}, pub, signature, domain []byte) error {
// VerifyBlockSigningRoot verifies the signing root of a block given it's public key, signature and domain.
func VerifyBlockSigningRoot(blk *ethpb.BeaconBlock, pub, signature, domain []byte) error {
set, err := RetrieveBlockSignatureSet(blk, pub, signature, domain)
set, err := BlockSignatureSet(blk, pub, signature, domain)
if err != nil {
return err
}
@@ -126,9 +118,9 @@ func VerifyBlockSigningRoot(blk *ethpb.BeaconBlock, pub, signature, domain []byt
return nil
}
// RetrieveBlockSignatureSet retrieves the relevant signature, message and pubkey data from a block and collating it
// BlockSignatureSet retrieves the relevant signature, message and pubkey data from a block and collating it
// into a signature set object.
func RetrieveBlockSignatureSet(blk *ethpb.BeaconBlock, pub, signature, domain []byte) (*bls.SignatureSet, error) {
func BlockSignatureSet(blk *ethpb.BeaconBlock, pub, signature, domain []byte) (*bls.SignatureSet, error) {
publicKey, err := bls.PublicKeyFromBytes(pub)
if err != nil {
return nil, errors.Wrap(err, "could not convert bytes to public key")

View File

@@ -6,6 +6,7 @@ import (
"time"
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/shared/mathutil"
"github.com/prysmaticlabs/prysm/shared/params"
@@ -24,8 +25,8 @@ const MaxSlotBuffer = uint64(1 << 7)
// Return the epoch number of ``slot``.
// """
// return Epoch(slot // SLOTS_PER_EPOCH)
func SlotToEpoch(slot uint64) uint64 {
return slot / params.BeaconConfig().SlotsPerEpoch
func SlotToEpoch(slot types.Slot) types.Epoch {
return types.Epoch(slot.DivSlot(params.BeaconConfig().SlotsPerEpoch))
}
// CurrentEpoch returns the current epoch number calculated from
@@ -37,7 +38,7 @@ func SlotToEpoch(slot uint64) uint64 {
// Return the current epoch.
// """
// return compute_epoch_of_slot(state.slot)
func CurrentEpoch(state *stateTrie.BeaconState) uint64 {
func CurrentEpoch(state *stateTrie.BeaconState) types.Epoch {
return SlotToEpoch(state.Slot())
}
@@ -52,7 +53,7 @@ func CurrentEpoch(state *stateTrie.BeaconState) uint64 {
// """
// current_epoch = get_current_epoch(state)
// return GENESIS_EPOCH if current_epoch == GENESIS_EPOCH else Epoch(current_epoch - 1)
func PrevEpoch(state *stateTrie.BeaconState) uint64 {
func PrevEpoch(state *stateTrie.BeaconState) types.Epoch {
currentEpoch := CurrentEpoch(state)
if currentEpoch == 0 {
return 0
@@ -62,7 +63,7 @@ func PrevEpoch(state *stateTrie.BeaconState) uint64 {
// NextEpoch returns the next epoch number calculated from
// the slot number stored in beacon state.
func NextEpoch(state *stateTrie.BeaconState) uint64 {
func NextEpoch(state *stateTrie.BeaconState) types.Epoch {
return SlotToEpoch(state.Slot()) + 1
}
@@ -75,8 +76,8 @@ func NextEpoch(state *stateTrie.BeaconState) uint64 {
// Return the start slot of ``epoch``.
// """
// return Slot(epoch * SLOTS_PER_EPOCH)
func StartSlot(epoch uint64) (uint64, error) {
slot, err := mathutil.Mul64(epoch, params.BeaconConfig().SlotsPerEpoch)
func StartSlot(epoch types.Epoch) (types.Slot, error) {
slot, err := params.BeaconConfig().SlotsPerEpoch.SafeMul(uint64(epoch))
if err != nil {
return slot, errors.Errorf("start slot calculation overflows: %v", err)
}
@@ -85,7 +86,7 @@ func StartSlot(epoch uint64) (uint64, error) {
// EndSlot returns the last slot number of the
// current epoch.
func EndSlot(epoch uint64) (uint64, error) {
func EndSlot(epoch types.Epoch) (types.Slot, error) {
if epoch == math.MaxUint64 {
return 0, errors.New("start slot calculation overflows")
}
@@ -98,23 +99,23 @@ func EndSlot(epoch uint64) (uint64, error) {
// IsEpochStart returns true if the given slot number is an epoch starting slot
// number.
func IsEpochStart(slot uint64) bool {
func IsEpochStart(slot types.Slot) bool {
return slot%params.BeaconConfig().SlotsPerEpoch == 0
}
// IsEpochEnd returns true if the given slot number is an epoch ending slot
// number.
func IsEpochEnd(slot uint64) bool {
func IsEpochEnd(slot types.Slot) bool {
return IsEpochStart(slot + 1)
}
// SlotsSinceEpochStarts returns number of slots since the start of the epoch.
func SlotsSinceEpochStarts(slot uint64) uint64 {
func SlotsSinceEpochStarts(slot types.Slot) types.Slot {
return slot % params.BeaconConfig().SlotsPerEpoch
}
// VerifySlotTime validates the input slot is not from the future.
func VerifySlotTime(genesisTime, slot uint64, timeTolerance time.Duration) error {
func VerifySlotTime(genesisTime uint64, slot types.Slot, timeTolerance time.Duration) error {
slotTime, err := SlotToTime(genesisTime, slot)
if err != nil {
return err
@@ -136,12 +137,12 @@ func VerifySlotTime(genesisTime, slot uint64, timeTolerance time.Duration) error
}
// SlotToTime takes the given slot and genesis time to determine the start time of the slot.
func SlotToTime(genesisTimeSec, slot uint64) (time.Time, error) {
timeSinceGenesis, err := mathutil.Mul64(slot, params.BeaconConfig().SecondsPerSlot)
func SlotToTime(genesisTimeSec uint64, slot types.Slot) (time.Time, error) {
timeSinceGenesis, err := slot.SafeMul(params.BeaconConfig().SecondsPerSlot)
if err != nil {
return time.Unix(0, 0), fmt.Errorf("slot (%d) is in the far distant future: %w", slot, err)
}
sTime, err := mathutil.Add64(genesisTimeSec, timeSinceGenesis)
sTime, err := timeSinceGenesis.SafeAdd(genesisTimeSec)
if err != nil {
return time.Unix(0, 0), fmt.Errorf("slot (%d) is in the far distant future: %w", slot, err)
}
@@ -149,26 +150,26 @@ func SlotToTime(genesisTimeSec, slot uint64) (time.Time, error) {
}
// SlotsSince computes the number of time slots that have occurred since the given timestamp.
func SlotsSince(time time.Time) uint64 {
func SlotsSince(time time.Time) types.Slot {
return CurrentSlot(uint64(time.Unix()))
}
// CurrentSlot returns the current slot as determined by the local clock and
// provided genesis time.
func CurrentSlot(genesisTimeSec uint64) uint64 {
func CurrentSlot(genesisTimeSec uint64) types.Slot {
now := timeutils.Now().Unix()
genesis := int64(genesisTimeSec)
if now < genesis {
return 0
}
return uint64(now-genesis) / params.BeaconConfig().SecondsPerSlot
return types.Slot(uint64(now-genesis) / params.BeaconConfig().SecondsPerSlot)
}
// ValidateSlotClock validates a provided slot against the local
// clock to ensure slots that are unreasonable are returned with
// an error.
func ValidateSlotClock(slot, genesisTimeSec uint64) error {
maxPossibleSlot := CurrentSlot(genesisTimeSec) + MaxSlotBuffer
func ValidateSlotClock(slot types.Slot, genesisTimeSec uint64) error {
maxPossibleSlot := CurrentSlot(genesisTimeSec).Add(MaxSlotBuffer)
// Defensive check to ensure that we only process slots up to a hard limit
// from our local clock.
if slot > maxPossibleSlot {
@@ -178,7 +179,7 @@ func ValidateSlotClock(slot, genesisTimeSec uint64) error {
}
// RoundUpToNearestEpoch rounds up the provided slot value to the nearest epoch.
func RoundUpToNearestEpoch(slot uint64) uint64 {
func RoundUpToNearestEpoch(slot types.Slot) types.Slot {
if slot%params.BeaconConfig().SlotsPerEpoch != 0 {
slot -= slot % params.BeaconConfig().SlotsPerEpoch
slot += params.BeaconConfig().SlotsPerEpoch
@@ -199,7 +200,7 @@ func RoundUpToNearestEpoch(slot uint64) uint64 {
// else:
// weak_subjectivity_period += SAFETY_DECAY*val_count/(2*100*MIN_PER_EPOCH_CHURN_LIMIT)
// return weak_subjectivity_period
func WeakSubjectivityCheckptEpoch(valCount uint64) (uint64, error) {
func WeakSubjectivityCheckptEpoch(valCount uint64) (types.Epoch, error) {
wsp := params.BeaconConfig().MinValidatorWithdrawabilityDelay
m := params.BeaconConfig().MinPerEpochChurnLimit
@@ -207,24 +208,22 @@ func WeakSubjectivityCheckptEpoch(valCount uint64) (uint64, error) {
d := params.BeaconConfig().SafetyDecay
if valCount >= m*q {
v := d * q / (2 * 100)
wsp += v
wsp += types.Epoch(v)
} else {
v, err := mathutil.Mul64(d, valCount)
if err != nil {
return 0, err
}
v = v / (2 * 100 * m)
wsp += v
v /= 2 * 100 * m
wsp += types.Epoch(v)
}
return wsp, nil
}
// VotingPeriodStartTime returns the current voting period's start time
// depending on the provided genesis and current slot.
func VotingPeriodStartTime(genesis, slot uint64) uint64 {
startTime := genesis
startTime +=
(slot - (slot % (params.BeaconConfig().EpochsPerEth1VotingPeriod * params.BeaconConfig().SlotsPerEpoch))) *
params.BeaconConfig().SecondsPerSlot
return startTime
func VotingPeriodStartTime(genesis uint64, slot types.Slot) uint64 {
slots := params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().EpochsPerEth1VotingPeriod))
startTime := uint64((slot - slot.ModSlot(slots)).Mul(params.BeaconConfig().SecondsPerSlot))
return genesis + startTime
}

View File

@@ -5,19 +5,19 @@ import (
"testing"
"time"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
"github.com/prysmaticlabs/prysm/shared/timeutils"
types "github.com/prysmaticlabs/eth2-types"
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
"github.com/prysmaticlabs/prysm/shared/timeutils"
)
func TestSlotToEpoch_OK(t *testing.T) {
tests := []struct {
slot uint64
epoch uint64
slot types.Slot
epoch types.Epoch
}{
{slot: 0, epoch: 0},
{slot: 50, epoch: 1},
@@ -32,8 +32,8 @@ func TestSlotToEpoch_OK(t *testing.T) {
func TestCurrentEpoch_OK(t *testing.T) {
tests := []struct {
slot uint64
epoch uint64
slot types.Slot
epoch types.Epoch
}{
{slot: 0, epoch: 0},
{slot: 50, epoch: 1},
@@ -50,8 +50,8 @@ func TestCurrentEpoch_OK(t *testing.T) {
func TestPrevEpoch_OK(t *testing.T) {
tests := []struct {
slot uint64
epoch uint64
slot types.Slot
epoch types.Epoch
}{
{slot: 0, epoch: 0},
{slot: 0 + params.BeaconConfig().SlotsPerEpoch + 1, epoch: 0},
@@ -66,14 +66,14 @@ func TestPrevEpoch_OK(t *testing.T) {
func TestNextEpoch_OK(t *testing.T) {
tests := []struct {
slot uint64
epoch uint64
slot types.Slot
epoch types.Epoch
}{
{slot: 0, epoch: 0/params.BeaconConfig().SlotsPerEpoch + 1},
{slot: 50, epoch: 0/params.BeaconConfig().SlotsPerEpoch + 2},
{slot: 64, epoch: 64/params.BeaconConfig().SlotsPerEpoch + 1},
{slot: 128, epoch: 128/params.BeaconConfig().SlotsPerEpoch + 1},
{slot: 200, epoch: 200/params.BeaconConfig().SlotsPerEpoch + 1},
{slot: 0, epoch: types.Epoch(0/params.BeaconConfig().SlotsPerEpoch + 1)},
{slot: 50, epoch: types.Epoch(0/params.BeaconConfig().SlotsPerEpoch + 2)},
{slot: 64, epoch: types.Epoch(64/params.BeaconConfig().SlotsPerEpoch + 1)},
{slot: 128, epoch: types.Epoch(128/params.BeaconConfig().SlotsPerEpoch + 1)},
{slot: 200, epoch: types.Epoch(200/params.BeaconConfig().SlotsPerEpoch + 1)},
}
for _, tt := range tests {
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{Slot: tt.slot})
@@ -84,8 +84,8 @@ func TestNextEpoch_OK(t *testing.T) {
func TestEpochStartSlot_OK(t *testing.T) {
tests := []struct {
epoch uint64
startSlot uint64
epoch types.Epoch
startSlot types.Slot
error bool
}{
{epoch: 0, startSlot: 0 * params.BeaconConfig().SlotsPerEpoch, error: false},
@@ -108,8 +108,8 @@ func TestEpochStartSlot_OK(t *testing.T) {
func TestEpochEndSlot_OK(t *testing.T) {
tests := []struct {
epoch uint64
startSlot uint64
epoch types.Epoch
startSlot types.Slot
error bool
}{
{epoch: 0, startSlot: 1*params.BeaconConfig().SlotsPerEpoch - 1, error: false},
@@ -134,7 +134,7 @@ func TestIsEpochStart(t *testing.T) {
epochLength := params.BeaconConfig().SlotsPerEpoch
tests := []struct {
slot uint64
slot types.Slot
result bool
}{
{
@@ -164,7 +164,7 @@ func TestIsEpochEnd(t *testing.T) {
epochLength := params.BeaconConfig().SlotsPerEpoch
tests := []struct {
slot uint64
slot types.Slot
result bool
}{
{
@@ -188,8 +188,8 @@ func TestIsEpochEnd(t *testing.T) {
func TestSlotsSinceEpochStarts(t *testing.T) {
tests := []struct {
slots uint64
wantedSlots uint64
slots types.Slot
wantedSlots types.Slot
}{
{slots: 0, wantedSlots: 0},
{slots: 1, wantedSlots: 1},
@@ -204,8 +204,8 @@ func TestSlotsSinceEpochStarts(t *testing.T) {
func TestRoundUpToNearestEpoch_OK(t *testing.T) {
tests := []struct {
startSlot uint64
roundedUpSlot uint64
startSlot types.Slot
roundedUpSlot types.Slot
}{
{startSlot: 0 * params.BeaconConfig().SlotsPerEpoch, roundedUpSlot: 0},
{startSlot: 1*params.BeaconConfig().SlotsPerEpoch - 10, roundedUpSlot: 1 * params.BeaconConfig().SlotsPerEpoch},
@@ -219,7 +219,7 @@ func TestRoundUpToNearestEpoch_OK(t *testing.T) {
func TestSlotToTime(t *testing.T) {
type args struct {
genesisTimeSec uint64
slot uint64
slot types.Slot
}
tests := []struct {
name string
@@ -276,7 +276,7 @@ func TestSlotToTime(t *testing.T) {
func TestVerifySlotTime(t *testing.T) {
type args struct {
genesisTime int64
slot uint64
slot types.Slot
timeTolerance time.Duration
}
tests := []struct {
@@ -310,7 +310,7 @@ func TestVerifySlotTime(t *testing.T) {
name: "max future slot",
args: args{
genesisTime: timeutils.Now().Add(-1 * 5 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second).Unix(),
slot: MaxSlotBuffer + 6,
slot: types.Slot(MaxSlotBuffer + 6),
},
wantedErr: "exceeds max allowed value relative to the local clock",
},
@@ -320,7 +320,7 @@ func TestVerifySlotTime(t *testing.T) {
genesisTime: timeutils.Now().Add(-1 * 24 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second).Unix(), // 24 slots in the past
// Gets multiplied with slot duration, and results in an overflow. Wraps around to a valid time.
// Lower than max signed int. And chosen specifically to wrap to a valid slot 24
slot: ((^uint64(0)) / params.BeaconConfig().SecondsPerSlot) + 24,
slot: types.Slot((^uint64(0))/params.BeaconConfig().SecondsPerSlot) + 24,
},
wantedErr: "is in the far distant future",
},
@@ -340,16 +340,16 @@ func TestVerifySlotTime(t *testing.T) {
func TestValidateSlotClock_HandlesBadSlot(t *testing.T) {
genTime := timeutils.Now().Add(-1 * time.Duration(MaxSlotBuffer) * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second).Unix()
assert.NoError(t, ValidateSlotClock(MaxSlotBuffer, uint64(genTime)), "unexpected error validating slot")
assert.NoError(t, ValidateSlotClock(2*MaxSlotBuffer, uint64(genTime)), "unexpected error validating slot")
assert.ErrorContains(t, "which exceeds max allowed value relative to the local clock", ValidateSlotClock(2*MaxSlotBuffer+1, uint64(genTime)), "no error from bad slot")
assert.NoError(t, ValidateSlotClock(types.Slot(MaxSlotBuffer), uint64(genTime)), "unexpected error validating slot")
assert.NoError(t, ValidateSlotClock(types.Slot(2*MaxSlotBuffer), uint64(genTime)), "unexpected error validating slot")
assert.ErrorContains(t, "which exceeds max allowed value relative to the local clock", ValidateSlotClock(types.Slot(2*MaxSlotBuffer+1), uint64(genTime)), "no error from bad slot")
assert.ErrorContains(t, "which exceeds max allowed value relative to the local clock", ValidateSlotClock(1<<63, uint64(genTime)), "no error from bad slot")
}
func TestWeakSubjectivityCheckptEpoch(t *testing.T) {
tests := []struct {
valCount uint64
want uint64
want types.Epoch
}{
// Verifying these numbers aligned with the reference table defined:
// https://github.com/ethereum/eth2.0-specs/blob/weak-subjectivity-guide/specs/phase0/weak-subjectivity.md#calculating-the-weak-subjectivity-period

View File

@@ -4,6 +4,7 @@ import (
"bytes"
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
@@ -22,16 +23,16 @@ import (
// Check if ``validator`` is active.
// """
// return validator.activation_epoch <= epoch < validator.exit_epoch
func IsActiveValidator(validator *ethpb.Validator, epoch uint64) bool {
func IsActiveValidator(validator *ethpb.Validator, epoch types.Epoch) bool {
return checkValidatorActiveStatus(validator.ActivationEpoch, validator.ExitEpoch, epoch)
}
// IsActiveValidatorUsingTrie checks if a read only validator is active.
func IsActiveValidatorUsingTrie(validator stateTrie.ReadOnlyValidator, epoch uint64) bool {
func IsActiveValidatorUsingTrie(validator stateTrie.ReadOnlyValidator, epoch types.Epoch) bool {
return checkValidatorActiveStatus(validator.ActivationEpoch(), validator.ExitEpoch(), epoch)
}
func checkValidatorActiveStatus(activationEpoch, exitEpoch, epoch uint64) bool {
func checkValidatorActiveStatus(activationEpoch, exitEpoch, epoch types.Epoch) bool {
return activationEpoch <= epoch && epoch < exitEpoch
}
@@ -44,16 +45,16 @@ func checkValidatorActiveStatus(activationEpoch, exitEpoch, epoch uint64) bool {
// Check if ``validator`` is slashable.
// """
// return (not validator.slashed) and (validator.activation_epoch <= epoch < validator.withdrawable_epoch)
func IsSlashableValidator(activationEpoch, withdrawableEpoch uint64, slashed bool, epoch uint64) bool {
func IsSlashableValidator(activationEpoch, withdrawableEpoch types.Epoch, slashed bool, epoch types.Epoch) bool {
return checkValidatorSlashable(activationEpoch, withdrawableEpoch, slashed, epoch)
}
// IsSlashableValidatorUsingTrie checks if a read only validator is slashable.
func IsSlashableValidatorUsingTrie(val stateTrie.ReadOnlyValidator, epoch uint64) bool {
func IsSlashableValidatorUsingTrie(val stateTrie.ReadOnlyValidator, epoch types.Epoch) bool {
return checkValidatorSlashable(val.ActivationEpoch(), val.WithdrawableEpoch(), val.Slashed(), epoch)
}
func checkValidatorSlashable(activationEpoch, withdrawableEpoch uint64, slashed bool, epoch uint64) bool {
func checkValidatorSlashable(activationEpoch, withdrawableEpoch types.Epoch, slashed bool, epoch types.Epoch) bool {
active := activationEpoch <= epoch
beforeWithdrawable := epoch < withdrawableEpoch
return beforeWithdrawable && active && !slashed
@@ -72,7 +73,7 @@ func checkValidatorSlashable(activationEpoch, withdrawableEpoch uint64, slashed
// Return the sequence of active validator indices at ``epoch``.
// """
// return [ValidatorIndex(i) for i, v in enumerate(state.validators) if is_active_validator(v, epoch)]
func ActiveValidatorIndices(state *stateTrie.BeaconState, epoch uint64) ([]uint64, error) {
func ActiveValidatorIndices(state *stateTrie.BeaconState, epoch types.Epoch) ([]uint64, error) {
seed, err := Seed(state, epoch, params.BeaconConfig().DomainBeaconAttester)
if err != nil {
return nil, errors.Wrap(err, "could not get seed")
@@ -103,7 +104,7 @@ func ActiveValidatorIndices(state *stateTrie.BeaconState, epoch uint64) ([]uint6
// ActiveValidatorCount returns the number of active validators in the state
// at the given epoch.
func ActiveValidatorCount(state *stateTrie.BeaconState, epoch uint64) (uint64, error) {
func ActiveValidatorCount(state *stateTrie.BeaconState, epoch types.Epoch) (uint64, error) {
seed, err := Seed(state, epoch, params.BeaconConfig().DomainBeaconAttester)
if err != nil {
return 0, errors.Wrap(err, "could not get seed")
@@ -142,7 +143,7 @@ func ActiveValidatorCount(state *stateTrie.BeaconState, epoch uint64) (uint64, e
// Return the epoch during which validator activations and exits initiated in ``epoch`` take effect.
// """
// return Epoch(epoch + 1 + MAX_SEED_LOOKAHEAD)
func ActivationExitEpoch(epoch uint64) uint64 {
func ActivationExitEpoch(epoch types.Epoch) types.Epoch {
return epoch + 1 + params.BeaconConfig().MaxSeedLookahead
}
@@ -203,7 +204,7 @@ func BeaconProposerIndex(state *stateTrie.BeaconState) (uint64, error) {
}
return proposerIndices[state.Slot()%params.BeaconConfig().SlotsPerEpoch], nil
}
if err := UpdateProposerIndicesInCache(state, e); err != nil {
if err := UpdateProposerIndicesInCache(state); err != nil {
return 0, errors.Wrap(err, "could not update committee cache")
}
}
@@ -214,7 +215,7 @@ func BeaconProposerIndex(state *stateTrie.BeaconState) (uint64, error) {
return 0, errors.Wrap(err, "could not generate seed")
}
seedWithSlot := append(seed[:], bytesutil.Bytes8(state.Slot())...)
seedWithSlot := append(seed[:], bytesutil.Bytes8(uint64(state.Slot()))...)
seedWithSlotHash := hashutil.Hash(seedWithSlot)
indices, err := ActiveValidatorIndices(state, e)
@@ -283,7 +284,7 @@ func ComputeProposerIndex(bState *stateTrie.BeaconState, activeIndices []uint64,
// 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 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) {
func Domain(fork *pb.Fork, epoch types.Epoch, domainType [bls.DomainByteLength]byte, genesisRoot []byte) ([]byte, error) {
if fork == nil {
return []byte{}, errors.New("nil fork or domain type")
}
@@ -324,7 +325,7 @@ func IsEligibleForActivationQueueUsingTrie(validator stateTrie.ReadOnlyValidator
}
// isEligibleForActivationQueue carries out the logic for IsEligibleForActivationQueue*
func isEligibileForActivationQueue(activationEligibilityEpoch, effectiveBalance uint64) bool {
func isEligibileForActivationQueue(activationEligibilityEpoch types.Epoch, effectiveBalance uint64) bool {
return activationEligibilityEpoch == params.BeaconConfig().FarFutureEpoch &&
effectiveBalance == params.BeaconConfig().MaxEffectiveBalance
}
@@ -357,7 +358,7 @@ func IsEligibleForActivationUsingTrie(state *stateTrie.BeaconState, validator st
}
// isEligibleForActivation carries out the logic for IsEligibleForActivation*
func isEligibleForActivation(activationEligibilityEpoch, activationEpoch, finalizedEpoch uint64) bool {
func isEligibleForActivation(activationEligibilityEpoch, activationEpoch, finalizedEpoch types.Epoch) bool {
return activationEligibilityEpoch <= finalizedEpoch &&
activationEpoch == params.BeaconConfig().FarFutureEpoch
}

View File

@@ -4,6 +4,7 @@ import (
"errors"
"testing"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
@@ -17,7 +18,7 @@ import (
func TestIsActiveValidator_OK(t *testing.T) {
tests := []struct {
a uint64
a types.Epoch
b bool
}{
{a: 0, b: false},
@@ -34,7 +35,7 @@ func TestIsActiveValidator_OK(t *testing.T) {
func TestIsActiveValidatorUsingTrie_OK(t *testing.T) {
tests := []struct {
a uint64
a types.Epoch
b bool
}{
{a: 0, b: false},
@@ -57,7 +58,7 @@ func TestIsSlashableValidator_OK(t *testing.T) {
tests := []struct {
name string
validator *ethpb.Validator
epoch uint64
epoch types.Epoch
slashable bool
}{
{
@@ -139,7 +140,7 @@ func TestIsSlashableValidatorUsingTrie_OK(t *testing.T) {
tests := []struct {
name string
validator *ethpb.Validator
epoch uint64
epoch types.Epoch
slashable bool
}{
{
@@ -241,7 +242,7 @@ func TestBeaconProposerIndex_OK(t *testing.T) {
require.NoError(t, err)
tests := []struct {
slot uint64
slot types.Slot
index uint64
}{
{
@@ -288,7 +289,7 @@ func TestBeaconProposerIndex_BadState(t *testing.T) {
}
}
roots := make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot)
for i := uint64(0); i < params.BeaconConfig().SlotsPerHistoricalRoot; i++ {
for i := uint64(0); i < uint64(params.BeaconConfig().SlotsPerHistoricalRoot); i++ {
roots[i] = make([]byte, 32)
}
@@ -328,7 +329,7 @@ func TestComputeProposerIndex_Compatibility(t *testing.T) {
var proposerIndices []uint64
seed, err := Seed(state, 0, params.BeaconConfig().DomainBeaconProposer)
require.NoError(t, err)
for i := uint64(0); i < params.BeaconConfig().SlotsPerEpoch; i++ {
for i := uint64(0); i < uint64(params.BeaconConfig().SlotsPerEpoch); i++ {
seedWithSlot := append(seed[:], bytesutil.Bytes8(i)...)
seedWithSlotHash := hashutil.Hash(seedWithSlot)
index, err := ComputeProposerIndex(state, indices, seedWithSlotHash)
@@ -339,7 +340,7 @@ func TestComputeProposerIndex_Compatibility(t *testing.T) {
var wantedProposerIndices []uint64
seed, err = Seed(state, 0, params.BeaconConfig().DomainBeaconProposer)
require.NoError(t, err)
for i := uint64(0); i < params.BeaconConfig().SlotsPerEpoch; i++ {
for i := uint64(0); i < uint64(params.BeaconConfig().SlotsPerEpoch); i++ {
seedWithSlot := append(seed[:], bytesutil.Bytes8(i)...)
seedWithSlotHash := hashutil.Hash(seedWithSlot)
index, err := computeProposerIndexWithValidators(state.Validators(), indices, seedWithSlotHash)
@@ -350,7 +351,7 @@ func TestComputeProposerIndex_Compatibility(t *testing.T) {
}
func TestDelayedActivationExitEpoch_OK(t *testing.T) {
epoch := uint64(9999)
epoch := types.Epoch(9999)
wanted := epoch + 1 + params.BeaconConfig().MaxSeedLookahead
assert.Equal(t, wanted, ActivationExitEpoch(epoch))
}
@@ -422,7 +423,7 @@ func TestDomain_OK(t *testing.T) {
},
}
tests := []struct {
epoch uint64
epoch types.Epoch
domainType [4]byte
result []byte
}{
@@ -445,7 +446,7 @@ func TestActiveValidatorIndices(t *testing.T) {
farFutureEpoch := params.BeaconConfig().FarFutureEpoch
type args struct {
state *pb.BeaconState
epoch uint64
epoch types.Epoch
}
tests := []struct {
name string

View File

@@ -9,6 +9,7 @@ go_library(
"log.go",
"skip_slot_cache.go",
"state.go",
"trailing_slot_state_cache.go",
"transition.go",
],
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/core/state",
@@ -34,12 +35,16 @@ go_library(
"//proto/beacon/p2p/v1:go_default_library",
"//shared/bls:go_default_library",
"//shared/bytesutil:go_default_library",
"//shared/featureconfig:go_default_library",
"//shared/hashutil:go_default_library",
"//shared/mathutil:go_default_library",
"//shared/params:go_default_library",
"//shared/traceutil:go_default_library",
"//shared/trieutil:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_prometheus_client_golang//prometheus:go_default_library",
"@com_github_prometheus_client_golang//prometheus/promauto:go_default_library",
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@io_opencensus_go//trace:go_default_library",
@@ -54,6 +59,7 @@ go_test(
"skip_slot_cache_test.go",
"state_fuzz_test.go",
"state_test.go",
"trailing_slot_state_cache_test.go",
"transition_fuzz_test.go",
"transition_test.go",
],
@@ -74,13 +80,13 @@ go_test(
"//shared/bytesutil:go_default_library",
"//shared/hashutil:go_default_library",
"//shared/params:go_default_library",
"//shared/sszutil:go_default_library",
"//shared/testutil:go_default_library",
"//shared/testutil/assert:go_default_library",
"//shared/testutil/require:go_default_library",
"//shared/trieutil:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"@com_github_google_gofuzz//:go_default_library",
"@com_github_prysmaticlabs_eth2_types//: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",
@@ -112,6 +118,5 @@ go_test(
"//shared/params:go_default_library",
"//shared/testutil/require:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
],
)

View File

@@ -2,6 +2,7 @@ package state
import (
"context"
"errors"
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
@@ -19,9 +20,13 @@ var SkipSlotCache = cache.NewSkipSlotCache()
// state root is in the mix to defend against different forks with same skip slots
// to hit the same cache. We don't want beacon states mixed up between different chains.
func cacheKey(ctx context.Context, state *beaconstate.BeaconState) ([32]byte, error) {
r, err := state.HashTreeRoot(ctx)
bh := state.LatestBlockHeader()
if bh == nil {
return [32]byte{}, errors.New("block head in state can't be nil")
}
r, err := bh.HashTreeRoot()
if err != nil {
return [32]byte{}, err
}
return hashutil.Hash(append(bytesutil.Bytes32(state.Slot()), r[:]...)), nil
return hashutil.Hash(append(bytesutil.Bytes32(uint64(state.Slot())), r[:]...)), nil
}

View File

@@ -1,7 +1,6 @@
package state_test
import (
"bytes"
"context"
"sync"
"testing"
@@ -9,8 +8,8 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/sszutil"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
)
@@ -34,9 +33,7 @@ func TestSkipSlotCache_OK(t *testing.T) {
bState, err = state.ExecuteStateTransition(context.Background(), bState, blk)
require.NoError(t, err, "Could not process state transition")
if !sszutil.DeepEqual(originalState.CloneInnerState(), bState.CloneInnerState()) {
t.Fatal("Skipped slots cache leads to different states")
}
assert.DeepEqual(t, originalState.CloneInnerState(), bState.CloneInnerState(), "Skipped slots cache leads to different states")
}
func TestSkipSlotCache_ConcurrentMixup(t *testing.T) {
@@ -113,9 +110,8 @@ func TestSkipSlotCache_ConcurrentMixup(t *testing.T) {
tmp1, err := state.ProcessSlots(context.Background(), expected1.Copy(), problemSlot+1)
require.NoError(t, err)
if gotRoot := tmp1.StateRoots()[problemSlot]; !bytes.Equal(gotRoot, expectedRoot1[:]) {
t.Fatalf("state roots for chain 1 are bad, expected root doesn't match: %x <> %x", gotRoot, expectedRoot1[:])
}
gotRoot := tmp1.StateRoots()[problemSlot]
require.DeepEqual(t, expectedRoot1[:], gotRoot, "State roots for chain 1 are bad, expected root doesn't match")
expected2, err := state.ProcessSlots(context.Background(), state2.Copy(), problemSlot)
require.NoError(t, err)
@@ -125,27 +121,22 @@ func TestSkipSlotCache_ConcurrentMixup(t *testing.T) {
tmp2, err := state.ProcessSlots(context.Background(), expected2.Copy(), problemSlot+1)
require.NoError(t, err)
if gotRoot := tmp2.StateRoots()[problemSlot]; !bytes.Equal(gotRoot, expectedRoot2[:]) {
t.Fatalf("state roots for chain 2 are bad, expected root doesn't match %x <> %x", gotRoot, expectedRoot2[:])
}
gotRoot = tmp2.StateRoots()[problemSlot]
require.DeepEqual(t, expectedRoot2[:], gotRoot, "State roots for chain 2 are bad, expected root doesn't match")
var wg sync.WaitGroup
wg.Add(len(setups))
step := func(i int, setup *beaconstate.BeaconState) {
// go at least 1 past problemSlot, to ensure problem slot state root is available
outState, err := state.ProcessSlots(context.Background(), setup, problemSlot+1+uint64(i)) // keep increasing, to hit and extend the cache
outState, err := state.ProcessSlots(context.Background(), setup, problemSlot.Add(1+uint64(i))) // keep increasing, to hit and extend the cache
require.NoError(t, err, "Could not process state transition")
roots := outState.StateRoots()
gotRoot := roots[problemSlot]
if i%2 == 0 {
if !bytes.Equal(gotRoot, expectedRoot1[:]) {
t.Errorf("unexpected root on chain 1, item %3d: %x", i, gotRoot)
}
assert.DeepEqual(t, expectedRoot1[:], gotRoot, "Unexpected root on chain 1")
} else {
if !bytes.Equal(gotRoot, expectedRoot2[:]) {
t.Errorf("unexpected root on chain 2, item %3d: %x", i, gotRoot)
}
assert.DeepEqual(t, expectedRoot2[:], gotRoot, "Unexpected root on chain 2")
}
wg.Done()
}

View File

@@ -34,7 +34,6 @@ go_test(
"//shared/testutil/require:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
"@com_github_urfave_cli_v2//:go_default_library",
"@in_gopkg_d4l3k_messagediff_v1//:go_default_library",
"@io_bazel_rules_go//go/tools/bazel:go_default_library",
@@ -69,7 +68,6 @@ go_test(
"//shared/testutil/require:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
"@com_github_urfave_cli_v2//:go_default_library",
"@in_gopkg_d4l3k_messagediff_v1//:go_default_library",
"@io_bazel_rules_go//go/tools/bazel:go_default_library",

View File

@@ -43,7 +43,7 @@ func runSlotProcessingTests(t *testing.T, config string) {
require.NoError(t, err)
postBeaconState := &pb.BeaconState{}
require.NoError(t, postBeaconState.UnmarshalSSZ(postBeaconStateFile), "Failed to unmarshal")
postState, err := state.ProcessSlots(context.Background(), beaconState, beaconState.Slot()+uint64(slotsCount))
postState, err := state.ProcessSlots(context.Background(), beaconState, beaconState.Slot().Add(uint64(slotsCount)))
require.NoError(t, err)
if !proto.Equal(postState.CloneInnerState(), postBeaconState) {

View File

@@ -4,6 +4,7 @@ import (
"testing"
"github.com/gogo/protobuf/proto"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
@@ -15,19 +16,19 @@ import (
)
func TestGenesisBeaconState_OK(t *testing.T) {
genesisEpochNumber := uint64(0)
genesisEpoch := types.Epoch(0)
assert.DeepEqual(t, []byte{0, 0, 0, 0}, params.BeaconConfig().GenesisForkVersion, "GenesisSlot( should be {0,0,0,0} for these tests to pass")
genesisForkVersion := params.BeaconConfig().GenesisForkVersion
assert.Equal(t, [32]byte{}, params.BeaconConfig().ZeroHash, "ZeroHash should be all 0s for these tests to pass")
assert.Equal(t, uint64(65536), params.BeaconConfig().EpochsPerHistoricalVector, "EpochsPerHistoricalVector should be 8192 for these tests to pass")
assert.Equal(t, types.Epoch(65536), params.BeaconConfig().EpochsPerHistoricalVector, "EpochsPerHistoricalVector should be 8192 for these tests to pass")
latestRandaoMixesLength := params.BeaconConfig().EpochsPerHistoricalVector
assert.Equal(t, uint64(16777216), params.BeaconConfig().HistoricalRootsLimit, "HistoricalRootsLimit should be 16777216 for these tests to pass")
depositsForChainStart := 100
assert.Equal(t, uint64(8192), params.BeaconConfig().EpochsPerSlashingsVector, "EpochsPerSlashingsVector should be 8192 for these tests to pass")
assert.Equal(t, types.Epoch(8192), params.BeaconConfig().EpochsPerSlashingsVector, "EpochsPerSlashingsVector should be 8192 for these tests to pass")
genesisTime := uint64(99999)
deposits, _, err := testutil.DeterministicDepositsAndKeys(uint64(depositsForChainStart))
@@ -38,11 +39,11 @@ func TestGenesisBeaconState_OK(t *testing.T) {
require.NoError(t, err, "Could not execute GenesisBeaconState")
// Misc fields checks.
assert.Equal(t, uint64(0), newState.Slot(), "Slot was not correctly initialized")
assert.Equal(t, types.Slot(0), newState.Slot(), "Slot was not correctly initialized")
if !proto.Equal(newState.Fork(), &pb.Fork{
PreviousVersion: genesisForkVersion,
CurrentVersion: genesisForkVersion,
Epoch: genesisEpochNumber,
Epoch: genesisEpoch,
}) {
t.Error("Fork was not correctly initialized")
}
@@ -51,28 +52,28 @@ func TestGenesisBeaconState_OK(t *testing.T) {
assert.Equal(t, depositsForChainStart, len(newState.Validators()), "Validators was not correctly initialized")
v, err := newState.ValidatorAtIndex(0)
require.NoError(t, err)
assert.Equal(t, uint64(0), v.ActivationEpoch, "Validators was not correctly initialized")
assert.Equal(t, types.Epoch(0), v.ActivationEpoch, "Validators was not correctly initialized")
v, err = newState.ValidatorAtIndex(0)
require.NoError(t, err)
assert.Equal(t, uint64(0), v.ActivationEligibilityEpoch, "Validators was not correctly initialized")
assert.Equal(t, types.Epoch(0), v.ActivationEligibilityEpoch, "Validators was not correctly initialized")
assert.Equal(t, depositsForChainStart, len(newState.Balances()), "Balances was not correctly initialized")
// Randomness and committees fields checks.
assert.Equal(t, latestRandaoMixesLength, uint64(len(newState.RandaoMixes())), "Length of RandaoMixes was not correctly initialized")
assert.Equal(t, latestRandaoMixesLength, types.Epoch(len(newState.RandaoMixes())), "Length of RandaoMixes was not correctly initialized")
mix, err := newState.RandaoMixAtIndex(0)
require.NoError(t, err)
assert.DeepEqual(t, eth1Data.BlockHash, mix, "RandaoMixes was not correctly initialized")
// Finality fields checks.
assert.Equal(t, genesisEpochNumber, newState.PreviousJustifiedCheckpoint().Epoch, "PreviousJustifiedCheckpoint.Epoch was not correctly initialized")
assert.Equal(t, genesisEpochNumber, newState.CurrentJustifiedCheckpoint().Epoch, "JustifiedEpoch was not correctly initialized")
assert.Equal(t, genesisEpochNumber, newState.FinalizedCheckpointEpoch(), "FinalizedSlot was not correctly initialized")
assert.Equal(t, genesisEpoch, newState.PreviousJustifiedCheckpoint().Epoch, "PreviousJustifiedCheckpoint.Epoch was not correctly initialized")
assert.Equal(t, genesisEpoch, newState.CurrentJustifiedCheckpoint().Epoch, "JustifiedEpoch was not correctly initialized")
assert.Equal(t, genesisEpoch, newState.FinalizedCheckpointEpoch(), "FinalizedSlot was not correctly initialized")
assert.Equal(t, uint8(0x00), newState.JustificationBits()[0], "JustificationBits was not correctly initialized")
// Recent state checks.
assert.DeepEqual(t, make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector), newState.Slashings(), "Slashings was not correctly initialized")
assert.DeepEqual(t, []*pb.PendingAttestation{}, newState.CurrentEpochAttestations(), "CurrentEpochAttestations was not correctly initialized")
assert.DeepEqual(t, []*pb.PendingAttestation{}, newState.PreviousEpochAttestations(), "PreviousEpochAttestations was not correctly initialized")
assert.DeepSSZEqual(t, []*pb.PendingAttestation{}, newState.CurrentEpochAttestations(), "CurrentEpochAttestations was not correctly initialized")
assert.DeepSSZEqual(t, []*pb.PendingAttestation{}, newState.PreviousEpochAttestations(), "PreviousEpochAttestations was not correctly initialized")
zeroHash := params.BeaconConfig().ZeroHash[:]
// History root checks.
@@ -81,7 +82,7 @@ func TestGenesisBeaconState_OK(t *testing.T) {
// Deposit root checks.
assert.DeepEqual(t, eth1Data.DepositRoot, newState.Eth1Data().DepositRoot, "Eth1Data DepositRoot was not correctly initialized")
assert.DeepEqual(t, []*ethpb.Eth1Data{}, newState.Eth1DataVotes(), "Eth1DataVotes was not correctly initialized")
assert.DeepSSZEqual(t, []*ethpb.Eth1Data{}, newState.Eth1DataVotes(), "Eth1DataVotes was not correctly initialized")
}
func TestGenesisState_HashEquality(t *testing.T) {
@@ -104,7 +105,7 @@ func TestGenesisState_HashEquality(t *testing.T) {
func TestGenesisState_InitializesLatestBlockHashes(t *testing.T) {
s, err := state.GenesisBeaconState(nil, 0, &ethpb.Eth1Data{})
require.NoError(t, err)
got, want := uint64(len(s.BlockRoots())), params.BeaconConfig().SlotsPerHistoricalRoot
got, want := uint64(len(s.BlockRoots())), uint64(params.BeaconConfig().SlotsPerHistoricalRoot)
assert.Equal(t, want, got, "Wrong number of recent block hashes")
got = uint64(cap(s.BlockRoots()))

View File

@@ -0,0 +1,64 @@
package state
import (
"bytes"
"context"
"sync"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
)
type nextSlotCache struct {
sync.RWMutex
root []byte
state *state.BeaconState
}
var (
nsc nextSlotCache
// Metrics for the validator cache.
nextSlotCacheHit = promauto.NewCounter(prometheus.CounterOpts{
Name: "next_slot_cache_hit",
Help: "The total number of cache hits on the next slot state cache.",
})
nextSlotCacheMiss = promauto.NewCounter(prometheus.CounterOpts{
Name: "next_slot_cache_miss",
Help: "The total number of cache misses on the next slot state cache.",
})
)
// NextSlotState returns the saved state if the input root matches the root in `nextSlotCache`. Returns nil otherwise.
// This is useful to check before processing slots. With a cache hit, it will return last processed state with slot plus
// one advancement.
func NextSlotState(ctx context.Context, root []byte) (*state.BeaconState, error) {
nsc.RLock()
defer nsc.RUnlock()
if !bytes.Equal(root, nsc.root) {
nextSlotCacheMiss.Inc()
return nil, nil
}
nextSlotCacheHit.Inc()
// Returning copied state.
return nsc.state.Copy(), nil
}
// UpdateNextSlotCache updates the `nextSlotCache`. It saves the input state after advancing the state slot by 1
// by calling `ProcessSlots`, it also saves the input root for later look up.
// This is useful to call after successfully processing a block.
func UpdateNextSlotCache(ctx context.Context, root []byte, state *state.BeaconState) error {
// Advancing one slot by using a copied state.
copied := state.Copy()
copied, err := ProcessSlots(ctx, copied, copied.Slot()+1)
if err != nil {
return err
}
nsc.Lock()
defer nsc.Unlock()
nsc.root = root
nsc.state = copied
return nil
}

View File

@@ -0,0 +1,31 @@
package state_test
import (
"context"
"testing"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
st "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
)
func TestTrailingSlotState_RoundTrip(t *testing.T) {
ctx := context.Background()
r := []byte{'a'}
s, err := state.NextSlotState(ctx, r)
require.NoError(t, err)
require.Equal(t, (*st.BeaconState)(nil), s)
s, _ = testutil.DeterministicGenesisState(t, 1)
require.NoError(t, state.UpdateNextSlotCache(ctx, r, s))
s, err = state.NextSlotState(ctx, r)
require.NoError(t, err)
require.Equal(t, types.Slot(1), s.Slot())
require.NoError(t, state.UpdateNextSlotCache(ctx, r, s))
s, err = state.NextSlotState(ctx, r)
require.NoError(t, err)
require.Equal(t, types.Slot(2), s.Slot())
}

View File

@@ -9,6 +9,7 @@ import (
"fmt"
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
b "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
@@ -18,6 +19,7 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/core/state/interop"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/featureconfig"
"github.com/prysmaticlabs/prysm/shared/mathutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/traceutil"
@@ -70,7 +72,7 @@ func ExecuteStateTransition(
return nil, errors.New("nil block")
}
ctx, span := trace.StartSpan(ctx, "beacon-chain.ChainService.ExecuteStateTransition")
ctx, span := trace.StartSpan(ctx, "core.state.ExecuteStateTransition")
defer span.End()
var err error
// Execute per slots transition.
@@ -126,14 +128,20 @@ func ExecuteStateTransitionNoVerifyAnySig(
return nil, nil, errors.New("nil block")
}
ctx, span := trace.StartSpan(ctx, "beacon-chain.ChainService.ExecuteStateTransitionNoVerifyAttSigs")
ctx, span := trace.StartSpan(ctx, "core.state.ExecuteStateTransitionNoVerifyAttSigs")
defer span.End()
var err error
// Execute per slots transition.
state, err = ProcessSlots(ctx, state, signed.Block.Slot)
if err != nil {
return nil, nil, errors.Wrap(err, "could not process slot")
if featureconfig.Get().EnableNextSlotStateCache {
state, err = ProcessSlotsUsingNextSlotCache(ctx, state, signed.Block.ParentRoot, signed.Block.Slot)
if err != nil {
return nil, nil, errors.Wrap(err, "could not process slots")
}
} else {
state, err = ProcessSlots(ctx, state, signed.Block.Slot)
if err != nil {
return nil, nil, errors.Wrap(err, "could not process slot")
}
}
// Execute per block transition.
@@ -166,7 +174,7 @@ func CalculateStateRoot(
state *stateTrie.BeaconState,
signed *ethpb.SignedBeaconBlock,
) ([32]byte, error) {
ctx, span := trace.StartSpan(ctx, "beacon-chain.ChainService.CalculateStateRoot")
ctx, span := trace.StartSpan(ctx, "core.state.CalculateStateRoot")
defer span.End()
if ctx.Err() != nil {
traceutil.AnnotateError(span, ctx.Err())
@@ -183,9 +191,17 @@ func CalculateStateRoot(
state = state.Copy()
// Execute per slots transition.
state, err := ProcessSlots(ctx, state, signed.Block.Slot)
if err != nil {
return [32]byte{}, errors.Wrap(err, "could not process slot")
var err error
if featureconfig.Get().EnableNextSlotStateCache {
state, err = ProcessSlotsUsingNextSlotCache(ctx, state, signed.Block.ParentRoot, signed.Block.Slot)
if err != nil {
return [32]byte{}, errors.Wrap(err, "could not process slots")
}
} else {
state, err = ProcessSlots(ctx, state, signed.Block.Slot)
if err != nil {
return [32]byte{}, errors.Wrap(err, "could not process slot")
}
}
// Execute per block transition.
@@ -214,7 +230,7 @@ func CalculateStateRoot(
// previous_block_root = hash_tree_root(state.latest_block_header)
// state.block_roots[state.slot % SLOTS_PER_HISTORICAL_ROOT] = previous_block_root
func ProcessSlot(ctx context.Context, state *stateTrie.BeaconState) (*stateTrie.BeaconState, error) {
ctx, span := trace.StartSpan(ctx, "beacon-chain.ChainService.state.ProcessSlot")
ctx, span := trace.StartSpan(ctx, "core.state.ProcessSlot")
defer span.End()
span.AddAttributes(trace.Int64Attribute("slot", int64(state.Slot())))
@@ -223,7 +239,7 @@ func ProcessSlot(ctx context.Context, state *stateTrie.BeaconState) (*stateTrie.
return nil, err
}
if err := state.UpdateStateRootAtIndex(
state.Slot()%params.BeaconConfig().SlotsPerHistoricalRoot,
uint64(state.Slot()%params.BeaconConfig().SlotsPerHistoricalRoot),
prevStateRoot,
); err != nil {
return nil, err
@@ -245,7 +261,7 @@ func ProcessSlot(ctx context.Context, state *stateTrie.BeaconState) (*stateTrie.
}
// Cache the block root.
if err := state.UpdateBlockRootAtIndex(
state.Slot()%params.BeaconConfig().SlotsPerHistoricalRoot,
uint64(state.Slot()%params.BeaconConfig().SlotsPerHistoricalRoot),
prevBlockRoot,
); err != nil {
return nil, err
@@ -253,6 +269,37 @@ func ProcessSlot(ctx context.Context, state *stateTrie.BeaconState) (*stateTrie.
return state, nil
}
// ProcessSlotsUsingNextSlotCache processes slots by using next slot cache for higher efficiency.
func ProcessSlotsUsingNextSlotCache(
ctx context.Context,
parentState *stateTrie.BeaconState,
parentRoot []byte,
slot types.Slot) (*stateTrie.BeaconState, error) {
ctx, span := trace.StartSpan(ctx, "core.state.ProcessSlotsUsingNextSlotCache")
defer span.End()
// Check whether the parent state has been advanced by 1 slot in next slot cache.
nextSlotState, err := NextSlotState(ctx, parentRoot)
if err != nil {
return nil, err
}
// If the next slot state is not nil (i.e. cache hit).
// We replace next slot state with parent state.
if nextSlotState != nil {
parentState = nextSlotState
}
// Since next slot cache only advances state by 1 slot,
// we check if there's more slots that need to process.
if slot > parentState.Slot() {
parentState, err = ProcessSlots(ctx, parentState, slot)
if err != nil {
return nil, errors.Wrap(err, "could not process slots")
}
}
return parentState, nil
}
// ProcessSlots process through skip slots and apply epoch transition when it's needed
//
// Spec pseudocode definition:
@@ -265,8 +312,8 @@ func ProcessSlot(ctx context.Context, state *stateTrie.BeaconState) (*stateTrie.
// process_epoch(state)
// state.slot += 1
// ]
func ProcessSlots(ctx context.Context, state *stateTrie.BeaconState, slot uint64) (*stateTrie.BeaconState, error) {
ctx, span := trace.StartSpan(ctx, "beacon-chain.ChainService.ProcessSlots")
func ProcessSlots(ctx context.Context, state *stateTrie.BeaconState, slot types.Slot) (*stateTrie.BeaconState, error) {
ctx, span := trace.StartSpan(ctx, "core.state.ProcessSlots")
defer span.End()
if state == nil {
return nil, errors.New("nil state")
@@ -370,7 +417,7 @@ func ProcessBlock(
state *stateTrie.BeaconState,
signed *ethpb.SignedBeaconBlock,
) (*stateTrie.BeaconState, error) {
ctx, span := trace.StartSpan(ctx, "beacon-chain.ChainService.state.ProcessBlock")
ctx, span := trace.StartSpan(ctx, "core.state.ProcessBlock")
defer span.End()
var err error
@@ -401,7 +448,7 @@ func ProcessBlockNoVerifyAnySig(
state *stateTrie.BeaconState,
signed *ethpb.SignedBeaconBlock,
) (*bls.SignatureSet, *stateTrie.BeaconState, error) {
ctx, span := trace.StartSpan(ctx, "beacon-chain.ChainService.state.ProcessBlockNoVerifyAnySig")
ctx, span := trace.StartSpan(ctx, "core.state.ProcessBlockNoVerifyAnySig")
defer span.End()
state, err := b.ProcessBlockHeaderNoVerify(state, signed.Block)
@@ -477,7 +524,7 @@ func ProcessOperationsNoVerifyAttsSigs(
ctx context.Context,
state *stateTrie.BeaconState,
signedBeaconBlock *ethpb.SignedBeaconBlock) (*stateTrie.BeaconState, error) {
ctx, span := trace.StartSpan(ctx, "beacon-chain.ChainService.state.ProcessOperationsNoVerifyAttsSigs")
ctx, span := trace.StartSpan(ctx, "core.state.ProcessOperationsNoVerifyAttsSigs")
defer span.End()
if _, err := VerifyOperationLengths(ctx, state, signedBeaconBlock); err != nil {
@@ -510,8 +557,8 @@ func ProcessOperationsNoVerifyAttsSigs(
// VerifyOperationLengths verifies that block operation lengths are valid.
func VerifyOperationLengths(_ context.Context, state *stateTrie.BeaconState, b *ethpb.SignedBeaconBlock) (*stateTrie.BeaconState, error) {
if b.Block == nil || b.Block.Body == nil {
return nil, errors.New("block and block body can't be nil")
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
return nil, err
}
body := b.Block.Body
@@ -575,7 +622,7 @@ func CanProcessEpoch(state *stateTrie.BeaconState) bool {
// ProcessEpochPrecompute describes the per epoch operations that are performed on the beacon state.
// It's optimized by pre computing validator attested info and epoch total/attested balances upfront.
func ProcessEpochPrecompute(ctx context.Context, state *stateTrie.BeaconState) (*stateTrie.BeaconState, error) {
ctx, span := trace.StartSpan(ctx, "beacon-chain.ChainService.state.ProcessEpochPrecompute")
ctx, span := trace.StartSpan(ctx, "core.state.ProcessEpochPrecompute")
defer span.End()
span.AddAttributes(trace.Int64Attribute("epoch", int64(helpers.CurrentEpoch(state))))
@@ -625,7 +672,7 @@ func ProcessBlockForStateRoot(
state *stateTrie.BeaconState,
signed *ethpb.SignedBeaconBlock,
) (*stateTrie.BeaconState, error) {
ctx, span := trace.StartSpan(ctx, "beacon-chain.ChainService.state.ProcessBlockForStateRoot")
ctx, span := trace.StartSpan(ctx, "core.state.ProcessBlockForStateRoot")
defer span.End()
state, err := b.ProcessBlockHeaderNoVerify(state, signed.Block)

View File

@@ -5,6 +5,7 @@ import (
"testing"
fuzz "github.com/google/gofuzz"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
)
@@ -66,7 +67,7 @@ func TestFuzzProcessSlots_1000(t *testing.T) {
defer SkipSlotCache.Enable()
ctx := context.Background()
state := &stateTrie.BeaconState{}
slot := uint64(0)
slot := types.Slot(0)
fuzzer := fuzz.NewWithSeed(0)
fuzzer.NilChance(0.1)
for i := 0; i < 1000; i++ {

View File

@@ -1,12 +1,12 @@
package state_test
import (
"bytes"
"context"
"encoding/binary"
"fmt"
"testing"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/go-bitfield"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
@@ -101,9 +101,7 @@ func TestExecuteStateTransition_FullProcess(t *testing.T) {
mix, err := beaconState.RandaoMixAtIndex(1)
require.NoError(t, err)
if bytes.Equal(mix, oldMix) {
t.Errorf("Did not expect new and old randao mix to equal, %#x == %#x", mix, oldMix)
}
assert.DeepNotEqual(t, oldMix, mix, "Did not expect new and old randao mix to equal")
}
func TestExecuteStateTransitionNoVerify_FullProcess(t *testing.T) {
@@ -254,7 +252,7 @@ func TestProcessBlock_IncorrectProcessExits(t *testing.T) {
},
}
var blockRoots [][]byte
for i := uint64(0); i < params.BeaconConfig().SlotsPerHistoricalRoot; i++ {
for i := uint64(0); i < uint64(params.BeaconConfig().SlotsPerHistoricalRoot); i++ {
blockRoots = append(blockRoots, []byte{byte(i)})
}
require.NoError(t, beaconState.SetBlockRoots(blockRoots))
@@ -324,7 +322,7 @@ func createFullBlockWithOperations(t *testing.T) (*beaconstate.BeaconState,
proposerSlashIdx := uint64(3)
slotsPerEpoch := params.BeaconConfig().SlotsPerEpoch
err = beaconState.SetSlot((params.BeaconConfig().ShardCommitteePeriod * slotsPerEpoch) + params.BeaconConfig().MinAttestationInclusionDelay)
err = beaconState.SetSlot(slotsPerEpoch.Mul(uint64(params.BeaconConfig().ShardCommitteePeriod)) + params.BeaconConfig().MinAttestationInclusionDelay)
require.NoError(t, err)
currentEpoch := helpers.CurrentEpoch(beaconState)
@@ -398,7 +396,7 @@ func createFullBlockWithOperations(t *testing.T) (*beaconstate.BeaconState,
}
var blockRoots [][]byte
for i := uint64(0); i < params.BeaconConfig().SlotsPerHistoricalRoot; i++ {
for i := uint64(0); i < uint64(params.BeaconConfig().SlotsPerHistoricalRoot); i++ {
blockRoots = append(blockRoots, []byte{byte(i)})
}
require.NoError(t, beaconState.SetBlockRoots(blockRoots))
@@ -415,7 +413,8 @@ func createFullBlockWithOperations(t *testing.T) (*beaconstate.BeaconState,
committee, err := helpers.BeaconCommitteeFromState(beaconState, blockAtt.Data.Slot, blockAtt.Data.CommitteeIndex)
assert.NoError(t, err)
attestingIndices := attestationutil.AttestingIndices(blockAtt.AggregationBits, committee)
attestingIndices, err := attestationutil.AttestingIndices(blockAtt.AggregationBits, committee)
require.NoError(t, err)
assert.NoError(t, err)
hashTreeRoot, err = helpers.ComputeSigningRoot(blockAtt.Data, domain)
assert.NoError(t, err)
@@ -503,12 +502,12 @@ func TestProcessBlockNoVerify_PassesProcessingConditions(t *testing.T) {
}
func TestProcessEpochPrecompute_CanProcess(t *testing.T) {
epoch := uint64(1)
epoch := types.Epoch(1)
atts := []*pb.PendingAttestation{{Data: &ethpb.AttestationData{Target: &ethpb.Checkpoint{Root: make([]byte, 32)}}, InclusionDelay: 1}}
slashing := make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector)
base := &pb.BeaconState{
Slot: epoch*params.BeaconConfig().SlotsPerEpoch + 1,
Slot: params.BeaconConfig().SlotsPerEpoch.Mul(uint64(epoch)) + 1,
BlockRoots: make([][]byte, 128),
Slashings: slashing,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
@@ -697,7 +696,7 @@ func TestProcessBlk_AttsBasedOnValidatorCount(t *testing.T) {
s, privKeys := testutil.DeterministicGenesisState(t, validatorCount)
require.NoError(t, s.SetSlot(params.BeaconConfig().SlotsPerEpoch))
bitCount := validatorCount / params.BeaconConfig().SlotsPerEpoch
bitCount := validatorCount / uint64(params.BeaconConfig().SlotsPerEpoch)
aggBits := bitfield.NewBitlist(bitCount)
for i := uint64(1); i < bitCount; i++ {
aggBits.SetBitAt(i, true)
@@ -712,7 +711,8 @@ func TestProcessBlk_AttsBasedOnValidatorCount(t *testing.T) {
committee, err := helpers.BeaconCommitteeFromState(s, att.Data.Slot, att.Data.CommitteeIndex)
assert.NoError(t, err)
attestingIndices := attestationutil.AttestingIndices(att.AggregationBits, committee)
attestingIndices, err := attestationutil.AttestingIndices(att.AggregationBits, committee)
require.NoError(t, err)
domain, err := helpers.Domain(s.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, s.GenesisValidatorRoot())
require.NoError(t, err)
sigs := make([]bls.Signature, len(attestingIndices))
@@ -765,7 +765,7 @@ func TestProcessBlk_AttsBasedOnValidatorCount(t *testing.T) {
func TestCanProcessEpoch_TrueOnEpochs(t *testing.T) {
tests := []struct {
slot uint64
slot types.Slot
canProcessEpoch bool
}{
{
@@ -875,7 +875,7 @@ func TestProcessBlock_IncorrectDeposits(t *testing.T) {
}
func TestProcessSlots_SameSlotAsParentState(t *testing.T) {
slot := uint64(2)
slot := types.Slot(2)
parentState, err := beaconstate.InitializeFromProto(&pb.BeaconState{Slot: slot})
require.NoError(t, err)
@@ -884,10 +884,19 @@ func TestProcessSlots_SameSlotAsParentState(t *testing.T) {
}
func TestProcessSlots_LowerSlotAsParentState(t *testing.T) {
slot := uint64(2)
slot := types.Slot(2)
parentState, err := beaconstate.InitializeFromProto(&pb.BeaconState{Slot: slot})
require.NoError(t, err)
_, err = state.ProcessSlots(context.Background(), parentState, slot-1)
assert.ErrorContains(t, "expected state.slot 2 < slot 1", err)
}
func TestProcessSlotsUsingNextSlotCache(t *testing.T) {
ctx := context.Background()
s, _ := testutil.DeterministicGenesisState(t, 1)
r := []byte{'a'}
s, err := state.ProcessSlotsUsingNextSlotCache(ctx, s, r, 5)
require.NoError(t, err)
require.Equal(t, types.Slot(5), s.Slot())
}

View File

@@ -9,9 +9,9 @@ go_library(
deps = [
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/state:go_default_library",
"//shared/mathutil:go_default_library",
"//shared/params:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
],
)
@@ -28,6 +28,7 @@ go_test(
"//shared/params:go_default_library",
"//shared/testutil/assert:go_default_library",
"//shared/testutil/require:go_default_library",
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
],
)

View File

@@ -6,10 +6,10 @@ package validators
import (
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/shared/mathutil"
"github.com/prysmaticlabs/prysm/shared/params"
)
@@ -44,7 +44,7 @@ func InitiateValidatorExit(state *stateTrie.BeaconState, idx uint64) (*stateTrie
if validator.ExitEpoch != params.BeaconConfig().FarFutureEpoch {
return state, nil
}
var exitEpochs []uint64
var exitEpochs []types.Epoch
err = state.ReadFromEveryValidator(func(idx int, val stateTrie.ReadOnlyValidator) error {
if val.ExitEpoch() != params.BeaconConfig().FarFutureEpoch {
exitEpochs = append(exitEpochs, val.ExitEpoch())
@@ -57,7 +57,7 @@ func InitiateValidatorExit(state *stateTrie.BeaconState, idx uint64) (*stateTrie
exitEpochs = append(exitEpochs, helpers.ActivationExitEpoch(helpers.CurrentEpoch(state)))
// Obtain the exit queue epoch as the maximum number in the exit epochs array.
exitQueueEpoch := uint64(0)
exitQueueEpoch := types.Epoch(0)
for _, i := range exitEpochs {
if exitQueueEpoch < i {
exitQueueEpoch = i
@@ -132,7 +132,7 @@ func SlashValidator(state *stateTrie.BeaconState, slashedIdx uint64) (*stateTrie
return nil, err
}
validator.Slashed = true
maxWithdrawableEpoch := mathutil.Max(validator.WithdrawableEpoch, currentEpoch+params.BeaconConfig().EpochsPerSlashingsVector)
maxWithdrawableEpoch := types.MaxEpoch(validator.WithdrawableEpoch, currentEpoch+params.BeaconConfig().EpochsPerSlashingsVector)
validator.WithdrawableEpoch = maxWithdrawableEpoch
if err := state.UpdateValidatorAtIndex(slashedIdx, validator); err != nil {
@@ -143,7 +143,7 @@ func SlashValidator(state *stateTrie.BeaconState, slashedIdx uint64) (*stateTrie
slashings := state.Slashings()
currentSlashing := slashings[currentEpoch%params.BeaconConfig().EpochsPerSlashingsVector]
if err := state.UpdateSlashingsAtIndex(
currentEpoch%params.BeaconConfig().EpochsPerSlashingsVector,
uint64(currentEpoch%params.BeaconConfig().EpochsPerSlashingsVector),
currentSlashing+validator.EffectiveBalance,
); err != nil {
return nil, err
@@ -172,7 +172,7 @@ func SlashValidator(state *stateTrie.BeaconState, slashedIdx uint64) (*stateTrie
}
// ActivatedValidatorIndices determines the indices activated during the given epoch.
func ActivatedValidatorIndices(epoch uint64, validators []*ethpb.Validator) []uint64 {
func ActivatedValidatorIndices(epoch types.Epoch, validators []*ethpb.Validator) []uint64 {
activations := make([]uint64, 0)
for i := 0; i < len(validators); i++ {
val := validators[i]
@@ -184,11 +184,11 @@ func ActivatedValidatorIndices(epoch uint64, validators []*ethpb.Validator) []ui
}
// SlashedValidatorIndices determines the indices slashed during the given epoch.
func SlashedValidatorIndices(epoch uint64, validators []*ethpb.Validator) []uint64 {
func SlashedValidatorIndices(epoch types.Epoch, validators []*ethpb.Validator) []uint64 {
slashed := make([]uint64, 0)
for i := 0; i < len(validators); i++ {
val := validators[i]
maxWithdrawableEpoch := mathutil.Max(val.WithdrawableEpoch, epoch+params.BeaconConfig().EpochsPerSlashingsVector)
maxWithdrawableEpoch := types.MaxEpoch(val.WithdrawableEpoch, epoch+params.BeaconConfig().EpochsPerSlashingsVector)
if val.WithdrawableEpoch == maxWithdrawableEpoch && val.Slashed {
slashed = append(slashed, uint64(i))
}
@@ -197,16 +197,16 @@ func SlashedValidatorIndices(epoch uint64, validators []*ethpb.Validator) []uint
}
// ExitedValidatorIndices determines the indices exited during the current epoch.
func ExitedValidatorIndices(epoch uint64, validators []*ethpb.Validator, activeValidatorCount uint64) ([]uint64, error) {
func ExitedValidatorIndices(epoch types.Epoch, validators []*ethpb.Validator, activeValidatorCount uint64) ([]uint64, error) {
exited := make([]uint64, 0)
exitEpochs := make([]uint64, 0)
exitEpochs := make([]types.Epoch, 0)
for i := 0; i < len(validators); i++ {
val := validators[i]
if val.ExitEpoch != params.BeaconConfig().FarFutureEpoch {
exitEpochs = append(exitEpochs, val.ExitEpoch)
}
}
exitQueueEpoch := uint64(0)
exitQueueEpoch := types.Epoch(0)
for _, i := range exitEpochs {
if exitQueueEpoch < i {
exitQueueEpoch = i
@@ -238,16 +238,16 @@ func ExitedValidatorIndices(epoch uint64, validators []*ethpb.Validator, activeV
}
// EjectedValidatorIndices determines the indices ejected during the given epoch.
func EjectedValidatorIndices(epoch uint64, validators []*ethpb.Validator, activeValidatorCount uint64) ([]uint64, error) {
func EjectedValidatorIndices(epoch types.Epoch, validators []*ethpb.Validator, activeValidatorCount uint64) ([]uint64, error) {
ejected := make([]uint64, 0)
exitEpochs := make([]uint64, 0)
exitEpochs := make([]types.Epoch, 0)
for i := 0; i < len(validators); i++ {
val := validators[i]
if val.ExitEpoch != params.BeaconConfig().FarFutureEpoch {
exitEpochs = append(exitEpochs, val.ExitEpoch)
}
}
exitQueueEpoch := uint64(0)
exitQueueEpoch := types.Epoch(0)
for _, i := range exitEpochs {
if exitQueueEpoch < i {
exitQueueEpoch = i

View File

@@ -3,6 +3,7 @@ package validators
import (
"testing"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
@@ -39,7 +40,7 @@ func TestHasVoted_OK(t *testing.T) {
}
func TestInitiateValidatorExit_AlreadyExited(t *testing.T) {
exitEpoch := uint64(199)
exitEpoch := types.Epoch(199)
base := &pb.BeaconState{Validators: []*ethpb.Validator{{
ExitEpoch: exitEpoch},
}}
@@ -53,7 +54,7 @@ func TestInitiateValidatorExit_AlreadyExited(t *testing.T) {
}
func TestInitiateValidatorExit_ProperExit(t *testing.T) {
exitedEpoch := uint64(100)
exitedEpoch := types.Epoch(100)
idx := uint64(3)
base := &pb.BeaconState{Validators: []*ethpb.Validator{
{ExitEpoch: exitedEpoch},
@@ -71,7 +72,7 @@ func TestInitiateValidatorExit_ProperExit(t *testing.T) {
}
func TestInitiateValidatorExit_ChurnOverflow(t *testing.T) {
exitedEpoch := uint64(100)
exitedEpoch := types.Epoch(100)
idx := uint64(4)
base := &pb.BeaconState{Validators: []*ethpb.Validator{
{ExitEpoch: exitedEpoch + 2},
@@ -133,7 +134,7 @@ func TestSlashValidator_OK(t *testing.T) {
assert.Equal(t, helpers.CurrentEpoch(state)+params.BeaconConfig().EpochsPerSlashingsVector, v.WithdrawableEpoch, "Withdrawable epoch not the expected value")
maxBalance := params.BeaconConfig().MaxEffectiveBalance
slashedBalance := state.Slashings()[state.Slot()%params.BeaconConfig().EpochsPerSlashingsVector]
slashedBalance := state.Slashings()[state.Slot().Mod(uint64(params.BeaconConfig().EpochsPerSlashingsVector))]
assert.Equal(t, maxBalance, slashedBalance, "Slashed balance isnt the expected amount")
whistleblowerReward := slashedBalance / params.BeaconConfig().WhistleBlowerRewardQuotient

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