Compare commits

...

461 Commits

Author SHA1 Message Date
terence tsao
4db77ce691 Merge branch 'hf1' of github.com:prysmaticlabs/prysm into hf1 2021-08-16 12:55:37 -07:00
terence tsao
1919484cae Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-08-16 12:55:23 -07:00
terence tsao
b28d65dc34 Add pyrmont hard fork config (#9394)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-08-16 19:51:43 +00:00
prestonvanloon
89637634f6 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-08-16 14:17:44 -05:00
Preston Van Loon
643e20c50a p2p: report status failure when no genesis time is set after start (#9395) 2021-08-16 19:15:43 +00:00
terence tsao
b870b126f1 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-08-16 10:22:32 -07:00
Radosław Kapka
bb68c591f2 Remove beacon-chain/rpc/eth/v1 directory (#9392) 2021-08-16 13:11:25 +02:00
nisdas
873335c93f Merge branch 'develop' of https://github.com/prysmaticlabs/geth-sharding into hf1 2021-08-16 17:01:42 +08:00
Nishant Das
f8355bb241 Add in Database Support For Altair State (#9388)
* add in schema

* add in altair state support

* nil check

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-08-16 12:39:52 +08:00
Raul Jordan
8122da6c97 Add Gosec Github Action (#9332)
* add gosec security scan

* add gosec ignores first batch

* more nosec for exec

* add filepath clean

* more nosec

* file inclusion nosec

* build

* herumi

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-08-15 15:24:13 +00:00
nisdas
8e9976be54 remove cache 2021-08-15 18:51:06 +08:00
Radosław Kapka
1936f991eb Prepare protos for Ethereum API v2.0.0 (#9384)
* Move proto services to a different package

# Conflicts:
#	beacon-chain/rpc/service.go

* fix tests

* goimports

* fix java class name

* without aggregation_bits

* aggregation_bits

* v2 endpoints

* generate new code and define function stubs

* build files

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-08-14 16:41:03 +00:00
Nishant Das
49440c90ba Add in Database Support For Altair Blocks (#9387)
* add in schema

* gaz

* fix panic in rpc

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-08-14 15:50:49 +00:00
Nishant Das
47ee6fa17e Add in Altair Message ID Function (#9382)
* add in changes

* add method call

* gaz

* rauls review

* rauls review

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-08-14 14:36:02 +00:00
Radosław Kapka
de907fc362 Fix java classname in beacon_debug_service.proto (#9380)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-08-13 17:59:55 +00:00
Nishant Das
a1c0bee397 Add in Object Mapping For Types (#9381)
Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-08-13 17:28:26 +00:00
Raul Jordan
b42465a7dd Optimized Slasher Parameters (#9361)
* add in parameters and helpers files

* add in small set of changes

* build file

* viz
2021-08-13 16:53:04 +00:00
Nishant Das
8fe22422a6 add it in (#9383) 2021-08-13 10:53:51 -05:00
nisdas
aa2f058a8e Merge branch 'develop' of https://github.com/prysmaticlabs/geth-sharding into hf1 2021-08-13 19:17:52 +08:00
Radosław Kapka
f516e71167 Move proto services to a different package (#9379)
* Move proto services to a different package

# Conflicts:
#	beacon-chain/rpc/service.go

* fix tests

* goimports

* fix java class name
2021-08-13 10:55:24 +00:00
Radosław Kapka
61702e101b Move proto services to a separate package (#9378) 2021-08-13 12:46:59 +02:00
nisdas
bcaefd34e7 Merge branch 'develop' of https://github.com/prysmaticlabs/geth-sharding into hf1 2021-08-13 18:12:21 +08:00
Radosław Kapka
ede85c21e2 Clean up v1 protos (#9377)
* Clean up v1 protos

# Conflicts:
#	proto/eth/v1/generated.ssz.go

* A little more cleanup

# Conflicts:
#	proto/eth/v1/generated.ssz.go

* fix java class names
2021-08-13 09:12:18 +00:00
Radosław Kapka
df2cebb4e3 Clean up v1 protos (#9376)
* Clean up v1 protos

* A little more cleanup

* fix java class names
2021-08-13 16:54:54 +08:00
nisdas
8813ed35d4 Merge branch 'develop' of https://github.com/prysmaticlabs/geth-sharding into hf1 2021-08-13 13:18:40 +08:00
Nishant Das
a9f2170657 Update P2PUtils And Parameters From Altair (#9373)
* add changes

* add p2putils changes

* clean up

* fix build

* remove test

* raul's review
2021-08-13 13:11:11 +08:00
nisdas
e80ce8be95 Merge branch 'develop' of https://github.com/prysmaticlabs/geth-sharding into hf1 2021-08-13 09:29:34 +08:00
Nishant Das
3a528147a2 Change to Proto Check For Blocks (#9372)
* check inner objects

* add test in here.

* verify better
2021-08-13 00:35:23 +00:00
Nishant Das
c8cffbbf02 Update Dependencies For Prysm (#9374)
* update deps

* tidy
2021-08-12 11:07:13 -05:00
nisdas
75a4ad364d revert gateway change 2021-08-12 20:02:42 +08:00
nisdas
acdf29ef44 fix tests 2021-08-12 16:08:41 +08:00
nisdas
1691cea615 Merge branch 'develop' of https://github.com/prysmaticlabs/geth-sharding into hf1 2021-08-12 15:54:40 +08:00
Raul Jordan
1f102c256d Altair Committee Cache Changes (#9366)
* changes to hf1 caches

* suggested

* Update beacon-chain/cache/sync_subnet_ids.go

* add in proper changes

* committee.go

* committee test and disabled

* nil active balance check
2021-08-12 00:04:40 -05:00
terence tsao
e3492698f8 Core: modified process attestation for Altair (#9367)
* Add epoch participation and proposer base reward helpers

* Update beacon-chain/core/altair/attestation.go

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

* Check length

* Go fmt

* Add process att

* Refactor and tests

* Update attestation.go

* Gazelle

* Under flow error message

* Update beacon-chain/core/altair/attestation.go

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-08-11 21:58:25 -05:00
Jim McDonald
5256751e8b Trim SSE event names. (#9342)
* Trim SSE event names.

When sending SSE events the event name contains trailing whitespace.
This patch removes the whitespace before processing the event, ensuring
it is easily parsed by clients.

* Separate test.

* Test receiveEvents, not writeEvent.

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: Radosław Kapka <rkapka@wp.pl>
Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
2021-08-11 23:00:39 +00:00
terence tsao
225f9a74f6 Add epoch participation and proposer base reward helpers (#9356)
* Add epoch participation and proposer base reward helpers

* Update beacon-chain/core/altair/attestation.go

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

* Check length

* Go fmt

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-08-11 20:54:45 +00:00
terence tsao
d77616f705 Fixes Issues Found by Goland IDE Code Inspect (#9368)
* Ran code inspect

* Update shared/testutil/altair.go

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-08-11 20:12:22 +00:00
Raul Jordan
621aff1b86 use protos from develop 2021-08-11 13:21:44 -06:00
Raul Jordan
aad0dd80d1 sync with develop 2021-08-11 13:21:02 -06:00
Raul Jordan
a217d71d08 Sync Protobufs Between Hard Fork Branch and Develop (#9362)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-08-11 19:14:49 +00:00
Raul Jordan
efa1f29311 Use Different Golang JWT Library (#9360)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-08-11 18:10:53 +00:00
Raul Jordan
136b157d00 Better Slashing Protection Import/Export User Experience (#9355)
* failure mode if command goes wrong

* improve export

* fix struct orderw

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-08-11 17:24:24 +00:00
Raul Jordan
c1280867ed Add Tracing Request Sink to E2E (#9341)
* add tracing request sink

* fix struct order

* add in base64 encode and gzip

* add encoding and gzip

* tracing sink and replay tool

* post

* replay

* include latest sink and replay tool

* capture the gzout file instead

* rem time sleep

* handle err

* better handling

* add documentation

* changes

* working sync

* working

* added more logging
2021-08-11 15:38:00 +00:00
Nishant Das
0dd7a8b078 Fixes Altair Bug Introduced For State Representation (#9358)
* add test

* test

* test
2021-08-11 15:02:55 +00:00
Nishant Das
6dc70c53ec Fix Config Loader Changes (#9359)
* add changes

* fix
2021-08-11 08:59:59 -05:00
nisdas
17f3816976 Merge branch 'hf1' of https://github.com/prysmaticlabs/geth-sharding into hf1 2021-08-11 10:20:51 +08:00
nisdas
f05ac82c6f fix slashing params 2021-08-11 10:18:20 +08:00
terence tsao
41ab27402f Sync committee subnet cache (#9350)
* Add sync subnet id cache

* Update BUILD.bazel

* Update BUILD.bazel

* Update beacon-chain/cache/sync_subnet_ids.go

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

* Add comments

* add more comments

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
Co-authored-by: nisdas <nishdas93@gmail.com>
2021-08-11 00:26:20 +00:00
Raul Jordan
e78e554d27 sync develop 2021-08-10 14:40:34 -06:00
terence tsao
9668ab0fea Clean up duplicated imports (#9354) 2021-08-10 14:55:24 -05:00
terence tsao
6c435382dc Clean up trace names 2021-08-10 09:05:19 -07:00
nisdas
1aa1165428 fix test 2021-08-10 20:36:50 +08:00
nisdas
6c086080c5 fix stuff 2021-08-10 19:50:19 +08:00
nisdas
c9dd3faf7a gaz 2021-08-10 19:25:40 +08:00
nisdas
86259e76de Merge branch 'develop' of https://github.com/prysmaticlabs/geth-sharding into hf1 2021-08-10 19:24:45 +08:00
Radosław Kapka
7a9c717ae0 Reduce locking time in recomputeFieldTrie (#9353)
* Reduce locking time in `recomputeFieldTrie`

* add comment

* reuse variable and improve comment
2021-08-10 09:54:35 +00:00
Nishant Das
a5998fab2f Clean Up State Representation (#9339)
* checkpoint all work

* add new fixes

* fixes

* gaz

* terence's review

* terence's review

Co-authored-by: terence tsao <terence@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-08-09 21:54:24 +00:00
terence tsao
8df6854a74 Core: upgrade state to Altair (#9349)
* Add upgrade to altair

* Update BUILD.bazel

* Update beacon-chain/core/altair/upgrade.go

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

* Move getter and setter outside the loop

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-08-09 21:27:51 +00:00
Jim McDonald
3de168b806 Fix state state transition logging. (#9343)
Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-08-09 20:05:46 +00:00
Preston Van Loon
bfdaf8a3f5 Fix config loader tests (#9348)
* don't mutate mainnet config

* add missing minimal config params

* Ensure all yaml fields were set and are correct

* gofmt

* Add sanity check that some empty yaml wasn't given

* Gazelle and deepsource feedback
2021-08-09 18:40:06 +00:00
terence tsao
38787353a2 Attestation: get participation status (#9340)
* Add participation flag indics matching helpers

* Gazelle

* Tests

* Update BUILD.bazel

* Update attestation.go
2021-08-09 16:35:46 +00:00
Nishant Das
170e2e115b Fix Flaky Sync Committee Test (#9337)
* fix flake

* Update beacon-chain/core/altair/sync_committee_test.go

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-08-09 14:49:13 +00:00
terence tsao
be85b7f909 Cleanup: remove test only process block/attestation (#9345)
* Remove test only process block attestation code

* Rm fuzz process block

* Revert "Rm fuzz process block"

This reverts commit 5d1b0f0741.

* Still can test fuzz

* Fix return

* More unused funcs
2021-08-08 22:01:06 -05:00
terence tsao
ad048a8750 Rewards/penalties: epoch processing for Altair (#9334)
* Add epoch precompute methods

* Better name

* Bring expensive computation outside

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
2021-08-06 20:02:35 +00:00
Raul Jordan
90ea158301 Add Some More Traces to Blockchain Service (#9336)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-08-06 15:02:36 +00:00
Nishant Das
d26f52a7cc Fix Altair State Migration (#9329)
* fix altair state migration

* add altair tests
2021-08-06 20:18:37 +08:00
Radosław Kapka
ef9eff29b8 Tiny state management improvements (#9338)
* Tiny state management improvements

* fix indices length calculation

* review comments

* revert function rename
2021-08-06 10:47:50 +00:00
terence tsao
4cce4f1ee5 Refactor slash validator func's signature (#9321)
* Refactor slash validator func's signature

* Named arguments

* Update beacon-chain/core/blocks/proposer_slashing.go

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-08-06 04:06:49 +00:00
Raul Jordan
ce10be9a16 Add Latest Slasher KV Methods to DB Subpackage (#9328)
* tests pass

* use end slot for epoch pruning

* amended to endslot of epoch

Co-authored-by: terence tsao <terence@prysmaticlabs.com>
2021-08-05 21:27:05 +00:00
Raul Jordan
4f0b00894b More Precise Metrics E2E (#9331)
* metrics test copute slots since genesis

* gazelle

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-08-05 20:44:56 +00:00
Radosław Kapka
57fac9b74f Improve API Middleware design (#9324)
* remove superfluous WriteHeader call

* move custom handlers outside hooks

* rename OnPostStart hook

* function that returns a default endpoint

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-08-05 20:21:43 +00:00
Mohamed Zahoor
395feeb35d Cross check db state bucket after migration (#9311)
* added state db check after migration

* satisfy deepsource

* added db compare after migration sub-command

* fomt issue

* point ot bolt issue

* gazel fix

* maxUint84

* revert accidental deletion of WORKSPACE file

* added sorting support

* cleanup debug

* gazel fix

* satisfy deepsource

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-08-05 18:30:05 +00:00
terence tsao
7bc22e4ddf Cache: sync committee index position (#9317)
* Add sync committee index cache

* Update BUILD.bazel

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-08-05 17:44:13 +00:00
Nishant Das
f3a8397f75 fix historical state (#9326) 2021-08-05 07:43:58 -05:00
Radosław Kapka
016beb51c0 Make SubmitAttestations v1 implementation similar to v1alpha1 (#9319)
* Make `SubmitAttestations` v1 implementation similar to v1alpha1

* fix test

* fix test

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-08-05 08:01:20 +00:00
Radosław Kapka
456b4d463e Implement PrepareBeaconCommitteeSubnet in the validator API (#9318)
* validator migration

* status helpers

* implementation

* fix existing tests

* build file

* tests

* run endpoint through API Middleware

* reduce helper package visibility

* empty caches before each test

* assign all validators to subnets

Co-authored-by: Nishant Das <nishdas93@gmail.com>
2021-08-05 07:23:52 +00:00
terence tsao
4d33068496 Core helper: validate sync message time (#9325)
* Add validate sync message time

* Update BUILD.bazel
2021-08-05 12:39:32 +08:00
terence tsao
5212cc649a Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-08-04 09:22:15 -07:00
terence tsao
6e9faa3618 Epoch: precompute functions for Altair part 1 (#9309)
* Add epoch precompute methods

* Split into part 1 for better review

* Update epoch_precompute_test.go

* Preston's feedback

* Skip if the valiator is not eligible

* Add regression test for non eligible

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-08-04 15:13:05 +00:00
Nishant Das
043850d972 General Interop Fixes (#9322) 2021-08-04 08:10:00 -07:00
Nishant Das
fd42cb712f Fix Incorrect Conditional Check (#9323)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-08-04 13:50:27 +00:00
Radosław Kapka
c5b68b4f03 Implement PublishAggregateAndProofs in the validator API (#9294)
* grpc implementation

* build file

* full implementation

* remove unused function

* tests

* wrap top-level array

* Update beacon-chain/rpc/eth/v1/validator/validator.go

Co-authored-by: terence tsao <terence@prysmaticlabs.com>

* review

Co-authored-by: terence tsao <terence@prysmaticlabs.com>
Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-08-04 09:01:38 +00:00
Nishant Das
e2238bd6d1 Fix Spec Edge Case For Altair (#9295)
* fix edge case

* Update validator/client/sync_committee.go

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

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
2021-08-04 16:22:01 +08:00
Mohamed Zahoor
239d904d27 Fix memory usability (#9310)
* fix cache usability

* fix the name of the prometheus flag

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-08-04 02:33:28 +00:00
terence tsao
461be99fac Block: process sync aggregate (#9308)
* Add altair base reward funcs

* Update BUILD.bazel

* Add process sync aggregate

* Update BUILD.bazel

* Update block.go

* Update block_test.go

* Feedback, refactor and more tests

* Further refactor sync committee votes

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
2021-08-03 16:14:15 +00:00
Preston Van Loon
9572add171 Fail fast when using old define=ssz=<value> (#9316)
* Fail fast when using old define=ssz=<value>

* remove print statement
2021-08-02 19:04:30 +00:00
ahadda5
17cf2e5377 Fixing .bat file issues (#9266)
* replacing [] with "" for ifs
using !! vs %% for var with delayed expansion
Check first for 404 then download.

* remove the goto after if are fixed

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: Nishant Das <nishdas93@gmail.com>
2021-08-02 16:09:09 +00:00
Radosław Kapka
e4388c7fce Update grpc-gateway dependency to proper version (#9315)
* logging

* properly update grpc-gateway dependency

* Revert "logging"

This reverts commit 6c59a87ac0.

# Conflicts:
#	go.mod

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-08-02 14:52:54 +00:00
Mohamed Mansour
47c28e6cd6 Show error in logs if passing invalid flags in yaml (#9033)
* Show error in logs if passing invalid flags in yaml

The YAML configs pass if an invalid flag is set, this causes frustration
because the flag could have been mispelled causing a huge mystery.

This will strictly check if the flags are deserialized, if a flag
doesn't exist, it will error out as a Fatal error with appropriate
reasoning which flag is wrong.

* Fix review comments to make some of them non-fatal

* Make yaml.TypeError a pointer

* Remove UnmarshalStrict from spectests since they use a different YAML package

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
2021-08-01 03:26:24 +00:00
Preston Van Loon
0c1fc65604 Core/deposit: refactor blocks.ProcessDeposit for less complex altair implementation (#9305)
* Refactor blocks.ProcessDeposit to return whether or not the deposit resulted in a new validator entry.

* Only mark validator as new after successfully appending it to the state

* fix merge conflict

* fix merge conflict

* gofmt

* fix merge conflict

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-07-31 23:42:07 +00:00
terence tsao
5c36d59672 Reward: altair base reward (#9307)
* Add altair base reward funcs

* Update BUILD.bazel

* Better tests

* Update BUILD.bazel
2021-07-30 19:17:20 +00:00
Nishant Das
7576442ef0 Only Create Deposit Proofs Pre-Genesis (#9289)
* remove proof gen

* fix pre-genesis case

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-07-30 18:33:31 +00:00
terence tsao
d130bf0035 Fix more duplicated import prefix (#9306) 2021-07-30 18:05:38 +00:00
terence tsao
df291e2ffb Update BUILD.bazel 2021-07-30 10:49:26 -07:00
terence tsao
5ba5b303d3 Fix spec test 2021-07-30 10:49:16 -07:00
terence tsao
f2ce4dcab3 Fix validator build 2021-07-30 10:19:10 -07:00
terence tsao
8765c3ac42 Add contexts to sync committee functions 2021-07-30 09:53:45 -07:00
terence tsao
57fff2d88e Update BUILD.bazel 2021-07-30 09:31:47 -07:00
terence tsao
c010a972e7 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-07-30 09:31:24 -07:00
Mohamed Zahoor
0d818a5709 Reduce memory overhead during DB migrations (#9298)
* wip

* migration happening

* wip

* fix memory utilization, add the testcases

* migration issues

* the gazel

* remove debug logging

* goimport

* gazel
2021-07-30 08:38:54 -05:00
terence tsao
560fe69425 Core: sync committee helpers (#9269)
* Add sync committee helpers

* Create BUILD.bazel

* Update BUILD.bazel

* Update BUILD.bazel

* Fix visibility

* Preston's review
2021-07-29 23:19:32 +00:00
terence tsao
012d279663 Fix duplicated imports (#9304)
* Fix duplicated imports

* Fix metrics test
2021-07-29 16:45:17 -05:00
terence tsao
fcd4938ec0 Head: validator index getters (#9303) 2021-07-29 20:05:48 +00:00
terence tsao
c02ed805b0 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-07-29 10:32:53 -07:00
Radosław Kapka
4db0dfc4f1 Properly broadcast attestations (#9301)
* better handling of gateway response

* empty response tests

* build file

* broadcast attestations properly

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-07-29 18:33:18 +02:00
Raul Jordan
93adf4980a Merge branch 'develop' into hf1 2021-07-29 09:26:19 -05:00
terence tsao
cf4ff3d6f9 Clean up phase 0 spec tests (#9299) 2021-07-29 09:01:18 -05:00
nisdas
3fe969992a fix bad merge 2021-07-29 19:25:34 +08:00
nisdas
2135108830 deepsource 2021-07-29 18:35:07 +08:00
nisdas
4c146dc896 gaz 2021-07-29 18:31:56 +08:00
nisdas
042a3cda02 fix again 2021-07-29 18:31:31 +08:00
nisdas
b8676480f0 fix again 2021-07-29 16:56:42 +08:00
nisdas
711022d34e fix p2p 2021-07-29 16:47:25 +08:00
nisdas
eec93be4ed fix 2021-07-29 16:33:20 +08:00
nisdas
21d096622f fix tests 2021-07-29 15:51:17 +08:00
nisdas
62846d61b8 fix spec tests 2021-07-29 15:45:12 +08:00
nisdas
a228a407be fix tests so far 2021-07-29 15:35:11 +08:00
Raul Jordan
f527b676da val tests pass 2021-07-28 22:43:44 -05:00
Raul Jordan
5bd4e10dd6 fix build 2021-07-28 22:04:54 -05:00
Raul Jordan
d19e13352b beacon builds 2021-07-28 21:56:10 -05:00
rauljordan
6bda9a0bf2 fix conflict in proto file 2021-07-28 20:19:46 -05:00
rauljordan
2da6b7bb97 attempt fix merge confs 2021-07-28 20:19:00 -05:00
Raul Jordan
9145310647 Eliminate Proto V2 Namespace (#9297)
* get rid of v2 in prysm codebase

* replace block2

* builds

* terence comments

* gazelle
2021-07-28 21:23:44 +00:00
Mohamed Zahoor
21c79f4dfa Protect the state objects in memory when saving them (#9291)
Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-07-28 18:27:27 +00:00
Raul Jordan
98f7f82b2f Copy Altair Changes Into v1alpha1 Namespace (#9296)
* move the v2 changes into v1alpha1

* v1alpha1 builds

* regenerate pbs

* regenerate ssz

* top level builds
2021-07-28 18:05:07 +00:00
terence tsao
f16b9859e7 Test: add altair test utility (#9287)
Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-07-28 17:15:23 +00:00
Raul Jordan
7faed861c4 Merge branch 'develop' into hf1 2021-07-28 11:30:41 -05:00
nisdas
8b9129d84e merge fixes 2021-07-28 23:11:49 +08:00
Nishant Das
a372e30c8f Fix Spaced Arguments for Subcommands (#9292)
* fix args for commands

* fix nasty edge case
2021-07-28 14:36:48 +00:00
nisdas
8b219b14da Merge branch 'develop' of https://github.com/prysmaticlabs/geth-sharding into hf1 2021-07-28 20:32:15 +08:00
Nishant Das
415973fca3 remove flag (#9290) 2021-07-28 16:11:22 +08:00
Raul Jordan
2d9915d2d9 Define Unimplemented V2 Services (#9286)
* generate ssz bindings for protos

* define services and unimplemented

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-07-27 20:42:14 +00:00
Mohamed Zahoor
c6bd7a2f83 Efficient Historical State Representation (#9155)
* added migration in to new schema

* gazel fix

* goimports fix

* construct state with validator entries from a seperate bucket

* save state with validator entry indirection

* fixed save and retreieve issues

* fixed more test cases related to DeepEqual

* added save benchmark

* gazel fix

* organize benchmarks

* add cache and improve state construction  performance

* gazel fix

* check type

* remove cache checking from Has

* fix decoding when cache is off

* fix slice bugs

* add migration testcases

* linter fix

* fix few review comments

* fix review feedback

* gazel fix

* satisfy deepsource

* added the feature flag

* lint fix

* fix usage of featureconfig Inti in testcases

* call resetConfig method

* add feature flag in  migration testcases

* fix formatting

* change bucket name from blockRootValidatorKeysIndexBucket to blockRootValidatorHashesBucket

* remove from cache when state deleted

* fixed few more comments

* added to devModeFlags

* added cache delete under the feature flag

* fix lint

* change cache sizes and improve documentation

* fiexed few more review coments

* not using hash anymore and using a new SaveStates function

* satisfu deepsource

* run gazel

* fix feature flag related stuff

* fixing merge conflict fix

* few goodies

* improve UX and dont swallow error

* merge fix

* import format fix

* fix migrationion when flag not given issue

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
Co-authored-by: Nishant Das <nishdas93@gmail.com>
2021-07-27 20:02:53 +00:00
terence tsao
7129af5ccf Core/deposit: altair processing methods and tests (#9227) 2021-07-27 12:10:08 -07:00
Raul Jordan
f700808c8b Generate SSZ Bindings for Latest Protos (#9285) 2021-07-27 17:57:11 +00:00
Raul Jordan
5bf9bd3d73 fix up conflicts with develop 2021-07-27 12:27:24 -05:00
Raul Jordan
59f12c8ac1 sync develop 2021-07-27 12:02:49 -05:00
Raul Jordan
1ea1c69174 Copy V1Alpha1 Protos and API Endpoints To V2 Namespace (#9284)
* v2 builds

* generate go code

* fix build
2021-07-27 16:54:49 +00:00
terence tsao
1094ca0838 Update field_trie.go 2021-07-27 08:52:51 -07:00
terence tsao
ebe4b309c0 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-07-27 08:52:42 -07:00
terence tsao
54772596e0 State/V2: rest of pkg (#9283)
* Add rest of state v2

* Update BUILD.bazel
2021-07-27 15:47:03 +00:00
Nishant Das
a556cf27c4 Use Only Checkpoint Cache for Processing Attestations (#9282)
* use only one cache

* clean up
2021-07-27 07:26:53 -07:00
rauljordan
ea94f0e70d add changes from develop 2021-07-26 21:16:03 -05:00
rauljordan
47443e130d merge slasher proto 2021-07-26 21:13:44 -05:00
rauljordan
4dfa5c2757 rem slashing proto 2021-07-26 21:02:09 -05:00
terence tsao
1851d40f74 Go fmt 2021-07-26 17:31:59 -07:00
terence tsao
eee1d47655 Fix conflicts 2021-07-26 17:14:57 -07:00
terence tsao
7ce76652fb Merge 2021-07-26 16:57:49 -07:00
terence tsao
5b5c8f4d3f State/V2: setters (#9279)
* Add state v2 getters

* Update BUILD.bazel

* Add state v2 setters

* Update BUILD.bazel
2021-07-26 17:27:05 -05:00
terence tsao
245dc23cde State/V2: getters (#9228)
* Add state v2 getters

* Update BUILD.bazel
2021-07-26 20:55:30 +00:00
Radosław Kapka
837cd4eb8f Implement ProduceAttestationData in the validator API (#9271)
* functionality

* test

* build file

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-07-26 19:22:58 +00:00
Radosław Kapka
8c8f1bb9c1 Regression test for #9264 (#9277) 2021-07-26 11:48:51 +00:00
Kaan
a8c49c50ad v1alpha1 validators: catch possible reqState nil case (#9275)
* v1alpha1 validators: catch possible reqState nil case

* Minor format of error log

Co-authored-by: terence tsao <terence@prysmaticlabs.com>
Co-authored-by: Radosław Kapka <rkapka@wp.pl>
2021-07-26 13:50:40 +08:00
Lorem Ipsum
14d0d9195f Fixing wrong node information in fallback log (#9258) (#9272) 2021-07-25 23:46:54 +02:00
terence tsao
8db0c9a0e6 Move proto/interfaces -> proto/prysm/v2 (#9270)
* Move proto/interfaces -> proto/prysm

* Update paths

* Fix block2

* Update blocks_fetcher_utils.go

* Update BUILD.bazel

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-07-23 20:10:15 +00:00
Preston Van Loon
938a038c42 Fix //... for darwin (#9273)
* Fixes

* More manual tags

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-07-23 18:26:49 +00:00
Raul Jordan
30e93f5763 Move Slashing Protos to V2 (#9256)
* proto slashing

* move slashing related protos

* gaz

* include slasher pbs consolidated

* slasher pb fmt imports

* imports

* beacon builds

* build validator

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-07-23 18:01:01 +00:00
Radosław Kapka
be82c8714f Do not require a handler function in the gateway (#9264)
* Do not require a handler function in the gateway

* test fix

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-07-23 16:48:22 +00:00
prestonvanloon
19e6f0c19a Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-07-23 11:46:41 -05:00
Preston Van Loon
c0076cc7a2 State: move state interfaces into state package (#9268)
* Move interfaces from github.com/prysmaticlabs/prysm/beacon-chain/state/interface to github.com/prysmaticlabs/prysm/beacon-chain/state

* remove/rename state2
2021-07-23 16:11:21 +00:00
Raul Jordan
6470e2718a Merge branch 'develop' into hf1 2021-07-23 11:01:22 -05:00
Raul Jordan
30cd5c076e fix confs 2021-07-23 11:00:47 -05:00
terence tsao
03d8af5cda Core/altair: sync committee tests clean up 2021-07-23 08:27:32 -07:00
Raul Jordan
194f0cb76d merge with develop 2021-07-23 10:04:22 -05:00
terence tsao
2a0e8510d4 Update skip_slot_cache_test.go 2021-07-23 07:32:36 -07:00
Radosław Kapka
a8363405f8 Implement ProduceBlock in the validator API (#9259)
* server-side implementation

* build file

* run through api middleware

* tests

* build file

* gofmt

Co-authored-by: Nishant Das <nishdas93@gmail.com>
2021-07-23 16:29:38 +02:00
Raul Jordan
2d10bcf179 Move State Protos Into V2 Namespace (#9257)
* move state protos

* regen ssz

* edit v1 code

* fix imports

* building

* beacon chain builds

* validator and shared builds

* fuzz builds

* changes

* spectest builds

* tools build

* remove import cycle

* generate ssz

* pcli

* gaz

* kafka

* gaz
2021-07-23 08:07:40 -05:00
Nishant Das
5e35f778b9 unregister rpc topics (#9241) 2021-07-23 13:00:44 +08:00
terence tsao
526596a679 State/v1: add atts and block roots getter tests (#9255)
* Add att and block getter tests

* Update BUILD.bazel

* Update getters_attestation_test.go

* Update beacon-chain/state/v1/getters_block_test.go

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

* Fix mutation tests

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
2021-07-22 22:31:14 +00:00
Raul Jordan
5864795ca5 Move RPC Protos Into V2 Namespace (#9254)
* moved rpc protos

* gazelle

* change pb

* validator health

* edit name

* naming
2021-07-22 21:00:28 +00:00
Raul Jordan
b7919b3115 Move DB Protos Into V2 Namespace (#9253)
* move db protos into prysm v2

* build

* build

* imports gaz

* v2

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-07-22 20:05:06 +00:00
Raul Jordan
715aa408e3 Move Web Protos Into Prysm V2 (#9249)
* move web protos

* move web to v2

* update web protos

* gaz

* proto build

* replace mentions of validator v2

* gaz
2021-07-22 19:19:24 +00:00
Raul Jordan
ceb1ec451a Remove Faucet Protos (#9252)
* rem faucet protos

* tidy
2021-07-22 18:27:31 +00:00
Radosław Kapka
b35c3ab2e7 Implement GetAggregateAttestation in the validator API (#9243)
* server-side implementation

* run through api middleware

* tests

* build file

* build file fix

* return attestation with most aggregation bits

* build file

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-07-22 17:48:32 +00:00
terence tsao
c8685d256c Lint: add v1 as import alias (#9250)
* Add v1 as import alias

* Update helpers.go

* More

* Update skip_slot_cache_test.go

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-07-22 17:13:18 +00:00
Raul Jordan
0fb43aec34 Remove Unused Cluster Protos (#9251)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-07-22 16:39:27 +00:00
terence tsao
9addb5f7c3 Core/epoch: sync committee period (#9248)
* Combine function parameters

* Add sync committee epoch calculations

* Update BUILD.bazel
2021-07-22 16:13:42 +00:00
terence tsao
972ae7f169 Merge branch 'hf1' of github.com:prysmaticlabs/prysm into hf1 2021-07-22 08:12:58 -07:00
terence tsao
80fafaddff Move TestSyncCommitteePeriod 2021-07-22 08:12:35 -07:00
Nishant Das
33f7582d25 Add Doppelganger E2E (#9239)
* add current fixes

* fix prev release

* Update endtoend/endtoend_test.go

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

* Update endtoend/endtoend_test.go

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

* Update endtoend/endtoend_test.go

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

* review comments for radek and raul

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-07-21 23:00:12 -05:00
rauljordan
e6ecdfde0d regen protos 2021-07-21 17:38:01 -05:00
rauljordan
1daf51788d merge with develop 2021-07-21 17:34:53 -05:00
Raul Jordan
6dadb80cc4 Move v1alpha1 into Prysm API namespace (#9245) 2021-07-21 21:34:07 +00:00
Radosław Kapka
ae140073e7 Remove proposer_sync_aggregate.go (#9231)
Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-07-21 19:35:18 +00:00
terence tsao
b667d30d3f Feature/UpdateHeadTimely: cache finalized checkpoint when initial sync (#9244) 2021-07-21 11:55:27 -07:00
terence tsao
e7bdf35721 Fix unused variables (#9234)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-07-21 16:06:57 +00:00
Nishant Das
c780301096 Remove Validator DB Cache (#9238)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-07-21 15:26:07 +00:00
terence tsao
35055539a7 Revamp head state + sync committee operations and the bug fix (#9200) 2021-07-21 08:04:18 -07:00
terence tsao
e1d543a77b Combine function parameters (#9242) 2021-07-21 14:55:37 +00:00
Nishant Das
81ab3ca46c Enable Sync Evaluator For E2E (#9240) 2021-07-21 06:56:26 -07:00
Nishant Das
2ffe8336fc Fix Parsing of Nested Subcommands (#9236) 2021-07-21 13:01:33 +02:00
terence tsao
5895b10678 Fix next epoch sync duty calculation (#9233)
* Fix next epoch duty assignment

* Regression test

* Update comment

* Go fmt

* Fix sync committee disable namings

* Fix test comment
2021-07-21 10:08:59 +08:00
Nishant Das
11d9e7da9b Update Libp2p to v0.14.4 (#9108)
* fix

* tidy

* fix deps

* tidy

* fix pubsub
2021-07-20 23:50:47 +00:00
Radosław Kapka
53e02b1601 Log correct warning when disabling flags (#9230)
* Log correct warning when disabling flags

* use interface

Co-authored-by: prestonvanloon <preston@prysmaticlabs.com>
2021-07-20 16:54:08 +00:00
prestonvanloon
7ea645ed37 Merge commit '8d1c9fe1e22630d9fd03c4be861a1d33f35b7a11' of github.com:prysmaticlabs/prysm into hf1 2021-07-20 09:46:46 -05:00
prestonvanloon
a900792160 Merge commit '412ddbb29ef73466b880e7ba4101252ac88cf078' of github.com:prysmaticlabs/prysm into hf1 2021-07-20 09:44:45 -05:00
prestonvanloon
cd87bfd8ab Merge commit '8a7010f5aaeb95abd1f7036fcd356817a2b339fe' of github.com:prysmaticlabs/prysm into hf1 2021-07-20 09:38:53 -05:00
terence tsao
98477a0286 Merge commit '1beb0071b5730f0ec0fb1beb9056c06d55ef562b' of github.com:prysmaticlabs/prysm into hf1 2021-07-20 07:26:55 -07:00
prestonvanloon
2d1a63d9f4 Merge commit '2a0c4e0d5fe8e8a422e3bb47a7a692db56ec55c9' of github.com:prysmaticlabs/prysm into hf1 2021-07-20 08:58:58 -05:00
terence tsao
52be270f0a Update TargetAggregatorsPerSyncSubcommittee to 16 (#9229) 2021-07-20 10:56:06 +08:00
prestonvanloon
895a86fd53 Merge commit '15bfcf8ff6f43db6029c5d8eee0b71a7bead86b0' of github.com:prysmaticlabs/prysm into hf1 2021-07-19 21:52:37 -05:00
terence tsao
af6246a5f9 Merge commit '15704053e112b8bb89472c75cba77e67e26e2c49' of github.com:prysmaticlabs/prysm into hf1 2021-07-19 18:29:13 -07:00
terence tsao
5e80ceeff9 Remove unused sync committee feed type 2021-07-19 14:01:00 -07:00
Preston Van Loon
3a35a953bf proto/prysm/v2: Introduce Altair pb changes (#9222)
* Copy v2 protos from hf1

* Remove some extra Altair naming

* Build with github.com/ferranbt/fastssz/pull/50

* Regen pb.go

* Update fastssz to master
2021-07-19 20:42:06 +00:00
Preston Van Loon
8d1c9fe1e2 epoch/precompute: Add changes from Altair (#9219)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-07-19 19:39:23 +00:00
terence tsao
4229b466ae Add sync committee pool pkg (#9203)
* Add sync committee pkg

* Fix err variable namings
2021-07-19 19:06:49 +00:00
Preston Van Loon
412ddbb29e beacon-chain/state/v1: ReadOnlyValidator wrapper constructor method (#9221)
* Introduce changes from Altair hf1 branch

* go pkg viz changes

* Fix test

* goimports for some reason

* Use a more safe method of wrapping validators with regards to nil validators. Add basic tests for this wrapped validator

* Use a more safe method of wrapping validators with regards to nil validators. Add basic tests for this wrapped validator

* Panic fixes

* Fix tests

* remove nil validator test as it is no longer possible

* goimports for some reason

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-07-19 18:26:39 +00:00
Radosław Kapka
8a7010f5aa Implement GetProposerDuties in the validator API (#9223)
* endpoint implementation

* extract common code

* tests

* remove named return values

* correct test log

* sort duties by slot

Co-authored-by: terence tsao <terence@prysmaticlabs.com>
2021-07-19 18:00:15 +00:00
Nishant Das
40a96bc2b6 Invert Update Head Timely Flag (#9224)
* invert

* Update shared/featureconfig/flags.go

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

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-07-19 17:23:43 +00:00
terence tsao
1beb0071b5 State/v2: Add InitializeFromProto and InitializeFromProtoUnsafe (#9226)
* Add `InitializeFromProto`

* Update BUILD.bazel
2021-07-19 16:47:42 +00:00
terence tsao
2a0c4e0d5f Use block wrapper and interface for propose block (#9218) 2021-07-19 15:51:38 +00:00
Nishant Das
dad205bd04 Invert Optimized Balance Update Feature (#9225) 2021-07-19 14:27:20 +00:00
Preston Van Loon
15bfcf8ff6 Add tests for wrapped Altair objects (#9213)
* start tests for wrapped methods

* Add a few tests and skeletons for interface impl methods

* Add latest interfaces update from hf1 and stub the appropriate tests

* Add a few more tests

* More progress

* Migitate nil pointer issues in construct. Complete tests

* Copy changes from hf1 to v1alpha1 wrapper

* Use testutils from #9201

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-07-18 19:32:52 +00:00
terence tsao
15704053e1 Add Altair configs (#9150)
* Add altair configs

* Update minimal_config.go

* Update workspace and config tests

* Revert workspace changes

* Update WORKSPACE

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
2021-07-18 16:18:43 +00:00
Nishant Das
ee661971f0 Add Fixes Observed From Devnet (#9205)
* add changes and test cases

* gaz

* add one more test

* comment

* deep source

* fix
2021-07-18 12:32:32 +08:00
nisdas
cc7e36776d gaz 2021-07-17 18:34:12 +08:00
nisdas
14a9d9a1ad Merge branch 'develop' of https://github.com/prysmaticlabs/geth-sharding into hf1 2021-07-17 18:33:45 +08:00
terence tsao
5be1ccd3cf Hydrate altair block (#9201)
* Hydrate altair blocks

* Update BUILD.bazel

* HTR test

* Update BUILD.bazel

* Comment

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-07-16 23:35:37 +00:00
terence tsao
97e6eb14e2 Altair block wrapper: update return to interfaces (#9212) 2021-07-16 23:09:45 +00:00
Mohamed Zahoor
6f126c92c0 Make exportdb tool faster (#9184)
* added prodecer consumer pattern for reading and printing

* make state interface visible in exploredb

* bazel magic for visibility

* fix manual visibilithy marking

* linter fix

* parallelized bucket stats

* add log.WithErr and log.Infof

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-07-16 22:24:16 +00:00
terence tsao
2b9fb29ed2 Sync with develop 2021-07-16 15:20:45 -07:00
Radosław Kapka
223d5309a0 Implement GetAttesterDuties in the validator API (#9207)
* remove irrelevant comment

* fix proto documentation

* first implementation

* register validator server

* first working version

* add sync checker and test file

* first test

* gzl

* final version + tests

* gzl

* run duties through API Middleware

* extract dependent root getter

* dependentRoot docs

* wrap indices in array

* fix static analysis issues

* modify err nil check

* create local variables in slot processing test

* Update proto/eth/v1/validator_service.proto

* review

* simplify index loops

* better calculation of committees at slot

* comment about impossible comndition

Co-authored-by: terence tsao <terence@prysmaticlabs.com>
Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-07-16 20:55:22 +00:00
Preston Van Loon
31d2482f9c Add proto wrappers for Altair (#9209)
* Starting attestation test

* Commiting checkpoint progress before dinner

* Add remainder of tests

* Copy hf1 cloners and add tests

* Introduce wrapper changes from hf1

Co-authored-by: terence tsao <terence@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-07-16 20:30:26 +00:00
terence tsao
3ef0c5d6e5 Fix deepsource: shadow of builtin detected (#9210)
Co-authored-by: Radosław Kapka <rkapka@wp.pl>
2021-07-16 20:04:30 +00:00
Preston Van Loon
187a1ca53d shared/copyutil: Add copy methods for Altair (#9208)
* Starting attestation test

* Commiting checkpoint progress before dinner

* Add remainder of tests

* Copy hf1 cloners and add tests

Co-authored-by: terence tsao <terence@prysmaticlabs.com>
2021-07-16 19:30:48 +00:00
Preston Van Loon
17d7fc492e shared/copyutil: Add tests for copy methods (#9204)
* Starting attestation test

* Commiting checkpoint progress before dinner

* Add remainder of tests

Co-authored-by: terence tsao <terence@prysmaticlabs.com>
2021-07-16 16:56:09 +00:00
Nishant Das
9300d1026f Add E2E Support For Altair (#9173) 2021-07-16 08:06:54 -07:00
Nishant Das
48345eb68e Fix Gossip Message ID Versioning (#9206) 2021-07-16 08:03:35 -07:00
Preston Van Loon
f029fdd44a beacon-chain/state/stateutil: Fix benchmark target (#9199)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-07-16 14:39:14 +00:00
Nishant Das
60d14f1806 Allow For Proper Registration and Deregistration of Topics (#9194)
* add fixes

* gaz

* fix

* fix

* Update beacon-chain/sync/fork_watcher.go

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

* preston's review

* add unit test

* gaz

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
2021-07-16 10:50:40 +08:00
terence tsao
d80d4d01a6 Update spec test (#9198) 2021-07-15 16:13:59 -07:00
Preston Van Loon
44d266313e testutil: Add NotEmpty method (#9202) 2021-07-15 22:32:10 +00:00
terence tsao
1a9a46d042 Block util: block header from block interface (#9196)
* Add beacon block header from block interface

* Update BUILD.bazel

* Update shared/blockutil/block_utils.go

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

* Go fmt

* Remove unused bodyroot

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
2021-07-15 16:03:46 +00:00
Preston Van Loon
71c8c75bc3 shared/queue: Add RetrieveByKey method (#9195)
* Checkout shared/queue changes from hf1 branch

* Remove logic that removes and reinserts an item into the queue at the back

* Add test to ensure the correct thing was returned

Co-authored-by: terence tsao <terence@prysmaticlabs.com>
2021-07-15 10:31:19 -05:00
terence tsao
275192680f Fix build 2021-07-15 07:10:19 -07:00
terence tsao
9ca958064e Fix build 2021-07-15 06:06:03 -07:00
Nishant Das
604958da6c Add List Blocks RPC For Altair (#9186)
* add new method in

* fix

* preston's review

* gaz
2021-07-15 13:22:40 +08:00
terence tsao
ade94444f2 Add active balance to committee cache (#9187) 2021-07-14 18:32:17 -07:00
terence tsao
b22935a724 Rename AttestationNotifier (#9197) 2021-07-14 18:32:03 -07:00
terence tsao
4df2f4c790 Fix signSlotWithSelectionProof signature 2021-07-14 15:56:50 -07:00
terence tsao
3f8f5edb3f Clean up deposits 2021-07-14 13:25:28 -07:00
terence tsao
0ad4e433a5 Sync with develop 2021-07-14 10:08:08 -07:00
terence tsao
1be2503e82 Disallow sync committee cache update if state root is 0s (#9190) 2021-07-14 08:00:23 -07:00
Radosław Kapka
3ff5b95945 Remove database field from v1alpha1 validator server (#9191)
* Remove database field from v1alpha1 validator server

* remove field

* gzl

* remove not needed variable

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-07-14 13:16:21 +00:00
Nishant Das
e6bd5f31b1 Cleanup Fast Aggregate Verify (#9193) 2021-07-14 11:12:50 +00:00
terence tsao
9a4ab41761 BaseReward test only (#9189)
* Move baseward to test only

* Update BUILD.bazel

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-07-13 20:12:53 +00:00
terence tsao
7f0749c398 Clean up shared interface package (#9172)
* Remove shared interface folder

* Rename file names

* Gazelle

* Move interface to /beacon/p2p/

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: Nishant Das <nishdas93@gmail.com>
2021-07-13 18:58:43 +00:00
Nishant Das
d73ac71ee6 add std out for beacon node (#9183) 2021-07-13 08:45:26 -05:00
terence tsao
0dd228bb94 Sync committee pool can retrieve without pop (#9179)
* `RetrieveByKey` for priority queue

* Sync committee pool to use `RetrieveByKey`

* Update message_test.go

* remove err

* fix test

Co-authored-by: nisdas <nishdas93@gmail.com>
2021-07-13 16:13:21 +08:00
terence tsao
78450ea557 Remove validator pubkey to index map (#9177) 2021-07-12 13:44:09 -07:00
terence tsao
6ba741f251 Calculate epoch outside of loop (#9178) 2021-07-12 12:35:36 -07:00
terence tsao
f0e6d4a0bd Sync committee cache: fill on miss (#9176) 2021-07-12 10:49:49 -07:00
Radosław Kapka
4ebb008bc9 Protos and stubs for validator API endpoints (#9174)
* match proto definitions with spec

* stubs for grpc server's functions
2021-07-12 10:38:55 -05:00
terence tsao
97901c90a5 Update sync committee cache using block root at boundary slot - 1 (#9171) 2021-07-12 08:06:47 -07:00
nisdas
1379dbfc23 Merge branch 'develop' of https://github.com/prysmaticlabs/geth-sharding into hf1 2021-07-12 14:01:52 +08:00
terence tsao
19dbc7e249 Revamp head state + sync committee operations (#9167) 2021-07-09 15:02:03 -07:00
terence tsao
76a70065f2 Add more metrics (#9168) 2021-07-09 08:01:15 -05:00
Nishant Das
51f513b246 Remove Non Spec Config Variables (#9170)
* only one way

* cleanup

* extra

* fix

* fix test
2021-07-09 07:57:26 -05:00
Nishant Das
2b349a1b06 Interop Fixes (#9163) 2021-07-08 20:33:44 -07:00
terence tsao
a819caca16 State gen's reply can upgrade state (#9164) 2021-07-08 15:38:30 -07:00
Nishant Das
e7116d4ea8 Fix Goimports and DeepSource (#9148)
* add goimports

* fix again

* imports

* deep source

* assignment

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-07-08 13:31:16 -05:00
prestonvanloon
f8cd989161 Fix build 2021-07-08 10:42:50 -05:00
prestonvanloon
4c19265ac5 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-07-08 10:33:11 -05:00
Nishant Das
f361bf781f Altair Networking Support (#8994)
* add method and test

* fix message type across forks

* invert fork version schedule

* add support for forks in metadata

* start fixing discovery

* fix fork version stuff

* fix up fork digest usage

* add fork transition mechanism

* gaz

* add fixes to mappings

* checking in current progress

* fix aggregates

* fix scheduling

* fix

* fix copy

* fix rpc stuff

* fixes

* add new topics and files

* gaz

* add pool

* finish pipeline for sync aggregate proofs

* gaz

* Update beacon-chain/cache/sync_subnet_ids.go

Co-authored-by: terence tsao <terence@prysmaticlabs.com>

* add support for sync committee pipeline

* fix

* check better

* fix

* fix again

* remove redundant code

* remove older code

* checkpoint

* get it working

* gaz

* regen

* checkpoint

* gaz

* build

* fix edge case

* fix all errors

* sync with hf1

* fix issues

* gaz

* fix bad rpc respones

* fix it all

* hash

* save everything

* fix all remaining tests

* comments

* fix build

* terence's review

* preston's review

* build

* gaz

* gaz

* add signature test

* add in more tests

* gaz

* add more tests

* fix goimports

* Revert "fix goimports"

This reverts commit 41bf7b4a5c.

* fix tests

* fix all tests

* fix all tests

* fix everything

* fix last test

* fix rpc registration

* fix build

* fix build

* remove outdated method

* add recovery

* Update subscriber.go

* terence's review

* fix bad merge

Co-authored-by: terence tsao <terence@prysmaticlabs.com>
Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-07-08 11:25:41 +08:00
terence tsao
a458e556e0 Align sync committee pipelines to alpha8 (#9160) 2021-07-07 10:54:48 -07:00
Nishant Das
773b259cd5 add in (#9158)
Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-07-07 11:03:16 -05:00
terence tsao
2bb3da1ba3 Clean up sync committee p2p pipelines (#9153) 2021-07-07 07:35:01 -07:00
Raul Jordan
47367d98b4 Resolve Deep Source Warnings (#9154) 2021-07-07 06:33:40 -07:00
terence tsao
1ff18c07a4 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-07-06 20:17:17 -07:00
terence tsao
279a95deba Fix spec tests 2021-07-06 13:26:17 -07:00
terence tsao
c0bfa6ef79 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1
# Conflicts:
#	beacon-chain/core/state/BUILD.bazel
#	beacon-chain/core/state/transition.go
#	beacon-chain/core/state/transition_no_verify_sig.go
#	beacon-chain/db/kv/BUILD.bazel
#	beacon-chain/db/kv/blocks.go
#	beacon-chain/db/kv/blocks_test.go
#	beacon-chain/rpc/eth/v1/beacon/BUILD.bazel
#	beacon-chain/rpc/prysm/v1alpha1/beacon/BUILD.bazel
#	beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel
#	beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go
#	beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go
#	beacon-chain/rpc/service.go
#	beacon-chain/state/stategen/BUILD.bazel
#	beacon-chain/state/stategen/replay.go
#	beacon-chain/sync/BUILD.bazel
#	beacon-chain/sync/rpc_chunked_response.go
#	proto/eth/v1alpha1/wrapper/beacon_block.go
#	shared/interfaces/BUILD.bazel
#	shared/testutil/BUILD.bazel
#	shared/testutil/block_test.go
2021-07-06 13:15:35 -07:00
terence tsao
7e961c2be9 Merge branch 'hf1' of github.com:prysmaticlabs/prysm into hf1 2021-07-06 11:09:43 -07:00
terence tsao
c7c7f9bf1b Fix missing 3rd arguments for gomock's Do 2021-07-06 11:09:32 -07:00
Nishant Das
7ce85cac31 Fix Stategen For Altair (#9152) 2021-07-06 10:43:36 -07:00
terence tsao
2d836f485d Move test only functions to testutil (#9137) 2021-07-06 12:08:52 -05:00
terence tsao
780253b786 Go fmt 2021-07-05 10:10:08 -07:00
terence tsao
710bb98575 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-07-05 09:38:49 -07:00
Nishant Das
d5387851d0 Validator Fixes From Interop (#9110)
* validator fixes

* gaz

* fix validator

* pull in fixes

* add in test

* terence's review

* fix references

* fix all tests
2021-07-02 13:50:16 +08:00
terence tsao
ab8dd3788f Altair: Green minimal spec tests (#9078) 2021-06-30 19:28:44 -07:00
terence tsao
bf1b550b7d Green Altair e2e tests (#9131) 2021-06-30 16:33:08 -07:00
prestonvanloon
705564108c Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-06-30 14:27:43 -05:00
terence tsao
3df82e7540 Use sync committee start period root as cache key (#9128) 2021-06-30 08:54:31 -07:00
Raul Jordan
d0a749ce4b ensure build 2021-06-30 10:49:54 -05:00
Raul Jordan
081c80998c fix conflicts and merge with develop 2021-06-30 10:44:18 -05:00
terence tsao
8c62f10b74 Altair: proposer pack sync aggregate (#9124)
* Pack sync aggregate into beacon block

* Build.bazel
2021-06-29 15:22:16 -05:00
terence tsao
e232b3ce30 Merge branch 'hf1' of github.com:prysmaticlabs/prysm into hf1 2021-06-29 12:14:37 -07:00
terence tsao
17153bb4e9 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-06-29 10:26:38 -07:00
Raul Jordan
329a45c06a fix confs 2021-06-29 12:24:47 -05:00
Raul Jordan
1c82394a69 sync changes 2021-06-29 12:21:09 -05:00
terence tsao
856081c80c Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-06-29 09:17:56 -07:00
terence tsao
6fff327864 Gazelle 2021-06-29 09:12:21 -07:00
terence tsao
e2879f8352 Resolve conflict 2021-06-29 09:12:14 -07:00
terence tsao
523fe58f61 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-06-29 09:10:07 -07:00
terence tsao
04a303c8d2 Add logging (#9115) 2021-06-29 08:27:41 +08:00
Raul Jordan
0844bd62ea sync changes 2021-06-28 13:47:42 -05:00
Nishant Das
816dc47b17 Add New V2 Streaming Blocks Method (#9094)
* add latest changes in

* gaz

* regen mocks

* build file

* gazelle

* import

* import

* add iface check

* add one more case

* add one more case

* add proper type

* fix wierd imports

* fix mocks

* go imports

* fix build

* fix go mocks

* pass in non nil objects

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-06-28 16:06:53 +08:00
terence tsao
caeec851d4 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-06-27 10:58:31 -07:00
terence tsao
062933af35 Update spec test to alpha8 (#9103) 2021-06-25 13:21:58 -07:00
terence tsao
169573c32e Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-06-25 12:27:56 -07:00
Raul Jordan
e7a7b2861e Merge branch 'develop' into hf1 2021-06-24 18:12:57 -06:00
Nishant Das
fe6c80fe95 Add Sync Subnet Id Cache (#9089)
* add stuff

* remove log

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-06-24 11:56:02 -05:00
Nishant Das
2f52dfe96e Add Updated Fork Utils (#9090)
* add fork utils

* fix it

* more unit tests

* fix test

* fix test

* fix tests

* fix tests

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-06-24 11:00:27 -05:00
Raul Jordan
93a7b96f16 skip test for validator at current release 2021-06-24 09:43:00 -06:00
Raul Jordan
f078b62c3e Merge branch 'develop' into hf1 2021-06-24 09:42:12 -06:00
Preston Van Loon
f476c39708 Use same version of spectests and spec in WORKSPACE (#9084)
* Use same version of spectests and spec in WORKSPACE

* Fix test loading eth2 spec files
2021-06-23 14:59:32 -05:00
terence tsao
c02e507422 Use correct fork version object for domain data (#9081)
* Use correct fork version object

* Use p2putils

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-06-23 13:40:03 -05:00
Raul Jordan
ece07e5fbb Implement Beacon Validator RPC V2 In Proper Package (#9083)
* implement v2 endpoints in own folder

* passing tests

* naming
2021-06-23 13:15:23 -05:00
prestonvanloon
6bbe3dbd10 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-06-23 12:48:22 -05:00
Raul Jordan
18bfc2a34e move rpc packages (#9082) 2021-06-23 12:27:19 -05:00
Raul Jordan
b774af9535 Altair: Use Validator Index for Sync Committee Caching (#9074)
* begin using validator indices for sync committee caching

* amend to use validator indices in rpc

* cache tests pass

* refactor for deduplication

* broken file

* amend core helper tests

* fix tests

* comment

* fix fuzzer iface

* imports

* fix up tests
2021-06-23 12:09:38 -05:00
Raul Jordan
719a5fca02 V2 Prysm Proto Definitions (#9062)
* begin v2 prysm protos

* define

* v2 protos build

* add in generated files

* imports

* do not modify v1alpha1

* revert imports

* use alias pattern

* attempt alias

* attempt new fastssz

* edit

* versioning all works

* edit protos

* edit terms

* edit to reflect proto versioning

* fix more build issues

* beacon chain builds

* beacon chain and shared packages build

* begin helping validator client build

* define protos

* gaz

* build

* tidy check

* gazelle

* revert
2021-06-23 11:27:06 -05:00
Nishant Das
b4a0e4375a add new changes (#9079) 2021-06-23 22:35:35 +08:00
terence tsao
4d276d2fdf Add sync committee head state cache (#9077) 2021-06-23 07:57:11 +08:00
terence tsao
8797179cfb Altair: Update sync committee cache (#9043)
* Update sync committee cache

* Remove debug log

* Gazelle
2021-06-23 07:39:22 +08:00
terence tsao
7cc38108aa Remove copy when push to priority queue (#9076)
* No reflect copy and clean up `SaveSyncCommitteeMessage`

* Update BUILD.bazel

* Go mod tidy
2021-06-23 07:38:30 +08:00
Raul Jordan
365ced285e Merge branch 'develop' into hf1 2021-06-22 14:23:33 -06:00
terence tsao
97e5730fd9 Altair: validator submit SignedContributionAndProof (#9064)
* Contribution and proof protos

* Completed `GetSyncCommitteeContribution` and `SubmitSignedContributionAndProof`

* Update beacon_validator_client_mock.go

* sync committee tests

* Update deposit_test.go
2021-06-22 18:58:56 +08:00
terence tsao
3919b49000 Fixed failing tests from resolving conflict 2021-06-21 21:56:13 -06:00
terence tsao
7f13396e44 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-06-21 08:10:13 -07:00
terence tsao
ae3e5718e6 Altair: check validator is an aggregator for sync committee (#9058) 2021-06-18 11:09:26 -07:00
Nishant Das
97a49240ba Add Block Proposals In Altair (#9056)
* add protobufs

* add tests

* mockgen

* fix mocks

* terence's review

* add ugly hack

* hack

* make ineffassign happy

* add back
2021-06-18 15:42:07 +08:00
terence tsao
232d519445 Fix sync committee duty off by 1 (#9057)
* Fix sync committee duty off by 1

* Update sync_committee_test.go
2021-06-18 11:57:55 +08:00
terence tsao
afd815bb5d Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-06-17 11:00:57 -07:00
terence tsao
56d383a354 Merge branch 'hf1' of github.com:prysmaticlabs/prysm into hf1 2021-06-17 10:44:25 -07:00
terence tsao
733023df03 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-06-17 10:09:04 -07:00
Nishant Das
9d9ce13753 Use Proper Test Util Methods For Altair (#9054)
* fix

* fix block

* terence's review

* fix
2021-06-17 14:22:12 +08:00
terence tsao
975e7a76bf Altair: Validator can submit sync committee msg (#9048)
* Grpc for submitting sync committee message

* RPC server implementation

* RPC client validator implementation

* Tests

* Use slot to get block root

* Gazelle

* Update tests

* Update tests

* Underflow check
2021-06-17 12:21:33 +08:00
Nishant Das
20ae23bd42 Add Sync Committee Pipelines (#9016)
* add sync pipelines

* gaz

* fix iface

* finally have 1 test working

* add all test cases

* gaz

* fix visibility

* ugly hack

* add all new test cases

* add more stuff

* all tests passing

* gaz

* fix lint
2021-06-17 10:42:34 +08:00
terence tsao
63cf429fa0 Add fallback check to sync committee helper (#9051)
* Add fallback to helper for sync committee check

* Gazelle

* Satisfy fuzz test

* Errors in its own file

* Update BUILD.bazel

* Gazelle
2021-06-17 10:28:21 +08:00
terence tsao
2aab4e2efe Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-06-16 10:44:45 -07:00
terence tsao
e2156f25e0 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-06-14 20:30:50 -07:00
terence tsao
a537833f75 Altair: add sync committee to duty rpc (#9037)
* Helpers to update sync committee cache

* Update grpc

* Update server implementation

* Update client implementation

* Fix test setup & deepsrc complains
2021-06-14 21:48:31 +00:00
terence tsao
61bf95e4e2 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-06-14 10:54:00 -07:00
terence tsao
357d3f3b6a Altair: Reuse validator wrapper (#9027) 2021-06-11 13:44:43 -07:00
terence tsao
b0bbfcab7f Run go mod tidy 2021-06-11 13:06:52 -07:00
terence tsao
06801a5230 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-06-11 12:01:27 -07:00
terence tsao
278857d576 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-06-10 20:29:44 -07:00
terence tsao
9c5c70fb32 Altair: sign block can handle versioning (#9013) 2021-06-10 15:44:49 -07:00
terence tsao
54326af141 Sync committee to use priority queue (#9018) 2021-06-10 15:44:28 -07:00
terence tsao
6020682ad1 Altair: beacon block operation in DB (#9012) 2021-06-10 15:16:32 -07:00
terence tsao
3f45d54986 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-06-09 14:27:24 -07:00
terence tsao
ecb51dc55d Altair: save state in DB (#9004)
* Altair: save state in DB

* Simplify return for `hasAltairKey`

* Go fmt
2021-06-09 11:34:42 +08:00
terence tsao
cbf4aeb859 Align to alpha7 (#9005) 2021-06-09 09:17:31 +08:00
terence tsao
b107bd2a5a Copy sync aggregate (#9003) 2021-06-09 09:17:12 +08:00
terence tsao
a5e2c3f551 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-06-08 08:06:20 -07:00
terence tsao
efffaeb359 Merge branch 'hf1' of github.com:prysmaticlabs/prysm into hf1 2021-06-08 08:05:12 -07:00
terence tsao
144576cf36 Altair Add back minimal spec tests (#8993) 2021-06-08 07:22:56 -07:00
Victor Farazdagi
fcf2be08d8 Altair: ssz_static tests (#8847) 2021-06-07 20:57:05 -07:00
terence tsao
2b5cd139f0 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-06-07 10:53:12 -07:00
terence tsao
77a4fdb509 Altair: fork transition and spec tests (#8919) 2021-06-04 15:43:36 -07:00
Nishant Das
a14d37b0ad Handle Multiple Block Types in Req/Resp (#8905)
* add in fork version

* fix

* add in for minimal

* params added in

* fix up

* checkpoint changes

* clean up

* add new stuff

* add new stuff

* fix rpc context

* fix context

* trigger gh hook

* trigger gh hook

* fix all tests

* fix perms

* support fast ssz everywhere

* fix tests

* fix

* map checks

* add initializer

* terence's review

* add metadata test

* add tests

* fix imports

* fix build

* remove junk
2021-06-04 11:30:53 +08:00
terence tsao
38e28af51e Gazelle 2021-06-03 19:34:27 -07:00
terence tsao
6dbe6cfd8c Add caches for sync committee signature and contribution (#8982) 2021-06-03 17:16:00 -07:00
rauljordan
c156c1fb91 rewrite imports and use builtin ethereumapis 2021-06-03 14:50:27 -05:00
rauljordan
393a744091 merge in develop 2021-06-03 14:33:43 -05:00
terence tsao
f83993b211 Altair: Utilize block interface for clean up (#8969) 2021-06-02 09:31:18 -07:00
nisdas
41433f8b2e Merge branch 'develop' of https://github.com/prysmaticlabs/geth-sharding into hf1 2021-06-02 14:02:51 +08:00
terence tsao
95f62de465 Add sync committee test (#8967) 2021-06-01 12:32:12 -07:00
terence tsao
fbb140eff7 Gazelle 2021-06-01 11:22:25 -07:00
terence tsao
22483a285a Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-06-01 11:10:21 -07:00
terence tsao
1d835d9859 Altair: Add Altair block wrapper (#8949)
* Add altair block wrapper

* Update comment

* fix test

Co-authored-by: nisdas <nishdas93@gmail.com>
2021-05-28 17:25:51 +08:00
terence tsao
98f8ab331a Altair: More spec tests (#8941) 2021-05-26 14:10:01 -07:00
terence tsao
0e88418b12 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-05-26 11:34:31 -07:00
terence tsao
ef3ff6f1d5 Sync with develop 2021-05-26 10:44:10 -07:00
terence tsao
7c22496c65 Fix sha256 2021-05-24 11:00:17 -07:00
terence tsao
c5256d09e0 Altair: update spec tests to alpha.6 (#8931) 2021-05-24 10:46:20 -07:00
terence tsao
d3d1eb833e Add fork spec tests (#8917) 2021-05-21 14:35:22 -05:00
terence tsao
2d9fd4ea29 Update to alpha.5 (#8915) 2021-05-20 13:32:51 -07:00
terence tsao
be168e4034 Altair: Add upgrade logic and tests (#8912) 2021-05-20 12:22:33 -07:00
terence tsao
f7c2b9c197 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-05-20 11:00:10 -07:00
Nishant Das
89b7cf9be3 Add In Altair Fork Data (#8903)
* add in fork version

* fix

* add in for minimal

* params added in

* fix up

* radek's review
2021-05-20 16:56:19 +08:00
Preston Van Loon
3591f85a66 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-05-19 12:34:58 -05:00
terence tsao
6ba5ad0325 Altair: align to alpha.4 release (#8900) 2021-05-18 11:14:56 -07:00
Preston Van Loon
76b16a8989 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-05-18 12:41:43 -05:00
terence tsao
74a19741b4 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-05-18 09:16:24 -07:00
nisdas
fdb68c482e Merge branch 'develop' of https://github.com/prysmaticlabs/geth-sharding into hf1 2021-05-18 13:23:49 +08:00
terence tsao
b51729bd2f Merge branch 'hf1' of github.com:prysmaticlabs/prysm into hf1 2021-05-17 14:08:26 -07:00
terence tsao
aef1269223 Sync with develop, remove gogo 2021-05-17 14:08:18 -07:00
terence tsao
9fc1683ec7 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-05-17 12:01:34 -07:00
terence tsao
3790c5edb2 Altair: Add validator helpers for sync committee (#8891)
* Add validator helpers for sync committee

* Fix `TestAssignedToSyncCommittee`

* Update beacon-chain/core/altair/sync_committee.go

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

* Better error message

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-05-17 13:53:38 -05:00
terence tsao
c6c7f8234d Altair: sync committee cache (#8884)
* Starting sync committee cache

* Update index position in committee

* Better comments and tests

* Go fmt

* Manually update BUILD.bazel

* Missing a comma with gazelle

* Unhandle error

* Add cache disabled for fuzzing

* Better place for to lock
2021-05-17 18:23:52 +00:00
terence tsao
c66ea88da8 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-05-17 10:33:04 -07:00
terence tsao
9a8facd76b Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-05-13 10:54:26 -07:00
terence tsao
ca7e0e4807 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-05-12 16:10:44 -07:00
terence tsao
6acedb7dfd Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-05-10 09:41:15 -07:00
terence tsao
a3183bc33e Add SyncCommitteeSigningData Protobuf (#8870) 2021-05-07 17:35:39 +00:00
terence tsao
f6caf627e1 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-05-06 22:25:41 -07:00
Victor Farazdagi
fa696a883d Altair: "sanity" spec tests (#8831)
* Altair: "sanity" spec tests

* Apply suggestions from code review

Co-authored-by: terence tsao <terence@prysmaticlabs.com>

* fix imports

* update cache disable

Co-authored-by: terence tsao <terence@prysmaticlabs.com>
2021-05-03 22:19:22 +03:00
terence tsao
cbbf188637 Fix an epoch offset for sync committee rotation (#8857)
* Fix an epoch offset for sync committee rotation

* Regression condition
2021-05-03 21:53:59 +03:00
terence tsao
4d3e65bdcd Altair: Fix field roots computations (#8856)
* Fix sync committee and participation roots

* Skip HTR test because generic fssz impelemntation is wrong

* Gazelle

* Update beacon-chain/state/state-altair/field_root_sync_committee.go

Co-authored-by: Victor Farazdagi <simple.square@gmail.com>
2021-05-03 11:23:01 +03:00
terence tsao
0be2bde4cc Altair: Add Eth2FastAggregateVerify (#8836)
* Add

* Add test

* Add stub

* Add stub
2021-04-30 08:35:51 +02:00
terence tsao
d5662556bc Use process inactivity updates (#8841) 2021-04-30 08:28:46 +02:00
terence tsao
26a10ca56e Merge branch 'hf1' of github.com:prysmaticlabs/prysm into hf1 2021-04-28 07:20:52 -07:00
terence tsao
bda70352ca Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-04-28 07:20:33 -07:00
Victor Farazdagi
fbd45dbf50 Altair: "epoch_processing" spec tests (#8806)
* effective_balance_updates tests

* eth1_data_reset tests

* historical_roots_update tests

* justification_and_finalization tests

* randao_mixes_reset tests

* registry -> registry_updates

* registry_updates tests

* rewards_and_penalties tests

* slashings and slashings_reset tests
2021-04-28 17:15:21 +03:00
Victor Farazdagi
119ef0f8fa Merge branch 'develop' into hf1 2021-04-27 22:20:04 +03:00
Victor Farazdagi
04f38324ba Altair: "rewards" spec tests (#8818)
* Altair: "rewards" spec tests

* better listing of tests

* update RunPrecomputeRewardsAndPenaltiesTests

* remove redundant code
2021-04-27 22:19:25 +03:00
terence tsao
fa27b6e24c Apply inactivity when validator is slashed (#8820)
Co-authored-by: Victor Farazdagi <simple.square@gmail.com>
2021-04-27 09:22:19 +03:00
terence tsao
fe647e99fc Move ProcessInactivityScores outside of ProcessRewards (#8813)
* Move ProcessInactivityScores out of rewards

* Fix tests
2021-04-27 07:57:25 +03:00
terence tsao
bbcaa7eaf2 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-04-25 08:44:34 -07:00
terence tsao
1c1b2eb811 Fix precision (#8808) 2021-04-23 13:08:28 -07:00
Victor Farazdagi
427e792073 Altair: "operations" spec tests (#8795)
* altair/operations/attestation test

* altair/operations/proposer_slashing tests

* altair/operations/block_header tests

* altair/operations/deposit tests

* altair/operations/proposer_slashing tests

* altair/operations/voluntary_exit tests

* ignoring minimal/altair for time being
2021-04-23 17:40:15 +03:00
Victor Farazdagi
463481febe Merge branch 'develop' into hf1 2021-04-23 15:14:15 +03:00
Victor Farazdagi
6e41923388 Merge branch 'develop' into hf1 2021-04-22 20:20:16 +03:00
Victor Farazdagi
17798f878a Merge branch 'develop' into hf1 2021-04-22 18:21:27 +03:00
terence tsao
d502f0825a Altair: ExecuteStateTransitionNoVerifyAnySig for state transition (#8796) 2021-04-21 14:29:00 -07:00
terence tsao
96fe2b76bf Altair: base reward implementation (#8797)
* Add altair basereward

* Test
2021-04-21 23:05:21 +03:00
terence tsao
a51a4ca9eb Merge branch 'hf1' of github.com:prysmaticlabs/prysm into hf1 2021-04-21 09:34:36 -07:00
terence tsao
9dd8a1737c Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-04-21 07:50:14 -07:00
Victor Farazdagi
c97f74ccef Merge branch 'develop' into hf1 2021-04-21 14:24:26 +03:00
terence tsao
806a923974 Altair: Add ProcessBlockNoVerifyAnySig (#8784) 2021-04-19 12:02:54 -07:00
terence tsao
4b4c2b97b7 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-04-16 14:49:33 -07:00
terence tsao
9d22ea840e Altair: Implement ProcessSlots and tests (#8774) 2021-04-16 09:09:22 -07:00
terence tsao
8a507d749a Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-04-15 14:19:24 -07:00
terence tsao
2850581611 Altair: Implement process epoch (#8772) 2021-04-15 09:06:39 -07:00
terence tsao
59bc0c679c Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-04-14 09:38:46 -07:00
terence tsao
969dec8ad2 Altair: Add SetInactivityScores and test (#8762)
* Starting epoch precompute Altair

* Add ProcessRewardsAndPenaltiesPrecompute and tests

* Apply suggestions from code review

* remove redundant err checking

* combine params

* gazelle

* Update beacon-chain/core/altair/epoch_precompute.go

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

* Update beacon-chain/core/altair/epoch_precompute.go

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

* Named returns

* Combine function parameters

* Fix ineffectual asssignment

* Add process_inactivity_updates and test

* Fix ordering

Co-authored-by: Victor Farazdagi <simple.square@gmail.com>
Co-authored-by: Radosław Kapka <rkapka@wp.pl>
2021-04-13 13:19:33 -05:00
terence tsao
91fb8eea8c Altair: add modified process rewards and penalties (#8753) 2021-04-13 10:37:32 -07:00
terence tsao
e7ebdb11be Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-04-13 09:55:28 -07:00
terence tsao
ff3bb0aa8a Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-04-12 12:31:07 -07:00
terence tsao
5945849cb4 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-04-11 14:35:25 -07:00
terence tsao
3435a61413 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-04-09 17:00:24 -07:00
terence tsao
a3b69600ef Altair: Slashing for block and epoch (#8732) 2021-04-09 16:41:08 -07:00
terence tsao
01841434ec Add ProcessParticipationFlagUpdates (#8731) 2021-04-09 13:44:23 -05:00
terence tsao
f60edb055c Altair: process attestation for block (#8729) 2021-04-08 20:53:16 -07:00
terence tsao
ee3d106a36 Altair: Process sync committee updates for epoch transition (#8728) 2021-04-08 12:53:07 -07:00
terence tsao
9b41a069eb Altair: Process sync committee (#8721) 2021-04-08 06:37:02 -07:00
terence tsao
dc1d5b778b Altair: Sync committee helpers (#8717)
* Add sync commitee helpers

* Remove extra i++
2021-04-07 16:44:24 +03:00
terence tsao
224b92781f Add Altair state trie black box tests (#8716) 2021-04-06 17:22:08 -07:00
terence tsao
6f54a9d057 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-04-06 09:49:59 -07:00
terence tsao
7906e571a8 Altair: genesis state (#8713) 2021-04-06 07:54:09 -07:00
terence tsao
458817d5ad Altair: Process deposits (#8712) 2021-04-05 13:57:20 -07:00
terence tsao
06290c6805 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-04-05 09:57:05 -07:00
terence tsao
1adf1f1bef Merge commit '9aa2dd1ae65a1c31bdc61413282871d7df8b1e8f' into hf1 2021-04-01 11:38:18 -07:00
terence tsao
af57cf5e96 Merge commit 'fe4a852e786f01eed02293f4578cd7a4f5e8bc4d' into hf1 2021-04-01 11:38:06 -07:00
terence tsao
d59ba818f0 Merge commit '3d405910e7d16c1af315097a74f0b8682a9a1eeb' into hf1 2021-04-01 11:33:30 -07:00
terence tsao
9aa2dd1ae6 Part of 3 of beacon state Altair pkg - copy and hash tree root (#8690) 2021-03-31 09:39:02 -07:00
terence tsao
f3abe70838 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-03-30 16:46:22 -07:00
terence tsao
fe4a852e78 Part of 2 of beacon state Altair pkg - getters and setters (#8658) 2021-03-30 16:35:54 -07:00
terence tsao
6af0f619c9 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-03-29 06:55:46 -07:00
terence tsao
3d405910e7 Part of 1 of beacon state Altair pkg (#8670) 2021-03-25 10:49:39 -07:00
terence tsao
2779daee32 Sync with develop 2021-03-25 09:57:35 -07:00
terence tsao
a0ba4a8563 Sync with develop 2021-03-25 09:50:02 -07:00
terence tsao
926b3725a1 Part of 1 of beacon state Altair pkg (#8652)
* Part 1 of stateAltair pkg- trie and partial field root

* Gazelle

* Sync with develop

* Update visibility
2021-03-24 13:25:38 +00:00
terence tsao
5cc9f4df0b Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-03-23 15:03:05 -07:00
terence tsao
fd297999b8 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-03-23 14:01:16 -07:00
terence tsao
0d45eeac56 Add altair config (#8642)
* Add altair config

* Add domain config and fix test

* Remove old configs

* Use Altair
2021-03-22 20:50:30 -07:00
terence tsao
e2fcd25039 Rename v1 to altair. Add inactivity_scores field (#8641) 2021-03-22 20:50:19 -07:00
terence tsao
2436d84370 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-03-22 09:47:23 -07:00
terence tsao
5418d8c367 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-03-19 13:21:40 -07:00
terence tsao
55e5dee7ab Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-03-18 21:02:40 -07:00
terence tsao
6a06a4bf98 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-03-18 07:08:04 -07:00
terence tsao
a9d981dce1 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-03-17 07:57:24 -07:00
terence tsao
a69947ba51 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-03-16 11:22:08 -07:00
terence tsao
6a32b18ca9 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-03-15 07:47:52 -07:00
terence tsao
9ebf8651b4 Merge branch 'hf1' of github.com:prysmaticlabs/prysm into hf1 2021-03-15 07:47:45 -07:00
terence tsao
8467485aec Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-03-12 13:22:52 -08:00
terence tsao
fdb6cf9b57 HF1: Beacon state protobuf definition (#8581) 2021-03-11 15:51:33 -08:00
terence tsao
3da55ad7a4 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-03-11 06:17:53 -08:00
terence tsao
773d561361 Merge branch 'develop' of github.com:prysmaticlabs/prysm into hf1 2021-03-09 10:13:12 -08:00
terence tsao
7f6d3ccb36 HF1: Add penalty config values (#8522)
* Add new configs

* More tests

* Fix message name
2021-02-25 14:59:47 -06:00
1272 changed files with 73869 additions and 51053 deletions

0
.bazelignore Normal file
View File

View File

@@ -24,11 +24,6 @@ build --sandbox_default_allow_network=false
build --workspace_status_command=./scripts/workspace_status.sh
build --stamp
# Use mainnet protobufs at runtime
run --define ssz=mainnet
test --define ssz=mainnet
build --define ssz=mainnet
# Prevent PATH changes from rebuilding when switching from IDE to command line.
build --incompatible_strict_action_env
test --incompatible_strict_action_env

View File

@@ -31,6 +31,10 @@ jobs:
with:
goimports-path: ./
- name: Gosec security scanner
uses: securego/gosec@master
with:
args: '-exclude-dir=shared/bls/herumi ./...'
build:
name: Build
runs-on: ubuntu-latest

View File

@@ -197,6 +197,8 @@ filegroup(
url = "https://github.com/eth2-clients/slashing-protection-interchange-tests/archive/b8413ca42dc92308019d0d4db52c87e9e125c4e9.tar.gz",
)
eth2_spec_version = "v1.1.0-beta.1"
http_archive(
name = "eth2_spec_tests_general",
build_file_content = """
@@ -209,8 +211,8 @@ filegroup(
visibility = ["//visibility:public"],
)
""",
sha256 = "deacc076365c727d653ac064894ecf0d1b0a675d86704dc8de271259f6a7314b",
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v1.1.0-alpha.3/general.tar.gz",
sha256 = "e9b4cc60a3e676c6b4a9348424e44cff1ebada603ffb31b0df600dbd70e7fbf6",
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/%s/general.tar.gz" % eth2_spec_version,
)
http_archive(
@@ -225,8 +227,8 @@ filegroup(
visibility = ["//visibility:public"],
)
""",
sha256 = "6e9886af3d2f024e563249d70388129e28e3e92f742f289238ed9b7ec7a7f930",
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v1.1.0-alpha.3/minimal.tar.gz",
sha256 = "cf82dc729ffe7b924f852e57d1973e1a6377c5b52acc903c953277fa9b4e6de8",
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/%s/minimal.tar.gz" % eth2_spec_version,
)
http_archive(
@@ -241,8 +243,24 @@ filegroup(
visibility = ["//visibility:public"],
)
""",
sha256 = "a7b3d0ffc02a567250f424d69b2474fdc9477cd56eada60af7474560b46a8527",
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v1.1.0-alpha.3/mainnet.tar.gz",
sha256 = "6c6792375b81858037014e282d28a64b0cf12e12daf16054265c85403b8b329f",
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/%s/mainnet.tar.gz" % eth2_spec_version,
)
http_archive(
name = "eth2_spec",
build_file_content = """
filegroup(
name = "spec_data",
srcs = glob([
"**/*.yaml",
]),
visibility = ["//visibility:public"],
)
""",
sha256 = "16094dad1bab4e8ab3adb60c10e311cd1e294cd7bbf5a89505f24bebd3d0e513",
strip_prefix = "eth2.0-specs-" + eth2_spec_version[1:],
url = "https://github.com/ethereum/eth2.0-specs/archive/refs/tags/%s.tar.gz" % eth2_spec_version,
)
http_archive(

View File

@@ -5,6 +5,7 @@ go_library(
srcs = [
"chain_info.go",
"head.go",
"head_sync_committee_info.go",
"info.go",
"init_sync_process_block.go",
"log.go",
@@ -26,6 +27,7 @@ go_library(
deps = [
"//beacon-chain/cache:go_default_library",
"//beacon-chain/cache/depositcache:go_default_library",
"//beacon-chain/core/altair:go_default_library",
"//beacon-chain/core/epoch/precompute:go_default_library",
"//beacon-chain/core/feed:go_default_library",
"//beacon-chain/core/feed/state:go_default_library",
@@ -40,13 +42,13 @@ go_library(
"//beacon-chain/operations/voluntaryexits:go_default_library",
"//beacon-chain/p2p:go_default_library",
"//beacon-chain/powchain:go_default_library",
"//beacon-chain/state/interface:go_default_library",
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/stategen:go_default_library",
"//beacon-chain/state/v2:go_default_library",
"//cmd/beacon-chain/flags:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//proto/eth/v1:go_default_library",
"//proto/eth/v1alpha1:go_default_library",
"//proto/interfaces:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//proto/prysm/v1alpha1/block:go_default_library",
"//shared/attestationutil:go_default_library",
"//shared/bls:go_default_library",
"//shared/bytesutil:go_default_library",
@@ -57,7 +59,9 @@ go_library(
"//shared/slotutil:go_default_library",
"//shared/timeutils:go_default_library",
"//shared/traceutil:go_default_library",
"//shared/version:go_default_library",
"@com_github_emicklei_dot//:go_default_library",
"@com_github_hashicorp_golang_lru//: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",
@@ -107,10 +111,8 @@ go_test(
"//beacon-chain/powchain:go_default_library",
"//beacon-chain/state/stateutil:go_default_library",
"//beacon-chain/state/v1:go_default_library",
"//proto/beacon/db:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//proto/eth/v1alpha1:go_default_library",
"//proto/eth/v1alpha1/wrapper:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//proto/prysm/v1alpha1/wrapper:go_default_library",
"//shared/bytesutil:go_default_library",
"//shared/event:go_default_library",
"//shared/params:go_default_library",
@@ -158,9 +160,8 @@ go_test(
"//beacon-chain/db/testing:go_default_library",
"//beacon-chain/p2p:go_default_library",
"//beacon-chain/powchain:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//proto/eth/v1alpha1:go_default_library",
"//proto/eth/v1alpha1/wrapper:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//proto/prysm/v1alpha1/wrapper:go_default_library",
"//shared/bytesutil:go_default_library",
"//shared/event:go_default_library",
"//shared/params:go_default_library",

View File

@@ -7,10 +7,9 @@ import (
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/interfaces"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/copyutil"
"github.com/prysmaticlabs/prysm/shared/params"
@@ -25,6 +24,8 @@ type ChainInfoFetcher interface {
GenesisFetcher
CanonicalFetcher
ForkFetcher
TimeFetcher
HeadDomainFetcher
}
// TimeFetcher retrieves the Ethereum consensus data that's related to time.
@@ -43,19 +44,23 @@ type GenesisFetcher interface {
type HeadFetcher interface {
HeadSlot() types.Slot
HeadRoot(ctx context.Context) ([]byte, error)
HeadBlock(ctx context.Context) (interfaces.SignedBeaconBlock, error)
HeadState(ctx context.Context) (iface.BeaconState, error)
HeadBlock(ctx context.Context) (block.SignedBeaconBlock, error)
HeadState(ctx context.Context) (state.BeaconState, error)
HeadValidatorsIndices(ctx context.Context, epoch types.Epoch) ([]types.ValidatorIndex, error)
HeadSeed(ctx context.Context, epoch types.Epoch) ([32]byte, error)
HeadGenesisValidatorRoot() [32]byte
HeadETH1Data() *ethpb.Eth1Data
HeadPublicKeyToValidatorIndex(ctx context.Context, pubKey [48]byte) (types.ValidatorIndex, bool)
HeadValidatorIndexToPublicKey(ctx context.Context, index types.ValidatorIndex) ([48]byte, error)
ProtoArrayStore() *protoarray.Store
ChainHeads() ([][32]byte, []types.Slot)
HeadSyncCommitteeFetcher
HeadDomainFetcher
}
// ForkFetcher retrieves the current fork information of the Ethereum beacon chain.
type ForkFetcher interface {
CurrentFork() *pb.Fork
CurrentFork() *ethpb.Fork
}
// CanonicalFetcher retrieves the current chain's canonical information.
@@ -140,7 +145,7 @@ func (s *Service) HeadRoot(ctx context.Context) ([]byte, error) {
// HeadBlock returns the head block of the chain.
// If the head is nil from service struct,
// it will attempt to get the head block from DB.
func (s *Service) HeadBlock(ctx context.Context) (interfaces.SignedBeaconBlock, error) {
func (s *Service) HeadBlock(ctx context.Context) (block.SignedBeaconBlock, error) {
s.headLock.RLock()
defer s.headLock.RUnlock()
@@ -154,7 +159,7 @@ func (s *Service) HeadBlock(ctx context.Context) (interfaces.SignedBeaconBlock,
// HeadState returns the head state of the chain.
// If the head is nil from service struct,
// it will attempt to get the head state from DB.
func (s *Service) HeadState(ctx context.Context) (iface.BeaconState, error) {
func (s *Service) HeadState(ctx context.Context) (state.BeaconState, error) {
ctx, span := trace.StartSpan(ctx, "blockChain.HeadState")
defer span.End()
s.headLock.RLock()
@@ -239,12 +244,12 @@ func (s *Service) GenesisValidatorRoot() [32]byte {
}
// CurrentFork retrieves the latest fork information of the beacon chain.
func (s *Service) CurrentFork() *pb.Fork {
func (s *Service) CurrentFork() *ethpb.Fork {
s.headLock.RLock()
defer s.headLock.RUnlock()
if !s.hasHeadState() {
return &pb.Fork{
return &ethpb.Fork{
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
}
@@ -284,3 +289,23 @@ func (s *Service) ChainHeads() ([][32]byte, []types.Slot) {
return headsRoots, headsSlots
}
// HeadPublicKeyToValidatorIndex returns the validator index of the `pubkey` in current head state.
func (s *Service) HeadPublicKeyToValidatorIndex(ctx context.Context, pubKey [48]byte) (types.ValidatorIndex, bool) {
s.headLock.RLock()
defer s.headLock.RUnlock()
return s.headState(ctx).ValidatorIndexByPubkey(pubKey)
}
// HeadValidatorIndexToPublicKey returns the pubkey of the validator `index` in current head state.
func (s *Service) HeadValidatorIndexToPublicKey(ctx context.Context, index types.ValidatorIndex) ([48]byte, error) {
s.headLock.RLock()
defer s.headLock.RUnlock()
v, err := s.headState(ctx).ValidatorAtIndexReadOnly(index)
if err != nil {
return [48]byte{}, err
}
return v.PublicKey(), nil
}

View File

@@ -6,8 +6,8 @@ import (
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/eth/v1alpha1/wrapper"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
)

View File

@@ -9,10 +9,9 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
"github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/eth/v1alpha1/wrapper"
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
@@ -105,7 +104,7 @@ func TestPrevJustifiedCheckpt_GenesisRootOk(t *testing.T) {
func TestHeadSlot_CanRetrieve(t *testing.T) {
c := &Service{}
s, err := v1.InitializeFromProto(&pb.BeaconState{})
s, err := v1.InitializeFromProto(&ethpb.BeaconState{})
require.NoError(t, err)
c.head = &head{slot: 100, state: s}
assert.Equal(t, types.Slot(100), c.HeadSlot())
@@ -127,7 +126,7 @@ func TestHeadRoot_UseDB(t *testing.T) {
br, err := b.Block.HashTreeRoot()
require.NoError(t, err)
require.NoError(t, beaconDB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(b)))
require.NoError(t, beaconDB.SaveStateSummary(context.Background(), &pb.StateSummary{Root: br[:]}))
require.NoError(t, beaconDB.SaveStateSummary(context.Background(), &ethpb.StateSummary{Root: br[:]}))
require.NoError(t, beaconDB.SaveHeadBlockRoot(context.Background(), br))
r, err := c.HeadRoot(context.Background())
require.NoError(t, err)
@@ -137,7 +136,7 @@ func TestHeadRoot_UseDB(t *testing.T) {
func TestHeadBlock_CanRetrieve(t *testing.T) {
b := testutil.NewBeaconBlock()
b.Block.Slot = 1
s, err := v1.InitializeFromProto(&pb.BeaconState{})
s, err := v1.InitializeFromProto(&ethpb.BeaconState{})
require.NoError(t, err)
c := &Service{}
c.head = &head{block: wrapper.WrappedPhase0SignedBeaconBlock(b), state: s}
@@ -148,7 +147,7 @@ func TestHeadBlock_CanRetrieve(t *testing.T) {
}
func TestHeadState_CanRetrieve(t *testing.T) {
s, err := v1.InitializeFromProto(&pb.BeaconState{Slot: 2, GenesisValidatorsRoot: params.BeaconConfig().ZeroHash[:]})
s, err := v1.InitializeFromProto(&ethpb.BeaconState{Slot: 2, GenesisValidatorsRoot: params.BeaconConfig().ZeroHash[:]})
require.NoError(t, err)
c := &Service{}
c.head = &head{state: s}
@@ -164,8 +163,8 @@ func TestGenesisTime_CanRetrieve(t *testing.T) {
}
func TestCurrentFork_CanRetrieve(t *testing.T) {
f := &pb.Fork{Epoch: 999}
s, err := v1.InitializeFromProto(&pb.BeaconState{Fork: f})
f := &ethpb.Fork{Epoch: 999}
s, err := v1.InitializeFromProto(&ethpb.BeaconState{Fork: f})
require.NoError(t, err)
c := &Service{}
c.head = &head{state: s}
@@ -175,7 +174,7 @@ func TestCurrentFork_CanRetrieve(t *testing.T) {
}
func TestCurrentFork_NilHeadSTate(t *testing.T) {
f := &pb.Fork{
f := &ethpb.Fork{
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
}
@@ -190,7 +189,7 @@ func TestGenesisValidatorRoot_CanRetrieve(t *testing.T) {
c := &Service{}
assert.Equal(t, [32]byte{}, c.GenesisValidatorRoot(), "Did not get correct genesis validator root")
s, err := v1.InitializeFromProto(&pb.BeaconState{GenesisValidatorsRoot: []byte{'a'}})
s, err := v1.InitializeFromProto(&ethpb.BeaconState{GenesisValidatorsRoot: []byte{'a'}})
require.NoError(t, err)
c.head = &head{state: s}
assert.Equal(t, [32]byte{'a'}, c.GenesisValidatorRoot(), "Did not get correct genesis validator root")
@@ -204,7 +203,7 @@ func TestHeadETH1Data_Nil(t *testing.T) {
func TestHeadETH1Data_CanRetrieve(t *testing.T) {
d := &ethpb.Eth1Data{DepositCount: 999}
s, err := v1.InitializeFromProto(&pb.BeaconState{Eth1Data: d})
s, err := v1.InitializeFromProto(&ethpb.BeaconState{Eth1Data: d})
require.NoError(t, err)
c := &Service{}
c.head = &head{state: s}
@@ -297,3 +296,33 @@ func TestService_ChainHeads(t *testing.T) {
require.DeepEqual(t, [][32]byte{{'c'}, {'d'}, {'e'}}, roots)
require.DeepEqual(t, []types.Slot{102, 103, 104}, slots)
}
func TestService_HeadPublicKeyToValidatorIndex(t *testing.T) {
s, _ := testutil.DeterministicGenesisState(t, 10)
c := &Service{}
c.head = &head{state: s}
_, e := c.HeadPublicKeyToValidatorIndex(context.Background(), [48]byte{})
require.Equal(t, false, e)
v, err := s.ValidatorAtIndex(0)
require.NoError(t, err)
i, e := c.HeadPublicKeyToValidatorIndex(context.Background(), bytesutil.ToBytes48(v.PublicKey))
require.Equal(t, true, e)
require.Equal(t, types.ValidatorIndex(0), i)
}
func TestService_HeadValidatorIndexToPublicKey(t *testing.T) {
s, _ := testutil.DeterministicGenesisState(t, 10)
c := &Service{}
c.head = &head{state: s}
p, err := c.HeadValidatorIndexToPublicKey(context.Background(), 0)
require.NoError(t, err)
v, err := s.ValidatorAtIndex(0)
require.NoError(t, err)
require.Equal(t, bytesutil.ToBytes48(v.PublicKey), p)
}

View File

@@ -11,9 +11,9 @@ import (
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
ethpbv1 "github.com/prysmaticlabs/prysm/proto/eth/v1"
"github.com/prysmaticlabs/prysm/proto/interfaces"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/slotutil"
@@ -23,10 +23,10 @@ import (
// This defines the current chain service's view of head.
type head struct {
slot types.Slot // current head slot.
root [32]byte // current head root.
block interfaces.SignedBeaconBlock // current head block.
state iface.BeaconState // current head state.
slot types.Slot // current head slot.
root [32]byte // current head root.
block block.SignedBeaconBlock // current head block.
state state.BeaconState // current head state.
}
// Determined the head from the fork choice service and saves its new data
@@ -168,7 +168,7 @@ func (s *Service) saveHead(ctx context.Context, headRoot [32]byte) error {
// This gets called to update canonical root mapping. It does not save head block
// 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 interfaces.SignedBeaconBlock, r [32]byte, hs iface.BeaconState) error {
func (s *Service) saveHeadNoDB(ctx context.Context, b block.SignedBeaconBlock, r [32]byte, hs state.BeaconState) error {
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
return err
}
@@ -185,7 +185,7 @@ func (s *Service) saveHeadNoDB(ctx context.Context, b interfaces.SignedBeaconBlo
}
// This sets head view object which is used to track the head slot, root, block and state.
func (s *Service) setHead(root [32]byte, block interfaces.SignedBeaconBlock, state iface.BeaconState) {
func (s *Service) setHead(root [32]byte, block block.SignedBeaconBlock, state state.BeaconState) {
s.headLock.Lock()
defer s.headLock.Unlock()
@@ -201,7 +201,7 @@ func (s *Service) setHead(root [32]byte, block interfaces.SignedBeaconBlock, sta
// This sets head view object which is used to track the head slot, root, block and state. The method
// assumes that state being passed into the method will not be modified by any other alternate
// caller which holds the state's reference.
func (s *Service) setHeadInitialSync(root [32]byte, block interfaces.SignedBeaconBlock, state iface.BeaconState) {
func (s *Service) setHeadInitialSync(root [32]byte, block block.SignedBeaconBlock, state state.BeaconState) {
s.headLock.Lock()
defer s.headLock.Unlock()
@@ -234,14 +234,14 @@ func (s *Service) headRoot() [32]byte {
// This returns the head block.
// It does a full copy on head block for immutability.
// This is a lock free version.
func (s *Service) headBlock() interfaces.SignedBeaconBlock {
func (s *Service) headBlock() block.SignedBeaconBlock {
return s.head.block.Copy()
}
// This returns the head state.
// It does a full copy on head state for immutability.
// This is a lock free version.
func (s *Service) headState(ctx context.Context) iface.BeaconState {
func (s *Service) headState(ctx context.Context) state.BeaconState {
ctx, span := trace.StartSpan(ctx, "blockChain.headState")
defer span.End()
@@ -268,7 +268,7 @@ func (s *Service) cacheJustifiedStateBalances(ctx context.Context, justifiedRoot
s.clearInitSyncBlocks()
var justifiedState iface.BeaconState
var justifiedState state.BeaconState
var err error
if justifiedRoot == s.genesisRoot {
justifiedState, err = s.cfg.BeaconDB.GenesisState(ctx)
@@ -288,7 +288,7 @@ func (s *Service) cacheJustifiedStateBalances(ctx context.Context, justifiedRoot
epoch := helpers.CurrentEpoch(justifiedState)
justifiedBalances := make([]uint64, justifiedState.NumValidators())
if err := justifiedState.ReadFromEveryValidator(func(idx int, val iface.ReadOnlyValidator) error {
if err := justifiedState.ReadFromEveryValidator(func(idx int, val state.ReadOnlyValidator) error {
if helpers.IsActiveValidatorUsingTrie(val, epoch) {
justifiedBalances[idx] = val.EffectiveBalance()
} else {
@@ -315,7 +315,7 @@ func (s *Service) getJustifiedBalances() []uint64 {
// chain head is determined, set, and saved to disk.
func (s *Service) notifyNewHeadEvent(
newHeadSlot types.Slot,
newHeadState iface.BeaconState,
newHeadState state.BeaconState,
newHeadStateRoot,
newHeadRoot []byte,
) error {

View File

@@ -0,0 +1,188 @@
package blockchain
import (
"context"
"sync"
lru "github.com/hashicorp/golang-lru"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core/altair"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
core "github.com/prysmaticlabs/prysm/beacon-chain/core/state"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state/v2"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/params"
)
// HeadSyncCommitteeFetcher is the interface that wraps the head sync committee related functions.
// The head sync committee functions return callers sync committee indices and public keys with respect to current head state.
type HeadSyncCommitteeFetcher interface {
HeadCurrentSyncCommitteeIndices(ctx context.Context, index types.ValidatorIndex, slot types.Slot) ([]types.CommitteeIndex, error)
HeadNextSyncCommitteeIndices(ctx context.Context, index types.ValidatorIndex, slot types.Slot) ([]types.CommitteeIndex, error)
HeadSyncCommitteePubKeys(ctx context.Context, slot types.Slot, committeeIndex types.CommitteeIndex) ([][]byte, error)
}
// HeadDomainFetcher is the interface that wraps the head sync domain related functions.
// The head sync committee domain functions return callers domain data with respect to slot and head state.
type HeadDomainFetcher interface {
HeadSyncCommitteeDomain(ctx context.Context, slot types.Slot) ([]byte, error)
HeadSyncSelectionProofDomain(ctx context.Context, slot types.Slot) ([]byte, error)
HeadSyncContributionProofDomain(ctx context.Context, slot types.Slot) ([]byte, error)
}
// HeadSyncCommitteeDomain returns the head sync committee domain using current head state advanced up to `slot`.
func (s *Service) HeadSyncCommitteeDomain(ctx context.Context, slot types.Slot) ([]byte, error) {
s.headLock.RLock()
defer s.headLock.RUnlock()
return s.domainWithHeadState(ctx, slot, params.BeaconConfig().DomainSyncCommittee)
}
// HeadSyncSelectionProofDomain returns the head sync committee domain using current head state advanced up to `slot`.
func (s *Service) HeadSyncSelectionProofDomain(ctx context.Context, slot types.Slot) ([]byte, error) {
s.headLock.RLock()
defer s.headLock.RUnlock()
return s.domainWithHeadState(ctx, slot, params.BeaconConfig().DomainSyncCommitteeSelectionProof)
}
// HeadSyncContributionProofDomain returns the head sync committee domain using current head state advanced up to `slot`.
func (s *Service) HeadSyncContributionProofDomain(ctx context.Context, slot types.Slot) ([]byte, error) {
s.headLock.RLock()
defer s.headLock.RUnlock()
return s.domainWithHeadState(ctx, slot, params.BeaconConfig().DomainContributionAndProof)
}
// HeadCurrentSyncCommitteeIndices returns the input validator `index`'s position indices in the current sync committee with respect to `slot`.
// Head state advanced up to `slot` is used for calculation.
func (s *Service) HeadCurrentSyncCommitteeIndices(ctx context.Context, index types.ValidatorIndex, slot types.Slot) ([]types.CommitteeIndex, error) {
s.headLock.RLock()
defer s.headLock.RUnlock()
headState, err := s.getSyncCommitteeHeadState(ctx, slot)
if err != nil {
return nil, err
}
return helpers.CurrentPeriodSyncSubcommitteeIndices(headState, index)
}
// HeadNextSyncCommitteeIndices returns the input validator `index`'s position indices in the next sync committee with respect to `slot`.
// Head state advanced up to `slot` is used for calculation.
func (s *Service) HeadNextSyncCommitteeIndices(ctx context.Context, index types.ValidatorIndex, slot types.Slot) ([]types.CommitteeIndex, error) {
s.headLock.RLock()
defer s.headLock.RUnlock()
headState, err := s.getSyncCommitteeHeadState(ctx, slot)
if err != nil {
return nil, err
}
return helpers.NextPeriodSyncSubcommitteeIndices(headState, index)
}
// HeadSyncCommitteePubKeys returns the head sync committee public keys with respect to `slot` and subcommittee index `committeeIndex`.
// Head state advanced up to `slot` is used for calculation.
func (s *Service) HeadSyncCommitteePubKeys(ctx context.Context, slot types.Slot, committeeIndex types.CommitteeIndex) ([][]byte, error) {
s.headLock.RLock()
defer s.headLock.RUnlock()
headState, err := s.getSyncCommitteeHeadState(ctx, slot)
if err != nil {
return nil, err
}
nextSlotEpoch := helpers.SlotToEpoch(headState.Slot() + 1)
currEpoch := helpers.SlotToEpoch(headState.Slot())
var syncCommittee *ethpb.SyncCommittee
if helpers.SyncCommitteePeriod(currEpoch) == helpers.SyncCommitteePeriod(nextSlotEpoch) {
syncCommittee, err = headState.CurrentSyncCommittee()
if err != nil {
return nil, err
}
} else {
syncCommittee, err = headState.NextSyncCommittee()
if err != nil {
return nil, err
}
}
return altair.SyncSubCommitteePubkeys(syncCommittee, committeeIndex)
}
// returns calculated domain using input `domain` and `slot`.
func (s *Service) domainWithHeadState(ctx context.Context, slot types.Slot, domain [4]byte) ([]byte, error) {
headState, err := s.getSyncCommitteeHeadState(ctx, slot)
if err != nil {
return nil, err
}
return helpers.Domain(headState.Fork(), helpers.SlotToEpoch(headState.Slot()), domain, headState.GenesisValidatorRoot())
}
// returns the head state that is advanced up to `slot`. It utilizes the cache `syncCommitteeHeadState` by retrieving using `slot` as key.
// For the cache miss, it processes head state up to slot and fill the cache with `slot` as key.
func (s *Service) getSyncCommitteeHeadState(ctx context.Context, slot types.Slot) (state.BeaconState, error) {
var headState state.BeaconState
var err error
// If there's already a head state exists with the request slot, we don't need to process slots.
cachedState := syncCommitteeHeadStateCache.get(slot)
if cachedState != nil && !cachedState.IsNil() {
syncHeadStateHit.Inc()
headState = cachedState
} else {
headState, err = s.HeadState(ctx)
if err != nil {
return nil, err
}
if slot > headState.Slot() {
headState, err = core.ProcessSlots(ctx, headState, slot)
if err != nil {
return nil, err
}
}
syncHeadStateMiss.Inc()
syncCommitteeHeadStateCache.add(slot, headState)
}
return headState, nil
}
var syncCommitteeHeadStateCache = newSyncCommitteeHeadState()
// syncCommitteeHeadState to caches latest head state requested by the sync committee participant.
type syncCommitteeHeadState struct {
cache *lru.Cache
lock sync.RWMutex
}
// newSyncCommitteeHeadState initializes the lru cache for `syncCommitteeHeadState` with size of 1.
func newSyncCommitteeHeadState() *syncCommitteeHeadState {
c, err := lru.New(1) // only need size of 1 to avoid redundant state copy, HTR, and process slots.
if err != nil {
panic(err)
}
return &syncCommitteeHeadState{cache: c}
}
// add `slot` as key and `state` as value onto the lru cache.
func (c *syncCommitteeHeadState) add(slot types.Slot, state state.BeaconState) {
c.lock.Lock()
defer c.lock.Unlock()
c.cache.Add(slot, state)
}
// get `state` using `slot` as key. Return nil if nothing is found.
func (c *syncCommitteeHeadState) get(slot types.Slot) state.BeaconState {
c.lock.RLock()
defer c.lock.RUnlock()
val, exists := c.cache.Get(slot)
if !exists {
return nil
}
if val == nil {
return nil
}
return val.(*stateAltair.BeaconState)
}

View File

@@ -0,0 +1,108 @@
package blockchain
import (
"context"
"testing"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
)
func TestService_HeadCurrentSyncCommitteeIndices(t *testing.T) {
s, _ := testutil.DeterministicGenesisStateAltair(t, params.BeaconConfig().TargetCommitteeSize)
c := &Service{}
c.head = &head{state: s}
// Process slot up to `EpochsPerSyncCommitteePeriod` so it can `ProcessSyncCommitteeUpdates`.
slot := uint64(params.BeaconConfig().EpochsPerSyncCommitteePeriod)*uint64(params.BeaconConfig().SlotsPerEpoch) + 1
indices, err := c.HeadCurrentSyncCommitteeIndices(context.Background(), 0, types.Slot(slot))
require.NoError(t, err)
// NextSyncCommittee becomes CurrentSyncCommittee so it should be empty by default.
require.Equal(t, 0, len(indices))
}
func TestService_HeadNextSyncCommitteeIndices(t *testing.T) {
s, _ := testutil.DeterministicGenesisStateAltair(t, params.BeaconConfig().TargetCommitteeSize)
c := &Service{}
c.head = &head{state: s}
// Process slot up to `EpochsPerSyncCommitteePeriod` so it can `ProcessSyncCommitteeUpdates`.
slot := uint64(params.BeaconConfig().EpochsPerSyncCommitteePeriod)*uint64(params.BeaconConfig().SlotsPerEpoch) + 1
indices, err := c.HeadNextSyncCommitteeIndices(context.Background(), 0, types.Slot(slot))
require.NoError(t, err)
// NextSyncCommittee should be be empty after `ProcessSyncCommitteeUpdates`. Validator should get indices.
require.NotEqual(t, 0, len(indices))
}
func TestService_HeadSyncCommitteePubKeys(t *testing.T) {
s, _ := testutil.DeterministicGenesisStateAltair(t, params.BeaconConfig().TargetCommitteeSize)
c := &Service{}
c.head = &head{state: s}
// Process slot up to 2 * `EpochsPerSyncCommitteePeriod` so it can run `ProcessSyncCommitteeUpdates` twice.
slot := uint64(2*params.BeaconConfig().EpochsPerSyncCommitteePeriod)*uint64(params.BeaconConfig().SlotsPerEpoch) + 1
pubkeys, err := c.HeadSyncCommitteePubKeys(context.Background(), types.Slot(slot), 0)
require.NoError(t, err)
// Any subcommittee should match the subcommittee size.
subCommitteeSize := params.BeaconConfig().SyncCommitteeSize / params.BeaconConfig().SyncCommitteeSubnetCount
require.Equal(t, int(subCommitteeSize), len(pubkeys))
}
func TestService_HeadSyncCommitteeDomain(t *testing.T) {
s, _ := testutil.DeterministicGenesisStateAltair(t, params.BeaconConfig().TargetCommitteeSize)
c := &Service{}
c.head = &head{state: s}
wanted, err := helpers.Domain(s.Fork(), helpers.SlotToEpoch(s.Slot()), params.BeaconConfig().DomainSyncCommittee, s.GenesisValidatorRoot())
require.NoError(t, err)
d, err := c.HeadSyncCommitteeDomain(context.Background(), 0)
require.NoError(t, err)
require.DeepEqual(t, wanted, d)
}
func TestService_HeadSyncContributionProofDomain(t *testing.T) {
s, _ := testutil.DeterministicGenesisStateAltair(t, params.BeaconConfig().TargetCommitteeSize)
c := &Service{}
c.head = &head{state: s}
wanted, err := helpers.Domain(s.Fork(), helpers.SlotToEpoch(s.Slot()), params.BeaconConfig().DomainContributionAndProof, s.GenesisValidatorRoot())
require.NoError(t, err)
d, err := c.HeadSyncContributionProofDomain(context.Background(), 0)
require.NoError(t, err)
require.DeepEqual(t, wanted, d)
}
func TestService_HeadSyncSelectionProofDomain(t *testing.T) {
s, _ := testutil.DeterministicGenesisStateAltair(t, params.BeaconConfig().TargetCommitteeSize)
c := &Service{}
c.head = &head{state: s}
wanted, err := helpers.Domain(s.Fork(), helpers.SlotToEpoch(s.Slot()), params.BeaconConfig().DomainSyncCommitteeSelectionProof, s.GenesisValidatorRoot())
require.NoError(t, err)
d, err := c.HeadSyncSelectionProofDomain(context.Background(), 0)
require.NoError(t, err)
require.DeepEqual(t, wanted, d)
}
func TestSyncCommitteeHeadStateCache_RoundTrip(t *testing.T) {
c := newSyncCommitteeHeadState()
beaconState, _ := testutil.DeterministicGenesisStateAltair(t, 100)
require.NoError(t, beaconState.SetSlot(100))
cachedState := c.get(101)
require.Equal(t, nil, cachedState)
c.add(101, beaconState)
cachedState = c.get(101)
require.DeepEqual(t, beaconState, cachedState)
}

View File

@@ -9,10 +9,9 @@ import (
mock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpbv1 "github.com/prysmaticlabs/prysm/proto/eth/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/eth/v1alpha1/wrapper"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
@@ -60,7 +59,7 @@ func TestSaveHead_Different(t *testing.T) {
headState, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, headState.SetSlot(1))
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(context.Background(), &pb.StateSummary{Slot: 1, Root: newRoot[:]}))
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(context.Background(), &ethpb.StateSummary{Slot: 1, Root: newRoot[:]}))
require.NoError(t, service.cfg.BeaconDB.SaveState(context.Background(), headState, newRoot))
require.NoError(t, service.saveHead(context.Background(), newRoot))
@@ -105,7 +104,7 @@ func TestSaveHead_Different_Reorg(t *testing.T) {
headState, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, headState.SetSlot(1))
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(context.Background(), &pb.StateSummary{Slot: 1, Root: newRoot[:]}))
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(context.Background(), &ethpb.StateSummary{Slot: 1, Root: newRoot[:]}))
require.NoError(t, service.cfg.BeaconDB.SaveState(context.Background(), headState, newRoot))
require.NoError(t, service.saveHead(context.Background(), newRoot))
@@ -127,7 +126,7 @@ func TestCacheJustifiedStateBalances_CanCache(t *testing.T) {
state, _ := testutil.DeterministicGenesisState(t, 100)
r := [32]byte{'a'}
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(context.Background(), &pb.StateSummary{Root: r[:]}))
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(context.Background(), &ethpb.StateSummary{Root: r[:]}))
require.NoError(t, service.cfg.BeaconDB.SaveState(context.Background(), state, r))
require.NoError(t, service.cacheJustifiedStateBalances(context.Background(), r))
require.DeepEqual(t, service.getJustifiedBalances(), state.Balances(), "Incorrect justified balances")

View File

@@ -9,7 +9,7 @@ import (
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
"github.com/prysmaticlabs/prysm/proto/eth/v1alpha1/wrapper"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"

View File

@@ -1,11 +1,11 @@
package blockchain
import (
"github.com/prysmaticlabs/prysm/proto/interfaces"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
)
// This saves a beacon block to the initial sync blocks cache.
func (s *Service) saveInitSyncBlock(r [32]byte, b interfaces.SignedBeaconBlock) {
func (s *Service) saveInitSyncBlock(r [32]byte, b block.SignedBeaconBlock) {
s.initSyncBlocksLock.Lock()
defer s.initSyncBlocksLock.Unlock()
s.initSyncBlocks[r] = b
@@ -22,7 +22,7 @@ func (s *Service) hasInitSyncBlock(r [32]byte) bool {
// This retrieves a beacon block from the initial sync blocks cache using the root of
// the block.
func (s *Service) getInitSyncBlock(r [32]byte) interfaces.SignedBeaconBlock {
func (s *Service) getInitSyncBlock(r [32]byte) block.SignedBeaconBlock {
s.initSyncBlocksLock.RLock()
defer s.initSyncBlocksLock.RUnlock()
b := s.initSyncBlocks[r]
@@ -31,11 +31,11 @@ func (s *Service) getInitSyncBlock(r [32]byte) interfaces.SignedBeaconBlock {
// This retrieves all the beacon blocks from the initial sync blocks cache, the returned
// blocks are unordered.
func (s *Service) getInitSyncBlocks() []interfaces.SignedBeaconBlock {
func (s *Service) getInitSyncBlocks() []block.SignedBeaconBlock {
s.initSyncBlocksLock.RLock()
defer s.initSyncBlocksLock.RUnlock()
blks := make([]interfaces.SignedBeaconBlock, 0, len(s.initSyncBlocks))
blks := make([]block.SignedBeaconBlock, 0, len(s.initSyncBlocks))
for _, b := range s.initSyncBlocks {
blks = append(blks, b)
}
@@ -46,5 +46,5 @@ func (s *Service) getInitSyncBlocks() []interfaces.SignedBeaconBlock {
func (s *Service) clearInitSyncBlocks() {
s.initSyncBlocksLock.Lock()
defer s.initSyncBlocksLock.Unlock()
s.initSyncBlocks = make(map[[32]byte]interfaces.SignedBeaconBlock)
s.initSyncBlocks = make(map[[32]byte]block.SignedBeaconBlock)
}

View File

@@ -6,18 +6,19 @@ import (
"time"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/interfaces"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/timeutils"
"github.com/prysmaticlabs/prysm/shared/version"
"github.com/sirupsen/logrus"
)
var log = logrus.WithField("prefix", "blockchain")
// logs state transition related data every slot.
func logStateTransitionData(b interfaces.BeaconBlock) {
log := log.WithField("slot", b.Slot)
func logStateTransitionData(b block.BeaconBlock) {
log := log.WithField("slot", b.Slot())
if len(b.Body().Attestations()) > 0 {
log = log.WithField("attestations", len(b.Body().Attestations()))
}
@@ -33,10 +34,16 @@ func logStateTransitionData(b interfaces.BeaconBlock) {
if len(b.Body().VoluntaryExits()) > 0 {
log = log.WithField("voluntaryExits", len(b.Body().VoluntaryExits()))
}
if b.Version() == version.Altair {
agg, err := b.Body().SyncAggregate()
if err == nil {
log = log.WithField("syncBitsCount", agg.SyncCommitteeBits.Count())
}
}
log.Info("Finished applying state transition")
}
func logBlockSyncStatus(block interfaces.BeaconBlock, blockRoot [32]byte, finalized *ethpb.Checkpoint, receivedTime time.Time, genesisTime uint64) error {
func logBlockSyncStatus(block block.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

View File

@@ -3,9 +3,9 @@ package blockchain
import (
"testing"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/eth/v1alpha1/wrapper"
"github.com/prysmaticlabs/prysm/proto/interfaces"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
logTest "github.com/sirupsen/logrus/hooks/test"
)
@@ -13,7 +13,7 @@ import (
func Test_logStateTransitionData(t *testing.T) {
tests := []struct {
name string
b interfaces.BeaconBlock
b block.BeaconBlock
want string
}{
{name: "empty block body",

View File

@@ -3,15 +3,18 @@ package blockchain
import (
"context"
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core/altair"
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute"
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/interfaces"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/version"
)
var (
@@ -107,6 +110,14 @@ var (
Buckets: []float64{1, 2, 3, 4, 6, 32, 64},
},
)
syncHeadStateMiss = promauto.NewCounter(prometheus.CounterOpts{
Name: "sync_head_state_miss",
Help: "The number of sync head state requests that are present in the cache.",
})
syncHeadStateHit = promauto.NewCounter(prometheus.CounterOpts{
Name: "sync_head_state_hit",
Help: "The number of sync head state requests that are not present in the cache.",
})
)
// reportSlotMetrics reports slot related metrics.
@@ -121,7 +132,7 @@ func reportSlotMetrics(stateSlot, headSlot, clockSlot types.Slot, finalizedCheck
}
// reportEpochMetrics reports epoch related metrics.
func reportEpochMetrics(ctx context.Context, postState, headState iface.BeaconState) error {
func reportEpochMetrics(ctx context.Context, postState, headState state.BeaconState) error {
currentEpoch := types.Epoch(postState.Slot() / params.BeaconConfig().SlotsPerEpoch)
// Validator instances
@@ -206,14 +217,31 @@ func reportEpochMetrics(ctx context.Context, postState, headState iface.BeaconSt
beaconFinalizedRoot.Set(float64(bytesutil.ToLowInt64(postState.FinalizedCheckpoint().Root)))
currentEth1DataDepositCount.Set(float64(postState.Eth1Data().DepositCount))
// Validator participation should be viewed on the canonical chain.
v, b, err := precompute.New(ctx, headState)
if err != nil {
return err
}
_, b, err = precompute.ProcessAttestations(ctx, headState, v, b)
if err != nil {
return err
var b *precompute.Balance
var v []*precompute.Validator
var err error
switch headState.Version() {
case version.Phase0:
// Validator participation should be viewed on the canonical chain.
v, b, err = precompute.New(ctx, headState)
if err != nil {
return err
}
_, b, err = precompute.ProcessAttestations(ctx, headState, v, b)
if err != nil {
return err
}
case version.Altair:
v, b, err = altair.InitializeEpochValidators(ctx, headState)
if err != nil {
return err
}
_, b, err = altair.ProcessEpochParticipation(ctx, headState, b, v)
if err != nil {
return err
}
default:
return errors.Errorf("invalid state type provided: %T", headState.InnerStateUnsafe())
}
prevEpochActiveBalances.Set(float64(b.ActivePrevEpoch))
prevEpochSourceBalances.Set(float64(b.PrevEpochAttested))
@@ -228,7 +256,7 @@ func reportEpochMetrics(ctx context.Context, postState, headState iface.BeaconSt
return nil
}
func reportAttestationInclusion(blk interfaces.BeaconBlock) {
func reportAttestationInclusion(blk block.BeaconBlock) {
for _, att := range blk.Body().Attestations() {
attestationInclusionDelay.Observe(float64(blk.Slot() - att.Data.Slot))
}

View File

@@ -4,8 +4,7 @@ import (
"context"
"testing"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
eth "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
eth "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
)
@@ -25,7 +24,7 @@ func TestReportEpochMetrics_BadAttestation(t *testing.T) {
require.NoError(t, err)
h, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, h.AppendCurrentEpochAttestations(&pb.PendingAttestation{InclusionDelay: 0}))
require.NoError(t, h.AppendCurrentEpochAttestations(&eth.PendingAttestation{InclusionDelay: 0}))
err = reportEpochMetrics(context.Background(), s, h)
require.ErrorContains(t, "attestation with inclusion delay of 0", err)
}
@@ -36,7 +35,7 @@ func TestReportEpochMetrics_SlashedValidatorOutOfBound(t *testing.T) {
require.NoError(t, err)
v.Slashed = true
require.NoError(t, h.UpdateValidatorAtIndex(0, v))
require.NoError(t, h.AppendCurrentEpochAttestations(&pb.PendingAttestation{InclusionDelay: 1, Data: testutil.HydrateAttestationData(&eth.AttestationData{})}))
require.NoError(t, h.AppendCurrentEpochAttestations(&eth.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

@@ -5,7 +5,7 @@ import (
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/attestationutil"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/copyutil"

View File

@@ -8,9 +8,9 @@ import (
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
core "github.com/prysmaticlabs/prysm/beacon-chain/core/state"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/featureconfig"
"github.com/prysmaticlabs/prysm/shared/mputil"
@@ -18,7 +18,7 @@ import (
)
// getAttPreState retrieves the att pre state by either from the cache or the DB.
func (s *Service) getAttPreState(ctx context.Context, c *ethpb.Checkpoint) (iface.BeaconState, error) {
func (s *Service) getAttPreState(ctx context.Context, c *ethpb.Checkpoint) (state.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(uint64(c.Epoch), 10 /* base 10 */)
@@ -44,32 +44,23 @@ func (s *Service) getAttPreState(ctx context.Context, c *ethpb.Checkpoint) (ifac
}
if epochStartSlot > baseState.Slot() {
if featureconfig.Get().EnableNextSlotStateCache {
baseState, err = state.ProcessSlotsUsingNextSlotCache(ctx, baseState, c.Root, epochStartSlot)
baseState, err = core.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)
baseState, err = core.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")
}
return baseState, nil
}
// To avoid sharing the same state across checkpoint state cache and hot state cache,
// we don't add the state to check point cache.
has, err := s.cfg.StateGen.HasStateInCache(ctx, bytesutil.ToBytes32(c.Root))
if err != nil {
return nil, err
}
if !has {
if err := s.checkpointStateCache.AddCheckpointState(c, baseState); err != nil {
return nil, errors.Wrap(err, "could not saved checkpoint state to cache")
}
// Sharing the same state across caches is perfectly fine here, the fetching
// of attestation prestate is by far the most accessed state fetching pattern in
// the beacon node. An extra state instance cached isn't an issue in the bigger
// picture.
if err := s.checkpointStateCache.AddCheckpointState(c, baseState); err != nil {
return nil, errors.Wrap(err, "could not save checkpoint state to cache")
}
return baseState, nil

View File

@@ -10,9 +10,8 @@ import (
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/eth/v1alpha1/wrapper"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
@@ -61,7 +60,7 @@ func TestStore_OnAttestation_ErrorConditions(t *testing.T) {
require.NoError(t, err)
s, err = testutil.NewBeaconState()
require.NoError(t, err)
err = s.SetFork(&pb.Fork{
err = s.SetFork(&ethpb.Fork{
Epoch: 0,
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
@@ -186,7 +185,7 @@ func TestStore_SaveCheckpointState(t *testing.T) {
r = bytesutil.ToBytes32([]byte{'A'})
cp1 := &ethpb.Checkpoint{Epoch: 1, Root: bytesutil.PadTo([]byte{'A'}, 32)}
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, s, bytesutil.ToBytes32([]byte{'A'})))
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &pb.StateSummary{Root: bytesutil.PadTo([]byte{'A'}, 32)}))
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &ethpb.StateSummary{Root: bytesutil.PadTo([]byte{'A'}, 32)}))
s1, err := service.getAttPreState(ctx, cp1)
require.NoError(t, err)
@@ -194,7 +193,7 @@ func TestStore_SaveCheckpointState(t *testing.T) {
cp2 := &ethpb.Checkpoint{Epoch: 2, Root: bytesutil.PadTo([]byte{'B'}, 32)}
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, s, bytesutil.ToBytes32([]byte{'B'})))
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &pb.StateSummary{Root: bytesutil.PadTo([]byte{'B'}, 32)}))
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &ethpb.StateSummary{Root: bytesutil.PadTo([]byte{'B'}, 32)}))
s2, err := service.getAttPreState(ctx, cp2)
require.NoError(t, err)
assert.Equal(t, 2*params.BeaconConfig().SlotsPerEpoch, s2.Slot(), "Unexpected state slot")
@@ -218,7 +217,7 @@ func TestStore_SaveCheckpointState(t *testing.T) {
service.prevFinalizedCheckpt = &ethpb.Checkpoint{Root: r[:]}
cp3 := &ethpb.Checkpoint{Epoch: 1, Root: bytesutil.PadTo([]byte{'C'}, 32)}
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, s, bytesutil.ToBytes32([]byte{'C'})))
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &pb.StateSummary{Root: bytesutil.PadTo([]byte{'C'}, 32)}))
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &ethpb.StateSummary{Root: bytesutil.PadTo([]byte{'C'}, 32)}))
s3, err := service.getAttPreState(ctx, cp3)
require.NoError(t, err)
assert.Equal(t, s.Slot(), s3.Slot(), "Unexpected state slot")

View File

@@ -9,12 +9,11 @@ import (
"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"
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
core "github.com/prysmaticlabs/prysm/beacon-chain/core/state"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
ethpbv1 "github.com/prysmaticlabs/prysm/proto/eth/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/interfaces"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
"github.com/prysmaticlabs/prysm/shared/attestationutil"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
@@ -83,7 +82,7 @@ var initialSyncBlockCacheSize = uint64(2 * params.BeaconConfig().SlotsPerEpoch)
// ancestor_at_finalized_slot = get_ancestor(store, store.justified_checkpoint.root, finalized_slot)
// if ancestor_at_finalized_slot != store.finalized_checkpoint.root:
// store.justified_checkpoint = state.current_justified_checkpoint
func (s *Service) onBlock(ctx context.Context, signed interfaces.SignedBeaconBlock, blockRoot [32]byte) error {
func (s *Service) onBlock(ctx context.Context, signed block.SignedBeaconBlock, blockRoot [32]byte) error {
ctx, span := trace.StartSpan(ctx, "blockChain.onBlock")
defer span.End()
@@ -97,7 +96,7 @@ func (s *Service) onBlock(ctx context.Context, signed interfaces.SignedBeaconBlo
return err
}
postState, err := state.ExecuteStateTransition(ctx, preState, signed)
postState, err := core.ExecuteStateTransition(ctx, preState, signed)
if err != nil {
return err
}
@@ -114,7 +113,7 @@ func (s *Service) onBlock(ctx context.Context, signed interfaces.SignedBeaconBlo
// 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 {
if err := core.UpdateNextSlotCache(slotCtx, blockRoot[:], postState); err != nil {
log.WithError(err).Debug("could not update next slot state cache")
}
}()
@@ -195,7 +194,7 @@ func (s *Service) onBlock(ctx context.Context, signed interfaces.SignedBeaconBlo
return s.handleEpochBoundary(ctx, postState)
}
func (s *Service) onBlockBatch(ctx context.Context, blks []interfaces.SignedBeaconBlock,
func (s *Service) onBlockBatch(ctx context.Context, blks []block.SignedBeaconBlock,
blockRoots [][32]byte) ([]*ethpb.Checkpoint, []*ethpb.Checkpoint, error) {
ctx, span := trace.StartSpan(ctx, "blockChain.onBlockBatch")
defer span.End()
@@ -228,9 +227,9 @@ func (s *Service) onBlockBatch(ctx context.Context, blks []interfaces.SignedBeac
Messages: [][32]byte{},
}
var set *bls.SignatureSet
boundaries := make(map[[32]byte]iface.BeaconState)
boundaries := make(map[[32]byte]state.BeaconState)
for i, b := range blks {
set, preState, err = state.ExecuteStateTransitionNoVerifyAnySig(ctx, preState, b)
set, preState, err = core.ExecuteStateTransitionNoVerifyAnySig(ctx, preState, b)
if err != nil {
return nil, nil, err
}
@@ -271,7 +270,7 @@ func (s *Service) onBlockBatch(ctx context.Context, blks []interfaces.SignedBeac
// handles a block after the block's batch has been verified, where we can save blocks
// their state summaries and split them off to relative hot/cold storage.
func (s *Service) handleBlockAfterBatchVerify(ctx context.Context, signed interfaces.SignedBeaconBlock,
func (s *Service) handleBlockAfterBatchVerify(ctx context.Context, signed block.SignedBeaconBlock,
blockRoot [32]byte, fCheckpoint, jCheckpoint *ethpb.Checkpoint) error {
b := signed.Block()
@@ -279,7 +278,7 @@ func (s *Service) handleBlockAfterBatchVerify(ctx context.Context, signed interf
if err := s.insertBlockToForkChoiceStore(ctx, b, blockRoot, fCheckpoint, jCheckpoint); err != nil {
return err
}
if err := s.cfg.BeaconDB.SaveStateSummary(ctx, &pb.StateSummary{
if err := s.cfg.BeaconDB.SaveStateSummary(ctx, &ethpb.StateSummary{
Slot: signed.Block().Slot(),
Root: blockRoot[:],
}); err != nil {
@@ -305,19 +304,26 @@ func (s *Service) handleBlockAfterBatchVerify(ctx context.Context, signed interf
if err := s.updateFinalized(ctx, fCheckpoint); err != nil {
return err
}
if featureconfig.Get().UpdateHeadTimely {
s.prevFinalizedCheckpt = s.finalizedCheckpt
s.finalizedCheckpt = fCheckpoint
}
}
return nil
}
// Epoch boundary bookkeeping such as logging epoch summaries.
func (s *Service) handleEpochBoundary(ctx context.Context, postState iface.BeaconState) error {
func (s *Service) handleEpochBoundary(ctx context.Context, postState state.BeaconState) error {
ctx, span := trace.StartSpan(ctx, "blockChain.handleEpochBoundary")
defer span.End()
if postState.Slot()+1 == s.nextEpochBoundarySlot {
// Update caches for the next epoch at epoch boundary slot - 1.
if err := helpers.UpdateCommitteeCache(postState, helpers.NextEpoch(postState)); err != nil {
return err
}
copied := postState.Copy()
copied, err := state.ProcessSlots(ctx, copied, copied.Slot()+1)
copied, err := core.ProcessSlots(ctx, copied, copied.Slot()+1)
if err != nil {
return err
}
@@ -349,8 +355,11 @@ func (s *Service) handleEpochBoundary(ctx context.Context, postState iface.Beaco
// This feeds in the block and block's attestations to fork choice store. It's allows fork choice store
// to gain information on the most current chain.
func (s *Service) insertBlockAndAttestationsToForkChoiceStore(ctx context.Context, blk interfaces.BeaconBlock, root [32]byte,
st iface.BeaconState) error {
func (s *Service) insertBlockAndAttestationsToForkChoiceStore(ctx context.Context, blk block.BeaconBlock, root [32]byte,
st state.BeaconState) error {
ctx, span := trace.StartSpan(ctx, "blockChain.insertBlockAndAttestationsToForkChoiceStore")
defer span.End()
fCheckpoint := st.FinalizedCheckpoint()
jCheckpoint := st.CurrentJustifiedCheckpoint()
if err := s.insertBlockToForkChoiceStore(ctx, blk, root, fCheckpoint, jCheckpoint); err != nil {
@@ -371,7 +380,7 @@ func (s *Service) insertBlockAndAttestationsToForkChoiceStore(ctx context.Contex
return nil
}
func (s *Service) insertBlockToForkChoiceStore(ctx context.Context, blk interfaces.BeaconBlock,
func (s *Service) insertBlockToForkChoiceStore(ctx context.Context, blk block.BeaconBlock,
root [32]byte, fCheckpoint, jCheckpoint *ethpb.Checkpoint) error {
if err := s.fillInForkChoiceMissingBlocks(ctx, blk, fCheckpoint, jCheckpoint); err != nil {
return err
@@ -388,7 +397,7 @@ func (s *Service) insertBlockToForkChoiceStore(ctx context.Context, blk interfac
// This saves post state info to DB or cache. This also saves post state info to fork choice store.
// Post state info consists of processed block and state. Do not call this method unless the block and state are verified.
func (s *Service) savePostStateInfo(ctx context.Context, r [32]byte, b interfaces.SignedBeaconBlock, st iface.BeaconState, initSync bool) error {
func (s *Service) savePostStateInfo(ctx context.Context, r [32]byte, b block.SignedBeaconBlock, st state.BeaconState, initSync bool) error {
ctx, span := trace.StartSpan(ctx, "blockChain.savePostStateInfo")
defer span.End()
if initSync {

View File

@@ -8,9 +8,9 @@ import (
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/interfaces"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
"github.com/prysmaticlabs/prysm/shared/attestationutil"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/featureconfig"
@@ -27,7 +27,7 @@ func (s *Service) CurrentSlot() types.Slot {
// getBlockPreState returns the pre state of an incoming block. It uses the parent root of the block
// to retrieve the state in DB. It verifies the pre state's validity and the incoming block
// is in the correct time window.
func (s *Service) getBlockPreState(ctx context.Context, b interfaces.BeaconBlock) (iface.BeaconState, error) {
func (s *Service) getBlockPreState(ctx context.Context, b block.BeaconBlock) (state.BeaconState, error) {
ctx, span := trace.StartSpan(ctx, "blockChain.getBlockPreState")
defer span.End()
@@ -58,7 +58,7 @@ func (s *Service) getBlockPreState(ctx context.Context, b interfaces.BeaconBlock
}
// verifyBlkPreState validates input block has a valid pre-state.
func (s *Service) verifyBlkPreState(ctx context.Context, b interfaces.BeaconBlock) error {
func (s *Service) verifyBlkPreState(ctx context.Context, b block.BeaconBlock) error {
ctx, span := trace.StartSpan(ctx, "blockChain.verifyBlkPreState")
defer span.End()
@@ -121,7 +121,7 @@ func (s *Service) VerifyBlkDescendant(ctx context.Context, root [32]byte) error
// verifyBlkFinalizedSlot validates input block is not less than or equal
// to current finalized slot.
func (s *Service) verifyBlkFinalizedSlot(b interfaces.BeaconBlock) error {
func (s *Service) verifyBlkFinalizedSlot(b block.BeaconBlock) error {
finalizedSlot, err := helpers.StartSlot(s.finalizedCheckpt.Epoch)
if err != nil {
return err
@@ -137,10 +137,13 @@ func (s *Service) verifyBlkFinalizedSlot(b interfaces.BeaconBlock) error {
// Otherwise, delay incorporation of new justified checkpoint until next epoch boundary.
// See https://ethresear.ch/t/prevention-of-bouncing-attack-on-ffg/6114 for more detailed analysis and discussion.
func (s *Service) shouldUpdateCurrentJustified(ctx context.Context, newJustifiedCheckpt *ethpb.Checkpoint) (bool, error) {
ctx, span := trace.StartSpan(ctx, "blockChain.shouldUpdateCurrentJustified")
defer span.End()
if helpers.SlotsSinceEpochStarts(s.CurrentSlot()) < params.BeaconConfig().SafeSlotsToUpdateJustified {
return true, nil
}
var newJustifiedBlockSigned interfaces.SignedBeaconBlock
var newJustifiedBlockSigned block.SignedBeaconBlock
justifiedRoot := s.ensureRootNotZeros(bytesutil.ToBytes32(newJustifiedCheckpt.Root))
var err error
if s.hasInitSyncBlock(justifiedRoot) {
@@ -163,7 +166,7 @@ func (s *Service) shouldUpdateCurrentJustified(ctx context.Context, newJustified
if newJustifiedBlock.Slot() <= jSlot {
return false, nil
}
var justifiedBlockSigned interfaces.SignedBeaconBlock
var justifiedBlockSigned block.SignedBeaconBlock
cachedJustifiedRoot := s.ensureRootNotZeros(bytesutil.ToBytes32(s.justifiedCheckpt.Root))
if s.hasInitSyncBlock(cachedJustifiedRoot) {
justifiedBlockSigned = s.getInitSyncBlock(cachedJustifiedRoot)
@@ -188,7 +191,10 @@ func (s *Service) shouldUpdateCurrentJustified(ctx context.Context, newJustified
return true, nil
}
func (s *Service) updateJustified(ctx context.Context, state iface.ReadOnlyBeaconState) error {
func (s *Service) updateJustified(ctx context.Context, state state.ReadOnlyBeaconState) error {
ctx, span := trace.StartSpan(ctx, "blockChain.updateJustified")
defer span.End()
cpt := state.CurrentJustifiedCheckpoint()
if cpt.Epoch > s.bestJustifiedCheckpt.Epoch {
s.bestJustifiedCheckpt = cpt
@@ -223,6 +229,9 @@ func (s *Service) updateJustifiedInitSync(ctx context.Context, cp *ethpb.Checkpo
}
func (s *Service) updateFinalized(ctx context.Context, cp *ethpb.Checkpoint) error {
ctx, span := trace.StartSpan(ctx, "blockChain.updateFinalized")
defer span.End()
// Blocks need to be saved so that we can retrieve finalized block from
// DB when migrating states.
if err := s.cfg.BeaconDB.SaveBlocks(ctx, s.getInitSyncBlocks()); err != nil {
@@ -334,7 +343,7 @@ func (s *Service) ancestorByDB(ctx context.Context, r [32]byte, slot types.Slot)
// ancestor_at_finalized_slot = get_ancestor(store, store.justified_checkpoint.root, finalized_slot)
// if ancestor_at_finalized_slot != store.finalized_checkpoint.root:
// store.justified_checkpoint = state.current_justified_checkpoint
func (s *Service) finalizedImpliesNewJustified(ctx context.Context, state iface.BeaconState) error {
func (s *Service) finalizedImpliesNewJustified(ctx context.Context, state state.BeaconState) error {
// Update justified if it's different than the one cached in the store.
if !attestationutil.CheckPointIsEqual(s.justifiedCheckpt, state.CurrentJustifiedCheckpoint()) {
if state.CurrentJustifiedCheckpoint().Epoch > s.justifiedCheckpt.Epoch {
@@ -364,9 +373,9 @@ func (s *Service) finalizedImpliesNewJustified(ctx context.Context, state iface.
// This retrieves missing blocks from DB (ie. the blocks that couldn't be received over sync) and inserts them to fork choice store.
// This is useful for block tree visualizer and additional vote accounting.
func (s *Service) fillInForkChoiceMissingBlocks(ctx context.Context, blk interfaces.BeaconBlock,
func (s *Service) fillInForkChoiceMissingBlocks(ctx context.Context, blk block.BeaconBlock,
fCheckpoint, jCheckpoint *ethpb.Checkpoint) error {
pendingNodes := make([]interfaces.BeaconBlock, 0)
pendingNodes := make([]block.BeaconBlock, 0)
pendingRoots := make([][32]byte, 0)
parentRoot := bytesutil.ToBytes32(blk.ParentRoot())

View File

@@ -13,17 +13,16 @@ import (
mock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
core "github.com/prysmaticlabs/prysm/beacon-chain/core/state"
"github.com/prysmaticlabs/prysm/beacon-chain/db"
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
"github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/eth/v1alpha1/wrapper"
"github.com/prysmaticlabs/prysm/proto/interfaces"
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
"github.com/prysmaticlabs/prysm/shared/attestationutil"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
@@ -60,16 +59,16 @@ func TestStore_OnBlock(t *testing.T) {
assert.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(random)))
randomParentRoot, err := random.Block.HashTreeRoot()
assert.NoError(t, err)
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &pb.StateSummary{Slot: st.Slot(), Root: randomParentRoot[:]}))
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &ethpb.StateSummary{Slot: st.Slot(), Root: randomParentRoot[:]}))
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, st.Copy(), randomParentRoot))
randomParentRoot2 := roots[1]
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &pb.StateSummary{Slot: st.Slot(), Root: randomParentRoot2}))
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &ethpb.StateSummary{Slot: st.Slot(), Root: randomParentRoot2}))
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, st.Copy(), bytesutil.ToBytes32(randomParentRoot2)))
tests := []struct {
name string
blk *ethpb.SignedBeaconBlock
s iface.BeaconState
s state.BeaconState
time uint64
wantErrString string
}{
@@ -155,13 +154,13 @@ func TestStore_OnBlockBatch(t *testing.T) {
bState := st.Copy()
var blks []interfaces.SignedBeaconBlock
var blks []block.SignedBeaconBlock
var blkRoots [][32]byte
var firstState iface.BeaconState
var firstState state.BeaconState
for i := 1; i < 10; i++ {
b, err := testutil.GenerateFullBlock(bState, keys, testutil.DefaultBlockGenConfig(), types.Slot(i))
require.NoError(t, err)
bState, err = state.ExecuteStateTransition(ctx, bState, wrapper.WrappedPhase0SignedBeaconBlock(b))
bState, err = core.ExecuteStateTransition(ctx, bState, wrapper.WrappedPhase0SignedBeaconBlock(b))
require.NoError(t, err)
if i == 1 {
firstState = bState.Copy()
@@ -256,7 +255,7 @@ func TestCachedPreState_CanGetFromStateSummary(t *testing.T) {
service, err := NewService(ctx, cfg)
require.NoError(t, err)
s, err := v1.InitializeFromProto(&pb.BeaconState{Slot: 1, GenesisValidatorsRoot: params.BeaconConfig().ZeroHash[:]})
s, err := v1.InitializeFromProto(&ethpb.BeaconState{Slot: 1, GenesisValidatorsRoot: params.BeaconConfig().ZeroHash[:]})
require.NoError(t, err)
genesisStateRoot := [32]byte{}
@@ -273,7 +272,7 @@ func TestCachedPreState_CanGetFromStateSummary(t *testing.T) {
b := testutil.NewBeaconBlock()
b.Block.Slot = 1
b.Block.ParentRoot = gRoot[:]
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &pb.StateSummary{Slot: 1, Root: gRoot[:]}))
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &ethpb.StateSummary{Slot: 1, Root: gRoot[:]}))
require.NoError(t, service.cfg.StateGen.SaveState(ctx, gRoot, s))
require.NoError(t, service.verifyBlkPreState(ctx, wrapper.WrappedPhase0BeaconBlock(b.Block)))
}
@@ -308,9 +307,9 @@ func TestCachedPreState_CanGetFromDB(t *testing.T) {
assert.ErrorContains(t, wanted, err)
b.Block.ParentRoot = gRoot[:]
s, err := v1.InitializeFromProto(&pb.BeaconState{Slot: 1})
s, err := v1.InitializeFromProto(&ethpb.BeaconState{Slot: 1})
require.NoError(t, err)
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &pb.StateSummary{Slot: 1, Root: gRoot[:]}))
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &ethpb.StateSummary{Slot: 1, Root: gRoot[:]}))
require.NoError(t, service.cfg.StateGen.SaveState(ctx, gRoot, s))
require.NoError(t, service.verifyBlkPreState(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b).Block()))
}
@@ -763,7 +762,7 @@ func TestFinalizedImpliesNewJustified(t *testing.T) {
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.cfg.BeaconDB.SaveStateSummary(ctx, &pb.StateSummary{Root: bytesutil.PadTo(test.want.Root, 32)}))
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &ethpb.StateSummary{Root: bytesutil.PadTo(test.want.Root, 32)}))
genesisState, err := testutil.NewBeaconState()
require.NoError(t, err)
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, genesisState, bytesutil.ToBytes32(test.want.Root)))
@@ -878,7 +877,7 @@ func TestUpdateJustifiedInitSync(t *testing.T) {
require.NoError(t, err)
require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(gBlk)))
require.NoError(t, service.cfg.BeaconDB.SaveGenesisBlockRoot(ctx, gRoot))
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &pb.StateSummary{Root: gRoot[:]}))
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &ethpb.StateSummary{Root: gRoot[:]}))
beaconState, _ := testutil.DeterministicGenesisState(t, 32)
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, beaconState, gRoot))
service.genesisRoot = gRoot

View File

@@ -9,8 +9,8 @@ import (
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/slotutil"
@@ -21,7 +21,7 @@ import (
// AttestationReceiver interface defines the methods of chain service receive and processing new attestations.
type AttestationReceiver interface {
ReceiveAttestationNoPubsub(ctx context.Context, att *ethpb.Attestation) error
AttestationPreState(ctx context.Context, att *ethpb.Attestation) (iface.BeaconState, error)
AttestationPreState(ctx context.Context, att *ethpb.Attestation) (state.BeaconState, error)
VerifyLmdFfgConsistency(ctx context.Context, att *ethpb.Attestation) error
VerifyFinalizedConsistency(ctx context.Context, root []byte) error
}
@@ -43,7 +43,7 @@ func (s *Service) ReceiveAttestationNoPubsub(ctx context.Context, att *ethpb.Att
}
// AttestationPreState returns the pre state of attestation.
func (s *Service) AttestationPreState(ctx context.Context, att *ethpb.Attestation) (iface.BeaconState, error) {
func (s *Service) AttestationPreState(ctx context.Context, att *ethpb.Attestation) (state.BeaconState, error) {
ss, err := helpers.StartSlot(att.Data.Target.Epoch)
if err != nil {
return nil, err

View File

@@ -12,8 +12,8 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
"github.com/prysmaticlabs/prysm/beacon-chain/operations/attestations"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/eth/v1alpha1/wrapper"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"

View File

@@ -8,7 +8,7 @@ import (
"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/proto/interfaces"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
"github.com/prysmaticlabs/prysm/shared/featureconfig"
"github.com/prysmaticlabs/prysm/shared/timeutils"
"github.com/prysmaticlabs/prysm/shared/traceutil"
@@ -20,8 +20,8 @@ var epochsSinceFinalitySaveHotStateDB = types.Epoch(100)
// BlockReceiver interface defines the methods of chain service receive and processing new blocks.
type BlockReceiver interface {
ReceiveBlock(ctx context.Context, block interfaces.SignedBeaconBlock, blockRoot [32]byte) error
ReceiveBlockBatch(ctx context.Context, blocks []interfaces.SignedBeaconBlock, blkRoots [][32]byte) error
ReceiveBlock(ctx context.Context, block block.SignedBeaconBlock, blockRoot [32]byte) error
ReceiveBlockBatch(ctx context.Context, blocks []block.SignedBeaconBlock, blkRoots [][32]byte) error
HasInitSyncBlock(root [32]byte) bool
}
@@ -30,7 +30,7 @@ type BlockReceiver interface {
// 1. Validate block, apply state transition and update check points
// 2. Apply fork choice to the processed block
// 3. Save latest head info
func (s *Service) ReceiveBlock(ctx context.Context, block interfaces.SignedBeaconBlock, blockRoot [32]byte) error {
func (s *Service) ReceiveBlock(ctx context.Context, block block.SignedBeaconBlock, blockRoot [32]byte) error {
ctx, span := trace.StartSpan(ctx, "blockChain.ReceiveBlock")
defer span.End()
receivedTime := timeutils.Now()
@@ -86,7 +86,7 @@ func (s *Service) ReceiveBlock(ctx context.Context, block interfaces.SignedBeaco
// ReceiveBlockBatch processes the whole block batch at once, assuming the block batch is linear ,transitioning
// the state, performing batch verification of all collected signatures and then performing the appropriate
// actions for a block post-transition.
func (s *Service) ReceiveBlockBatch(ctx context.Context, blocks []interfaces.SignedBeaconBlock, blkRoots [][32]byte) error {
func (s *Service) ReceiveBlockBatch(ctx context.Context, blocks []block.SignedBeaconBlock, blkRoots [][32]byte) error {
ctx, span := trace.StartSpan(ctx, "blockChain.ReceiveBlockBatch")
defer span.End()
@@ -134,7 +134,7 @@ func (s *Service) HasInitSyncBlock(root [32]byte) bool {
return s.hasInitSyncBlock(root)
}
func (s *Service) handlePostBlockOperations(b interfaces.BeaconBlock) error {
func (s *Service) handlePostBlockOperations(b block.BeaconBlock) error {
// Delete the processed block attestations from attestation pool.
if err := s.deletePoolAtts(b.Body().Attestations()); err != nil {
return err

View File

@@ -8,15 +8,17 @@ import (
types "github.com/prysmaticlabs/eth2-types"
blockchainTesting "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
"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/operations/voluntaryexits"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/eth/v1alpha1/wrapper"
"github.com/prysmaticlabs/prysm/proto/interfaces"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
"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"
@@ -270,7 +272,7 @@ func TestService_ReceiveBlockBatch(t *testing.T) {
s.finalizedCheckpt = &ethpb.Checkpoint{Root: gRoot[:]}
root, err := tt.args.block.Block.HashTreeRoot()
require.NoError(t, err)
blks := []interfaces.SignedBeaconBlock{wrapper.WrappedPhase0SignedBeaconBlock(tt.args.block)}
blks := []block.SignedBeaconBlock{wrapper.WrappedPhase0SignedBeaconBlock(tt.args.block)}
roots := [][32]byte{root}
err = s.ReceiveBlockBatch(ctx, blks, roots)
if tt.wantedErr != "" {
@@ -283,6 +285,62 @@ func TestService_ReceiveBlockBatch(t *testing.T) {
}
}
func TestService_ReceiveBlockBatch_UpdateFinalizedCheckpoint(t *testing.T) {
// Must enable head timely feature flag to test this.
resetCfg := featureconfig.InitWithReset(&featureconfig.Flags{
UpdateHeadTimely: true,
})
defer resetCfg()
ctx := context.Background()
genesis, keys := testutil.DeterministicGenesisState(t, 64)
// Generate 5 epochs worth of blocks.
var blks []block.SignedBeaconBlock
var roots [][32]byte
copied := genesis.Copy()
for i := types.Slot(1); i < params.BeaconConfig().SlotsPerEpoch*5; i++ {
b, err := testutil.GenerateFullBlock(copied, keys, testutil.DefaultBlockGenConfig(), i)
assert.NoError(t, err)
copied, err = state.ExecuteStateTransition(context.Background(), copied, wrapper.WrappedPhase0SignedBeaconBlock(b))
assert.NoError(t, err)
r, err := b.Block.HashTreeRoot()
require.NoError(t, err)
blks = append(blks, wrapper.WrappedPhase0SignedBeaconBlock(b))
roots = append(roots, r)
}
beaconDB := testDB.SetupDB(t)
genesisBlockRoot, err := genesis.HashTreeRoot(ctx)
require.NoError(t, err)
cfg := &Config{
BeaconDB: beaconDB,
ForkChoiceStore: protoarray.New(
0, // justifiedEpoch
0, // finalizedEpoch
genesisBlockRoot,
),
StateNotifier: &blockchainTesting.MockStateNotifier{RecordEvents: false},
StateGen: stategen.New(beaconDB),
}
s, err := NewService(ctx, cfg)
require.NoError(t, err)
err = s.saveGenesisData(ctx, genesis)
require.NoError(t, err)
gBlk, err := s.cfg.BeaconDB.GenesisBlock(ctx)
require.NoError(t, err)
gRoot, err := gBlk.Block().HashTreeRoot()
require.NoError(t, err)
s.finalizedCheckpt = &ethpb.Checkpoint{Root: gRoot[:]}
// Process 5 epochs worth of blocks.
require.NoError(t, s.ReceiveBlockBatch(ctx, blks, roots))
// Finalized epoch must be updated.
require.Equal(t, types.Epoch(2), s.finalizedCheckpt.Epoch)
}
func TestService_HasInitSyncBlock(t *testing.T) {
s, err := NewService(context.Background(), &Config{StateNotifier: &blockchainTesting.MockStateNotifier{}})
require.NoError(t, err)

View File

@@ -16,7 +16,7 @@ import (
"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"
core "github.com/prysmaticlabs/prysm/beacon-chain/core/state"
"github.com/prysmaticlabs/prysm/beacon-chain/db"
f "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice"
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
@@ -25,11 +25,11 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits"
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
"github.com/prysmaticlabs/prysm/cmd/beacon-chain/flags"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/interfaces"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/copyutil"
"github.com/prysmaticlabs/prysm/shared/params"
@@ -60,7 +60,7 @@ type Service struct {
nextEpochBoundarySlot types.Slot
boundaryRoots [][32]byte
checkpointStateCache *cache.CheckpointStateCache
initSyncBlocks map[[32]byte]interfaces.SignedBeaconBlock
initSyncBlocks map[[32]byte]block.SignedBeaconBlock
initSyncBlocksLock sync.RWMutex
justifiedBalances []uint64
justifiedBalancesLock sync.RWMutex
@@ -95,7 +95,7 @@ func NewService(ctx context.Context, cfg *Config) (*Service, error) {
cancel: cancel,
boundaryRoots: [][32]byte{},
checkpointStateCache: cache.NewCheckpointStateCache(),
initSyncBlocks: make(map[[32]byte]interfaces.SignedBeaconBlock),
initSyncBlocks: make(map[[32]byte]block.SignedBeaconBlock),
justifiedBalances: make([]uint64, 0),
}, nil
}
@@ -271,14 +271,14 @@ func (s *Service) processChainStartTime(ctx context.Context, genesisTime time.Ti
func (s *Service) initializeBeaconChain(
ctx context.Context,
genesisTime time.Time,
preGenesisState iface.BeaconState,
eth1data *ethpb.Eth1Data) (iface.BeaconState, error) {
preGenesisState state.BeaconState,
eth1data *ethpb.Eth1Data) (state.BeaconState, error) {
ctx, span := trace.StartSpan(ctx, "beacon-chain.Service.initializeBeaconChain")
defer span.End()
s.genesisTime = genesisTime
unixTime := uint64(genesisTime.Unix())
genesisState, err := state.OptimizedGenesisBeaconState(unixTime, preGenesisState, eth1data)
genesisState, err := core.OptimizedGenesisBeaconState(unixTime, preGenesisState, eth1data)
if err != nil {
return nil, errors.Wrap(err, "could not initialize genesis state")
}
@@ -332,7 +332,7 @@ func (s *Service) Status() error {
}
// This gets called when beacon chain is first initialized to save genesis data (state, block, and more) in db.
func (s *Service) saveGenesisData(ctx context.Context, genesisState iface.BeaconState) error {
func (s *Service) saveGenesisData(ctx context.Context, genesisState state.BeaconState) error {
if err := s.cfg.BeaconDB.SaveGenesisData(ctx, genesisState); err != nil {
return errors.Wrap(err, "could not save genesis data")
}
@@ -399,7 +399,7 @@ func (s *Service) initializeChainInfo(ctx context.Context) error {
return errors.New("no finalized epoch in the database")
}
finalizedRoot := s.ensureRootNotZeros(bytesutil.ToBytes32(finalized.Root))
var finalizedState iface.BeaconState
var finalizedState state.BeaconState
finalizedState, err = s.cfg.StateGen.Resume(ctx)
if err != nil {

View File

@@ -21,13 +21,11 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
"github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
"github.com/prysmaticlabs/prysm/cmd/beacon-chain/flags"
protodb "github.com/prysmaticlabs/prysm/proto/beacon/db"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/eth/v1alpha1/wrapper"
"github.com/prysmaticlabs/prysm/proto/interfaces"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/event"
"github.com/prysmaticlabs/prysm/shared/params"
@@ -64,6 +62,11 @@ func (mb *mockBroadcaster) BroadcastAttestation(_ context.Context, _ uint64, _ *
return nil
}
func (mb *mockBroadcaster) BroadcastSyncCommitteeMessage(_ context.Context, _ uint64, _ *ethpb.SyncCommitteeMessage) error {
mb.broadcastCalled = true
return nil
}
var _ p2p.Broadcaster = (*mockBroadcaster)(nil)
func setupBeaconChain(t *testing.T, beaconDB db.Database) *Service {
@@ -74,20 +77,20 @@ func setupBeaconChain(t *testing.T, beaconDB db.Database) *Service {
bState, _ := testutil.DeterministicGenesisState(t, 10)
pbState, err := v1.ProtobufBeaconState(bState.InnerStateUnsafe())
require.NoError(t, err)
err = beaconDB.SavePowchainData(ctx, &protodb.ETH1ChainData{
err = beaconDB.SavePowchainData(ctx, &ethpb.ETH1ChainData{
BeaconState: pbState,
Trie: &protodb.SparseMerkleTrie{},
CurrentEth1Data: &protodb.LatestETH1Data{
Trie: &ethpb.SparseMerkleTrie{},
CurrentEth1Data: &ethpb.LatestETH1Data{
BlockHash: make([]byte, 32),
},
ChainstartData: &protodb.ChainStartData{
ChainstartData: &ethpb.ChainStartData{
Eth1Data: &ethpb.Eth1Data{
DepositRoot: make([]byte, 32),
DepositCount: 0,
BlockHash: make([]byte, 32),
},
},
DepositContainers: []*protodb.DepositContainer{},
DepositContainers: []*ethpb.DepositContainer{},
})
require.NoError(t, err)
web3Service, err = powchain.NewService(ctx, &powchain.Web3ServiceConfig{
@@ -456,7 +459,7 @@ func TestServiceStop_SaveCachedBlocks(t *testing.T) {
cfg: &Config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB)},
ctx: ctx,
cancel: cancel,
initSyncBlocks: make(map[[32]byte]interfaces.SignedBeaconBlock),
initSyncBlocks: make(map[[32]byte]block.SignedBeaconBlock),
}
block := testutil.NewBeaconBlock()
r, err := block.Block.HashTreeRoot()
@@ -507,7 +510,7 @@ func BenchmarkHasBlockForkChoiceStore(b *testing.B) {
block := &ethpb.SignedBeaconBlock{Block: &ethpb.BeaconBlock{Body: &ethpb.BeaconBlockBody{}}}
r, err := block.Block.HashTreeRoot()
require.NoError(b, err)
bs := &pb.BeaconState{FinalizedCheckpoint: &ethpb.Checkpoint{Root: make([]byte, 32)}, CurrentJustifiedCheckpoint: &ethpb.Checkpoint{Root: make([]byte, 32)}}
bs := &ethpb.BeaconState{FinalizedCheckpoint: &ethpb.Checkpoint{Root: make([]byte, 32)}, CurrentJustifiedCheckpoint: &ethpb.Checkpoint{Root: make([]byte, 32)}}
beaconState, err := v1.InitializeFromProto(bs)
require.NoError(b, err)
require.NoError(b, s.insertBlockAndAttestationsToForkChoiceStore(ctx, wrapper.WrappedPhase0SignedBeaconBlock(block).Block(), r, beaconState))

View File

@@ -18,11 +18,10 @@ go_library(
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/db:go_default_library",
"//beacon-chain/forkchoice/protoarray:go_default_library",
"//beacon-chain/state/interface:go_default_library",
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/v1:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//proto/eth/v1alpha1:go_default_library",
"//proto/interfaces:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//proto/prysm/v1alpha1/block:go_default_library",
"//shared/bytesutil:go_default_library",
"//shared/event:go_default_library",
"//shared/params:go_default_library",

View File

@@ -18,11 +18,10 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/db"
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
"github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/interfaces"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/event"
"github.com/prysmaticlabs/prysm/shared/params"
@@ -31,18 +30,18 @@ import (
// ChainService defines the mock interface for testing
type ChainService struct {
State iface.BeaconState
State state.BeaconState
Root []byte
Block interfaces.SignedBeaconBlock
Block block.SignedBeaconBlock
FinalizedCheckPoint *ethpb.Checkpoint
CurrentJustifiedCheckPoint *ethpb.Checkpoint
PreviousJustifiedCheckPoint *ethpb.Checkpoint
BlocksReceived []interfaces.SignedBeaconBlock
BlocksReceived []block.SignedBeaconBlock
Balance *precompute.Balance
Genesis time.Time
ValidatorsRoot [32]byte
CanonicalRoots map[[32]byte]bool
Fork *pb.Fork
Fork *ethpb.Fork
ETH1Data *ethpb.Eth1Data
DB db.Database
stateNotifier statefeed.Notifier
@@ -52,6 +51,13 @@ type ChainService struct {
ForkChoiceStore *protoarray.Store
VerifyBlkDescendantErr error
Slot *types.Slot // Pointer because 0 is a useful value, so checking against it can be incorrect.
CurrentSyncCommitteeIndices []types.CommitteeIndex
NextSyncCommitteeIndices []types.CommitteeIndex
SyncCommitteeDomain []byte
SyncSelectionProofDomain []byte
SyncContributionProofDomain []byte
PublicKey [48]byte
SyncCommitteePubkeys [][]byte
}
// StateNotifier mocks the same method in the chain service.
@@ -150,7 +156,7 @@ func (mon *MockOperationNotifier) OperationFeed() *event.Feed {
}
// ReceiveBlockInitialSync mocks ReceiveBlockInitialSync method in chain service.
func (s *ChainService) ReceiveBlockInitialSync(ctx context.Context, block interfaces.SignedBeaconBlock, _ [32]byte) error {
func (s *ChainService) ReceiveBlockInitialSync(ctx context.Context, block block.SignedBeaconBlock, _ [32]byte) error {
if s.State == nil {
s.State = &v1.BeaconState{}
}
@@ -177,7 +183,7 @@ func (s *ChainService) ReceiveBlockInitialSync(ctx context.Context, block interf
}
// ReceiveBlockBatch processes blocks in batches from initial-sync.
func (s *ChainService) ReceiveBlockBatch(ctx context.Context, blks []interfaces.SignedBeaconBlock, _ [][32]byte) error {
func (s *ChainService) ReceiveBlockBatch(ctx context.Context, blks []block.SignedBeaconBlock, _ [][32]byte) error {
if s.State == nil {
s.State = &v1.BeaconState{}
}
@@ -206,7 +212,7 @@ func (s *ChainService) ReceiveBlockBatch(ctx context.Context, blks []interfaces.
}
// ReceiveBlock mocks ReceiveBlock method in chain service.
func (s *ChainService) ReceiveBlock(ctx context.Context, block interfaces.SignedBeaconBlock, _ [32]byte) error {
func (s *ChainService) ReceiveBlock(ctx context.Context, block block.SignedBeaconBlock, _ [32]byte) error {
if s.State == nil {
s.State = &v1.BeaconState{}
}
@@ -249,17 +255,17 @@ func (s *ChainService) HeadRoot(_ context.Context) ([]byte, error) {
}
// HeadBlock mocks HeadBlock method in chain service.
func (s *ChainService) HeadBlock(context.Context) (interfaces.SignedBeaconBlock, error) {
func (s *ChainService) HeadBlock(context.Context) (block.SignedBeaconBlock, error) {
return s.Block, nil
}
// HeadState mocks HeadState method in chain service.
func (s *ChainService) HeadState(context.Context) (iface.BeaconState, error) {
func (s *ChainService) HeadState(context.Context) (state.BeaconState, error) {
return s.State, nil
}
// CurrentFork mocks HeadState method in chain service.
func (s *ChainService) CurrentFork() *pb.Fork {
func (s *ChainService) CurrentFork() *ethpb.Fork {
return s.Fork
}
@@ -289,7 +295,7 @@ func (s *ChainService) ReceiveAttestationNoPubsub(context.Context, *ethpb.Attest
}
// AttestationPreState mocks AttestationPreState method in chain service.
func (s *ChainService) AttestationPreState(_ context.Context, _ *ethpb.Attestation) (iface.BeaconState, error) {
func (s *ChainService) AttestationPreState(_ context.Context, _ *ethpb.Attestation) (state.BeaconState, error) {
return s.State, nil
}
@@ -393,3 +399,43 @@ func (s *ChainService) ChainHeads() ([][32]byte, []types.Slot) {
},
[]types.Slot{0, 1}
}
// HeadPublicKeyToValidatorIndex mocks HeadPublicKeyToValidatorIndex and always return 0 and true.
func (s *ChainService) HeadPublicKeyToValidatorIndex(ctx context.Context, pubKey [48]byte) (types.ValidatorIndex, bool) {
return 0, true
}
// HeadValidatorIndexToPublicKey mocks HeadValidatorIndexToPublicKey and always return empty and nil.
func (s *ChainService) HeadValidatorIndexToPublicKey(ctx context.Context, index types.ValidatorIndex) ([48]byte, error) {
return s.PublicKey, nil
}
// HeadCurrentSyncCommitteeIndices mocks HeadCurrentSyncCommitteeIndices and always return `CurrentSyncCommitteeIndices`.
func (s *ChainService) HeadCurrentSyncCommitteeIndices(ctx context.Context, index types.ValidatorIndex, slot types.Slot) ([]types.CommitteeIndex, error) {
return s.CurrentSyncCommitteeIndices, nil
}
// HeadNextSyncCommitteeIndices mocks HeadNextSyncCommitteeIndices and always return `HeadNextSyncCommitteeIndices`.
func (s *ChainService) HeadNextSyncCommitteeIndices(ctx context.Context, index types.ValidatorIndex, slot types.Slot) ([]types.CommitteeIndex, error) {
return s.NextSyncCommitteeIndices, nil
}
// HeadSyncCommitteePubKeys mocks HeadSyncCommitteePubKeys and always return empty nil.
func (s *ChainService) HeadSyncCommitteePubKeys(ctx context.Context, slot types.Slot, committeeIndex types.CommitteeIndex) ([][]byte, error) {
return s.SyncCommitteePubkeys, nil
}
// HeadSyncCommitteeDomain mocks HeadSyncCommitteeDomain and always return empty nil.
func (s *ChainService) HeadSyncCommitteeDomain(ctx context.Context, slot types.Slot) ([]byte, error) {
return s.SyncCommitteeDomain, nil
}
// HeadSyncSelectionProofDomain mocks HeadSyncSelectionProofDomain and always return empty nil.
func (s *ChainService) HeadSyncSelectionProofDomain(ctx context.Context, slot types.Slot) ([]byte, error) {
return s.SyncSelectionProofDomain, nil
}
// HeadSyncContributionProofDomain mocks HeadSyncContributionProofDomain and always return empty nil.
func (s *ChainService) HeadSyncContributionProofDomain(ctx context.Context, slot types.Slot) ([]byte, error) {
return s.SyncContributionProofDomain, nil
}

View File

@@ -6,8 +6,8 @@ import (
types "github.com/prysmaticlabs/eth2-types"
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/eth/v1alpha1/wrapper"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/testutil/require"

View File

@@ -10,17 +10,21 @@ go_library(
"committees.go",
"common.go",
"doc.go",
"error.go",
"proposer_indices_type.go",
"skip_slot_cache.go",
"subnet_ids.go",
"sync_subnet_ids.go",
] + select({
"//fuzz:fuzzing_enabled": [
"committee_disabled.go",
"proposer_indices_disabled.go",
"sync_committee_disabled.go",
],
"//conditions:default": [
"committee.go",
"proposer_indices.go",
"sync_committee.go",
],
}),
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/cache",
@@ -30,11 +34,13 @@ go_library(
"//tools:__subpackages__",
],
deps = [
"//beacon-chain/state/interface:go_default_library",
"//proto/eth/v1alpha1:go_default_library",
"//beacon-chain/state:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//shared/bytesutil:go_default_library",
"//shared/copyutil:go_default_library",
"//shared/hashutil:go_default_library",
"//shared/params:go_default_library",
"//shared/rand:go_default_library",
"//shared/sliceutil:go_default_library",
"@com_github_hashicorp_golang_lru//:go_default_library",
"@com_github_patrickmn_go_cache//:go_default_library",
@@ -58,15 +64,17 @@ go_test(
"proposer_indices_test.go",
"skip_slot_cache_test.go",
"subnet_ids_test.go",
"sync_committee_test.go",
"sync_subnet_ids_test.go",
],
embed = [":go_default_library"],
deps = [
"//beacon-chain/state/interface:go_default_library",
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/v1:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//proto/eth/v1alpha1:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//shared/bytesutil:go_default_library",
"//shared/params:go_default_library",
"//shared/testutil:go_default_library",
"//shared/testutil/assert:go_default_library",
"//shared/testutil/require:go_default_library",
"@com_github_google_gofuzz//:go_default_library",

View File

@@ -10,7 +10,7 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/copyutil"
"k8s.io/client-go/tools/cache"
)

View File

@@ -5,7 +5,7 @@ import (
"testing"
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
"google.golang.org/protobuf/proto"
)

View File

@@ -6,8 +6,8 @@ import (
lru "github.com/hashicorp/golang-lru"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/hashutil"
)
@@ -47,7 +47,7 @@ func NewCheckpointStateCache() *CheckpointStateCache {
// StateByCheckpoint fetches state by checkpoint. Returns true with a
// reference to the CheckpointState info, if exists. Otherwise returns false, nil.
func (c *CheckpointStateCache) StateByCheckpoint(cp *ethpb.Checkpoint) (iface.BeaconState, error) {
func (c *CheckpointStateCache) StateByCheckpoint(cp *ethpb.Checkpoint) (state.BeaconState, error) {
c.lock.RLock()
defer c.lock.RUnlock()
h, err := hashutil.HashProto(cp)
@@ -60,7 +60,7 @@ func (c *CheckpointStateCache) StateByCheckpoint(cp *ethpb.Checkpoint) (iface.Be
if exists && item != nil {
checkpointStateHit.Inc()
// Copy here is unnecessary since the return will only be used to verify attestation signature.
return item.(iface.BeaconState), nil
return item.(state.BeaconState), nil
}
checkpointStateMiss.Inc()
@@ -69,7 +69,7 @@ func (c *CheckpointStateCache) StateByCheckpoint(cp *ethpb.Checkpoint) (iface.Be
// AddCheckpointState adds CheckpointState object to the cache. This method also trims the least
// recently added CheckpointState object if the cache size has ready the max cache size limit.
func (c *CheckpointStateCache) AddCheckpointState(cp *ethpb.Checkpoint, s iface.ReadOnlyBeaconState) error {
func (c *CheckpointStateCache) AddCheckpointState(cp *ethpb.Checkpoint, s state.ReadOnlyBeaconState) error {
c.lock.Lock()
defer c.lock.Unlock()
h, err := hashutil.HashProto(cp)

View File

@@ -4,10 +4,9 @@ import (
"testing"
types "github.com/prysmaticlabs/eth2-types"
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
"github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
@@ -19,48 +18,48 @@ func TestCheckpointStateCache_StateByCheckpoint(t *testing.T) {
cache := NewCheckpointStateCache()
cp1 := &ethpb.Checkpoint{Epoch: 1, Root: bytesutil.PadTo([]byte{'A'}, 32)}
st, err := v1.InitializeFromProto(&pb.BeaconState{
st, err := v1.InitializeFromProto(&ethpb.BeaconState{
GenesisValidatorsRoot: params.BeaconConfig().ZeroHash[:],
Slot: 64,
})
require.NoError(t, err)
state, err := cache.StateByCheckpoint(cp1)
s, err := cache.StateByCheckpoint(cp1)
require.NoError(t, err)
assert.Equal(t, iface.BeaconState(nil), state, "Expected state not to exist in empty cache")
assert.Equal(t, state.BeaconState(nil), s, "Expected state not to exist in empty cache")
require.NoError(t, cache.AddCheckpointState(cp1, st))
state, err = cache.StateByCheckpoint(cp1)
s, err = cache.StateByCheckpoint(cp1)
require.NoError(t, err)
pbState1, err := v1.ProtobufBeaconState(state.InnerStateUnsafe())
pbState1, err := v1.ProtobufBeaconState(s.InnerStateUnsafe())
require.NoError(t, err)
pbState2, err := v1.ProtobufBeaconState(st.InnerStateUnsafe())
pbstate, err := v1.ProtobufBeaconState(st.InnerStateUnsafe())
require.NoError(t, err)
if !proto.Equal(pbState1, pbState2) {
if !proto.Equal(pbState1, pbstate) {
t.Error("incorrectly cached state")
}
cp2 := &ethpb.Checkpoint{Epoch: 2, Root: bytesutil.PadTo([]byte{'B'}, 32)}
st2, err := v1.InitializeFromProto(&pb.BeaconState{
st2, err := v1.InitializeFromProto(&ethpb.BeaconState{
Slot: 128,
})
require.NoError(t, err)
require.NoError(t, cache.AddCheckpointState(cp2, st2))
state, err = cache.StateByCheckpoint(cp2)
s, err = cache.StateByCheckpoint(cp2)
require.NoError(t, err)
assert.DeepEqual(t, st2.CloneInnerState(), state.CloneInnerState(), "incorrectly cached state")
assert.DeepEqual(t, st2.CloneInnerState(), s.CloneInnerState(), "incorrectly cached state")
state, err = cache.StateByCheckpoint(cp1)
s, err = cache.StateByCheckpoint(cp1)
require.NoError(t, err)
assert.DeepEqual(t, st.CloneInnerState(), state.CloneInnerState(), "incorrectly cached state")
assert.DeepEqual(t, st.CloneInnerState(), s.CloneInnerState(), "incorrectly cached state")
}
func TestCheckpointStateCache_MaxSize(t *testing.T) {
c := NewCheckpointStateCache()
st, err := v1.InitializeFromProto(&pb.BeaconState{
st, err := v1.InitializeFromProto(&ethpb.BeaconState{
Slot: 0,
})
require.NoError(t, err)

View File

@@ -127,6 +127,35 @@ func (c *CommitteeCache) ActiveIndices(seed [32]byte) ([]types.ValidatorIndex, e
return item.SortedIndices, nil
}
// ActiveBalance returns the total active balance of a given seed stored in cache.
func (c *CommitteeCache) ActiveBalance(seed [32]byte) (uint64, error) {
c.lock.RLock()
defer c.lock.RUnlock()
obj, exists := c.CommitteeCache.Get(key(seed))
if exists {
CommitteeCacheHit.Inc()
} else {
CommitteeCacheMiss.Inc()
return 0, ErrNonCommitteeKey
}
item, ok := obj.(*Committees)
if !ok {
return 0, ErrNotCommittee
}
if item == nil || item.ActiveBalance == nil {
return 0, errors.New("item is nil")
}
// Return `ErrNonCommitteeKey` if active balance field doesnt exist in item.
if !item.ActiveBalance.Exist {
return 0, ErrNonCommitteeKey
}
return item.ActiveBalance.Total, nil
}
// ActiveIndicesCount returns the active indices count of a given seed stored in cache.
func (c *CommitteeCache) ActiveIndicesCount(seed [32]byte) (int, error) {
c.lock.RLock()

View File

@@ -41,6 +41,11 @@ func (c *FakeCommitteeCache) ActiveIndicesCount(seed [32]byte) (int, error) {
return 0, nil
}
// ActiveBalance returns the active balance of a given seed stored in cache.
func (c *FakeCommitteeCache) ActiveBalance(seed [32]byte) (uint64, error) {
return 0, nil
}
// ProposerIndices returns the proposer indices of a given seed.
func (c *FakeCommitteeCache) ProposerIndices(seed [32]byte) ([]types.ValidatorIndex, error) {
return nil, nil

View File

@@ -88,6 +88,24 @@ func TestCommitteeCache_ActiveCount(t *testing.T) {
assert.Equal(t, len(item.SortedIndices), count)
}
func TestCommitteeCache_ActiveBalance(t *testing.T) {
cache := NewCommitteesCache()
balances := &Balance{
Exist: true,
Total: uint64(10000),
}
item := &Committees{Seed: [32]byte{'A'}, ActiveBalance: balances}
_, err := cache.ActiveBalance(item.Seed)
require.Equal(t, ErrNonCommitteeKey, err)
require.NoError(t, cache.AddCommitteeShuffledList(item))
got, err := cache.ActiveBalance(item.Seed)
require.NoError(t, err)
assert.Equal(t, balances.Total, got)
}
func TestCommitteeCache_CanRotate(t *testing.T) {
cache := NewCommitteesCache()

View File

@@ -10,10 +10,22 @@ import (
// a Committee struct.
var ErrNotCommittee = errors.New("object is not a committee struct")
// ErrNonCommitteeKey will be returned when the committee key does not exist in cache.
var ErrNonCommitteeKey = errors.New("committee key does not exist")
// Committees defines the shuffled committees seed.
type Committees struct {
CommitteeCount uint64
Seed [32]byte
ShuffledIndices []types.ValidatorIndex
SortedIndices []types.ValidatorIndex
ActiveBalance *Balance
}
// Balance tracks active balance.
// Given default uint64 is 0, `Exist` is used to distinguish whether
// this field has been filed.
type Balance struct {
Exist bool
Total uint64
}

View File

@@ -10,8 +10,7 @@ go_library(
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache",
visibility = ["//beacon-chain:__subpackages__"],
deps = [
"//proto/beacon/db:go_default_library",
"//proto/eth/v1alpha1:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//shared/bytesutil:go_default_library",
"//shared/hashutil:go_default_library",
"//shared/params:go_default_library",
@@ -32,8 +31,7 @@ go_test(
],
embed = [":go_default_library"],
deps = [
"//proto/beacon/db:go_default_library",
"//proto/eth/v1alpha1:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//shared/bytesutil:go_default_library",
"//shared/params:go_default_library",
"//shared/testutil/assert:go_default_library",

View File

@@ -15,8 +15,8 @@ import (
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
dbpb "github.com/prysmaticlabs/prysm/proto/beacon/db"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
dbpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/trieutil"

View File

@@ -7,8 +7,8 @@ import (
"math/big"
"testing"
dbpb "github.com/prysmaticlabs/prysm/proto/beacon/db"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
dbpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"

View File

@@ -7,8 +7,8 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
dbpb "github.com/prysmaticlabs/prysm/proto/beacon/db"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
dbpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/hashutil"
"github.com/sirupsen/logrus"
"go.opencensus.io/trace"

View File

@@ -5,8 +5,8 @@ import (
"math/big"
"testing"
dbpb "github.com/prysmaticlabs/prysm/proto/beacon/db"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
dbpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
"google.golang.org/protobuf/proto"

9
beacon-chain/cache/error.go vendored Normal file
View File

@@ -0,0 +1,9 @@
package cache
import "errors"
// Sync committee cache related errors
// ErrNonExistingSyncCommitteeKey when sync committee key (root) does not exist in cache.
var ErrNonExistingSyncCommitteeKey = errors.New("does not exist sync committee key")
var errNotSyncCommitteeIndexPosition = errors.New("not syncCommitteeIndexPosition struct")

View File

@@ -9,7 +9,7 @@ import (
lru "github.com/hashicorp/golang-lru"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
"go.opencensus.io/trace"
)
@@ -57,7 +57,7 @@ func (c *SkipSlotCache) Disable() {
// Get waits for any in progress calculation to complete before returning a
// cached response, if any.
func (c *SkipSlotCache) Get(ctx context.Context, r [32]byte) (iface.BeaconState, error) {
func (c *SkipSlotCache) Get(ctx context.Context, r [32]byte) (state.BeaconState, error) {
ctx, span := trace.StartSpan(ctx, "skipSlotCache.Get")
defer span.End()
if c.disabled {
@@ -97,7 +97,7 @@ func (c *SkipSlotCache) Get(ctx context.Context, r [32]byte) (iface.BeaconState,
if exists && item != nil {
skipSlotCacheHit.Inc()
span.AddAttributes(trace.BoolAttribute("hit", true))
return item.(iface.BeaconState).Copy(), nil
return item.(state.BeaconState).Copy(), nil
}
skipSlotCacheMiss.Inc()
span.AddAttributes(trace.BoolAttribute("hit", false))
@@ -136,7 +136,7 @@ func (c *SkipSlotCache) MarkNotInProgress(r [32]byte) error {
}
// Put the response in the cache.
func (c *SkipSlotCache) Put(_ context.Context, r [32]byte, state iface.BeaconState) error {
func (c *SkipSlotCache) Put(_ context.Context, r [32]byte, state state.BeaconState) error {
if c.disabled {
return nil
}

View File

@@ -5,9 +5,9 @@ import (
"testing"
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
"github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
)
@@ -17,21 +17,21 @@ func TestSkipSlotCache_RoundTrip(t *testing.T) {
c := cache.NewSkipSlotCache()
r := [32]byte{'a'}
state, err := c.Get(ctx, r)
s, err := c.Get(ctx, r)
require.NoError(t, err)
assert.Equal(t, iface.BeaconState(nil), state, "Empty cache returned an object")
assert.Equal(t, state.BeaconState(nil), s, "Empty cache returned an object")
require.NoError(t, c.MarkInProgress(r))
state, err = v1.InitializeFromProto(&pb.BeaconState{
s, err = v1.InitializeFromProto(&ethpb.BeaconState{
Slot: 10,
})
require.NoError(t, err)
require.NoError(t, c.Put(ctx, r, state))
require.NoError(t, c.Put(ctx, r, s))
require.NoError(t, c.MarkNotInProgress(r))
res, err := c.Get(ctx, r)
require.NoError(t, err)
assert.DeepEqual(t, res.CloneInnerState(), state.CloneInnerState(), "Expected equal protos to return from cache")
assert.DeepEqual(t, res.CloneInnerState(), s.CloneInnerState(), "Expected equal protos to return from cache")
}

187
beacon-chain/cache/sync_committee.go vendored Normal file
View File

@@ -0,0 +1,187 @@
// +build !libfuzzer
package cache
import (
"sync"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"k8s.io/client-go/tools/cache"
)
var (
maxSyncCommitteeSize = uint64(3) // Allows 3 forks to happen around `EPOCHS_PER_SYNC_COMMITTEE_PERIOD` boundary.
// SyncCommitteeCacheMiss tracks the number of committee requests that aren't present in the cache.
SyncCommitteeCacheMiss = promauto.NewCounter(prometheus.CounterOpts{
Name: "sync_committee_index_cache_miss_total",
Help: "The number of committee requests that aren't present in the sync committee index cache.",
})
// SyncCommitteeCacheHit tracks the number of committee requests that are in the cache.
SyncCommitteeCacheHit = promauto.NewCounter(prometheus.CounterOpts{
Name: "sync_committee_index_cache_hit_total",
Help: "The number of committee requests that are present in the sync committee index cache.",
})
)
// SyncCommitteeCache utilizes a FIFO cache to sufficiently cache validator position within sync committee.
// It is thread safe with concurrent read write.
type SyncCommitteeCache struct {
cache *cache.FIFO
lock sync.RWMutex
}
// Index position of all validators in sync committee where `currentSyncCommitteeRoot` is the
// key and `vIndexToPositionMap` is value. Inside `vIndexToPositionMap`, validator positions
// are cached where key is the validator index and the value is the `positionInCommittee` struct.
type syncCommitteeIndexPosition struct {
currentSyncCommitteeRoot [32]byte
vIndexToPositionMap map[types.ValidatorIndex]*positionInCommittee
}
// Index position of individual validator of current period and next period sync committee.
type positionInCommittee struct {
currentPeriod []types.CommitteeIndex
nextPeriod []types.CommitteeIndex
}
// NewSyncCommittee initializes and returns a new SyncCommitteeCache.
func NewSyncCommittee() *SyncCommitteeCache {
return &SyncCommitteeCache{
cache: cache.NewFIFO(keyFn),
}
}
// CurrentPeriodIndexPosition returns current period index position of a validator index with respect with
// sync committee. If the input validator index has no assignment, an empty list will be returned.
// If the input root does not exist in cache, `ErrNonExistingSyncCommitteeKey` is returned.
// Manual checking of state for index position in state is recommended when `ErrNonExistingSyncCommitteeKey` is returned.
func (s *SyncCommitteeCache) CurrentPeriodIndexPosition(root [32]byte, valIdx types.ValidatorIndex) ([]types.CommitteeIndex, error) {
s.lock.RLock()
defer s.lock.RUnlock()
pos, err := s.idxPositionInCommittee(root, valIdx)
if err != nil {
return nil, err
}
if pos == nil {
return []types.CommitteeIndex{}, nil
}
return pos.currentPeriod, nil
}
// NextPeriodIndexPosition returns next period index position of a validator index in respect with sync committee.
// If the input validator index has no assignment, an empty list will be returned.
// If the input root does not exist in cache, `ErrNonExistingSyncCommitteeKey` is returned.
// Manual checking of state for index position in state is recommended when `ErrNonExistingSyncCommitteeKey` is returned.
func (s *SyncCommitteeCache) NextPeriodIndexPosition(root [32]byte, valIdx types.ValidatorIndex) ([]types.CommitteeIndex, error) {
s.lock.RLock()
defer s.lock.RUnlock()
pos, err := s.idxPositionInCommittee(root, valIdx)
if err != nil {
return nil, err
}
if pos == nil {
return []types.CommitteeIndex{}, nil
}
return pos.nextPeriod, nil
}
// Helper function for `CurrentPeriodIndexPosition` and `NextPeriodIndexPosition` to return a mapping
// of validator index to its index(s) position in the sync committee.
func (s *SyncCommitteeCache) idxPositionInCommittee(
root [32]byte, valIdx types.ValidatorIndex,
) (*positionInCommittee, error) {
obj, exists, err := s.cache.GetByKey(key(root))
if err != nil {
return nil, err
}
if !exists {
SyncCommitteeCacheMiss.Inc()
return nil, ErrNonExistingSyncCommitteeKey
}
item, ok := obj.(*syncCommitteeIndexPosition)
if !ok {
return nil, errNotSyncCommitteeIndexPosition
}
idxInCommittee, ok := item.vIndexToPositionMap[valIdx]
if !ok {
SyncCommitteeCacheMiss.Inc()
return nil, nil
}
SyncCommitteeCacheHit.Inc()
return idxInCommittee, nil
}
// UpdatePositionsInCommittee updates caching of validators position in sync committee in respect to
// current epoch and next epoch. This should be called when `current_sync_committee` and `next_sync_committee`
// change and that happens every `EPOCHS_PER_SYNC_COMMITTEE_PERIOD`.
func (s *SyncCommitteeCache) UpdatePositionsInCommittee(syncCommitteeBoundaryRoot [32]byte, st state.BeaconStateAltair) error {
csc, err := st.CurrentSyncCommittee()
if err != nil {
return err
}
positionsMap := make(map[types.ValidatorIndex]*positionInCommittee)
for i, pubkey := range csc.Pubkeys {
p := bytesutil.ToBytes48(pubkey)
validatorIndex, ok := st.ValidatorIndexByPubkey(p)
if !ok {
continue
}
if _, ok := positionsMap[validatorIndex]; !ok {
m := &positionInCommittee{currentPeriod: []types.CommitteeIndex{types.CommitteeIndex(i)}, nextPeriod: []types.CommitteeIndex{}}
positionsMap[validatorIndex] = m
} else {
positionsMap[validatorIndex].currentPeriod = append(positionsMap[validatorIndex].currentPeriod, types.CommitteeIndex(i))
}
}
nsc, err := st.NextSyncCommittee()
if err != nil {
return err
}
for i, pubkey := range nsc.Pubkeys {
p := bytesutil.ToBytes48(pubkey)
validatorIndex, ok := st.ValidatorIndexByPubkey(p)
if !ok {
continue
}
if _, ok := positionsMap[validatorIndex]; !ok {
m := &positionInCommittee{nextPeriod: []types.CommitteeIndex{types.CommitteeIndex(i)}, currentPeriod: []types.CommitteeIndex{}}
positionsMap[validatorIndex] = m
} else {
positionsMap[validatorIndex].nextPeriod = append(positionsMap[validatorIndex].nextPeriod, types.CommitteeIndex(i))
}
}
s.lock.Lock()
defer s.lock.Unlock()
if err := s.cache.Add(&syncCommitteeIndexPosition{
currentSyncCommitteeRoot: syncCommitteeBoundaryRoot,
vIndexToPositionMap: positionsMap,
}); err != nil {
return err
}
trim(s.cache, maxSyncCommitteeSize)
return nil
}
// Given the `syncCommitteeIndexPosition` object, this returns the key of the object.
// The key is the `currentSyncCommitteeRoot` within the field.
// Error gets returned if input does not comply with `currentSyncCommitteeRoot` object.
func keyFn(obj interface{}) (string, error) {
info, ok := obj.(*syncCommitteeIndexPosition)
if !ok {
return "", errNotSyncCommitteeIndexPosition
}
return string(info.currentSyncCommitteeRoot[:]), nil
}

View File

@@ -0,0 +1,32 @@
// +build libfuzzer
package cache
import (
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
)
// FakeSyncCommitteeCache is a fake `SyncCommitteeCache` to satisfy fuzzing.
type FakeSyncCommitteeCache struct {
}
// NewSyncCommittee initializes and returns a new SyncCommitteeCache.
func NewSyncCommittee() *FakeSyncCommitteeCache {
return &FakeSyncCommitteeCache{}
}
// CurrentEpochIndexPosition -- fake.
func (s *FakeSyncCommitteeCache) CurrentPeriodIndexPosition(root [32]byte, valIdx types.ValidatorIndex) ([]types.CommitteeIndex, error) {
return nil, nil
}
// NextEpochIndexPosition -- fake.
func (s *FakeSyncCommitteeCache) NextPeriodIndexPosition(root [32]byte, valIdx types.ValidatorIndex) ([]types.CommitteeIndex, error) {
return nil, nil
}
// UpdatePositionsInCommittee -- fake.
func (s *FakeSyncCommitteeCache) UpdatePositionsInCommittee(syncCommitteeBoundaryRoot [32]byte, state state.BeaconStateAltair) error {
return nil
}

View File

@@ -0,0 +1,222 @@
package cache_test
import (
"testing"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"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"
)
func TestSyncCommitteeCache_CanUpdateAndRetrieve(t *testing.T) {
numValidators := 101
deterministicState, _ := testutil.DeterministicGenesisStateAltair(t, uint64(numValidators))
pubKeys := make([][]byte, deterministicState.NumValidators())
for i, val := range deterministicState.Validators() {
pubKeys[i] = val.PublicKey
}
tests := []struct {
name string
currentSyncCommittee *ethpb.SyncCommittee
nextSyncCommittee *ethpb.SyncCommittee
currentSyncMap map[types.ValidatorIndex][]types.CommitteeIndex
nextSyncMap map[types.ValidatorIndex][]types.CommitteeIndex
}{
{
name: "only current epoch",
currentSyncCommittee: convertToCommittee([][]byte{
pubKeys[1], pubKeys[2], pubKeys[3], pubKeys[2], pubKeys[2],
}),
nextSyncCommittee: convertToCommittee([][]byte{}),
currentSyncMap: map[types.ValidatorIndex][]types.CommitteeIndex{
1: {0},
2: {1, 3, 4},
3: {2},
},
nextSyncMap: map[types.ValidatorIndex][]types.CommitteeIndex{
1: {},
2: {},
3: {},
},
},
{
name: "only next epoch",
currentSyncCommittee: convertToCommittee([][]byte{}),
nextSyncCommittee: convertToCommittee([][]byte{
pubKeys[1], pubKeys[2], pubKeys[3], pubKeys[2], pubKeys[2],
}),
currentSyncMap: map[types.ValidatorIndex][]types.CommitteeIndex{
1: {},
2: {},
3: {},
},
nextSyncMap: map[types.ValidatorIndex][]types.CommitteeIndex{
1: {0},
2: {1, 3, 4},
3: {2},
},
},
{
name: "some current epoch and some next epoch",
currentSyncCommittee: convertToCommittee([][]byte{
pubKeys[1],
pubKeys[2],
pubKeys[3],
pubKeys[2],
pubKeys[2],
}),
nextSyncCommittee: convertToCommittee([][]byte{
pubKeys[7],
pubKeys[6],
pubKeys[5],
pubKeys[4],
pubKeys[7],
}),
currentSyncMap: map[types.ValidatorIndex][]types.CommitteeIndex{
1: {0},
2: {1, 3, 4},
3: {2},
},
nextSyncMap: map[types.ValidatorIndex][]types.CommitteeIndex{
7: {0, 4},
6: {1},
5: {2},
4: {3},
},
},
{
name: "some current epoch and some next epoch duplicated across",
currentSyncCommittee: convertToCommittee([][]byte{
pubKeys[1],
pubKeys[2],
pubKeys[3],
pubKeys[2],
pubKeys[2],
}),
nextSyncCommittee: convertToCommittee([][]byte{
pubKeys[2],
pubKeys[1],
pubKeys[3],
pubKeys[2],
pubKeys[1],
}),
currentSyncMap: map[types.ValidatorIndex][]types.CommitteeIndex{
1: {0},
2: {1, 3, 4},
3: {2},
},
nextSyncMap: map[types.ValidatorIndex][]types.CommitteeIndex{
1: {1, 4},
2: {0, 3},
3: {2},
},
},
{
name: "all duplicated",
currentSyncCommittee: convertToCommittee([][]byte{
pubKeys[100],
pubKeys[100],
pubKeys[100],
pubKeys[100],
}),
nextSyncCommittee: convertToCommittee([][]byte{
pubKeys[100],
pubKeys[100],
pubKeys[100],
pubKeys[100],
}),
currentSyncMap: map[types.ValidatorIndex][]types.CommitteeIndex{
100: {0, 1, 2, 3},
},
nextSyncMap: map[types.ValidatorIndex][]types.CommitteeIndex{
100: {0, 1, 2, 3},
},
},
{
name: "unknown keys",
currentSyncCommittee: convertToCommittee([][]byte{
pubKeys[100],
pubKeys[100],
pubKeys[100],
pubKeys[100],
}),
nextSyncCommittee: convertToCommittee([][]byte{
pubKeys[100],
pubKeys[100],
pubKeys[100],
pubKeys[100],
}),
currentSyncMap: map[types.ValidatorIndex][]types.CommitteeIndex{
1: {},
},
nextSyncMap: map[types.ValidatorIndex][]types.CommitteeIndex{
1: {},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s, _ := testutil.DeterministicGenesisStateAltair(t, uint64(numValidators))
require.NoError(t, s.SetCurrentSyncCommittee(tt.currentSyncCommittee))
require.NoError(t, s.SetNextSyncCommittee(tt.nextSyncCommittee))
cache := cache.NewSyncCommittee()
r := [32]byte{'a'}
require.NoError(t, cache.UpdatePositionsInCommittee(r, s))
for key, indices := range tt.currentSyncMap {
pos, err := cache.CurrentPeriodIndexPosition(r, key)
require.NoError(t, err)
require.DeepEqual(t, indices, pos)
}
for key, indices := range tt.nextSyncMap {
pos, err := cache.NextPeriodIndexPosition(r, key)
require.NoError(t, err)
require.DeepEqual(t, indices, pos)
}
})
}
}
func TestSyncCommitteeCache_RootDoesNotExist(t *testing.T) {
c := cache.NewSyncCommittee()
_, err := c.CurrentPeriodIndexPosition([32]byte{}, 0)
require.Equal(t, cache.ErrNonExistingSyncCommitteeKey, err)
}
func TestSyncCommitteeCache_CanRotate(t *testing.T) {
c := cache.NewSyncCommittee()
s, _ := testutil.DeterministicGenesisStateAltair(t, 64)
require.NoError(t, s.SetCurrentSyncCommittee(convertToCommittee([][]byte{{1}})))
require.NoError(t, c.UpdatePositionsInCommittee([32]byte{'a'}, s))
require.NoError(t, s.SetCurrentSyncCommittee(convertToCommittee([][]byte{{2}})))
require.NoError(t, c.UpdatePositionsInCommittee([32]byte{'b'}, s))
require.NoError(t, s.SetCurrentSyncCommittee(convertToCommittee([][]byte{{3}})))
require.NoError(t, c.UpdatePositionsInCommittee([32]byte{'c'}, s))
require.NoError(t, s.SetCurrentSyncCommittee(convertToCommittee([][]byte{{4}})))
require.NoError(t, c.UpdatePositionsInCommittee([32]byte{'d'}, s))
_, err := c.CurrentPeriodIndexPosition([32]byte{'a'}, 0)
require.Equal(t, cache.ErrNonExistingSyncCommitteeKey, err)
_, err = c.CurrentPeriodIndexPosition([32]byte{'c'}, 0)
require.NoError(t, err)
}
func convertToCommittee(inputKeys [][]byte) *ethpb.SyncCommittee {
var pubKeys [][]byte
for i := uint64(0); i < params.BeaconConfig().SyncCommitteeSize; i++ {
if i < uint64(len(inputKeys)) {
pubKeys = append(pubKeys, bytesutil.PadTo(inputKeys[i], params.BeaconConfig().BLSPubkeyLength))
} else {
pubKeys = append(pubKeys, bytesutil.PadTo([]byte{}, params.BeaconConfig().BLSPubkeyLength))
}
}
return &ethpb.SyncCommittee{
Pubkeys: pubKeys,
AggregatePubkey: bytesutil.PadTo([]byte{}, params.BeaconConfig().BLSPubkeyLength),
}
}

131
beacon-chain/cache/sync_subnet_ids.go vendored Normal file
View File

@@ -0,0 +1,131 @@
package cache
import (
"sync"
"time"
"github.com/patrickmn/go-cache"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/rand"
"github.com/prysmaticlabs/prysm/shared/sliceutil"
)
type syncSubnetIDs struct {
sCommittee *cache.Cache
sCommiteeLock sync.RWMutex
}
// SyncSubnetIDs for sync committee participant.
var SyncSubnetIDs = newSyncSubnetIDs()
func newSyncSubnetIDs() *syncSubnetIDs {
epochDuration := time.Duration(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().SecondsPerSlot))
// Set the default duration of a sync subnet index as the whole sync committee period.
subLength := epochDuration * time.Duration(params.BeaconConfig().EpochsPerSyncCommitteePeriod)
persistentCache := cache.New(subLength*time.Second, epochDuration*time.Second)
return &syncSubnetIDs{sCommittee: persistentCache}
}
// GetSyncCommitteeSubnets retrieves the sync committee subnet and expiration time of that validator's subscription.
func (s *syncSubnetIDs) GetSyncCommitteeSubnets(pubkey []byte, epoch types.Epoch) ([]uint64, types.Epoch, bool, time.Time) {
s.sCommiteeLock.RLock()
defer s.sCommiteeLock.RUnlock()
id, duration, ok := s.sCommittee.GetWithExpiration(keyBuilder(pubkey, epoch))
if !ok {
return []uint64{}, 0, ok, time.Time{}
}
// Retrieve indices from the cache.
idxs, ok := id.([]uint64)
if !ok {
return []uint64{}, 0, ok, time.Time{}
}
// If no committees are saved, we return nothing.
if len(idxs) <= 1 {
return []uint64{}, 0, ok, time.Time{}
}
// Index 0 was used to store validator's join epoch. We do not
// return it to the caller.
// Index 1 and beyond were used to store subnets.
return idxs[1:], types.Epoch(idxs[0]), ok, duration
}
// GetAllSubnets retrieves all the non-expired subscribed subnets of all the validators
// in the cache. This method also takes the epoch as an argument to only retrieve
// assignments for epochs that have happened.
func (s *syncSubnetIDs) GetAllSubnets(currEpoch types.Epoch) []uint64 {
s.sCommiteeLock.RLock()
defer s.sCommiteeLock.RUnlock()
itemsMap := s.sCommittee.Items()
var committees []uint64
for _, v := range itemsMap {
if v.Expired() {
continue
}
idxs, ok := v.Object.([]uint64)
if !ok {
continue
}
// We skip if we do not have a join
// epoch or any relevant committee indices.
if len(idxs) <= 1 {
continue
}
// Check if the subnet is valid in the current epoch. If our
// join epoch is still in the future we skip retrieving the
// relevant committee index.
if types.Epoch(idxs[0]) > currEpoch {
continue
}
// Ignore the first index as that represents the
// epoch of the validator's assignments.
committees = append(committees, idxs[1:]...)
}
return sliceutil.SetUint64(committees)
}
// AddSyncCommitteeSubnets adds the relevant committee for that particular validator along with its
// expiration period. An Epoch argument here denotes the epoch from which the sync committee subnets
// will be active.
func (s *syncSubnetIDs) AddSyncCommitteeSubnets(pubkey []byte, epoch types.Epoch, comIndex []uint64, duration time.Duration) {
s.sCommiteeLock.Lock()
defer s.sCommiteeLock.Unlock()
subComCount := params.BeaconConfig().SyncCommitteeSubnetCount
// To join a sync committee subnet, select a random number of epochs before the end of the
// current sync committee period between 1 and SYNC_COMMITTEE_SUBNET_COUNT, inclusive.
// This is to smoothing out the join and exiting of the subnets so not everyone surging at the same time.
diff := (rand.NewGenerator().Uint64() % subComCount) + 1
joinEpoch, err := epoch.SafeSub(diff)
if err != nil {
// If we underflow here, we simply set the value to join
// at 0.
joinEpoch = 0
}
// Append the epoch of the subnet into the first index here. The join epoch is a special
// value, it is the epoch at which a node is supposed to join the relevant subnets.
s.sCommittee.Set(keyBuilder(pubkey, epoch), append([]uint64{uint64(joinEpoch)}, comIndex...), duration)
}
// EmptyAllCaches empties out all the related caches and flushes any stored
// entries on them. This should only ever be used for testing, in normal
// production, handling of the relevant subnets for each role is done
// separately.
func (s *syncSubnetIDs) EmptyAllCaches() {
// Clear the cache.
s.sCommiteeLock.Lock()
s.sCommittee.Flush()
s.sCommiteeLock.Unlock()
}
// build a key composed of both the pubkey and epoch here. The epoch
// here would be the 1st epoch of the sync committee period.
func keyBuilder(pubkey []byte, epoch types.Epoch) string {
epochBytes := bytesutil.Bytes8(uint64(epoch))
return string(append(pubkey, epochBytes...))
}

View File

@@ -0,0 +1,57 @@
package cache
import (
"testing"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
)
func TestSyncSubnetIDsCache_Roundtrip(t *testing.T) {
c := newSyncSubnetIDs()
for i := 0; i < 20; i++ {
pubkey := [48]byte{byte(i)}
c.AddSyncCommitteeSubnets(pubkey[:], 100, []uint64{uint64(i)}, 0)
}
for i := uint64(0); i < 20; i++ {
pubkey := [48]byte{byte(i)}
idxs, _, ok, _ := c.GetSyncCommitteeSubnets(pubkey[:], 100)
if !ok {
t.Errorf("Couldn't find entry in cache for pubkey %#x", pubkey)
continue
}
require.Equal(t, i, idxs[0])
}
coms := c.GetAllSubnets(100)
assert.Equal(t, 20, len(coms))
}
func TestSyncSubnetIDsCache_ValidateCurrentEpoch(t *testing.T) {
c := newSyncSubnetIDs()
for i := 0; i < 20; i++ {
pubkey := [48]byte{byte(i)}
c.AddSyncCommitteeSubnets(pubkey[:], 100, []uint64{uint64(i)}, 0)
}
coms := c.GetAllSubnets(50)
assert.Equal(t, 0, len(coms))
for i := uint64(0); i < 20; i++ {
pubkey := [48]byte{byte(i)}
_, jEpoch, ok, _ := c.GetSyncCommitteeSubnets(pubkey[:], 100)
if !ok {
t.Errorf("Couldn't find entry in cache for pubkey %#x", pubkey)
continue
}
require.Equal(t, true, uint64(jEpoch) >= 100-params.BeaconConfig().SyncCommitteeSubnetCount)
}
coms = c.GetAllSubnets(99)
assert.Equal(t, 20, len(coms))
}

View File

@@ -0,0 +1,86 @@
load("@prysm//tools/go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"attestation.go",
"block.go",
"deposit.go",
"epoch_precompute.go",
"epoch_spec.go",
"reward.go",
"sync_committee.go",
"transition.go",
"upgrade.go",
"validator.go",
],
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/core/altair",
visibility = [
"//beacon-chain:__subpackages__",
"//shared/testutil:__pkg__",
"//spectest:__subpackages__",
"//validator/client:__pkg__",
],
deps = [
"//beacon-chain/core/blocks:go_default_library",
"//beacon-chain/core/epoch:go_default_library",
"//beacon-chain/core/epoch/precompute:go_default_library",
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/core/validators:go_default_library",
"//beacon-chain/p2p/types:go_default_library",
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/v2:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//proto/prysm/v1alpha1/block:go_default_library",
"//shared/attestationutil:go_default_library",
"//shared/bls:go_default_library",
"//shared/bytesutil:go_default_library",
"//shared/hashutil: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",
"@io_opencensus_go//trace:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = [
"attestation_test.go",
"block_test.go",
"deposit_fuzz_test.go",
"deposit_test.go",
"epoch_precompute_test.go",
"epoch_spec_test.go",
"reward_test.go",
"sync_committee_test.go",
"transition_test.go",
"upgrade_test.go",
"validator_test.go",
],
embed = [":go_default_library"],
deps = [
"//beacon-chain/core/epoch/precompute:go_default_library",
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/p2p/types:go_default_library",
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/v2:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//proto/prysm/v1alpha1/wrapper:go_default_library",
"//shared/attestationutil:go_default_library",
"//shared/bls:go_default_library",
"//shared/bytesutil:go_default_library",
"//shared/mathutil:go_default_library",
"//shared/params:go_default_library",
"//shared/testutil:go_default_library",
"//shared/testutil/assert:go_default_library",
"//shared/testutil/require:go_default_library",
"//shared/timeutils:go_default_library",
"//shared/trieutil:go_default_library",
"@com_github_google_gofuzz//:go_default_library",
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
"@org_golang_google_protobuf//proto:go_default_library",
],
)

View File

@@ -0,0 +1,299 @@
package altair
import (
"bytes"
"context"
"fmt"
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
"github.com/prysmaticlabs/prysm/shared/attestationutil"
"github.com/prysmaticlabs/prysm/shared/params"
"go.opencensus.io/trace"
)
// ProcessAttestationsNoVerifySignature applies processing operations to a block's inner attestation
// records. The only difference would be that the attestation signature would not be verified.
func ProcessAttestationsNoVerifySignature(
ctx context.Context,
beaconState state.BeaconState,
b block.SignedBeaconBlock,
) (state.BeaconState, error) {
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
return nil, err
}
body := b.Block().Body()
var err error
for idx, attestation := range body.Attestations() {
beaconState, err = ProcessAttestationNoVerifySignature(ctx, beaconState, attestation)
if err != nil {
return nil, errors.Wrapf(err, "could not verify attestation at index %d in block", idx)
}
}
return beaconState, nil
}
// ProcessAttestationNoVerifySignature processes the attestation without verifying the attestation signature. This
// method is used to validate attestations whose signatures have already been verified or will be verified later.
func ProcessAttestationNoVerifySignature(
ctx context.Context,
beaconState state.BeaconStateAltair,
att *ethpb.Attestation,
) (state.BeaconStateAltair, error) {
ctx, span := trace.StartSpan(ctx, "altair.ProcessAttestationNoVerifySignature")
defer span.End()
if err := blocks.VerifyAttestationNoVerifySignature(ctx, beaconState, att); err != nil {
return nil, err
}
delay, err := beaconState.Slot().SafeSubSlot(att.Data.Slot)
if err != nil {
return nil, fmt.Errorf("att slot %d can't be greater than state slot %d", att.Data.Slot, beaconState.Slot())
}
participatedFlags, err := AttestationParticipationFlagIndices(beaconState, att.Data, delay)
if err != nil {
return nil, err
}
committee, err := helpers.BeaconCommitteeFromState(beaconState, att.Data.Slot, att.Data.CommitteeIndex)
if err != nil {
return nil, err
}
indices, err := attestationutil.AttestingIndices(att.AggregationBits, committee)
if err != nil {
return nil, err
}
return SetParticipationAndRewardProposer(beaconState, att.Data.Target.Epoch, indices, participatedFlags)
}
// SetParticipationAndRewardProposer retrieves and sets the epoch participation bits in state. Based on the epoch participation, it rewards
// the proposer in state.
//
// Spec code:
// # Update epoch participation flags
// if data.target.epoch == get_current_epoch(state):
// epoch_participation = state.current_epoch_participation
// else:
// epoch_participation = state.previous_epoch_participation
//
// proposer_reward_numerator = 0
// for index in get_attesting_indices(state, data, attestation.aggregation_bits):
// for flag_index, weight in enumerate(PARTICIPATION_FLAG_WEIGHTS):
// if flag_index in participation_flag_indices and not has_flag(epoch_participation[index], flag_index):
// epoch_participation[index] = add_flag(epoch_participation[index], flag_index)
// proposer_reward_numerator += get_base_reward(state, index) * weight
//
// # Reward proposer
// proposer_reward_denominator = (WEIGHT_DENOMINATOR - PROPOSER_WEIGHT) * WEIGHT_DENOMINATOR // PROPOSER_WEIGHT
// proposer_reward = Gwei(proposer_reward_numerator // proposer_reward_denominator)
// increase_balance(state, get_beacon_proposer_index(state), proposer_reward)
func SetParticipationAndRewardProposer(
beaconState state.BeaconState,
targetEpoch types.Epoch,
indices []uint64,
participatedFlags map[uint8]bool) (state.BeaconState, error) {
var epochParticipation []byte
currentEpoch := helpers.CurrentEpoch(beaconState)
var err error
if targetEpoch == currentEpoch {
epochParticipation, err = beaconState.CurrentEpochParticipation()
if err != nil {
return nil, err
}
} else {
epochParticipation, err = beaconState.PreviousEpochParticipation()
if err != nil {
return nil, err
}
}
proposerRewardNumerator, epochParticipation, err := EpochParticipation(beaconState, indices, epochParticipation, participatedFlags)
if err != nil {
return nil, err
}
if targetEpoch == currentEpoch {
if err := beaconState.SetCurrentParticipationBits(epochParticipation); err != nil {
return nil, err
}
} else {
if err := beaconState.SetPreviousParticipationBits(epochParticipation); err != nil {
return nil, err
}
}
if err := RewardProposer(beaconState, proposerRewardNumerator); err != nil {
return nil, err
}
return beaconState, nil
}
// HasValidatorFlag returns true if the flag at position has set.
func HasValidatorFlag(flag, flagPosition uint8) bool {
return ((flag >> flagPosition) & 1) == 1
}
// AddValidatorFlag adds new validator flag to existing one.
func AddValidatorFlag(flag, flagPosition uint8) uint8 {
return flag | (1 << flagPosition)
}
// EpochParticipation sets and returns the proposer reward numerator and epoch participation.
//
// Spec code:
// proposer_reward_numerator = 0
// for index in get_attesting_indices(state, data, attestation.aggregation_bits):
// for flag_index, weight in enumerate(PARTICIPATION_FLAG_WEIGHTS):
// if flag_index in participation_flag_indices and not has_flag(epoch_participation[index], flag_index):
// epoch_participation[index] = add_flag(epoch_participation[index], flag_index)
// proposer_reward_numerator += get_base_reward(state, index) * weight
func EpochParticipation(beaconState state.BeaconState, indices []uint64, epochParticipation []byte, participatedFlags map[uint8]bool) (uint64, []byte, error) {
cfg := params.BeaconConfig()
sourceFlagIndex := cfg.TimelySourceFlagIndex
targetFlagIndex := cfg.TimelyTargetFlagIndex
headFlagIndex := cfg.TimelyHeadFlagIndex
proposerRewardNumerator := uint64(0)
totalBalance, err := helpers.TotalActiveBalance(beaconState)
if err != nil {
return 0, nil, err
}
for _, index := range indices {
if index >= uint64(len(epochParticipation)) {
return 0, nil, fmt.Errorf("index %d exceeds participation length %d", index, len(epochParticipation))
}
br, err := BaseRewardWithTotalBalance(beaconState, types.ValidatorIndex(index), totalBalance)
if err != nil {
return 0, nil, err
}
if participatedFlags[sourceFlagIndex] && !HasValidatorFlag(epochParticipation[index], sourceFlagIndex) {
epochParticipation[index] = AddValidatorFlag(epochParticipation[index], sourceFlagIndex)
proposerRewardNumerator += br * cfg.TimelySourceWeight
}
if participatedFlags[targetFlagIndex] && !HasValidatorFlag(epochParticipation[index], targetFlagIndex) {
epochParticipation[index] = AddValidatorFlag(epochParticipation[index], targetFlagIndex)
proposerRewardNumerator += br * cfg.TimelyTargetWeight
}
if participatedFlags[headFlagIndex] && !HasValidatorFlag(epochParticipation[index], headFlagIndex) {
epochParticipation[index] = AddValidatorFlag(epochParticipation[index], headFlagIndex)
proposerRewardNumerator += br * cfg.TimelyHeadWeight
}
}
return proposerRewardNumerator, epochParticipation, nil
}
// RewardProposer rewards proposer by increasing proposer's balance with input reward numerator and calculated reward denominator.
//
// Spec code:
// proposer_reward_denominator = (WEIGHT_DENOMINATOR - PROPOSER_WEIGHT) * WEIGHT_DENOMINATOR // PROPOSER_WEIGHT
// proposer_reward = Gwei(proposer_reward_numerator // proposer_reward_denominator)
// increase_balance(state, get_beacon_proposer_index(state), proposer_reward)
func RewardProposer(beaconState state.BeaconState, proposerRewardNumerator uint64) error {
cfg := params.BeaconConfig()
d := (cfg.WeightDenominator - cfg.ProposerWeight) * cfg.WeightDenominator / cfg.ProposerWeight
proposerReward := proposerRewardNumerator / d
i, err := helpers.BeaconProposerIndex(beaconState)
if err != nil {
return err
}
return helpers.IncreaseBalance(beaconState, i, proposerReward)
}
// AttestationParticipationFlagIndices retrieves a map of attestation scoring based on Altair's participation flag indices.
// This is used to facilitate process attestation during state transition and during upgrade to altair state.
//
// Spec code:
// def get_attestation_participation_flag_indices(state: BeaconState,
// data: AttestationData,
// inclusion_delay: uint64) -> Sequence[int]:
// """
// Return the flag indices that are satisfied by an attestation.
// """
// if data.target.epoch == get_current_epoch(state):
// justified_checkpoint = state.current_justified_checkpoint
// else:
// justified_checkpoint = state.previous_justified_checkpoint
//
// # Matching roots
// is_matching_source = data.source == justified_checkpoint
// is_matching_target = is_matching_source and data.target.root == get_block_root(state, data.target.epoch)
// is_matching_head = is_matching_target and data.beacon_block_root == get_block_root_at_slot(state, data.slot)
// assert is_matching_source
//
// participation_flag_indices = []
// if is_matching_source and inclusion_delay <= integer_squareroot(SLOTS_PER_EPOCH):
// participation_flag_indices.append(TIMELY_SOURCE_FLAG_INDEX)
// if is_matching_target and inclusion_delay <= SLOTS_PER_EPOCH:
// participation_flag_indices.append(TIMELY_TARGET_FLAG_INDEX)
// if is_matching_head and inclusion_delay == MIN_ATTESTATION_INCLUSION_DELAY:
// participation_flag_indices.append(TIMELY_HEAD_FLAG_INDEX)
//
// return participation_flag_indices
func AttestationParticipationFlagIndices(beaconState state.BeaconStateAltair, data *ethpb.AttestationData, delay types.Slot) (map[uint8]bool, error) {
currEpoch := helpers.CurrentEpoch(beaconState)
var justifiedCheckpt *ethpb.Checkpoint
if data.Target.Epoch == currEpoch {
justifiedCheckpt = beaconState.CurrentJustifiedCheckpoint()
} else {
justifiedCheckpt = beaconState.PreviousJustifiedCheckpoint()
}
matchedSrc, matchedTgt, matchedHead, err := MatchingStatus(beaconState, data, justifiedCheckpt)
if err != nil {
return nil, err
}
if !matchedSrc {
return nil, errors.New("source epoch does not match")
}
participatedFlags := make(map[uint8]bool)
cfg := params.BeaconConfig()
sourceFlagIndex := cfg.TimelySourceFlagIndex
targetFlagIndex := cfg.TimelyTargetFlagIndex
headFlagIndex := cfg.TimelyHeadFlagIndex
slotsPerEpoch := cfg.SlotsPerEpoch
sqtRootSlots := cfg.SqrRootSlotsPerEpoch
if matchedSrc && delay <= sqtRootSlots {
participatedFlags[sourceFlagIndex] = true
}
matchedSrcTgt := matchedSrc && matchedTgt
if matchedSrcTgt && delay <= slotsPerEpoch {
participatedFlags[targetFlagIndex] = true
}
matchedSrcTgtHead := matchedHead && matchedSrcTgt
if matchedSrcTgtHead && delay == cfg.MinAttestationInclusionDelay {
participatedFlags[headFlagIndex] = true
}
return participatedFlags, nil
}
// MatchingStatus returns the matching statues for attestation data's source target and head.
//
// Spec code:
// is_matching_source = data.source == justified_checkpoint
// is_matching_target = is_matching_source and data.target.root == get_block_root(state, data.target.epoch)
// is_matching_head = is_matching_target and data.beacon_block_root == get_block_root_at_slot(state, data.slot)
func MatchingStatus(beaconState state.BeaconState, data *ethpb.AttestationData, cp *ethpb.Checkpoint) (matchedSrc bool, matchedTgt bool, matchedHead bool, err error) {
matchedSrc = attestationutil.CheckPointIsEqual(data.Source, cp)
r, err := helpers.BlockRoot(beaconState, data.Target.Epoch)
if err != nil {
return false, false, false, err
}
matchedTgt = bytes.Equal(r, data.Target.Root)
r, err = helpers.BlockRootAtSlot(beaconState, data.Slot)
if err != nil {
return false, false, false, err
}
matchedHead = bytes.Equal(r, data.BeaconBlockRoot)
return
}

View File

@@ -0,0 +1,746 @@
package altair_test
import (
"context"
"fmt"
"testing"
fuzz "github.com/google/gofuzz"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/go-bitfield"
"github.com/prysmaticlabs/prysm/beacon-chain/core/altair"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state/v2"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
"github.com/prysmaticlabs/prysm/shared/attestationutil"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/mathutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
)
func TestProcessAttestations_InclusionDelayFailure(t *testing.T) {
attestations := []*ethpb.Attestation{
testutil.HydrateAttestation(&ethpb.Attestation{
Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 0, Root: make([]byte, 32)},
Slot: 5,
},
}),
}
b := testutil.NewBeaconBlockAltair()
b.Block = &ethpb.BeaconBlockAltair{
Body: &ethpb.BeaconBlockBodyAltair{
Attestations: attestations,
},
}
beaconState, _ := testutil.DeterministicGenesisStateAltair(t, 100)
want := fmt.Sprintf(
"attestation slot %d + inclusion delay %d > state slot %d",
attestations[0].Data.Slot,
params.BeaconConfig().MinAttestationInclusionDelay,
beaconState.Slot(),
)
wsb, err := wrapper.WrappedAltairSignedBeaconBlock(b)
require.NoError(t, err)
_, err = altair.ProcessAttestationsNoVerifySignature(context.Background(), beaconState, wsb)
require.ErrorContains(t, want, err)
}
func TestProcessAttestations_NeitherCurrentNorPrevEpoch(t *testing.T) {
att := testutil.HydrateAttestation(&ethpb.Attestation{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
Target: &ethpb.Checkpoint{Epoch: 0}}})
b := testutil.NewBeaconBlockAltair()
b.Block = &ethpb.BeaconBlockAltair{
Body: &ethpb.BeaconBlockBodyAltair{
Attestations: []*ethpb.Attestation{att},
},
}
beaconState, _ := testutil.DeterministicGenesisStateAltair(t, 100)
err := beaconState.SetSlot(beaconState.Slot() + params.BeaconConfig().SlotsPerEpoch*4 + params.BeaconConfig().MinAttestationInclusionDelay)
require.NoError(t, err)
pfc := beaconState.PreviousJustifiedCheckpoint()
pfc.Root = []byte("hello-world")
require.NoError(t, beaconState.SetPreviousJustifiedCheckpoint(pfc))
want := fmt.Sprintf(
"expected target epoch (%d) to be the previous epoch (%d) or the current epoch (%d)",
att.Data.Target.Epoch,
helpers.PrevEpoch(beaconState),
helpers.CurrentEpoch(beaconState),
)
wsb, err := wrapper.WrappedAltairSignedBeaconBlock(b)
require.NoError(t, err)
_, err = altair.ProcessAttestationsNoVerifySignature(context.Background(), beaconState, wsb)
require.ErrorContains(t, want, err)
}
func TestProcessAttestations_CurrentEpochFFGDataMismatches(t *testing.T) {
attestations := []*ethpb.Attestation{
{
Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 0, Root: make([]byte, 32)},
Source: &ethpb.Checkpoint{Epoch: 1, Root: make([]byte, 32)},
},
AggregationBits: bitfield.Bitlist{0x09},
},
}
b := testutil.NewBeaconBlockAltair()
b.Block = &ethpb.BeaconBlockAltair{
Body: &ethpb.BeaconBlockBodyAltair{
Attestations: attestations,
},
}
beaconState, _ := testutil.DeterministicGenesisStateAltair(t, 100)
require.NoError(t, beaconState.SetSlot(beaconState.Slot()+params.BeaconConfig().MinAttestationInclusionDelay))
cfc := beaconState.CurrentJustifiedCheckpoint()
cfc.Root = []byte("hello-world")
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(cfc))
want := "source check point not equal to current justified checkpoint"
wsb, err := wrapper.WrappedAltairSignedBeaconBlock(b)
require.NoError(t, err)
_, err = altair.ProcessAttestationsNoVerifySignature(context.Background(), beaconState, wsb)
require.ErrorContains(t, want, err)
b.Block.Body.Attestations[0].Data.Source.Epoch = helpers.CurrentEpoch(beaconState)
b.Block.Body.Attestations[0].Data.Source.Root = []byte{}
wsb, err = wrapper.WrappedAltairSignedBeaconBlock(b)
require.NoError(t, err)
_, err = altair.ProcessAttestationsNoVerifySignature(context.Background(), beaconState, wsb)
require.ErrorContains(t, want, err)
}
func TestProcessAttestations_PrevEpochFFGDataMismatches(t *testing.T) {
beaconState, _ := testutil.DeterministicGenesisStateAltair(t, 100)
aggBits := bitfield.NewBitlist(3)
aggBits.SetBitAt(0, true)
attestations := []*ethpb.Attestation{
{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 1, Root: make([]byte, 32)},
Target: &ethpb.Checkpoint{Epoch: 1, Root: make([]byte, 32)},
Slot: params.BeaconConfig().SlotsPerEpoch,
},
AggregationBits: aggBits,
},
}
b := testutil.NewBeaconBlockAltair()
b.Block = &ethpb.BeaconBlockAltair{
Body: &ethpb.BeaconBlockBodyAltair{
Attestations: attestations,
},
}
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))
want := "source check point not equal to previous justified checkpoint"
wsb, err := wrapper.WrappedAltairSignedBeaconBlock(b)
require.NoError(t, err)
_, err = altair.ProcessAttestationsNoVerifySignature(context.Background(), beaconState, wsb)
require.ErrorContains(t, want, err)
b.Block.Body.Attestations[0].Data.Source.Epoch = helpers.PrevEpoch(beaconState)
b.Block.Body.Attestations[0].Data.Target.Epoch = helpers.PrevEpoch(beaconState)
b.Block.Body.Attestations[0].Data.Source.Root = []byte{}
wsb, err = wrapper.WrappedAltairSignedBeaconBlock(b)
require.NoError(t, err)
_, err = altair.ProcessAttestationsNoVerifySignature(context.Background(), beaconState, wsb)
require.ErrorContains(t, want, err)
}
func TestProcessAttestations_InvalidAggregationBitsLength(t *testing.T) {
beaconState, _ := testutil.DeterministicGenesisStateAltair(t, 100)
aggBits := bitfield.NewBitlist(4)
att := &ethpb.Attestation{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
Target: &ethpb.Checkpoint{Epoch: 0}},
AggregationBits: aggBits,
}
b := testutil.NewBeaconBlockAltair()
b.Block = &ethpb.BeaconBlockAltair{
Body: &ethpb.BeaconBlockBodyAltair{
Attestations: []*ethpb.Attestation{att},
},
}
err := beaconState.SetSlot(beaconState.Slot() + params.BeaconConfig().MinAttestationInclusionDelay)
require.NoError(t, err)
cfc := beaconState.CurrentJustifiedCheckpoint()
cfc.Root = []byte("hello-world")
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(cfc))
expected := "failed to verify aggregation bitfield: wanted participants bitfield length 3, got: 4"
wsb, err := wrapper.WrappedAltairSignedBeaconBlock(b)
require.NoError(t, err)
_, err = altair.ProcessAttestationsNoVerifySignature(context.Background(), beaconState, wsb)
require.ErrorContains(t, expected, err)
}
func TestProcessAttestations_OK(t *testing.T) {
beaconState, privKeys := testutil.DeterministicGenesisStateAltair(t, 100)
aggBits := bitfield.NewBitlist(3)
aggBits.SetBitAt(0, true)
var mockRoot [32]byte
copy(mockRoot[:], "hello-world")
att := testutil.HydrateAttestation(&ethpb.Attestation{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Root: mockRoot[:]},
Target: &ethpb.Checkpoint{Root: mockRoot[:]},
},
AggregationBits: aggBits,
})
cfc := beaconState.CurrentJustifiedCheckpoint()
cfc.Root = mockRoot[:]
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(cfc))
committee, err := helpers.BeaconCommitteeFromState(beaconState, att.Data.Slot, att.Data.CommitteeIndex)
require.NoError(t, err)
attestingIndices, err := attestationutil.AttestingIndices(att.AggregationBits, committee)
require.NoError(t, err)
sigs := make([]bls.Signature, len(attestingIndices))
for i, indice := range attestingIndices {
sb, err := helpers.ComputeDomainAndSign(beaconState, 0, att.Data, params.BeaconConfig().DomainBeaconAttester, privKeys[indice])
require.NoError(t, err)
sig, err := bls.SignatureFromBytes(sb)
require.NoError(t, err)
sigs[i] = sig
}
att.Signature = bls.AggregateSignatures(sigs).Marshal()
block := testutil.NewBeaconBlockAltair()
block.Block.Body.Attestations = []*ethpb.Attestation{att}
err = beaconState.SetSlot(beaconState.Slot() + params.BeaconConfig().MinAttestationInclusionDelay)
require.NoError(t, err)
wsb, err := wrapper.WrappedAltairSignedBeaconBlock(block)
require.NoError(t, err)
_, err = altair.ProcessAttestationsNoVerifySignature(context.Background(), beaconState, wsb)
require.NoError(t, err)
}
func TestProcessAttestationNoVerify_SourceTargetHead(t *testing.T) {
beaconState, _ := testutil.DeterministicGenesisStateAltair(t, 64)
err := beaconState.SetSlot(beaconState.Slot() + params.BeaconConfig().MinAttestationInclusionDelay)
require.NoError(t, err)
aggBits := bitfield.NewBitlist(2)
aggBits.SetBitAt(0, true)
aggBits.SetBitAt(1, true)
r, err := helpers.BlockRootAtSlot(beaconState, 0)
require.NoError(t, err)
att := &ethpb.Attestation{
Data: &ethpb.AttestationData{
BeaconBlockRoot: r,
Source: &ethpb.Checkpoint{Epoch: 0, Root: make([]byte, 32)},
Target: &ethpb.Checkpoint{Epoch: 0, Root: make([]byte, 32)},
},
AggregationBits: aggBits,
}
zeroSig := [96]byte{}
att.Signature = zeroSig[:]
ckp := beaconState.CurrentJustifiedCheckpoint()
copy(ckp.Root, make([]byte, 32))
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(ckp))
beaconState, err = altair.ProcessAttestationNoVerifySignature(context.Background(), beaconState, att)
require.NoError(t, err)
p, err := beaconState.CurrentEpochParticipation()
require.NoError(t, err)
committee, err := helpers.BeaconCommitteeFromState(beaconState, att.Data.Slot, att.Data.CommitteeIndex)
require.NoError(t, err)
indices, err := attestationutil.AttestingIndices(att.AggregationBits, committee)
require.NoError(t, err)
for _, index := range indices {
require.Equal(t, true, altair.HasValidatorFlag(p[index], params.BeaconConfig().TimelyHeadFlagIndex))
require.Equal(t, true, altair.HasValidatorFlag(p[index], params.BeaconConfig().TimelyTargetFlagIndex))
require.Equal(t, true, altair.HasValidatorFlag(p[index], params.BeaconConfig().TimelySourceFlagIndex))
}
}
func TestValidatorFlag_Has(t *testing.T) {
tests := []struct {
name string
set uint8
expected []uint8
}{
{name: "none",
set: 0,
expected: []uint8{},
},
{
name: "source",
set: 1,
expected: []uint8{params.BeaconConfig().TimelySourceFlagIndex},
},
{
name: "target",
set: 2,
expected: []uint8{params.BeaconConfig().TimelyTargetFlagIndex},
},
{
name: "head",
set: 4,
expected: []uint8{params.BeaconConfig().TimelyHeadFlagIndex},
},
{
name: "source, target",
set: 3,
expected: []uint8{params.BeaconConfig().TimelySourceFlagIndex, params.BeaconConfig().TimelyTargetFlagIndex},
},
{
name: "source, head",
set: 5,
expected: []uint8{params.BeaconConfig().TimelySourceFlagIndex, params.BeaconConfig().TimelyHeadFlagIndex},
},
{
name: "target, head",
set: 6,
expected: []uint8{params.BeaconConfig().TimelyTargetFlagIndex, params.BeaconConfig().TimelyTargetFlagIndex},
},
{
name: "source, target, head",
set: 7,
expected: []uint8{params.BeaconConfig().TimelySourceFlagIndex, params.BeaconConfig().TimelyTargetFlagIndex, params.BeaconConfig().TimelyHeadFlagIndex},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
for _, f := range tt.expected {
require.Equal(t, true, altair.HasValidatorFlag(tt.set, f))
}
})
}
}
func TestValidatorFlag_Add(t *testing.T) {
tests := []struct {
name string
set []uint8
expectedTrue []uint8
expectedFalse []uint8
}{
{name: "none",
set: []uint8{},
expectedTrue: []uint8{},
expectedFalse: []uint8{params.BeaconConfig().TimelySourceFlagIndex, params.BeaconConfig().TimelyTargetFlagIndex, params.BeaconConfig().TimelyHeadFlagIndex},
},
{
name: "source",
set: []uint8{params.BeaconConfig().TimelySourceFlagIndex},
expectedTrue: []uint8{params.BeaconConfig().TimelySourceFlagIndex},
expectedFalse: []uint8{params.BeaconConfig().TimelyTargetFlagIndex, params.BeaconConfig().TimelyHeadFlagIndex},
},
{
name: "source, target",
set: []uint8{params.BeaconConfig().TimelySourceFlagIndex, params.BeaconConfig().TimelyTargetFlagIndex},
expectedTrue: []uint8{params.BeaconConfig().TimelySourceFlagIndex, params.BeaconConfig().TimelyTargetFlagIndex},
expectedFalse: []uint8{params.BeaconConfig().TimelyHeadFlagIndex},
},
{
name: "source, target, head",
set: []uint8{params.BeaconConfig().TimelySourceFlagIndex, params.BeaconConfig().TimelyTargetFlagIndex, params.BeaconConfig().TimelyHeadFlagIndex},
expectedTrue: []uint8{params.BeaconConfig().TimelySourceFlagIndex, params.BeaconConfig().TimelyTargetFlagIndex, params.BeaconConfig().TimelyHeadFlagIndex},
expectedFalse: []uint8{},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
b := uint8(0)
for _, f := range tt.set {
b = altair.AddValidatorFlag(b, f)
}
for _, f := range tt.expectedFalse {
require.Equal(t, false, altair.HasValidatorFlag(b, f))
}
for _, f := range tt.expectedTrue {
require.Equal(t, true, altair.HasValidatorFlag(b, f))
}
})
}
}
func TestFuzzProcessAttestationsNoVerify_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &ethpb.BeaconStateAltair{}
b := &ethpb.SignedBeaconBlockAltair{Block: &ethpb.BeaconBlockAltair{}}
ctx := context.Background()
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(b)
if b.Block == nil {
b.Block = &ethpb.BeaconBlockAltair{}
}
s, err := stateAltair.InitializeFromProtoUnsafe(state)
require.NoError(t, err)
wsb, err := wrapper.WrappedAltairSignedBeaconBlock(b)
require.NoError(t, err)
r, err := altair.ProcessAttestationsNoVerifySignature(ctx, s, wsb)
if err != nil && r != nil {
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, b)
}
}
}
func TestSetParticipationAndRewardProposer(t *testing.T) {
cfg := params.BeaconConfig()
sourceFlagIndex := cfg.TimelySourceFlagIndex
targetFlagIndex := cfg.TimelyTargetFlagIndex
headFlagIndex := cfg.TimelyHeadFlagIndex
tests := []struct {
name string
indices []uint64
epochParticipation []byte
participatedFlags map[uint8]bool
epoch types.Epoch
wantedBalance uint64
wantedParticipation []byte
}{
{name: "none participated",
indices: []uint64{}, epochParticipation: []byte{0, 0, 0, 0, 0, 0, 0, 0}, participatedFlags: map[uint8]bool{
sourceFlagIndex: false,
targetFlagIndex: false,
headFlagIndex: false,
},
wantedParticipation: []byte{0, 0, 0, 0, 0, 0, 0, 0},
wantedBalance: 32000000000,
},
{name: "some participated without flags",
indices: []uint64{0, 1, 2, 3}, epochParticipation: []byte{0, 0, 0, 0, 0, 0, 0, 0}, participatedFlags: map[uint8]bool{
sourceFlagIndex: false,
targetFlagIndex: false,
headFlagIndex: false,
},
wantedParticipation: []byte{0, 0, 0, 0, 0, 0, 0, 0},
wantedBalance: 32000000000,
},
{name: "some participated with some flags",
indices: []uint64{0, 1, 2, 3}, epochParticipation: []byte{0, 0, 0, 0, 0, 0, 0, 0}, participatedFlags: map[uint8]bool{
sourceFlagIndex: true,
targetFlagIndex: true,
headFlagIndex: false,
},
wantedParticipation: []byte{3, 3, 3, 3, 0, 0, 0, 0},
wantedBalance: 32000090342,
},
{name: "all participated with some flags",
indices: []uint64{0, 1, 2, 3, 4, 5, 6, 7}, epochParticipation: []byte{0, 0, 0, 0, 0, 0, 0, 0}, participatedFlags: map[uint8]bool{
sourceFlagIndex: true,
targetFlagIndex: false,
headFlagIndex: false,
},
wantedParticipation: []byte{1, 1, 1, 1, 1, 1, 1, 1},
wantedBalance: 32000063240,
},
{name: "all participated with all flags",
indices: []uint64{0, 1, 2, 3, 4, 5, 6, 7}, epochParticipation: []byte{0, 0, 0, 0, 0, 0, 0, 0}, participatedFlags: map[uint8]bool{
sourceFlagIndex: true,
targetFlagIndex: true,
headFlagIndex: true,
},
wantedParticipation: []byte{7, 7, 7, 7, 7, 7, 7, 7},
wantedBalance: 32000243925,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
beaconState, _ := testutil.DeterministicGenesisStateAltair(t, params.BeaconConfig().MaxValidatorsPerCommittee)
require.NoError(t, beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch))
currentEpoch := helpers.CurrentEpoch(beaconState)
if test.epoch == currentEpoch {
require.NoError(t, beaconState.SetCurrentParticipationBits(test.epochParticipation))
} else {
require.NoError(t, beaconState.SetPreviousParticipationBits(test.epochParticipation))
}
st, err := altair.SetParticipationAndRewardProposer(beaconState, test.epoch, test.indices, test.participatedFlags)
require.NoError(t, err)
i, err := helpers.BeaconProposerIndex(st)
require.NoError(t, err)
b, err := beaconState.BalanceAtIndex(i)
require.NoError(t, err)
require.Equal(t, test.wantedBalance, b)
if test.epoch == currentEpoch {
p, err := beaconState.CurrentEpochParticipation()
require.NoError(t, err)
require.DeepSSZEqual(t, test.wantedParticipation, p)
} else {
p, err := beaconState.PreviousEpochParticipation()
require.NoError(t, err)
require.DeepSSZEqual(t, test.wantedParticipation, p)
}
})
}
}
func TestEpochParticipation(t *testing.T) {
beaconState, _ := testutil.DeterministicGenesisStateAltair(t, params.BeaconConfig().MaxValidatorsPerCommittee)
cfg := params.BeaconConfig()
sourceFlagIndex := cfg.TimelySourceFlagIndex
targetFlagIndex := cfg.TimelyTargetFlagIndex
headFlagIndex := cfg.TimelyHeadFlagIndex
tests := []struct {
name string
indices []uint64
epochParticipation []byte
participatedFlags map[uint8]bool
wantedNumerator uint64
wantedEpochParticipation []byte
}{
{name: "none participated",
indices: []uint64{}, epochParticipation: []byte{0, 0, 0, 0, 0, 0, 0, 0}, participatedFlags: map[uint8]bool{
sourceFlagIndex: false,
targetFlagIndex: false,
headFlagIndex: false,
},
wantedNumerator: 0,
wantedEpochParticipation: []byte{0, 0, 0, 0, 0, 0, 0, 0},
},
{name: "some participated without flags",
indices: []uint64{0, 1, 2, 3}, epochParticipation: []byte{0, 0, 0, 0, 0, 0, 0, 0}, participatedFlags: map[uint8]bool{
sourceFlagIndex: false,
targetFlagIndex: false,
headFlagIndex: false,
},
wantedNumerator: 0,
wantedEpochParticipation: []byte{0, 0, 0, 0, 0, 0, 0, 0},
},
{name: "some participated with some flags",
indices: []uint64{0, 1, 2, 3}, epochParticipation: []byte{0, 0, 0, 0, 0, 0, 0, 0}, participatedFlags: map[uint8]bool{
sourceFlagIndex: true,
targetFlagIndex: true,
headFlagIndex: false,
},
wantedNumerator: 40473600,
wantedEpochParticipation: []byte{3, 3, 3, 3, 0, 0, 0, 0},
},
{name: "all participated with some flags",
indices: []uint64{0, 1, 2, 3, 4, 5, 6, 7}, epochParticipation: []byte{0, 0, 0, 0, 0, 0, 0, 0}, participatedFlags: map[uint8]bool{
sourceFlagIndex: true,
targetFlagIndex: false,
headFlagIndex: false,
},
wantedNumerator: 28331520,
wantedEpochParticipation: []byte{1, 1, 1, 1, 1, 1, 1, 1},
},
{name: "all participated with all flags",
indices: []uint64{0, 1, 2, 3, 4, 5, 6, 7}, epochParticipation: []byte{0, 0, 0, 0, 0, 0, 0, 0}, participatedFlags: map[uint8]bool{
sourceFlagIndex: true,
targetFlagIndex: true,
headFlagIndex: true,
},
wantedNumerator: 109278720,
wantedEpochParticipation: []byte{7, 7, 7, 7, 7, 7, 7, 7},
},
}
for _, test := range tests {
n, p, err := altair.EpochParticipation(beaconState, test.indices, test.epochParticipation, test.participatedFlags)
require.NoError(t, err)
require.Equal(t, test.wantedNumerator, n)
require.DeepSSZEqual(t, test.wantedEpochParticipation, p)
}
}
func TestRewardProposer(t *testing.T) {
beaconState, _ := testutil.DeterministicGenesisStateAltair(t, params.BeaconConfig().MaxValidatorsPerCommittee)
require.NoError(t, beaconState.SetSlot(1))
tests := []struct {
rewardNumerator uint64
want uint64
}{
{rewardNumerator: 1, want: 32000000000},
{rewardNumerator: 10000, want: 32000000022},
{rewardNumerator: 1000000, want: 32000002254},
{rewardNumerator: 1000000000, want: 32002234396},
{rewardNumerator: 1000000000000, want: 34234377253},
}
for _, test := range tests {
require.NoError(t, altair.RewardProposer(beaconState, test.rewardNumerator))
i, err := helpers.BeaconProposerIndex(beaconState)
require.NoError(t, err)
b, err := beaconState.BalanceAtIndex(i)
require.NoError(t, err)
require.Equal(t, test.want, b)
}
}
func TestAttestationParticipationFlagIndices(t *testing.T) {
beaconState, _ := testutil.DeterministicGenesisStateAltair(t, params.BeaconConfig().MaxValidatorsPerCommittee)
require.NoError(t, beaconState.SetSlot(1))
cfg := params.BeaconConfig()
sourceFlagIndex := cfg.TimelySourceFlagIndex
targetFlagIndex := cfg.TimelyTargetFlagIndex
headFlagIndex := cfg.TimelyHeadFlagIndex
tests := []struct {
name string
inputState state.BeaconState
inputData *ethpb.AttestationData
inputDelay types.Slot
participationIndices map[uint8]bool
}{
{
name: "none",
inputState: func() state.BeaconState {
return beaconState
}(),
inputData: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]},
Target: &ethpb.Checkpoint{},
},
inputDelay: params.BeaconConfig().SlotsPerEpoch,
participationIndices: map[uint8]bool{},
},
{
name: "participated source",
inputState: func() state.BeaconState {
return beaconState
}(),
inputData: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]},
Target: &ethpb.Checkpoint{},
},
inputDelay: types.Slot(mathutil.IntegerSquareRoot(uint64(cfg.SlotsPerEpoch)) - 1),
participationIndices: map[uint8]bool{
sourceFlagIndex: true,
},
},
{
name: "participated source and target",
inputState: func() state.BeaconState {
return beaconState
}(),
inputData: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]},
Target: &ethpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]},
},
inputDelay: types.Slot(mathutil.IntegerSquareRoot(uint64(cfg.SlotsPerEpoch)) - 1),
participationIndices: map[uint8]bool{
sourceFlagIndex: true,
targetFlagIndex: true,
},
},
{
name: "participated source and target and head",
inputState: func() state.BeaconState {
return beaconState
}(),
inputData: &ethpb.AttestationData{
BeaconBlockRoot: params.BeaconConfig().ZeroHash[:],
Source: &ethpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]},
Target: &ethpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]},
},
inputDelay: 1,
participationIndices: map[uint8]bool{
sourceFlagIndex: true,
targetFlagIndex: true,
headFlagIndex: true,
},
},
}
for _, test := range tests {
flagIndices, err := altair.AttestationParticipationFlagIndices(test.inputState, test.inputData, test.inputDelay)
require.NoError(t, err)
require.DeepEqual(t, test.participationIndices, flagIndices)
}
}
func TestMatchingStatus(t *testing.T) {
beaconState, _ := testutil.DeterministicGenesisStateAltair(t, params.BeaconConfig().MaxValidatorsPerCommittee)
require.NoError(t, beaconState.SetSlot(1))
tests := []struct {
name string
inputState state.BeaconState
inputData *ethpb.AttestationData
inputCheckpt *ethpb.Checkpoint
matchedSource bool
matchedTarget bool
matchedHead bool
}{
{
name: "non matched",
inputState: beaconState,
inputData: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 1},
Target: &ethpb.Checkpoint{},
},
inputCheckpt: &ethpb.Checkpoint{},
},
{
name: "source matched",
inputState: beaconState,
inputData: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{},
Target: &ethpb.Checkpoint{},
},
inputCheckpt: &ethpb.Checkpoint{},
matchedSource: true,
},
{
name: "target matched",
inputState: beaconState,
inputData: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 1},
Target: &ethpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]},
},
inputCheckpt: &ethpb.Checkpoint{},
matchedTarget: true,
},
{
name: "head matched",
inputState: beaconState,
inputData: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 1},
Target: &ethpb.Checkpoint{},
BeaconBlockRoot: params.BeaconConfig().ZeroHash[:],
},
inputCheckpt: &ethpb.Checkpoint{},
matchedHead: true,
},
{
name: "everything matched",
inputState: beaconState,
inputData: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{},
Target: &ethpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]},
BeaconBlockRoot: params.BeaconConfig().ZeroHash[:],
},
inputCheckpt: &ethpb.Checkpoint{},
matchedSource: true,
matchedTarget: true,
matchedHead: true,
},
}
for _, test := range tests {
src, tgt, head, err := altair.MatchingStatus(test.inputState, test.inputData, test.inputCheckpt)
require.NoError(t, err)
require.Equal(t, test.matchedSource, src)
require.Equal(t, test.matchedTarget, tgt)
require.Equal(t, test.matchedHead, head)
}
}

View File

@@ -0,0 +1,175 @@
package altair
import (
"errors"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
p2pType "github.com/prysmaticlabs/prysm/beacon-chain/p2p/types"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
)
// ProcessSyncAggregate verifies sync committee aggregate signature signing over the previous slot block root.
//
// Spec code:
// def process_sync_aggregate(state: BeaconState, sync_aggregate: SyncAggregate) -> None:
// # Verify sync committee aggregate signature signing over the previous slot block root
// committee_pubkeys = state.current_sync_committee.pubkeys
// participant_pubkeys = [pubkey for pubkey, bit in zip(committee_pubkeys, sync_aggregate.sync_committee_bits) if bit]
// previous_slot = max(state.slot, Slot(1)) - Slot(1)
// domain = get_domain(state, DOMAIN_SYNC_COMMITTEE, compute_epoch_at_slot(previous_slot))
// signing_root = compute_signing_root(get_block_root_at_slot(state, previous_slot), domain)
// assert eth2_fast_aggregate_verify(participant_pubkeys, signing_root, sync_aggregate.sync_committee_signature)
//
// # Compute participant and proposer rewards
// total_active_increments = get_total_active_balance(state) // EFFECTIVE_BALANCE_INCREMENT
// total_base_rewards = Gwei(get_base_reward_per_increment(state) * total_active_increments)
// max_participant_rewards = Gwei(total_base_rewards * SYNC_REWARD_WEIGHT // WEIGHT_DENOMINATOR // SLOTS_PER_EPOCH)
// participant_reward = Gwei(max_participant_rewards // SYNC_COMMITTEE_SIZE)
// proposer_reward = Gwei(participant_reward * PROPOSER_WEIGHT // (WEIGHT_DENOMINATOR - PROPOSER_WEIGHT))
//
// # Apply participant and proposer rewards
// all_pubkeys = [v.pubkey for v in state.validators]
// committee_indices = [ValidatorIndex(all_pubkeys.index(pubkey)) for pubkey in state.current_sync_committee.pubkeys]
// for participant_index, participation_bit in zip(committee_indices, sync_aggregate.sync_committee_bits):
// if participation_bit:
// increase_balance(state, participant_index, participant_reward)
// increase_balance(state, get_beacon_proposer_index(state), proposer_reward)
// else:
// decrease_balance(state, participant_index, participant_reward)
func ProcessSyncAggregate(s state.BeaconStateAltair, sync *ethpb.SyncAggregate) (state.BeaconStateAltair, error) {
votedKeys, votedIndices, didntVoteIndices, err := FilterSyncCommitteeVotes(s, sync)
if err != nil {
return nil, err
}
if err := VerifySyncCommitteeSig(s, votedKeys, sync.SyncCommitteeSignature); err != nil {
return nil, err
}
return ApplySyncRewardsPenalties(s, votedIndices, didntVoteIndices)
}
// FilterSyncCommitteeVotes filters the validator public keys and indices for the ones that voted and didn't vote.
func FilterSyncCommitteeVotes(s state.BeaconStateAltair, sync *ethpb.SyncAggregate) (
votedKeys []bls.PublicKey,
votedIndices []types.ValidatorIndex,
didntVoteIndices []types.ValidatorIndex,
err error) {
currentSyncCommittee, err := s.CurrentSyncCommittee()
if err != nil {
return nil, nil, nil, err
}
if currentSyncCommittee == nil {
return nil, nil, nil, errors.New("nil current sync committee in state")
}
committeeKeys := currentSyncCommittee.Pubkeys
if sync.SyncCommitteeBits.Len() > uint64(len(committeeKeys)) {
return nil, nil, nil, errors.New("bits length exceeds committee length")
}
votedKeys = make([]bls.PublicKey, 0, len(committeeKeys))
votedIndices = make([]types.ValidatorIndex, 0, len(committeeKeys))
didntVoteIndices = make([]types.ValidatorIndex, 0) // No allocation. Expect most votes.
for i := uint64(0); i < sync.SyncCommitteeBits.Len(); i++ {
vIdx, exists := s.ValidatorIndexByPubkey(bytesutil.ToBytes48(committeeKeys[i]))
// Impossible scenario.
if !exists {
return nil, nil, nil, errors.New("validator public key does not exist in state")
}
if sync.SyncCommitteeBits.BitAt(i) {
pubKey, err := bls.PublicKeyFromBytes(committeeKeys[i])
if err != nil {
return nil, nil, nil, err
}
votedKeys = append(votedKeys, pubKey)
votedIndices = append(votedIndices, vIdx)
} else {
didntVoteIndices = append(didntVoteIndices, vIdx)
}
}
return
}
// VerifySyncCommitteeSig verifies sync committee signature `syncSig` is valid with respect to public keys `syncKeys`.
func VerifySyncCommitteeSig(s state.BeaconStateAltair, syncKeys []bls.PublicKey, syncSig []byte) error {
ps := helpers.PrevSlot(s.Slot())
d, err := helpers.Domain(s.Fork(), helpers.SlotToEpoch(ps), params.BeaconConfig().DomainSyncCommittee, s.GenesisValidatorRoot())
if err != nil {
return err
}
pbr, err := helpers.BlockRootAtSlot(s, ps)
if err != nil {
return err
}
sszBytes := p2pType.SSZBytes(pbr)
r, err := helpers.ComputeSigningRoot(&sszBytes, d)
if err != nil {
return err
}
sig, err := bls.SignatureFromBytes(syncSig)
if err != nil {
return err
}
if !sig.Eth2FastAggregateVerify(syncKeys, r) {
return errors.New("invalid sync committee signature")
}
return nil
}
// ApplySyncRewardsPenalties applies rewards and penalties for proposer and sync committee participants.
func ApplySyncRewardsPenalties(s state.BeaconStateAltair, votedIndices, didntVoteIndices []types.ValidatorIndex) (state.BeaconStateAltair, error) {
activeBalance, err := helpers.TotalActiveBalance(s)
if err != nil {
return nil, err
}
proposerReward, participantReward, err := SyncRewards(activeBalance)
if err != nil {
return nil, err
}
// Apply sync committee rewards.
earnedProposerReward := uint64(0)
for _, index := range votedIndices {
if err := helpers.IncreaseBalance(s, index, participantReward); err != nil {
return nil, err
}
earnedProposerReward += proposerReward
}
// Apply proposer rewards.
proposerIndex, err := helpers.BeaconProposerIndex(s)
if err != nil {
return nil, err
}
if err := helpers.IncreaseBalance(s, proposerIndex, earnedProposerReward); err != nil {
return nil, err
}
// Apply sync committee penalties.
for _, index := range didntVoteIndices {
if err := helpers.DecreaseBalance(s, index, participantReward); err != nil {
return nil, err
}
}
return s, nil
}
// SyncRewards returns the proposer reward and the sync participant reward given the total active balance in state.
func SyncRewards(activeBalance uint64) (proposerReward uint64, participantReward uint64, err error) {
cfg := params.BeaconConfig()
totalActiveIncrements := activeBalance / cfg.EffectiveBalanceIncrement
baseRewardPerInc, err := BaseRewardPerIncrement(activeBalance)
if err != nil {
return 0, 0, err
}
totalBaseRewards := baseRewardPerInc * totalActiveIncrements
maxParticipantRewards := totalBaseRewards * cfg.SyncRewardWeight / cfg.WeightDenominator / uint64(cfg.SlotsPerEpoch)
participantReward = maxParticipantRewards / cfg.SyncCommitteeSize
proposerReward = participantReward * cfg.ProposerWeight / (cfg.WeightDenominator - cfg.ProposerWeight)
return
}

View File

@@ -0,0 +1,317 @@
package altair_test
import (
"context"
"math"
"testing"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/go-bitfield"
"github.com/prysmaticlabs/prysm/beacon-chain/core/altair"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
p2pType "github.com/prysmaticlabs/prysm/beacon-chain/p2p/types"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"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/require"
)
func TestProcessSyncCommittee_PerfectParticipation(t *testing.T) {
beaconState, privKeys := testutil.DeterministicGenesisStateAltair(t, params.BeaconConfig().MaxValidatorsPerCommittee)
require.NoError(t, beaconState.SetSlot(1))
committee, err := altair.NextSyncCommittee(context.Background(), beaconState)
require.NoError(t, err)
require.NoError(t, beaconState.SetCurrentSyncCommittee(committee))
syncBits := bitfield.NewBitvector512()
for i := range syncBits {
syncBits[i] = 0xff
}
indices, err := altair.NextSyncCommitteeIndices(context.Background(), beaconState)
require.NoError(t, err)
ps := helpers.PrevSlot(beaconState.Slot())
pbr, err := helpers.BlockRootAtSlot(beaconState, ps)
require.NoError(t, err)
sigs := make([]bls.Signature, len(indices))
for i, indice := range indices {
b := p2pType.SSZBytes(pbr)
sb, err := helpers.ComputeDomainAndSign(beaconState, helpers.CurrentEpoch(beaconState), &b, params.BeaconConfig().DomainSyncCommittee, privKeys[indice])
require.NoError(t, err)
sig, err := bls.SignatureFromBytes(sb)
require.NoError(t, err)
sigs[i] = sig
}
aggregatedSig := bls.AggregateSignatures(sigs).Marshal()
syncAggregate := &ethpb.SyncAggregate{
SyncCommitteeBits: syncBits,
SyncCommitteeSignature: aggregatedSig,
}
beaconState, err = altair.ProcessSyncAggregate(beaconState, syncAggregate)
require.NoError(t, err)
// Use a non-sync committee index to compare profitability.
syncCommittee := make(map[types.ValidatorIndex]bool)
for _, index := range indices {
syncCommittee[index] = true
}
nonSyncIndex := types.ValidatorIndex(params.BeaconConfig().MaxValidatorsPerCommittee + 1)
for i := types.ValidatorIndex(0); uint64(i) < params.BeaconConfig().MaxValidatorsPerCommittee; i++ {
if !syncCommittee[i] {
nonSyncIndex = i
break
}
}
// Sync committee should be more profitable than non sync committee
balances := beaconState.Balances()
require.Equal(t, true, balances[indices[0]] > balances[nonSyncIndex])
// Proposer should be more profitable than rest of the sync committee
proposerIndex, err := helpers.BeaconProposerIndex(beaconState)
require.NoError(t, err)
require.Equal(t, true, balances[proposerIndex] > balances[indices[0]])
// Sync committee should have the same profits, except you are a proposer
for i := 1; i < len(indices); i++ {
if proposerIndex == indices[i-1] || proposerIndex == indices[i] {
continue
}
require.Equal(t, balances[indices[i-1]], balances[indices[i]])
}
// Increased balance validator count should equal to sync committee count
increased := uint64(0)
for _, balance := range balances {
if balance > params.BeaconConfig().MaxEffectiveBalance {
increased++
}
}
require.Equal(t, params.BeaconConfig().SyncCommitteeSize, increased)
}
func TestProcessSyncCommittee_MixParticipation_BadSignature(t *testing.T) {
beaconState, privKeys := testutil.DeterministicGenesisStateAltair(t, params.BeaconConfig().MaxValidatorsPerCommittee)
require.NoError(t, beaconState.SetSlot(1))
committee, err := altair.NextSyncCommittee(context.Background(), beaconState)
require.NoError(t, err)
require.NoError(t, beaconState.SetCurrentSyncCommittee(committee))
syncBits := bitfield.NewBitvector512()
for i := range syncBits {
syncBits[i] = 0xAA
}
indices, err := altair.NextSyncCommitteeIndices(context.Background(), beaconState)
require.NoError(t, err)
ps := helpers.PrevSlot(beaconState.Slot())
pbr, err := helpers.BlockRootAtSlot(beaconState, ps)
require.NoError(t, err)
sigs := make([]bls.Signature, len(indices))
for i, indice := range indices {
b := p2pType.SSZBytes(pbr)
sb, err := helpers.ComputeDomainAndSign(beaconState, helpers.CurrentEpoch(beaconState), &b, params.BeaconConfig().DomainSyncCommittee, privKeys[indice])
require.NoError(t, err)
sig, err := bls.SignatureFromBytes(sb)
require.NoError(t, err)
sigs[i] = sig
}
aggregatedSig := bls.AggregateSignatures(sigs).Marshal()
syncAggregate := &ethpb.SyncAggregate{
SyncCommitteeBits: syncBits,
SyncCommitteeSignature: aggregatedSig,
}
_, err = altair.ProcessSyncAggregate(beaconState, syncAggregate)
require.ErrorContains(t, "invalid sync committee signature", err)
}
func TestProcessSyncCommittee_MixParticipation_GoodSignature(t *testing.T) {
beaconState, privKeys := testutil.DeterministicGenesisStateAltair(t, params.BeaconConfig().MaxValidatorsPerCommittee)
require.NoError(t, beaconState.SetSlot(1))
committee, err := altair.NextSyncCommittee(context.Background(), beaconState)
require.NoError(t, err)
require.NoError(t, beaconState.SetCurrentSyncCommittee(committee))
syncBits := bitfield.NewBitvector512()
for i := range syncBits {
syncBits[i] = 0xAA
}
indices, err := altair.NextSyncCommitteeIndices(context.Background(), beaconState)
require.NoError(t, err)
ps := helpers.PrevSlot(beaconState.Slot())
pbr, err := helpers.BlockRootAtSlot(beaconState, ps)
require.NoError(t, err)
sigs := make([]bls.Signature, 0, len(indices))
for i, indice := range indices {
if syncBits.BitAt(uint64(i)) {
b := p2pType.SSZBytes(pbr)
sb, err := helpers.ComputeDomainAndSign(beaconState, helpers.CurrentEpoch(beaconState), &b, params.BeaconConfig().DomainSyncCommittee, privKeys[indice])
require.NoError(t, err)
sig, err := bls.SignatureFromBytes(sb)
require.NoError(t, err)
sigs = append(sigs, sig)
}
}
aggregatedSig := bls.AggregateSignatures(sigs).Marshal()
syncAggregate := &ethpb.SyncAggregate{
SyncCommitteeBits: syncBits,
SyncCommitteeSignature: aggregatedSig,
}
_, err = altair.ProcessSyncAggregate(beaconState, syncAggregate)
require.NoError(t, err)
}
func TestProcessSyncCommittee_FilterSyncCommitteeVotes(t *testing.T) {
beaconState, _ := testutil.DeterministicGenesisStateAltair(t, params.BeaconConfig().MaxValidatorsPerCommittee)
require.NoError(t, beaconState.SetSlot(1))
committee, err := altair.NextSyncCommittee(context.Background(), beaconState)
require.NoError(t, err)
require.NoError(t, beaconState.SetCurrentSyncCommittee(committee))
syncBits := bitfield.NewBitvector512()
for i := range syncBits {
syncBits[i] = 0xAA
}
syncAggregate := &ethpb.SyncAggregate{
SyncCommitteeBits: syncBits,
}
votedKeys, votedIndices, didntVoteIndices, err := altair.FilterSyncCommitteeVotes(beaconState, syncAggregate)
require.NoError(t, err)
votedMap := make(map[[48]byte]bool)
for _, key := range votedKeys {
votedMap[bytesutil.ToBytes48(key.Marshal())] = true
}
require.Equal(t, int(syncBits.Len()/2), len(votedKeys))
require.Equal(t, int(syncBits.Len()/2), len(votedIndices))
require.Equal(t, int(syncBits.Len()/2), len(didntVoteIndices))
for i := 0; i < len(syncBits); i++ {
if syncBits.BitAt(uint64(i)) {
pk := beaconState.PubkeyAtIndex(votedIndices[i])
require.DeepEqual(t, true, votedMap[pk])
} else {
pk := beaconState.PubkeyAtIndex(didntVoteIndices[i])
require.DeepEqual(t, false, votedMap[pk])
}
}
}
func Test_VerifySyncCommitteeSig(t *testing.T) {
beaconState, privKeys := testutil.DeterministicGenesisStateAltair(t, params.BeaconConfig().MaxValidatorsPerCommittee)
require.NoError(t, beaconState.SetSlot(1))
committee, err := altair.NextSyncCommittee(context.Background(), beaconState)
require.NoError(t, err)
require.NoError(t, beaconState.SetCurrentSyncCommittee(committee))
syncBits := bitfield.NewBitvector512()
for i := range syncBits {
syncBits[i] = 0xff
}
indices, err := altair.NextSyncCommitteeIndices(context.Background(), beaconState)
require.NoError(t, err)
ps := helpers.PrevSlot(beaconState.Slot())
pbr, err := helpers.BlockRootAtSlot(beaconState, ps)
require.NoError(t, err)
sigs := make([]bls.Signature, len(indices))
pks := make([]bls.PublicKey, len(indices))
for i, indice := range indices {
b := p2pType.SSZBytes(pbr)
sb, err := helpers.ComputeDomainAndSign(beaconState, helpers.CurrentEpoch(beaconState), &b, params.BeaconConfig().DomainSyncCommittee, privKeys[indice])
require.NoError(t, err)
sig, err := bls.SignatureFromBytes(sb)
require.NoError(t, err)
sigs[i] = sig
pks[i] = privKeys[indice].PublicKey()
}
aggregatedSig := bls.AggregateSignatures(sigs).Marshal()
blsKey, err := bls.RandKey()
require.NoError(t, err)
require.ErrorContains(t, "invalid sync committee signature", altair.VerifySyncCommitteeSig(beaconState, pks, blsKey.Sign([]byte{'m', 'e', 'o', 'w'}).Marshal()))
require.NoError(t, altair.VerifySyncCommitteeSig(beaconState, pks, aggregatedSig))
}
func Test_ApplySyncRewardsPenalties(t *testing.T) {
beaconState, _ := testutil.DeterministicGenesisStateAltair(t, params.BeaconConfig().MaxValidatorsPerCommittee)
beaconState, err := altair.ApplySyncRewardsPenalties(beaconState,
[]types.ValidatorIndex{0, 1}, // voted
[]types.ValidatorIndex{2, 3}) // didn't vote
require.NoError(t, err)
balances := beaconState.Balances()
require.Equal(t, uint64(32000000988), balances[0])
require.Equal(t, balances[0], balances[1])
require.Equal(t, uint64(31999999012), balances[2])
require.Equal(t, balances[2], balances[3])
proposerIndex, err := helpers.BeaconProposerIndex(beaconState)
require.NoError(t, err)
require.Equal(t, uint64(32000000282), balances[proposerIndex])
}
func Test_SyncRewards(t *testing.T) {
tests := []struct {
name string
activeBalance uint64
wantProposerReward uint64
wantParticipantReward uint64
errString string
}{
{
name: "active balance is 0",
activeBalance: 0,
wantProposerReward: 0,
wantParticipantReward: 0,
errString: "active balance can't be 0",
},
{
name: "active balance is 1",
activeBalance: 1,
wantProposerReward: 0,
wantParticipantReward: 0,
errString: "",
},
{
name: "active balance is 1eth",
activeBalance: params.BeaconConfig().EffectiveBalanceIncrement,
wantProposerReward: 0,
wantParticipantReward: 3,
errString: "",
},
{
name: "active balance is 32eth",
activeBalance: params.BeaconConfig().MaxEffectiveBalance,
wantProposerReward: 3,
wantParticipantReward: 21,
errString: "",
},
{
name: "active balance is 32eth * 1m validators",
activeBalance: params.BeaconConfig().MaxEffectiveBalance * 1e9,
wantProposerReward: 62780,
wantParticipantReward: 439463,
errString: "",
},
{
name: "active balance is max uint64",
activeBalance: math.MaxUint64,
wantProposerReward: 70368,
wantParticipantReward: 492581,
errString: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
proposerReward, participarntReward, err := altair.SyncRewards(tt.activeBalance)
if (err != nil) && (tt.errString != "") {
require.ErrorContains(t, tt.errString, err)
return
}
require.Equal(t, tt.wantProposerReward, proposerReward)
require.Equal(t, tt.wantParticipantReward, participarntReward)
})
}
}

View File

@@ -0,0 +1,55 @@
package altair
import (
"context"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
)
// ProcessDeposits processes validator deposits for beacon state Altair.
func ProcessDeposits(
ctx context.Context,
beaconState state.BeaconStateAltair,
deposits []*ethpb.Deposit,
) (state.BeaconStateAltair, error) {
batchVerified, err := blocks.BatchVerifyDepositsSignatures(ctx, deposits)
if err != nil {
return nil, err
}
for _, deposit := range deposits {
if deposit == nil || deposit.Data == nil {
return nil, errors.New("got a nil deposit in block")
}
beaconState, err = ProcessDeposit(ctx, beaconState, deposit, batchVerified)
if err != nil {
return nil, errors.Wrapf(err, "could not process deposit from %#x", bytesutil.Trunc(deposit.Data.PublicKey))
}
}
return beaconState, nil
}
// ProcessDeposit processes validator deposit for beacon state Altair.
func ProcessDeposit(ctx context.Context, beaconState state.BeaconStateAltair, deposit *ethpb.Deposit, verifySignature bool) (state.BeaconStateAltair, error) {
beaconState, isNewValidator, err := blocks.ProcessDeposit(beaconState, deposit, verifySignature)
if err != nil {
return nil, err
}
if isNewValidator {
if err := beaconState.AppendInactivityScore(0); err != nil {
return nil, err
}
if err := beaconState.AppendPreviousParticipationBits(0); err != nil {
return nil, err
}
if err := beaconState.AppendCurrentParticipationBits(0); err != nil {
return nil, err
}
}
return beaconState, nil
}

View File

@@ -0,0 +1,48 @@
package altair_test
import (
"context"
"testing"
fuzz "github.com/google/gofuzz"
"github.com/prysmaticlabs/prysm/beacon-chain/core/altair"
stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state/v2"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
)
func TestFuzzProcessDeposits_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &ethpb.BeaconStateAltair{}
deposits := make([]*ethpb.Deposit, 100)
ctx := context.Background()
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
for i := range deposits {
fuzzer.Fuzz(deposits[i])
}
s, err := stateAltair.InitializeFromProtoUnsafe(state)
require.NoError(t, err)
r, err := altair.ProcessDeposits(ctx, s, deposits)
if err != nil && r != nil {
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, deposits)
}
}
}
func TestFuzzProcessDeposit_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &ethpb.BeaconStateAltair{}
deposit := &ethpb.Deposit{}
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(deposit)
s, err := stateAltair.InitializeFromProtoUnsafe(state)
require.NoError(t, err)
r, err := altair.ProcessDeposit(context.Background(), s, deposit, true)
if err != nil && r != nil {
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, deposit)
}
}
}

View File

@@ -0,0 +1,245 @@
package altair_test
import (
"context"
"testing"
"github.com/prysmaticlabs/prysm/beacon-chain/core/altair"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state/v2"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"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/require"
"github.com/prysmaticlabs/prysm/shared/trieutil"
)
func TestProcessDeposits_SameValidatorMultipleDepositsSameBlock(t *testing.T) {
// Same validator created 3 valid deposits within the same block
dep, _, err := testutil.DeterministicDepositsAndKeysSameValidator(3)
require.NoError(t, err)
eth1Data, err := testutil.DeterministicEth1Data(len(dep))
require.NoError(t, err)
registry := []*ethpb.Validator{
{
PublicKey: []byte{1},
WithdrawalCredentials: []byte{1, 2, 3},
},
}
balances := []uint64{0}
beaconState, err := stateAltair.InitializeFromProto(&ethpb.BeaconStateAltair{
Validators: registry,
Balances: balances,
Eth1Data: eth1Data,
Fork: &ethpb.Fork{
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
},
})
require.NoError(t, err)
newState, err := altair.ProcessDeposits(context.Background(), beaconState, []*ethpb.Deposit{dep[0], dep[1], dep[2]})
require.NoError(t, err, "Expected block deposits to process correctly")
require.Equal(t, 2, len(newState.Validators()), "Incorrect validator count")
}
func TestProcessDeposits_MerkleBranchFailsVerification(t *testing.T) {
deposit := &ethpb.Deposit{
Data: &ethpb.Deposit_Data{
PublicKey: bytesutil.PadTo([]byte{1, 2, 3}, 48),
WithdrawalCredentials: make([]byte, 32),
Signature: make([]byte, 96),
},
}
leaf, err := deposit.Data.HashTreeRoot()
require.NoError(t, err)
// We then create a merkle branch for the test.
depositTrie, err := trieutil.GenerateTrieFromItems([][]byte{leaf[:]}, params.BeaconConfig().DepositContractTreeDepth)
require.NoError(t, err, "Could not generate trie")
proof, err := depositTrie.MerkleProof(0)
require.NoError(t, err, "Could not generate proof")
deposit.Proof = proof
beaconState, err := stateAltair.InitializeFromProto(&ethpb.BeaconStateAltair{
Eth1Data: &ethpb.Eth1Data{
DepositRoot: []byte{0},
BlockHash: []byte{1},
},
})
require.NoError(t, err)
want := "deposit root did not verify"
_, err = altair.ProcessDeposits(context.Background(), beaconState, []*ethpb.Deposit{deposit})
require.ErrorContains(t, want, err)
}
func TestProcessDeposits_AddsNewValidatorDeposit(t *testing.T) {
dep, _, err := testutil.DeterministicDepositsAndKeys(1)
require.NoError(t, err)
eth1Data, err := testutil.DeterministicEth1Data(len(dep))
require.NoError(t, err)
registry := []*ethpb.Validator{
{
PublicKey: []byte{1},
WithdrawalCredentials: []byte{1, 2, 3},
},
}
balances := []uint64{0}
beaconState, err := stateAltair.InitializeFromProto(&ethpb.BeaconStateAltair{
Validators: registry,
Balances: balances,
Eth1Data: eth1Data,
Fork: &ethpb.Fork{
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
},
})
require.NoError(t, err)
newState, err := altair.ProcessDeposits(context.Background(), beaconState, []*ethpb.Deposit{dep[0]})
require.NoError(t, err, "Expected block deposits to process correctly")
if newState.Balances()[1] != dep[0].Data.Amount {
t.Errorf(
"Expected state validator balances index 0 to equal %d, received %d",
dep[0].Data.Amount,
newState.Balances()[1],
)
}
}
func TestProcessDeposits_RepeatedDeposit_IncreasesValidatorBalance(t *testing.T) {
sk, err := bls.RandKey()
require.NoError(t, err)
deposit := &ethpb.Deposit{
Data: &ethpb.Deposit_Data{
PublicKey: sk.PublicKey().Marshal(),
Amount: 1000,
WithdrawalCredentials: make([]byte, 32),
Signature: make([]byte, 96),
},
}
sr, err := helpers.ComputeSigningRoot(deposit.Data, bytesutil.ToBytes(3, 32))
require.NoError(t, err)
sig := sk.Sign(sr[:])
deposit.Data.Signature = sig.Marshal()
leaf, err := deposit.Data.HashTreeRoot()
require.NoError(t, err)
// We then create a merkle branch for the test.
depositTrie, err := trieutil.GenerateTrieFromItems([][]byte{leaf[:]}, params.BeaconConfig().DepositContractTreeDepth)
require.NoError(t, err, "Could not generate trie")
proof, err := depositTrie.MerkleProof(0)
require.NoError(t, err, "Could not generate proof")
deposit.Proof = proof
registry := []*ethpb.Validator{
{
PublicKey: []byte{1, 2, 3},
},
{
PublicKey: sk.PublicKey().Marshal(),
WithdrawalCredentials: []byte{1},
},
}
balances := []uint64{0, 50}
root := depositTrie.Root()
beaconState, err := stateAltair.InitializeFromProto(&ethpb.BeaconStateAltair{
Validators: registry,
Balances: balances,
Eth1Data: &ethpb.Eth1Data{
DepositRoot: root[:],
BlockHash: root[:],
},
})
require.NoError(t, err)
newState, err := altair.ProcessDeposits(context.Background(), beaconState, []*ethpb.Deposit{deposit})
require.NoError(t, err, "Process deposit failed")
require.Equal(t, uint64(1000+50), newState.Balances()[1], "Expected balance at index 1 to be 1050")
}
func TestProcessDeposit_AddsNewValidatorDeposit(t *testing.T) {
// Similar to TestProcessDeposits_AddsNewValidatorDeposit except that this test directly calls ProcessDeposit
dep, _, err := testutil.DeterministicDepositsAndKeys(1)
require.NoError(t, err)
eth1Data, err := testutil.DeterministicEth1Data(len(dep))
require.NoError(t, err)
registry := []*ethpb.Validator{
{
PublicKey: []byte{1},
WithdrawalCredentials: []byte{1, 2, 3},
},
}
balances := []uint64{0}
beaconState, err := stateAltair.InitializeFromProto(&ethpb.BeaconStateAltair{
Validators: registry,
Balances: balances,
Eth1Data: eth1Data,
Fork: &ethpb.Fork{
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
},
})
require.NoError(t, err)
newState, err := altair.ProcessDeposit(context.Background(), beaconState, dep[0], true)
require.NoError(t, err, "Process deposit failed")
require.Equal(t, 2, len(newState.Validators()), "Expected validator list to have length 2")
require.Equal(t, 2, len(newState.Balances()), "Expected validator balances list to have length 2")
if newState.Balances()[1] != dep[0].Data.Amount {
t.Errorf(
"Expected state validator balances index 1 to equal %d, received %d",
dep[0].Data.Amount,
newState.Balances()[1],
)
}
}
func TestProcessDeposit_SkipsInvalidDeposit(t *testing.T) {
// Same test settings as in TestProcessDeposit_AddsNewValidatorDeposit, except that we use an invalid signature
dep, _, err := testutil.DeterministicDepositsAndKeys(1)
require.NoError(t, err)
dep[0].Data.Signature = make([]byte, 96)
trie, _, err := testutil.DepositTrieFromDeposits(dep)
require.NoError(t, err)
root := trie.Root()
eth1Data := &ethpb.Eth1Data{
DepositRoot: root[:],
DepositCount: 1,
}
registry := []*ethpb.Validator{
{
PublicKey: []byte{1},
WithdrawalCredentials: []byte{1, 2, 3},
},
}
balances := []uint64{0}
beaconState, err := stateAltair.InitializeFromProto(&ethpb.BeaconStateAltair{
Validators: registry,
Balances: balances,
Eth1Data: eth1Data,
Fork: &ethpb.Fork{
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
},
})
require.NoError(t, err)
newState, err := altair.ProcessDeposit(context.Background(), beaconState, dep[0], true)
require.NoError(t, err, "Expected invalid block deposit to be ignored without error")
if newState.Eth1DepositIndex() != 1 {
t.Errorf(
"Expected Eth1DepositIndex to be increased by 1 after processing an invalid deposit, received change: %v",
newState.Eth1DepositIndex(),
)
}
if len(newState.Validators()) != 1 {
t.Errorf("Expected validator list to have length 1, received: %v", len(newState.Validators()))
}
if len(newState.Balances()) != 1 {
t.Errorf("Expected validator balances list to have length 1, received: %v", len(newState.Balances()))
}
if newState.Balances()[0] != 0 {
t.Errorf("Expected validator balance at index 0 to stay 0, received: %v", newState.Balances()[0])
}
}

View File

@@ -0,0 +1,291 @@
package altair
import (
"context"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/shared/mathutil"
"github.com/prysmaticlabs/prysm/shared/params"
"go.opencensus.io/trace"
)
// InitializeEpochValidators gets called at the beginning of process epoch cycle to return
// pre computed instances of validators attesting records and total
// balances attested in an epoch.
func InitializeEpochValidators(ctx context.Context, st state.BeaconStateAltair) ([]*precompute.Validator, *precompute.Balance, error) {
ctx, span := trace.StartSpan(ctx, "altair.InitializeEpochValidators")
defer span.End()
pValidators := make([]*precompute.Validator, st.NumValidators())
bal := &precompute.Balance{}
prevEpoch := helpers.PrevEpoch(st)
currentEpoch := helpers.CurrentEpoch(st)
inactivityScores, err := st.InactivityScores()
if err != nil {
return nil, nil, err
}
// This shouldn't happen with a correct beacon state,
// but rather be safe to defend against index out of bound panics.
if st.NumValidators() > len(inactivityScores) {
return nil, nil, errors.New("num of validators can't be greater than length of inactivity scores")
}
if err := st.ReadFromEveryValidator(func(idx int, val state.ReadOnlyValidator) error {
// Was validator withdrawable or slashed
withdrawable := currentEpoch >= val.WithdrawableEpoch()
pVal := &precompute.Validator{
IsSlashed: val.Slashed(),
IsWithdrawableCurrentEpoch: withdrawable,
CurrentEpochEffectiveBalance: val.EffectiveBalance(),
InactivityScore: inactivityScores[idx],
}
// Validator active current epoch
if helpers.IsActiveValidatorUsingTrie(val, currentEpoch) {
pVal.IsActiveCurrentEpoch = true
bal.ActiveCurrentEpoch += val.EffectiveBalance()
}
// Validator active previous epoch
if helpers.IsActiveValidatorUsingTrie(val, prevEpoch) {
pVal.IsActivePrevEpoch = true
bal.ActivePrevEpoch += val.EffectiveBalance()
}
pValidators[idx] = pVal
return nil
}); err != nil {
return nil, nil, errors.Wrap(err, "could not initialize epoch validator")
}
return pValidators, bal, nil
}
// ProcessInactivityScores of beacon chain. This updates inactivity scores of beacon chain and
// updates the precompute validator struct for later processing. The inactivity scores work as following:
// For fully inactive validators and perfect active validators, the effect is the same as before Altair.
// For a validator is inactive and the chain fails to finalize, the inactivity score increases by a fixed number, the total loss after N epochs is proportional to N**2/2.
// For imperfectly active validators. The inactivity score's behavior is specified by this function:
// If a validator fails to submit an attestation with the correct target, their inactivity score goes up by 4.
// If they successfully submit an attestation with the correct source and target, their inactivity score drops by 1
// If the chain has recently finalized, each validator's score drops by 16.
func ProcessInactivityScores(
ctx context.Context,
state state.BeaconState,
vals []*precompute.Validator,
) (state.BeaconState, []*precompute.Validator, error) {
cfg := params.BeaconConfig()
if helpers.CurrentEpoch(state) == cfg.GenesisEpoch {
return state, vals, nil
}
inactivityScores, err := state.InactivityScores()
if err != nil {
return nil, nil, err
}
bias := cfg.InactivityScoreBias
recoveryRate := cfg.InactivityScoreRecoveryRate
for i, v := range vals {
if !precompute.EligibleForRewards(v) {
continue
}
if v.IsPrevEpochTargetAttester && !v.IsSlashed {
// Decrease inactivity score when validator gets target correct.
if v.InactivityScore > 0 {
score := uint64(1)
// Prevents underflow below 0.
if score > v.InactivityScore {
score = v.InactivityScore
}
v.InactivityScore -= score
}
} else {
v.InactivityScore += bias
}
if !helpers.IsInInactivityLeak(helpers.PrevEpoch(state), state.FinalizedCheckpointEpoch()) {
score := recoveryRate
// Prevents underflow below 0.
if score > v.InactivityScore {
score = v.InactivityScore
}
v.InactivityScore -= score
}
inactivityScores[i] = v.InactivityScore
}
if err := state.SetInactivityScores(inactivityScores); err != nil {
return nil, nil, err
}
return state, vals, nil
}
// ProcessEpochParticipation processes the epoch participation in state and updates individual validator's pre computes,
// it also tracks and updates epoch attesting balances.
func ProcessEpochParticipation(
ctx context.Context,
state state.BeaconState,
bal *precompute.Balance,
vals []*precompute.Validator,
) ([]*precompute.Validator, *precompute.Balance, error) {
ctx, span := trace.StartSpan(ctx, "altair.ProcessEpochParticipation")
defer span.End()
cp, err := state.CurrentEpochParticipation()
if err != nil {
return nil, nil, err
}
cfg := params.BeaconConfig()
targetIdx := cfg.TimelyTargetFlagIndex
sourceIdx := cfg.TimelySourceFlagIndex
headIdx := cfg.TimelyHeadFlagIndex
for i, b := range cp {
if HasValidatorFlag(b, targetIdx) {
vals[i].IsCurrentEpochTargetAttester = true
}
}
pp, err := state.PreviousEpochParticipation()
if err != nil {
return nil, nil, err
}
for i, b := range pp {
if HasValidatorFlag(b, sourceIdx) {
vals[i].IsPrevEpochAttester = true
}
if HasValidatorFlag(b, targetIdx) {
vals[i].IsPrevEpochTargetAttester = true
}
if HasValidatorFlag(b, headIdx) {
vals[i].IsPrevEpochHeadAttester = true
}
}
bal = precompute.UpdateBalance(vals, bal)
return vals, bal, nil
}
// ProcessRewardsAndPenaltiesPrecompute processes the rewards and penalties of individual validator.
// This is an optimized version by passing in precomputed validator attesting records and and total epoch balances.
func ProcessRewardsAndPenaltiesPrecompute(
state state.BeaconStateAltair,
bal *precompute.Balance,
vals []*precompute.Validator,
) (state.BeaconStateAltair, error) {
// Don't process rewards and penalties in genesis epoch.
if helpers.CurrentEpoch(state) == 0 {
return state, nil
}
numOfVals := state.NumValidators()
// Guard against an out-of-bounds using validator balance precompute.
if len(vals) != numOfVals || len(vals) != state.BalancesLength() {
return state, errors.New("validator registries not the same length as state's validator registries")
}
attsRewards, attsPenalties, err := AttestationsDelta(state, bal, vals)
if err != nil {
return nil, errors.Wrap(err, "could not get attestation delta")
}
balances := state.Balances()
for i := 0; i < numOfVals; i++ {
vals[i].BeforeEpochTransitionBalance = balances[i]
// Compute the post balance of the validator after accounting for the
// attester and proposer rewards and penalties.
balances[i] = helpers.IncreaseBalanceWithVal(balances[i], attsRewards[i])
balances[i] = helpers.DecreaseBalanceWithVal(balances[i], attsPenalties[i])
vals[i].AfterEpochTransitionBalance = balances[i]
}
if err := state.SetBalances(balances); err != nil {
return nil, errors.Wrap(err, "could not set validator balances")
}
return state, nil
}
// AttestationsDelta computes and returns the rewards and penalties differences for individual validators based on the
// voting records.
func AttestationsDelta(state state.BeaconStateAltair, bal *precompute.Balance, vals []*precompute.Validator) (rewards, penalties []uint64, err error) {
numOfVals := state.NumValidators()
rewards = make([]uint64, numOfVals)
penalties = make([]uint64, numOfVals)
prevEpoch := helpers.PrevEpoch(state)
finalizedEpoch := state.FinalizedCheckpointEpoch()
cfg := params.BeaconConfig()
increment := cfg.EffectiveBalanceIncrement
factor := cfg.BaseRewardFactor
baseRewardMultiplier := increment * factor / mathutil.IntegerSquareRoot(bal.ActiveCurrentEpoch)
leak := helpers.IsInInactivityLeak(prevEpoch, finalizedEpoch)
inactivityDenominator := cfg.InactivityScoreBias * cfg.InactivityPenaltyQuotientAltair
for i, v := range vals {
rewards[i], penalties[i] = attestationDelta(bal, v, baseRewardMultiplier, inactivityDenominator, leak)
}
return rewards, penalties, nil
}
func attestationDelta(
bal *precompute.Balance,
v *precompute.Validator,
baseRewardMultiplier, inactivityDenominator uint64,
inactivityLeak bool) (reward, penalty uint64) {
eligible := v.IsActivePrevEpoch || (v.IsSlashed && !v.IsWithdrawableCurrentEpoch)
// Per spec `ActiveCurrentEpoch` can't be 0 to process attestation delta.
if !eligible || bal.ActiveCurrentEpoch == 0 {
return 0, 0
}
cfg := params.BeaconConfig()
increment := cfg.EffectiveBalanceIncrement
effectiveBalance := v.CurrentEpochEffectiveBalance
baseReward := (effectiveBalance / increment) * baseRewardMultiplier
activeIncrement := bal.ActiveCurrentEpoch / increment
weightDenominator := cfg.WeightDenominator
srcWeight := cfg.TimelySourceWeight
tgtWeight := cfg.TimelyTargetWeight
headWeight := cfg.TimelyHeadWeight
reward, penalty = uint64(0), uint64(0)
// Process source reward / penalty
if v.IsPrevEpochAttester && !v.IsSlashed {
if !inactivityLeak {
n := baseReward * srcWeight * (bal.PrevEpochAttested / increment)
reward += n / (activeIncrement * weightDenominator)
}
} else {
penalty += baseReward * srcWeight / weightDenominator
}
// Process target reward / penalty
if v.IsPrevEpochTargetAttester && !v.IsSlashed {
if !inactivityLeak {
n := baseReward * tgtWeight * (bal.PrevEpochTargetAttested / increment)
reward += n / (activeIncrement * weightDenominator)
}
} else {
penalty += baseReward * tgtWeight / weightDenominator
}
// Process head reward / penalty
if v.IsPrevEpochHeadAttester && !v.IsSlashed {
if !inactivityLeak {
n := baseReward * headWeight * (bal.PrevEpochHeadAttested / increment)
reward += n / (activeIncrement * weightDenominator)
}
}
// Process finality delay penalty
// Apply an additional penalty to validators that did not vote on the correct target or slashed
if !v.IsPrevEpochTargetAttester || v.IsSlashed {
n := effectiveBalance * v.InactivityScore
penalty += n / inactivityDenominator
}
return reward, penalty
}

View File

@@ -0,0 +1,344 @@
package altair
import (
"context"
"testing"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state/v2"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
)
func TestInitializeEpochValidators_Ok(t *testing.T) {
ffe := params.BeaconConfig().FarFutureEpoch
s, err := stateAltair.InitializeFromProto(&ethpb.BeaconStateAltair{
Slot: params.BeaconConfig().SlotsPerEpoch,
// Validator 0 is slashed
// Validator 1 is withdrawable
// Validator 2 is active prev epoch and current epoch
// Validator 3 is active prev epoch
Validators: []*ethpb.Validator{
{Slashed: true, WithdrawableEpoch: ffe, EffectiveBalance: 100},
{EffectiveBalance: 100},
{WithdrawableEpoch: ffe, ExitEpoch: ffe, EffectiveBalance: 100},
{WithdrawableEpoch: ffe, ExitEpoch: 1, EffectiveBalance: 100},
},
InactivityScores: []uint64{0, 1, 2, 3},
})
require.NoError(t, err)
v, b, err := InitializeEpochValidators(context.Background(), s)
require.NoError(t, err)
assert.DeepEqual(t, &precompute.Validator{
IsSlashed: true,
CurrentEpochEffectiveBalance: 100,
InactivityScore: 0,
}, v[0], "Incorrect validator 0 status")
assert.DeepEqual(t, &precompute.Validator{
IsWithdrawableCurrentEpoch: true,
CurrentEpochEffectiveBalance: 100,
InactivityScore: 1,
}, v[1], "Incorrect validator 1 status")
assert.DeepEqual(t, &precompute.Validator{
IsActivePrevEpoch: true,
IsActiveCurrentEpoch: true,
CurrentEpochEffectiveBalance: 100,
InactivityScore: 2,
}, v[2], "Incorrect validator 2 status")
assert.DeepEqual(t, &precompute.Validator{
IsActivePrevEpoch: true,
CurrentEpochEffectiveBalance: 100,
InactivityScore: 3,
}, v[3], "Incorrect validator 3 status")
wantedBalances := &precompute.Balance{
ActiveCurrentEpoch: 100,
ActivePrevEpoch: 200,
}
assert.DeepEqual(t, wantedBalances, b, "Incorrect wanted balance")
}
func TestInitializeEpochValidators_BadState(t *testing.T) {
s, err := stateAltair.InitializeFromProto(&ethpb.BeaconStateAltair{
Validators: []*ethpb.Validator{{}},
InactivityScores: []uint64{},
})
require.NoError(t, err)
_, _, err = InitializeEpochValidators(context.Background(), s)
require.ErrorContains(t, "num of validators can't be greater than length of inactivity scores", err)
}
func TestProcessEpochParticipation(t *testing.T) {
s, err := testState()
require.NoError(t, err)
validators, balance, err := InitializeEpochValidators(context.Background(), s)
require.NoError(t, err)
validators, balance, err = ProcessEpochParticipation(context.Background(), s, balance, validators)
require.NoError(t, err)
require.DeepEqual(t, &precompute.Validator{
IsActiveCurrentEpoch: true,
IsActivePrevEpoch: true,
IsWithdrawableCurrentEpoch: true,
CurrentEpochEffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
}, validators[0])
require.DeepEqual(t, &precompute.Validator{
IsActiveCurrentEpoch: true,
IsActivePrevEpoch: true,
IsWithdrawableCurrentEpoch: true,
CurrentEpochEffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
IsPrevEpochAttester: true,
}, validators[1])
require.DeepEqual(t, &precompute.Validator{
IsActiveCurrentEpoch: true,
IsActivePrevEpoch: true,
IsWithdrawableCurrentEpoch: true,
CurrentEpochEffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
IsPrevEpochAttester: true,
IsCurrentEpochTargetAttester: true,
IsPrevEpochTargetAttester: true,
}, validators[2])
require.DeepEqual(t, &precompute.Validator{
IsActiveCurrentEpoch: true,
IsActivePrevEpoch: true,
IsWithdrawableCurrentEpoch: true,
CurrentEpochEffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
IsPrevEpochAttester: true,
IsCurrentEpochTargetAttester: true,
IsPrevEpochTargetAttester: true,
IsPrevEpochHeadAttester: true,
}, validators[3])
require.Equal(t, params.BeaconConfig().MaxEffectiveBalance*3, balance.PrevEpochAttested)
require.Equal(t, balance.CurrentEpochTargetAttested, params.BeaconConfig().MaxEffectiveBalance*2)
require.Equal(t, balance.PrevEpochTargetAttested, params.BeaconConfig().MaxEffectiveBalance*2)
require.Equal(t, balance.PrevEpochHeadAttested, params.BeaconConfig().MaxEffectiveBalance*1)
}
func TestAttestationsDelta(t *testing.T) {
s, err := testState()
require.NoError(t, err)
validators, balance, err := InitializeEpochValidators(context.Background(), s)
require.NoError(t, err)
validators, balance, err = ProcessEpochParticipation(context.Background(), s, balance, validators)
require.NoError(t, err)
rewards, penalties, err := AttestationsDelta(s, balance, validators)
require.NoError(t, err)
// Reward amount should increase as validator index increases due to setup.
for i := 1; i < len(rewards); i++ {
require.Equal(t, true, rewards[i] > rewards[i-1])
}
// Penalty amount should decrease as validator index increases due to setup.
for i := 1; i < len(penalties); i++ {
require.Equal(t, true, penalties[i] <= penalties[i-1])
}
// First index should have 0 reward.
require.Equal(t, uint64(0), rewards[0])
// Last index should have 0 penalty.
require.Equal(t, uint64(0), penalties[len(penalties)-1])
}
func TestProcessRewardsAndPenaltiesPrecompute_Ok(t *testing.T) {
s, err := testState()
require.NoError(t, err)
validators, balance, err := InitializeEpochValidators(context.Background(), s)
require.NoError(t, err)
validators, balance, err = ProcessEpochParticipation(context.Background(), s, balance, validators)
require.NoError(t, err)
s, err = ProcessRewardsAndPenaltiesPrecompute(s, balance, validators)
require.NoError(t, err)
balances := s.Balances()
// Reward amount should increase as validator index increases due to setup.
for i := 1; i < len(balances); i++ {
require.Equal(t, true, balances[i] >= balances[i-1])
}
wanted := make([]uint64, s.NumValidators())
rewards, penalties, err := AttestationsDelta(s, balance, validators)
require.NoError(t, err)
for i := range rewards {
wanted[i] += rewards[i]
}
for i := range penalties {
if wanted[i] > penalties[i] {
wanted[i] -= penalties[i]
} else {
wanted[i] = 0
}
}
require.DeepEqual(t, wanted, balances)
}
func TestProcessRewardsAndPenaltiesPrecompute_InactivityLeak(t *testing.T) {
s, err := testState()
require.NoError(t, err)
validators, balance, err := InitializeEpochValidators(context.Background(), s)
require.NoError(t, err)
validators, balance, err = ProcessEpochParticipation(context.Background(), s, balance, validators)
require.NoError(t, err)
sCopy := s.Copy()
s, err = ProcessRewardsAndPenaltiesPrecompute(s, balance, validators)
require.NoError(t, err)
// Copied state where finality happened long ago
require.NoError(t, sCopy.SetSlot(params.BeaconConfig().SlotsPerEpoch*1000))
sCopy, err = ProcessRewardsAndPenaltiesPrecompute(sCopy, balance, validators)
require.NoError(t, err)
balances := s.Balances()
inactivityBalances := sCopy.Balances()
// Balances decreased to 0 due to inactivity
require.Equal(t, uint64(2101898), balances[2])
require.Equal(t, uint64(2414946), balances[3])
require.Equal(t, uint64(0), inactivityBalances[2])
require.Equal(t, uint64(0), inactivityBalances[3])
}
func TestProcessInactivityScores_CanProcessInactivityLeak(t *testing.T) {
s, err := testState()
require.NoError(t, err)
defaultScore := uint64(5)
require.NoError(t, s.SetInactivityScores([]uint64{defaultScore, defaultScore, defaultScore, defaultScore}))
require.NoError(t, s.SetSlot(params.BeaconConfig().SlotsPerEpoch*types.Slot(params.BeaconConfig().MinEpochsToInactivityPenalty+2)))
validators, balance, err := InitializeEpochValidators(context.Background(), s)
require.NoError(t, err)
validators, _, err = ProcessEpochParticipation(context.Background(), s, balance, validators)
require.NoError(t, err)
s, _, err = ProcessInactivityScores(context.Background(), s, validators)
require.NoError(t, err)
inactivityScores, err := s.InactivityScores()
require.NoError(t, err)
// V0 and V1 didn't vote head. V2 and V3 did.
require.Equal(t, defaultScore+params.BeaconConfig().InactivityScoreBias, inactivityScores[0])
require.Equal(t, defaultScore+params.BeaconConfig().InactivityScoreBias, inactivityScores[1])
require.Equal(t, defaultScore-1, inactivityScores[2])
require.Equal(t, defaultScore-1, inactivityScores[3])
}
func TestProcessInactivityScores_CanProcessNonInactivityLeak(t *testing.T) {
s, err := testState()
require.NoError(t, err)
defaultScore := uint64(5)
require.NoError(t, s.SetInactivityScores([]uint64{defaultScore, defaultScore, defaultScore, defaultScore}))
validators, balance, err := InitializeEpochValidators(context.Background(), s)
require.NoError(t, err)
validators, _, err = ProcessEpochParticipation(context.Background(), s, balance, validators)
require.NoError(t, err)
s, _, err = ProcessInactivityScores(context.Background(), s, validators)
require.NoError(t, err)
inactivityScores, err := s.InactivityScores()
require.NoError(t, err)
require.Equal(t, uint64(0), inactivityScores[0])
require.Equal(t, uint64(0), inactivityScores[1])
require.Equal(t, uint64(0), inactivityScores[2])
require.Equal(t, uint64(0), inactivityScores[3])
}
func TestProcessRewardsAndPenaltiesPrecompute_GenesisEpoch(t *testing.T) {
s, err := testState()
require.NoError(t, err)
validators, balance, err := InitializeEpochValidators(context.Background(), s)
require.NoError(t, err)
validators, balance, err = ProcessEpochParticipation(context.Background(), s, balance, validators)
require.NoError(t, err)
require.NoError(t, s.SetSlot(0))
s, err = ProcessRewardsAndPenaltiesPrecompute(s, balance, validators)
require.NoError(t, err)
balances := s.Balances()
// Nothing should happen at genesis epoch
require.Equal(t, uint64(0), balances[0])
for i := 1; i < len(balances); i++ {
require.Equal(t, true, balances[i] == balances[i-1])
}
}
func TestProcessRewardsAndPenaltiesPrecompute_BadState(t *testing.T) {
s, err := testState()
require.NoError(t, err)
validators, balance, err := InitializeEpochValidators(context.Background(), s)
require.NoError(t, err)
_, balance, err = ProcessEpochParticipation(context.Background(), s, balance, validators)
require.NoError(t, err)
_, err = ProcessRewardsAndPenaltiesPrecompute(s, balance, []*precompute.Validator{})
require.ErrorContains(t, "validator registries not the same length as state's validator registries", err)
}
func TestProcessInactivityScores_NonEligibleValidator(t *testing.T) {
s, err := testState()
require.NoError(t, err)
defaultScore := uint64(5)
require.NoError(t, s.SetInactivityScores([]uint64{defaultScore, defaultScore, defaultScore, defaultScore}))
validators, balance, err := InitializeEpochValidators(context.Background(), s)
require.NoError(t, err)
// v0 is eligible (not active previous epoch, slashed and not withdrawable)
validators[0].IsActivePrevEpoch = false
validators[0].IsSlashed = true
validators[0].IsWithdrawableCurrentEpoch = false
// v1 is not eligible (not active previous epoch, not slashed and not withdrawable)
validators[1].IsActivePrevEpoch = false
validators[1].IsSlashed = false
validators[1].IsWithdrawableCurrentEpoch = false
// v2 is not eligible (not active previous epoch, slashed and withdrawable)
validators[2].IsActivePrevEpoch = false
validators[2].IsSlashed = true
validators[2].IsWithdrawableCurrentEpoch = true
// v3 is eligible (active previous epoch)
validators[3].IsActivePrevEpoch = true
validators, _, err = ProcessEpochParticipation(context.Background(), s, balance, validators)
require.NoError(t, err)
s, _, err = ProcessInactivityScores(context.Background(), s, validators)
require.NoError(t, err)
inactivityScores, err := s.InactivityScores()
require.NoError(t, err)
require.Equal(t, uint64(0), inactivityScores[0])
require.Equal(t, defaultScore, inactivityScores[1]) // Should remain unchanged
require.Equal(t, defaultScore, inactivityScores[2]) // Should remain unchanged
require.Equal(t, uint64(0), inactivityScores[3])
}
func testState() (state.BeaconState, error) {
generateParticipation := func(flags ...uint8) byte {
b := byte(0)
for _, flag := range flags {
b = AddValidatorFlag(b, flag)
}
return b
}
return stateAltair.InitializeFromProto(&ethpb.BeaconStateAltair{
Slot: 2 * params.BeaconConfig().SlotsPerEpoch,
Validators: []*ethpb.Validator{
{EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, ExitEpoch: params.BeaconConfig().FarFutureEpoch},
{EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, ExitEpoch: params.BeaconConfig().FarFutureEpoch},
{EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, ExitEpoch: params.BeaconConfig().FarFutureEpoch},
{EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, ExitEpoch: params.BeaconConfig().FarFutureEpoch},
},
CurrentEpochParticipation: []byte{
0,
generateParticipation(params.BeaconConfig().TimelySourceFlagIndex),
generateParticipation(params.BeaconConfig().TimelySourceFlagIndex, params.BeaconConfig().TimelyTargetFlagIndex),
generateParticipation(params.BeaconConfig().TimelySourceFlagIndex, params.BeaconConfig().TimelyTargetFlagIndex, params.BeaconConfig().TimelyHeadFlagIndex),
},
PreviousEpochParticipation: []byte{
0,
generateParticipation(params.BeaconConfig().TimelySourceFlagIndex),
generateParticipation(params.BeaconConfig().TimelySourceFlagIndex, params.BeaconConfig().TimelyTargetFlagIndex),
generateParticipation(params.BeaconConfig().TimelySourceFlagIndex, params.BeaconConfig().TimelyTargetFlagIndex, params.BeaconConfig().TimelyHeadFlagIndex),
},
InactivityScores: []uint64{0, 0, 0, 0},
Balances: []uint64{0, 0, 0, 0},
})
}

View File

@@ -0,0 +1,116 @@
package altair
import (
"context"
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/mathutil"
"github.com/prysmaticlabs/prysm/shared/params"
)
// ProcessSyncCommitteeUpdates processes sync client committee updates for the beacon state.
//
// Spec code:
// def process_sync_committee_updates(state: BeaconState) -> None:
// next_epoch = get_current_epoch(state) + Epoch(1)
// if next_epoch % EPOCHS_PER_SYNC_COMMITTEE_PERIOD == 0:
// state.current_sync_committee = state.next_sync_committee
// state.next_sync_committee = get_next_sync_committee(state)
func ProcessSyncCommitteeUpdates(ctx context.Context, beaconState state.BeaconStateAltair) (state.BeaconStateAltair, error) {
nextEpoch := helpers.NextEpoch(beaconState)
if nextEpoch%params.BeaconConfig().EpochsPerSyncCommitteePeriod == 0 {
currentSyncCommittee, err := beaconState.NextSyncCommittee()
if err != nil {
return nil, err
}
if err := beaconState.SetCurrentSyncCommittee(currentSyncCommittee); err != nil {
return nil, err
}
nextCommittee, err := NextSyncCommittee(ctx, beaconState)
if err != nil {
return nil, err
}
if err := beaconState.SetNextSyncCommittee(nextCommittee); err != nil {
return nil, err
}
if err := helpers.UpdateSyncCommitteeCache(beaconState); err != nil {
return nil, err
}
}
return beaconState, nil
}
// ProcessParticipationFlagUpdates processes participation flag updates by rotating current to previous.
//
// Spec code:
// def process_participation_flag_updates(state: BeaconState) -> None:
// state.previous_epoch_participation = state.current_epoch_participation
// state.current_epoch_participation = [ParticipationFlags(0b0000_0000) for _ in range(len(state.validators))]
func ProcessParticipationFlagUpdates(beaconState state.BeaconStateAltair) (state.BeaconStateAltair, error) {
c, err := beaconState.CurrentEpochParticipation()
if err != nil {
return nil, err
}
if err := beaconState.SetPreviousParticipationBits(c); err != nil {
return nil, err
}
if err := beaconState.SetCurrentParticipationBits(make([]byte, beaconState.NumValidators())); err != nil {
return nil, err
}
return beaconState, nil
}
// ProcessSlashings processes the slashed validators during epoch processing,
// The function is modified to use PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR.
//
// Spec code:
// def process_slashings(state: BeaconState) -> None:
// epoch = get_current_epoch(state)
// total_balance = get_total_active_balance(state)
// adjusted_total_slashing_balance = min(sum(state.slashings) * PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR, total_balance)
// for index, validator in enumerate(state.validators):
// if validator.slashed and epoch + EPOCHS_PER_SLASHINGS_VECTOR // 2 == validator.withdrawable_epoch:
// increment = EFFECTIVE_BALANCE_INCREMENT # Factored out from penalty numerator to avoid uint64 overflow
// penalty_numerator = validator.effective_balance // increment * adjusted_total_slashing_balance
// penalty = penalty_numerator // total_balance * increment
// decrease_balance(state, ValidatorIndex(index), penalty)
// decrease_balance(state, ValidatorIndex(index), penalty)
func ProcessSlashings(state state.BeaconState) (state.BeaconState, error) {
currentEpoch := helpers.CurrentEpoch(state)
totalBalance, err := helpers.TotalActiveBalance(state)
if err != nil {
return nil, errors.Wrap(err, "could not get total active balance")
}
// Compute slashed balances in the current epoch
exitLength := params.BeaconConfig().EpochsPerSlashingsVector
// Compute the sum of state slashings
slashings := state.Slashings()
totalSlashing := uint64(0)
for _, slashing := range slashings {
totalSlashing += slashing
}
// a callback is used here to apply the following actions to all validators
// below equally.
increment := params.BeaconConfig().EffectiveBalanceIncrement
minSlashing := mathutil.Min(totalSlashing*params.BeaconConfig().ProportionalSlashingMultiplierAltair, totalBalance)
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, types.ValidatorIndex(idx), penalty); err != nil {
return false, val, err
}
return true, val, nil
}
return false, val, nil
})
return state, err
}

View File

@@ -0,0 +1,181 @@
package altair_test
import (
"context"
"fmt"
"testing"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core/altair"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state/v2"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"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"
"google.golang.org/protobuf/proto"
)
func TestProcessSyncCommitteeUpdates_CanRotate(t *testing.T) {
s, _ := testutil.DeterministicGenesisStateAltair(t, params.BeaconConfig().MaxValidatorsPerCommittee)
h := &ethpb.BeaconBlockHeader{
StateRoot: bytesutil.PadTo([]byte{'a'}, 32),
ParentRoot: bytesutil.PadTo([]byte{'b'}, 32),
BodyRoot: bytesutil.PadTo([]byte{'c'}, 32),
}
require.NoError(t, s.SetLatestBlockHeader(h))
postState, err := altair.ProcessSyncCommitteeUpdates(context.Background(), s)
require.NoError(t, err)
current, err := postState.CurrentSyncCommittee()
require.NoError(t, err)
next, err := postState.NextSyncCommittee()
require.NoError(t, err)
require.DeepEqual(t, current, next)
require.NoError(t, s.SetSlot(params.BeaconConfig().SlotsPerEpoch))
postState, err = altair.ProcessSyncCommitteeUpdates(context.Background(), s)
require.NoError(t, err)
c, err := postState.CurrentSyncCommittee()
require.NoError(t, err)
n, err := postState.NextSyncCommittee()
require.NoError(t, err)
require.DeepEqual(t, current, c)
require.DeepEqual(t, next, n)
require.NoError(t, s.SetSlot(types.Slot(params.BeaconConfig().EpochsPerSyncCommitteePeriod)*params.BeaconConfig().SlotsPerEpoch-1))
postState, err = altair.ProcessSyncCommitteeUpdates(context.Background(), s)
require.NoError(t, err)
c, err = postState.CurrentSyncCommittee()
require.NoError(t, err)
n, err = postState.NextSyncCommittee()
require.NoError(t, err)
require.NotEqual(t, current, c)
require.NotEqual(t, next, n)
require.DeepEqual(t, next, c)
// Test boundary condition.
slot := params.BeaconConfig().SlotsPerEpoch * types.Slot(helpers.CurrentEpoch(s)+params.BeaconConfig().EpochsPerSyncCommitteePeriod)
require.NoError(t, s.SetSlot(slot))
boundaryCommittee, err := altair.NextSyncCommittee(context.Background(), s)
require.NoError(t, err)
require.DeepNotEqual(t, boundaryCommittee, n)
}
func TestProcessParticipationFlagUpdates_CanRotate(t *testing.T) {
s, _ := testutil.DeterministicGenesisStateAltair(t, params.BeaconConfig().MaxValidatorsPerCommittee)
c, err := s.CurrentEpochParticipation()
require.NoError(t, err)
require.DeepEqual(t, make([]byte, params.BeaconConfig().MaxValidatorsPerCommittee), c)
p, err := s.PreviousEpochParticipation()
require.NoError(t, err)
require.DeepEqual(t, make([]byte, params.BeaconConfig().MaxValidatorsPerCommittee), p)
newC := []byte{'a'}
newP := []byte{'b'}
require.NoError(t, s.SetCurrentParticipationBits(newC))
require.NoError(t, s.SetPreviousParticipationBits(newP))
c, err = s.CurrentEpochParticipation()
require.NoError(t, err)
require.DeepEqual(t, newC, c)
p, err = s.PreviousEpochParticipation()
require.NoError(t, err)
require.DeepEqual(t, newP, p)
s, err = altair.ProcessParticipationFlagUpdates(s)
require.NoError(t, err)
c, err = s.CurrentEpochParticipation()
require.NoError(t, err)
require.DeepEqual(t, make([]byte, params.BeaconConfig().MaxValidatorsPerCommittee), c)
p, err = s.PreviousEpochParticipation()
require.NoError(t, err)
require.DeepEqual(t, newC, p)
}
func TestProcessSlashings_NotSlashed(t *testing.T) {
base := &ethpb.BeaconStateAltair{
Slot: 0,
Validators: []*ethpb.Validator{{Slashed: true}},
Balances: []uint64{params.BeaconConfig().MaxEffectiveBalance},
Slashings: []uint64{0, 1e9},
}
s, err := stateAltair.InitializeFromProto(base)
require.NoError(t, err)
newState, err := altair.ProcessSlashings(s)
require.NoError(t, err)
wanted := params.BeaconConfig().MaxEffectiveBalance
assert.Equal(t, wanted, newState.Balances()[0], "Unexpected slashed balance")
}
func TestProcessSlashings_SlashedLess(t *testing.T) {
tests := []struct {
state *ethpb.BeaconStateAltair
want uint64
}{
{
state: &ethpb.BeaconStateAltair{
Validators: []*ethpb.Validator{
{Slashed: true,
WithdrawableEpoch: params.BeaconConfig().EpochsPerSlashingsVector / 2,
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance},
{ExitEpoch: params.BeaconConfig().FarFutureEpoch, EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance}},
Balances: []uint64{params.BeaconConfig().MaxEffectiveBalance, params.BeaconConfig().MaxEffectiveBalance},
Slashings: []uint64{0, 1e9},
},
want: uint64(30000000000),
},
{
state: &ethpb.BeaconStateAltair{
Validators: []*ethpb.Validator{
{Slashed: true,
WithdrawableEpoch: params.BeaconConfig().EpochsPerSlashingsVector / 2,
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance},
{ExitEpoch: params.BeaconConfig().FarFutureEpoch, EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance},
{ExitEpoch: params.BeaconConfig().FarFutureEpoch, EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance},
},
Balances: []uint64{params.BeaconConfig().MaxEffectiveBalance, params.BeaconConfig().MaxEffectiveBalance},
Slashings: []uint64{0, 1e9},
},
want: uint64(31000000000),
},
{
state: &ethpb.BeaconStateAltair{
Validators: []*ethpb.Validator{
{Slashed: true,
WithdrawableEpoch: params.BeaconConfig().EpochsPerSlashingsVector / 2,
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance},
{ExitEpoch: params.BeaconConfig().FarFutureEpoch, EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance},
{ExitEpoch: params.BeaconConfig().FarFutureEpoch, EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance},
},
Balances: []uint64{params.BeaconConfig().MaxEffectiveBalance, params.BeaconConfig().MaxEffectiveBalance},
Slashings: []uint64{0, 2 * 1e9},
},
want: uint64(30000000000),
},
{
state: &ethpb.BeaconStateAltair{
Validators: []*ethpb.Validator{
{Slashed: true,
WithdrawableEpoch: params.BeaconConfig().EpochsPerSlashingsVector / 2,
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance - params.BeaconConfig().EffectiveBalanceIncrement},
{ExitEpoch: params.BeaconConfig().FarFutureEpoch, EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance - params.BeaconConfig().EffectiveBalanceIncrement}},
Balances: []uint64{params.BeaconConfig().MaxEffectiveBalance - params.BeaconConfig().EffectiveBalanceIncrement, params.BeaconConfig().MaxEffectiveBalance - params.BeaconConfig().EffectiveBalanceIncrement},
Slashings: []uint64{0, 1e9},
},
want: uint64(29000000000),
},
}
for i, tt := range tests {
t.Run(fmt.Sprint(i), func(t *testing.T) {
helpers.ClearCache()
original := proto.Clone(tt.state)
s, err := stateAltair.InitializeFromProto(tt.state)
require.NoError(t, err)
newState, err := altair.ProcessSlashings(s)
require.NoError(t, err)
assert.Equal(t, tt.want, newState.Balances()[0], "ProcessSlashings({%v}) = newState; newState.Balances[0] = %d", original, newState.Balances()[0])
})
}
}

View File

@@ -0,0 +1,60 @@
package altair
import (
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/shared/mathutil"
"github.com/prysmaticlabs/prysm/shared/params"
)
// BaseReward takes state and validator index and calculate
// individual validator's base reward.
//
// Spec code:
// def get_base_reward(state: BeaconState, index: ValidatorIndex) -> Gwei:
// """
// Return the base reward for the validator defined by ``index`` with respect to the current ``state``.
//
// Note: An optimally performing validator can earn one base reward per epoch over a long time horizon.
// This takes into account both per-epoch (e.g. attestation) and intermittent duties (e.g. block proposal
// and sync committees).
// """
// increments = state.validators[index].effective_balance // EFFECTIVE_BALANCE_INCREMENT
// return Gwei(increments * get_base_reward_per_increment(state))
func BaseReward(s state.ReadOnlyBeaconState, index types.ValidatorIndex) (uint64, error) {
totalBalance, err := helpers.TotalActiveBalance(s)
if err != nil {
return 0, errors.Wrap(err, "could not calculate active balance")
}
return BaseRewardWithTotalBalance(s, index, totalBalance)
}
// BaseRewardWithTotalBalance calculates the base reward with the provided total balance.
func BaseRewardWithTotalBalance(s state.ReadOnlyBeaconState, index types.ValidatorIndex, totalBalance uint64) (uint64, error) {
val, err := s.ValidatorAtIndexReadOnly(index)
if err != nil {
return 0, err
}
cfg := params.BeaconConfig()
increments := val.EffectiveBalance() / cfg.EffectiveBalanceIncrement
baseRewardPerInc, err := BaseRewardPerIncrement(totalBalance)
if err != nil {
return 0, err
}
return increments * baseRewardPerInc, nil
}
// BaseRewardPerIncrement of the beacon state
//
// Spec code:
// def get_base_reward_per_increment(state: BeaconState) -> Gwei:
// return Gwei(EFFECTIVE_BALANCE_INCREMENT * BASE_REWARD_FACTOR // integer_squareroot(get_total_active_balance(state)))
func BaseRewardPerIncrement(activeBalance uint64) (uint64, error) {
if activeBalance == 0 {
return 0, errors.New("active balance can't be 0")
}
cfg := params.BeaconConfig()
return cfg.EffectiveBalanceIncrement * cfg.BaseRewardFactor / mathutil.IntegerSquareRoot(activeBalance), nil
}

View File

@@ -0,0 +1,193 @@
package altair_test
import (
"math"
"testing"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core/altair"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
)
func Test_BaseReward(t *testing.T) {
genState := func(valCount uint64) state.ReadOnlyBeaconState {
s, _ := testutil.DeterministicGenesisStateAltair(t, valCount)
return s
}
tests := []struct {
name string
valIdx types.ValidatorIndex
st state.ReadOnlyBeaconState
want uint64
errString string
}{
{
name: "unknown validator",
valIdx: 2,
st: genState(1),
want: 0,
errString: "index 2 out of range",
},
{
name: "active balance is 32eth",
valIdx: 0,
st: genState(1),
want: 11448672,
errString: "",
},
{
name: "active balance is 32eth * target committee size",
valIdx: 0,
st: genState(params.BeaconConfig().TargetCommitteeSize),
want: 1011904,
errString: "",
},
{
name: "active balance is 32eth * max validator per committee size",
valIdx: 0,
st: genState(params.BeaconConfig().MaxValidatorsPerCommittee),
want: 252960,
errString: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := altair.BaseReward(tt.st, tt.valIdx)
if (err != nil) && (tt.errString != "") {
require.ErrorContains(t, tt.errString, err)
return
}
require.Equal(t, tt.want, got)
})
}
}
func Test_BaseRewardWithTotalBalance(t *testing.T) {
s, _ := testutil.DeterministicGenesisStateAltair(t, 1)
tests := []struct {
name string
valIdx types.ValidatorIndex
activeBalance uint64
want uint64
errString string
}{
{
name: "active balance is 0",
valIdx: 0,
activeBalance: 0,
want: 0,
errString: "active balance can't be 0",
},
{
name: "unknown validator",
valIdx: 2,
activeBalance: 1,
want: 0,
errString: "index 2 out of range",
},
{
name: "active balance is 1",
valIdx: 0,
activeBalance: 1,
want: 2048000000000,
errString: "",
},
{
name: "active balance is 1eth",
valIdx: 0,
activeBalance: params.BeaconConfig().EffectiveBalanceIncrement,
want: 64765024,
errString: "",
},
{
name: "active balance is 32eth",
valIdx: 0,
activeBalance: params.BeaconConfig().MaxEffectiveBalance,
want: 11448672,
errString: "",
},
{
name: "active balance is 32eth * 1m validators",
valIdx: 0,
activeBalance: params.BeaconConfig().MaxEffectiveBalance * 1e9,
want: 544,
errString: "",
},
{
name: "active balance is max uint64",
valIdx: 0,
activeBalance: math.MaxUint64,
want: 448,
errString: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := altair.BaseRewardWithTotalBalance(s, tt.valIdx, tt.activeBalance)
if (err != nil) && (tt.errString != "") {
require.ErrorContains(t, tt.errString, err)
return
}
require.Equal(t, tt.want, got)
})
}
}
func Test_BaseRewardPerIncrement(t *testing.T) {
tests := []struct {
name string
activeBalance uint64
want uint64
errString string
}{
{
name: "active balance is 0",
activeBalance: 0,
want: 0,
errString: "active balance can't be 0",
},
{
name: "active balance is 1",
activeBalance: 1,
want: 64000000000,
errString: "",
},
{
name: "active balance is 1eth",
activeBalance: params.BeaconConfig().EffectiveBalanceIncrement,
want: 2023907,
errString: "",
},
{
name: "active balance is 32eth",
activeBalance: params.BeaconConfig().MaxEffectiveBalance,
want: 357771,
errString: "",
},
{
name: "active balance is 32eth * 1m validators",
activeBalance: params.BeaconConfig().MaxEffectiveBalance * 1e9,
want: 17,
errString: "",
},
{
name: "active balance is max uint64",
activeBalance: math.MaxUint64,
want: 14,
errString: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := altair.BaseRewardPerIncrement(tt.activeBalance)
if (err != nil) && (tt.errString != "") {
require.ErrorContains(t, tt.errString, err)
return
}
require.Equal(t, tt.want, got)
})
}
}

View File

@@ -0,0 +1,221 @@
package altair
import (
"context"
"fmt"
"time"
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/hashutil"
"github.com/prysmaticlabs/prysm/shared/mathutil"
"github.com/prysmaticlabs/prysm/shared/params"
)
const maxRandomByte = uint64(1<<8 - 1)
// ValidateNilSyncContribution validates the following fields are not nil:
// -the contribution and proof itself
// -the message within contribution and proof
// -the contribution within contribution and proof
// -the aggregation bits within contribution
func ValidateNilSyncContribution(s *ethpb.SignedContributionAndProof) error {
if s == nil {
return errors.New("signed message can't be nil")
}
if s.Message == nil {
return errors.New("signed contribution's message can't be nil")
}
if s.Message.Contribution == nil {
return errors.New("inner contribution can't be nil")
}
if s.Message.Contribution.AggregationBits == nil {
return errors.New("contribution's bitfield can't be nil")
}
return nil
}
// NextSyncCommittee returns the next sync committee for a given state.
//
// Spec code:
// def get_next_sync_committee(state: BeaconState) -> SyncCommittee:
// """
// Return the next sync committee, with possible pubkey duplicates.
// """
// indices = get_next_sync_committee_indices(state)
// pubkeys = [state.validators[index].pubkey for index in indices]
// aggregate_pubkey = bls.AggregatePKs(pubkeys)
// return SyncCommittee(pubkeys=pubkeys, aggregate_pubkey=aggregate_pubkey)
func NextSyncCommittee(ctx context.Context, s state.BeaconStateAltair) (*ethpb.SyncCommittee, error) {
indices, err := NextSyncCommitteeIndices(ctx, s)
if err != nil {
return nil, err
}
pubkeys := make([][]byte, len(indices))
for i, index := range indices {
p := s.PubkeyAtIndex(index)
pubkeys[i] = p[:]
}
aggregated, err := bls.AggregatePublicKeys(pubkeys)
if err != nil {
return nil, err
}
return &ethpb.SyncCommittee{
Pubkeys: pubkeys,
AggregatePubkey: aggregated.Marshal(),
}, nil
}
// NextSyncCommitteeIndices returns the next sync committee indices for a given state.
//
// Spec code:
// def get_next_sync_committee_indices(state: BeaconState) -> Sequence[ValidatorIndex]:
// """
// Return the sync committee indices, with possible duplicates, for the next sync committee.
// """
// epoch = Epoch(get_current_epoch(state) + 1)
//
// MAX_RANDOM_BYTE = 2**8 - 1
// active_validator_indices = get_active_validator_indices(state, epoch)
// active_validator_count = uint64(len(active_validator_indices))
// seed = get_seed(state, epoch, DOMAIN_SYNC_COMMITTEE)
// i = 0
// sync_committee_indices: List[ValidatorIndex] = []
// while len(sync_committee_indices) < SYNC_COMMITTEE_SIZE:
// shuffled_index = compute_shuffled_index(uint64(i % active_validator_count), active_validator_count, seed)
// candidate_index = active_validator_indices[shuffled_index]
// random_byte = hash(seed + uint_to_bytes(uint64(i // 32)))[i % 32]
// effective_balance = state.validators[candidate_index].effective_balance
// if effective_balance * MAX_RANDOM_BYTE >= MAX_EFFECTIVE_BALANCE * random_byte:
// sync_committee_indices.append(candidate_index)
// i += 1
// return sync_committee_indices
func NextSyncCommitteeIndices(ctx context.Context, s state.BeaconStateAltair) ([]types.ValidatorIndex, error) {
epoch := helpers.NextEpoch(s)
indices, err := helpers.ActiveValidatorIndices(s, epoch)
if err != nil {
return nil, err
}
seed, err := helpers.Seed(s, epoch, params.BeaconConfig().DomainSyncCommittee)
if err != nil {
return nil, err
}
count := uint64(len(indices))
cfg := params.BeaconConfig()
syncCommitteeSize := cfg.SyncCommitteeSize
cIndices := make([]types.ValidatorIndex, 0, syncCommitteeSize)
hashFunc := hashutil.CustomSHA256Hasher()
for i := types.ValidatorIndex(0); uint64(len(cIndices)) < params.BeaconConfig().SyncCommitteeSize; i++ {
if ctx.Err() != nil {
return nil, ctx.Err()
}
sIndex, err := helpers.ComputeShuffledIndex(i.Mod(count), count, seed, true)
if err != nil {
return nil, err
}
b := append(seed[:], bytesutil.Bytes8(uint64(i.Div(32)))...)
randomByte := hashFunc(b)[i%32]
cIndex := indices[sIndex]
v, err := s.ValidatorAtIndexReadOnly(cIndex)
if err != nil {
return nil, err
}
effectiveBal := v.EffectiveBalance()
if effectiveBal*maxRandomByte >= cfg.MaxEffectiveBalance*uint64(randomByte) {
cIndices = append(cIndices, cIndex)
}
}
return cIndices, nil
}
// SyncSubCommitteePubkeys returns the pubkeys participating in a sync subcommittee.
//
// def get_sync_subcommittee_pubkeys(state: BeaconState, subcommittee_index: uint64) -> Sequence[BLSPubkey]:
// # Committees assigned to `slot` sign for `slot - 1`
// # This creates the exceptional logic below when transitioning between sync committee periods
// next_slot_epoch = compute_epoch_at_slot(Slot(state.slot + 1))
// if compute_sync_committee_period(get_current_epoch(state)) == compute_sync_committee_period(next_slot_epoch):
// sync_committee = state.current_sync_committee
// else:
// sync_committee = state.next_sync_committee
//
// # Return pubkeys for the subcommittee index
// sync_subcommittee_size = SYNC_COMMITTEE_SIZE // SYNC_COMMITTEE_SUBNET_COUNT
// i = subcommittee_index * sync_subcommittee_size
// return sync_committee.pubkeys[i:i + sync_subcommittee_size]
func SyncSubCommitteePubkeys(syncCommittee *ethpb.SyncCommittee, subComIdx types.CommitteeIndex) ([][]byte, error) {
cfg := params.BeaconConfig()
subCommSize := cfg.SyncCommitteeSize / cfg.SyncCommitteeSubnetCount
i := uint64(subComIdx) * subCommSize
endOfSubCom := i + subCommSize
pubkeyLen := uint64(len(syncCommittee.Pubkeys))
if endOfSubCom > pubkeyLen {
return nil, errors.Errorf("end index is larger than array length: %d > %d", endOfSubCom, pubkeyLen)
}
return syncCommittee.Pubkeys[i:endOfSubCom], nil
}
// IsSyncCommitteeAggregator checks whether the provided signature is for a valid
// aggregator.
//
// def is_sync_committee_aggregator(signature: BLSSignature) -> bool:
// modulo = max(1, SYNC_COMMITTEE_SIZE // SYNC_COMMITTEE_SUBNET_COUNT // TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE)
// return bytes_to_uint64(hash(signature)[0:8]) % modulo == 0
func IsSyncCommitteeAggregator(sig []byte) (bool, error) {
if len(sig) != params.BeaconConfig().BLSSignatureLength {
return false, errors.New("incorrect sig length")
}
cfg := params.BeaconConfig()
modulo := mathutil.Max(1, cfg.SyncCommitteeSize/cfg.SyncCommitteeSubnetCount/cfg.TargetAggregatorsPerSyncSubcommittee)
hashedSig := hashutil.Hash(sig)
return bytesutil.FromBytes8(hashedSig[:8])%modulo == 0, nil
}
// ValidateSyncMessageTime validates sync message to ensure that the provided slot is valid.
func ValidateSyncMessageTime(slot types.Slot, genesisTime time.Time, clockDisparity time.Duration) error {
if err := helpers.ValidateSlotClock(slot, uint64(genesisTime.Unix())); err != nil {
return err
}
messageTime, err := helpers.SlotToTime(uint64(genesisTime.Unix()), slot)
if err != nil {
return err
}
currentSlot := helpers.SlotsSince(genesisTime)
slotStartTime, err := helpers.SlotToTime(uint64(genesisTime.Unix()), currentSlot)
if err != nil {
return err
}
lowestSlotBound := slotStartTime.Add(-clockDisparity)
currentLowerBound := time.Now().Add(-clockDisparity)
// In the event the Slot's start time, is before the
// current allowable bound, we set the slot's start
// time as the bound.
if slotStartTime.Before(currentLowerBound) {
lowestSlotBound = slotStartTime
}
lowerBound := lowestSlotBound
upperBound := time.Now().Add(clockDisparity)
// Verify sync message slot is within the time range.
if messageTime.Before(lowerBound) || messageTime.After(upperBound) {
return fmt.Errorf(
"sync message slot %d not within allowable range of %d to %d (current slot)",
slot,
lowerBound.Unix(),
upperBound.Unix(),
)
}
return nil
}

View File

@@ -0,0 +1,402 @@
package altair_test
import (
"context"
"testing"
"time"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core/altair"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state/v2"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/bls"
"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 TestSyncCommitteeIndices_CanGet(t *testing.T) {
getState := func(t *testing.T, count uint64) *stateAltair.BeaconState {
validators := make([]*ethpb.Validator, count)
for i := 0; i < len(validators); i++ {
validators[i] = &ethpb.Validator{
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
EffectiveBalance: params.BeaconConfig().MinDepositAmount,
}
}
state, err := stateAltair.InitializeFromProto(&ethpb.BeaconStateAltair{
Validators: validators,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
})
require.NoError(t, err)
return state
}
type args struct {
state *stateAltair.BeaconState
epoch types.Epoch
}
tests := []struct {
name string
args args
wantErr bool
errString string
}{
{
name: "nil state",
args: args{
state: nil,
},
wantErr: true,
errString: "nil inner state",
},
{
name: "genesis validator count, epoch 0",
args: args{
state: getState(t, params.BeaconConfig().MinGenesisActiveValidatorCount),
epoch: 0,
},
wantErr: false,
},
{
name: "genesis validator count, epoch 100",
args: args{
state: getState(t, params.BeaconConfig().MinGenesisActiveValidatorCount),
epoch: 100,
},
wantErr: false,
},
{
name: "less than optimal validator count, epoch 100",
args: args{
state: getState(t, params.BeaconConfig().MaxValidatorsPerCommittee),
epoch: 100,
},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
helpers.ClearCache()
got, err := altair.NextSyncCommitteeIndices(context.Background(), tt.args.state)
if tt.wantErr {
require.ErrorContains(t, tt.errString, err)
} else {
require.NoError(t, err)
require.Equal(t, int(params.BeaconConfig().SyncCommitteeSize), len(got))
}
})
}
}
func TestSyncCommitteeIndices_DifferentPeriods(t *testing.T) {
helpers.ClearCache()
getState := func(t *testing.T, count uint64) *stateAltair.BeaconState {
validators := make([]*ethpb.Validator, count)
for i := 0; i < len(validators); i++ {
validators[i] = &ethpb.Validator{
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
EffectiveBalance: params.BeaconConfig().MinDepositAmount,
}
}
state, err := stateAltair.InitializeFromProto(&ethpb.BeaconStateAltair{
Validators: validators,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
})
require.NoError(t, err)
return state
}
state := getState(t, params.BeaconConfig().MaxValidatorsPerCommittee)
got1, err := altair.NextSyncCommitteeIndices(context.Background(), state)
require.NoError(t, err)
require.NoError(t, state.SetSlot(params.BeaconConfig().SlotsPerEpoch))
got2, err := altair.NextSyncCommitteeIndices(context.Background(), state)
require.NoError(t, err)
require.DeepNotEqual(t, got1, got2)
require.NoError(t, state.SetSlot(params.BeaconConfig().SlotsPerEpoch*types.Slot(params.BeaconConfig().EpochsPerSyncCommitteePeriod)))
got2, err = altair.NextSyncCommitteeIndices(context.Background(), state)
require.NoError(t, err)
require.DeepNotEqual(t, got1, got2)
require.NoError(t, state.SetSlot(params.BeaconConfig().SlotsPerEpoch*types.Slot(2*params.BeaconConfig().EpochsPerSyncCommitteePeriod)))
got2, err = altair.NextSyncCommitteeIndices(context.Background(), state)
require.NoError(t, err)
require.DeepNotEqual(t, got1, got2)
}
func TestSyncCommittee_CanGet(t *testing.T) {
getState := func(t *testing.T, count uint64) *stateAltair.BeaconState {
validators := make([]*ethpb.Validator, count)
for i := 0; i < len(validators); i++ {
blsKey, err := bls.RandKey()
require.NoError(t, err)
validators[i] = &ethpb.Validator{
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
EffectiveBalance: params.BeaconConfig().MinDepositAmount,
PublicKey: blsKey.PublicKey().Marshal(),
}
}
state, err := stateAltair.InitializeFromProto(&ethpb.BeaconStateAltair{
Validators: validators,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
})
require.NoError(t, err)
return state
}
type args struct {
state *stateAltair.BeaconState
epoch types.Epoch
}
tests := []struct {
name string
args args
wantErr bool
errString string
}{
{
name: "nil state",
args: args{
state: nil,
},
wantErr: true,
errString: "nil inner state",
},
{
name: "genesis validator count, epoch 0",
args: args{
state: getState(t, params.BeaconConfig().MinGenesisActiveValidatorCount),
epoch: 0,
},
wantErr: false,
},
{
name: "genesis validator count, epoch 100",
args: args{
state: getState(t, params.BeaconConfig().MinGenesisActiveValidatorCount),
epoch: 100,
},
wantErr: false,
},
{
name: "less than optimal validator count, epoch 100",
args: args{
state: getState(t, params.BeaconConfig().MaxValidatorsPerCommittee),
epoch: 100,
},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
helpers.ClearCache()
if !tt.wantErr {
require.NoError(t, tt.args.state.SetSlot(types.Slot(tt.args.epoch)*params.BeaconConfig().SlotsPerEpoch))
}
got, err := altair.NextSyncCommittee(context.Background(), tt.args.state)
if tt.wantErr {
require.ErrorContains(t, tt.errString, err)
} else {
require.NoError(t, err)
require.Equal(t, int(params.BeaconConfig().SyncCommitteeSize), len(got.Pubkeys))
require.Equal(t, params.BeaconConfig().BLSPubkeyLength, len(got.AggregatePubkey))
}
})
}
}
func TestValidateNilSyncContribution(t *testing.T) {
tests := []struct {
name string
s *ethpb.SignedContributionAndProof
wantErr bool
}{
{
name: "nil object",
s: nil,
wantErr: true,
},
{
name: "nil message",
s: &ethpb.SignedContributionAndProof{},
wantErr: true,
},
{
name: "nil contribution",
s: &ethpb.SignedContributionAndProof{Message: &ethpb.ContributionAndProof{}},
wantErr: true,
},
{
name: "nil bitfield",
s: &ethpb.SignedContributionAndProof{
Message: &ethpb.ContributionAndProof{
Contribution: &ethpb.SyncCommitteeContribution{},
}},
wantErr: true,
},
{
name: "non nil sync contribution",
s: &ethpb.SignedContributionAndProof{
Message: &ethpb.ContributionAndProof{
Contribution: &ethpb.SyncCommitteeContribution{
AggregationBits: []byte{},
},
}},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := altair.ValidateNilSyncContribution(tt.s); (err != nil) != tt.wantErr {
t.Errorf("ValidateNilSyncContribution() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
func TestSyncSubCommitteePubkeys_CanGet(t *testing.T) {
helpers.ClearCache()
state := getState(t, params.BeaconConfig().MaxValidatorsPerCommittee)
com, err := altair.NextSyncCommittee(context.Background(), state)
require.NoError(t, err)
sub, err := altair.SyncSubCommitteePubkeys(com, 0)
require.NoError(t, err)
subCommSize := params.BeaconConfig().SyncCommitteeSize / params.BeaconConfig().SyncCommitteeSubnetCount
require.Equal(t, int(subCommSize), len(sub))
require.DeepSSZEqual(t, com.Pubkeys[0:subCommSize], sub)
sub, err = altair.SyncSubCommitteePubkeys(com, 1)
require.NoError(t, err)
require.DeepSSZEqual(t, com.Pubkeys[subCommSize:2*subCommSize], sub)
sub, err = altair.SyncSubCommitteePubkeys(com, 2)
require.NoError(t, err)
require.DeepSSZEqual(t, com.Pubkeys[2*subCommSize:3*subCommSize], sub)
sub, err = altair.SyncSubCommitteePubkeys(com, 3)
require.NoError(t, err)
require.DeepSSZEqual(t, com.Pubkeys[3*subCommSize:], sub)
}
func Test_ValidateSyncMessageTime(t *testing.T) {
if params.BeaconNetworkConfig().MaximumGossipClockDisparity < 200*time.Millisecond {
t.Fatal("This test expects the maximum clock disparity to be at least 200ms")
}
type args struct {
syncMessageSlot types.Slot
genesisTime time.Time
}
tests := []struct {
name string
args args
wantedErr string
}{
{
name: "sync_message.slot == current_slot",
args: args{
syncMessageSlot: 15,
genesisTime: timeutils.Now().Add(-15 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second),
},
},
{
name: "sync_message.slot == current_slot, received in middle of slot",
args: args{
syncMessageSlot: 15,
genesisTime: timeutils.Now().Add(
-15 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second,
).Add(-(time.Duration(params.BeaconConfig().SecondsPerSlot/2) * time.Second)),
},
},
{
name: "sync_message.slot == current_slot, received 200ms early",
args: args{
syncMessageSlot: 16,
genesisTime: timeutils.Now().Add(
-16 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second,
).Add(-200 * time.Millisecond),
},
},
{
name: "sync_message.slot > current_slot",
args: args{
syncMessageSlot: 16,
genesisTime: timeutils.Now().Add(-(15 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second)),
},
wantedErr: "sync message slot 16 not within allowable range of",
},
{
name: "sync_message.slot == current_slot+CLOCK_DISPARITY",
args: args{
syncMessageSlot: 100,
genesisTime: timeutils.Now().Add(-(100*time.Duration(params.BeaconConfig().SecondsPerSlot)*time.Second - params.BeaconNetworkConfig().MaximumGossipClockDisparity)),
},
wantedErr: "",
},
{
name: "sync_message.slot == current_slot+CLOCK_DISPARITY-1000ms",
args: args{
syncMessageSlot: 100,
genesisTime: timeutils.Now().Add(-(100 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second) + params.BeaconNetworkConfig().MaximumGossipClockDisparity + 1000*time.Millisecond),
},
wantedErr: "sync message slot 100 not within allowable range of",
},
{
name: "sync_message.slot == current_slot-CLOCK_DISPARITY",
args: args{
syncMessageSlot: 100,
genesisTime: timeutils.Now().Add(-(100*time.Duration(params.BeaconConfig().SecondsPerSlot)*time.Second + params.BeaconNetworkConfig().MaximumGossipClockDisparity)),
},
wantedErr: "",
},
{
name: "sync_message.slot > current_slot+CLOCK_DISPARITY",
args: args{
syncMessageSlot: 101,
genesisTime: timeutils.Now().Add(-(100*time.Duration(params.BeaconConfig().SecondsPerSlot)*time.Second + params.BeaconNetworkConfig().MaximumGossipClockDisparity)),
},
wantedErr: "sync message slot 101 not within allowable range of",
},
{
name: "sync_message.slot is well beyond current slot",
args: args{
syncMessageSlot: 1 << 32,
genesisTime: timeutils.Now().Add(-15 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second),
},
wantedErr: "which exceeds max allowed value relative to the local clock",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := altair.ValidateSyncMessageTime(tt.args.syncMessageSlot, tt.args.genesisTime,
params.BeaconNetworkConfig().MaximumGossipClockDisparity)
if tt.wantedErr != "" {
assert.ErrorContains(t, tt.wantedErr, err)
} else {
assert.NoError(t, err)
}
})
}
}
func getState(t *testing.T, count uint64) *stateAltair.BeaconState {
validators := make([]*ethpb.Validator, count)
for i := 0; i < len(validators); i++ {
blsKey, err := bls.RandKey()
require.NoError(t, err)
validators[i] = &ethpb.Validator{
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
EffectiveBalance: params.BeaconConfig().MinDepositAmount,
PublicKey: blsKey.PublicKey().Marshal(),
}
}
state, err := stateAltair.InitializeFromProto(&ethpb.BeaconStateAltair{
Validators: validators,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
})
require.NoError(t, err)
return state
}

View File

@@ -0,0 +1,110 @@
package altair
import (
"context"
"github.com/pkg/errors"
e "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch"
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
"go.opencensus.io/trace"
)
// ProcessEpoch 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.
//
// Spec code:
// def process_epoch(state: BeaconState) -> None:
// process_justification_and_finalization(state) # [Modified in Altair]
// process_inactivity_updates(state) # [New in Altair]
// process_rewards_and_penalties(state) # [Modified in Altair]
// process_registry_updates(state)
// process_slashings(state) # [Modified in Altair]
// process_eth1_data_reset(state)
// process_effective_balance_updates(state)
// process_slashings_reset(state)
// process_randao_mixes_reset(state)
// process_historical_roots_update(state)
// process_participation_flag_updates(state) # [New in Altair]
// process_sync_committee_updates(state) # [New in Altair]
func ProcessEpoch(ctx context.Context, state state.BeaconStateAltair) (state.BeaconStateAltair, error) {
ctx, span := trace.StartSpan(ctx, "altair.ProcessEpoch")
defer span.End()
if state == nil || state.IsNil() {
return nil, errors.New("nil state")
}
vp, bp, err := InitializeEpochValidators(ctx, state)
if err != nil {
return nil, err
}
// New in Altair.
vp, bp, err = ProcessEpochParticipation(ctx, state, bp, vp)
if err != nil {
return nil, err
}
state, err = precompute.ProcessJustificationAndFinalizationPreCompute(state, bp)
if err != nil {
return nil, errors.Wrap(err, "could not process justification")
}
// New in Altair.
state, vp, err = ProcessInactivityScores(ctx, state, vp)
if err != nil {
return nil, errors.Wrap(err, "could not process inactivity updates")
}
// New in Altair.
state, err = ProcessRewardsAndPenaltiesPrecompute(state, bp, vp)
if err != nil {
return nil, errors.Wrap(err, "could not process rewards and penalties")
}
state, err = e.ProcessRegistryUpdates(state)
if err != nil {
return nil, errors.Wrap(err, "could not process registry updates")
}
// Modified in Altair.
state, err = ProcessSlashings(state)
if err != nil {
return nil, err
}
state, err = e.ProcessEth1DataReset(state)
if err != nil {
return nil, err
}
state, err = e.ProcessEffectiveBalanceUpdates(state)
if err != nil {
return nil, err
}
state, err = e.ProcessSlashingsReset(state)
if err != nil {
return nil, err
}
state, err = e.ProcessRandaoMixesReset(state)
if err != nil {
return nil, err
}
state, err = e.ProcessHistoricalRootsUpdate(state)
if err != nil {
return nil, err
}
// New in Altair.
state, err = ProcessParticipationFlagUpdates(state)
if err != nil {
return nil, err
}
// New in Altair.
state, err = ProcessSyncCommitteeUpdates(ctx, state)
if err != nil {
return nil, err
}
return state, nil
}

View File

@@ -0,0 +1,34 @@
package altair_test
import (
"context"
"testing"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/go-bitfield"
"github.com/prysmaticlabs/prysm/beacon-chain/core/altair"
stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state/v2"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
)
func TestProcessEpoch_CanProcess(t *testing.T) {
epoch := types.Epoch(1)
slashing := make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector)
base := &ethpb.BeaconStateAltair{
Slot: params.BeaconConfig().SlotsPerEpoch.Mul(uint64(epoch)) + 1,
BlockRoots: make([][]byte, 128),
Slashings: slashing,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
FinalizedCheckpoint: &ethpb.Checkpoint{Root: make([]byte, 32)},
JustificationBits: bitfield.Bitvector4{0x00},
CurrentJustifiedCheckpoint: &ethpb.Checkpoint{Root: make([]byte, 32)},
}
s, err := stateAltair.InitializeFromProto(base)
require.NoError(t, err)
require.NoError(t, s.SetValidators([]*ethpb.Validator{}))
newState, err := altair.ProcessEpoch(context.Background(), s)
require.NoError(t, err)
require.Equal(t, uint64(0), newState.Slashings()[2], "Unexpected slashed balance")
}

View File

@@ -0,0 +1,180 @@
package altair
import (
"context"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
statealtair "github.com/prysmaticlabs/prysm/beacon-chain/state/v2"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/attestationutil"
"github.com/prysmaticlabs/prysm/shared/params"
)
// UpgradeToAltair updates input state to return the version Altair state.
//
// Spec code:
// def upgrade_to_altair(pre: phase0.BeaconState) -> BeaconState:
// epoch = phase0.get_current_epoch(pre)
// post = BeaconState(
// # Versioning
// genesis_time=pre.genesis_time,
// genesis_validators_root=pre.genesis_validators_root,
// slot=pre.slot,
// fork=Fork(
// previous_version=pre.fork.current_version,
// current_version=ALTAIR_FORK_VERSION,
// epoch=epoch,
// ),
// # History
// latest_block_header=pre.latest_block_header,
// block_roots=pre.block_roots,
// state_roots=pre.state_roots,
// historical_roots=pre.historical_roots,
// # Eth1
// eth1_data=pre.eth1_data,
// eth1_data_votes=pre.eth1_data_votes,
// eth1_deposit_index=pre.eth1_deposit_index,
// # Registry
// validators=pre.validators,
// balances=pre.balances,
// # Randomness
// randao_mixes=pre.randao_mixes,
// # Slashings
// slashings=pre.slashings,
// # Participation
// previous_epoch_participation=[ParticipationFlags(0b0000_0000) for _ in range(len(pre.validators))],
// current_epoch_participation=[ParticipationFlags(0b0000_0000) for _ in range(len(pre.validators))],
// # Finality
// justification_bits=pre.justification_bits,
// previous_justified_checkpoint=pre.previous_justified_checkpoint,
// current_justified_checkpoint=pre.current_justified_checkpoint,
// finalized_checkpoint=pre.finalized_checkpoint,
// # Inactivity
// inactivity_scores=[uint64(0) for _ in range(len(pre.validators))],
// )
// # Fill in previous epoch participation from the pre state's pending attestations
// translate_participation(post, pre.previous_epoch_attestations)
//
// # Fill in sync committees
// # Note: A duplicate committee is assigned for the current and next committee at the fork boundary
// post.current_sync_committee = get_next_sync_committee(post)
// post.next_sync_committee = get_next_sync_committee(post)
// return post
func UpgradeToAltair(ctx context.Context, state state.BeaconState) (state.BeaconStateAltair, error) {
epoch := helpers.CurrentEpoch(state)
numValidators := state.NumValidators()
s := &ethpb.BeaconStateAltair{
GenesisTime: state.GenesisTime(),
GenesisValidatorsRoot: state.GenesisValidatorRoot(),
Slot: state.Slot(),
Fork: &ethpb.Fork{
PreviousVersion: state.Fork().CurrentVersion,
CurrentVersion: params.BeaconConfig().AltairForkVersion,
Epoch: epoch,
},
LatestBlockHeader: state.LatestBlockHeader(),
BlockRoots: state.BlockRoots(),
StateRoots: state.StateRoots(),
HistoricalRoots: state.HistoricalRoots(),
Eth1Data: state.Eth1Data(),
Eth1DataVotes: state.Eth1DataVotes(),
Eth1DepositIndex: state.Eth1DepositIndex(),
Validators: state.Validators(),
Balances: state.Balances(),
RandaoMixes: state.RandaoMixes(),
Slashings: state.Slashings(),
PreviousEpochParticipation: make([]byte, numValidators),
CurrentEpochParticipation: make([]byte, numValidators),
JustificationBits: state.JustificationBits(),
PreviousJustifiedCheckpoint: state.PreviousJustifiedCheckpoint(),
CurrentJustifiedCheckpoint: state.CurrentJustifiedCheckpoint(),
FinalizedCheckpoint: state.FinalizedCheckpoint(),
InactivityScores: make([]uint64, numValidators),
}
newState, err := statealtair.InitializeFromProto(s)
if err != nil {
return nil, err
}
prevEpochAtts, err := state.PreviousEpochAttestations()
if err != nil {
return nil, err
}
newState, err = TranslateParticipation(newState, prevEpochAtts)
if err != nil {
return nil, err
}
committee, err := NextSyncCommittee(ctx, newState)
if err != nil {
return nil, err
}
if err := newState.SetCurrentSyncCommittee(committee); err != nil {
return nil, err
}
if err := newState.SetNextSyncCommittee(committee); err != nil {
return nil, err
}
return newState, nil
}
// TranslateParticipation translates pending attestations into participation bits, then inserts the bits into beacon state.
// This is helper function to convert phase 0 beacon state(pending_attestations) to Altair beacon state(participation_bits).
//
// Spec code:
// def translate_participation(state: BeaconState, pending_attestations: Sequence[phase0.PendingAttestation]) -> None:
// for attestation in pending_attestations:
// data = attestation.data
// inclusion_delay = attestation.inclusion_delay
// # Translate attestation inclusion info to flag indices
// participation_flag_indices = get_attestation_participation_flag_indices(state, data, inclusion_delay)
//
// # Apply flags to all attesting validators
// epoch_participation = state.previous_epoch_participation
// for index in get_attesting_indices(state, data, attestation.aggregation_bits):
// for flag_index in participation_flag_indices:
// epoch_participation[index] = add_flag(epoch_participation[index], flag_index)
func TranslateParticipation(state *statealtair.BeaconState, atts []*ethpb.PendingAttestation) (*statealtair.BeaconState, error) {
epochParticipation, err := state.PreviousEpochParticipation()
if err != nil {
return nil, err
}
for _, att := range atts {
participatedFlags, err := AttestationParticipationFlagIndices(state, att.Data, att.InclusionDelay)
if err != nil {
return nil, err
}
committee, err := helpers.BeaconCommitteeFromState(state, att.Data.Slot, att.Data.CommitteeIndex)
if err != nil {
return nil, err
}
indices, err := attestationutil.AttestingIndices(att.AggregationBits, committee)
if err != nil {
return nil, err
}
cfg := params.BeaconConfig()
sourceFlagIndex := cfg.TimelySourceFlagIndex
targetFlagIndex := cfg.TimelyTargetFlagIndex
headFlagIndex := cfg.TimelyHeadFlagIndex
for _, index := range indices {
if participatedFlags[sourceFlagIndex] && !HasValidatorFlag(epochParticipation[index], sourceFlagIndex) {
epochParticipation[index] = AddValidatorFlag(epochParticipation[index], sourceFlagIndex)
}
if participatedFlags[targetFlagIndex] && !HasValidatorFlag(epochParticipation[index], targetFlagIndex) {
epochParticipation[index] = AddValidatorFlag(epochParticipation[index], targetFlagIndex)
}
if participatedFlags[headFlagIndex] && !HasValidatorFlag(epochParticipation[index], headFlagIndex) {
epochParticipation[index] = AddValidatorFlag(epochParticipation[index], headFlagIndex)
}
}
}
if err := state.SetPreviousParticipationBits(epochParticipation); err != nil {
return nil, err
}
return state, nil
}

View File

@@ -0,0 +1,117 @@
package altair_test
import (
"context"
"testing"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/go-bitfield"
"github.com/prysmaticlabs/prysm/beacon-chain/core/altair"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state/v2"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/attestationutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
)
func TestTranslateParticipation(t *testing.T) {
s, _ := testutil.DeterministicGenesisStateAltair(t, 64)
st, ok := s.(*stateAltair.BeaconState)
require.Equal(t, true, ok)
require.NoError(t, st.SetSlot(st.Slot()+params.BeaconConfig().MinAttestationInclusionDelay))
var err error
newState, err := altair.TranslateParticipation(st, nil)
require.NoError(t, err)
participation, err := newState.PreviousEpochParticipation()
require.NoError(t, err)
require.DeepSSZEqual(t, make([]byte, 64), participation)
aggBits := bitfield.NewBitlist(2)
aggBits.SetBitAt(0, true)
aggBits.SetBitAt(1, true)
r, err := helpers.BlockRootAtSlot(s, 0)
require.NoError(t, err)
var pendingAtts []*ethpb.PendingAttestation
for i := 0; i < 3; i++ {
pendingAtts = append(pendingAtts, &ethpb.PendingAttestation{
Data: &ethpb.AttestationData{
CommitteeIndex: types.CommitteeIndex(i),
BeaconBlockRoot: r,
Source: &ethpb.Checkpoint{Epoch: 0, Root: make([]byte, 32)},
Target: &ethpb.Checkpoint{Epoch: 0, Root: make([]byte, 32)},
},
AggregationBits: aggBits,
InclusionDelay: 1,
})
}
newState, err = altair.TranslateParticipation(newState, pendingAtts)
require.NoError(t, err)
participation, err = newState.PreviousEpochParticipation()
require.NoError(t, err)
require.DeepNotSSZEqual(t, make([]byte, 64), participation)
committee, err := helpers.BeaconCommitteeFromState(st, pendingAtts[0].Data.Slot, pendingAtts[0].Data.CommitteeIndex)
require.NoError(t, err)
indices, err := attestationutil.AttestingIndices(pendingAtts[0].AggregationBits, committee)
require.NoError(t, err)
for _, index := range indices {
require.Equal(t, true, altair.HasValidatorFlag(participation[index], params.BeaconConfig().TimelyHeadFlagIndex))
require.Equal(t, true, altair.HasValidatorFlag(participation[index], params.BeaconConfig().TimelyTargetFlagIndex))
require.Equal(t, true, altair.HasValidatorFlag(participation[index], params.BeaconConfig().TimelySourceFlagIndex))
}
}
func TestUpgradeToAltair(t *testing.T) {
st, _ := testutil.DeterministicGenesisState(t, params.BeaconConfig().MaxValidatorsPerCommittee)
preForkState := st.Copy()
aState, err := altair.UpgradeToAltair(context.Background(), st)
require.NoError(t, err)
_, ok := aState.(state.BeaconStateAltair)
require.Equal(t, true, ok)
require.Equal(t, preForkState.GenesisTime(), aState.GenesisTime())
require.DeepSSZEqual(t, preForkState.GenesisValidatorRoot(), aState.GenesisValidatorRoot())
require.Equal(t, preForkState.Slot(), aState.Slot())
require.DeepSSZEqual(t, preForkState.LatestBlockHeader(), aState.LatestBlockHeader())
require.DeepSSZEqual(t, preForkState.BlockRoots(), aState.BlockRoots())
require.DeepSSZEqual(t, preForkState.StateRoots(), aState.StateRoots())
require.DeepSSZEqual(t, preForkState.HistoricalRoots(), aState.HistoricalRoots())
require.DeepSSZEqual(t, preForkState.Eth1Data(), aState.Eth1Data())
require.DeepSSZEqual(t, preForkState.Eth1DataVotes(), aState.Eth1DataVotes())
require.DeepSSZEqual(t, preForkState.Eth1DepositIndex(), aState.Eth1DepositIndex())
require.DeepSSZEqual(t, preForkState.Validators(), aState.Validators())
require.DeepSSZEqual(t, preForkState.Balances(), aState.Balances())
require.DeepSSZEqual(t, preForkState.RandaoMixes(), aState.RandaoMixes())
require.DeepSSZEqual(t, preForkState.Slashings(), aState.Slashings())
require.DeepSSZEqual(t, preForkState.JustificationBits(), aState.JustificationBits())
require.DeepSSZEqual(t, preForkState.PreviousJustifiedCheckpoint(), aState.PreviousJustifiedCheckpoint())
require.DeepSSZEqual(t, preForkState.CurrentJustifiedCheckpoint(), aState.CurrentJustifiedCheckpoint())
require.DeepSSZEqual(t, preForkState.FinalizedCheckpoint(), aState.FinalizedCheckpoint())
numValidators := aState.NumValidators()
p, err := aState.PreviousEpochParticipation()
require.NoError(t, err)
require.DeepSSZEqual(t, make([]byte, numValidators), p)
p, err = aState.CurrentEpochParticipation()
require.NoError(t, err)
require.DeepSSZEqual(t, make([]byte, numValidators), p)
s, err := aState.InactivityScores()
require.NoError(t, err)
require.DeepSSZEqual(t, make([]uint64, numValidators), s)
f := aState.Fork()
require.DeepSSZEqual(t, &ethpb.Fork{
PreviousVersion: st.Fork().CurrentVersion,
CurrentVersion: params.BeaconConfig().AltairForkVersion,
Epoch: helpers.CurrentEpoch(st),
}, f)
csc, err := aState.CurrentSyncCommittee()
require.NoError(t, err)
nsc, err := aState.NextSyncCommittee()
require.NoError(t, err)
require.DeepSSZEqual(t, nsc, csc)
}

View File

@@ -0,0 +1,87 @@
package altair
import (
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/core/validators"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/shared/params"
)
// SlashValidator with slashed index.
// The function is modified to use MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR and use PROPOSER_WEIGHT when calculating the proposer reward.
//
// def slash_validator(state: BeaconState,
// slashed_index: ValidatorIndex,
// whistleblower_index: ValidatorIndex=None) -> None:
// """
// Slash the validator with index ``slashed_index``.
// """
// epoch = get_current_epoch(state)
// initiate_validator_exit(state, slashed_index)
// validator = state.validators[slashed_index]
// validator.slashed = True
// validator.withdrawable_epoch = max(validator.withdrawable_epoch, Epoch(epoch + EPOCHS_PER_SLASHINGS_VECTOR))
// state.slashings[epoch % EPOCHS_PER_SLASHINGS_VECTOR] += validator.effective_balance
// decrease_balance(state, slashed_index, validator.effective_balance // MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR)
//
// # Apply proposer and whistleblower rewards
// proposer_index = get_beacon_proposer_index(state)
// if whistleblower_index is None:
// whistleblower_index = proposer_index
// whistleblower_reward = Gwei(validator.effective_balance // WHISTLEBLOWER_REWARD_QUOTIENT)
// proposer_reward = Gwei(whistleblower_reward * PROPOSER_WEIGHT // WEIGHT_DENOMINATOR)
// increase_balance(state, proposer_index, proposer_reward)
// increase_balance(state, whistleblower_index, Gwei(whistleblower_reward - proposer_reward))
func SlashValidator(state state.BeaconState, slashedIdx types.ValidatorIndex, penaltyQuotient uint64,
proposerRewardQuotient uint64) (state.BeaconState, error) {
state, err := validators.InitiateValidatorExit(state, slashedIdx)
if err != nil {
return nil, errors.Wrapf(err, "could not initiate validator %d exit", slashedIdx)
}
currentEpoch := helpers.SlotToEpoch(state.Slot())
validator, err := state.ValidatorAtIndex(slashedIdx)
if err != nil {
return nil, err
}
validator.Slashed = true
maxWithdrawableEpoch := types.MaxEpoch(validator.WithdrawableEpoch, currentEpoch+params.BeaconConfig().EpochsPerSlashingsVector)
validator.WithdrawableEpoch = maxWithdrawableEpoch
if err := state.UpdateValidatorAtIndex(slashedIdx, validator); err != nil {
return nil, err
}
// The slashing amount is represented by epochs per slashing vector. The validator's effective balance is then applied to that amount.
slashings := state.Slashings()
currentSlashing := slashings[currentEpoch%params.BeaconConfig().EpochsPerSlashingsVector]
if err := state.UpdateSlashingsAtIndex(
uint64(currentEpoch%params.BeaconConfig().EpochsPerSlashingsVector),
currentSlashing+validator.EffectiveBalance,
); err != nil {
return nil, err
}
if err := helpers.DecreaseBalance(state, slashedIdx, validator.EffectiveBalance/penaltyQuotient); err != nil {
return nil, err
}
proposerIdx, err := helpers.BeaconProposerIndex(state)
if err != nil {
return nil, errors.Wrap(err, "could not get proposer idx")
}
// In this implementation, proposer is the whistleblower.
whistleBlowerIdx := proposerIdx
whistleblowerReward := validator.EffectiveBalance / params.BeaconConfig().WhistleBlowerRewardQuotient
proposerReward := whistleblowerReward * params.BeaconConfig().ProposerWeight / params.BeaconConfig().WeightDenominator
err = helpers.IncreaseBalance(state, proposerIdx, proposerReward)
if err != nil {
return nil, err
}
err = helpers.IncreaseBalance(state, whistleBlowerIdx, whistleblowerReward-proposerReward)
if err != nil {
return nil, err
}
return state, nil
}

View File

@@ -0,0 +1,69 @@
package altair_test
import (
"testing"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core/altair"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state/v2"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
)
func TestSlashValidator_OK(t *testing.T) {
validatorCount := params.BeaconConfig().MinGenesisActiveValidatorCount
registry := make([]*ethpb.Validator, 0, validatorCount)
balances := make([]uint64, 0, validatorCount)
for i := uint64(0); i < validatorCount; i++ {
registry = append(registry, &ethpb.Validator{
ActivationEpoch: 0,
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
})
balances = append(balances, params.BeaconConfig().MaxEffectiveBalance)
}
base := &ethpb.BeaconStateAltair{
Validators: registry,
Slashings: make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector),
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
Balances: balances,
}
state, err := stateAltair.InitializeFromProto(base)
require.NoError(t, err)
slashedIdx := types.ValidatorIndex(2)
proposer, err := helpers.BeaconProposerIndex(state)
require.NoError(t, err, "Could not get proposer")
proposerBal, err := state.BalanceAtIndex(proposer)
require.NoError(t, err)
cfg := params.BeaconConfig()
slashedState, err := altair.SlashValidator(state, slashedIdx, cfg.MinSlashingPenaltyQuotientAltair, cfg.ProposerRewardQuotient)
require.NoError(t, err, "Could not slash validator")
state, ok := slashedState.(*stateAltair.BeaconState)
require.Equal(t, true, ok)
v, err := state.ValidatorAtIndex(slashedIdx)
require.NoError(t, err)
assert.Equal(t, true, v.Slashed, "Validator not slashed despite supposed to being slashed")
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().Mod(uint64(params.BeaconConfig().EpochsPerSlashingsVector))]
assert.Equal(t, maxBalance, slashedBalance, "Slashed balance isnt the expected amount")
whistleblowerReward := slashedBalance / params.BeaconConfig().WhistleBlowerRewardQuotient
bal, err := state.BalanceAtIndex(proposer)
require.NoError(t, err)
// The proposer is the whistleblower in phase 0.
assert.Equal(t, proposerBal+whistleblowerReward, bal, "Did not get expected balance for proposer")
bal, err = state.BalanceAtIndex(slashedIdx)
require.NoError(t, err)
v, err = state.ValidatorAtIndex(slashedIdx)
require.NoError(t, err)
assert.Equal(t, maxBalance-(v.EffectiveBalance/params.BeaconConfig().MinSlashingPenaltyQuotientAltair), bal, "Did not get expected balance for slashed validator")
}

View File

@@ -26,10 +26,9 @@ go_library(
deps = [
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/core/validators:go_default_library",
"//beacon-chain/state/interface:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//proto/eth/v1alpha1:go_default_library",
"//proto/interfaces:go_default_library",
"//beacon-chain/state:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//proto/prysm/v1alpha1/block:go_default_library",
"//shared/attestationutil:go_default_library",
"//shared/bls:go_default_library",
"//shared/bytesutil:go_default_library",
@@ -37,10 +36,12 @@ go_library(
"//shared/depositutil:go_default_library",
"//shared/hashutil:go_default_library",
"//shared/mathutil:go_default_library",
"//shared/p2putils:go_default_library",
"//shared/params:go_default_library",
"//shared/slashutil:go_default_library",
"//shared/sliceutil:go_default_library",
"//shared/trieutil:go_default_library",
"//shared/version:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
@@ -66,6 +67,7 @@ go_test(
"proposer_slashing_regression_test.go",
"proposer_slashing_test.go",
"randao_test.go",
"signature_test.go",
],
data = glob(["testdata/**"]),
embed = [":go_default_library"],
@@ -74,11 +76,10 @@ go_test(
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/core/validators:go_default_library",
"//beacon-chain/p2p/types:go_default_library",
"//beacon-chain/state/interface:go_default_library",
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/v1:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//proto/eth/v1alpha1:go_default_library",
"//proto/eth/v1alpha1/wrapper:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//proto/prysm/v1alpha1/wrapper:go_default_library",
"//shared/aggregation:go_default_library",
"//shared/aggregation/attestations:go_default_library",
"//shared/attestationutil:go_default_library",

View File

@@ -7,85 +7,22 @@ import (
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/interfaces"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
"github.com/prysmaticlabs/prysm/shared/attestationutil"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/params"
"go.opencensus.io/trace"
)
// ProcessAttestations applies processing operations to a block's inner attestation
// records.
func ProcessAttestations(
ctx context.Context,
beaconState iface.BeaconState,
b interfaces.SignedBeaconBlock,
) (iface.BeaconState, error) {
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
return nil, err
}
var err error
for idx, attestation := range b.Block().Body().Attestations() {
beaconState, err = ProcessAttestation(ctx, beaconState, attestation)
if err != nil {
return nil, errors.Wrapf(err, "could not verify attestation at index %d in block", idx)
}
}
return beaconState, nil
}
// ProcessAttestation verifies an input attestation can pass through processing using the given beacon state.
//
// Spec pseudocode definition:
// def process_attestation(state: BeaconState, attestation: Attestation) -> None:
// data = attestation.data
// assert data.target.epoch in (get_previous_epoch(state), get_current_epoch(state))
// assert data.target.epoch == compute_epoch_at_slot(data.slot)
// assert data.slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot <= data.slot + SLOTS_PER_EPOCH
// assert data.index < get_committee_count_per_slot(state, data.target.epoch)
//
// committee = get_beacon_committee(state, data.slot, data.index)
// assert len(attestation.aggregation_bits) == len(committee)
//
// pending_attestation = PendingAttestation(
// data=data,
// aggregation_bits=attestation.aggregation_bits,
// inclusion_delay=state.slot - data.slot,
// proposer_index=get_beacon_proposer_index(state),
// )
//
// if data.target.epoch == get_current_epoch(state):
// assert data.source == state.current_justified_checkpoint
// state.current_epoch_attestations.append(pending_attestation)
// else:
// assert data.source == state.previous_justified_checkpoint
// state.previous_epoch_attestations.append(pending_attestation)
//
// # Verify signature
// assert is_valid_indexed_attestation(state, get_indexed_attestation(state, attestation))
func ProcessAttestation(
ctx context.Context,
beaconState iface.BeaconState,
att *ethpb.Attestation,
) (iface.BeaconState, error) {
beaconState, err := ProcessAttestationNoVerifySignature(ctx, beaconState, att)
if err != nil {
return nil, err
}
return beaconState, VerifyAttestationSignature(ctx, beaconState, att)
}
// ProcessAttestationsNoVerifySignature applies processing operations to a block's inner attestation
// records. The only difference would be that the attestation signature would not be verified.
func ProcessAttestationsNoVerifySignature(
ctx context.Context,
beaconState iface.BeaconState,
b interfaces.SignedBeaconBlock,
) (iface.BeaconState, error) {
beaconState state.BeaconState,
b block.SignedBeaconBlock,
) (state.BeaconState, error) {
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
return nil, err
}
@@ -104,7 +41,7 @@ func ProcessAttestationsNoVerifySignature(
// used before processing attestation with the beacon state.
func VerifyAttestationNoVerifySignature(
ctx context.Context,
beaconState iface.ReadOnlyBeaconState,
beaconState state.ReadOnlyBeaconState,
att *ethpb.Attestation,
) error {
ctx, span := trace.StartSpan(ctx, "core.VerifyAttestationNoVerifySignature")
@@ -188,9 +125,9 @@ func VerifyAttestationNoVerifySignature(
// method is used to validate attestations whose signatures have already been verified.
func ProcessAttestationNoVerifySignature(
ctx context.Context,
beaconState iface.BeaconState,
beaconState state.BeaconState,
att *ethpb.Attestation,
) (iface.BeaconState, error) {
) (state.BeaconState, error) {
ctx, span := trace.StartSpan(ctx, "core.ProcessAttestationNoVerifySignature")
defer span.End()
@@ -205,7 +142,7 @@ func ProcessAttestationNoVerifySignature(
if err != nil {
return nil, err
}
pendingAtt := &pb.PendingAttestation{
pendingAtt := &ethpb.PendingAttestation{
Data: data,
AggregationBits: att.AggregationBits,
InclusionDelay: beaconState.Slot() - s,
@@ -227,7 +164,7 @@ func ProcessAttestationNoVerifySignature(
// VerifyAttestationSignature converts and attestation into an indexed attestation and verifies
// the signature in that attestation.
func VerifyAttestationSignature(ctx context.Context, beaconState iface.ReadOnlyBeaconState, att *ethpb.Attestation) error {
func VerifyAttestationSignature(ctx context.Context, beaconState state.ReadOnlyBeaconState, att *ethpb.Attestation) error {
if err := helpers.ValidateNilAttestation(att); err != nil {
return err
}
@@ -258,7 +195,7 @@ func VerifyAttestationSignature(ctx context.Context, beaconState iface.ReadOnlyB
// domain = get_domain(state, DOMAIN_BEACON_ATTESTER, indexed_attestation.data.target.epoch)
// signing_root = compute_signing_root(indexed_attestation.data, domain)
// return bls.FastAggregateVerify(pubkeys, signing_root, indexed_attestation.signature)
func VerifyIndexedAttestation(ctx context.Context, beaconState iface.ReadOnlyBeaconState, indexedAtt *ethpb.IndexedAttestation) error {
func VerifyIndexedAttestation(ctx context.Context, beaconState state.ReadOnlyBeaconState, indexedAtt *ethpb.IndexedAttestation) error {
ctx, span := trace.StartSpan(ctx, "core.VerifyIndexedAttestation")
defer span.End()

View File

@@ -7,9 +7,8 @@ import (
"github.com/prysmaticlabs/go-bitfield"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
@@ -33,7 +32,7 @@ func TestProcessAttestationNoVerifySignature_BeaconFuzzIssue78(t *testing.T) {
if err != nil {
t.Fatal(err)
}
spb := &pb.BeaconState{}
spb := &ethpb.BeaconState{}
if err := spb.UnmarshalSSZ(stateData); err != nil {
t.Fatal(err)
}
@@ -73,7 +72,7 @@ func TestVerifyAttestationNoVerifySignature_IncorrectSourceEpoch(t *testing.T) {
ckp := beaconState.CurrentJustifiedCheckpoint()
copy(ckp.Root, "hello-world")
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(ckp))
require.NoError(t, beaconState.AppendCurrentEpochAttestations(&pb.PendingAttestation{}))
require.NoError(t, beaconState.AppendCurrentEpochAttestations(&ethpb.PendingAttestation{}))
err = blocks.VerifyAttestationNoVerifySignature(context.TODO(), beaconState, att)
assert.NotEqual(t, nil, err)

View File

@@ -2,17 +2,14 @@ package blocks_test
import (
"context"
"fmt"
"testing"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/go-bitfield"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/eth/v1alpha1/wrapper"
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/aggregation"
attaggregation "github.com/prysmaticlabs/prysm/shared/aggregation/attestations"
"github.com/prysmaticlabs/prysm/shared/attestationutil"
@@ -24,208 +21,6 @@ import (
"github.com/prysmaticlabs/prysm/shared/testutil/require"
)
func TestProcessAttestations_InclusionDelayFailure(t *testing.T) {
attestations := []*ethpb.Attestation{
testutil.HydrateAttestation(&ethpb.Attestation{
Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 0, Root: make([]byte, 32)},
Slot: 5,
},
}),
}
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
Attestations: attestations,
},
}
beaconState, _ := testutil.DeterministicGenesisState(t, 100)
want := fmt.Sprintf(
"attestation slot %d + inclusion delay %d > state slot %d",
attestations[0].Data.Slot,
params.BeaconConfig().MinAttestationInclusionDelay,
beaconState.Slot(),
)
_, err := blocks.ProcessAttestations(context.Background(), beaconState, wrapper.WrappedPhase0SignedBeaconBlock(b))
assert.ErrorContains(t, want, err)
}
func TestProcessAttestations_NeitherCurrentNorPrevEpoch(t *testing.T) {
att := testutil.HydrateAttestation(&ethpb.Attestation{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
Target: &ethpb.Checkpoint{Epoch: 0}}})
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
Attestations: []*ethpb.Attestation{att},
},
}
beaconState, _ := testutil.DeterministicGenesisState(t, 100)
err := beaconState.SetSlot(beaconState.Slot() + params.BeaconConfig().SlotsPerEpoch*4 + params.BeaconConfig().MinAttestationInclusionDelay)
require.NoError(t, err)
pfc := beaconState.PreviousJustifiedCheckpoint()
pfc.Root = []byte("hello-world")
require.NoError(t, beaconState.SetPreviousJustifiedCheckpoint(pfc))
require.NoError(t, beaconState.AppendPreviousEpochAttestations(&pb.PendingAttestation{}))
want := fmt.Sprintf(
"expected target epoch (%d) to be the previous epoch (%d) or the current epoch (%d)",
att.Data.Target.Epoch,
helpers.PrevEpoch(beaconState),
helpers.CurrentEpoch(beaconState),
)
_, err = blocks.ProcessAttestations(context.Background(), beaconState, wrapper.WrappedPhase0SignedBeaconBlock(b))
assert.ErrorContains(t, want, err)
}
func TestProcessAttestations_CurrentEpochFFGDataMismatches(t *testing.T) {
attestations := []*ethpb.Attestation{
{
Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 0, Root: make([]byte, 32)},
Source: &ethpb.Checkpoint{Epoch: 1, Root: make([]byte, 32)},
},
AggregationBits: bitfield.Bitlist{0x09},
},
}
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
Attestations: attestations,
},
}
beaconState, _ := testutil.DeterministicGenesisState(t, 100)
require.NoError(t, beaconState.SetSlot(beaconState.Slot()+params.BeaconConfig().MinAttestationInclusionDelay))
cfc := beaconState.CurrentJustifiedCheckpoint()
cfc.Root = []byte("hello-world")
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(cfc))
require.NoError(t, beaconState.AppendCurrentEpochAttestations(&pb.PendingAttestation{}))
want := "source check point not equal to current justified checkpoint"
_, err := blocks.ProcessAttestations(context.Background(), beaconState, wrapper.WrappedPhase0SignedBeaconBlock(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{}
_, err = blocks.ProcessAttestations(context.Background(), beaconState, wrapper.WrappedPhase0SignedBeaconBlock(b))
assert.ErrorContains(t, want, err)
}
func TestProcessAttestations_PrevEpochFFGDataMismatches(t *testing.T) {
beaconState, _ := testutil.DeterministicGenesisState(t, 100)
aggBits := bitfield.NewBitlist(3)
aggBits.SetBitAt(0, true)
attestations := []*ethpb.Attestation{
{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 1, Root: make([]byte, 32)},
Target: &ethpb.Checkpoint{Epoch: 1, Root: make([]byte, 32)},
Slot: params.BeaconConfig().SlotsPerEpoch,
},
AggregationBits: aggBits,
},
}
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
Attestations: attestations,
},
}
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.AppendPreviousEpochAttestations(&pb.PendingAttestation{}))
want := "source check point not equal to previous justified checkpoint"
_, err = blocks.ProcessAttestations(context.Background(), beaconState, wrapper.WrappedPhase0SignedBeaconBlock(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.PrevEpoch(beaconState)
b.Block.Body.Attestations[0].Data.Source.Root = []byte{}
_, err = blocks.ProcessAttestations(context.Background(), beaconState, wrapper.WrappedPhase0SignedBeaconBlock(b))
assert.ErrorContains(t, want, err)
}
func TestProcessAttestations_InvalidAggregationBitsLength(t *testing.T) {
beaconState, _ := testutil.DeterministicGenesisState(t, 100)
aggBits := bitfield.NewBitlist(4)
att := &ethpb.Attestation{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
Target: &ethpb.Checkpoint{Epoch: 0}},
AggregationBits: aggBits,
}
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
Attestations: []*ethpb.Attestation{att},
},
}
err := beaconState.SetSlot(beaconState.Slot() + params.BeaconConfig().MinAttestationInclusionDelay)
require.NoError(t, err)
cfc := beaconState.CurrentJustifiedCheckpoint()
cfc.Root = []byte("hello-world")
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(cfc))
require.NoError(t, beaconState.AppendCurrentEpochAttestations(&pb.PendingAttestation{}))
expected := "failed to verify aggregation bitfield: wanted participants bitfield length 3, got: 4"
_, err = blocks.ProcessAttestations(context.Background(), beaconState, wrapper.WrappedPhase0SignedBeaconBlock(b))
assert.ErrorContains(t, expected, err)
}
func TestProcessAttestations_OK(t *testing.T) {
beaconState, privKeys := testutil.DeterministicGenesisState(t, 100)
aggBits := bitfield.NewBitlist(3)
aggBits.SetBitAt(0, true)
var mockRoot [32]byte
copy(mockRoot[:], "hello-world")
att := testutil.HydrateAttestation(&ethpb.Attestation{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Root: mockRoot[:]},
Target: &ethpb.Checkpoint{Root: mockRoot[:]},
},
AggregationBits: aggBits,
})
cfc := beaconState.CurrentJustifiedCheckpoint()
cfc.Root = mockRoot[:]
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(cfc))
require.NoError(t, beaconState.AppendCurrentEpochAttestations(&pb.PendingAttestation{}))
committee, err := helpers.BeaconCommitteeFromState(beaconState, att.Data.Slot, att.Data.CommitteeIndex)
require.NoError(t, err)
attestingIndices, err := attestationutil.AttestingIndices(att.AggregationBits, committee)
require.NoError(t, err)
sigs := make([]bls.Signature, len(attestingIndices))
for i, indice := range attestingIndices {
sb, err := helpers.ComputeDomainAndSign(beaconState, 0, att.Data, params.BeaconConfig().DomainBeaconAttester, privKeys[indice])
require.NoError(t, err)
sig, err := bls.SignatureFromBytes(sb)
require.NoError(t, err)
sigs[i] = sig
}
att.Signature = bls.AggregateSignatures(sigs).Marshal()
block := testutil.NewBeaconBlock()
block.Block.Body.Attestations = []*ethpb.Attestation{att}
err = beaconState.SetSlot(beaconState.Slot() + params.BeaconConfig().MinAttestationInclusionDelay)
require.NoError(t, err)
_, err = blocks.ProcessAttestations(context.Background(), beaconState, wrapper.WrappedPhase0SignedBeaconBlock(block))
assert.NoError(t, err)
}
func TestProcessAggregatedAttestation_OverlappingBits(t *testing.T) {
beaconState, privKeys := testutil.DeterministicGenesisState(t, 100)
data := testutil.HydrateAttestationData(&ethpb.AttestationData{
@@ -243,7 +38,7 @@ func TestProcessAggregatedAttestation_OverlappingBits(t *testing.T) {
cfc := beaconState.CurrentJustifiedCheckpoint()
cfc.Root = bytesutil.PadTo([]byte("hello-world"), 32)
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(cfc))
require.NoError(t, beaconState.AppendCurrentEpochAttestations(&pb.PendingAttestation{}))
require.NoError(t, beaconState.AppendCurrentEpochAttestations(&ethpb.PendingAttestation{}))
committee, err := helpers.BeaconCommitteeFromState(beaconState, att1.Data.Slot, att1.Data.CommitteeIndex)
require.NoError(t, err)
@@ -285,78 +80,6 @@ func TestProcessAggregatedAttestation_OverlappingBits(t *testing.T) {
assert.ErrorContains(t, aggregation.ErrBitsOverlap.Error(), err)
}
func TestProcessAggregatedAttestation_NoOverlappingBits(t *testing.T) {
beaconState, privKeys := testutil.DeterministicGenesisState(t, 300)
var mockRoot [32]byte
copy(mockRoot[:], "hello-world")
data := testutil.HydrateAttestationData(&ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0, Root: mockRoot[:]},
Target: &ethpb.Checkpoint{Epoch: 0, Root: mockRoot[:]},
})
aggBits1 := bitfield.NewBitlist(9)
aggBits1.SetBitAt(0, true)
aggBits1.SetBitAt(1, true)
att1 := &ethpb.Attestation{
Data: data,
AggregationBits: aggBits1,
Signature: make([]byte, 32),
}
cfc := beaconState.CurrentJustifiedCheckpoint()
cfc.Root = mockRoot[:]
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(cfc))
require.NoError(t, beaconState.AppendCurrentEpochAttestations(&pb.PendingAttestation{}))
committee, err := helpers.BeaconCommitteeFromState(beaconState, att1.Data.Slot, att1.Data.CommitteeIndex)
require.NoError(t, err)
attestingIndices1, err := attestationutil.AttestingIndices(att1.AggregationBits, committee)
require.NoError(t, err)
sigs := make([]bls.Signature, len(attestingIndices1))
for i, indice := range attestingIndices1 {
sb, err := helpers.ComputeDomainAndSign(beaconState, 0, data, params.BeaconConfig().DomainBeaconAttester, privKeys[indice])
require.NoError(t, err)
sig, err := bls.SignatureFromBytes(sb)
require.NoError(t, err)
sigs[i] = sig
}
att1.Signature = bls.AggregateSignatures(sigs).Marshal()
aggBits2 := bitfield.NewBitlist(9)
aggBits2.SetBitAt(2, true)
aggBits2.SetBitAt(3, true)
att2 := &ethpb.Attestation{
Data: data,
AggregationBits: aggBits2,
Signature: make([]byte, 32),
}
committee, err = helpers.BeaconCommitteeFromState(beaconState, att2.Data.Slot, att2.Data.CommitteeIndex)
require.NoError(t, err)
attestingIndices2, err := attestationutil.AttestingIndices(att2.AggregationBits, committee)
require.NoError(t, err)
sigs = make([]bls.Signature, len(attestingIndices2))
for i, indice := range attestingIndices2 {
sb, err := helpers.ComputeDomainAndSign(beaconState, 0, att2.Data, params.BeaconConfig().DomainBeaconAttester, privKeys[indice])
require.NoError(t, err)
sig, err := bls.SignatureFromBytes(sb)
require.NoError(t, err)
sigs[i] = sig
}
att2.Signature = bls.AggregateSignatures(sigs).Marshal()
aggregatedAtt, err := attaggregation.AggregatePair(att1, att2)
require.NoError(t, err)
block := testutil.NewBeaconBlock()
block.Block.Body.Attestations = []*ethpb.Attestation{aggregatedAtt}
err = beaconState.SetSlot(beaconState.Slot() + params.BeaconConfig().MinAttestationInclusionDelay)
require.NoError(t, err)
_, err = blocks.ProcessAttestations(context.Background(), beaconState, wrapper.WrappedPhase0SignedBeaconBlock(block))
assert.NoError(t, err)
}
func TestVerifyAttestationNoVerifySignature_IncorrectSlotTargetEpoch(t *testing.T) {
beaconState, _ := testutil.DeterministicGenesisState(t, 1)
@@ -396,7 +119,7 @@ func TestProcessAttestationsNoVerify_OK(t *testing.T) {
ckp := beaconState.CurrentJustifiedCheckpoint()
copy(ckp.Root, "hello-world")
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(ckp))
require.NoError(t, beaconState.AppendCurrentEpochAttestations(&pb.PendingAttestation{}))
require.NoError(t, beaconState.AppendCurrentEpochAttestations(&ethpb.PendingAttestation{}))
_, err = blocks.ProcessAttestationNoVerifySignature(context.TODO(), beaconState, att)
assert.NoError(t, err)
@@ -427,7 +150,7 @@ func TestVerifyAttestationNoVerifySignature_OK(t *testing.T) {
ckp := beaconState.CurrentJustifiedCheckpoint()
copy(ckp.Root, "hello-world")
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(ckp))
require.NoError(t, beaconState.AppendCurrentEpochAttestations(&pb.PendingAttestation{}))
require.NoError(t, beaconState.AppendCurrentEpochAttestations(&ethpb.PendingAttestation{}))
err = blocks.VerifyAttestationNoVerifySignature(context.TODO(), beaconState, att)
assert.NoError(t, err)
@@ -453,7 +176,7 @@ func TestVerifyAttestationNoVerifySignature_BadAttIdx(t *testing.T) {
ckp := beaconState.CurrentJustifiedCheckpoint()
copy(ckp.Root, "hello-world")
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(ckp))
require.NoError(t, beaconState.AppendCurrentEpochAttestations(&pb.PendingAttestation{}))
require.NoError(t, beaconState.AppendCurrentEpochAttestations(&ethpb.PendingAttestation{}))
err := blocks.VerifyAttestationNoVerifySignature(context.TODO(), beaconState, att)
require.ErrorContains(t, "committee index 100 >= committee count 1", err)
}
@@ -467,7 +190,7 @@ func TestConvertToIndexed_OK(t *testing.T) {
}
}
state, err := v1.InitializeFromProto(&pb.BeaconState{
state, err := v1.InitializeFromProto(&ethpb.BeaconState{
Slot: 5,
Validators: validators,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
@@ -525,10 +248,10 @@ func TestVerifyIndexedAttestation_OK(t *testing.T) {
}
}
state, err := v1.InitializeFromProto(&pb.BeaconState{
state, err := v1.InitializeFromProto(&ethpb.BeaconState{
Slot: 5,
Validators: validators,
Fork: &pb.Fork{
Fork: &ethpb.Fork{
Epoch: 0,
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
@@ -676,7 +399,7 @@ func TestVerifyAttestations_HandlesPlannedFork(t *testing.T) {
require.NoError(t, err)
require.NoError(t, st.SetSlot(35))
require.NoError(t, st.SetValidators(validators))
require.NoError(t, st.SetFork(&pb.Fork{
require.NoError(t, st.SetFork(&ethpb.Fork{
Epoch: 1,
CurrentVersion: []byte{0, 1, 2, 3},
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
@@ -803,7 +526,7 @@ func TestRetrieveAttestationSignatureSet_AcrossFork(t *testing.T) {
require.NoError(t, err)
require.NoError(t, st.SetSlot(5))
require.NoError(t, st.SetValidators(validators))
require.NoError(t, st.SetFork(&pb.Fork{Epoch: 1, CurrentVersion: []byte{0, 1, 2, 3}, PreviousVersion: []byte{0, 1, 1, 1}}))
require.NoError(t, st.SetFork(&ethpb.Fork{Epoch: 1, CurrentVersion: []byte{0, 1, 2, 3}, PreviousVersion: []byte{0, 1, 1, 1}}))
comm1, err := helpers.BeaconCommitteeFromState(st, 1 /*slot*/, 0 /*committeeIndex*/)
require.NoError(t, err)

View File

@@ -7,11 +7,13 @@ import (
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/attestationutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/slashutil"
"github.com/prysmaticlabs/prysm/shared/sliceutil"
"github.com/prysmaticlabs/prysm/shared/version"
)
// ProcessAttesterSlashings is one of the operations performed
@@ -35,10 +37,10 @@ import (
// assert slashed_any
func ProcessAttesterSlashings(
ctx context.Context,
beaconState iface.BeaconState,
beaconState state.BeaconState,
slashings []*ethpb.AttesterSlashing,
slashFunc slashValidatorFunc,
) (iface.BeaconState, error) {
) (state.BeaconState, error) {
for idx, slashing := range slashings {
if err := VerifyAttesterSlashing(ctx, beaconState, slashing); err != nil {
return nil, errors.Wrapf(err, "could not verify attester slashing %d", idx)
@@ -50,14 +52,19 @@ func ProcessAttesterSlashings(
currentEpoch := helpers.SlotToEpoch(beaconState.Slot())
var err error
var slashedAny bool
var val iface.ReadOnlyValidator
var val state.ReadOnlyValidator
for _, validatorIndex := range slashableIndices {
val, err = beaconState.ValidatorAtIndexReadOnly(types.ValidatorIndex(validatorIndex))
if err != nil {
return nil, err
}
if helpers.IsSlashableValidator(val.ActivationEpoch(), val.WithdrawableEpoch(), val.Slashed(), currentEpoch) {
beaconState, err = slashFunc(beaconState, types.ValidatorIndex(validatorIndex))
cfg := params.BeaconConfig()
slashingQuotient := cfg.MinSlashingPenaltyQuotient
if beaconState.Version() == version.Altair {
slashingQuotient = cfg.MinSlashingPenaltyQuotientAltair
}
beaconState, err = slashFunc(beaconState, types.ValidatorIndex(validatorIndex), slashingQuotient, cfg.ProposerRewardQuotient)
if err != nil {
return nil, errors.Wrapf(err, "could not slash validator index %d",
validatorIndex)
@@ -73,7 +80,7 @@ func ProcessAttesterSlashings(
}
// VerifyAttesterSlashing validates the attestation data in both attestations in the slashing object.
func VerifyAttesterSlashing(ctx context.Context, beaconState iface.ReadOnlyBeaconState, slashing *ethpb.AttesterSlashing) error {
func VerifyAttesterSlashing(ctx context.Context, beaconState state.ReadOnlyBeaconState, slashing *ethpb.AttesterSlashing) error {
if slashing == nil {
return errors.New("nil slashing")
}

View File

@@ -8,9 +8,8 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
v "github.com/prysmaticlabs/prysm/beacon-chain/core/validators"
"github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
@@ -47,7 +46,7 @@ func TestProcessAttesterSlashings_DataNotSlashable(t *testing.T) {
var registry []*ethpb.Validator
currentSlot := types.Slot(0)
beaconState, err := v1.InitializeFromProto(&pb.BeaconState{
beaconState, err := v1.InitializeFromProto(&ethpb.BeaconState{
Validators: registry,
Slot: currentSlot,
})
@@ -66,7 +65,7 @@ func TestProcessAttesterSlashings_IndexedAttestationFailedToVerify(t *testing.T)
var registry []*ethpb.Validator
currentSlot := types.Slot(0)
beaconState, err := v1.InitializeFromProto(&pb.BeaconState{
beaconState, err := v1.InitializeFromProto(&ethpb.BeaconState{
Validators: registry,
Slot: currentSlot,
})

View File

@@ -7,10 +7,10 @@ import (
fuzz "github.com/google/gofuzz"
types "github.com/prysmaticlabs/eth2-types"
v "github.com/prysmaticlabs/prysm/beacon-chain/core/validators"
"github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
eth "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/eth/v1alpha1/wrapper"
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
eth "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
)
@@ -18,7 +18,7 @@ import (
func TestFuzzProcessAttestationNoVerify_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
ctx := context.Background()
state := &pb.BeaconState{}
state := &ethpb.BeaconState{}
att := &eth.Attestation{}
for i := 0; i < 10000; i++ {
@@ -33,7 +33,7 @@ func TestFuzzProcessAttestationNoVerify_10000(t *testing.T) {
func TestFuzzProcessBlockHeader_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &pb.BeaconState{}
state := &ethpb.BeaconState{}
block := &eth.SignedBeaconBlock{}
for i := 0; i < 10000; i++ {
@@ -105,7 +105,7 @@ func TestFuzzEth1DataHasEnoughSupport_10000(t *testing.T) {
for i := 0; i < 100000; i++ {
fuzzer.Fuzz(eth1data)
fuzzer.Fuzz(&stateVotes)
s, err := v1.InitializeFromProto(&pb.BeaconState{
s, err := v1.InitializeFromProto(&ethpb.BeaconState{
Eth1DataVotes: stateVotes,
})
require.NoError(t, err)
@@ -117,7 +117,7 @@ func TestFuzzEth1DataHasEnoughSupport_10000(t *testing.T) {
func TestFuzzProcessBlockHeaderNoVerify_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &pb.BeaconState{}
state := &ethpb.BeaconState{}
block := &eth.BeaconBlock{}
for i := 0; i < 10000; i++ {
@@ -132,7 +132,7 @@ func TestFuzzProcessBlockHeaderNoVerify_10000(t *testing.T) {
func TestFuzzProcessRandao_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &pb.BeaconState{}
state := &ethpb.BeaconState{}
b := &eth.SignedBeaconBlock{}
for i := 0; i < 10000; i++ {
@@ -149,7 +149,7 @@ func TestFuzzProcessRandao_10000(t *testing.T) {
func TestFuzzProcessRandaoNoVerify_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &pb.BeaconState{}
state := &ethpb.BeaconState{}
blockBody := &eth.BeaconBlockBody{}
for i := 0; i < 10000; i++ {
@@ -166,7 +166,7 @@ func TestFuzzProcessRandaoNoVerify_10000(t *testing.T) {
func TestFuzzProcessProposerSlashings_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &pb.BeaconState{}
state := &ethpb.BeaconState{}
p := &eth.ProposerSlashing{}
ctx := context.Background()
for i := 0; i < 10000; i++ {
@@ -183,7 +183,7 @@ func TestFuzzProcessProposerSlashings_10000(t *testing.T) {
func TestFuzzVerifyProposerSlashing_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &pb.BeaconState{}
state := &ethpb.BeaconState{}
proposerSlashing := &eth.ProposerSlashing{}
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
@@ -197,7 +197,7 @@ func TestFuzzVerifyProposerSlashing_10000(t *testing.T) {
func TestFuzzProcessAttesterSlashings_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &pb.BeaconState{}
state := &ethpb.BeaconState{}
a := &eth.AttesterSlashing{}
ctx := context.Background()
for i := 0; i < 10000; i++ {
@@ -214,7 +214,7 @@ func TestFuzzProcessAttesterSlashings_10000(t *testing.T) {
func TestFuzzVerifyAttesterSlashing_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &pb.BeaconState{}
state := &ethpb.BeaconState{}
attesterSlashing := &eth.AttesterSlashing{}
ctx := context.Background()
for i := 0; i < 10000; i++ {
@@ -249,26 +249,9 @@ func TestFuzzslashableAttesterIndices_10000(t *testing.T) {
}
}
func TestFuzzProcessAttestations_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &pb.BeaconState{}
b := &eth.SignedBeaconBlock{}
ctx := context.Background()
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(b)
s, err := v1.InitializeFromProtoUnsafe(state)
require.NoError(t, err)
r, err := ProcessAttestations(ctx, s, wrapper.WrappedPhase0SignedBeaconBlock(b))
if err != nil && r != nil {
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, b)
}
}
}
func TestFuzzProcessAttestationsNoVerify_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &pb.BeaconState{}
state := &ethpb.BeaconState{}
b := &eth.SignedBeaconBlock{}
ctx := context.Background()
for i := 0; i < 10000; i++ {
@@ -283,26 +266,9 @@ func TestFuzzProcessAttestationsNoVerify_10000(t *testing.T) {
}
}
func TestFuzzProcessAttestation_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &pb.BeaconState{}
attestation := &eth.Attestation{}
ctx := context.Background()
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(attestation)
s, err := v1.InitializeFromProtoUnsafe(state)
require.NoError(t, err)
r, err := ProcessAttestation(ctx, s, attestation)
if err != nil && r != nil {
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, attestation)
}
}
}
func TestFuzzVerifyIndexedAttestationn_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &pb.BeaconState{}
state := &ethpb.BeaconState{}
idxAttestation := &eth.IndexedAttestation{}
ctx := context.Background()
for i := 0; i < 10000; i++ {
@@ -317,7 +283,7 @@ func TestFuzzVerifyIndexedAttestationn_10000(t *testing.T) {
func TestFuzzVerifyAttestation_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &pb.BeaconState{}
state := &ethpb.BeaconState{}
attestation := &eth.Attestation{}
ctx := context.Background()
for i := 0; i < 10000; i++ {
@@ -332,7 +298,7 @@ func TestFuzzVerifyAttestation_10000(t *testing.T) {
func TestFuzzProcessDeposits_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &pb.BeaconState{}
state := &ethpb.BeaconState{}
deposits := make([]*eth.Deposit, 100)
ctx := context.Background()
for i := 0; i < 10000; i++ {
@@ -351,7 +317,7 @@ func TestFuzzProcessDeposits_10000(t *testing.T) {
func TestFuzzProcessPreGenesisDeposit_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &pb.BeaconState{}
state := &ethpb.BeaconState{}
deposit := &eth.Deposit{}
ctx := context.Background()
@@ -369,7 +335,7 @@ func TestFuzzProcessPreGenesisDeposit_10000(t *testing.T) {
func TestFuzzProcessDeposit_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &pb.BeaconState{}
state := &ethpb.BeaconState{}
deposit := &eth.Deposit{}
for i := 0; i < 10000; i++ {
@@ -377,7 +343,7 @@ func TestFuzzProcessDeposit_10000(t *testing.T) {
fuzzer.Fuzz(deposit)
s, err := v1.InitializeFromProtoUnsafe(state)
require.NoError(t, err)
r, err := ProcessDeposit(s, deposit, true)
r, _, err := ProcessDeposit(s, deposit, true)
if err != nil && r != nil {
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, deposit)
}
@@ -386,7 +352,7 @@ func TestFuzzProcessDeposit_10000(t *testing.T) {
func TestFuzzverifyDeposit_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &pb.BeaconState{}
state := &ethpb.BeaconState{}
deposit := &eth.Deposit{}
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
@@ -400,7 +366,7 @@ func TestFuzzverifyDeposit_10000(t *testing.T) {
func TestFuzzProcessVoluntaryExits_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &pb.BeaconState{}
state := &ethpb.BeaconState{}
e := &eth.SignedVoluntaryExit{}
ctx := context.Background()
for i := 0; i < 10000; i++ {
@@ -417,7 +383,7 @@ func TestFuzzProcessVoluntaryExits_10000(t *testing.T) {
func TestFuzzProcessVoluntaryExitsNoVerify_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &pb.BeaconState{}
state := &ethpb.BeaconState{}
e := &eth.SignedVoluntaryExit{}
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
@@ -434,13 +400,14 @@ func TestFuzzProcessVoluntaryExitsNoVerify_10000(t *testing.T) {
func TestFuzzVerifyExit_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
ve := &eth.SignedVoluntaryExit{}
val := v1.ReadOnlyValidator{}
fork := &pb.Fork{}
val, err := v1.NewValidator(&ethpb.Validator{})
_ = err
fork := &ethpb.Fork{}
var slot types.Slot
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(ve)
fuzzer.Fuzz(&val)
fuzzer.Fuzz(val)
fuzzer.Fuzz(fork)
fuzzer.Fuzz(&slot)
err := VerifyExitAndSignature(val, slot, fork, ve, params.BeaconConfig().ZeroHash[:])

View File

@@ -8,7 +8,7 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
v "github.com/prysmaticlabs/prysm/beacon-chain/core/validators"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"

View File

@@ -6,9 +6,8 @@ import (
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/depositutil"
@@ -20,9 +19,9 @@ import (
// ProcessPreGenesisDeposits processes a deposit for the beacon state before chainstart.
func ProcessPreGenesisDeposits(
ctx context.Context,
beaconState iface.BeaconState,
beaconState state.BeaconState,
deposits []*ethpb.Deposit,
) (iface.BeaconState, error) {
) (state.BeaconState, error) {
var err error
beaconState, err = ProcessDeposits(ctx, beaconState, deposits)
if err != nil {
@@ -36,7 +35,7 @@ func ProcessPreGenesisDeposits(
}
// ActivateValidatorWithEffectiveBalance updates validator's effective balance, and if it's above MaxEffectiveBalance, validator becomes active in genesis.
func ActivateValidatorWithEffectiveBalance(beaconState iface.BeaconState, deposits []*ethpb.Deposit) (iface.BeaconState, error) {
func ActivateValidatorWithEffectiveBalance(beaconState state.BeaconState, deposits []*ethpb.Deposit) (state.BeaconState, error) {
for _, deposit := range deposits {
pubkey := deposit.Data.PublicKey
index, ok := beaconState.ValidatorIndexByPubkey(bytesutil.ToBytes48(pubkey))
@@ -75,9 +74,9 @@ func ActivateValidatorWithEffectiveBalance(beaconState iface.BeaconState, deposi
// process_deposit(state, deposit)
func ProcessDeposits(
ctx context.Context,
beaconState iface.BeaconState,
beaconState state.BeaconState,
deposits []*ethpb.Deposit,
) (iface.BeaconState, error) {
) (state.BeaconState, error) {
// Attempt to verify all deposit signatures at once, if this fails then fall back to processing
// individual deposits with signature verification enabled.
batchVerified, err := BatchVerifyDepositsSignatures(ctx, deposits)
@@ -89,7 +88,7 @@ func ProcessDeposits(
if deposit == nil || deposit.Data == nil {
return nil, errors.New("got a nil deposit in block")
}
beaconState, err = ProcessDeposit(beaconState, deposit, batchVerified)
beaconState, _, err = ProcessDeposit(beaconState, deposit, batchVerified)
if err != nil {
return nil, errors.Wrapf(err, "could not process deposit from %#x", bytesutil.Trunc(deposit.Data.PublicKey))
}
@@ -115,6 +114,8 @@ func BatchVerifyDepositsSignatures(ctx context.Context, deposits []*ethpb.Deposi
// ProcessDeposit takes in a deposit object and inserts it
// into the registry as a new validator or balance change.
// Returns the resulting state, a boolean to indicate whether or not the deposit
// resulted in a new validator entry into the beacon state, and any error.
//
// Spec pseudocode definition:
// def process_deposit(state: BeaconState, deposit: Deposit) -> None:
@@ -152,15 +153,16 @@ func BatchVerifyDepositsSignatures(ctx context.Context, deposits []*ethpb.Deposi
// # Increase balance by deposit amount
// index = ValidatorIndex(validator_pubkeys.index(pubkey))
// increase_balance(state, index, amount)
func ProcessDeposit(beaconState iface.BeaconState, deposit *ethpb.Deposit, verifySignature bool) (iface.BeaconState, error) {
func ProcessDeposit(beaconState state.BeaconState, deposit *ethpb.Deposit, verifySignature bool) (state.BeaconState, bool, error) {
var newValidator bool
if err := verifyDeposit(beaconState, deposit); err != nil {
if deposit == nil || deposit.Data == nil {
return nil, err
return nil, newValidator, err
}
return nil, errors.Wrapf(err, "could not verify deposit from %#x", bytesutil.Trunc(deposit.Data.PublicKey))
return nil, newValidator, errors.Wrapf(err, "could not verify deposit from %#x", bytesutil.Trunc(deposit.Data.PublicKey))
}
if err := beaconState.SetEth1DepositIndex(beaconState.Eth1DepositIndex() + 1); err != nil {
return nil, err
return nil, newValidator, err
}
pubKey := deposit.Data.PublicKey
amount := deposit.Data.Amount
@@ -169,12 +171,12 @@ func ProcessDeposit(beaconState iface.BeaconState, deposit *ethpb.Deposit, verif
if verifySignature {
domain, err := helpers.ComputeDomain(params.BeaconConfig().DomainDeposit, nil, nil)
if err != nil {
return nil, err
return nil, newValidator, err
}
if err := verifyDepositDataSigningRoot(deposit.Data, domain); err != nil {
// Ignore this error as in the spec pseudo code.
log.Debugf("Skipping deposit: could not verify deposit data signature: %v", err)
return beaconState, nil
return beaconState, newValidator, nil
}
}
@@ -191,19 +193,20 @@ func ProcessDeposit(beaconState iface.BeaconState, deposit *ethpb.Deposit, verif
WithdrawableEpoch: params.BeaconConfig().FarFutureEpoch,
EffectiveBalance: effectiveBalance,
}); err != nil {
return nil, err
return nil, newValidator, err
}
newValidator = true
if err := beaconState.AppendBalance(amount); err != nil {
return nil, err
return nil, newValidator, err
}
} else if err := helpers.IncreaseBalance(beaconState, index, amount); err != nil {
return nil, err
return nil, newValidator, err
}
return beaconState, nil
return beaconState, newValidator, nil
}
func verifyDeposit(beaconState iface.ReadOnlyBeaconState, deposit *ethpb.Deposit) error {
func verifyDeposit(beaconState state.ReadOnlyBeaconState, deposit *ethpb.Deposit) error {
// Verify Merkle proof of deposit and deposit trie root.
if deposit == nil || deposit.Data == nil {
return errors.New("received nil deposit or nil deposit data")
@@ -258,7 +261,7 @@ func verifyDepositDataWithDomain(ctx context.Context, deps []*ethpb.Deposit, dom
}
pks[i] = dpk
sigs[i] = dep.Data.Signature
depositMessage := &pb.DepositMessage{
depositMessage := &ethpb.DepositMessage{
PublicKey: dep.Data.PublicKey,
WithdrawalCredentials: dep.Data.WithdrawalCredentials,
Amount: dep.Data.Amount,

View File

@@ -7,9 +7,8 @@ import (
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
@@ -40,11 +39,11 @@ func TestProcessDeposits_SameValidatorMultipleDepositsSameBlock(t *testing.T) {
},
}
balances := []uint64{0}
beaconState, err := v1.InitializeFromProto(&pb.BeaconState{
beaconState, err := v1.InitializeFromProto(&ethpb.BeaconState{
Validators: registry,
Balances: balances,
Eth1Data: eth1Data,
Fork: &pb.Fork{
Fork: &ethpb.Fork{
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
},
@@ -80,7 +79,7 @@ func TestProcessDeposits_MerkleBranchFailsVerification(t *testing.T) {
Deposits: []*ethpb.Deposit{deposit},
},
}
beaconState, err := v1.InitializeFromProto(&pb.BeaconState{
beaconState, err := v1.InitializeFromProto(&ethpb.BeaconState{
Eth1Data: &ethpb.Eth1Data{
DepositRoot: []byte{0},
BlockHash: []byte{1},
@@ -111,11 +110,11 @@ func TestProcessDeposits_AddsNewValidatorDeposit(t *testing.T) {
},
}
balances := []uint64{0}
beaconState, err := v1.InitializeFromProto(&pb.BeaconState{
beaconState, err := v1.InitializeFromProto(&ethpb.BeaconState{
Validators: registry,
Balances: balances,
Eth1Data: eth1Data,
Fork: &pb.Fork{
Fork: &ethpb.Fork{
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
},
@@ -174,7 +173,7 @@ func TestProcessDeposits_RepeatedDeposit_IncreasesValidatorBalance(t *testing.T)
}
balances := []uint64{0, 50}
root := depositTrie.Root()
beaconState, err := v1.InitializeFromProto(&pb.BeaconState{
beaconState, err := v1.InitializeFromProto(&ethpb.BeaconState{
Validators: registry,
Balances: balances,
Eth1Data: &ethpb.Eth1Data{
@@ -202,18 +201,19 @@ func TestProcessDeposit_AddsNewValidatorDeposit(t *testing.T) {
},
}
balances := []uint64{0}
beaconState, err := v1.InitializeFromProto(&pb.BeaconState{
beaconState, err := v1.InitializeFromProto(&ethpb.BeaconState{
Validators: registry,
Balances: balances,
Eth1Data: eth1Data,
Fork: &pb.Fork{
Fork: &ethpb.Fork{
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
},
})
require.NoError(t, err)
newState, err := blocks.ProcessDeposit(beaconState, dep[0], true)
newState, isNewValidator, err := blocks.ProcessDeposit(beaconState, dep[0], true)
require.NoError(t, err, "Process deposit failed")
assert.Equal(t, true, isNewValidator, "Expected isNewValidator to be true")
assert.Equal(t, 2, len(newState.Validators()), "Expected validator list to have length 2")
assert.Equal(t, 2, len(newState.Balances()), "Expected validator balances list to have length 2")
if newState.Balances()[1] != dep[0].Data.Amount {
@@ -244,18 +244,19 @@ func TestProcessDeposit_SkipsInvalidDeposit(t *testing.T) {
},
}
balances := []uint64{0}
beaconState, err := v1.InitializeFromProto(&pb.BeaconState{
beaconState, err := v1.InitializeFromProto(&ethpb.BeaconState{
Validators: registry,
Balances: balances,
Eth1Data: eth1Data,
Fork: &pb.Fork{
Fork: &ethpb.Fork{
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
},
})
require.NoError(t, err)
newState, err := blocks.ProcessDeposit(beaconState, dep[0], true)
newState, isNewValidator, err := blocks.ProcessDeposit(beaconState, dep[0], true)
require.NoError(t, err, "Expected invalid block deposit to be ignored without error")
assert.Equal(t, false, isNewValidator, "Expected isNewValidator to be false")
if newState.Eth1DepositIndex() != 1 {
t.Errorf(
@@ -299,11 +300,11 @@ func TestPreGenesisDeposits_SkipInvalidDeposit(t *testing.T) {
},
}
balances := []uint64{0}
beaconState, err := v1.InitializeFromProto(&pb.BeaconState{
beaconState, err := v1.InitializeFromProto(&ethpb.BeaconState{
Validators: registry,
Balances: balances,
Eth1Data: eth1Data,
Fork: &pb.Fork{
Fork: &ethpb.Fork{
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
},
@@ -338,3 +339,54 @@ func TestPreGenesisDeposits_SkipInvalidDeposit(t *testing.T) {
t.Errorf("Expected validator balance at index 0 to stay 0, received: %v", newState.Balances()[0])
}
}
func TestProcessDeposit_RepeatedDeposit_IncreasesValidatorBalance(t *testing.T) {
sk, err := bls.RandKey()
require.NoError(t, err)
deposit := &ethpb.Deposit{
Data: &ethpb.Deposit_Data{
PublicKey: sk.PublicKey().Marshal(),
Amount: 1000,
WithdrawalCredentials: make([]byte, 32),
Signature: make([]byte, 96),
},
}
sr, err := helpers.ComputeSigningRoot(deposit.Data, bytesutil.ToBytes(3, 32))
require.NoError(t, err)
sig := sk.Sign(sr[:])
deposit.Data.Signature = sig.Marshal()
leaf, err := deposit.Data.HashTreeRoot()
require.NoError(t, err)
// We then create a merkle branch for the test.
depositTrie, err := trieutil.GenerateTrieFromItems([][]byte{leaf[:]}, params.BeaconConfig().DepositContractTreeDepth)
require.NoError(t, err, "Could not generate trie")
proof, err := depositTrie.MerkleProof(0)
require.NoError(t, err, "Could not generate proof")
deposit.Proof = proof
registry := []*ethpb.Validator{
{
PublicKey: []byte{1, 2, 3},
},
{
PublicKey: sk.PublicKey().Marshal(),
WithdrawalCredentials: []byte{1},
},
}
balances := []uint64{0, 50}
root := depositTrie.Root()
beaconState, err := v1.InitializeFromProto(&ethpb.BeaconState{
Validators: registry,
Balances: balances,
Eth1Data: &ethpb.Eth1Data{
DepositRoot: root[:],
BlockHash: root[:],
},
})
require.NoError(t, err)
newState, isNewValidator, err := blocks.ProcessDeposit(beaconState, deposit, true /*verifySignature*/)
require.NoError(t, err, "Process deposit failed")
assert.Equal(t, false, isNewValidator, "Expected isNewValidator to be false")
assert.Equal(t, uint64(1000+50), newState.Balances()[1], "Expected balance at index 1 to be 1050")
}

View File

@@ -5,8 +5,8 @@ import (
"context"
"errors"
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/copyutil"
"github.com/prysmaticlabs/prysm/shared/params"
)
@@ -20,7 +20,7 @@ import (
// state.eth1_data_votes.append(body.eth1_data)
// if state.eth1_data_votes.count(body.eth1_data) * 2 > EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH:
// state.eth1_data = body.eth1_data
func ProcessEth1DataInBlock(_ context.Context, beaconState iface.BeaconState, eth1Data *ethpb.Eth1Data) (iface.BeaconState, error) {
func ProcessEth1DataInBlock(_ context.Context, beaconState state.BeaconState, eth1Data *ethpb.Eth1Data) (state.BeaconState, error) {
if beaconState == nil || beaconState.IsNil() {
return nil, errors.New("nil state")
}
@@ -56,7 +56,7 @@ func AreEth1DataEqual(a, b *ethpb.Eth1Data) bool {
// eth1 voting period. A vote is cast by including eth1data in a block and part of state processing
// appends eth1data to the state in the Eth1DataVotes list. Iterating through this list checks the
// votes to see if they match the eth1data.
func Eth1DataHasEnoughSupport(beaconState iface.ReadOnlyBeaconState, data *ethpb.Eth1Data) (bool, error) {
func Eth1DataHasEnoughSupport(beaconState state.ReadOnlyBeaconState, data *ethpb.Eth1Data) (bool, error) {
voteCount := uint64(0)
data = copyutil.CopyETH1Data(data)

View File

@@ -7,9 +7,8 @@ import (
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/copyutil"
"github.com/prysmaticlabs/prysm/shared/params"
@@ -71,7 +70,7 @@ func TestEth1DataHasEnoughSupport(t *testing.T) {
c.EpochsPerEth1VotingPeriod = tt.votingPeriodLength
params.OverrideBeaconConfig(c)
s, err := v1.InitializeFromProto(&pb.BeaconState{
s, err := v1.InitializeFromProto(&ethpb.BeaconState{
Eth1DataVotes: tt.stateVotes,
})
require.NoError(t, err)
@@ -161,7 +160,7 @@ func TestAreEth1DataEqual(t *testing.T) {
}
func TestProcessEth1Data_SetsCorrectly(t *testing.T) {
beaconState, err := v1.InitializeFromProto(&pb.BeaconState{
beaconState, err := v1.InitializeFromProto(&ethpb.BeaconState{
Eth1DataVotes: []*ethpb.Eth1Data{},
})
require.NoError(t, err)

View File

@@ -8,9 +8,8 @@ import (
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
v "github.com/prysmaticlabs/prysm/beacon-chain/core/validators"
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/params"
)
@@ -45,9 +44,9 @@ var ValidatorCannotExitYetMsg = "validator has not been active long enough to ex
// initiate_validator_exit(state, voluntary_exit.validator_index)
func ProcessVoluntaryExits(
_ context.Context,
beaconState iface.BeaconState,
beaconState state.BeaconState,
exits []*ethpb.SignedVoluntaryExit,
) (iface.BeaconState, error) {
) (state.BeaconState, error) {
for idx, exit := range exits {
if exit == nil || exit.Exit == nil {
return nil, errors.New("nil voluntary exit in block body")
@@ -88,9 +87,9 @@ func ProcessVoluntaryExits(
// # Initiate exit
// initiate_validator_exit(state, voluntary_exit.validator_index)
func VerifyExitAndSignature(
validator iface.ReadOnlyValidator,
validator state.ReadOnlyValidator,
currentSlot types.Slot,
fork *pb.Fork,
fork *ethpb.Fork,
signed *ethpb.SignedVoluntaryExit,
genesisRoot []byte,
) error {
@@ -133,7 +132,7 @@ func VerifyExitAndSignature(
// assert bls.Verify(validator.pubkey, signing_root, signed_voluntary_exit.signature)
// # Initiate exit
// initiate_validator_exit(state, voluntary_exit.validator_index)
func verifyExitConditions(validator iface.ReadOnlyValidator, currentSlot types.Slot, exit *ethpb.VoluntaryExit) error {
func verifyExitConditions(validator state.ReadOnlyValidator, currentSlot types.Slot, exit *ethpb.VoluntaryExit) error {
currentEpoch := helpers.SlotToEpoch(currentSlot)
// Verify the validator is active.
if !helpers.IsActiveValidatorUsingTrie(validator, currentEpoch) {

View File

@@ -7,9 +7,8 @@ import (
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
@@ -31,7 +30,7 @@ func TestProcessVoluntaryExits_NotActiveLongEnoughToExit(t *testing.T) {
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
},
}
state, err := v1.InitializeFromProto(&pb.BeaconState{
state, err := v1.InitializeFromProto(&ethpb.BeaconState{
Validators: registry,
Slot: 10,
})
@@ -61,7 +60,7 @@ func TestProcessVoluntaryExits_ExitAlreadySubmitted(t *testing.T) {
ExitEpoch: 10,
},
}
state, err := v1.InitializeFromProto(&pb.BeaconState{
state, err := v1.InitializeFromProto(&ethpb.BeaconState{
Validators: registry,
Slot: 0,
})
@@ -93,9 +92,9 @@ func TestProcessVoluntaryExits_AppliesCorrectStatus(t *testing.T) {
ActivationEpoch: 0,
},
}
state, err := v1.InitializeFromProto(&pb.BeaconState{
state, err := v1.InitializeFromProto(&ethpb.BeaconState{
Validators: registry,
Fork: &pb.Fork{
Fork: &ethpb.Fork{
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
},

View File

@@ -3,7 +3,7 @@
package blocks
import (
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
)

View File

@@ -7,9 +7,9 @@ import (
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/interfaces"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
"github.com/prysmaticlabs/prysm/shared/params"
)
@@ -40,9 +40,9 @@ import (
// assert not proposer.slashed
func ProcessBlockHeader(
_ context.Context,
beaconState iface.BeaconState,
block interfaces.SignedBeaconBlock,
) (iface.BeaconState, error) {
beaconState state.BeaconState,
block block.SignedBeaconBlock,
) (state.BeaconState, error) {
if err := helpers.VerifyNilBeaconBlock(block); err != nil {
return nil, err
}
@@ -92,10 +92,10 @@ func ProcessBlockHeader(
// proposer = state.validators[block.proposer_index]
// assert not proposer.slashed
func ProcessBlockHeaderNoVerify(
beaconState iface.BeaconState,
beaconState state.BeaconState,
slot types.Slot, proposerIndex types.ValidatorIndex,
parentRoot, bodyRoot []byte,
) (iface.BeaconState, error) {
) (state.BeaconState, error) {
if beaconState.Slot() != slot {
return nil, fmt.Errorf("state slot: %d is different than block slot: %d", beaconState.Slot(), slot)
}

View File

@@ -8,8 +8,8 @@ import (
"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"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/eth/v1alpha1/wrapper"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"

View File

@@ -7,13 +7,14 @@ import (
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/version"
"google.golang.org/protobuf/proto"
)
type slashValidatorFunc func(iface.BeaconState, types.ValidatorIndex) (iface.BeaconState, error)
type slashValidatorFunc func(st state.BeaconState, vid types.ValidatorIndex, penaltyQuotient, proposerRewardQuotient uint64) (state.BeaconState, error)
// ProcessProposerSlashings is one of the operations performed
// on each processed beacon block to slash proposers based on
@@ -42,10 +43,10 @@ type slashValidatorFunc func(iface.BeaconState, types.ValidatorIndex) (iface.Bea
// slash_validator(state, header_1.proposer_index)
func ProcessProposerSlashings(
_ context.Context,
beaconState iface.BeaconState,
beaconState state.BeaconState,
slashings []*ethpb.ProposerSlashing,
slashFunc slashValidatorFunc,
) (iface.BeaconState, error) {
) (state.BeaconState, error) {
var err error
for idx, slashing := range slashings {
if slashing == nil {
@@ -54,7 +55,12 @@ func ProcessProposerSlashings(
if err = VerifyProposerSlashing(beaconState, slashing); err != nil {
return nil, errors.Wrapf(err, "could not verify proposer slashing %d", idx)
}
beaconState, err = slashFunc(beaconState, slashing.Header_1.Header.ProposerIndex)
cfg := params.BeaconConfig()
slashingQuotient := cfg.MinSlashingPenaltyQuotient
if beaconState.Version() == version.Altair {
slashingQuotient = cfg.MinSlashingPenaltyQuotientAltair
}
beaconState, err = slashFunc(beaconState, slashing.Header_1.Header.ProposerIndex, slashingQuotient, cfg.ProposerRewardQuotient)
if err != nil {
return nil, errors.Wrapf(err, "could not slash proposer index %d", slashing.Header_1.Header.ProposerIndex)
}
@@ -64,7 +70,7 @@ func ProcessProposerSlashings(
// VerifyProposerSlashing verifies that the data provided from slashing is valid.
func VerifyProposerSlashing(
beaconState iface.BeaconState,
beaconState state.BeaconState,
slashing *ethpb.ProposerSlashing,
) error {
if slashing.Header_1 == nil || slashing.Header_1.Header == nil || slashing.Header_2 == nil || slashing.Header_2.Header == nil {

View File

@@ -5,10 +5,8 @@ import (
"testing"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
)
@@ -20,7 +18,7 @@ import (
func TestVerifyProposerSlashing_BeaconFuzzIssue91(t *testing.T) {
file, err := ioutil.ReadFile("testdata/beaconfuzz_91_beacon.ssz")
require.NoError(t, err)
rawState := &pb.BeaconState{}
rawState := &ethpb.BeaconState{}
err = rawState.UnmarshalSSZ(file)
require.NoError(t, err)

View File

@@ -9,10 +9,9 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
v "github.com/prysmaticlabs/prysm/beacon-chain/core/validators"
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
"github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
@@ -118,7 +117,7 @@ func TestProcessProposerSlashings_ValidatorNotSlashable(t *testing.T) {
},
}
beaconState, err := v1.InitializeFromProto(&pb.BeaconState{
beaconState, err := v1.InitializeFromProto(&ethpb.BeaconState{
Validators: registry,
Slot: currentSlot,
})
@@ -184,7 +183,7 @@ func TestProcessProposerSlashings_AppliesCorrectStatus(t *testing.T) {
func TestVerifyProposerSlashing(t *testing.T) {
type args struct {
beaconState iface.BeaconState
beaconState state.BeaconState
slashing *ethpb.ProposerSlashing
}

View File

@@ -5,8 +5,8 @@ import (
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
"github.com/prysmaticlabs/prysm/proto/interfaces"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
"github.com/prysmaticlabs/prysm/shared/hashutil"
"github.com/prysmaticlabs/prysm/shared/params"
)
@@ -27,9 +27,9 @@ import (
// state.randao_mixes[epoch % EPOCHS_PER_HISTORICAL_VECTOR] = mix
func ProcessRandao(
_ context.Context,
beaconState iface.BeaconState,
b interfaces.SignedBeaconBlock,
) (iface.BeaconState, error) {
beaconState state.BeaconState,
b block.SignedBeaconBlock,
) (state.BeaconState, error) {
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
return nil, err
}
@@ -59,9 +59,9 @@ func ProcessRandao(
// hash(body.randao_reveal))
// )
func ProcessRandaoNoVerify(
beaconState iface.BeaconState,
beaconState state.BeaconState,
randaoReveal []byte,
) (iface.BeaconState, error) {
) (state.BeaconState, error) {
currentEpoch := helpers.SlotToEpoch(beaconState.Slot())
// 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.

View File

@@ -8,9 +8,8 @@ import (
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/eth/v1alpha1/wrapper"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
@@ -27,7 +26,7 @@ func TestProcessRandao_IncorrectProposerFailsVerification(t *testing.T) {
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()
root, err := (&ethpb.SigningData{ObjectRoot: buf, Domain: domain}).HashTreeRoot()
require.NoError(t, err)
// We make the previous validator's index sign the message instead of the proposer.
epochSignature := privKeys[proposerIdx-1].Sign(root[:])

View File

@@ -7,11 +7,12 @@ import (
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
"github.com/prysmaticlabs/prysm/shared/attestationutil"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/p2putils"
"github.com/prysmaticlabs/prysm/shared/params"
)
@@ -21,7 +22,7 @@ func signatureSet(signedData, pub, signature, domain []byte) (*bls.SignatureSet,
if err != nil {
return nil, errors.Wrap(err, "could not convert bytes to public key")
}
signingData := &pb.SigningData{
signingData := &ethpb.SigningData{
ObjectRoot: signedData,
Domain: domain,
}
@@ -60,7 +61,7 @@ func verifySignature(signedData, pub, signature, domain []byte) error {
}
// VerifyBlockSignature verifies the proposer signature of a beacon block.
func VerifyBlockSignature(beaconState iface.ReadOnlyBeaconState,
func VerifyBlockSignature(beaconState state.ReadOnlyBeaconState,
proposerIndex types.ValidatorIndex,
sig []byte,
rootFunc func() ([32]byte, error)) error {
@@ -77,8 +78,29 @@ func VerifyBlockSignature(beaconState iface.ReadOnlyBeaconState,
return helpers.VerifyBlockSigningRoot(proposerPubKey, sig, domain, rootFunc)
}
// VerifyBlockSignatureUsingCurrentFork verifies the proposer signature of a beacon block. This differs
// from the above method by not using fork data from the state and instead retrieving it
// via the respective epoch.
func VerifyBlockSignatureUsingCurrentFork(beaconState state.ReadOnlyBeaconState, blk block.SignedBeaconBlock) error {
currentEpoch := helpers.SlotToEpoch(blk.Block().Slot())
fork, err := p2putils.Fork(currentEpoch)
if err != nil {
return err
}
domain, err := helpers.Domain(fork, currentEpoch, params.BeaconConfig().DomainBeaconProposer, beaconState.GenesisValidatorRoot())
if err != nil {
return err
}
proposer, err := beaconState.ValidatorAtIndex(blk.Block().ProposerIndex())
if err != nil {
return err
}
proposerPubKey := proposer.PublicKey
return helpers.VerifyBlockSigningRoot(proposerPubKey, blk.Signature(), domain, blk.Block().HashTreeRoot)
}
// BlockSignatureSet retrieves the block signature set from the provided block and its corresponding state.
func BlockSignatureSet(beaconState iface.ReadOnlyBeaconState,
func BlockSignatureSet(beaconState state.ReadOnlyBeaconState,
proposerIndex types.ValidatorIndex,
sig []byte,
rootFunc func() ([32]byte, error)) (*bls.SignatureSet, error) {
@@ -97,7 +119,7 @@ func BlockSignatureSet(beaconState iface.ReadOnlyBeaconState,
// RandaoSignatureSet retrieves the relevant randao specific signature set object
// from a block and its corresponding state.
func RandaoSignatureSet(beaconState iface.ReadOnlyBeaconState,
func RandaoSignatureSet(beaconState state.ReadOnlyBeaconState,
reveal []byte,
) (*bls.SignatureSet, error) {
buf, proposerPub, domain, err := randaoSigningData(beaconState)
@@ -112,7 +134,7 @@ func RandaoSignatureSet(beaconState iface.ReadOnlyBeaconState,
}
// retrieves the randao related signing data from the state.
func randaoSigningData(beaconState iface.ReadOnlyBeaconState) ([]byte, []byte, []byte, error) {
func randaoSigningData(beaconState state.ReadOnlyBeaconState) ([]byte, []byte, []byte, error) {
proposerIdx, err := helpers.BeaconProposerIndex(beaconState)
if err != nil {
return nil, nil, nil, errors.Wrap(err, "could not get beacon proposer index")
@@ -133,7 +155,7 @@ func randaoSigningData(beaconState iface.ReadOnlyBeaconState) ([]byte, []byte, [
// Method to break down attestations of the same domain and collect them into a single signature set.
func createAttestationSignatureSet(
ctx context.Context,
beaconState iface.ReadOnlyBeaconState,
beaconState state.ReadOnlyBeaconState,
atts []*ethpb.Attestation,
domain []byte,
) (*bls.SignatureSet, error) {
@@ -184,7 +206,7 @@ func createAttestationSignatureSet(
// AttestationSignatureSet retrieves all the related attestation signature data such as the relevant public keys,
// signatures and attestation signing data and collate it into a signature set object.
func AttestationSignatureSet(ctx context.Context, beaconState iface.ReadOnlyBeaconState, atts []*ethpb.Attestation) (*bls.SignatureSet, error) {
func AttestationSignatureSet(ctx context.Context, beaconState state.ReadOnlyBeaconState, atts []*ethpb.Attestation) (*bls.SignatureSet, error) {
if len(atts) == 0 {
return bls.NewSet(), nil
}

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