Compare commits

...

306 Commits

Author SHA1 Message Date
Preston Van Loon
0b3ce46d28 Minor runtime fixes (#2961) 2019-07-14 10:23:23 -07:00
Preston Van Loon
d0ef6dd7f3 Minor fixes for runtime (#2960)
* Minor fixes for runtime

* use comments

* goimports

* revert beacon-chain/core/state/state.go and fix comment for lint

* fix test too
2019-07-13 23:00:42 -04:00
Nishant Das
5be922abe4 Add Tests for Genesis Deposits Caching (#2952)
* remove old method and replace with an improved one

* add new files

* gaz

* add test

* added all these tests

* gaz

* Apply suggestions from code review

Co-Authored-By: terence tsao <terence@prysmaticlabs.com>

* fix merkle proof error

* fix config
2019-07-13 15:33:45 -04:00
Preston Van Loon
97b9176411 Fix deposit input data (#2956)
* fix deposit input data

* fix deposit input data

* gaz and build fix
2019-07-13 15:06:36 -04:00
Preston Van Loon
76ca77bc1b fix breakages from #2957 (#2958)
* fix breakages from #2957

* oops
2019-07-13 14:53:59 -04:00
Preston Van Loon
78d17f07c6 remove unused chainstart param (#2957) 2019-07-13 13:05:13 -04:00
Preston Van Loon
882c1e6bf3 cleanup deposit contract slightly 2019-07-13 11:16:49 -04:00
Preston Van Loon
4b8490a4dd add skip reason 2019-07-13 10:38:57 -04:00
Raul Jordan
9daff21027 Add Back Eth1Data After Bad Merge (#2953)
* eth1data rpc endpoint

* first version

* comment added

* gazelle fix

* new function to go once over the deposit array

* fix tests

* export DepositContainer

* terence feedback

* move structure decleration

* binary search

* fix block into Block

* preston feedback

* keep slice sorted to remove overhead in retrival

* merge changes

* feedback

* update to the latest go-ssz

* revert change

* chnages to fit new ssz

* revert merge reversion

* go fmt goimprts duplicate string

* exception for lint unused doesParentExist

* feedback changes

* latesteth1data to eth1data

* goimports and stop exposing Eth1Data

* revert unneeded change

* remove exposure of DepositContainer

* feedback and fixes

* fix workspace duplicate dependancy

* greatest number of deposits at current height

* add count votes function

* change method name

* revert back to latesteth1data

* latesteth1data

* preston feedback

* seperate function add tests fix bug

* stop exposing voteCountMap

* eth1data comment fix

* preston feedback

* fix tests

* new proto files

* workspace to default version of ssz

* new ssz

* chnage test size

* marshalled  marshaled

* everything passing again
2019-07-12 14:33:46 -05:00
terence tsao
e5648f46c1 Static check on branch spec-v0.6 (#2946)
* Ran staticcheck and fixed the important complains

* commit

* commit

* Create Test Runner for Genesis State Spec Tests (#2940)

* genesis change

* integrate changes

* bodyroot

* remove unused code

* HasChainStarted

* added isValidGenesisState to ProcessLog

* state fix

* fix gazelle

* uint64 timestamp

* SetupInitialDeposits adds proof

* remove unneeded parts of test

* deposithash

* merkleproof from spec utils

* Revert "merkleproof from spec utils"

This reverts commit 1b0a124352.

* fix test failures

* chain started and hashtree root in tests

* simple eth2genesistime

* eth2 genesis time

* fix zero time

* add comment

* remove eth1data and feedback

* fix build issues

* main changes: add fields and methods to track active validator
count

* gaz

* fix test

* fix more tests

* improve test utils

* Start genesis spec tests

* shift spec method to state package, improve test setup

* Add Genesis validity spec test

* Bazel

* fixed log processing tests

* remove log

* gaz

* fix invalid metric

* use json tags

* fix up latest changes

* Fix most of test errors

* Attempts to see whats wrong with genesis validity

* Fix merge

* skip minimal

* fix state test

* new commit

* fix nishant comment

* gaz
2019-07-12 11:32:44 -05:00
Ivan Martinez
0d8165aa98 Create Test Runner for Genesis State Spec Tests (#2940)
* genesis change

* integrate changes

* bodyroot

* remove unused code

* HasChainStarted

* added isValidGenesisState to ProcessLog

* state fix

* fix gazelle

* uint64 timestamp

* SetupInitialDeposits adds proof

* remove unneeded parts of test

* deposithash

* merkleproof from spec utils

* Revert "merkleproof from spec utils"

This reverts commit 1b0a124352.

* fix test failures

* chain started and hashtree root in tests

* simple eth2genesistime

* eth2 genesis time

* fix zero time

* add comment

* remove eth1data and feedback

* fix build issues

* main changes: add fields and methods to track active validator
count

* gaz

* fix test

* fix more tests

* improve test utils

* Start genesis spec tests

* shift spec method to state package, improve test setup

* Add Genesis validity spec test

* Bazel

* fixed log processing tests

* remove log

* gaz

* fix invalid metric

* use json tags

* fix up latest changes

* Fix most of test errors

* Attempts to see whats wrong with genesis validity

* Fix merge

* skip minimal

* fix state test

* new commit

* fix nishant comment

* gaz
2019-07-12 11:19:46 -05:00
Nishant Das
971d8bdcce Remove Block Signing Root (#2945)
* replace with hash tree root

* Revert "replace with hash tree root"

This reverts commit 77d8f16a16.

* replace with signing root instead

* remove one more ref
2019-07-12 09:13:29 -04:00
Preston Van Loon
a5d483aa50 Merge branch 'spec-v0.6' of github.com:prysmaticlabs/prysm into spec-v0.6 2019-07-12 01:17:18 -04:00
Preston Van Loon
cdd2e35152 use better tag names, not latest 2019-07-12 01:17:08 -04:00
shayzluf
5f9f496f64 Genesis trigger (#2905)
* genesis change

* integrate changes

* bodyroot

* remove unused code

* HasChainStarted

* added isValidGenesisState to ProcessLog

* state fix

* fix gazelle

* uint64 timestamp

* SetupInitialDeposits adds proof

* remove unneeded parts of test

* deposithash

* merkleproof from spec utils

* Revert "merkleproof from spec utils"

This reverts commit 1b0a124352.

* fix test failures

* chain started and hashtree root in tests

* simple eth2genesistime

* eth2 genesis time

* fix zero time

* add comment

* remove eth1data and feedback

* fix build issues

* main changes: add fields and methods to track active validator
count

* gaz

* fix test

* fix more tests

* improve test utils

* shift spec method to state package, improve test setup

* fixed log processing tests

* remove log

* gaz

* fix invalid metric
2019-07-11 16:10:37 -05:00
terence tsao
1514f7849a Final updates spec tests (#2901)
* set up tests

* need to reorder pbs

* figuring out how to seqeeze in multiple fields in a tag for pb

* Added max tags and regenerated pb.go

* updated to new standard

* New bitfield types in proto (#2915)

* Cast bytes to correct bitfield, failing tests now though

* Add forked gogo/protobuf until https://github.com/gogo/protobuf/pull/582

* remove newline

* use proper override for gogo-protobuf

* fix a few tags

* forgot to include custody bits and Slashable not used

* playing with tags idea, can revert this commit later

* fixes after merge

* reset caches before test

* all epoch tests pass

* gazelle
2019-07-11 15:35:09 -05:00
Preston Van Loon
35de6cc816 fix bes flag 2019-07-11 10:33:26 -04:00
terence tsao
67c083460e Add ssz compatibility tests for signing root (#2931)
* Added tests for signing root

* imports

* fix lint on travis
2019-07-11 09:26:21 -05:00
Preston Van Loon
7c4b5eba09 add backend service 2019-07-11 10:17:34 -04:00
Ivan Martinez
921b56522d Perform Mutesting In core/state Package (#2923)
* Perform mutesting on validator

* Mutesting in helpers package

* Mutested eth1data

* Perform mutesting in epoch and state packages

* Fix voluntary exits test

* Fix typo

* Fix comments

* Fix formatting

* Fix error message

* Handle missing errors

* Handle all errors

* Perform Mutesting In State Package

* Fix block roots size

* Remove comment

* Fix error
2019-07-11 08:39:16 -04:00
terence tsao
ddbecc81bf Epoch Process Slashings Spec Tests (#2930)
* updated justification bits, tests passing OK

* regen pb.go, clarify bit operations

* justification and finalization tests; failing

* Add wrapper, so we call the correct method

* checkpoint

* Update tar ref

* TestSlashingsMinimal/small_penalty still failing

* Use bigint instead of () and float

* Revert a bad merge from workspace

* Fmt

* add note about https://github.com/ethereum/eth2.0-specs/issues/1284

* improve tests

* gaz
2019-07-11 08:37:48 -04:00
Preston Van Loon
58ca70acfa Add ssz regression tests for investigation of test failures in PR #2828 (#2935)
* Adding regression tests for investigation

* add another example

* goimports

* add quick comment about test case 0
2019-07-10 23:38:37 -05:00
Preston Van Loon
ec1aa897bf satisfy deprecation warning 2019-07-10 23:55:40 -04:00
Preston Van Loon
2b57cf3bac Merge branch 'spec-v0.6' of github.com:prysmaticlabs/prysm into spec-v0.6 2019-07-10 23:19:16 -04:00
Preston Van Loon
8b47f2ad1a update bazel jobs flag 2019-07-10 23:19:11 -04:00
Preston Van Loon
fbfbb126a1 update bazel jobs flag 2019-07-10 23:18:42 -04:00
terence tsao
b04d4c466a Block operations spec tests (#2828)
* update PrevEpoch

* debugging proposer slashing tests

* fmt

* add deposit tests

* Added skeleton for attestation minimal test

* remove bazel runfiles thing

* add deposits

* proposer slashing test is done

* comment

* complete test, some failing cases

* sig verify on

* refactor slightly to support mainnet and minimal

* included mainnet stuff

* Add block header tests

* volunary exit done

* transfer done

* new changes

* fix all tests

* update domain functions

* fmt

* fixed lint

* fixed all the tests

* fixed a transfer bug

* finished attester slashing tests and fixed a few bugs

* started fixing...

* cleaned up exit and proposr slashing tests

* attester slashing passing

* refactored deposit tests

* remove yamls, update ssz

* Added todo for invalid sig

* gazelle

* deposits test done!

* transfer tests done and pass!

* fix attesting indices bug

* temporarily disabled signature verification

* cleaned up most of the block ops, except for att

* update committee AttestingIndices

* oops, i dont know how or why i changed this file

* fixed all the rpc tests

* 6 more failing packages

* test max transfer in state package

* replace hashproto with treehash in package blockchain

* gazelle

* fix test

* fix test again

* fixed transition test, 2 more left

* expect an error in attestation tests

* Handle panic when no votes in aggregate attestation

* clear cache

* Add differ, add logging, tests pass yay

* remove todo, add tag

* fixed TestReceiveBlock_RemovesPendingDeposits

* TestAttestationMinimal/success_since_max_epochs_per_crosslink fails now...

* handle panics

* Transfer tests were disabled in https://github.com/ethereum/eth2.0-specs/pull/1238

* more fixes after merge, updating block_operations.yaml.go to match yaml

* figuring out how to seqeeze in multiple fields in a tag for pb

* Added max tags and regenerated pb.go

* updated to new standard

* New bitfield types in proto (#2915)

* Cast bytes to correct bitfield, failing tests now though

* Add forked gogo/protobuf until https://github.com/gogo/protobuf/pull/582

* remove newline

* fix references and test panic

* change to proto objects from custom types

* fix panics in tests

* use proper override for gogo-protobuf

* fix a few tags

* fix tests

* forgot to include custody bits and Slashable not used

* fix tests

* sort again

* Update yaml struct to use pb

* Update workspace to use latest ssz

* All tests fail

* Use the latest go-ssz commit

* All pass except for state (too long to taste)

* Update test.proto

* Added rest of the tests

* use 1 justification bits

* minor fixes

* wrong proto.Equal

* fix tag test, apply @rauljordan's suggestion

* add IsEmpty and use ssz struct

* inverted logic

* update zero hash

* change zero hash to conform with spec

* goimports

* add test for zero hash

* Revert "Update zero hash to sha256().digest() (#2932)"

This reverts commit b926ae0667.

* update ssz, fix import, shard big test

* checkpoint

* fix compress validator

* update go-ssz

* missing import

* missing import

* tests now pass

* been a good day

* update test size

* fix lint

* imports and remove unused const
2019-07-11 08:34:27 +05:30
Preston Van Loon
ee826991a3 try minimal 2019-07-10 22:12:12 -04:00
Preston Van Loon
9e589a6b62 build without the bytes test 2019-07-10 22:08:08 -04:00
Preston Van Loon
afc2bad4d7 Fix compress validator (#2936)
* fix compress validator

* update go-ssz
2019-07-10 15:50:35 -05:00
Nishant Das
18d7f909e2 Revert "Update zero hash to sha256().digest() (#2932)" (#2933)
This reverts commit b926ae0667.
2019-07-10 08:13:35 -04:00
Preston Van Loon
b926ae0667 Update zero hash to sha256().digest() (#2932)
* update zero hash

* change zero hash to conform with spec

* goimports

* add test for zero hash
2019-07-09 22:29:14 -04:00
Preston Van Loon
9eb22c4f52 delete unused file 2019-07-09 19:59:48 -04:00
terence tsao
af142a4119 Fix SSZ Compatibility Test (#2924)
* figuring out how to seqeeze in multiple fields in a tag for pb

* Added max tags and regenerated pb.go

* updated to new standard

* New bitfield types in proto (#2915)

* Cast bytes to correct bitfield, failing tests now though

* Add forked gogo/protobuf until https://github.com/gogo/protobuf/pull/582

* remove newline

* use proper override for gogo-protobuf

* fix a few tags

* forgot to include custody bits and Slashable not used

* Update yaml struct to use pb

* Update workspace to use latest ssz

* All tests fail

* Use the latest go-ssz commit

* All pass except for state (too long to taste)

* Update test.proto

* Added rest of the tests

* use 1 justification bits

* fix tag test, apply @rauljordan's suggestion

* add IsEmpty and use ssz struct
2019-07-09 19:47:48 -04:00
Preston Van Loon
c6372c109e Merge branch 'master' of github.com:prysmaticlabs/prysm into spec-v0.6 2019-07-09 16:24:11 -04:00
Preston Van Loon
a9d88725fe update go-ssz 2019-07-09 16:07:21 -04:00
Preston Van Loon
0acf164ebd Justification spec tests (#2896) 2019-07-09 10:08:04 -07:00
terence tsao
af0d9d1c63 Update Validator Workflow (#2906) 2019-07-09 09:36:22 -07:00
terence tsao
f34ef8c54c Fixed a few incorrect proto fields (#2926) 2019-07-08 14:18:04 -07:00
Terence Tsao
320e7affd6 Regen pb.go 2019-07-08 11:13:38 -07:00
Terence Tsao
e9931a6fe0 No more space between ssz-size numbers 2019-07-08 11:12:24 -07:00
terence tsao
c029fed293 Add Max Size Tag for Protobuf Fields (#2908) 2019-07-08 10:42:05 -07:00
terence tsao
4b4441ed8e done with updates (#2890) 2019-07-08 11:14:36 +05:30
Ivan Martinez
8773bf881a Perform Mutesting in Epoch and State Packages (#2913) 2019-07-07 13:13:22 -07:00
Nishant Das
1cf1e081ac Fix Spec tests (#2907)
* fix panics

* handle failed transitions

* remove log

* fix to protos

* new changes

* remove i

* change ssz commit

* new changes

* update epoch tests

* fix epoch testing

* fix shuffle tests

* fix test
2019-07-07 10:51:01 -04:00
Nishant Das
5ae798549a Update BLS Domain (#2916)
* change from integer to byte slice

* add test

* fix func for bytes4
2019-07-07 10:41:28 -04:00
terence tsao
175ad3c9b1 s/volundary/voluntary (#2914) 2019-07-06 10:44:13 -07:00
Ivan Martinez
064f6cba4d Perform Mutesting in Helpers Package (#2912)
* Perform mutesting on validator

* Mutesting in helpers package

* Mutested eth1data
2019-07-06 12:17:58 -04:00
Preston Van Loon
add9647b7b update WORKSPACE to use 0.8 spec tests 2019-07-04 16:09:54 -04:00
Nishant Das
2e145dd3ae Update Deposit Contract (#2903)
* update to new contract

* fix references

* fix tests

* fix some more tests

* fix local deposit trie

* gaz

* shays review

* more changes
2019-07-04 16:17:22 +05:30
Preston Van Loon
3cb5203f2b Remove deprecated fields from attestation data (#2892)
* fix broken tests

* remove comment

* fixes
2019-07-03 18:58:21 -04:00
Nishant Das
8674cc3d26 Implement Compact Committee Root (#2897)
* add tags

* add function

* add new code

* add function

* add all new changes

* lint

* add tests

* fix tests

* fix more tests

* fix all outstanding tests

* gaz

* Update beacon-chain/core/helpers/committee.go

Co-Authored-By: terence tsao <terence@prysmaticlabs.com>

* comment
2019-07-03 19:41:27 +05:30
Nishant Das
79c7307095 Slashing Penalty Calculation Change (#2889)
* lint

* change config val

* add max helper

* changes to slashing and process slashing, add a min function for integers

* gaz

* fix failing tests

* fix test

* fixed all tests

* Change Yaml tag

* lint

* remove gc hack

* fix test

* gaz

* preston's comments

* change failing field

* fix and regen proto

* lint
2019-07-03 08:30:22 +05:30
terence tsao
be35f0297b reorder proto fields (#2902) 2019-07-02 21:06:57 -04:00
Ivan Martinez
4ba541dea4 Move Block Operation Length Checks to ProcessOperations (#2900)
* Move block operation length checks to ProcessOperations

* Write tests for each length check in ProcessOperations

* Remove unneeded test

* Move checks to a new function

* Move duplicate check back into ProcessOperations
2019-07-03 02:30:10 +09:00
Ivan Martinez
f612b816f6 Make Constants Explicit and Minor Cleanups (#2898)
* Rename outdated configs, make constants explicitly delcared

* Remove activate_validator, not needed

* Remove GenesisSlot and GenesisEpoch

* Remove unused import
2019-07-03 01:22:55 +09:00
terence tsao
24f630d70b updated all the helper pseudocodes (#2895) 2019-07-02 07:40:33 -07:00
Preston Van Loon
2d09a1e539 Update justification bits (#2894) 2019-07-01 14:32:17 -07:00
terence tsao
61fafd0523 Update Freeze Spec Simplification Section - part 1 (#2893)
* finished changes to attesting_indices

* removed index_count <= 2**40 requirement

* lint

* reverted index_count <= 2**40 check

* added short cut len(a) > len(b)
2019-07-01 14:58:09 -04:00
Nishant Das
de5df510e4 Change Base Reward Factor (#2888) 2019-07-01 06:54:21 -07:00
terence tsao
5af9774a41 Update State Transition Function (#2867) 2019-07-01 06:52:44 -07:00
Preston Van Loon
69e46a9628 fix build 2019-07-01 02:36:12 -04:00
Preston Van Loon
d3cbad3608 update latest sha for spec tests 2019-07-01 02:10:43 -04:00
Preston Van Loon
878540bfc5 update readme target 2019-07-01 00:58:20 -04:00
Preston Van Loon
8b024d58ac Mutation testing fixes for beacon-chain/core/helpers/committee.go (#2870)
* Add some fixes for mutation testing on blocks.go

* working on mutation testing fo committee.go

* gofmt

* goimports
2019-06-30 21:21:24 -04:00
terence tsao
059c1daff8 Update Configs for Freeze (#2876)
* update configs

* updated minimal configs

* almost there

* all tests passing except for spec tests

* better comment for MinGenesisTime

* done, ready for review

* rm seconds per day

* feedback
2019-06-30 21:17:23 -04:00
Preston Van Loon
4b94d88f3d Removes some deprecated fields from protobuf (#2877)
* search and replace checkpoints

* fix tests, except spec tests
2019-06-30 21:11:58 -04:00
terence tsao
06aae90f15 Align Protobuf Type Names (#2872) 2019-06-30 13:59:35 -07:00
Preston Van Loon
74a2198a22 Spec freeze release candidate spectests 2019-06-30 16:48:52 -04:00
Preston Van Loon
230810533e gaz 2019-06-30 12:20:34 -04:00
Preston Van Loon
237f0db6de Fix sizes 2019-06-30 12:20:20 -04:00
Preston Van Loon
697a3dcb04 Merge branch 'master' of github.com:prysmaticlabs/prysm into spec-v0.6 2019-06-30 12:10:53 -04:00
Preston Van Loon
db5463e7fa Add some fixes for mutation testing on blocks.go (#2869) 2019-06-29 14:40:20 -07:00
Preston Van Loon
b87b730f60 Mutation testing fixes for beacon-chain/core/helpers/attestation.go (#2868)
* mutation testing for attestation.go

* new line

* lint

* revert fmt.Errorf deletion

* gofmt
2019-06-29 13:34:14 -04:00
Nishant Das
c5a4778ef9 Block Processing Sanity Spec Tests (#2817)
* update PrevEpoch

* add new changes

* shift to blocks package

* add more changes

* new changes

* updated pb with size tags

* add new changes

* fix errors

* uncomment code

* more changes

* add new changes

* rename and lint

* gaz

* more changes

* proccess slot SigningRoot instead of HashTreeRoot

* ensure yaml generated structs work

* block sanity all passing

* minimal and mainnet all pass

* remove commented code

* fix one test

* fix all tests

* fix again

* no state comparison

* matching spec

* change target viz

* comments gazelle

* clear caches before test cases

* latest attempts

* clean up test format

* remove debugging log, remove yaml

* unskip attestation

* remove skip, check post state, diff state diffs

* handle err

* add bug fixes

* fixed one more bug

* fixed churn limit bug

* change hashProto to HashTreeRoot

* all tests pass :)

* fix all tests

* gaz

* add regression tests

* fix test bug
2019-06-29 20:06:02 +05:30
terence tsao
816d14f31b removed old chaintest, simulated backend and state generator (#2863) 2019-06-26 16:44:56 -07:00
Nishant Das
598916566e Attesting Indices Fix (#2862)
* add change

* fix one test

* fix all tests

* add test

* clear cache
2019-06-26 09:39:29 -05:00
shayzluf
50e63f0cf0 eth1data rpc endpoint (#2733)
* eth1data rpc endpoint

* first version

* comment added

* gazelle fix

* new function to go once over the deposit array

* fix tests

* export DepositContainer

* terence feedback

* move structure decleration

* binary search

* fix block into Block

* preston feedback

* keep slice sorted to remove overhead in retrival

* merge changes

* feedback

* update to the latest go-ssz

* revert change

* chnages to fit new ssz

* revert merge reversion

* go fmt goimprts duplicate string

* exception for lint unused doesParentExist

* feedback changes

* latesteth1data to eth1data

* goimports and stop exposing Eth1Data

* revert unneeded change

* remove exposure of DepositContainer

* feedback and fixes

* fix workspace duplicate dependancy

* greatest number of deposits at current height

* add count votes function

* change method name

* revert back to latesteth1data

* latesteth1data

* preston feedback

* seperate function add tests fix bug

* stop exposing voteCountMap

* eth1data comment fix

* preston feedback

* fix tests

* new proto files

* workspace to default version of ssz

* new ssz

* chnage test size

* marshalled  marshaled
2019-06-26 04:19:54 +03:00
terence tsao
50eae63112 Slot processing spec test (#2813) 2019-06-25 11:12:11 -07:00
Nishant Das
e083bb5086 Merge branch 'master' into spec-v0.6 2019-06-25 23:40:28 +05:30
Nishant Das
7bc42b3c6b BLS spec tests (#2826) (#2856)
* bls spec tests

* add more bls tests

* use ioutil instead of bazel runfiles

* dont read bytes

* skip tests that overflow uint64

* manually fix input data

* add tests

* lint and gaz

* add all new changes

* some refactoring, cleanup, remove new API methods that only exist for tests

* gaz

* Remove yamls, skip test
2019-06-25 23:33:02 +05:30
Preston Van Loon
d4be71cbe0 remove yamls from branch 2019-06-25 12:52:47 -04:00
Preston Van Loon
bfd50c3f10 update workspace spec sha 2019-06-25 12:35:39 -04:00
terence tsao
12bc617b62 SSZ compatibility test for protobufs (#2839) 2019-06-25 08:45:02 -07:00
shayzluf
c081179cdd Shuffle tests revisited (#2829)
* first commit

* remove old files, add log

* remove duplicate yaml testing code

* reduce visability

* nishant feedback changes

* skip TestFromYaml_Pass

* added tags to bazel build

* gazelle fix

* remove unused vars

* adda back config

* remove config handling

* remove unused var

* gazelle fix
2019-06-25 13:35:17 +05:30
Nishant Das
f59563cfbe Remove Deposit Index (#2851) 2019-06-24 17:08:38 -07:00
terence tsao
c6f119bd08 Epoch processing spec tests (#2814) 2019-06-24 14:54:28 -07:00
Terence Tsao
85ae64855c Merge branch 'master' into spec-v0.6 2019-06-24 14:39:27 -07:00
Terence Tsao
4a487fca6a sync with master 2019-06-24 14:00:11 -07:00
terence tsao
2b20455037 Update types PB with Size Tags (#2840) 2019-06-23 11:17:09 -07:00
terence tsao
1def1d8d32 Block Processing Bug Fixes (#2836) 2019-06-23 10:07:34 -07:00
terence tsao
540b568bd3 Add ConvertToPb to package testutil (#2838) 2019-06-21 22:37:09 -07:00
Preston Van Loon
ea9de682f9 Revert "Add Functions for Compressed and Uncompressed HashG2 With Domain (#2833)" (#2835)
This reverts commit 7fb2ebf3f1.
2019-06-21 19:35:56 +05:30
Nishant Das
7fb2ebf3f1 Add Functions for Compressed and Uncompressed HashG2 With Domain (#2833)
* add tests

* gaz

* lint
2019-06-21 08:43:03 +05:30
terence tsao
35b67a3dcf Update Domain Related Functions (#2832) 2019-06-20 09:44:58 -07:00
terence tsao
b4b00fd41c Revert "Align Protobuf Type Names (#2825)" (#2827)
This reverts commit 882d067144.
2019-06-19 11:13:48 +05:30
Preston Van Loon
650383d117 gofmt 2019-06-18 23:11:18 -04:00
terence tsao
882d067144 Align Protobuf Type Names (#2825) 2019-06-18 17:22:39 -07:00
Preston Van Loon
06d1161bd2 Merge branch 'master' of github.com:prysmaticlabs/prysm into spec-v0.6 2019-06-18 18:00:58 -04:00
Nishant Das
7563db0538 Add Config YAML for Spec Tests (#2818) 2019-06-18 13:48:33 -07:00
Raul Jordan
f61688a08c Fix Final Missing Items in Block Processing v0.6 (#2710)
* override config successfully

* passes processing

* add signing root helper

* blockchain tests pass

* tests blocked by signing root

* lint

* fix references

* fix protos

* proper use of signing root

* only few failing tests now

* fix final test

* tests passing

* lint and imports

* rem unused

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

Co-Authored-By: terence tsao <terence@prysmaticlabs.com>

* lint

* Update beacon-chain/attestation/service_test.go

Co-Authored-By: terence tsao <terence@prysmaticlabs.com>

* Update beacon-chain/db/block_test.go

Co-Authored-By: terence tsao <terence@prysmaticlabs.com>

* rename to hash tree root

* rename decode to unmarshal

* fix

* use latest ssz

* all tests passing

* lint

* fmt
2019-06-18 11:22:24 -05:00
terence tsao
55ea83066c Update BlockRoot to BlockHash (#2816) 2019-06-17 19:42:36 -07:00
Raul Jordan
eecec35b03 Merge branch 'master' into spec-v0.6 2019-06-17 10:24:34 -05:00
terence tsao
b2ddee1ae8 Optimize Committee Assignment RPC (#2787) 2019-06-17 05:56:50 -07:00
Ivan Martinez
ae0a501646 Refactor Deposit Flow and Cleanup Tests (#2788)
* More WIP on cleaning deposit flow

* Fix tests

* Cleanup and imports

* run gazelle

* Move deposit to block_operations

* gazelle

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

Co-Authored-By: terence tsao <terence@prysmaticlabs.com>

* Fix docs

* Remove unneeded calculations

* Fix tests

* Fix tests finally (?)
2019-06-13 10:00:25 -07:00
Preston Van Loon
2dfc2de155 Merge branch 'master' of github.com:prysmaticlabs/prysm into spec-v0.6 2019-06-12 16:27:06 -04:00
terence tsao
8078917d8c Minor Updates to 0.7 (#2795) 2019-06-12 08:18:15 -07:00
Ivan Martinez
d07ed6427e Update config and function parameters to v0.7 (#2791) 2019-06-12 06:16:55 -07:00
terence tsao
f02afa20ab Update Attester Server RPC Calls (#2773) 2019-06-11 09:57:24 -07:00
Preston Van Loon
5217749c4f Merge branch 'master' into spec-v0.6 2019-06-10 16:14:51 -04:00
Preston Van Loon
5ff4139f0e unstaged changes 2019-06-10 13:55:20 -04:00
Preston Van Loon
5bb7ad31a8 Merge branch 'master' into spec-v0.6 2019-06-10 13:46:33 -04:00
Preston Van Loon
69d1cb40ac Merge remote-tracking branch 'origin/new-v0.6' into spec-v0.6 2019-06-10 13:20:10 -04:00
nisdas
fda0310e42 update to latest go-ssz 2019-06-10 22:57:19 +08:00
nisdas
01c646b2bc Revert "temp change for go-ssz"
This reverts commit 3411cb9d6d.
2019-06-10 22:23:46 +08:00
nisdas
64162a51fa fix test 2019-06-10 16:50:04 +08:00
nisdas
3411cb9d6d temp change for go-ssz 2019-06-10 16:22:45 +08:00
nisdas
3c6c3b9999 fix build files 2019-06-10 16:22:16 +08:00
nisdas
d48e6b17d0 fix all genesis errors 2019-06-10 16:10:06 +08:00
nisdas
9798f83dc6 fix genesis issue for slot ticker 2019-06-10 16:05:13 +08:00
nisdas
5f9c2edebd fix genesis issue 2019-06-10 16:03:47 +08:00
nisdas
8d9960d912 fix errors 2019-06-10 16:02:58 +08:00
nisdas
ca427dcb66 add back protos and mocks 2019-06-10 15:23:46 +08:00
nisdas
df00a73b0c add back deleted stuff that was deleted accidentally 2019-06-10 15:05:31 +08:00
nisdas
d9719b2a83 add back deleted stuff 2019-06-10 14:44:22 +08:00
nisdas
26d275568d updating rpc package 2019-06-10 14:41:51 +08:00
nisdas
7a0f4c0ed2 lint 2019-06-10 13:51:23 +08:00
Terence Tsao
bd0f18281a started fixing blockchain package 2019-06-09 09:06:41 -07:00
Terence Tsao
8b2184dd9c removed shared/forkutils 2019-06-09 08:55:23 -07:00
Terence Tsao
eb76044fff all core tests passing! 2019-06-09 08:48:48 -07:00
Terence Tsao
f01dc69a35 started fixing core 2019-06-09 07:30:16 -07:00
Terence Tsao
03abcd5497 regenerated protos 2019-06-09 06:49:41 -07:00
nisdas
0e035c787e regen protos and mocks 2019-06-09 20:48:06 +08:00
nisdas
e3d4cff19e lint 2019-06-09 19:01:34 +08:00
Nishant Das
4e82811264 Update Genesis State Function to v0.6 (#2465)
* add pseudocode

* make changes

* fix all tests

* fix tests
2019-06-09 18:58:19 +08:00
terence tsao
76a21207bb Update Shard Helpers for 0.6 (#2497)
* ValidatorStatus Estimating Activation RPC Server (#2469)

* fix spacing

* working on position in queue

* fmt

* spacing

* feedback

* tests

* rename

* Only Perform Initial Sync With a Single Peer (#2471)

* fix spacing

* use send instead of broadcast in initial sync

* Fix Estimation of Deposit Inclusion Slot in ValidatorActivationStatus (#2472)

* fix spacing

* fix time estimates

* correct slot estimation

* naming

* Update beacon-chain/rpc/validator_server.go

Co-Authored-By: rauljordan <raul@prysmaticlabs.com>

* SSZ web api for decoding input data (#2473)

* first pass ssz server for decoding deposit input data

* fix decoding

* revert viz change on helper

* add image target

* use /api prefix, add deployment for cluster

* fix lint

* standardize slot numbers (#2475)

* Add CORS for ssz api (#2476)

* first pass ssz server for decoding deposit input data

* fix decoding

* revert viz change on helper

* add image target

* use /api prefix, add deployment for cluster

* fix lint

* needed CORS

* Allow Client to Retrieve Multiple Validator Statuses (#2474)

* multiple validator statuses

* gazelle

* context

* fixing bugs

* remove old way of checking

* fix logging

* make activation queue more accurate

* fix rpc test

* add test

* fix remaining tests

* lint

* comment

* review comments

* Update Prysm README (#2477)

* README updated

* readme updates

* no err throw (#2479)

* Fix Status Nil Pointer Error (#2480)

* no err throw

* nil errors

* 3.175 (#2482)

* Better Error Message if Failing to Exit Initial Sync (#2483)

* no err throw

* nil errors

* better error on init sync

* Only Log Active Balances (#2485)

* only log active balance

* dont need ()

* change logging (#2487)

* fix chainstart waiting on rpc server (#2488)

* shift ticker to after activation (#2489)

* Add drain script (#2418)

* Add drain script

* Fix script to drain contracts from newest to oldest

* Add README

* remove comments

* Only after block 400k, look up by deposit event

* issue warn log on disconnecting peer instead of error (#2491)

* Display Only Active Validator Data (#2490)

* Fix Validator Status Field in RPC Server (#2492)

* fix status of key

* status test fix

* fmt

* Estimate the Time Till Follow Distance Is Completed (#2486)

* use estimation instead

* fix test

* fixing another test

* fix tests and preston's comments

* remove unused var

* fix condition

* Revert "fix condition"

This reverts commit dee0e3112c.

* dont return error

* add production config for testnet release (#2493)

* Lookup Validator Index in State in Status Check (#2494)

* state lookup

* refactor duplicate code

* refactor with mapping

* fix broken tests

* finish refactor

* merged master

* updated EpochCommitteeCount and fixed tests

* implemented ShardDelta

* test for ShardDelta

* implemented EpochStartShard

* added epoch out of bound test

* test for accurate start shard

* lint
2019-06-09 18:56:25 +08:00
Nishant Das
185dade934 Update Deposit Contract (#2648)
* lint

* add new contract

* change version

* remove log

* generating abi and binary files

* fix tests

* update to current version

* new changes

* add new hash function

* save hashed nodes

* add more things

* new method

* add update to trie

* new stuff

* gaz

* more stuff

* finally fixed build

* remove deposit data

* Revert "remove deposit data"

This reverts commit 9085409e91.

* more changes

* lint and gaz

* lint
2019-06-09 18:53:28 +08:00
terence tsao
bf441a8ec8 Cache Active Validator Indices, Count, and Balances (#2737) 2019-06-09 18:45:35 +08:00
nisdas
ccbe0720fd Merge remote-tracking branch 'remotes/origin/master' into fixMess 2019-06-09 18:35:03 +08:00
terence tsao
0b476749fb Update RPC end point for Proposer (#2767)
* add RequestBlock

* run mockgen

* implemented RequestBlock

* updated proto definitions

* updated tests

* updated validator attest tests

* done

* comment

* todo issue

* removed unused proto
2019-06-09 17:47:48 +08:00
terence tsao
f2c31004de Clean up Old RPC Endpoints (#2763) 2019-06-09 17:47:31 +08:00
terence tsao
da0e6bb28b Tidying up Godoc for Core Package (#2762) 2019-06-09 17:47:13 +08:00
terence tsao
32975baa3c Benchmark Process Block with Attestations (#2758) 2019-06-09 17:46:56 +08:00
Ivan Martinez
4a0b3710ef Add graffiti and update generate seed (#2759) 2019-06-09 17:46:54 +08:00
Ivan Martinez
82dc94e023 Cleanup and Docs update (#2756) 2019-06-09 17:46:35 +08:00
terence tsao
348579780e Optimize Process Eth1 Data Vote (#2754) 2019-06-09 17:46:21 +08:00
terence tsao
8373d75033 removed deprecated configs (#2755) 2019-06-09 17:46:00 +08:00
terence tsao
76fa1e5adb Optimize Base Reward Calculation (#2753)
* benchmark process epoch

* revert prof.out

* Add some optimizations

* beware where we use ActiveValidatorIndices...

* revert extra file

* gaz

* quick commit to get feedback

* revert extra file

* started fixing tests

* fixed broken TestProcessCrosslink_NoUpdate

* gaz

* cache randao seed

* fixed all the tests

* fmt and lint

* spacing

* Added todo

* lint

* revert binary file

* started regression test

* basic tests done

* using a fifo for active indices cache

* using a fifo for active count cache

* using a fifo for total balance cache

* using a fifo for active balance cache

* using a fifo for start shard cache

* using a fifo for seed cache

* gaz

* clean up

* fixing tests

* fixed all the core tests

* fixed all the tests!!!

* lint

* comment

* rm'ed commented code

* cache size to 1000 should be good enough

* optimized base reward

* revert binary file

* Added comments to calculate adjusted quotient outside
2019-06-09 17:45:42 +08:00
Ivan Martinez
b899305a69 Fix most of skipped tests (#2735) 2019-06-09 17:32:48 +08:00
Ivan Martinez
b88d7a841e Remove Deprecated Validator Protobuf (#2727)
* Remove deprecated validator protos

* Fix to comments
2019-06-09 17:32:23 +08:00
Nishant Das
0c33dc472f change hash function (#2732) 2019-06-09 17:31:41 +08:00
Nishant Das
ae11795617 Refactor Deposit Contract Test Setup (#2731)
* add new package

* fix all tests

* lint
2019-06-09 17:31:15 +08:00
terence tsao
94cb85d847 Optimize Shuffled Indices Cache (#2728) 2019-06-09 17:30:40 +08:00
terence tsao
87ff6a0773 Fixed Skipped Attestation Tests (#2730) 2019-06-09 17:30:27 +08:00
terence tsao
d9a109ad37 Benchmark Compute Committee (#2698) 2019-06-09 17:30:06 +08:00
terence tsao
013aee6958 Remove Committee Cache (#2729) 2019-06-09 17:29:55 +08:00
Nishant Das
0f43b261bd Fix Deposit Trie (#2686)
* remove deposit data

* remove deposit input

* fix references

* remove deposit helpers

* fix all refs

* gaz

* rgene proto

* fix all tests

* remove deposit data deprecated field

* fix remaining references

* fix all tests

* fix lint

* new tests with contract

* gaz

* more tests

* fixed bugs

* new test

* finally fixed it

* gaz

* fix test
2019-06-09 17:29:50 +08:00
Nishant Das
d29a2be222 Remove Latest Block (#2721)
* lint

* remove latest block

* lint

* add proto

* fix build
2019-06-09 17:28:53 +08:00
shayzluf
ee3a38821a YAML shuffle tests for v0.6 (#2667)
* new shuffle tests

* added comment for exported function

* fix format and print

* added config files handling

* gazelle fix

* shuffle test debugging

* added shuffle list and benchmark

* hash function addition from nishant code

* gazelle fix

* remove unused function

* few minor changes

* add test to test protos optimization

* test a bigger list

* remove commented code

* small changes

* fix spec test and test indices to pass

* remove empty line

* abstraction of repeated code and comment arrangement

* terence change requests

* fix new test

* add small comment for better readability

* change from unshuflle to shuffle

* comment

* better comment

* fix all tests
2019-06-09 17:28:20 +08:00
terence tsao
1fb02639b0 Cache Shuffled Validator Indices (#2682) 2019-06-09 17:27:16 +08:00
terence tsao
13c9432d37 Remove Deprecated Attestation Proto Fields (#2723) 2019-06-09 17:25:39 +08:00
terence tsao
1cbe622859 Remove Deprecated Beacon Block Proto Fields (#2717) 2019-06-09 17:12:15 +08:00
terence tsao
b0db321a57 Remove Deprecated Protobuf Crosslink/Slashing/Block Fields (#2714) 2019-06-09 17:11:27 +08:00
terence tsao
98f8331649 Remove Deprecated Protobuf State Fields (#2713) 2019-06-09 17:05:42 +08:00
Nishant Das
131823511e Remove Obsolete Deposit Proto Objects (#2673)
* remove deposit data

* remove deposit input

* fix references

* remove deposit helpers

* fix all refs

* gaz

* rgene proto

* fix all tests

* remove deposit data deprecated field

* fix remaining references

* fix all tests

* fix lint

* regen proto

* fix test
2019-06-09 17:03:59 +08:00
terence tsao
5fd97e9ed2 Fixed Skipped Tests for RPC Server (#2712) 2019-06-09 17:00:28 +08:00
Raul Jordan
52ef370817 Process Block Attestations v0.6 (#2650)
* attestation.go is ready, tests not

* ready for review

* fixing linter issues

* modified Crosslink and AttestationData proto fields to spec 2.0,marked deprecated fields

* gazelle

* fixed tests

* fixed error

* add att processing:

* process atts

* error msg

* finish process attestations logic

* spacing

* ssz move

* inclusion delay failure passing

* more attestation tests

* more att tests passing

* more tests

* ffg data mismatching test

* ffg tests complete

* gofmt

* fix testing to match attestation updates

* ssz

* lint
2019-06-09 16:59:22 +08:00
terence tsao
1877c2e441 cleaned up skipped tests for core processing (#2697) 2019-06-09 16:56:46 +08:00
terence tsao
66a922dab2 Update CommitteeAssignment (#2693) 2019-06-09 16:56:42 +08:00
terence tsao
c25ed02bb3 Implement Process Epoch for 0.6 (#2675)
* can't find process j f functons

* implemented process_epoch

* tests done

* lint

* nishant's feedback

* stupid goland replace

* goimports
2019-06-09 16:55:36 +08:00
Raul Jordan
ebff47bde1 Update Slot Processing and State Transition v0.6 (#2664)
* edit state transition to add slot processing logic, reorder logic

* fix build

* lint

* tests passing

* spacing

* tests pass

* imports

* passing tests
2019-06-09 16:52:48 +08:00
terence tsao
5c1410b224 Implement process_rewards_and_penalties for 0.6 (#2665)
* update process crosslink and update existing tests

* added a test case to cover no crosslink changes

* more test

* preston's feedback

* spellings

* ValidatorStatus Estimating Activation RPC Server (#2469)

* fix spacing

* working on position in queue

* fmt

* spacing

* feedback

* tests

* rename

* Only Perform Initial Sync With a Single Peer (#2471)

* fix spacing

* use send instead of broadcast in initial sync

* Fix Estimation of Deposit Inclusion Slot in ValidatorActivationStatus (#2472)

* fix spacing

* fix time estimates

* correct slot estimation

* naming

* Update beacon-chain/rpc/validator_server.go

Co-Authored-By: rauljordan <raul@prysmaticlabs.com>

* SSZ web api for decoding input data (#2473)

* first pass ssz server for decoding deposit input data

* fix decoding

* revert viz change on helper

* add image target

* use /api prefix, add deployment for cluster

* fix lint

* standardize slot numbers (#2475)

* Add CORS for ssz api (#2476)

* first pass ssz server for decoding deposit input data

* fix decoding

* revert viz change on helper

* add image target

* use /api prefix, add deployment for cluster

* fix lint

* needed CORS

* Allow Client to Retrieve Multiple Validator Statuses (#2474)

* multiple validator statuses

* gazelle

* context

* fixing bugs

* remove old way of checking

* fix logging

* make activation queue more accurate

* fix rpc test

* add test

* fix remaining tests

* lint

* comment

* review comments

* Update Prysm README (#2477)

* README updated

* readme updates

* no err throw (#2479)

* Fix Status Nil Pointer Error (#2480)

* no err throw

* nil errors

* 3.175 (#2482)

* Better Error Message if Failing to Exit Initial Sync (#2483)

* no err throw

* nil errors

* better error on init sync

* Only Log Active Balances (#2485)

* only log active balance

* dont need ()

* change logging (#2487)

* fix chainstart waiting on rpc server (#2488)

* shift ticker to after activation (#2489)

* Add drain script (#2418)

* Add drain script

* Fix script to drain contracts from newest to oldest

* Add README

* remove comments

* Only after block 400k, look up by deposit event

* issue warn log on disconnecting peer instead of error (#2491)

* Display Only Active Validator Data (#2490)

* Fix Validator Status Field in RPC Server (#2492)

* fix status of key

* status test fix

* fmt

* Estimate the Time Till Follow Distance Is Completed (#2486)

* use estimation instead

* fix test

* fixing another test

* fix tests and preston's comments

* remove unused var

* fix condition

* Revert "fix condition"

This reverts commit dee0e3112c.

* dont return error

* add production config for testnet release (#2493)

* Lookup Validator Index in State in Status Check (#2494)

* state lookup

* refactor duplicate code

* refactor with mapping

* fix broken tests

* finish refactor

* merged master

* Starting, I need get_epoch_start_shard

* updated EpochCommitteeCount and fixed tests

* implemented ShardDelta

* test for ShardDelta

* implemented EpochStartShard

* added epoch out of bound test

* test for accurate start shard

* lint

* need to use changes from latest crosslinks

* added BaseReward and totalActiveBalance

* added test for base reward

* implemented process_attestation_delta

* comments

* comments

* merged master

* all tests passing

* start testing

* done

* merged master

* fixed tests

* tests, more to come

* tests done

* lint

* spaces over tabs

* addressed shay's feedback

* starting but need to merge a few things...

* tests

* fmt
2019-06-09 16:49:58 +08:00
terence tsao
f747de5dc8 Implement Attestation Delta for v0.6 (#2646)
* update process crosslink and update existing tests

* added a test case to cover no crosslink changes

* more test

* preston's feedback

* spellings

* ValidatorStatus Estimating Activation RPC Server (#2469)

* fix spacing

* working on position in queue

* fmt

* spacing

* feedback

* tests

* rename

* Only Perform Initial Sync With a Single Peer (#2471)

* fix spacing

* use send instead of broadcast in initial sync

* Fix Estimation of Deposit Inclusion Slot in ValidatorActivationStatus (#2472)

* fix spacing

* fix time estimates

* correct slot estimation

* naming

* Update beacon-chain/rpc/validator_server.go

Co-Authored-By: rauljordan <raul@prysmaticlabs.com>

* SSZ web api for decoding input data (#2473)

* first pass ssz server for decoding deposit input data

* fix decoding

* revert viz change on helper

* add image target

* use /api prefix, add deployment for cluster

* fix lint

* standardize slot numbers (#2475)

* Add CORS for ssz api (#2476)

* first pass ssz server for decoding deposit input data

* fix decoding

* revert viz change on helper

* add image target

* use /api prefix, add deployment for cluster

* fix lint

* needed CORS

* Allow Client to Retrieve Multiple Validator Statuses (#2474)

* multiple validator statuses

* gazelle

* context

* fixing bugs

* remove old way of checking

* fix logging

* make activation queue more accurate

* fix rpc test

* add test

* fix remaining tests

* lint

* comment

* review comments

* Update Prysm README (#2477)

* README updated

* readme updates

* no err throw (#2479)

* Fix Status Nil Pointer Error (#2480)

* no err throw

* nil errors

* 3.175 (#2482)

* Better Error Message if Failing to Exit Initial Sync (#2483)

* no err throw

* nil errors

* better error on init sync

* Only Log Active Balances (#2485)

* only log active balance

* dont need ()

* change logging (#2487)

* fix chainstart waiting on rpc server (#2488)

* shift ticker to after activation (#2489)

* Add drain script (#2418)

* Add drain script

* Fix script to drain contracts from newest to oldest

* Add README

* remove comments

* Only after block 400k, look up by deposit event

* issue warn log on disconnecting peer instead of error (#2491)

* Display Only Active Validator Data (#2490)

* Fix Validator Status Field in RPC Server (#2492)

* fix status of key

* status test fix

* fmt

* Estimate the Time Till Follow Distance Is Completed (#2486)

* use estimation instead

* fix test

* fixing another test

* fix tests and preston's comments

* remove unused var

* fix condition

* Revert "fix condition"

This reverts commit dee0e3112c.

* dont return error

* add production config for testnet release (#2493)

* Lookup Validator Index in State in Status Check (#2494)

* state lookup

* refactor duplicate code

* refactor with mapping

* fix broken tests

* finish refactor

* merged master

* Starting, I need get_epoch_start_shard

* updated EpochCommitteeCount and fixed tests

* implemented ShardDelta

* test for ShardDelta

* implemented EpochStartShard

* added epoch out of bound test

* test for accurate start shard

* lint

* need to use changes from latest crosslinks

* added BaseReward and totalActiveBalance

* added test for base reward

* implemented process_attestation_delta

* comments

* comments

* merged master

* all tests passing

* start testing

* done

* merged master

* fixed tests

* tests, more to come

* tests done

* lint

* spaces over tabs

* addressed shay's feedback

* merged master
2019-06-09 16:49:53 +08:00
terence tsao
518e129d46 Putting Crosslink Delta Back (#2654)
* update process crosslink and update existing tests

* added a test case to cover no crosslink changes

* more test

* preston's feedback

* spellings

* ValidatorStatus Estimating Activation RPC Server (#2469)

* fix spacing

* working on position in queue

* fmt

* spacing

* feedback

* tests

* rename

* Only Perform Initial Sync With a Single Peer (#2471)

* fix spacing

* use send instead of broadcast in initial sync

* Fix Estimation of Deposit Inclusion Slot in ValidatorActivationStatus (#2472)

* fix spacing

* fix time estimates

* correct slot estimation

* naming

* Update beacon-chain/rpc/validator_server.go

Co-Authored-By: rauljordan <raul@prysmaticlabs.com>

* SSZ web api for decoding input data (#2473)

* first pass ssz server for decoding deposit input data

* fix decoding

* revert viz change on helper

* add image target

* use /api prefix, add deployment for cluster

* fix lint

* standardize slot numbers (#2475)

* Add CORS for ssz api (#2476)

* first pass ssz server for decoding deposit input data

* fix decoding

* revert viz change on helper

* add image target

* use /api prefix, add deployment for cluster

* fix lint

* needed CORS

* Allow Client to Retrieve Multiple Validator Statuses (#2474)

* multiple validator statuses

* gazelle

* context

* fixing bugs

* remove old way of checking

* fix logging

* make activation queue more accurate

* fix rpc test

* add test

* fix remaining tests

* lint

* comment

* review comments

* Update Prysm README (#2477)

* README updated

* readme updates

* no err throw (#2479)

* Fix Status Nil Pointer Error (#2480)

* no err throw

* nil errors

* 3.175 (#2482)

* Better Error Message if Failing to Exit Initial Sync (#2483)

* no err throw

* nil errors

* better error on init sync

* Only Log Active Balances (#2485)

* only log active balance

* dont need ()

* change logging (#2487)

* fix chainstart waiting on rpc server (#2488)

* shift ticker to after activation (#2489)

* Add drain script (#2418)

* Add drain script

* Fix script to drain contracts from newest to oldest

* Add README

* remove comments

* Only after block 400k, look up by deposit event

* issue warn log on disconnecting peer instead of error (#2491)

* Display Only Active Validator Data (#2490)

* Fix Validator Status Field in RPC Server (#2492)

* fix status of key

* status test fix

* fmt

* Estimate the Time Till Follow Distance Is Completed (#2486)

* use estimation instead

* fix test

* fixing another test

* fix tests and preston's comments

* remove unused var

* fix condition

* Revert "fix condition"

This reverts commit dee0e3112c.

* dont return error

* add production config for testnet release (#2493)

* Lookup Validator Index in State in Status Check (#2494)

* state lookup

* refactor duplicate code

* refactor with mapping

* fix broken tests

* finish refactor

* merged master

* Starting, I need get_epoch_start_shard

* updated EpochCommitteeCount and fixed tests

* implemented ShardDelta

* test for ShardDelta

* implemented EpochStartShard

* added epoch out of bound test

* test for accurate start shard

* lint

* need to use changes from latest crosslinks

* added BaseReward and totalActiveBalance

* added test for base reward

* merged master

* all tests passing

* start testing

* done

* fixed tests

* addressed shay's feedback
2019-06-09 16:48:04 +08:00
Raul Jordan
c504931c3b Follow up on process block header v0.6 (#2666) 2019-06-09 16:47:26 +08:00
terence tsao
53dcc5e8d7 Add Process Registry for Epoch Processing (#2668)
* update update-process-registry

* added back the old tests

* fmt

* gaz
2019-06-09 16:46:56 +08:00
shayzluf
9ecd5d4c4e add ProcessBlockHeader v0.6 (#2534)
* add ProcessBlockHeader

* function has all its dependancies in place

* arange the basic ok test

* gazzele and skip test update

* skip wrong sig test

* fmt imports and change requests

* goimports fmt

* map for struct fields to be location independent

* reorder protobuf fields

* added tests

* gazzle fix

* few change requests fixes

* revert changes in types.proto

* revert changes in types

* fix tests

* fix lint

* fmt imports

* fix gazelle

* fix var naming

* pb update

* var naming

* tarance change request fixes

* fix test
2019-06-09 16:46:11 +08:00
terence tsao
d21dbca1af Implement Crosslink Delta Rewards for 0.6 (#2517)
* update process crosslink and update existing tests

* added a test case to cover no crosslink changes

* more test

* preston's feedback

* spellings

* ValidatorStatus Estimating Activation RPC Server (#2469)

* fix spacing

* working on position in queue

* fmt

* spacing

* feedback

* tests

* rename

* Only Perform Initial Sync With a Single Peer (#2471)

* fix spacing

* use send instead of broadcast in initial sync

* Fix Estimation of Deposit Inclusion Slot in ValidatorActivationStatus (#2472)

* fix spacing

* fix time estimates

* correct slot estimation

* naming

* Update beacon-chain/rpc/validator_server.go

Co-Authored-By: rauljordan <raul@prysmaticlabs.com>

* SSZ web api for decoding input data (#2473)

* first pass ssz server for decoding deposit input data

* fix decoding

* revert viz change on helper

* add image target

* use /api prefix, add deployment for cluster

* fix lint

* standardize slot numbers (#2475)

* Add CORS for ssz api (#2476)

* first pass ssz server for decoding deposit input data

* fix decoding

* revert viz change on helper

* add image target

* use /api prefix, add deployment for cluster

* fix lint

* needed CORS

* Allow Client to Retrieve Multiple Validator Statuses (#2474)

* multiple validator statuses

* gazelle

* context

* fixing bugs

* remove old way of checking

* fix logging

* make activation queue more accurate

* fix rpc test

* add test

* fix remaining tests

* lint

* comment

* review comments

* Update Prysm README (#2477)

* README updated

* readme updates

* no err throw (#2479)

* Fix Status Nil Pointer Error (#2480)

* no err throw

* nil errors

* 3.175 (#2482)

* Better Error Message if Failing to Exit Initial Sync (#2483)

* no err throw

* nil errors

* better error on init sync

* Only Log Active Balances (#2485)

* only log active balance

* dont need ()

* change logging (#2487)

* fix chainstart waiting on rpc server (#2488)

* shift ticker to after activation (#2489)

* Add drain script (#2418)

* Add drain script

* Fix script to drain contracts from newest to oldest

* Add README

* remove comments

* Only after block 400k, look up by deposit event

* issue warn log on disconnecting peer instead of error (#2491)

* Display Only Active Validator Data (#2490)

* Fix Validator Status Field in RPC Server (#2492)

* fix status of key

* status test fix

* fmt

* Estimate the Time Till Follow Distance Is Completed (#2486)

* use estimation instead

* fix test

* fixing another test

* fix tests and preston's comments

* remove unused var

* fix condition

* Revert "fix condition"

This reverts commit dee0e3112c.

* dont return error

* add production config for testnet release (#2493)

* Lookup Validator Index in State in Status Check (#2494)

* state lookup

* refactor duplicate code

* refactor with mapping

* fix broken tests

* finish refactor

* merged master

* Starting, I need get_epoch_start_shard

* updated EpochCommitteeCount and fixed tests

* implemented ShardDelta

* test for ShardDelta

* implemented EpochStartShard

* added epoch out of bound test

* test for accurate start shard

* lint

* need to use changes from latest crosslinks

* added BaseReward and totalActiveBalance

* added test for base reward

* merged master

* all tests passing

* start testing

* done
2019-06-09 16:45:31 +08:00
Raul Jordan
67878ec06a Process Block Deposits v0.6 (#2647)
* imports fixes

* deposits tests pass

* wrapped up gazelle

* spacing
2019-06-09 16:45:24 +08:00
Andrei Ivasko
ddf7a96aad Get attestation data slot v0.6 (#2593)
* attestation.go is ready, tests not

* ready for review

* fixing linter issues

* modified Crosslink and AttestationData proto fields to spec 2.0,marked deprecated fields

* gazelle

* fixed tests

* fixed error

* error msg
2019-06-09 16:44:46 +08:00
Raul Jordan
7beeec460c Process Block Eth1 Data v0.6 (#2645) 2019-06-09 16:44:16 +08:00
terence tsao
744affa75b Implement Process Crosslink From 0.6 (#2460) 2019-06-09 16:43:15 +08:00
Raul Jordan
86ff17337e Process Beacon Chain Transfers v0.6 (#2642)
* add transfers

* beacon transfer operations complete

* full cov

* transfer testing

* finished tests

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

Co-Authored-By: terence tsao <terence@prysmaticlabs.com>

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

Co-Authored-By: terence tsao <terence@prysmaticlabs.com>
2019-06-09 16:42:19 +08:00
terence tsao
b09ecec75e Finalize helper functions for 0.6 (#2632) 2019-06-09 16:42:04 +08:00
terence tsao
b26fe09351 Clean up Helper Functions Part 1 (#2612) 2019-06-09 16:40:43 +08:00
Andrei Ivasko
e181666982 Update processEth1Data for v0.6 (#2516) 2019-06-09 16:39:36 +08:00
Raul Jordan
3e63695e43 Update Block Processing Voluntary Exits (#2609) 2019-06-09 16:39:36 +08:00
shayzluf
233adc9bcd update to new spec (#2614) 2019-06-09 16:39:32 +08:00
terence tsao
07b5e52b52 Update Reward Helper v0.6 (#2470)
* added BaseReward

* added rewards helper

* added test for BaseReward

* extra space

* move exported function above
2019-06-09 16:38:46 +08:00
terence tsao
dc3e73ee5a Implement Final Updates 0.6 (#2562)
* ValidatorStatus Estimating Activation RPC Server (#2469)

* fix spacing

* working on position in queue

* fmt

* spacing

* feedback

* tests

* rename

* Only Perform Initial Sync With a Single Peer (#2471)

* fix spacing

* use send instead of broadcast in initial sync

* Fix Estimation of Deposit Inclusion Slot in ValidatorActivationStatus (#2472)

* fix spacing

* fix time estimates

* correct slot estimation

* naming

* Update beacon-chain/rpc/validator_server.go

Co-Authored-By: rauljordan <raul@prysmaticlabs.com>

* SSZ web api for decoding input data (#2473)

* first pass ssz server for decoding deposit input data

* fix decoding

* revert viz change on helper

* add image target

* use /api prefix, add deployment for cluster

* fix lint

* standardize slot numbers (#2475)

* Add CORS for ssz api (#2476)

* first pass ssz server for decoding deposit input data

* fix decoding

* revert viz change on helper

* add image target

* use /api prefix, add deployment for cluster

* fix lint

* needed CORS

* Allow Client to Retrieve Multiple Validator Statuses (#2474)

* multiple validator statuses

* gazelle

* context

* fixing bugs

* remove old way of checking

* fix logging

* make activation queue more accurate

* fix rpc test

* add test

* fix remaining tests

* lint

* comment

* review comments

* Update Prysm README (#2477)

* README updated

* readme updates

* no err throw (#2479)

* Fix Status Nil Pointer Error (#2480)

* no err throw

* nil errors

* 3.175 (#2482)

* Better Error Message if Failing to Exit Initial Sync (#2483)

* no err throw

* nil errors

* better error on init sync

* Only Log Active Balances (#2485)

* only log active balance

* dont need ()

* change logging (#2487)

* fix chainstart waiting on rpc server (#2488)

* shift ticker to after activation (#2489)

* Add drain script (#2418)

* Add drain script

* Fix script to drain contracts from newest to oldest

* Add README

* remove comments

* Only after block 400k, look up by deposit event

* issue warn log on disconnecting peer instead of error (#2491)

* Display Only Active Validator Data (#2490)

* Fix Validator Status Field in RPC Server (#2492)

* fix status of key

* status test fix

* fmt

* Estimate the Time Till Follow Distance Is Completed (#2486)

* use estimation instead

* fix test

* fixing another test

* fix tests and preston's comments

* remove unused var

* fix condition

* Revert "fix condition"

This reverts commit dee0e3112c.

* dont return error

* add production config for testnet release (#2493)

* Lookup Validator Index in State in Status Check (#2494)

* state lookup

* refactor duplicate code

* refactor with mapping

* fix broken tests

* finish refactor

* merged master

* updated EpochCommitteeCount and fixed tests

* implemented ShardDelta

* test for ShardDelta

* implemented EpochStartShard

* added epoch out of bound test

* test for accurate start shard

* lint

* implemented process_final_updates

* move to the top of the file

* add comment back

* gaz

* Test for process final updates

* fixed tests

* fixed all the tests
2019-06-09 16:38:46 +08:00
Raul Jordan
c774917749 Update Proposer/Attester Slashings and Slashing Helpers (#2603) 2019-06-09 16:38:46 +08:00
terence tsao
57bc1070f6 Implement Process Slashings for 0.6 (#2523) 2019-06-09 16:38:46 +08:00
terence tsao
67902e1977 Update Committee Helper Part 2 (#2592) 2019-06-09 16:38:39 +08:00
Ivan Martinez
cb63eca4f2 Update Committee Helpers to v0.6.0 (#2398) 2019-06-09 16:35:22 +08:00
shayzluf
6a26fb2465 update registry updates func (#2521)
* update registry updates func

* added tests and moved to epoch processing

* fixed naming issues
2019-06-09 16:32:16 +08:00
Nishant Das
1c0aa9438c changes name to signature (#2535) 2019-06-09 16:32:04 +08:00
shayzluf
129762a65f Add convert to indexed (#2519)
* sort participants slice

* add bitfield functions and tests

* added BitfieldBit test

* add AttestationParticipantsNew

* revert AttestationParticipants to its previous change

* add tests

* remove verifybitfieldnew

* fix tests and remove multiple tests

* remove duplicate test

* start work

* convert attestation to indexed attestations

* fix test for convert index

* remove calling getter

* add more tests

* remove underscore
2019-06-09 16:28:24 +08:00
terence tsao
d77c3e2dd6 Implement Justification and finalization Processing (#2448) 2019-06-09 16:28:24 +08:00
shayzluf
6fcf25c811 Update attesting indices v0.6 (#2449)
* sort participants slice

* add bitfield functions and tests

* added BitfieldBit test

* add AttestationParticipantsNew

* revert AttestationParticipants to its previous change

* add tests

* remove verifybitfieldnew

* fix tests and remove multiple tests

* remove duplicate test

* change magic number into ceildiv8
2019-06-09 16:28:24 +08:00
terence tsao
508c36a430 Update RPC end point for Proposer (#2767)
* add RequestBlock

* run mockgen

* implemented RequestBlock

* updated proto definitions

* updated tests

* updated validator attest tests

* done

* comment

* todo issue

* removed unused proto
2019-06-09 09:47:03 +08:00
terence tsao
7d1b304e8c Clean up Old RPC Endpoints (#2763) 2019-06-07 10:25:03 -04:00
terence tsao
5f1ec70e2b Tidying up Godoc for Core Package (#2762) 2019-06-06 17:16:15 -04:00
terence tsao
71eea358a1 Benchmark Process Block with Attestations (#2758) 2019-06-06 07:32:32 -04:00
Ivan Martinez
ebc0d67d1a Add graffiti and update generate seed (#2759) 2019-06-06 07:22:02 -04:00
Ivan Martinez
ed2fadc738 Cleanup and Docs update (#2756) 2019-06-05 04:40:24 -07:00
terence tsao
60aba6cebf Optimize Process Eth1 Data Vote (#2754) 2019-06-05 04:28:50 -07:00
terence tsao
f4ebbff4af removed deprecated configs (#2755) 2019-06-05 04:00:17 -07:00
terence tsao
cd1033c7f9 Optimize Base Reward Calculation (#2753)
* benchmark process epoch

* revert prof.out

* Add some optimizations

* beware where we use ActiveValidatorIndices...

* revert extra file

* gaz

* quick commit to get feedback

* revert extra file

* started fixing tests

* fixed broken TestProcessCrosslink_NoUpdate

* gaz

* cache randao seed

* fixed all the tests

* fmt and lint

* spacing

* Added todo

* lint

* revert binary file

* started regression test

* basic tests done

* using a fifo for active indices cache

* using a fifo for active count cache

* using a fifo for total balance cache

* using a fifo for active balance cache

* using a fifo for start shard cache

* using a fifo for seed cache

* gaz

* clean up

* fixing tests

* fixed all the core tests

* fixed all the tests!!!

* lint

* comment

* rm'ed commented code

* cache size to 1000 should be good enough

* optimized base reward

* revert binary file

* Added comments to calculate adjusted quotient outside
2019-06-04 20:05:07 +08:00
terence tsao
5a04d0d6bb Cache Active Validator Indices, Count, and Balances (#2737) 2019-06-03 21:18:07 -07:00
Ivan Martinez
901966c031 Fix most of skipped tests (#2735) 2019-06-01 22:23:53 -07:00
Ivan Martinez
2fb1f3d817 Remove Deprecated Validator Protobuf (#2727)
* Remove deprecated validator protos

* Fix to comments
2019-06-01 01:14:10 +08:00
Nishant Das
085962a848 change hash function (#2732) 2019-06-01 00:45:26 +08:00
Nishant Das
988b1fbfc5 Refactor Deposit Contract Test Setup (#2731)
* add new package

* fix all tests

* lint
2019-06-01 00:37:07 +08:00
terence tsao
5b4651748a Optimize Shuffled Indices Cache (#2728) 2019-05-30 23:46:52 -07:00
terence tsao
d36019d5ea Fixed Skipped Attestation Tests (#2730) 2019-05-30 23:21:43 -07:00
terence tsao
9d1989d473 Benchmark Compute Committee (#2698) 2019-05-30 23:10:38 -07:00
terence tsao
a685b461e3 Remove Committee Cache (#2729) 2019-05-30 22:56:57 -07:00
Nishant Das
7d5e7172d6 Fix Deposit Trie (#2686)
* remove deposit data

* remove deposit input

* fix references

* remove deposit helpers

* fix all refs

* gaz

* rgene proto

* fix all tests

* remove deposit data deprecated field

* fix remaining references

* fix all tests

* fix lint

* new tests with contract

* gaz

* more tests

* fixed bugs

* new test

* finally fixed it

* gaz

* fix test
2019-05-31 11:58:13 +08:00
Nishant Das
e099432551 Remove Latest Block (#2721)
* lint

* remove latest block

* lint

* add proto

* fix build
2019-05-30 13:47:32 +08:00
shayzluf
a562ece1c1 YAML shuffle tests for v0.6 (#2667)
* new shuffle tests

* added comment for exported function

* fix format and print

* added config files handling

* gazelle fix

* shuffle test debugging

* added shuffle list and benchmark

* hash function addition from nishant code

* gazelle fix

* remove unused function

* few minor changes

* add test to test protos optimization

* test a bigger list

* remove commented code

* small changes

* fix spec test and test indices to pass

* remove empty line

* abstraction of repeated code and comment arrangement

* terence change requests

* fix new test

* add small comment for better readability

* change from unshuflle to shuffle

* comment

* better comment

* fix all tests
2019-05-30 13:22:16 +08:00
terence tsao
18332ad929 Cache Shuffled Validator Indices (#2682) 2019-05-29 18:03:28 -07:00
terence tsao
32a0b8a5da Remove Deprecated Attestation Proto Fields (#2723) 2019-05-29 15:47:31 -07:00
Nishant Das
d3d6223b68 Sync With Master (#2718) 2019-05-29 07:39:48 -07:00
terence tsao
e7db3b2aa8 Remove Deprecated Beacon Block Proto Fields (#2717) 2019-05-28 07:09:27 -07:00
terence tsao
6bef43cda6 Remove Deprecated Protobuf Crosslink/Slashing/Block Fields (#2714) 2019-05-28 06:43:29 -07:00
terence tsao
6c0b9264e4 Remove Deprecated Protobuf State Fields (#2713) 2019-05-28 06:18:50 -07:00
Nishant Das
371c38916c Remove Obsolete Deposit Proto Objects (#2673)
* remove deposit data

* remove deposit input

* fix references

* remove deposit helpers

* fix all refs

* gaz

* rgene proto

* fix all tests

* remove deposit data deprecated field

* fix remaining references

* fix all tests

* fix lint

* regen proto

* fix test
2019-05-28 11:18:45 +08:00
terence tsao
65fe416b19 Fixed Skipped Tests for RPC Server (#2712) 2019-05-27 19:53:40 -07:00
Raul Jordan
6c1e74b3de Process Block Attestations v0.6 (#2650)
* attestation.go is ready, tests not

* ready for review

* fixing linter issues

* modified Crosslink and AttestationData proto fields to spec 2.0,marked deprecated fields

* gazelle

* fixed tests

* fixed error

* add att processing:

* process atts

* error msg

* finish process attestations logic

* spacing

* ssz move

* inclusion delay failure passing

* more attestation tests

* more att tests passing

* more tests

* ffg data mismatching test

* ffg tests complete

* gofmt

* fix testing to match attestation updates

* ssz

* lint
2019-05-27 00:11:36 -04:00
terence tsao
bc25747275 cleaned up skipped tests for core processing (#2697) 2019-05-25 22:08:38 -07:00
terence tsao
b9eab2a2cc Update CommitteeAssignment (#2693) 2019-05-25 21:44:04 -07:00
terence tsao
c34f2911ff Reorder Epoch Processing Functions (#2676) 2019-05-24 07:06:49 -07:00
terence tsao
6d86d0b3b9 Implement Process Epoch for 0.6 (#2675)
* can't find process j f functons

* implemented process_epoch

* tests done

* lint

* nishant's feedback

* stupid goland replace

* goimports
2019-05-24 15:14:03 +08:00
Nishant Das
855bf7cec9 Update Deposit Contract (#2648)
* lint

* add new contract

* change version

* remove log

* generating abi and binary files

* fix tests

* update to current version

* new changes

* add new hash function

* save hashed nodes

* add more things

* new method

* add update to trie

* new stuff

* gaz

* more stuff

* finally fixed build

* remove deposit data

* Revert "remove deposit data"

This reverts commit 9085409e91.

* more changes

* lint and gaz

* lint
2019-05-24 13:30:40 +08:00
Raul Jordan
c0c2671c5f Update Slot Processing and State Transition v0.6 (#2664)
* edit state transition to add slot processing logic, reorder logic

* fix build

* lint

* tests passing

* spacing

* tests pass

* imports

* passing tests
2019-05-21 19:56:40 -04:00
terence tsao
126e8d4487 Implement process_rewards_and_penalties for 0.6 (#2665)
* update process crosslink and update existing tests

* added a test case to cover no crosslink changes

* more test

* preston's feedback

* spellings

* ValidatorStatus Estimating Activation RPC Server (#2469)

* fix spacing

* working on position in queue

* fmt

* spacing

* feedback

* tests

* rename

* Only Perform Initial Sync With a Single Peer (#2471)

* fix spacing

* use send instead of broadcast in initial sync

* Fix Estimation of Deposit Inclusion Slot in ValidatorActivationStatus (#2472)

* fix spacing

* fix time estimates

* correct slot estimation

* naming

* Update beacon-chain/rpc/validator_server.go

Co-Authored-By: rauljordan <raul@prysmaticlabs.com>

* SSZ web api for decoding input data (#2473)

* first pass ssz server for decoding deposit input data

* fix decoding

* revert viz change on helper

* add image target

* use /api prefix, add deployment for cluster

* fix lint

* standardize slot numbers (#2475)

* Add CORS for ssz api (#2476)

* first pass ssz server for decoding deposit input data

* fix decoding

* revert viz change on helper

* add image target

* use /api prefix, add deployment for cluster

* fix lint

* needed CORS

* Allow Client to Retrieve Multiple Validator Statuses (#2474)

* multiple validator statuses

* gazelle

* context

* fixing bugs

* remove old way of checking

* fix logging

* make activation queue more accurate

* fix rpc test

* add test

* fix remaining tests

* lint

* comment

* review comments

* Update Prysm README (#2477)

* README updated

* readme updates

* no err throw (#2479)

* Fix Status Nil Pointer Error (#2480)

* no err throw

* nil errors

* 3.175 (#2482)

* Better Error Message if Failing to Exit Initial Sync (#2483)

* no err throw

* nil errors

* better error on init sync

* Only Log Active Balances (#2485)

* only log active balance

* dont need ()

* change logging (#2487)

* fix chainstart waiting on rpc server (#2488)

* shift ticker to after activation (#2489)

* Add drain script (#2418)

* Add drain script

* Fix script to drain contracts from newest to oldest

* Add README

* remove comments

* Only after block 400k, look up by deposit event

* issue warn log on disconnecting peer instead of error (#2491)

* Display Only Active Validator Data (#2490)

* Fix Validator Status Field in RPC Server (#2492)

* fix status of key

* status test fix

* fmt

* Estimate the Time Till Follow Distance Is Completed (#2486)

* use estimation instead

* fix test

* fixing another test

* fix tests and preston's comments

* remove unused var

* fix condition

* Revert "fix condition"

This reverts commit dee0e3112c.

* dont return error

* add production config for testnet release (#2493)

* Lookup Validator Index in State in Status Check (#2494)

* state lookup

* refactor duplicate code

* refactor with mapping

* fix broken tests

* finish refactor

* merged master

* Starting, I need get_epoch_start_shard

* updated EpochCommitteeCount and fixed tests

* implemented ShardDelta

* test for ShardDelta

* implemented EpochStartShard

* added epoch out of bound test

* test for accurate start shard

* lint

* need to use changes from latest crosslinks

* added BaseReward and totalActiveBalance

* added test for base reward

* implemented process_attestation_delta

* comments

* comments

* merged master

* all tests passing

* start testing

* done

* merged master

* fixed tests

* tests, more to come

* tests done

* lint

* spaces over tabs

* addressed shay's feedback

* starting but need to merge a few things...

* tests

* fmt
2019-05-21 19:07:42 -04:00
terence tsao
1127fc656e Implement Attestation Delta for v0.6 (#2646)
* update process crosslink and update existing tests

* added a test case to cover no crosslink changes

* more test

* preston's feedback

* spellings

* ValidatorStatus Estimating Activation RPC Server (#2469)

* fix spacing

* working on position in queue

* fmt

* spacing

* feedback

* tests

* rename

* Only Perform Initial Sync With a Single Peer (#2471)

* fix spacing

* use send instead of broadcast in initial sync

* Fix Estimation of Deposit Inclusion Slot in ValidatorActivationStatus (#2472)

* fix spacing

* fix time estimates

* correct slot estimation

* naming

* Update beacon-chain/rpc/validator_server.go

Co-Authored-By: rauljordan <raul@prysmaticlabs.com>

* SSZ web api for decoding input data (#2473)

* first pass ssz server for decoding deposit input data

* fix decoding

* revert viz change on helper

* add image target

* use /api prefix, add deployment for cluster

* fix lint

* standardize slot numbers (#2475)

* Add CORS for ssz api (#2476)

* first pass ssz server for decoding deposit input data

* fix decoding

* revert viz change on helper

* add image target

* use /api prefix, add deployment for cluster

* fix lint

* needed CORS

* Allow Client to Retrieve Multiple Validator Statuses (#2474)

* multiple validator statuses

* gazelle

* context

* fixing bugs

* remove old way of checking

* fix logging

* make activation queue more accurate

* fix rpc test

* add test

* fix remaining tests

* lint

* comment

* review comments

* Update Prysm README (#2477)

* README updated

* readme updates

* no err throw (#2479)

* Fix Status Nil Pointer Error (#2480)

* no err throw

* nil errors

* 3.175 (#2482)

* Better Error Message if Failing to Exit Initial Sync (#2483)

* no err throw

* nil errors

* better error on init sync

* Only Log Active Balances (#2485)

* only log active balance

* dont need ()

* change logging (#2487)

* fix chainstart waiting on rpc server (#2488)

* shift ticker to after activation (#2489)

* Add drain script (#2418)

* Add drain script

* Fix script to drain contracts from newest to oldest

* Add README

* remove comments

* Only after block 400k, look up by deposit event

* issue warn log on disconnecting peer instead of error (#2491)

* Display Only Active Validator Data (#2490)

* Fix Validator Status Field in RPC Server (#2492)

* fix status of key

* status test fix

* fmt

* Estimate the Time Till Follow Distance Is Completed (#2486)

* use estimation instead

* fix test

* fixing another test

* fix tests and preston's comments

* remove unused var

* fix condition

* Revert "fix condition"

This reverts commit dee0e3112c.

* dont return error

* add production config for testnet release (#2493)

* Lookup Validator Index in State in Status Check (#2494)

* state lookup

* refactor duplicate code

* refactor with mapping

* fix broken tests

* finish refactor

* merged master

* Starting, I need get_epoch_start_shard

* updated EpochCommitteeCount and fixed tests

* implemented ShardDelta

* test for ShardDelta

* implemented EpochStartShard

* added epoch out of bound test

* test for accurate start shard

* lint

* need to use changes from latest crosslinks

* added BaseReward and totalActiveBalance

* added test for base reward

* implemented process_attestation_delta

* comments

* comments

* merged master

* all tests passing

* start testing

* done

* merged master

* fixed tests

* tests, more to come

* tests done

* lint

* spaces over tabs

* addressed shay's feedback

* merged master
2019-05-21 14:57:25 -04:00
terence tsao
d8aada8258 Putting Crosslink Delta Back (#2654)
* update process crosslink and update existing tests

* added a test case to cover no crosslink changes

* more test

* preston's feedback

* spellings

* ValidatorStatus Estimating Activation RPC Server (#2469)

* fix spacing

* working on position in queue

* fmt

* spacing

* feedback

* tests

* rename

* Only Perform Initial Sync With a Single Peer (#2471)

* fix spacing

* use send instead of broadcast in initial sync

* Fix Estimation of Deposit Inclusion Slot in ValidatorActivationStatus (#2472)

* fix spacing

* fix time estimates

* correct slot estimation

* naming

* Update beacon-chain/rpc/validator_server.go

Co-Authored-By: rauljordan <raul@prysmaticlabs.com>

* SSZ web api for decoding input data (#2473)

* first pass ssz server for decoding deposit input data

* fix decoding

* revert viz change on helper

* add image target

* use /api prefix, add deployment for cluster

* fix lint

* standardize slot numbers (#2475)

* Add CORS for ssz api (#2476)

* first pass ssz server for decoding deposit input data

* fix decoding

* revert viz change on helper

* add image target

* use /api prefix, add deployment for cluster

* fix lint

* needed CORS

* Allow Client to Retrieve Multiple Validator Statuses (#2474)

* multiple validator statuses

* gazelle

* context

* fixing bugs

* remove old way of checking

* fix logging

* make activation queue more accurate

* fix rpc test

* add test

* fix remaining tests

* lint

* comment

* review comments

* Update Prysm README (#2477)

* README updated

* readme updates

* no err throw (#2479)

* Fix Status Nil Pointer Error (#2480)

* no err throw

* nil errors

* 3.175 (#2482)

* Better Error Message if Failing to Exit Initial Sync (#2483)

* no err throw

* nil errors

* better error on init sync

* Only Log Active Balances (#2485)

* only log active balance

* dont need ()

* change logging (#2487)

* fix chainstart waiting on rpc server (#2488)

* shift ticker to after activation (#2489)

* Add drain script (#2418)

* Add drain script

* Fix script to drain contracts from newest to oldest

* Add README

* remove comments

* Only after block 400k, look up by deposit event

* issue warn log on disconnecting peer instead of error (#2491)

* Display Only Active Validator Data (#2490)

* Fix Validator Status Field in RPC Server (#2492)

* fix status of key

* status test fix

* fmt

* Estimate the Time Till Follow Distance Is Completed (#2486)

* use estimation instead

* fix test

* fixing another test

* fix tests and preston's comments

* remove unused var

* fix condition

* Revert "fix condition"

This reverts commit dee0e3112c.

* dont return error

* add production config for testnet release (#2493)

* Lookup Validator Index in State in Status Check (#2494)

* state lookup

* refactor duplicate code

* refactor with mapping

* fix broken tests

* finish refactor

* merged master

* Starting, I need get_epoch_start_shard

* updated EpochCommitteeCount and fixed tests

* implemented ShardDelta

* test for ShardDelta

* implemented EpochStartShard

* added epoch out of bound test

* test for accurate start shard

* lint

* need to use changes from latest crosslinks

* added BaseReward and totalActiveBalance

* added test for base reward

* merged master

* all tests passing

* start testing

* done

* fixed tests

* addressed shay's feedback
2019-05-21 14:45:59 -04:00
Raul Jordan
967f3efc50 Follow up on process block header v0.6 (#2666) 2019-05-21 12:12:35 -05:00
terence tsao
0fa4197a9b Add Process Registry for Epoch Processing (#2668)
* update update-process-registry

* added back the old tests

* fmt

* gaz
2019-05-21 09:23:06 -04:00
shayzluf
95bc2ca224 add ProcessBlockHeader v0.6 (#2534)
* add ProcessBlockHeader

* function has all its dependancies in place

* arange the basic ok test

* gazzele and skip test update

* skip wrong sig test

* fmt imports and change requests

* goimports fmt

* map for struct fields to be location independent

* reorder protobuf fields

* added tests

* gazzle fix

* few change requests fixes

* revert changes in types.proto

* revert changes in types

* fix tests

* fix lint

* fmt imports

* fix gazelle

* fix var naming

* pb update

* var naming

* tarance change request fixes

* fix test
2019-05-21 04:17:25 +05:30
Preston Van Loon
ab35814d39 Genesis == zero (#2653) 2019-05-19 19:25:06 -04:00
terence tsao
3c9b099ae5 Implement Crosslink Delta Rewards for 0.6 (#2517)
* update process crosslink and update existing tests

* added a test case to cover no crosslink changes

* more test

* preston's feedback

* spellings

* ValidatorStatus Estimating Activation RPC Server (#2469)

* fix spacing

* working on position in queue

* fmt

* spacing

* feedback

* tests

* rename

* Only Perform Initial Sync With a Single Peer (#2471)

* fix spacing

* use send instead of broadcast in initial sync

* Fix Estimation of Deposit Inclusion Slot in ValidatorActivationStatus (#2472)

* fix spacing

* fix time estimates

* correct slot estimation

* naming

* Update beacon-chain/rpc/validator_server.go

Co-Authored-By: rauljordan <raul@prysmaticlabs.com>

* SSZ web api for decoding input data (#2473)

* first pass ssz server for decoding deposit input data

* fix decoding

* revert viz change on helper

* add image target

* use /api prefix, add deployment for cluster

* fix lint

* standardize slot numbers (#2475)

* Add CORS for ssz api (#2476)

* first pass ssz server for decoding deposit input data

* fix decoding

* revert viz change on helper

* add image target

* use /api prefix, add deployment for cluster

* fix lint

* needed CORS

* Allow Client to Retrieve Multiple Validator Statuses (#2474)

* multiple validator statuses

* gazelle

* context

* fixing bugs

* remove old way of checking

* fix logging

* make activation queue more accurate

* fix rpc test

* add test

* fix remaining tests

* lint

* comment

* review comments

* Update Prysm README (#2477)

* README updated

* readme updates

* no err throw (#2479)

* Fix Status Nil Pointer Error (#2480)

* no err throw

* nil errors

* 3.175 (#2482)

* Better Error Message if Failing to Exit Initial Sync (#2483)

* no err throw

* nil errors

* better error on init sync

* Only Log Active Balances (#2485)

* only log active balance

* dont need ()

* change logging (#2487)

* fix chainstart waiting on rpc server (#2488)

* shift ticker to after activation (#2489)

* Add drain script (#2418)

* Add drain script

* Fix script to drain contracts from newest to oldest

* Add README

* remove comments

* Only after block 400k, look up by deposit event

* issue warn log on disconnecting peer instead of error (#2491)

* Display Only Active Validator Data (#2490)

* Fix Validator Status Field in RPC Server (#2492)

* fix status of key

* status test fix

* fmt

* Estimate the Time Till Follow Distance Is Completed (#2486)

* use estimation instead

* fix test

* fixing another test

* fix tests and preston's comments

* remove unused var

* fix condition

* Revert "fix condition"

This reverts commit dee0e3112c.

* dont return error

* add production config for testnet release (#2493)

* Lookup Validator Index in State in Status Check (#2494)

* state lookup

* refactor duplicate code

* refactor with mapping

* fix broken tests

* finish refactor

* merged master

* Starting, I need get_epoch_start_shard

* updated EpochCommitteeCount and fixed tests

* implemented ShardDelta

* test for ShardDelta

* implemented EpochStartShard

* added epoch out of bound test

* test for accurate start shard

* lint

* need to use changes from latest crosslinks

* added BaseReward and totalActiveBalance

* added test for base reward

* merged master

* all tests passing

* start testing

* done
2019-05-19 12:09:53 -04:00
Raul Jordan
a62acd965d Process Block Deposits v0.6 (#2647)
* imports fixes

* deposits tests pass

* wrapped up gazelle

* spacing
2019-05-19 11:16:25 -04:00
Andrei Ivasko
aec8f398d9 Get attestation data slot v0.6 (#2593)
* attestation.go is ready, tests not

* ready for review

* fixing linter issues

* modified Crosslink and AttestationData proto fields to spec 2.0,marked deprecated fields

* gazelle

* fixed tests

* fixed error

* error msg
2019-05-19 10:48:18 -04:00
Raul Jordan
f0e1235910 Process Block Eth1 Data v0.6 (#2645) 2019-05-18 21:09:51 -04:00
terence tsao
4f3ab898bc Implement Process Crosslink From 0.6 (#2460) 2019-05-18 16:47:52 -04:00
Raul Jordan
fc325255fb Process Beacon Chain Transfers v0.6 (#2642)
* add transfers

* beacon transfer operations complete

* full cov

* transfer testing

* finished tests

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

Co-Authored-By: terence tsao <terence@prysmaticlabs.com>

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

Co-Authored-By: terence tsao <terence@prysmaticlabs.com>
2019-05-18 16:24:25 -04:00
terence tsao
097b147921 Removed Old Epoch Processing Functions (#2644)
* removed old epoch processing stuff

* gaz
2019-05-18 14:50:16 -04:00
terence tsao
98cc1e98c6 Finalize helper functions for 0.6 (#2632) 2019-05-17 19:01:07 -04:00
terence tsao
216469c8a0 Clean up Helper Functions Part 1 (#2612) 2019-05-17 11:43:30 -04:00
Andrei Ivasko
9bf2874f0f Update processEth1Data for v0.6 (#2516) 2019-05-16 12:38:19 -04:00
Raul Jordan
20a543507b Update Block Processing Voluntary Exits (#2609) 2019-05-16 11:19:45 -04:00
shayzluf
70ad16f58e update to new spec (#2614) 2019-05-16 05:31:48 -07:00
terence tsao
5ae4ced152 Update Reward Helper v0.6 (#2470)
* added BaseReward

* added rewards helper

* added test for BaseReward

* extra space

* move exported function above
2019-05-15 09:00:18 -05:00
terence tsao
169ffcd66f Implement Final Updates 0.6 (#2562)
* ValidatorStatus Estimating Activation RPC Server (#2469)

* fix spacing

* working on position in queue

* fmt

* spacing

* feedback

* tests

* rename

* Only Perform Initial Sync With a Single Peer (#2471)

* fix spacing

* use send instead of broadcast in initial sync

* Fix Estimation of Deposit Inclusion Slot in ValidatorActivationStatus (#2472)

* fix spacing

* fix time estimates

* correct slot estimation

* naming

* Update beacon-chain/rpc/validator_server.go

Co-Authored-By: rauljordan <raul@prysmaticlabs.com>

* SSZ web api for decoding input data (#2473)

* first pass ssz server for decoding deposit input data

* fix decoding

* revert viz change on helper

* add image target

* use /api prefix, add deployment for cluster

* fix lint

* standardize slot numbers (#2475)

* Add CORS for ssz api (#2476)

* first pass ssz server for decoding deposit input data

* fix decoding

* revert viz change on helper

* add image target

* use /api prefix, add deployment for cluster

* fix lint

* needed CORS

* Allow Client to Retrieve Multiple Validator Statuses (#2474)

* multiple validator statuses

* gazelle

* context

* fixing bugs

* remove old way of checking

* fix logging

* make activation queue more accurate

* fix rpc test

* add test

* fix remaining tests

* lint

* comment

* review comments

* Update Prysm README (#2477)

* README updated

* readme updates

* no err throw (#2479)

* Fix Status Nil Pointer Error (#2480)

* no err throw

* nil errors

* 3.175 (#2482)

* Better Error Message if Failing to Exit Initial Sync (#2483)

* no err throw

* nil errors

* better error on init sync

* Only Log Active Balances (#2485)

* only log active balance

* dont need ()

* change logging (#2487)

* fix chainstart waiting on rpc server (#2488)

* shift ticker to after activation (#2489)

* Add drain script (#2418)

* Add drain script

* Fix script to drain contracts from newest to oldest

* Add README

* remove comments

* Only after block 400k, look up by deposit event

* issue warn log on disconnecting peer instead of error (#2491)

* Display Only Active Validator Data (#2490)

* Fix Validator Status Field in RPC Server (#2492)

* fix status of key

* status test fix

* fmt

* Estimate the Time Till Follow Distance Is Completed (#2486)

* use estimation instead

* fix test

* fixing another test

* fix tests and preston's comments

* remove unused var

* fix condition

* Revert "fix condition"

This reverts commit dee0e3112c.

* dont return error

* add production config for testnet release (#2493)

* Lookup Validator Index in State in Status Check (#2494)

* state lookup

* refactor duplicate code

* refactor with mapping

* fix broken tests

* finish refactor

* merged master

* updated EpochCommitteeCount and fixed tests

* implemented ShardDelta

* test for ShardDelta

* implemented EpochStartShard

* added epoch out of bound test

* test for accurate start shard

* lint

* implemented process_final_updates

* move to the top of the file

* add comment back

* gaz

* Test for process final updates

* fixed tests

* fixed all the tests
2019-05-15 08:47:22 -05:00
Raul Jordan
ab72752422 Update Proposer/Attester Slashings and Slashing Helpers (#2603) 2019-05-15 06:26:24 -07:00
terence tsao
f8118e4599 Implement Process Slashings for 0.6 (#2523) 2019-05-15 06:15:07 -07:00
terence tsao
23de5ca6c4 Update Committee Helper Part 2 (#2592) 2019-05-14 21:02:34 -07:00
terence tsao
83b13a1602 Update Shard Helpers for 0.6 (#2497)
* ValidatorStatus Estimating Activation RPC Server (#2469)

* fix spacing

* working on position in queue

* fmt

* spacing

* feedback

* tests

* rename

* Only Perform Initial Sync With a Single Peer (#2471)

* fix spacing

* use send instead of broadcast in initial sync

* Fix Estimation of Deposit Inclusion Slot in ValidatorActivationStatus (#2472)

* fix spacing

* fix time estimates

* correct slot estimation

* naming

* Update beacon-chain/rpc/validator_server.go

Co-Authored-By: rauljordan <raul@prysmaticlabs.com>

* SSZ web api for decoding input data (#2473)

* first pass ssz server for decoding deposit input data

* fix decoding

* revert viz change on helper

* add image target

* use /api prefix, add deployment for cluster

* fix lint

* standardize slot numbers (#2475)

* Add CORS for ssz api (#2476)

* first pass ssz server for decoding deposit input data

* fix decoding

* revert viz change on helper

* add image target

* use /api prefix, add deployment for cluster

* fix lint

* needed CORS

* Allow Client to Retrieve Multiple Validator Statuses (#2474)

* multiple validator statuses

* gazelle

* context

* fixing bugs

* remove old way of checking

* fix logging

* make activation queue more accurate

* fix rpc test

* add test

* fix remaining tests

* lint

* comment

* review comments

* Update Prysm README (#2477)

* README updated

* readme updates

* no err throw (#2479)

* Fix Status Nil Pointer Error (#2480)

* no err throw

* nil errors

* 3.175 (#2482)

* Better Error Message if Failing to Exit Initial Sync (#2483)

* no err throw

* nil errors

* better error on init sync

* Only Log Active Balances (#2485)

* only log active balance

* dont need ()

* change logging (#2487)

* fix chainstart waiting on rpc server (#2488)

* shift ticker to after activation (#2489)

* Add drain script (#2418)

* Add drain script

* Fix script to drain contracts from newest to oldest

* Add README

* remove comments

* Only after block 400k, look up by deposit event

* issue warn log on disconnecting peer instead of error (#2491)

* Display Only Active Validator Data (#2490)

* Fix Validator Status Field in RPC Server (#2492)

* fix status of key

* status test fix

* fmt

* Estimate the Time Till Follow Distance Is Completed (#2486)

* use estimation instead

* fix test

* fixing another test

* fix tests and preston's comments

* remove unused var

* fix condition

* Revert "fix condition"

This reverts commit dee0e3112c.

* dont return error

* add production config for testnet release (#2493)

* Lookup Validator Index in State in Status Check (#2494)

* state lookup

* refactor duplicate code

* refactor with mapping

* fix broken tests

* finish refactor

* merged master

* updated EpochCommitteeCount and fixed tests

* implemented ShardDelta

* test for ShardDelta

* implemented EpochStartShard

* added epoch out of bound test

* test for accurate start shard

* lint
2019-05-14 15:44:12 -05:00
Ivan Martinez
c4c76c747c Update Committee Helpers to v0.6.0 (#2398) 2019-05-13 08:24:39 -07:00
terence tsao
d54bd42230 Rebase 0.6 with Master (#2563)
* ValidatorStatus Estimating Activation RPC Server (#2469)

* fix spacing

* working on position in queue

* fmt

* spacing

* feedback

* tests

* rename

* Only Perform Initial Sync With a Single Peer (#2471)

* fix spacing

* use send instead of broadcast in initial sync

* Fix Estimation of Deposit Inclusion Slot in ValidatorActivationStatus (#2472)

* fix spacing

* fix time estimates

* correct slot estimation

* naming

* Update beacon-chain/rpc/validator_server.go

Co-Authored-By: rauljordan <raul@prysmaticlabs.com>

* SSZ web api for decoding input data (#2473)

* first pass ssz server for decoding deposit input data

* fix decoding

* revert viz change on helper

* add image target

* use /api prefix, add deployment for cluster

* fix lint

* standardize slot numbers (#2475)

* Add CORS for ssz api (#2476)

* first pass ssz server for decoding deposit input data

* fix decoding

* revert viz change on helper

* add image target

* use /api prefix, add deployment for cluster

* fix lint

* needed CORS

* Allow Client to Retrieve Multiple Validator Statuses (#2474)

* multiple validator statuses

* gazelle

* context

* fixing bugs

* remove old way of checking

* fix logging

* make activation queue more accurate

* fix rpc test

* add test

* fix remaining tests

* lint

* comment

* review comments

* Update Prysm README (#2477)

* README updated

* readme updates

* no err throw (#2479)

* Fix Status Nil Pointer Error (#2480)

* no err throw

* nil errors

* 3.175 (#2482)

* Better Error Message if Failing to Exit Initial Sync (#2483)

* no err throw

* nil errors

* better error on init sync

* Only Log Active Balances (#2485)

* only log active balance

* dont need ()

* change logging (#2487)

* fix chainstart waiting on rpc server (#2488)

* shift ticker to after activation (#2489)

* Add drain script (#2418)

* Add drain script

* Fix script to drain contracts from newest to oldest

* Add README

* remove comments

* Only after block 400k, look up by deposit event

* issue warn log on disconnecting peer instead of error (#2491)

* Display Only Active Validator Data (#2490)

* Fix Validator Status Field in RPC Server (#2492)

* fix status of key

* status test fix

* fmt

* Estimate the Time Till Follow Distance Is Completed (#2486)

* use estimation instead

* fix test

* fixing another test

* fix tests and preston's comments

* remove unused var

* fix condition

* Revert "fix condition"

This reverts commit dee0e3112c.

* dont return error

* add production config for testnet release (#2493)

* Lookup Validator Index in State in Status Check (#2494)

* state lookup

* refactor duplicate code

* refactor with mapping

* fix broken tests

* finish refactor

* Fix Status Update Progression in RPC Server (#2495)

* fix status updates

* standardize logs in validator

* tests

* fix conditional

* Renovate Updates in Batch (#2505)

* Update com_github_atlassian_bazel_tools commit hash to 20cbdb1

* Update io_bazel_rules_k8s commit hash to 94e92d1

* Update prysm_testnet_site commit hash to b6c4983

* Update dependency com_github_jbenet_goprocess to v0.1.0

* Update dependency com_github_pkg_errors to v0.8.1

* Update dependency com_google_cloud_go to v0.38.0

* Update libp2p

* fixed

* add path for prylabs.net/ssz (#2508)

* Add GCP test configuration and p2p-host-ip flag (#2510)

* Add GCP startup script

* add flag for external IP

* specify that it must be for linux

* /deploy/create

* gofmt

* Canonical Blocks for Batch Block Request (#2511)

* only reply canonical block for reg sync

* CanonicalBlock test

* lint

* Use Single Code Path for Receiving Blocks and Fork Choice (#2514)

* insert canonical

* one path

* single entry

* travis

* lint

* Do Not Broadcast Attestations in Operations Service (#2509)

* no att broadcast

* broadcast in rpc but not operations

* fix space

* tests

* Revert "Renovate Updates in Batch (#2505)" (#2515)

This reverts commit 0e8ef07587.

* fix validator flags (#2518)

* Update Attestation Target for AttestHead (#2525)

* update attestation target for AttestHead

* fixed test

* fixed atts verification (#2527)

* delete failed pending atts (#2528)

* Do Not Subscribe to Blocks in Initial Sync (#2524)

* only sub to block batches

* batch sub remove

* tests

* fix lint

* gazelle

* delete old im mem blocks code

* Sort list before processing batched blocks (#2531)

* Revert "Canonical Blocks for Batch Block Request (#2511)" (#2532)

This reverts commit a818564b8d.

* Do Not Run Fork Choice on Block Proposals (#2526)

* removed unused doesParentExist (#2538)

* Sync Responds With Canonical Block Lists (#2539)

* first attempt at canonical blk list

* lint

* condition 1

* ctx w/ time out

* added canonical block list tests

* revert

* add to BeaconChainFlags

* dont use map, use proto

* attempt to use proto, take 1

* add run

* like canonical better than head

* removed unused

* Update proto/beacon/p2p/v1/messages.proto

Co-Authored-By: rauljordan <raul@prysmaticlabs.com>

* protos

* Check context has not expired before expensive operations (#2541)

* use ctx.Err for potentially expensive RPC methods, use batch for saving attestations

* more

* in sync too

* Update BUILD.bazel

* fix spacing

* enhance forkchoice log (#2537)

* add attestation data req cache (#2542)

* add attestation data req cache

* add tests

* godocs

* fix cache size gauge

* lint

* fix tests

* gazelle

* add more comments

* exclusive of finalized block

* Refactor DB Package to Enable Multiple Blocks/States at Slots (#2540)

* prefixed blocks blocked

* db refactor

* new historical state saving

* builds but tests fail

* more tests pass

* fix tests

* fix tests

* delete buf

* Update beacon-chain/db/block.go

Co-Authored-By: rauljordan <raul@prysmaticlabs.com>

* Update beacon-chain/db/block.go

Co-Authored-By: rauljordan <raul@prysmaticlabs.com>

* rem unused

* exclusive of finalized block (#2547)

* PreChainStart Activation Fix (#2544)

* fix activation

* remove logs

* remove logs

* revert change

* fix test

* Prevent Reorgs if Chain Head Does Not Change (#2548)

* revent reorgs if head does not change

* lint

* spacing

* Fetch Block Tree from Justified Block to Highest Observed Slot via RPC (#2549)

* test block tree req

* tree improvement

* use the right data

* block tree blocked by children func

* rem file

* imports

* add ctx

* imports

* mock

* check expired context

* added block root

* gazelle

* sace

* "Super sync" and naive p2p reputation (#2550)

* checkpoint on super sync with reputation

* ensure handling only expected peers msg

* exclusive of finalized block

* skip block saved already

* clean up struct

* remove 2 more fields

* _

* everything builds, but doesnt test yet

* lint

* fix p2p tests

* space

* space

* space

* fmt

* fmt

* Filter Canonical Attester for RPC (#2551)

* exclusive of finalized block

* add filter to only include canonical attestation

* comments

* grammer

* gaz

* typo

* fixed existing tests

* added test for IsAttCanonical

* add nil blocks test

* Can't save attestation target when head is nil (#2530)

* take care nil block

* warn to info

* preston's feedback

* Only marshal broadcast debug message when actually logging debug (#2553)

* fix broadcast debug message

* feedback

* Fix lint issues (#2554)

* fix broadcast debug message

* feedback

* imports

* lint

* Fix Logging in Validator Client (#2555)

* Use a prysm specific DHT protocol (#2558)

* use a prysm specific DHT

* gazelle

* space

* Fix BlockTree RPC Server Response (#2556)
2019-05-12 08:55:17 +08:00
Nishant Das
46fde662c8 Implement Self Signed Root in SSZ (#2520)
* add function

* add tests

* finally fixed it

* more changes

* assert slice type

* new changes

* add tests

* more test cases

* remove useless vars

* gazelle

* remove requirement

* shay's comments

* lint
2019-05-09 18:12:58 +08:00
shayzluf
59ae4260bf Update get domain and Fork to v0.6 (#2545)
* get_domain DomainVersion refactoring

* fix test to comply with new call

* remove forkutil

* remove forkdata

* fix nishant change requests
2019-05-09 17:23:56 +08:00
shayzluf
54184eb108 update registry updates func (#2521)
* update registry updates func

* added tests and moved to epoch processing

* fixed naming issues
2019-05-09 05:51:39 +05:30
Nishant Das
417a7ddf7a changes name to signature (#2535) 2019-05-08 06:10:41 -07:00
shayzluf
6a2591ff34 Add convert to indexed (#2519)
* sort participants slice

* add bitfield functions and tests

* added BitfieldBit test

* add AttestationParticipantsNew

* revert AttestationParticipants to its previous change

* add tests

* remove verifybitfieldnew

* fix tests and remove multiple tests

* remove duplicate test

* start work

* convert attestation to indexed attestations

* fix test for convert index

* remove calling getter

* add more tests

* remove underscore
2019-05-08 05:56:56 +05:30
terence tsao
fde0a7819b Implement Justification and finalization Processing (#2448) 2019-05-06 21:09:22 -07:00
shayzluf
4cec1b1e74 Update attesting indices v0.6 (#2449)
* sort participants slice

* add bitfield functions and tests

* added BitfieldBit test

* add AttestationParticipantsNew

* revert AttestationParticipants to its previous change

* add tests

* remove verifybitfieldnew

* fix tests and remove multiple tests

* remove duplicate test

* change magic number into ceildiv8
2019-05-07 08:39:53 +05:30
Nishant Das
2452266033 Update Genesis State Function to v0.6 (#2465)
* add pseudocode

* make changes

* fix all tests

* fix tests
2019-05-06 09:05:13 +08:00
terence tsao
49c70769cb Rebase Spec 0.6 with Master (#2496) 2019-05-05 16:56:22 -07:00
Preston Van Loon
f0c45f5011 merge master 2019-05-02 11:53:40 -04:00
Nishant Das
c87f71b303 Changes Names of Variables that aren't Actually Deprecated (#2466) 2019-05-02 05:54:42 -07:00
shayzluf
191cc9d1c5 Update bitfield helpers v0.6 (#2446)
* add bitfield functions and tests

* added BitfieldBit test

* remove verifybitfieldnew

* fix checkbit and tests

* change request fixes from nishant and terence

* nicer code by nishant
2019-05-01 13:04:00 +08:00
Nishant Das
c1fdfcd63c Update from Master (#2447) 2019-04-29 21:45:50 -07:00
shayzluf
6a245babba Update generateseed to 0.6 spec (#2371)
* update generateseed to 0.6 spec

* added fixes to active index to fix  tests

* fix comment and rewrote the assignment

* fix terence change requests

* remove extra space
2019-04-30 03:25:57 +05:30
Ivan Martinez
1af61109fb Add VerifyIndexedAttestation for v0.6 (#2385) 2019-04-29 14:13:27 -07:00
terence tsao
bb703e4ab7 Implement Crosslink Helpers (#2403) 2019-04-29 12:34:09 -07:00
shayzluf
7a44bd2873 Update active index root helpers (#2369) 2019-04-28 21:54:08 -07:00
terence tsao
dd09c5ed06 Implement Epoch Processing Helpers - Attesting Indices, Balances, Inclusion Slot... (#2393) 2019-04-27 10:29:39 -07:00
shayzluf
5d4780b746 PermutedIndex helper function (#2350)
* PermutedIndex helper function with Benchmark

* removed duplicate functions

* fix change requests by preston

* fix gazelle

* t.skip with todo as new yaml tests depands on compute commitee

* added new test yaml files for shuffling

* added comment for exported struct

* review comments

* review comments

* review comments

* change naming
2019-04-26 22:33:13 +08:00
terence tsao
f9dbbb8496 Implement Epoch Processing Helpers - Attestations Matching (#2379) 2019-04-26 07:11:07 -07:00
Nishant Das
4318d21872 Merge From Master (#2392) 2019-04-26 06:36:53 -07:00
shayzluf
6cdf27c356 Add split offset function v0.6 (#2365)
* add SplitOffset function and test that fails"

* use splitoffset in function

* Update beacon-chain/utils/shuffle_test.go

error format change

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

* add test
2019-04-26 18:00:49 +08:00
Ivan Martinez
cffe93e7b0 Update missing constants and some proto to v0.6 (#2388)
* Update missing constants and some proto to v0.6
2019-04-26 00:18:32 -04:00
terence tsao
4a71a37d34 Implement new initiate validator exit function (#2366) 2019-04-25 18:10:22 -07:00
shayzluf
0035a5f783 Update balance helpers v0.6 (#2348) 2019-04-24 18:31:05 -07:00
Ivan Martinez
f319ec7eb2 Update Randao Mix Helpers to v0.6 (#2357) 2019-04-24 14:40:42 -07:00
terence tsao
50708c961a Update Block & State Root Helpers (#2355) 2019-04-24 14:18:44 -07:00
terence tsao
792b52a03c Implement Validator Helpers (#2364) 2019-04-24 13:56:48 -07:00
Ivan Martinez
14698aee6b Update Validator Helpers to v0.6 (#2352) 2019-04-23 19:40:49 -07:00
terence tsao
fbdeae1792 Update Balances Related Helpers (#2356) 2019-04-23 11:17:54 -07:00
Ivan Martinez
4fc37fcf41 Add WithdrawableEpoch to Validiator (#2351)
* Add WithdrawableEpoch to Validiator

* Build proto
2019-04-23 06:52:48 -04:00
terence tsao
89cf5f5645 Update Beacon State Protobuf Field (#2341) 2019-04-22 21:39:28 -07:00
terence tsao
4172198ff4 Update DepositData and Validator Proto Fields (#2318) 2019-04-22 21:21:14 -07:00
terence tsao
bf97c6e1a2 Update Beacon Block Proto Fields (#2340) 2019-04-22 21:07:15 -07:00
terence tsao
e2ecbc3575 Update Historical Batch, Blk Header and Deposit Proto Fields (#2327) 2019-04-22 21:07:00 -07:00
Ivan Martinez
17147c7449 Update constants v0.6 (#2343)
* Update config to v0.6.0

* finish docs

* Add comment for deprecated fields

* Move deprecated lines
2019-04-22 23:59:20 -04:00
terence tsao
bb28b50c81 Update Block Operations Proto Fields (#2338)
* update attestation related protos

* use root for hash32

* fixed a few typos

* review comments

* update historical batch, deposit and blk header fields

* Add nogo to introduce built time linting (#2317)

* Add nogo and fix lint issues

* Run gazelle

* better gazelle

* ignore external struct tags

* Exclude all third party code from unsafeptr (#2321)

* Fix Assingments Bug (#2320)

* fix

* fix tests

* Add feature flag to toggle gossip sub in p2p (#2322)

* add feature flag to enable gossip sub in p2p

* invert the enable/disable logic

* add the flag in k8s and fix tests

* gazellle

* return empty config if nil

* Prevent Canceling Goroutines in Validator Client (#2324)

* do not cancel assignments goroutines

* exclude rule

* disable lostcancel for now

* Fix Pending Attestations RPC Call (#2304)

* pending atts

* use proposal slot

* attestation inclusion fix

* lint

* advance state transitions

* gazelle

* lint tests pass

* Do Not Update Validator Registry on Nil Block (#2326)

* no registry update if block is nil

* regression test

* lint

* Ensure Block Processing Failures Return an Error (#2325)

* ensure block failed processing returns an error

* fixed test

* test assertion corrected

* comments

* fix tests

* imports

* rebase

* add spec badge. Thanks to https://github.com/ChainSafe/lodestar/pull/166 for the idea :)

* Update Crosslink Protobuf Fields (#2313)

* rebase

* rebase

* rebase

* Prevent Canceling Goroutines in Validator Client (#2324)

* do not cancel assignments goroutines

* exclude rule

* disable lostcancel for now

* starting proposer slashing

* starting attester slashing

* revert gen file

* Update types.pb.go
2019-04-22 23:45:44 -04:00
terence tsao
a85612d155 Update Attestation Proto Fields (#2316)
* update attestation related protos

* use root for hash32

* fixed a few typos

* review comments

* revert genf ile
2019-04-22 23:40:19 -04:00
terence tsao
01f61664d8 Update Eth1data Protobuf Fields (#2315)
* update-eth1data

* use block root

* ops

* messed up crosslink

* review comments
2019-04-22 21:50:53 -04:00
Preston Van Loon
bae78a7f2c Merge branch 'master' of github.com:prysmaticlabs/prysm into spec-v0.6 2019-04-22 18:58:18 -04:00
Ivan Martinez
e913c73813 Update slot helpers v0.6 (#2345)
* Update config to v0.6.0

* finish docs

* Update slot helper docs to v0.6
2019-04-22 16:47:33 -05:00
Preston Van Loon
2cabf15525 Merge branch 'master' of github.com:prysmaticlabs/prysm into spec-v0.6 2019-04-22 10:21:56 -04:00
terence tsao
2b887bc01a Update Crosslink Protobuf Fields (#2313) 2019-04-20 17:00:05 -07:00
Preston Van Loon
92c6e854d5 add spec badge. Thanks to https://github.com/ChainSafe/lodestar/pull/166 for the idea :) 2019-04-20 12:19:25 -04:00
301 changed files with 25826 additions and 29066 deletions

View File

@@ -2,8 +2,7 @@
# across machines, developers, and workspaces.
#
# This config is loaded from https://github.com/bazelbuild/bazel-toolchains/blob/master/bazelrc/latest.bazelrc
build:remote-cache --remote_cache=remotebuildexecution.googleapis.com
build:remote-cache --tls_enabled=true
build:remote-cache --remote_cache=grpcs://remotebuildexecution.googleapis.com
build:remote-cache --remote_timeout=3600
build:remote-cache --auth_enabled=true
build:remote-cache --spawn_strategy=standalone
@@ -11,12 +10,22 @@ build:remote-cache --strategy=Javac=standalone
build:remote-cache --strategy=Closure=standalone
build:remote-cache --strategy=Genrule=standalone
# Build results backend.
build:remote-cache --bes_results_url="https://source.cloud.google.com/results/invocations/"
build:remote-cache --bes_backend=buildeventservice.googleapis.com
build:remote-cache --bes_timeout=60s
build:remote-cache --project_id=prysmaticlabs
build:remote-cache --bes_upload_mode=fully_async
# Prysm specific remote-cache properties.
build:remote-cache --disk_cache=
build:remote-cache --jobs=50
build:remote-cache --host_platform_remote_properties_override='properties:{name:\"cache-silo-key\" value:\"prysm\"}'
build:remote-cache --remote_instance_name=projects/prysmaticlabs/instances/default_instance
build:remote-cache --experimental_remote_download_outputs=minimal
build:remote-cache --experimental_inmemory_jdeps_files
build:remote-cache --experimental_inmemory_dotd_files
# Import workspace options.
import %workspace%/.bazelrc
@@ -31,5 +40,7 @@ build --curses=yes --color=yes
build --keep_going
build --test_output=errors
build --flaky_test_attempts=5
build --jobs=50
test --local_test_jobs=2
# Disabled race detection due to unstable test results under constrained environment build kite
# build --features=race

View File

View File

@@ -1,18 +0,0 @@
{
"extends": "solium:recommended",
"plugins": [
"security"
],
"rules": {
"quotes": [
"error",
"double"
],
"security/no-inline-assembly": ["warning"],
"indentation": [
"error",
4
]
}
}

View File

@@ -1,6 +1,7 @@
# Prysm: Ethereum 'Serenity' 2.0 Go Implementation
[![Build status](https://badge.buildkite.com/b555891daf3614bae4284dcf365b2340cefc0089839526f096.svg?branch=master)](https://buildkite.com/prysmatic-labs/prysm)
[![ETH2.0_Spec_Version 0.8.0](https://img.shields.io/badge/ETH2.0%20Spec%20Version-v0.8.0-blue.svg)](https://github.com/ethereum/eth2.0-specs/commit/8d324b7497bcb558e0183a30002d78d18704e3fa)
[![Discord](https://user-images.githubusercontent.com/7288322/34471967-1df7808a-efbb-11e7-9088-ed0b04151291.png)](https://discord.gg/KSA7rPr)
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/prysmaticlabs/geth-sharding?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)

View File

@@ -1,4 +1,5 @@
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
http_archive(
name = "bazel_skylib",
@@ -33,12 +34,6 @@ http_archive(
url = "https://github.com/bazelbuild/rules_docker/archive/v0.7.0.tar.gz",
)
http_archive(
name = "build_bazel_rules_nodejs",
sha256 = "1db950bbd27fb2581866e307c0130983471d4c3cd49c46063a2503ca7b6770a4",
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/0.29.0/rules_nodejs-0.29.0.tar.gz"],
)
http_archive(
name = "io_bazel_rules_k8s",
sha256 = "f37af27b3825dbaa811bcf4c3fcab581437fc0bd777e86468f19604ca2e99c6b",
@@ -46,6 +41,21 @@ http_archive(
url = "https://github.com/bazelbuild/rules_k8s/archive/60571086ea6e10b1ddd2512d5c0fd32d01fa5701.tar.gz",
)
# Override default import in rules_go with special patch until
# https://github.com/gogo/protobuf/pull/582 is merged.
git_repository(
name = "com_github_gogo_protobuf",
commit = "ba06b47c162d49f2af050fb4c75bcbc86a159d5c", # v1.2.1, as of 2019-03-03
patch_args = ["-p1"],
patches = [
"@io_bazel_rules_go//third_party:com_github_gogo_protobuf-gazelle.patch",
"//third_party:com_github_gogo_protobuf-equal.patch",
],
remote = "https://github.com/gogo/protobuf",
shallow_since = "1550471403 +0200",
# gazelle args: -go_prefix github.com/gogo/protobuf -proto legacy
)
load(
"@io_bazel_rules_docker//repositories:repositories.bzl",
container_repositories = "repositories",
@@ -53,16 +63,6 @@ load(
container_repositories()
load("@build_bazel_rules_nodejs//:defs.bzl", "node_repositories", "yarn_install")
node_repositories()
yarn_install(
name = "npm",
package_json = "//:package.json",
yarn_lock = "//:yarn.lock",
)
# This requires rules_docker to be fully instantiated before it is pulled in.
load("@io_bazel_rules_k8s//k8s:k8s.bzl", "k8s_defaults", "k8s_repositories")
@@ -140,8 +140,8 @@ filegroup(
visibility = ["//visibility:public"],
)
""",
sha256 = "56847989737e816ab7d23f3bb2422347dfa81271bae81a94de512c01461fab25",
url = "https://github.com/prysmaticlabs/eth2.0-spec-tests/releases/download/v0.7.1/base64_encoded_archive.tar.gz",
sha256 = "4be3a1a065abd46534b5b67d77be76de6ce6dbed27bffe8fcf1b3b6f4a11d9d5",
url = "https://github.com/prysmaticlabs/eth2.0-spec-tests/releases/download/v0.8.0/base64_encoded_archive.tar.gz",
)
http_archive(
@@ -154,17 +154,6 @@ load("@com_github_bazelbuild_buildtools//buildifier:deps.bzl", "buildifier_depen
buildifier_dependencies()
http_archive(
name = "com_github_prysmaticlabs_go_ssz",
sha256 = "f6fd5d623a988337810b956ddaf612dce771d9d0f9256934c8f4b1379f1cb2f6",
strip_prefix = "go-ssz-2e84733edbac32aca6d47feafc4441e43b10047f",
url = "https://github.com/prysmaticlabs/go-ssz/archive/2e84733edbac32aca6d47feafc4441e43b10047f.tar.gz",
)
load("@com_github_prysmaticlabs_go_ssz//:deps.bzl", "go_ssz_dependencies")
go_ssz_dependencies()
go_repository(
name = "com_github_golang_mock",
commit = "51421b967af1f557f93a59e0057aaf15ca02e29c", # v1.2.0
@@ -186,6 +175,12 @@ go_repository(
vcs = "git",
)
go_repository(
name = "com_github_prysmaticlabs_go_ssz",
commit = "08374e459d08fc6abeb43011a206ad54602e71b6",
importpath = "github.com/prysmaticlabs/go-ssz",
)
go_repository(
name = "com_github_urfave_cli",
commit = "cfb38830724cc34fedffe9a2a29fb54fa9169cd1", # v1.20.0
@@ -1103,3 +1098,19 @@ go_repository(
commit = "4afad1f6206cb9222914f2ec6ab9d0b414705c54",
importpath = "github.com/libp2p/go-eventbus",
)
go_repository(
name = "in_gopkg_d4l3k_messagediff_v1",
commit = "29f32d820d112dbd66e58492a6ffb7cc3106312b",
importpath = "gopkg.in/d4l3k/messagediff.v1",
)
go_repository(
name = "com_github_prysmaticlabs_go_bitfield",
commit = "ec88cc4d1d143cad98308da54b73d0cdb04254eb",
importpath = "github.com/prysmaticlabs/go-bitfield",
)
load("@com_github_prysmaticlabs_go_ssz//:deps.bzl", "go_ssz_dependencies")
go_ssz_dependencies()

View File

@@ -64,7 +64,7 @@ container_push(
image = ":image",
registry = "gcr.io",
repository = "prysmaticlabs/prysm/beacon-chain",
tag = "latest",
tag = "{DOCKER_TAG}",
tags = ["manual"],
visibility = ["//visibility:private"],
)

View File

@@ -9,15 +9,11 @@ go_library(
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/attestation",
visibility = ["//beacon-chain:__subpackages__"],
deps = [
"//beacon-chain/cache:go_default_library",
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/core/state:go_default_library",
"//beacon-chain/db:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//shared/bitutil:go_default_library",
"//shared/bytesutil:go_default_library",
"//shared/event:go_default_library",
"//shared/hashutil:go_default_library",
"//shared/messagehandler:go_default_library",
"//shared/params:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
@@ -33,13 +29,13 @@ go_test(
srcs = ["service_test.go"],
embed = [":go_default_library"],
deps = [
"//beacon-chain/cache:go_default_library",
"//beacon-chain/internal:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//shared/bytesutil:go_default_library",
"//shared/hashutil:go_default_library",
"//shared/params:go_default_library",
"//shared/testutil:go_default_library",
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
],

View File

@@ -4,26 +4,20 @@ package attestation
import (
"context"
"fmt"
"sort"
"sync"
"github.com/gogo/protobuf/proto"
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
"github.com/prysmaticlabs/prysm/beacon-chain/db"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/bitutil"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/event"
"github.com/prysmaticlabs/prysm/shared/hashutil"
handler "github.com/prysmaticlabs/prysm/shared/messagehandler"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/sirupsen/logrus"
)
var log = logrus.WithField("prefix", "attestation")
var committeeCache = cache.NewCommitteesCache()
// TargetHandler provides an interface for fetching latest attestation targets
// and updating attestations in batches.
@@ -87,7 +81,7 @@ func (a *Service) Stop() error {
}
// Status always returns nil.
// TODO(1201): Add service health checks.
// TODO(#1201): Add service health checks.
func (a *Service) Status() error {
return nil
}
@@ -106,10 +100,10 @@ func (a *Service) IncomingAttestationFeed() *event.Feed {
// BeaconBlock` be the target block in the attestation
// `get_latest_attestation(store, validator_index)`.
func (a *Service) LatestAttestationTarget(beaconState *pb.BeaconState, index uint64) (*pb.AttestationTarget, error) {
if index >= uint64(len(beaconState.ValidatorRegistry)) {
if index >= uint64(len(beaconState.Validators)) {
return nil, fmt.Errorf("invalid validator index %d", index)
}
validator := beaconState.ValidatorRegistry[index]
validator := beaconState.Validators[index]
pubKey := bytesutil.ToBytes48(validator.Pubkey)
a.store.RLock()
@@ -122,7 +116,7 @@ func (a *Service) LatestAttestationTarget(beaconState *pb.BeaconState, index uin
if attestation == nil {
return nil, nil
}
targetRoot := bytesutil.ToBytes32(attestation.Data.BeaconBlockRootHash32)
targetRoot := bytesutil.ToBytes32(attestation.Data.BeaconBlockRoot)
if !a.beaconDB.HasBlock(targetRoot) {
return nil, nil
}
@@ -162,11 +156,14 @@ func (a *Service) handleAttestation(ctx context.Context, msg proto.Message) erro
// This sets the pool limit, once the old pool is cleared out. It does by using the number of active
// validators per slot as an estimate. The active indices here are not used in the actual processing
// of attestations.
activeIndices := helpers.ActiveValidatorIndices(state.ValidatorRegistry, helpers.CurrentEpoch(state))
attPerSlot := len(activeIndices) / int(params.BeaconConfig().SlotsPerEpoch)
count, err := helpers.ActiveValidatorCount(state, helpers.CurrentEpoch(state))
if err != nil {
return err
}
attPerSlot := count / params.BeaconConfig().SlotsPerEpoch
// we only set the limit at 70% of the calculated amount to be safe so that relevant attestations
// arent carried over to the next batch.
a.poolLimit = attPerSlot * 7 / 10
a.poolLimit = int(attPerSlot) * 7 / 10
if a.poolLimit == 0 {
a.poolLimit++
}
@@ -190,15 +187,7 @@ func (a *Service) UpdateLatestAttestation(ctx context.Context, attestation *pb.A
if err != nil {
return err
}
head, err := a.beaconDB.ChainHead()
if err != nil {
return err
}
headRoot, err := hashutil.HashBeaconBlock(head)
if err != nil {
return err
}
return a.updateAttestation(ctx, headRoot, beaconState, attestation)
return a.updateAttestation(beaconState, attestation)
}
// BatchUpdateLatestAttestation updates multiple attestations and adds them into the attestation store
@@ -214,19 +203,9 @@ func (a *Service) BatchUpdateLatestAttestation(ctx context.Context, attestations
if err != nil {
return err
}
head, err := a.beaconDB.ChainHead()
if err != nil {
return err
}
headRoot, err := hashutil.HashBeaconBlock(head)
if err != nil {
return err
}
attestations = a.sortAttestations(attestations)
for _, attestation := range attestations {
if err := a.updateAttestation(ctx, headRoot, beaconState, attestation); err != nil {
if err := a.updateAttestation(beaconState, attestation); err != nil {
log.Error(err)
}
}
@@ -242,91 +221,53 @@ func (a *Service) InsertAttestationIntoStore(pubkey [48]byte, att *pb.Attestatio
a.store.m[pubkey] = att
}
func (a *Service) updateAttestation(ctx context.Context, headRoot [32]byte, beaconState *pb.BeaconState,
attestation *pb.Attestation) error {
func (a *Service) updateAttestation(beaconState *pb.BeaconState, attestation *pb.Attestation) error {
totalAttestationSeen.Inc()
slot := attestation.Data.Slot
var committee []uint64
var cachedCommittees *cache.CommitteesInSlot
var err error
for beaconState.Slot < slot {
beaconState, err = state.ExecuteStateTransition(
ctx, beaconState, nil /* block */, headRoot, state.DefaultConfig(),
)
if err != nil {
return fmt.Errorf("could not execute head transition: %v", err)
}
}
cachedCommittees, err = committeeCache.CommitteesInfoBySlot(slot)
committee, err := helpers.CrosslinkCommittee(beaconState, helpers.CurrentEpoch(beaconState), attestation.Data.Crosslink.Shard)
if err != nil {
return err
}
if cachedCommittees == nil {
crosslinkCommittees, err := helpers.CrosslinkCommitteesAtSlot(beaconState, slot, false /* registryChange */)
if err != nil {
return err
}
cachedCommittees = helpers.ToCommitteeCache(slot, crosslinkCommittees)
if err := committeeCache.AddCommittees(cachedCommittees); err != nil {
return err
}
slot, err := helpers.AttestationDataSlot(beaconState, attestation.Data)
if err != nil {
return fmt.Errorf("could not get attestation slot: %v", err)
}
// Find committee for shard.
for _, v := range cachedCommittees.Committees {
if v.Shard == attestation.Data.Shard {
committee = v.Committee
break
}
}
log.WithFields(logrus.Fields{
"attestationSlot": attestation.Data.Slot - params.BeaconConfig().GenesisSlot,
"attestationShard": attestation.Data.Shard,
"committeesShard": cachedCommittees.Committees[0].Shard,
"committeesList": cachedCommittees.Committees[0].Committee,
"lengthOfCommittees": len(cachedCommittees.Committees),
"attestationSlot": slot,
"attestationShard": attestation.Data.Crosslink.Shard,
"committeesList": committee,
"lengthOfCommittees": len(committee),
}).Debug("Updating latest attestation")
// The participation bitfield from attestation is represented in bytes,
// here we multiply by 8 to get an accurate validator count in bits.
bitfield := attestation.AggregationBitfield
totalBits := len(bitfield) * 8
// Check each bit of participation bitfield to find out which
// attester has submitted new attestation.
// This is has O(n) run time and could be optimized down the line.
for i := 0; i < totalBits; i++ {
bitSet, err := bitutil.CheckBit(bitfield, i)
if err != nil {
return err
}
if !bitSet {
for i := uint64(0); i < attestation.AggregationBits.Len(); i++ {
if !attestation.AggregationBits.BitAt(i) {
continue
}
if i >= len(committee) {
log.Debugf("bitfield points to an invalid index in the committee: bitfield %08b", bitfield)
if i >= uint64(len(committee)) {
// This should never happen.
log.Warnf("bitfield points to an invalid index in the committee: bitfield %08b", attestation.AggregationBits)
return nil
}
if int(committee[i]) >= len(beaconState.ValidatorRegistry) {
log.Debugf("index doesn't exist in validator registry: index %d", committee[i])
if int(committee[i]) >= len(beaconState.Validators) {
// This should never happen.
log.Warnf("index doesn't exist in validator registry: index %d", committee[i])
return nil
}
// If the attestation came from this attester. We use the slot committee to find the
// validator's actual index.
pubkey := bytesutil.ToBytes48(beaconState.ValidatorRegistry[committee[i]].Pubkey)
newAttestationSlot := attestation.Data.Slot
pubkey := bytesutil.ToBytes48(beaconState.Validators[committee[i]].Pubkey)
newAttestationSlot := slot
currentAttestationSlot := uint64(0)
a.store.Lock()
defer a.store.Unlock()
if _, exists := a.store.m[pubkey]; exists {
currentAttestationSlot = a.store.m[pubkey].Data.Slot
currentAttestationSlot = slot
}
// If the attestation is newer than this attester's one in pool.
if newAttestationSlot > currentAttestationSlot {
@@ -334,12 +275,12 @@ func (a *Service) updateAttestation(ctx context.Context, headRoot [32]byte, beac
log.WithFields(
logrus.Fields{
"attestationSlot": attestation.Data.Slot - params.BeaconConfig().GenesisSlot,
"justifiedEpoch": attestation.Data.JustifiedEpoch - params.BeaconConfig().GenesisEpoch,
"attestationSlot": slot,
"sourceEpoch": attestation.Data.Source.Epoch,
},
).Debug("Attestation store updated")
blockRoot := bytesutil.ToBytes32(attestation.Data.BeaconBlockRootHash32)
blockRoot := bytesutil.ToBytes32(attestation.Data.BeaconBlockRoot)
votedBlock, err := a.beaconDB.Block(blockRoot)
if err != nil {
return err
@@ -349,12 +290,3 @@ func (a *Service) updateAttestation(ctx context.Context, headRoot [32]byte, beac
}
return nil
}
// sortAttestations sorts attestations by their slot number in ascending order.
func (a *Service) sortAttestations(attestations []*pb.Attestation) []*pb.Attestation {
sort.SliceStable(attestations, func(i, j int) bool {
return attestations[i].Data.Slot < attestations[j].Data.Slot
})
return attestations
}

View File

@@ -4,15 +4,14 @@ import (
"bytes"
"context"
"fmt"
"reflect"
"strings"
"testing"
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
"github.com/prysmaticlabs/go-bitfield"
"github.com/prysmaticlabs/go-ssz"
"github.com/prysmaticlabs/prysm/beacon-chain/internal"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/hashutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/sirupsen/logrus"
@@ -34,63 +33,67 @@ func TestUpdateLatestAttestation_UpdatesLatest(t *testing.T) {
for i := 0; i < 64; i++ {
validators = append(validators, &pb.Validator{
Pubkey: []byte{byte(i)},
ActivationEpoch: params.BeaconConfig().GenesisEpoch,
ExitEpoch: params.BeaconConfig().GenesisEpoch + 10,
ActivationEpoch: 0,
ExitEpoch: 10,
})
}
beaconState := &pb.BeaconState{
Slot: params.BeaconConfig().GenesisSlot + 1,
ValidatorRegistry: validators,
Slot: 1,
Validators: validators,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
}
block := &pb.BeaconBlock{
Slot: params.BeaconConfig().GenesisSlot + 1,
Slot: 1,
}
if err := beaconDB.SaveBlock(block); err != nil {
t.Fatal(err)
}
beaconState.LatestBlock = block
if err := beaconDB.UpdateChainHead(ctx, block, beaconState); err != nil {
t.Fatal(err)
}
service := NewAttestationService(context.Background(), &Config{BeaconDB: beaconDB})
attestation := &pb.Attestation{
AggregationBitfield: []byte{0x80},
AggregationBits: bitfield.Bitlist{0x03},
Data: &pb.AttestationData{
Slot: params.BeaconConfig().GenesisSlot + 1,
Shard: 1,
Crosslink: &pb.Crosslink{
Shard: 1,
},
Target: &pb.Checkpoint{},
Source: &pb.Checkpoint{},
},
}
if err := service.UpdateLatestAttestation(ctx, attestation); err != nil {
t.Fatalf("could not update latest attestation: %v", err)
}
pubkey := bytesutil.ToBytes48([]byte{byte(3)})
if service.store.m[pubkey].Data.Slot !=
attestation.Data.Slot {
t.Errorf("Incorrect slot stored, wanted: %d, got: %d",
attestation.Data.Slot, service.store.m[pubkey].Data.Slot)
pubkey := bytesutil.ToBytes48(beaconState.Validators[10].Pubkey)
if service.store.m[pubkey].Data.Crosslink.Shard !=
attestation.Data.Crosslink.Shard {
t.Errorf("Incorrect shard stored, wanted: %d, got: %d",
attestation.Data.Crosslink.Shard, service.store.m[pubkey].Data.Crosslink.Shard)
}
beaconState = &pb.BeaconState{
Slot: params.BeaconConfig().GenesisSlot + 36,
ValidatorRegistry: validators,
Slot: 36,
Validators: validators,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
}
beaconState.LatestBlock = block
if err := beaconDB.UpdateChainHead(ctx, block, beaconState); err != nil {
t.Fatalf("could not save state: %v", err)
}
attestation.Data.Slot = params.BeaconConfig().GenesisSlot + 36
attestation.Data.Shard = 36
attestation.Data.Crosslink.Shard = 36
if err := service.UpdateLatestAttestation(ctx, attestation); err != nil {
t.Fatalf("could not update latest attestation: %v", err)
}
if service.store.m[pubkey].Data.Slot !=
attestation.Data.Slot {
t.Errorf("Incorrect slot stored, wanted: %d, got: %d",
attestation.Data.Slot, service.store.m[pubkey].Data.Slot)
if service.store.m[pubkey].Data.Crosslink.Shard !=
attestation.Data.Crosslink.Shard {
t.Errorf("Incorrect shard stored, wanted: %d, got: %d",
attestation.Data.Crosslink.Shard, service.store.m[pubkey].Data.Crosslink.Shard)
}
}
@@ -103,31 +106,31 @@ func TestAttestationPool_UpdatesAttestationPool(t *testing.T) {
for i := 0; i < 64; i++ {
validators = append(validators, &pb.Validator{
Pubkey: []byte{byte(i)},
ActivationEpoch: params.BeaconConfig().GenesisEpoch,
ExitEpoch: params.BeaconConfig().GenesisEpoch + 10,
ActivationEpoch: 0,
ExitEpoch: 10,
})
}
beaconState := &pb.BeaconState{
Slot: params.BeaconConfig().GenesisSlot + 1,
ValidatorRegistry: validators,
Slot: 1,
Validators: validators,
}
block := &pb.BeaconBlock{
Slot: params.BeaconConfig().GenesisSlot + 1,
Slot: 1,
}
if err := beaconDB.SaveBlock(block); err != nil {
t.Fatal(err)
}
beaconState.LatestBlock = block
if err := beaconDB.UpdateChainHead(ctx, block, beaconState); err != nil {
t.Fatal(err)
}
service := NewAttestationService(context.Background(), &Config{BeaconDB: beaconDB})
attestation := &pb.Attestation{
AggregationBitfield: []byte{0x80},
AggregationBits: bitfield.Bitlist{0x80, 0x01},
Data: &pb.AttestationData{
Slot: params.BeaconConfig().GenesisSlot + 1,
Shard: 1,
Crosslink: &pb.Crosslink{
Shard: 1,
},
},
}
@@ -142,8 +145,7 @@ func TestLatestAttestationTarget_CantGetAttestation(t *testing.T) {
ctx := context.Background()
if err := beaconDB.SaveState(ctx, &pb.BeaconState{
ValidatorRegistry: []*pb.Validator{{}},
LatestBlock: &pb.BeaconBlock{Slot: params.BeaconConfig().GenesisSlot},
Validators: []*pb.Validator{{}},
}); err != nil {
t.Fatalf("could not save state: %v", err)
}
@@ -167,8 +169,7 @@ func TestLatestAttestationTarget_ReturnsLatestAttestedBlock(t *testing.T) {
pubKey := []byte{'A'}
if err := beaconDB.SaveState(ctx, &pb.BeaconState{
ValidatorRegistry: []*pb.Validator{{Pubkey: pubKey}},
LatestBlock: &pb.BeaconBlock{Slot: params.BeaconConfig().GenesisSlot},
Validators: []*pb.Validator{{Pubkey: pubKey}},
}); err != nil {
t.Fatalf("could not save state: %v", err)
}
@@ -177,7 +178,7 @@ func TestLatestAttestationTarget_ReturnsLatestAttestedBlock(t *testing.T) {
if err := beaconDB.SaveBlock(block); err != nil {
t.Fatalf("could not save block: %v", err)
}
blockRoot, err := hashutil.HashBeaconBlock(block)
blockRoot, err := ssz.SigningRoot(block)
if err != nil {
log.Fatalf("could not hash block: %v", err)
}
@@ -193,7 +194,7 @@ func TestLatestAttestationTarget_ReturnsLatestAttestedBlock(t *testing.T) {
attestation := &pb.Attestation{
Data: &pb.AttestationData{
BeaconBlockRootHash32: blockRoot[:],
BeaconBlockRoot: blockRoot[:],
}}
pubKey48 := bytesutil.ToBytes48(pubKey)
service.store.m[pubKey48] = attestation
@@ -213,159 +214,6 @@ func TestLatestAttestationTarget_ReturnsLatestAttestedBlock(t *testing.T) {
}
}
func TestUpdateLatestAttestation_CacheEnabledAndMiss(t *testing.T) {
beaconDB := internal.SetupDB(t)
defer internal.TeardownDB(t, beaconDB)
ctx := context.Background()
var validators []*pb.Validator
for i := 0; i < 64; i++ {
validators = append(validators, &pb.Validator{
Pubkey: []byte{byte(i)},
ActivationEpoch: params.BeaconConfig().GenesisEpoch,
ExitEpoch: params.BeaconConfig().GenesisEpoch + 10,
})
}
beaconState := &pb.BeaconState{
Slot: params.BeaconConfig().GenesisSlot + 1,
ValidatorRegistry: validators,
}
block := &pb.BeaconBlock{
Slot: params.BeaconConfig().GenesisSlot + 1,
}
if err := beaconDB.SaveBlock(block); err != nil {
t.Fatal(err)
}
beaconState.LatestBlock = block
if err := beaconDB.UpdateChainHead(ctx, block, beaconState); err != nil {
t.Fatal(err)
}
service := NewAttestationService(context.Background(), &Config{BeaconDB: beaconDB})
attestation := &pb.Attestation{
AggregationBitfield: []byte{0x80},
Data: &pb.AttestationData{
Slot: params.BeaconConfig().GenesisSlot + 1,
Shard: 1,
},
}
if err := service.UpdateLatestAttestation(ctx, attestation); err != nil {
t.Fatalf("could not update latest attestation: %v", err)
}
pubkey := bytesutil.ToBytes48([]byte{byte(3)})
if service.store.m[pubkey].Data.Slot !=
attestation.Data.Slot {
t.Errorf("Incorrect slot stored, wanted: %d, got: %d",
attestation.Data.Slot, service.store.m[pubkey].Data.Slot)
}
attestation.Data.Slot = params.BeaconConfig().GenesisSlot + 36
attestation.Data.Shard = 36
beaconState = &pb.BeaconState{
Slot: params.BeaconConfig().GenesisSlot + 36,
ValidatorRegistry: validators,
}
beaconState.LatestBlock = block
if err := beaconDB.UpdateChainHead(ctx, block, beaconState); err != nil {
t.Fatalf("could not save state: %v", err)
}
if err := service.UpdateLatestAttestation(ctx, attestation); err != nil {
t.Fatalf("could not update latest attestation: %v", err)
}
if service.store.m[pubkey].Data.Slot !=
attestation.Data.Slot {
t.Errorf("Incorrect slot stored, wanted: %d, got: %d",
attestation.Data.Slot, service.store.m[pubkey].Data.Slot)
}
// Verify the committee for attestation's data slot was cached.
fetchedCommittees, err := committeeCache.CommitteesInfoBySlot(attestation.Data.Slot)
if err != nil {
t.Fatal(err)
}
wantedCommittee := []uint64{38}
if !reflect.DeepEqual(wantedCommittee, fetchedCommittees.Committees[0].Committee) {
t.Errorf(
"Result indices was an unexpected value. Wanted %d, got %d",
wantedCommittee,
fetchedCommittees.Committees[0].Committee,
)
}
}
func TestUpdateLatestAttestation_CacheEnabledAndHit(t *testing.T) {
var validators []*pb.Validator
for i := 0; i < 64; i++ {
validators = append(validators, &pb.Validator{
Pubkey: []byte{byte(i)},
ActivationEpoch: params.BeaconConfig().GenesisEpoch,
ExitEpoch: params.BeaconConfig().GenesisEpoch + 10,
})
}
beaconDB := internal.SetupDB(t)
defer internal.TeardownDB(t, beaconDB)
ctx := context.Background()
beaconState := &pb.BeaconState{
Slot: params.BeaconConfig().GenesisSlot + 2,
ValidatorRegistry: validators,
}
block := &pb.BeaconBlock{
Slot: params.BeaconConfig().GenesisSlot + 2,
}
if err := beaconDB.SaveBlock(block); err != nil {
t.Fatal(err)
}
beaconState.LatestBlock = block
if err := beaconDB.UpdateChainHead(ctx, block, beaconState); err != nil {
t.Fatal(err)
}
service := NewAttestationService(context.Background(), &Config{BeaconDB: beaconDB})
slot := params.BeaconConfig().GenesisSlot + 2
shard := uint64(3)
index := uint64(4)
attestation := &pb.Attestation{
AggregationBitfield: []byte{0x80},
Data: &pb.AttestationData{
Slot: slot,
Shard: shard,
},
}
csInSlot := &cache.CommitteesInSlot{
Slot: slot,
Committees: []*cache.CommitteeInfo{
{Shard: shard, Committee: []uint64{index, 999}},
}}
if err := committeeCache.AddCommittees(csInSlot); err != nil {
t.Fatal(err)
}
if err := service.UpdateLatestAttestation(ctx, attestation); err != nil {
t.Fatalf("could not update latest attestation: %v", err)
}
pubkey := bytesutil.ToBytes48([]byte{byte(index)})
if err := service.UpdateLatestAttestation(ctx, attestation); err != nil {
t.Fatalf("could not update latest attestation: %v", err)
}
if service.store.m[pubkey].Data.Slot !=
attestation.Data.Slot {
t.Errorf("Incorrect slot stored, wanted: %d, got: %d",
attestation.Data.Slot, service.store.m[pubkey].Data.Slot)
}
}
func TestUpdateLatestAttestation_InvalidIndex(t *testing.T) {
beaconDB := internal.SetupDB(t)
hook := logTest.NewGlobal()
@@ -376,31 +224,35 @@ func TestUpdateLatestAttestation_InvalidIndex(t *testing.T) {
for i := 0; i < 64; i++ {
validators = append(validators, &pb.Validator{
Pubkey: []byte{byte(i)},
ActivationEpoch: params.BeaconConfig().GenesisEpoch,
ExitEpoch: params.BeaconConfig().GenesisEpoch + 10,
ActivationEpoch: 0,
ExitEpoch: 10,
})
}
beaconState := &pb.BeaconState{
Slot: params.BeaconConfig().GenesisSlot + 1,
ValidatorRegistry: validators,
Slot: 1,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
Validators: validators,
}
block := &pb.BeaconBlock{
Slot: params.BeaconConfig().GenesisSlot + 1,
Slot: 1,
}
if err := beaconDB.SaveBlock(block); err != nil {
t.Fatal(err)
}
beaconState.LatestBlock = block
if err := beaconDB.UpdateChainHead(ctx, block, beaconState); err != nil {
t.Fatal(err)
}
service := NewAttestationService(context.Background(), &Config{BeaconDB: beaconDB})
attestation := &pb.Attestation{
AggregationBitfield: []byte{0xC0},
AggregationBits: bitfield.Bitlist{0xC0, 0x01},
Data: &pb.AttestationData{
Slot: params.BeaconConfig().GenesisSlot + 1,
Shard: 1,
Crosslink: &pb.Crosslink{
Shard: 1,
},
Target: &pb.Checkpoint{},
Source: &pb.Checkpoint{},
},
}
@@ -419,25 +271,30 @@ func TestBatchUpdate_FromSync(t *testing.T) {
ctx := context.Background()
var validators []*pb.Validator
var latestRandaoMixes [][]byte
var latestActiveIndexRoots [][]byte
for i := 0; i < 64; i++ {
validators = append(validators, &pb.Validator{
Pubkey: []byte{byte(i)},
ActivationEpoch: params.BeaconConfig().GenesisEpoch,
ExitEpoch: params.BeaconConfig().GenesisEpoch + 10,
ActivationEpoch: 0,
ExitEpoch: 10,
})
latestRandaoMixes = append(latestRandaoMixes, []byte{'A'})
latestActiveIndexRoots = append(latestActiveIndexRoots, []byte{'B'})
}
beaconState := &pb.BeaconState{
Slot: params.BeaconConfig().GenesisSlot + 1,
ValidatorRegistry: validators,
Slot: 1,
Validators: validators,
RandaoMixes: latestRandaoMixes,
ActiveIndexRoots: latestActiveIndexRoots,
}
block := &pb.BeaconBlock{
Slot: params.BeaconConfig().GenesisSlot + 1,
Slot: 1,
}
if err := beaconDB.SaveBlock(block); err != nil {
t.Fatal(err)
}
beaconState.LatestBlock = block
if err := beaconDB.UpdateChainHead(ctx, block, beaconState); err != nil {
t.Fatal(err)
}
@@ -445,10 +302,13 @@ func TestBatchUpdate_FromSync(t *testing.T) {
service.poolLimit = 9
for i := 0; i < 10; i++ {
attestation := &pb.Attestation{
AggregationBitfield: []byte{0x80},
AggregationBits: bitfield.Bitlist{0x80},
Data: &pb.AttestationData{
Slot: params.BeaconConfig().GenesisSlot + 1,
Shard: 1,
Target: &pb.Checkpoint{Epoch: 2},
Source: &pb.Checkpoint{},
Crosslink: &pb.Crosslink{
Shard: 1,
},
},
}
if err := service.handleAttestation(ctx, attestation); err != nil {
@@ -469,22 +329,23 @@ func TestUpdateLatestAttestation_BatchUpdate(t *testing.T) {
for i := 0; i < 64; i++ {
validators = append(validators, &pb.Validator{
Pubkey: []byte{byte(i)},
ActivationEpoch: params.BeaconConfig().GenesisEpoch,
ExitEpoch: params.BeaconConfig().GenesisEpoch + 10,
ActivationEpoch: 0,
ExitEpoch: 10,
})
}
beaconState := &pb.BeaconState{
Slot: params.BeaconConfig().GenesisSlot + 1,
ValidatorRegistry: validators,
Slot: 1,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
Validators: validators,
}
block := &pb.BeaconBlock{
Slot: params.BeaconConfig().GenesisSlot + 1,
Slot: 1,
}
if err := beaconDB.SaveBlock(block); err != nil {
t.Fatal(err)
}
beaconState.LatestBlock = block
if err := beaconDB.UpdateChainHead(ctx, block, beaconState); err != nil {
t.Fatal(err)
}
@@ -492,10 +353,13 @@ func TestUpdateLatestAttestation_BatchUpdate(t *testing.T) {
attestations := make([]*pb.Attestation, 0)
for i := 0; i < 10; i++ {
attestations = append(attestations, &pb.Attestation{
AggregationBitfield: []byte{0x80},
AggregationBits: bitfield.Bitlist{0x80, 0x01},
Data: &pb.AttestationData{
Slot: params.BeaconConfig().GenesisSlot + 1,
Shard: 1,
Crosslink: &pb.Crosslink{
Shard: 1,
},
Target: &pb.Checkpoint{},
Source: &pb.Checkpoint{},
},
})
}

View File

@@ -6,7 +6,6 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/params"
)
var (
@@ -37,7 +36,6 @@ func reportVoteMetrics(index uint64, block *pb.BeaconBlock) {
return
}
s := params.BeaconConfig().GenesisSlot
validatorLastVoteGauge.WithLabelValues(
"v" + strconv.Itoa(int(index))).Set(float64(block.Slot - s))
"v" + strconv.Itoa(int(index))).Set(float64(block.Slot))
}

View File

@@ -23,12 +23,11 @@ go_library(
"//shared/bytesutil:go_default_library",
"//shared/event:go_default_library",
"//shared/featureconfig:go_default_library",
"//shared/hashutil:go_default_library",
"//shared/p2p:go_default_library",
"//shared/params:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"@com_github_prometheus_client_golang//prometheus:go_default_library",
"@com_github_prometheus_client_golang//prometheus/promauto:go_default_library",
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@io_opencensus_go//trace:go_default_library",
],
@@ -36,7 +35,7 @@ go_library(
go_test(
name = "go_default_test",
size = "small",
size = "medium",
srcs = [
"block_processing_test.go",
"fork_choice_reorg_test.go",
@@ -59,7 +58,6 @@ go_test(
"//shared/bytesutil:go_default_library",
"//shared/event:go_default_library",
"//shared/featureconfig:go_default_library",
"//shared/forkutil:go_default_library",
"//shared/hashutil:go_default_library",
"//shared/p2p:go_default_library",
"//shared/params:go_default_library",
@@ -69,6 +67,7 @@ go_test(
"@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_ethereum_go_ethereum//core/types:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
],

View File

@@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"github.com/prysmaticlabs/go-ssz"
b "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
@@ -14,8 +15,6 @@ import (
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/event"
"github.com/prysmaticlabs/prysm/shared/featureconfig"
"github.com/prysmaticlabs/prysm/shared/hashutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/sirupsen/logrus"
"go.opencensus.io/trace"
)
@@ -33,7 +32,7 @@ type BlockReceiver interface {
// to beacon blocks and generating a new beacon state from the Ethereum 2.0 core primitives.
type BlockProcessor interface {
VerifyBlockValidity(ctx context.Context, block *pb.BeaconBlock, beaconState *pb.BeaconState) error
ApplyBlockStateTransition(ctx context.Context, block *pb.BeaconBlock, beaconState *pb.BeaconState) (*pb.BeaconState, error)
AdvanceState(ctx context.Context, beaconState *pb.BeaconState, block *pb.BeaconBlock) (*pb.BeaconState, error)
CleanupBlockOperations(ctx context.Context, block *pb.BeaconBlock) error
}
@@ -58,7 +57,7 @@ func (c *ChainService) ReceiveBlock(ctx context.Context, block *pb.BeaconBlock)
defer c.receiveBlockLock.Unlock()
ctx, span := trace.StartSpan(ctx, "beacon-chain.blockchain.ReceiveBlock")
defer span.End()
parentRoot := bytesutil.ToBytes32(block.ParentRootHash32)
parentRoot := bytesutil.ToBytes32(block.ParentRoot)
parent, err := c.beaconDB.Block(parentRoot)
if err != nil {
return nil, fmt.Errorf("failed to get parent block: %v", err)
@@ -70,9 +69,8 @@ func (c *ChainService) ReceiveBlock(ctx context.Context, block *pb.BeaconBlock)
if err != nil {
return nil, fmt.Errorf("could not retrieve beacon state: %v", err)
}
saveLatestBlock := beaconState.LatestBlock
blockRoot, err := hashutil.HashBeaconBlock(block)
blockRoot, err := ssz.SigningRoot(block)
if err != nil {
return nil, fmt.Errorf("could not hash beacon block")
}
@@ -85,15 +83,15 @@ func (c *ChainService) ReceiveBlock(ctx context.Context, block *pb.BeaconBlock)
if err := c.SaveAndBroadcastBlock(ctx, block); err != nil {
return beaconState, fmt.Errorf(
"could not save and broadcast beacon block with slot %d: %v",
block.Slot-params.BeaconConfig().GenesisSlot, err,
block.Slot, err,
)
}
log.WithField("slotNumber", block.Slot-params.BeaconConfig().GenesisSlot).Info(
log.WithField("slotNumber", block.Slot).Info(
"Executing state transition")
// We then apply the block state transition accordingly to obtain the resulting beacon state.
beaconState, err = c.ApplyBlockStateTransition(ctx, block, beaconState)
beaconState, err = c.AdvanceState(ctx, beaconState, block)
if err != nil {
switch err.(type) {
case *BlockFailedProcessingErr:
@@ -109,21 +107,18 @@ func (c *ChainService) ReceiveBlock(ctx context.Context, block *pb.BeaconBlock)
}
log.WithFields(logrus.Fields{
"slotNumber": block.Slot - params.BeaconConfig().GenesisSlot,
"currentEpoch": helpers.SlotToEpoch(block.Slot) - params.BeaconConfig().GenesisEpoch,
"slotNumber": block.Slot,
"currentEpoch": helpers.SlotToEpoch(block.Slot),
}).Info("State transition complete")
// Check state root
if featureconfig.FeatureConfig().EnableCheckBlockStateRoot {
// Calc state hash with previous block
beaconState.LatestBlock = saveLatestBlock
stateRoot, err := hashutil.HashProto(beaconState)
stateRoot, err := ssz.HashTreeRoot(beaconState)
if err != nil {
return nil, fmt.Errorf("could not hash beacon state: %v", err)
}
beaconState.LatestBlock = block
if !bytes.Equal(block.StateRootHash32, stateRoot[:]) {
return nil, fmt.Errorf("beacon state root is not equal to block state root: %#x != %#x", stateRoot, block.StateRootHash32)
if !bytes.Equal(block.StateRoot, stateRoot[:]) {
return nil, fmt.Errorf("beacon state root is not equal to block state root: %#x != %#x", stateRoot, block.StateRoot)
}
}
@@ -133,53 +128,7 @@ func (c *ChainService) ReceiveBlock(ctx context.Context, block *pb.BeaconBlock)
return beaconState, fmt.Errorf("could not process block deposits, attestations, and other operations: %v", err)
}
log.WithField("slot", block.Slot-params.BeaconConfig().GenesisSlot).Info("Finished processing beacon block")
return beaconState, nil
}
// ApplyBlockStateTransition runs the Ethereum 2.0 state transition function
// to produce a new beacon state and also accounts for skip slots occurring.
//
// def apply_block_state_transition(block):
// # process skipped slots
// while (state.slot < block.slot - 1):
// state = slot_state_transition(state, block=None)
//
// # process slot with block
// state = slot_state_transition(state, block)
//
// # check state root
// if block.state_root == hash(state):
// return state, error
// else:
// return nil, error # or throw or whatever
//
func (c *ChainService) ApplyBlockStateTransition(
ctx context.Context, block *pb.BeaconBlock, beaconState *pb.BeaconState,
) (*pb.BeaconState, error) {
// Retrieve the last processed beacon block's hash root.
headRoot, err := c.ChainHeadRoot()
if err != nil {
return beaconState, fmt.Errorf("could not retrieve chain head root: %v", err)
}
// Check for skipped slots.
numSkippedSlots := 0
for beaconState.Slot < block.Slot-1 {
beaconState, err = c.runStateTransition(ctx, headRoot, nil, beaconState)
if err != nil {
return beaconState, err
}
numSkippedSlots++
}
if numSkippedSlots > 0 {
log.Warnf("Processed %d skipped slots", numSkippedSlots)
}
beaconState, err = c.runStateTransition(ctx, headRoot, block, beaconState)
if err != nil {
return beaconState, err
}
log.WithField("slot", block.Slot).Info("Finished processing beacon block")
return beaconState, nil
}
@@ -194,9 +143,9 @@ func (c *ChainService) VerifyBlockValidity(
block *pb.BeaconBlock,
beaconState *pb.BeaconState,
) error {
if block.Slot == params.BeaconConfig().GenesisSlot {
if block.Slot == 0 {
return fmt.Errorf("cannot process a genesis block: received block with slot %d",
block.Slot-params.BeaconConfig().GenesisSlot)
block.Slot)
}
powBlockFetcher := c.web3Service.Client().BlockByHash
if err := b.IsValidBlock(ctx, beaconState, block,
@@ -210,7 +159,7 @@ func (c *ChainService) VerifyBlockValidity(
// peers via p2p. Blocks which have already been saved are not processed again via p2p, which is why
// the order of operations is important in this function to prevent infinite p2p loops.
func (c *ChainService) SaveAndBroadcastBlock(ctx context.Context, block *pb.BeaconBlock) error {
blockRoot, err := hashutil.HashBeaconBlock(block)
blockRoot, err := ssz.SigningRoot(block)
if err != nil {
return fmt.Errorf("could not tree hash incoming block: %v", err)
}
@@ -220,7 +169,7 @@ func (c *ChainService) SaveAndBroadcastBlock(ctx context.Context, block *pb.Beac
if err := c.beaconDB.SaveAttestationTarget(ctx, &pb.AttestationTarget{
Slot: block.Slot,
BlockRoot: blockRoot[:],
ParentRoot: block.ParentRootHash32,
ParentRoot: block.ParentRoot,
}); err != nil {
return fmt.Errorf("failed to save attestation target: %v", err)
}
@@ -253,21 +202,19 @@ func (c *ChainService) CleanupBlockOperations(ctx context.Context, block *pb.Bea
return nil
}
// runStateTransition executes the Ethereum 2.0 core state transition for the beacon chain and
// AdvanceState executes the Ethereum 2.0 core state transition for the beacon chain and
// updates important checkpoints and local persistent data during epoch transitions. It serves as a wrapper
// around the more low-level, core state transition function primitive.
func (c *ChainService) runStateTransition(
func (c *ChainService) AdvanceState(
ctx context.Context,
headRoot [32]byte,
block *pb.BeaconBlock,
beaconState *pb.BeaconState,
block *pb.BeaconBlock,
) (*pb.BeaconState, error) {
finalizedEpoch := beaconState.FinalizedEpoch
finalizedEpoch := beaconState.FinalizedCheckpoint.Epoch
newState, err := state.ExecuteStateTransition(
ctx,
beaconState,
block,
headRoot,
&state.TransitionConfig{
VerifySignatures: false, // We disable signature verification for now.
Logging: true, // We enable logging in this state transition call.
@@ -276,20 +223,22 @@ func (c *ChainService) runStateTransition(
if err != nil {
return beaconState, &BlockFailedProcessingErr{err}
}
// Prune the block cache on every new finalized epoch.
if newState.FinalizedEpoch > finalizedEpoch {
// Prune the block cache and helper caches on every new finalized epoch.
if newState.FinalizedCheckpoint.Epoch > finalizedEpoch {
helpers.ClearAllCaches()
c.beaconDB.ClearBlockCache()
}
log.WithField(
"slotsSinceGenesis", newState.Slot-params.BeaconConfig().GenesisSlot,
"slotsSinceGenesis", newState.Slot,
).Info("Slot transition successfully processed")
if block != nil {
log.WithField(
"slotsSinceGenesis", newState.Slot-params.BeaconConfig().GenesisSlot,
"slotsSinceGenesis", newState.Slot,
).Info("Block transition successfully processed")
blockRoot, err := hashutil.HashBeaconBlock(block)
blockRoot, err := ssz.SigningRoot(block)
if err != nil {
return nil, err
}
@@ -313,7 +262,7 @@ func (c *ChainService) runStateTransition(
return newState, fmt.Errorf("could not update FFG checkpts: %v", err)
}
log.WithField(
"SlotsSinceGenesis", newState.Slot-params.BeaconConfig().GenesisSlot,
"SlotsSinceGenesis", newState.Slot,
).Info("Epoch transition successfully processed")
}
return newState, nil
@@ -329,11 +278,11 @@ func (c *ChainService) saveValidatorIdx(state *pb.BeaconState) error {
for _, idx := range activatedValidators {
// If for some reason the activated validator indices is not in state,
// we skip them and save them to process for next epoch.
if int(idx) >= len(state.ValidatorRegistry) {
if int(idx) >= len(state.Validators) {
idxNotInState = append(idxNotInState, idx)
continue
}
pubKey := state.ValidatorRegistry[idx].Pubkey
pubKey := state.Validators[idx].Pubkey
if err := c.beaconDB.SaveValidatorIndex(pubKey, int(idx)); err != nil {
return fmt.Errorf("could not save validator index: %v", err)
}
@@ -351,7 +300,7 @@ func (c *ChainService) saveValidatorIdx(state *pb.BeaconState) error {
func (c *ChainService) deleteValidatorIdx(state *pb.BeaconState) error {
exitedValidators := validators.ExitedValFromEpoch(helpers.CurrentEpoch(state) + 1)
for _, idx := range exitedValidators {
pubKey := state.ValidatorRegistry[idx].Pubkey
pubKey := state.Validators[idx].Pubkey
if err := c.beaconDB.DeleteValidatorIndex(pubKey); err != nil {
return fmt.Errorf("could not delete validator index: %v", err)
}

View File

@@ -9,8 +9,10 @@ import (
"testing"
"time"
"github.com/prysmaticlabs/go-ssz"
"github.com/prysmaticlabs/prysm/beacon-chain/attestation"
b "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
v "github.com/prysmaticlabs/prysm/beacon-chain/core/validators"
"github.com/prysmaticlabs/prysm/beacon-chain/internal"
@@ -28,7 +30,7 @@ import (
var _ = BlockProcessor(&ChainService{})
func initBlockStateRoot(t *testing.T, block *pb.BeaconBlock, chainService *ChainService) {
parentRoot := bytesutil.ToBytes32(block.ParentRootHash32)
parentRoot := bytesutil.ToBytes32(block.ParentRoot)
parent, err := chainService.beaconDB.Block(parentRoot)
if err != nil {
t.Fatal(err)
@@ -37,19 +39,18 @@ func initBlockStateRoot(t *testing.T, block *pb.BeaconBlock, chainService *Chain
if err != nil {
t.Fatalf("Unable to retrieve state %v", err)
}
saveLatestBlock := beaconState.LatestBlock
computedState, err := chainService.ApplyBlockStateTransition(context.Background(), block, beaconState)
computedState, err := chainService.AdvanceState(context.Background(), beaconState, block)
if err != nil {
t.Fatalf("could not apply block state transition: %v", err)
}
computedState.LatestBlock = saveLatestBlock
stateRoot, err := hashutil.HashProto(computedState)
stateRoot, err := ssz.HashTreeRoot(computedState)
if err != nil {
t.Fatalf("could not tree hash state: %v", err)
}
block.StateRootHash32 = stateRoot[:]
block.StateRoot = stateRoot[:]
t.Logf("state root after block: %#x", stateRoot)
}
@@ -58,8 +59,8 @@ func TestReceiveBlock_FaultyPOWChain(t *testing.T) {
defer internal.TeardownDB(t, db)
chainService := setupBeaconChain(t, db, nil)
unixTime := uint64(time.Now().Unix())
deposits, _ := setupInitialDeposits(t, 100)
if err := db.InitializeState(context.Background(), unixTime, deposits, &pb.Eth1Data{}); err != nil {
deposits, _ := testutil.SetupInitialDeposits(t, 100, false)
if err := db.InitializeState(context.Background(), unixTime, deposits, nil); err != nil {
t.Fatalf("Could not initialize beacon state to disk: %v", err)
}
@@ -71,7 +72,7 @@ func TestReceiveBlock_FaultyPOWChain(t *testing.T) {
Slot: 1,
}
parentRoot, err := hashutil.HashBeaconBlock(parentBlock)
parentRoot, err := ssz.SigningRoot(parentBlock)
if err != nil {
t.Fatalf("Unable to tree hash block %v", err)
}
@@ -81,11 +82,13 @@ func TestReceiveBlock_FaultyPOWChain(t *testing.T) {
}
block := &pb.BeaconBlock{
Slot: 2,
ParentRootHash32: parentRoot[:],
Eth1Data: &pb.Eth1Data{
DepositRootHash32: []byte("a"),
BlockHash32: []byte("b"),
Slot: 2,
ParentRoot: parentRoot[:],
Body: &pb.BeaconBlockBody{
Eth1Data: &pb.Eth1Data{
DepositRoot: []byte("a"),
BlockHash: []byte("b"),
},
},
}
@@ -98,35 +101,41 @@ func TestReceiveBlock_FaultyPOWChain(t *testing.T) {
}
func TestReceiveBlock_ProcessCorrectly(t *testing.T) {
featureconfig.InitFeatureConfig(&featureconfig.FeatureFlagConfig{
EnableCheckBlockStateRoot: false,
})
hook := logTest.NewGlobal()
db := internal.SetupDB(t)
defer internal.TeardownDB(t, db)
ctx := context.Background()
chainService := setupBeaconChain(t, db, nil)
deposits, privKeys := setupInitialDeposits(t, 100)
eth1Data := &pb.Eth1Data{
DepositRootHash32: []byte{},
BlockHash32: []byte{},
}
beaconState, err := state.GenesisBeaconState(deposits, 0, eth1Data)
deposits, privKeys := testutil.SetupInitialDeposits(t, 100, true)
beaconState, err := state.GenesisBeaconState(deposits, 0, nil)
if err != nil {
t.Fatalf("Can't generate genesis state: %v", err)
}
stateRoot, err := hashutil.HashProto(beaconState)
if err != nil {
t.Fatalf("Could not tree hash state: %v", err)
}
beaconState.StateRoots = make([][]byte, params.BeaconConfig().HistoricalRootsLimit)
genesis := b.NewGenesisBlock([]byte{})
bodyRoot, err := ssz.HashTreeRoot(genesis.Body)
if err != nil {
t.Fatal(err)
}
beaconState.LatestBlockHeader = &pb.BeaconBlockHeader{
Slot: genesis.Slot,
ParentRoot: genesis.ParentRoot,
BodyRoot: bodyRoot[:],
}
beaconState.Eth1DepositIndex = 0
if err := chainService.beaconDB.SaveBlock(genesis); err != nil {
t.Fatalf("Could not save block to db: %v", err)
}
parentHash, err := hashutil.HashBeaconBlock(genesis)
parentRoot, err := ssz.SigningRoot(genesis)
if err != nil {
t.Fatalf("Unable to get tree hash root of canonical head: %v", err)
t.Fatal(err)
}
if err := db.SaveHistoricalState(ctx, beaconState, parentHash); err != nil {
if err := db.SaveHistoricalState(ctx, beaconState, parentRoot); err != nil {
t.Fatal(err)
}
@@ -135,24 +144,25 @@ func TestReceiveBlock_ProcessCorrectly(t *testing.T) {
}
beaconState.Slot++
randaoReveal := createRandaoReveal(t, beaconState, privKeys)
epoch := helpers.CurrentEpoch(beaconState)
randaoReveal, err := helpers.CreateRandaoReveal(beaconState, epoch, privKeys)
if err != nil {
t.Fatal(err)
}
block := &pb.BeaconBlock{
Slot: beaconState.Slot,
StateRootHash32: stateRoot[:],
ParentRootHash32: parentHash[:],
RandaoReveal: randaoReveal,
Eth1Data: &pb.Eth1Data{
DepositRootHash32: []byte("a"),
BlockHash32: []byte("b"),
},
Slot: beaconState.Slot,
ParentRoot: parentRoot[:],
Body: &pb.BeaconBlockBody{
Eth1Data: &pb.Eth1Data{
DepositRoot: []byte("a"),
BlockHash: []byte("b"),
},
RandaoReveal: randaoReveal,
Attestations: nil,
},
}
initBlockStateRoot(t, block, chainService)
if err := chainService.beaconDB.SaveJustifiedBlock(block); err != nil {
t.Fatal(err)
}
@@ -165,31 +175,36 @@ func TestReceiveBlock_ProcessCorrectly(t *testing.T) {
if _, err := chainService.ReceiveBlock(context.Background(), block); err != nil {
t.Errorf("Block failed processing: %v", err)
}
testutil.AssertLogsContain(t, hook, "Finished processing beacon block")
}
func TestReceiveBlock_UsesParentBlockState(t *testing.T) {
featureconfig.InitFeatureConfig(&featureconfig.FeatureFlagConfig{
EnableCheckBlockStateRoot: false,
})
hook := logTest.NewGlobal()
db := internal.SetupDB(t)
defer internal.TeardownDB(t, db)
ctx := context.Background()
chainService := setupBeaconChain(t, db, nil)
deposits, _ := setupInitialDeposits(t, 100)
eth1Data := &pb.Eth1Data{
DepositRootHash32: []byte{},
BlockHash32: []byte{},
}
beaconState, err := state.GenesisBeaconState(deposits, 0, eth1Data)
deposits, _ := testutil.SetupInitialDeposits(t, 100, false)
beaconState, err := state.GenesisBeaconState(deposits, 0, nil)
if err != nil {
t.Fatalf("Can't generate genesis state: %v", err)
}
stateRoot, err := hashutil.HashProto(beaconState)
beaconState.StateRoots = make([][]byte, params.BeaconConfig().HistoricalRootsLimit)
genesis := b.NewGenesisBlock([]byte{})
bodyRoot, err := ssz.HashTreeRoot(genesis.Body)
if err != nil {
t.Fatalf("Could not tree hash state: %v", err)
t.Fatal(err)
}
beaconState.LatestBlockHeader = &pb.BeaconBlockHeader{
Slot: genesis.Slot,
ParentRoot: genesis.ParentRoot,
BodyRoot: bodyRoot[:],
}
beaconState.Eth1DepositIndex = 0
parentHash, genesisBlock := setupGenesisBlock(t, chainService)
if err := chainService.beaconDB.UpdateChainHead(ctx, genesisBlock, beaconState); err != nil {
@@ -198,21 +213,24 @@ func TestReceiveBlock_UsesParentBlockState(t *testing.T) {
if err := chainService.beaconDB.SaveHistoricalState(ctx, beaconState, parentHash); err != nil {
t.Fatal(err)
}
parentRoot, err := ssz.SigningRoot(beaconState.LatestBlockHeader)
if err != nil {
t.Fatal(err)
}
// We ensure the block uses the right state parent if its ancestor is not block.Slot-1.
block := &pb.BeaconBlock{
Slot: beaconState.Slot + 4,
StateRootHash32: stateRoot[:],
ParentRootHash32: parentHash[:],
RandaoReveal: []byte{},
Eth1Data: &pb.Eth1Data{
DepositRootHash32: []byte("a"),
BlockHash32: []byte("b"),
},
Slot: beaconState.Slot + 4,
StateRoot: []byte{},
ParentRoot: parentRoot[:],
Body: &pb.BeaconBlockBody{
Eth1Data: &pb.Eth1Data{
DepositRoot: []byte("a"),
BlockHash: []byte("b"),
},
RandaoReveal: []byte{},
Attestations: nil,
},
}
initBlockStateRoot(t, block, chainService)
if err := chainService.beaconDB.SaveBlock(block); err != nil {
t.Fatal(err)
}
@@ -230,19 +248,25 @@ func TestReceiveBlock_DeletesBadBlock(t *testing.T) {
defer internal.TeardownDB(t, db)
ctx := context.Background()
chainService := setupBeaconChain(t, db, nil)
deposits, _ := setupInitialDeposits(t, 100)
eth1Data := &pb.Eth1Data{
DepositRootHash32: []byte{},
BlockHash32: []byte{},
}
beaconState, err := state.GenesisBeaconState(deposits, 0, eth1Data)
attsService := attestation.NewAttestationService(
context.Background(),
&attestation.Config{BeaconDB: db})
chainService := setupBeaconChain(t, db, attsService)
deposits, _ := testutil.SetupInitialDeposits(t, 100, false)
beaconState, err := state.GenesisBeaconState(deposits, 0, nil)
if err != nil {
t.Fatalf("Can't generate genesis state: %v", err)
}
stateRoot, err := hashutil.HashProto(beaconState)
beaconState.StateRoots = make([][]byte, params.BeaconConfig().HistoricalRootsLimit)
genesis := b.NewGenesisBlock([]byte{})
bodyRoot, err := ssz.HashTreeRoot(genesis.Body)
if err != nil {
t.Fatalf("Could not tree hash state: %v", err)
t.Fatal(err)
}
beaconState.LatestBlockHeader = &pb.BeaconBlockHeader{
Slot: genesis.Slot,
ParentRoot: genesis.ParentRoot,
BodyRoot: bodyRoot[:],
}
parentHash, genesisBlock := setupGenesisBlock(t, chainService)
@@ -255,27 +279,29 @@ func TestReceiveBlock_DeletesBadBlock(t *testing.T) {
beaconState.Slot++
parentRoot, err := ssz.SigningRoot(beaconState.LatestBlockHeader)
if err != nil {
t.Fatal(err)
}
block := &pb.BeaconBlock{
Slot: beaconState.Slot,
StateRootHash32: stateRoot[:],
ParentRootHash32: parentHash[:],
RandaoReveal: []byte{},
Eth1Data: &pb.Eth1Data{
DepositRootHash32: []byte("a"),
BlockHash32: []byte("b"),
},
Slot: beaconState.Slot,
StateRoot: []byte{},
ParentRoot: parentRoot[:],
Body: &pb.BeaconBlockBody{
Attestations: []*pb.Attestation{
{
Data: &pb.AttestationData{
JustifiedEpoch: params.BeaconConfig().GenesisSlot * 100,
},
},
Eth1Data: &pb.Eth1Data{
DepositRoot: []byte("a"),
BlockHash: []byte("b"),
},
RandaoReveal: []byte{},
Attestations: []*pb.Attestation{{
Data: &pb.AttestationData{
Target: &pb.Checkpoint{Epoch: 5},
},
}},
},
}
blockRoot, err := hashutil.HashBeaconBlock(block)
blockRoot, err := ssz.SigningRoot(block)
if err != nil {
t.Fatal(err)
}
@@ -285,7 +311,7 @@ func TestReceiveBlock_DeletesBadBlock(t *testing.T) {
case *BlockFailedProcessingErr:
t.Log("Block failed processing as expected")
default:
t.Errorf("Unexpected block processing error: %v", err)
t.Errorf("Expected block processing to fail, received: %v", err)
}
savedBlock, err := db.Block(blockRoot)
@@ -314,16 +340,23 @@ func TestReceiveBlock_CheckBlockStateRoot_GoodState(t *testing.T) {
context.Background(),
&attestation.Config{BeaconDB: db})
chainService := setupBeaconChain(t, db, attsService)
deposits, privKeys := setupInitialDeposits(t, 100)
eth1Data := &pb.Eth1Data{
DepositRootHash32: []byte{},
BlockHash32: []byte{},
}
beaconState, err := state.GenesisBeaconState(deposits, 0, eth1Data)
deposits, privKeys := testutil.SetupInitialDeposits(t, 100, true)
beaconState, err := state.GenesisBeaconState(deposits, 0, nil)
if err != nil {
t.Fatalf("Can't generate genesis state: %v", err)
}
beaconState.Eth1DepositIndex = 0
genesis := b.NewGenesisBlock([]byte{})
bodyRoot, err := ssz.HashTreeRoot(genesis.Body)
if err != nil {
t.Fatal(err)
}
beaconState.StateRoots = make([][]byte, params.BeaconConfig().HistoricalRootsLimit)
beaconState.LatestBlockHeader = &pb.BeaconBlockHeader{
Slot: genesis.Slot,
ParentRoot: genesis.ParentRoot,
BodyRoot: bodyRoot[:],
}
parentHash, genesisBlock := setupGenesisBlock(t, chainService)
if err := chainService.beaconDB.SaveHistoricalState(ctx, beaconState, parentHash); err != nil {
t.Fatal(err)
@@ -334,11 +367,23 @@ func TestReceiveBlock_CheckBlockStateRoot_GoodState(t *testing.T) {
}
beaconState.Slot++
parentRoot, err := ssz.SigningRoot(genesisBlock)
if err != nil {
t.Fatal(err)
}
epoch := helpers.CurrentEpoch(beaconState)
randaoReveal, err := helpers.CreateRandaoReveal(beaconState, epoch, privKeys)
if err != nil {
t.Fatal(err)
}
goodStateBlock := &pb.BeaconBlock{
Slot: beaconState.Slot,
ParentRootHash32: parentHash[:],
RandaoReveal: createRandaoReveal(t, beaconState, privKeys),
Body: &pb.BeaconBlockBody{},
Slot: beaconState.Slot,
ParentRoot: parentRoot[:],
Body: &pb.BeaconBlockBody{
Eth1Data: &pb.Eth1Data{},
RandaoReveal: randaoReveal,
},
}
beaconState.Slot--
initBlockStateRoot(t, goodStateBlock, chainService)
@@ -357,17 +402,25 @@ func TestReceiveBlock_CheckBlockStateRoot_GoodState(t *testing.T) {
func TestReceiveBlock_CheckBlockStateRoot_BadState(t *testing.T) {
db := internal.SetupDB(t)
defer internal.TeardownDB(t, db)
chainService := setupBeaconChain(t, db, nil)
deposits, privKeys := setupInitialDeposits(t, 100)
ctx := context.Background()
eth1Data := &pb.Eth1Data{
DepositRootHash32: []byte{},
BlockHash32: []byte{},
}
beaconState, err := state.GenesisBeaconState(deposits, 0, eth1Data)
chainService := setupBeaconChain(t, db, nil)
deposits, privKeys := testutil.SetupInitialDeposits(t, 100, true)
beaconState, err := state.GenesisBeaconState(deposits, 0, nil)
if err != nil {
t.Fatalf("Can't generate genesis state: %v", err)
}
beaconState.Eth1DepositIndex = 0
genesis := b.NewGenesisBlock([]byte{})
bodyRoot, err := ssz.HashTreeRoot(genesis.Body)
if err != nil {
t.Fatal(err)
}
beaconState.StateRoots = make([][]byte, params.BeaconConfig().HistoricalRootsLimit)
beaconState.LatestBlockHeader = &pb.BeaconBlockHeader{
Slot: genesis.Slot,
ParentRoot: genesis.ParentRoot,
BodyRoot: bodyRoot[:],
}
parentHash, genesisBlock := setupGenesisBlock(t, chainService)
if err := chainService.beaconDB.SaveHistoricalState(ctx, beaconState, parentHash); err != nil {
t.Fatal(err)
@@ -378,12 +431,24 @@ func TestReceiveBlock_CheckBlockStateRoot_BadState(t *testing.T) {
}
beaconState.Slot++
parentRoot, err := ssz.SigningRoot(genesis)
if err != nil {
t.Fatal(err)
}
epoch := helpers.CurrentEpoch(beaconState)
randaoReveal, err := helpers.CreateRandaoReveal(beaconState, epoch, privKeys)
if err != nil {
t.Fatal(err)
}
invalidStateBlock := &pb.BeaconBlock{
Slot: beaconState.Slot,
StateRootHash32: []byte{'b', 'a', 'd', ' ', 'h', 'a', 's', 'h'},
ParentRootHash32: parentHash[:],
RandaoReveal: createRandaoReveal(t, beaconState, privKeys),
Body: &pb.BeaconBlockBody{},
Slot: beaconState.Slot,
StateRoot: []byte{'b', 'a', 'd', ' ', 'h', 'a', 's', 'h'},
ParentRoot: parentRoot[:],
Body: &pb.BeaconBlockBody{
Eth1Data: &pb.Eth1Data{},
RandaoReveal: randaoReveal,
},
}
beaconState.Slot--
@@ -406,15 +471,24 @@ func TestReceiveBlock_RemovesPendingDeposits(t *testing.T) {
context.Background(),
&attestation.Config{BeaconDB: db})
chainService := setupBeaconChain(t, db, attsService)
deposits, privKeys := setupInitialDeposits(t, 100)
eth1Data := &pb.Eth1Data{
DepositRootHash32: []byte{},
BlockHash32: []byte{},
}
beaconState, err := state.GenesisBeaconState(deposits, 0, eth1Data)
deposits, privKeys := testutil.SetupInitialDeposits(t, 100, true)
beaconState, err := state.GenesisBeaconState(deposits, 0, nil)
if err != nil {
t.Fatalf("Can't generate genesis state: %v", err)
}
genesis := b.NewGenesisBlock([]byte{})
bodyRoot, err := ssz.HashTreeRoot(genesis.Body)
if err != nil {
t.Fatal(err)
}
beaconState.StateRoots = make([][]byte, params.BeaconConfig().HistoricalRootsLimit)
beaconState.LatestBlockHeader = &pb.BeaconBlockHeader{
Slot: genesis.Slot,
ParentRoot: genesis.ParentRoot,
BodyRoot: bodyRoot[:],
}
beaconState.Eth1Data.DepositCount = 1
beaconState.Eth1DepositIndex = 0
if err := chainService.beaconDB.SaveJustifiedState(beaconState); err != nil {
t.Fatal(err)
}
@@ -422,7 +496,7 @@ func TestReceiveBlock_RemovesPendingDeposits(t *testing.T) {
t.Fatal(err)
}
stateRoot, err := hashutil.HashProto(beaconState)
stateRoot, err := ssz.HashTreeRoot(beaconState)
if err != nil {
t.Fatalf("Could not tree hash state: %v", err)
}
@@ -432,57 +506,69 @@ func TestReceiveBlock_RemovesPendingDeposits(t *testing.T) {
t.Fatal(err)
}
currentSlot := params.BeaconConfig().GenesisSlot
randaoReveal := createRandaoReveal(t, beaconState, privKeys)
currentSlot := uint64(0)
epoch := helpers.CurrentEpoch(beaconState)
randaoReveal, err := helpers.CreateRandaoReveal(beaconState, epoch, privKeys)
if err != nil {
t.Fatal(err)
}
pendingDeposits := []*pb.Deposit{
createPreChainStartDeposit(t, []byte{'F'}, beaconState.DepositIndex),
createPreChainStartDeposit([]byte{'F'}),
}
pendingDepositsData := make([][]byte, len(pendingDeposits))
for i, pd := range pendingDeposits {
pendingDepositsData[i] = pd.DepositData
h, err := hashutil.DepositHash(pd.Data)
if err != nil {
t.Fatal(err)
}
pendingDepositsData[i] = h[:]
}
depositTrie, err := trieutil.GenerateTrieFromItems(pendingDepositsData, int(params.BeaconConfig().DepositContractTreeDepth))
if err != nil {
t.Fatalf("Could not generate deposit trie: %v", err)
}
for i := range pendingDeposits {
pendingDeposits[i].MerkleTreeIndex = 0
proof, err := depositTrie.MerkleProof(int(pendingDeposits[i].MerkleTreeIndex))
proof, err := depositTrie.MerkleProof(0)
if err != nil {
t.Fatalf("Could not generate proof: %v", err)
}
pendingDeposits[i].MerkleProofHash32S = proof
pendingDeposits[i].Proof = proof
}
depositRoot := depositTrie.Root()
beaconState.LatestEth1Data.DepositRootHash32 = depositRoot[:]
beaconState.Eth1Data.DepositRoot = depositRoot[:]
if err := db.SaveHistoricalState(context.Background(), beaconState, parentHash); err != nil {
t.Fatal(err)
}
parentRoot, err := ssz.SigningRoot(genesis)
if err != nil {
t.Fatal(err)
}
block := &pb.BeaconBlock{
Slot: currentSlot + 1,
StateRootHash32: stateRoot[:],
ParentRootHash32: parentHash[:],
RandaoReveal: randaoReveal,
Eth1Data: &pb.Eth1Data{
DepositRootHash32: []byte("a"),
BlockHash32: []byte("b"),
},
Slot: currentSlot + 1,
StateRoot: stateRoot[:],
ParentRoot: parentRoot[:],
Body: &pb.BeaconBlockBody{
Deposits: pendingDeposits,
Eth1Data: &pb.Eth1Data{
DepositRoot: []byte("a"),
BlockHash: []byte("b"),
},
RandaoReveal: randaoReveal,
Deposits: pendingDeposits,
},
}
beaconState.LatestBlock = block
beaconState.Slot--
beaconState.DepositIndex = 0
beaconState.Eth1DepositIndex = 0
if err := chainService.beaconDB.SaveState(ctx, beaconState); err != nil {
t.Fatal(err)
}
initBlockStateRoot(t, block, chainService)
blockRoot, err := hashutil.HashBeaconBlock(block)
blockRoot, err := ssz.SigningRoot(block)
if err != nil {
log.Fatalf("could not hash block: %v", err)
}
@@ -495,7 +581,7 @@ func TestReceiveBlock_RemovesPendingDeposits(t *testing.T) {
}
for _, dep := range pendingDeposits {
db.InsertPendingDeposit(chainService.ctx, dep, big.NewInt(0))
db.InsertPendingDeposit(chainService.ctx, dep, big.NewInt(0), 0, [32]byte{})
}
if len(db.PendingDeposits(chainService.ctx, nil)) != len(pendingDeposits) || len(pendingDeposits) == 0 {
@@ -513,11 +599,11 @@ func TestReceiveBlock_RemovesPendingDeposits(t *testing.T) {
if err != nil {
t.Fatal(err)
}
for i := 0; i < len(beaconState.ValidatorRegistry); i++ {
pubKey := bytesutil.ToBytes48(beaconState.ValidatorRegistry[i].Pubkey)
for i := 0; i < len(beaconState.Validators); i++ {
pubKey := bytesutil.ToBytes48(beaconState.Validators[i].Pubkey)
attsService.InsertAttestationIntoStore(pubKey, &pb.Attestation{
Data: &pb.AttestationData{
BeaconBlockRootHash32: blockRoot[:],
BeaconBlockRoot: blockRoot[:],
}},
)
}
@@ -569,56 +655,74 @@ func TestReceiveBlock_OnChainSplit(t *testing.T) {
ctx := context.Background()
chainService := setupBeaconChain(t, db, nil)
deposits, privKeys := setupInitialDeposits(t, 100)
eth1Data := &pb.Eth1Data{
DepositRootHash32: []byte{},
BlockHash32: []byte{},
}
beaconState, err := state.GenesisBeaconState(deposits, 0, eth1Data)
deposits, privKeys := testutil.SetupInitialDeposits(t, 100, true)
beaconState, err := state.GenesisBeaconState(deposits, 0, nil)
if err != nil {
t.Fatalf("Can't generate genesis state: %v", err)
}
stateRoot, err := hashutil.HashProto(beaconState)
beaconState.Eth1DepositIndex = 0
genesis := b.NewGenesisBlock([]byte{})
bodyRoot, err := ssz.HashTreeRoot(genesis.Body)
if err != nil {
t.Fatal(err)
}
beaconState.StateRoots = make([][]byte, params.BeaconConfig().HistoricalRootsLimit)
beaconState.LatestBlockHeader = &pb.BeaconBlockHeader{
Slot: genesis.Slot,
ParentRoot: genesis.ParentRoot,
BodyRoot: bodyRoot[:],
}
stateRoot, err := ssz.HashTreeRoot(beaconState)
if err != nil {
t.Fatalf("Could not tree hash state: %v", err)
}
parentHash, genesisBlock := setupGenesisBlock(t, chainService)
beaconState.LatestBlock = genesisBlock
_, genesisBlock := setupGenesisBlock(t, chainService)
if err := db.UpdateChainHead(ctx, genesisBlock, beaconState); err != nil {
t.Fatal(err)
}
if err := db.SaveFinalizedState(beaconState); err != nil {
t.Fatal(err)
}
genesisSlot := params.BeaconConfig().GenesisSlot
genesisSlot := uint64(0)
parentRoot, err := ssz.SigningRoot(genesisBlock)
if err != nil {
t.Fatal(err)
}
epoch := helpers.CurrentEpoch(beaconState)
randaoReveal, err := helpers.CreateRandaoReveal(beaconState, epoch, privKeys)
if err != nil {
t.Fatal(err)
}
// Top chain slots (see graph)
blockSlots := []uint64{1, 2, 3, 5, 8}
for _, slot := range blockSlots {
block := &pb.BeaconBlock{
Slot: genesisSlot + slot,
StateRootHash32: stateRoot[:],
ParentRootHash32: parentHash[:],
RandaoReveal: createRandaoReveal(t, beaconState, privKeys),
Body: &pb.BeaconBlockBody{},
Slot: genesisSlot + slot,
StateRoot: stateRoot[:],
ParentRoot: parentRoot[:],
Body: &pb.BeaconBlockBody{
Eth1Data: &pb.Eth1Data{},
RandaoReveal: randaoReveal,
},
}
initBlockStateRoot(t, block, chainService)
computedState, err := chainService.ReceiveBlock(ctx, block)
if err != nil {
t.Fatal(err)
}
stateRoot, err = hashutil.HashProto(computedState)
stateRoot, err = ssz.HashTreeRoot(computedState)
if err != nil {
t.Fatal(err)
}
if err = db.SaveBlock(block); err != nil {
t.Fatal(err)
}
computedState.LatestBlock = block
if err = db.UpdateChainHead(ctx, block, computedState); err != nil {
t.Fatal(err)
}
parentHash, err = hashutil.HashBeaconBlock(block)
parentRoot, err = ssz.SigningRoot(block)
if err != nil {
t.Fatal(err)
}
@@ -630,39 +734,48 @@ func TestReceiveBlock_OnChainSplit(t *testing.T) {
t.Fatal(err)
}
parentHash, err = hashutil.HashBeaconBlock(commonAncestor)
parentRoot, err = ssz.SigningRoot(commonAncestor)
if err != nil {
t.Fatal(err)
}
beaconState, err = db.HistoricalStateFromSlot(ctx, commonAncestor.Slot, parentHash)
beaconState, err = db.HistoricalStateFromSlot(ctx, commonAncestor.Slot, parentRoot)
if err != nil {
t.Fatal(err)
}
stateRoot, err = hashutil.HashProto(beaconState)
stateRoot, err = ssz.HashTreeRoot(beaconState)
if err != nil {
t.Fatal(err)
}
epoch = helpers.CurrentEpoch(beaconState)
randaoReveal, err = helpers.CreateRandaoReveal(beaconState, epoch, privKeys)
if err != nil {
t.Fatal(err)
}
// Then we receive the block `f` from slot 6
blockF := &pb.BeaconBlock{
Slot: genesisSlot + 6,
ParentRootHash32: parentHash[:],
StateRootHash32: stateRoot[:],
RandaoReveal: createRandaoReveal(t, beaconState, privKeys),
Body: &pb.BeaconBlockBody{},
Slot: genesisSlot + 6,
ParentRoot: parentRoot[:],
StateRoot: stateRoot[:],
Body: &pb.BeaconBlockBody{
Eth1Data: &pb.Eth1Data{},
RandaoReveal: randaoReveal,
},
}
rootF, _ := hashutil.HashBeaconBlock(blockF)
rootF, _ := ssz.SigningRoot(blockF)
if err := db.SaveHistoricalState(ctx, beaconState, rootF); err != nil {
t.Fatal(err)
}
initBlockStateRoot(t, blockF, chainService)
initBlockStateRoot(t, blockF, chainService)
computedState, err := chainService.ReceiveBlock(ctx, blockF)
if err != nil {
t.Fatal(err)
}
stateRoot, err = hashutil.HashProto(computedState)
stateRoot, err = ssz.HashTreeRoot(computedState)
if err != nil {
t.Fatal(err)
}
@@ -671,18 +784,26 @@ func TestReceiveBlock_OnChainSplit(t *testing.T) {
t.Fatal(err)
}
parentHash, err = hashutil.HashBeaconBlock(blockF)
parentRoot, err = ssz.SigningRoot(blockF)
if err != nil {
t.Fatal(err)
}
epoch = helpers.CurrentEpoch(beaconState)
randaoReveal, err = helpers.CreateRandaoReveal(beaconState, epoch, privKeys)
if err != nil {
t.Fatal(err)
}
// Then we apply block `g` from slot 7
blockG := &pb.BeaconBlock{
Slot: genesisSlot + 7,
ParentRootHash32: parentHash[:],
StateRootHash32: stateRoot[:],
RandaoReveal: createRandaoReveal(t, computedState, privKeys),
Body: &pb.BeaconBlockBody{},
Slot: genesisSlot + 7,
ParentRoot: parentRoot[:],
StateRoot: stateRoot[:],
Body: &pb.BeaconBlockBody{
Eth1Data: &pb.Eth1Data{},
RandaoReveal: randaoReveal,
},
}
initBlockStateRoot(t, blockG, chainService)
@@ -703,63 +824,79 @@ func TestIsBlockReadyForProcessing_ValidBlock(t *testing.T) {
chainService := setupBeaconChain(t, db, nil)
unixTime := uint64(time.Now().Unix())
deposits, privKeys := setupInitialDeposits(t, 100)
if err := db.InitializeState(context.Background(), unixTime, deposits, &pb.Eth1Data{}); err != nil {
deposits, privKeys := testutil.SetupInitialDeposits(t, 100, true)
if err := db.InitializeState(context.Background(), unixTime, deposits, nil); err != nil {
t.Fatalf("Could not initialize beacon state to disk: %v", err)
}
beaconState, err := db.HeadState(ctx)
if err != nil {
t.Fatalf("Can't get genesis state: %v", err)
}
genesis := b.NewGenesisBlock([]byte{})
bodyRoot, err := ssz.HashTreeRoot(genesis.Body)
if err != nil {
t.Fatal(err)
}
beaconState.StateRoots = make([][]byte, params.BeaconConfig().HistoricalRootsLimit)
beaconState.LatestBlockHeader = &pb.BeaconBlockHeader{
Slot: genesis.Slot,
ParentRoot: genesis.ParentRoot,
BodyRoot: bodyRoot[:],
}
block := &pb.BeaconBlock{
ParentRootHash32: []byte{'a'},
ParentRoot: []byte{'a'},
}
if err := chainService.VerifyBlockValidity(ctx, block, beaconState); err == nil {
t.Fatal("block processing succeeded despite block having no parent saved")
}
beaconState.Slot = params.BeaconConfig().GenesisSlot + 10
beaconState.Slot = 10
stateRoot, err := hashutil.HashProto(beaconState)
stateRoot, err := ssz.HashTreeRoot(beaconState)
if err != nil {
t.Fatalf("Could not tree hash state: %v", err)
}
genesis := b.NewGenesisBlock([]byte{})
if err := chainService.beaconDB.SaveBlock(genesis); err != nil {
t.Fatalf("cannot save block: %v", err)
}
parentRoot, err := hashutil.HashBeaconBlock(genesis)
parentRoot, err := ssz.SigningRoot(genesis)
if err != nil {
t.Fatalf("unable to get root of canonical head: %v", err)
}
beaconState.LatestEth1Data = &pb.Eth1Data{
DepositRootHash32: []byte{2},
BlockHash32: []byte{3},
beaconState.Eth1Data = &pb.Eth1Data{
DepositRoot: []byte{2},
BlockHash: []byte{3},
}
beaconState.Slot = params.BeaconConfig().GenesisSlot
beaconState.Slot = 0
currentSlot := params.BeaconConfig().GenesisSlot + 1
attestationSlot := params.BeaconConfig().GenesisSlot
currentSlot := uint64(1)
epoch := helpers.CurrentEpoch(beaconState)
randaoReveal, err := helpers.CreateRandaoReveal(beaconState, epoch, privKeys)
if err != nil {
t.Fatal(err)
}
randaoReveal := createRandaoReveal(t, beaconState, privKeys)
block2 := &pb.BeaconBlock{
Slot: currentSlot,
StateRootHash32: stateRoot[:],
ParentRootHash32: parentRoot[:],
RandaoReveal: randaoReveal,
Eth1Data: &pb.Eth1Data{
DepositRootHash32: []byte("a"),
BlockHash32: []byte("b"),
},
Slot: currentSlot,
StateRoot: stateRoot[:],
ParentRoot: parentRoot[:],
Body: &pb.BeaconBlockBody{
Eth1Data: &pb.Eth1Data{
DepositRoot: []byte("a"),
BlockHash: []byte("b"),
},
RandaoReveal: randaoReveal,
Attestations: []*pb.Attestation{{
AggregationBitfield: []byte{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
AggregationBits: []byte{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
Data: &pb.AttestationData{
Slot: attestationSlot,
JustifiedBlockRootHash32: parentRoot[:],
Source: &pb.Checkpoint{Root: parentRoot[:]},
Crosslink: &pb.Crosslink{
Shard: 960,
},
},
}},
},
@@ -785,8 +922,8 @@ func TestDeleteValidatorIdx_DeleteWorks(t *testing.T) {
})
}
state := &pb.BeaconState{
ValidatorRegistry: validators,
Slot: epoch * params.BeaconConfig().SlotsPerEpoch,
Validators: validators,
Slot: epoch * params.BeaconConfig().SlotsPerEpoch,
}
chainService := setupBeaconChain(t, db, nil)
if err := chainService.saveValidatorIdx(state); err != nil {
@@ -827,8 +964,8 @@ func TestSaveValidatorIdx_SaveRetrieveWorks(t *testing.T) {
})
}
state := &pb.BeaconState{
ValidatorRegistry: validators,
Slot: epoch * params.BeaconConfig().SlotsPerEpoch,
Validators: validators,
Slot: epoch * params.BeaconConfig().SlotsPerEpoch,
}
chainService := setupBeaconChain(t, db, nil)
if err := chainService.saveValidatorIdx(state); err != nil {
@@ -854,7 +991,7 @@ func TestSaveValidatorIdx_IdxNotInState(t *testing.T) {
defer internal.TeardownDB(t, db)
epoch := uint64(100)
// Tried to insert 5 active indices to DB with only 3 validators in state.
// Tried to insert 5 active indices to DB with only 3 validators in state
v.InsertActivatedIndices(epoch+1, []uint64{0, 1, 2, 3, 4})
var validators []*pb.Validator
for i := 0; i < 3; i++ {
@@ -865,8 +1002,8 @@ func TestSaveValidatorIdx_IdxNotInState(t *testing.T) {
})
}
state := &pb.BeaconState{
ValidatorRegistry: validators,
Slot: epoch * params.BeaconConfig().SlotsPerEpoch,
Validators: validators,
Slot: epoch * params.BeaconConfig().SlotsPerEpoch,
}
chainService := setupBeaconChain(t, db, nil)
if err := chainService.saveValidatorIdx(state); err != nil {
@@ -886,7 +1023,7 @@ func TestSaveValidatorIdx_IdxNotInState(t *testing.T) {
t.Errorf("Activated validators mapping for epoch %d still there", epoch)
}
// Verify the skipped validators are included in the next epoch.
// Verify the skipped validators are included in the next epoch
if !reflect.DeepEqual(v.ActivatedValFromEpoch(epoch+2), []uint64{3, 4}) {
t.Error("Did not get wanted validator from activation queue")
}

View File

@@ -8,13 +8,12 @@ import (
"github.com/gogo/protobuf/proto"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/prysmaticlabs/go-ssz"
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/db"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/hashutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/sirupsen/logrus"
"go.opencensus.io/trace"
)
@@ -43,7 +42,7 @@ type TargetsFetcher interface {
// are not older than the ones just processed in state. If it's older, we update
// the db with the latest FFG check points, both justification and finalization.
func (c *ChainService) updateFFGCheckPts(ctx context.Context, state *pb.BeaconState) error {
lastJustifiedSlot := helpers.StartSlot(state.JustifiedEpoch)
lastJustifiedSlot := helpers.StartSlot(state.CurrentJustifiedCheckpoint.Epoch)
savedJustifiedBlock, err := c.beaconDB.JustifiedBlock()
if err != nil {
return err
@@ -60,7 +59,7 @@ func (c *ChainService) updateFFGCheckPts(ctx context.Context, state *pb.BeaconSt
// until we can get a block.
lastAvailBlkSlot := lastJustifiedSlot
for newJustifiedBlock == nil {
log.WithField("slot", lastAvailBlkSlot-params.BeaconConfig().GenesisSlot).Debug("Missing block in DB, looking one slot back")
log.WithField("slot", lastAvailBlkSlot).Debug("Missing block in DB, looking one slot back")
lastAvailBlkSlot--
newJustifiedBlock, err = c.beaconDB.CanonicalBlockBySlot(ctx, lastAvailBlkSlot)
if err != nil {
@@ -68,7 +67,7 @@ func (c *ChainService) updateFFGCheckPts(ctx context.Context, state *pb.BeaconSt
}
}
newJustifiedRoot, err := hashutil.HashBeaconBlock(newJustifiedBlock)
newJustifiedRoot, err := ssz.SigningRoot(newJustifiedBlock)
if err != nil {
return err
}
@@ -85,7 +84,7 @@ func (c *ChainService) updateFFGCheckPts(ctx context.Context, state *pb.BeaconSt
}
}
lastFinalizedSlot := helpers.StartSlot(state.FinalizedEpoch)
lastFinalizedSlot := helpers.StartSlot(state.FinalizedCheckpoint.Epoch)
savedFinalizedBlock, err := c.beaconDB.FinalizedBlock()
// If the last processed finalized slot in state is greater than
// the slot of finalized block saved in DB.
@@ -102,7 +101,7 @@ func (c *ChainService) updateFFGCheckPts(ctx context.Context, state *pb.BeaconSt
// until we can get a block.
lastAvailBlkSlot := lastFinalizedSlot
for newFinalizedBlock == nil {
log.WithField("slot", lastAvailBlkSlot-params.BeaconConfig().GenesisSlot).Debug("Missing block in DB, looking one slot back")
log.WithField("slot", lastAvailBlkSlot).Debug("Missing block in DB, looking one slot back")
lastAvailBlkSlot--
newFinalizedBlock, err = c.beaconDB.CanonicalBlockBySlot(ctx, lastAvailBlkSlot)
if err != nil {
@@ -110,7 +109,7 @@ func (c *ChainService) updateFFGCheckPts(ctx context.Context, state *pb.BeaconSt
}
}
newFinalizedRoot, err := hashutil.HashBeaconBlock(newFinalizedBlock)
newFinalizedRoot, err := ssz.SigningRoot(newFinalizedBlock)
if err != nil {
return err
}
@@ -160,7 +159,7 @@ func (c *ChainService) ApplyForkChoiceRule(
if err != nil {
return fmt.Errorf("could not run fork choice: %v", err)
}
newHeadRoot, err := hashutil.HashBeaconBlock(newHead)
newHeadRoot, err := ssz.SigningRoot(newHead)
if err != nil {
return fmt.Errorf("could not hash new head block: %v", err)
}
@@ -172,7 +171,7 @@ func (c *ChainService) ApplyForkChoiceRule(
if err != nil {
return fmt.Errorf("could not retrieve chain head: %v", err)
}
currentHeadRoot, err := hashutil.HashBeaconBlock(currentHead)
currentHeadRoot, err := ssz.SigningRoot(currentHead)
if err != nil {
return fmt.Errorf("could not hash current head block: %v", err)
}
@@ -185,9 +184,9 @@ func (c *ChainService) ApplyForkChoiceRule(
newState := postState
if !isDescendant && !proto.Equal(currentHead, newHead) {
log.WithFields(logrus.Fields{
"currentSlot": currentHead.Slot - params.BeaconConfig().GenesisSlot,
"currentSlot": currentHead.Slot,
"currentRoot": fmt.Sprintf("%#x", bytesutil.Trunc(currentHeadRoot[:])),
"newSlot": newHead.Slot - params.BeaconConfig().GenesisSlot,
"newSlot": newHead.Slot,
"newRoot": fmt.Sprintf("%#x", bytesutil.Trunc(newHeadRoot[:])),
}).Warn("Reorg happened")
// Only regenerate head state if there was a reorg.
@@ -204,7 +203,7 @@ func (c *ChainService) ApplyForkChoiceRule(
if proto.Equal(currentHead, newHead) {
log.WithFields(logrus.Fields{
"currentSlot": currentHead.Slot - params.BeaconConfig().GenesisSlot,
"currentSlot": currentHead.Slot,
"currentRoot": fmt.Sprintf("%#x", bytesutil.Trunc(currentHeadRoot[:])),
}).Warn("Head did not change after fork choice, current head has the most votes")
}
@@ -220,14 +219,14 @@ func (c *ChainService) ApplyForkChoiceRule(
if err := c.beaconDB.UpdateChainHead(ctx, newHead, newState); err != nil {
return fmt.Errorf("failed to update chain: %v", err)
}
h, err := hashutil.HashBeaconBlock(newHead)
h, err := ssz.SigningRoot(newHead)
if err != nil {
return fmt.Errorf("could not hash head: %v", err)
}
log.WithFields(logrus.Fields{
"headRoot": fmt.Sprintf("%#x", bytesutil.Trunc(h[:])),
"headSlot": newHead.Slot - params.BeaconConfig().GenesisSlot,
"stateSlot": newState.Slot - params.BeaconConfig().GenesisSlot,
"headSlot": newHead.Slot,
"stateSlot": newState.Slot,
}).Info("Chain head block and state updated")
return nil
@@ -288,11 +287,11 @@ func (c *ChainService) lmdGhost(
if err != nil {
return nil, fmt.Errorf("unable to determine vote count for block: %v", err)
}
maxChildRoot, err := hashutil.HashBeaconBlock(maxChild)
maxChildRoot, err := ssz.SigningRoot(maxChild)
if err != nil {
return nil, err
}
candidateChildRoot, err := hashutil.HashBeaconBlock(children[i])
candidateChildRoot, err := ssz.SigningRoot(children[i])
if err != nil {
return nil, err
}
@@ -318,7 +317,7 @@ func (c *ChainService) lmdGhost(
// get_children(store: Store, block: BeaconBlock) -> List[BeaconBlock]
// returns the child blocks of the given block.
func (c *ChainService) BlockChildren(ctx context.Context, block *pb.BeaconBlock, highestSlot uint64) ([]*pb.BeaconBlock, error) {
blockRoot, err := hashutil.HashBeaconBlock(block)
blockRoot, err := ssz.SigningRoot(block)
if err != nil {
return nil, err
}
@@ -334,7 +333,7 @@ func (c *ChainService) BlockChildren(ctx context.Context, block *pb.BeaconBlock,
filteredChildren := []*pb.BeaconBlock{}
for _, kid := range children {
parentRoot := bytesutil.ToBytes32(kid.ParentRootHash32)
parentRoot := bytesutil.ToBytes32(kid.ParentRoot)
if blockRoot == parentRoot {
filteredChildren = append(filteredChildren, kid)
}
@@ -344,15 +343,15 @@ func (c *ChainService) BlockChildren(ctx context.Context, block *pb.BeaconBlock,
// isDescendant checks if the new head block is a descendant block of the current head.
func (c *ChainService) isDescendant(currentHead *pb.BeaconBlock, newHead *pb.BeaconBlock) (bool, error) {
currentHeadRoot, err := hashutil.HashBeaconBlock(currentHead)
currentHeadRoot, err := ssz.SigningRoot(currentHead)
if err != nil {
return false, nil
}
for newHead.Slot > currentHead.Slot {
if bytesutil.ToBytes32(newHead.ParentRootHash32) == currentHeadRoot {
if bytesutil.ToBytes32(newHead.ParentRoot) == currentHeadRoot {
return true, nil
}
newHead, err = c.beaconDB.Block(bytesutil.ToBytes32(newHead.ParentRootHash32))
newHead, err = c.beaconDB.Block(bytesutil.ToBytes32(newHead.ParentRoot))
if err != nil {
return false, err
}
@@ -367,7 +366,11 @@ func (c *ChainService) isDescendant(currentHead *pb.BeaconBlock, newHead *pb.Bea
// each attestation target consists of validator index and its attestation target (i.e. the block
// which the validator attested to)
func (c *ChainService) AttestationTargets(state *pb.BeaconState) (map[uint64]*pb.AttestationTarget, error) {
indices := helpers.ActiveValidatorIndices(state.ValidatorRegistry, helpers.CurrentEpoch(state))
indices, err := helpers.ActiveValidatorIndices(state, helpers.CurrentEpoch(state))
if err != nil {
return nil, err
}
attestationTargets := make(map[uint64]*pb.AttestationTarget)
for i, index := range indices {
target, err := c.attsService.LatestAttestationTarget(state, index)
@@ -397,7 +400,7 @@ func VoteCount(block *pb.BeaconBlock, state *pb.BeaconState, targets map[uint64]
var ancestorRoot []byte
var err error
blockRoot, err := hashutil.HashBeaconBlock(block)
blockRoot, err := ssz.SigningRoot(block)
if err != nil {
return 0, err
}
@@ -417,7 +420,7 @@ func VoteCount(block *pb.BeaconBlock, state *pb.BeaconState, targets map[uint64]
}
if bytes.Equal(blockRoot[:], ancestorRoot) {
balances += int(helpers.EffectiveBalance(state, validatorIndex))
balances += int(state.Validators[validatorIndex].EffectiveBalance)
}
}
return balances, nil
@@ -454,7 +457,7 @@ func BlockAncestor(targetBlock *pb.AttestationTarget, slot uint64, beaconDB *db.
newTarget := &pb.AttestationTarget{
Slot: parent.Slot,
BlockRoot: parentRoot[:],
ParentRoot: parent.ParentRootHash32,
ParentRoot: parent.ParentRoot,
}
return BlockAncestor(newTarget, slot, beaconDB)
}
@@ -485,7 +488,7 @@ func cachedAncestor(target *pb.AttestationTarget, height uint64, beaconDB *db.Be
ancestorTarget := &pb.AttestationTarget{
Slot: ancestor.Slot,
BlockRoot: ancestorRoot,
ParentRoot: ancestor.ParentRootHash32,
ParentRoot: ancestor.ParentRoot,
}
if err := blkAncestorCache.AddBlockAncestor(&cache.AncestorInfo{
Height: height,

View File

@@ -5,10 +5,10 @@ import (
"testing"
"github.com/gogo/protobuf/proto"
"github.com/prysmaticlabs/go-ssz"
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
"github.com/prysmaticlabs/prysm/beacon-chain/internal"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/hashutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
logTest "github.com/sirupsen/logrus/hooks/test"
@@ -27,20 +27,22 @@ func (m *mockAttestationHandler) BatchUpdateLatestAttestation(ctx context.Contex
}
func TestApplyForkChoice_ChainSplitReorg(t *testing.T) {
// TODO(#2307): Fix test once v0.6 is merged.
t.Skip()
hook := logTest.NewGlobal()
beaconDB := internal.SetupDB(t)
defer internal.TeardownDB(t, beaconDB)
ctx := context.Background()
deposits, _ := setupInitialDeposits(t, 100)
eth1Data := &pb.Eth1Data{
DepositRootHash32: []byte{},
BlockHash32: []byte{},
}
justifiedState, err := state.GenesisBeaconState(deposits, 0, eth1Data)
deposits, _ := testutil.SetupInitialDeposits(t, 100, false)
justifiedState, err := state.GenesisBeaconState(deposits, 0, nil)
if err != nil {
t.Fatalf("Can't generate genesis state: %v", err)
}
justifiedState.StateRoots = make([][]byte, params.BeaconConfig().HistoricalRootsLimit)
justifiedState.LatestBlockHeader = &pb.BeaconBlockHeader{
StateRoot: []byte{},
}
chainService := setupBeaconChain(t, beaconDB, nil)
@@ -54,7 +56,6 @@ func TestApplyForkChoice_ChainSplitReorg(t *testing.T) {
if err := chainService.beaconDB.SaveBlock(blocks[0]); err != nil {
t.Fatal(err)
}
justifiedState.LatestBlock = blocks[0]
if err := chainService.beaconDB.SaveJustifiedState(justifiedState); err != nil {
t.Fatal(err)
}
@@ -67,7 +68,7 @@ func TestApplyForkChoice_ChainSplitReorg(t *testing.T) {
canonicalBlockIndices := []int{1, 3, 5}
postState := proto.Clone(justifiedState).(*pb.BeaconState)
for _, canonicalIndex := range canonicalBlockIndices {
postState, err = chainService.ApplyBlockStateTransition(ctx, blocks[canonicalIndex], postState)
postState, err = chainService.AdvanceState(ctx, postState, blocks[canonicalIndex])
if err != nil {
t.Fatal(err)
}
@@ -86,8 +87,8 @@ func TestApplyForkChoice_ChainSplitReorg(t *testing.T) {
if chainHead.Slot != justifiedState.Slot+5 {
t.Errorf(
"Expected chain head with slot %d, received %d",
justifiedState.Slot+5-params.BeaconConfig().GenesisSlot,
chainHead.Slot-params.BeaconConfig().GenesisSlot,
justifiedState.Slot+5,
chainHead.Slot,
)
}
@@ -96,7 +97,7 @@ func TestApplyForkChoice_ChainSplitReorg(t *testing.T) {
forkedBlockIndices := []int{2, 4}
forkState := proto.Clone(justifiedState).(*pb.BeaconState)
for _, forkIndex := range forkedBlockIndices {
forkState, err = chainService.ApplyBlockStateTransition(ctx, blocks[forkIndex], forkState)
forkState, err = chainService.AdvanceState(ctx, forkState, blocks[forkIndex])
if err != nil {
t.Fatal(err)
}
@@ -113,13 +114,13 @@ func TestApplyForkChoice_ChainSplitReorg(t *testing.T) {
voteTargets[0] = &pb.AttestationTarget{
Slot: blocks[5].Slot,
BlockRoot: roots[5][:],
ParentRoot: blocks[5].ParentRootHash32,
ParentRoot: blocks[5].ParentRoot,
}
for i := 1; i < len(deposits); i++ {
voteTargets[uint64(i)] = &pb.AttestationTarget{
Slot: blocks[4].Slot,
BlockRoot: roots[4][:],
ParentRoot: blocks[4].ParentRootHash32,
ParentRoot: blocks[4].ParentRoot,
}
}
attHandler := &mockAttestationHandler{
@@ -159,61 +160,73 @@ func constructForkedChain(t *testing.T, beaconState *pb.BeaconState) ([]*pb.Beac
roots := make([][32]byte, 6)
var err error
blocks[0] = &pb.BeaconBlock{
Slot: beaconState.Slot,
ParentRootHash32: []byte{'A'},
Body: &pb.BeaconBlockBody{},
Slot: beaconState.Slot,
ParentRoot: []byte{'A'},
Body: &pb.BeaconBlockBody{
Eth1Data: &pb.Eth1Data{},
},
}
roots[0], err = hashutil.HashBeaconBlock(blocks[0])
roots[0], err = ssz.SigningRoot(blocks[0])
if err != nil {
t.Fatalf("Could not hash block: %v", err)
}
blocks[1] = &pb.BeaconBlock{
Slot: beaconState.Slot + 2,
ParentRootHash32: roots[0][:],
Body: &pb.BeaconBlockBody{},
Slot: beaconState.Slot + 2,
ParentRoot: roots[0][:],
Body: &pb.BeaconBlockBody{
Eth1Data: &pb.Eth1Data{},
},
}
roots[1], err = hashutil.HashBeaconBlock(blocks[1])
roots[1], err = ssz.SigningRoot(blocks[1])
if err != nil {
t.Fatalf("Could not hash block: %v", err)
}
blocks[2] = &pb.BeaconBlock{
Slot: beaconState.Slot + 1,
ParentRootHash32: roots[0][:],
Body: &pb.BeaconBlockBody{},
Slot: beaconState.Slot + 1,
ParentRoot: roots[0][:],
Body: &pb.BeaconBlockBody{
Eth1Data: &pb.Eth1Data{},
},
}
roots[2], err = hashutil.HashBeaconBlock(blocks[2])
roots[2], err = ssz.SigningRoot(blocks[2])
if err != nil {
t.Fatalf("Could not hash block: %v", err)
}
blocks[3] = &pb.BeaconBlock{
Slot: beaconState.Slot + 3,
ParentRootHash32: roots[1][:],
Body: &pb.BeaconBlockBody{},
Slot: beaconState.Slot + 3,
ParentRoot: roots[1][:],
Body: &pb.BeaconBlockBody{
Eth1Data: &pb.Eth1Data{},
},
}
roots[3], err = hashutil.HashBeaconBlock(blocks[3])
roots[3], err = ssz.SigningRoot(blocks[3])
if err != nil {
t.Fatalf("Could not hash block: %v", err)
}
blocks[4] = &pb.BeaconBlock{
Slot: beaconState.Slot + 4,
ParentRootHash32: roots[2][:],
Body: &pb.BeaconBlockBody{},
Slot: beaconState.Slot + 4,
ParentRoot: roots[2][:],
Body: &pb.BeaconBlockBody{
Eth1Data: &pb.Eth1Data{},
},
}
roots[4], err = hashutil.HashBeaconBlock(blocks[4])
roots[4], err = ssz.SigningRoot(blocks[4])
if err != nil {
t.Fatalf("Could not hash block: %v", err)
}
blocks[5] = &pb.BeaconBlock{
Slot: beaconState.Slot + 5,
ParentRootHash32: roots[3][:],
Body: &pb.BeaconBlockBody{},
Slot: beaconState.Slot + 5,
ParentRoot: roots[3][:],
Body: &pb.BeaconBlockBody{
Eth1Data: &pb.Eth1Data{},
},
}
roots[5], err = hashutil.HashBeaconBlock(blocks[5])
roots[5], err = ssz.SigningRoot(blocks[5])
if err != nil {
t.Fatalf("Could not hash block: %v", err)
}

File diff suppressed because it is too large Load Diff

View File

@@ -11,6 +11,7 @@ import (
"sync"
"time"
"github.com/prysmaticlabs/go-ssz"
"github.com/prysmaticlabs/prysm/beacon-chain/attestation"
b "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/db"
@@ -18,7 +19,6 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/event"
"github.com/prysmaticlabs/prysm/shared/hashutil"
"github.com/prysmaticlabs/prysm/shared/p2p"
"github.com/sirupsen/logrus"
"go.opencensus.io/trace"
@@ -95,7 +95,7 @@ func (c *ChainService) Start() {
if beaconState != nil {
log.Info("Beacon chain data already exists, starting service")
c.genesisTime = time.Unix(int64(beaconState.GenesisTime), 0)
c.finalizedEpoch = beaconState.FinalizedEpoch
c.finalizedEpoch = beaconState.FinalizedCheckpoint.Epoch
} else {
log.Info("Waiting for ChainStart log from the Validator Deposit Contract to start the beacon chain...")
if c.web3Service == nil {
@@ -114,17 +114,12 @@ func (c *ChainService) Start() {
// processChainStartTime initializes a series of deposits from the ChainStart deposits in the eth1
// deposit contract, initializes the beacon chain's state, and kicks off the beacon chain.
func (c *ChainService) processChainStartTime(genesisTime time.Time, chainStartSub event.Subscription) {
initialDepositsData := c.web3Service.ChainStartDeposits()
initialDeposits := make([]*pb.Deposit, len(initialDepositsData))
for i := range initialDepositsData {
initialDeposits[i] = &pb.Deposit{DepositData: initialDepositsData[i]}
}
initialDeposits := c.web3Service.ChainStartDeposits()
beaconState, err := c.initializeBeaconChain(genesisTime, initialDeposits, c.web3Service.ChainStartETH1Data())
if err != nil {
log.Fatalf("Could not initialize beacon chain: %v", err)
}
c.finalizedEpoch = beaconState.FinalizedEpoch
c.finalizedEpoch = beaconState.FinalizedCheckpoint.Epoch
c.stateInitializedFeed.Send(genesisTime)
chainStartSub.Unsubscribe()
}
@@ -132,8 +127,7 @@ func (c *ChainService) processChainStartTime(genesisTime time.Time, chainStartSu
// initializes the state and genesis block of the beacon chain to persistent storage
// based on a genesis timestamp value obtained from the ChainStart event emitted
// by the ETH1.0 Deposit Contract and the POWChain service of the node.
func (c *ChainService) initializeBeaconChain(genesisTime time.Time, deposits []*pb.Deposit,
eth1data *pb.Eth1Data) (*pb.BeaconState, error) {
func (c *ChainService) initializeBeaconChain(genesisTime time.Time, deposits []*pb.Deposit, eth1data *pb.Eth1Data) (*pb.BeaconState, error) {
ctx, span := trace.StartSpan(context.Background(), "beacon-chain.ChainService.initializeBeaconChain")
defer span.End()
log.Info("ChainStart time reached, starting the beacon chain!")
@@ -147,26 +141,23 @@ func (c *ChainService) initializeBeaconChain(genesisTime time.Time, deposits []*
return nil, fmt.Errorf("could not attempt fetch beacon state: %v", err)
}
stateRoot, err := hashutil.HashProto(beaconState)
stateRoot, err := ssz.HashTreeRoot(beaconState)
if err != nil {
return nil, fmt.Errorf("could not hash beacon state: %v", err)
}
genBlock := b.NewGenesisBlock(stateRoot[:])
genBlockRoot, err := hashutil.HashBeaconBlock(genBlock)
genBlockRoot, err := ssz.SigningRoot(genBlock)
if err != nil {
return nil, fmt.Errorf("could not hash beacon block: %v", err)
}
// TODO(#2011): Remove this in state caching.
beaconState.LatestBlock = genBlock
if err := c.beaconDB.SaveBlock(genBlock); err != nil {
return nil, fmt.Errorf("could not save genesis block to disk: %v", err)
}
if err := c.beaconDB.SaveAttestationTarget(ctx, &pb.AttestationTarget{
Slot: genBlock.Slot,
BlockRoot: genBlockRoot[:],
ParentRoot: genBlock.ParentRootHash32,
ParentRoot: genBlock.ParentRoot,
}); err != nil {
return nil, fmt.Errorf("failed to save attestation target: %v", err)
}
@@ -225,7 +216,7 @@ func (c *ChainService) ChainHeadRoot() ([32]byte, error) {
return [32]byte{}, fmt.Errorf("could not retrieve chain head: %v", err)
}
root, err := hashutil.HashBeaconBlock(head)
root, err := ssz.SigningRoot(head)
if err != nil {
return [32]byte{}, fmt.Errorf("could not tree hash parent block: %v", err)
}

View File

@@ -2,8 +2,6 @@ package blockchain
import (
"context"
"crypto/rand"
"encoding/binary"
"errors"
"io/ioutil"
"math/big"
@@ -14,18 +12,15 @@ import (
"github.com/ethereum/go-ethereum/common"
gethTypes "github.com/ethereum/go-ethereum/core/types"
"github.com/gogo/protobuf/proto"
"github.com/prysmaticlabs/go-ssz"
"github.com/prysmaticlabs/prysm/beacon-chain/attestation"
b "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/db"
"github.com/prysmaticlabs/prysm/beacon-chain/internal"
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/event"
"github.com/prysmaticlabs/prysm/shared/featureconfig"
"github.com/prysmaticlabs/prysm/shared/forkutil"
"github.com/prysmaticlabs/prysm/shared/hashutil"
"github.com/prysmaticlabs/prysm/shared/p2p"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
@@ -156,54 +151,13 @@ func (mb *mockBroadcaster) Broadcast(_ context.Context, _ proto.Message) {
var _ = p2p.Broadcaster(&mockBroadcaster{})
func setupInitialDeposits(t *testing.T, numDeposits int) ([]*pb.Deposit, []*bls.SecretKey) {
privKeys := make([]*bls.SecretKey, numDeposits)
deposits := make([]*pb.Deposit, numDeposits)
for i := 0; i < len(deposits); i++ {
priv, err := bls.RandKey(rand.Reader)
if err != nil {
t.Fatal(err)
}
depositInput := &pb.DepositInput{
Pubkey: priv.PublicKey().Marshal(),
}
balance := params.BeaconConfig().MaxDepositAmount
depositData, err := helpers.EncodeDepositData(depositInput, balance, time.Now().Unix())
if err != nil {
t.Fatalf("Cannot encode data: %v", err)
}
deposits[i] = &pb.Deposit{
DepositData: depositData,
MerkleTreeIndex: uint64(i),
}
privKeys[i] = priv
}
return deposits, privKeys
}
func createPreChainStartDeposit(pk []byte) *pb.Deposit {
balance := params.BeaconConfig().MaxEffectiveBalance
depositData := &pb.DepositData{Pubkey: pk, Amount: balance, Signature: make([]byte, 96)}
func createPreChainStartDeposit(t *testing.T, pk []byte, index uint64) *pb.Deposit {
depositInput := &pb.DepositInput{Pubkey: pk}
balance := params.BeaconConfig().MaxDepositAmount
depositData, err := helpers.EncodeDepositData(depositInput, balance, time.Now().Unix())
if err != nil {
t.Fatalf("Cannot encode data: %v", err)
return &pb.Deposit{
Data: depositData,
}
return &pb.Deposit{DepositData: depositData, MerkleTreeIndex: index}
}
func createRandaoReveal(t *testing.T, beaconState *pb.BeaconState, privKeys []*bls.SecretKey) []byte {
// We fetch the proposer's index as that is whom the RANDAO will be verified against.
proposerIdx, err := helpers.BeaconProposerIndex(beaconState, beaconState.Slot)
if err != nil {
t.Fatal(err)
}
epoch := helpers.SlotToEpoch(beaconState.Slot)
buf := make([]byte, 32)
binary.LittleEndian.PutUint64(buf, epoch)
domain := forkutil.DomainVersion(beaconState.Fork, epoch, params.BeaconConfig().DomainRandao)
// We make the previous validator's index sign the message instead of the proposer.
epochSignature := privKeys[proposerIdx].Sign(buf, domain)
return epochSignature.Marshal()
}
func setupGenesisBlock(t *testing.T, cs *ChainService) ([32]byte, *pb.BeaconBlock) {
@@ -211,7 +165,7 @@ func setupGenesisBlock(t *testing.T, cs *ChainService) ([32]byte, *pb.BeaconBloc
if err := cs.beaconDB.SaveBlock(genesis); err != nil {
t.Fatalf("could not save block to db: %v", err)
}
parentHash, err := hashutil.HashBeaconBlock(genesis)
parentHash, err := ssz.SigningRoot(genesis)
if err != nil {
t.Fatalf("unable to get tree hash root of canonical head: %v", err)
}
@@ -289,7 +243,7 @@ func TestChainStartStop_Uninitialized(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if beaconState == nil || beaconState.Slot != params.BeaconConfig().GenesisSlot {
if beaconState == nil || beaconState.Slot != 0 {
t.Error("Expected canonical state feed to send a state with genesis block")
}
if err := chainService.Stop(); err != nil {
@@ -311,8 +265,8 @@ func TestChainStartStop_Initialized(t *testing.T) {
chainService := setupBeaconChain(t, db, nil)
unixTime := uint64(time.Now().Unix())
deposits, _ := setupInitialDeposits(t, 100)
if err := db.InitializeState(context.Background(), unixTime, deposits, &pb.Eth1Data{}); err != nil {
deposits, _ := testutil.SetupInitialDeposits(t, 100, false)
if err := db.InitializeState(context.Background(), unixTime, deposits, nil); err != nil {
t.Fatalf("Could not initialize beacon state to disk: %v", err)
}
setupGenesisBlock(t, chainService)

View File

@@ -1,32 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = ["state_generator.go"],
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/stategenerator",
visibility = ["//beacon-chain:__subpackages__"],
deps = [
"//beacon-chain/core/state:go_default_library",
"//beacon-chain/db:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//shared/bytesutil:go_default_library",
"//shared/hashutil:go_default_library",
"//shared/params:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@io_opencensus_go//trace:go_default_library",
],
)
go_test(
name = "go_default_test",
size = "small",
srcs = ["state_generator_test.go"],
embed = [":go_default_library"],
deps = [
"//beacon-chain/chaintest/backend:go_default_library",
"//beacon-chain/db:go_default_library",
"//shared/featureconfig:go_default_library",
"//shared/params:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
],
)

View File

@@ -1,179 +0,0 @@
package stategenerator
import (
"context"
"fmt"
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
"github.com/prysmaticlabs/prysm/beacon-chain/db"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/hashutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/sirupsen/logrus"
"go.opencensus.io/trace"
)
var log = logrus.WithField("prefix", "stategenerator")
// GenerateStateFromBlock generates state from the last finalized state to the input slot.
// Ex:
// 1A - 2B(finalized) - 3C - 4 - 5D - 6 - 7F (letters mean there's a block).
// Input: slot 6.
// Output: resulting state of state transition function after applying block C and D.
// along with skipped slot 4 and 6.
func GenerateStateFromBlock(ctx context.Context, db *db.BeaconDB, slot uint64) (*pb.BeaconState, error) {
ctx, span := trace.StartSpan(ctx, "beacon-chain.blockchain.stategenerator.GenerateStateFromBlock")
defer span.End()
fState, err := db.HistoricalStateFromSlot(ctx, slot, [32]byte{})
if err != nil {
return nil, err
}
// return finalized state if it's the same as input slot.
if fState.Slot == slot {
return fState, nil
}
// input slot can't be smaller than last finalized state's slot.
if fState.Slot > slot {
return nil, fmt.Errorf(
"requested slot %d < current slot %d in the finalized beacon state",
slot-params.BeaconConfig().GenesisSlot,
fState.Slot-params.BeaconConfig().GenesisSlot,
)
}
if fState.LatestBlock == nil {
return nil, fmt.Errorf("latest head in state is nil %v", err)
}
fRoot, err := hashutil.HashBeaconBlock(fState.LatestBlock)
if err != nil {
return nil, fmt.Errorf("unable to get block root %v", err)
}
// from input slot, retrieve its corresponding block and call that the most recent block.
mostRecentBlocks, err := db.BlocksBySlot(ctx, slot)
if err != nil {
return nil, err
}
mostRecentBlock := mostRecentBlocks[0]
// if the most recent block is a skip block, we get its parent block.
// ex:
// 1A - 2B - 3C - 4 - 5 (letters mean there's a block).
// input slot is 5, but slots 4 and 5 are skipped, we get block C from slot 3.
lastSlot := slot
for mostRecentBlock == nil {
lastSlot--
blocks, err := db.BlocksBySlot(ctx, lastSlot)
if err != nil {
return nil, err
}
mostRecentBlock = blocks[0]
}
// retrieve the block list to recompute state of the input slot.
blocks, err := blocksSinceFinalized(ctx, db, mostRecentBlock, fRoot)
if err != nil {
return nil, fmt.Errorf("unable to look up block ancestors %v", err)
}
log.Infof("Recompute state starting last finalized slot %d and ending slot %d",
fState.Slot-params.BeaconConfig().GenesisSlot, slot-params.BeaconConfig().GenesisSlot)
postState := fState
root := fRoot
// this recomputes state up to the last available block.
// ex: 1A - 2B (finalized) - 3C - 4 - 5 - 6C - 7 - 8 (C is the last block).
// input slot 8, this recomputes state to slot 6.
for i := len(blocks); i > 0; i-- {
block := blocks[i-1]
if block.Slot <= postState.Slot {
continue
}
// running state transitions for skipped slots.
for block.Slot != fState.Slot+1 {
postState, err = state.ExecuteStateTransition(
ctx,
postState,
nil,
root,
&state.TransitionConfig{
VerifySignatures: false,
Logging: false,
},
)
if err != nil {
return nil, fmt.Errorf("could not execute state transition %v", err)
}
}
postState, err = state.ExecuteStateTransition(
ctx,
postState,
block,
root,
&state.TransitionConfig{
VerifySignatures: false,
Logging: false,
},
)
if err != nil {
return nil, fmt.Errorf("could not execute state transition %v", err)
}
root, err = hashutil.HashBeaconBlock(block)
if err != nil {
return nil, fmt.Errorf("unable to get block root %v", err)
}
}
// this recomputes state from last block to last slot if there's skipp slots after.
// ex: 1A - 2B (finalized) - 3C - 4 - 5 - 6C - 7 - 8 (7 and 8 are skipped slots).
// input slot 8, this recomputes state from 6C to 8.
for i := postState.Slot; i < slot; i++ {
postState, err = state.ExecuteStateTransition(
ctx,
postState,
nil,
root,
&state.TransitionConfig{
VerifySignatures: false,
Logging: false,
},
)
if err != nil {
return nil, fmt.Errorf("could not execute state transition %v", err)
}
}
log.Infof("Finished recompute state with slot %d and finalized epoch %d",
postState.Slot-params.BeaconConfig().GenesisSlot, postState.FinalizedEpoch-params.BeaconConfig().GenesisEpoch)
return postState, nil
}
// blocksSinceFinalized will return a list of linked blocks that's
// between the input block and the last finalized block in the db.
// The input block is also returned in the list.
// Ex:
// A -> B(finalized) -> C -> D -> E -> D.
// Input: E, output: [E, D, C, B].
func blocksSinceFinalized(ctx context.Context, db *db.BeaconDB, block *pb.BeaconBlock,
finalizedBlockRoot [32]byte) ([]*pb.BeaconBlock, error) {
ctx, span := trace.StartSpan(ctx, "beacon-chain.blockchain.stategenerator.blocksSinceFinalized")
defer span.End()
blockAncestors := make([]*pb.BeaconBlock, 0)
blockAncestors = append(blockAncestors, block)
parentRoot := bytesutil.ToBytes32(block.ParentRootHash32)
// looking up ancestors, until the finalized block.
for parentRoot != finalizedBlockRoot {
retblock, err := db.Block(parentRoot)
if err != nil {
return nil, err
}
blockAncestors = append(blockAncestors, retblock)
parentRoot = bytesutil.ToBytes32(retblock.ParentRootHash32)
}
return blockAncestors, nil
}

View File

@@ -1,162 +0,0 @@
package stategenerator_test
import (
"context"
"testing"
"github.com/gogo/protobuf/proto"
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain/stategenerator"
"github.com/prysmaticlabs/prysm/beacon-chain/chaintest/backend"
"github.com/prysmaticlabs/prysm/beacon-chain/db"
"github.com/prysmaticlabs/prysm/shared/featureconfig"
"github.com/prysmaticlabs/prysm/shared/params"
)
func init() {
featureconfig.InitFeatureConfig(&featureconfig.FeatureFlagConfig{
CacheTreeHash: false,
})
}
func TestGenerateState_OK(t *testing.T) {
b, err := backend.NewSimulatedBackend()
if err != nil {
t.Fatalf("Could not create a new simulated backend %v", err)
}
privKeys, err := b.SetupBackend(100)
if err != nil {
t.Fatalf("Could not set up backend %v", err)
}
beaconDb := b.DB()
defer b.Shutdown()
defer db.TeardownDB(beaconDb)
ctx := context.Background()
slotLimit := uint64(30)
// Run the simulated chain for 30 slots, to get a state that we can save as finalized.
for i := uint64(0); i < slotLimit; i++ {
if err := b.GenerateBlockAndAdvanceChain(&backend.SimulatedObjects{}, privKeys); err != nil {
t.Fatalf("Could not generate block and transition state successfully %v for slot %d", err, b.State().Slot+1)
}
inMemBlocks := b.InMemoryBlocks()
if err := beaconDb.SaveBlock(inMemBlocks[len(inMemBlocks)-1]); err != nil {
t.Fatalf("Unable to save block %v", err)
}
if err := beaconDb.UpdateChainHead(ctx, inMemBlocks[len(inMemBlocks)-1], b.State()); err != nil {
t.Fatalf("Unable to save block %v", err)
}
if err := beaconDb.SaveFinalizedBlock(inMemBlocks[len(inMemBlocks)-1]); err != nil {
t.Fatalf("Unable to save finalized state: %v", err)
}
}
if err := beaconDb.SaveFinalizedState(b.State()); err != nil {
t.Fatalf("Unable to save finalized state: %v", err)
}
// Run the chain for another 30 slots so that we can have this at the current head.
for i := uint64(0); i < slotLimit; i++ {
if err := b.GenerateBlockAndAdvanceChain(&backend.SimulatedObjects{}, privKeys); err != nil {
t.Fatalf("Could not generate block and transition state successfully %v for slot %d", err, b.State().Slot+1)
}
inMemBlocks := b.InMemoryBlocks()
if err := beaconDb.SaveBlock(inMemBlocks[len(inMemBlocks)-1]); err != nil {
t.Fatalf("Unable to save block %v", err)
}
if err := beaconDb.UpdateChainHead(ctx, inMemBlocks[len(inMemBlocks)-1], b.State()); err != nil {
t.Fatalf("Unable to save block %v", err)
}
}
// Ran 30 slots to save finalized slot then ran another 30 slots.
slotToGenerateTill := params.BeaconConfig().GenesisSlot + slotLimit*2
newState, err := stategenerator.GenerateStateFromBlock(context.Background(), beaconDb, slotToGenerateTill)
if err != nil {
t.Fatalf("Unable to generate new state from previous finalized state %v", err)
}
if newState.Slot != b.State().Slot {
t.Fatalf("The generated state and the current state do not have the same slot, expected: %d but got %d",
b.State().Slot, newState.Slot)
}
if !proto.Equal(newState, b.State()) {
t.Error("Generated and saved states are unequal")
}
}
func TestGenerateState_WithNilBlocksOK(t *testing.T) {
b, err := backend.NewSimulatedBackend()
if err != nil {
t.Fatalf("Could not create a new simulated backend %v", err)
}
privKeys, err := b.SetupBackend(100)
if err != nil {
t.Fatalf("Could not set up backend %v", err)
}
beaconDb := b.DB()
defer b.Shutdown()
defer db.TeardownDB(beaconDb)
ctx := context.Background()
slotLimit := uint64(30)
// Run the simulated chain for 30 slots, to get a state that we can save as finalized.
for i := uint64(0); i < slotLimit; i++ {
if err := b.GenerateBlockAndAdvanceChain(&backend.SimulatedObjects{}, privKeys); err != nil {
t.Fatalf("Could not generate block and transition state successfully %v for slot %d", err, b.State().Slot+1)
}
inMemBlocks := b.InMemoryBlocks()
if err := beaconDb.SaveBlock(inMemBlocks[len(inMemBlocks)-1]); err != nil {
t.Fatalf("Unable to save block %v", err)
}
if err := beaconDb.UpdateChainHead(ctx, inMemBlocks[len(inMemBlocks)-1], b.State()); err != nil {
t.Fatalf("Unable to save block %v", err)
}
if err := beaconDb.SaveFinalizedBlock(inMemBlocks[len(inMemBlocks)-1]); err != nil {
t.Fatalf("Unable to save finalized state: %v", err)
}
}
if err := beaconDb.SaveFinalizedState(b.State()); err != nil {
t.Fatalf("Unable to save finalized state")
}
slotsWithNil := uint64(10)
// Run the chain for 10 slots with nil blocks.
for i := uint64(0); i < slotsWithNil; i++ {
if err := b.GenerateNilBlockAndAdvanceChain(); err != nil {
t.Fatalf("Could not generate block and transition state successfully %v for slot %d", err, b.State().Slot+1)
}
}
for i := uint64(0); i < slotLimit-slotsWithNil; i++ {
if err := b.GenerateBlockAndAdvanceChain(&backend.SimulatedObjects{}, privKeys); err != nil {
t.Fatalf("Could not generate block and transition state successfully %v for slot %d", err, b.State().Slot+1)
}
inMemBlocks := b.InMemoryBlocks()
if err := beaconDb.SaveBlock(inMemBlocks[len(inMemBlocks)-1]); err != nil {
t.Fatalf("Unable to save block %v", err)
}
if err := beaconDb.UpdateChainHead(ctx, inMemBlocks[len(inMemBlocks)-1], b.State()); err != nil {
t.Fatalf("Unable to save block %v", err)
}
}
// Ran 30 slots to save finalized slot then ran another 10 slots w/o blocks and 20 slots w/ blocks.
slotToGenerateTill := params.BeaconConfig().GenesisSlot + slotLimit*2
newState, err := stategenerator.GenerateStateFromBlock(context.Background(), beaconDb, slotToGenerateTill)
if err != nil {
t.Fatalf("Unable to generate new state from previous finalized state %v", err)
}
if newState.Slot != b.State().Slot {
t.Fatalf("The generated state and the current state do not have the same slot, expected: %d but got %d",
b.State().Slot, newState.Slot)
}
if !proto.Equal(newState, b.State()) {
t.Error("generated and saved states are unequal")
}
}

View File

@@ -3,9 +3,17 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"active_balance.go",
"active_count.go",
"active_indices.go",
"attestation_data.go",
"block.go",
"committee.go",
"common.go",
"eth1_data.go",
"seed.go",
"shuffled_indices.go",
"start_shard.go",
"total_balance.go",
],
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/cache",
visibility = ["//beacon-chain:__subpackages__"],
@@ -23,15 +31,23 @@ go_test(
name = "go_default_test",
size = "small",
srcs = [
"active_balance_test.go",
"active_count_test.go",
"active_indices_test.go",
"attestation_data_test.go",
"block_test.go",
"committee_test.go",
"eth1_data_test.go",
"seed_test.go",
"shuffled_indices_test.go",
"start_shard_test.go",
"total_balance_test.go",
],
embed = [":go_default_library"],
race = "on",
deps = [
"//proto/beacon/p2p/v1:go_default_library",
"//proto/beacon/rpc/v1:go_default_library",
"//shared/params:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
],
)

98
beacon-chain/cache/active_balance.go vendored Normal file
View File

@@ -0,0 +1,98 @@
package cache
import (
"errors"
"strconv"
"sync"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/prysmaticlabs/prysm/shared/params"
"k8s.io/client-go/tools/cache"
)
var (
// ErrNotActiveBalanceInfo will be returned when a cache object is not a pointer to
// a ActiveBalanceByEpoch struct.
ErrNotActiveBalanceInfo = errors.New("object is not a active balance obj")
// maxActiveBalanceListSize defines the max number of active balance can cache.
maxActiveBalanceListSize = 1000
// Metrics.
activeBalanceCacheMiss = promauto.NewCounter(prometheus.CounterOpts{
Name: "active_balance_cache_miss",
Help: "The number of active balance requests that aren't present in the cache.",
})
activeBalanceCacheHit = promauto.NewCounter(prometheus.CounterOpts{
Name: "active_balance_cache_hit",
Help: "The number of active balance requests that are present in the cache.",
})
)
// ActiveBalanceByEpoch defines the active validator balance per epoch.
type ActiveBalanceByEpoch struct {
Epoch uint64
ActiveBalance uint64
}
// ActiveBalanceCache is a struct with 1 queue for looking up active balance by epoch.
type ActiveBalanceCache struct {
activeBalanceCache *cache.FIFO
lock sync.RWMutex
}
// activeBalanceKeyFn takes the epoch as the key for the active balance of a given epoch.
func activeBalanceKeyFn(obj interface{}) (string, error) {
tInfo, ok := obj.(*ActiveBalanceByEpoch)
if !ok {
return "", ErrNotActiveBalanceInfo
}
return strconv.Itoa(int(tInfo.Epoch)), nil
}
// NewActiveBalanceCache creates a new active balance cache for storing/accessing active validator balance.
func NewActiveBalanceCache() *ActiveBalanceCache {
return &ActiveBalanceCache{
activeBalanceCache: cache.NewFIFO(activeBalanceKeyFn),
}
}
// ActiveBalanceInEpoch fetches ActiveBalanceByEpoch by epoch. Returns true with a
// reference to the ActiveBalanceInEpoch info, if exists. Otherwise returns false, nil.
func (c *ActiveBalanceCache) ActiveBalanceInEpoch(epoch uint64) (uint64, error) {
c.lock.RLock()
defer c.lock.RUnlock()
obj, exists, err := c.activeBalanceCache.GetByKey(strconv.Itoa(int(epoch)))
if err != nil {
return params.BeaconConfig().FarFutureEpoch, err
}
if exists {
activeBalanceCacheHit.Inc()
} else {
activeBalanceCacheMiss.Inc()
return params.BeaconConfig().FarFutureEpoch, nil
}
tInfo, ok := obj.(*ActiveBalanceByEpoch)
if !ok {
return params.BeaconConfig().FarFutureEpoch, ErrNotActiveBalanceInfo
}
return tInfo.ActiveBalance, nil
}
// AddActiveBalance adds ActiveBalanceByEpoch object to the cache. This method also trims the least
// recently added ActiveBalanceByEpoch object if the cache size has ready the max cache size limit.
func (c *ActiveBalanceCache) AddActiveBalance(activeBalance *ActiveBalanceByEpoch) error {
c.lock.Lock()
defer c.lock.Unlock()
if err := c.activeBalanceCache.AddIfNotPresent(activeBalance); err != nil {
return err
}
trim(c.activeBalanceCache, maxActiveBalanceListSize)
return nil
}

View File

@@ -0,0 +1,83 @@
package cache
import (
"reflect"
"strconv"
"testing"
"github.com/prysmaticlabs/prysm/shared/params"
)
func TestActiveBalanceKeyFn_OK(t *testing.T) {
tInfo := &ActiveBalanceByEpoch{
Epoch: 45,
ActiveBalance: 7456,
}
key, err := activeBalanceKeyFn(tInfo)
if err != nil {
t.Fatal(err)
}
if key != strconv.Itoa(int(tInfo.Epoch)) {
t.Errorf("Incorrect hash key: %s, expected %s", key, strconv.Itoa(int(tInfo.Epoch)))
}
}
func TestActiveBalanceKeyFn_InvalidObj(t *testing.T) {
_, err := activeBalanceKeyFn("bad")
if err != ErrNotActiveBalanceInfo {
t.Errorf("Expected error %v, got %v", ErrNotActiveBalanceInfo, err)
}
}
func TestActiveBalanceCache_ActiveBalanceByEpoch(t *testing.T) {
cache := NewActiveBalanceCache()
tInfo := &ActiveBalanceByEpoch{
Epoch: 16511,
ActiveBalance: 4456547,
}
activeBalance, err := cache.ActiveBalanceInEpoch(tInfo.Epoch)
if err != nil {
t.Fatal(err)
}
if activeBalance != params.BeaconConfig().FarFutureEpoch {
t.Error("Expected active balance not to exist in empty cache")
}
if err := cache.AddActiveBalance(tInfo); err != nil {
t.Fatal(err)
}
activeBalance, err = cache.ActiveBalanceInEpoch(tInfo.Epoch)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(activeBalance, tInfo.ActiveBalance) {
t.Errorf(
"Expected fetched active balance to be %v, got %v",
tInfo.ActiveBalance,
activeBalance,
)
}
}
func TestActiveBalance_MaxSize(t *testing.T) {
cache := NewActiveBalanceCache()
for i := uint64(0); i < 1001; i++ {
tInfo := &ActiveBalanceByEpoch{
Epoch: i,
}
if err := cache.AddActiveBalance(tInfo); err != nil {
t.Fatal(err)
}
}
if len(cache.activeBalanceCache.ListKeys()) != maxActiveBalanceListSize {
t.Errorf(
"Expected hash cache key size to be %d, got %d",
maxActiveBalanceListSize,
len(cache.activeBalanceCache.ListKeys()),
)
}
}

98
beacon-chain/cache/active_count.go vendored Normal file
View File

@@ -0,0 +1,98 @@
package cache
import (
"errors"
"strconv"
"sync"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/prysmaticlabs/prysm/shared/params"
"k8s.io/client-go/tools/cache"
)
var (
// ErrNotActiveCountInfo will be returned when a cache object is not a pointer to
// a ActiveCountByEpoch struct.
ErrNotActiveCountInfo = errors.New("object is not a active count obj")
// maxActiveCountListSize defines the max number of active count can cache.
maxActiveCountListSize = 1000
// Metrics.
activeCountCacheMiss = promauto.NewCounter(prometheus.CounterOpts{
Name: "active_validator_count_cache_miss",
Help: "The number of active validator count requests that aren't present in the cache.",
})
activeCountCacheHit = promauto.NewCounter(prometheus.CounterOpts{
Name: "active_validator_count_cache_hit",
Help: "The number of active validator count requests that are present in the cache.",
})
)
// ActiveCountByEpoch defines the active validator count per epoch.
type ActiveCountByEpoch struct {
Epoch uint64
ActiveCount uint64
}
// ActiveCountCache is a struct with 1 queue for looking up active count by epoch.
type ActiveCountCache struct {
activeCountCache *cache.FIFO
lock sync.RWMutex
}
// activeCountKeyFn takes the epoch as the key for the active count of a given epoch.
func activeCountKeyFn(obj interface{}) (string, error) {
aInfo, ok := obj.(*ActiveCountByEpoch)
if !ok {
return "", ErrNotActiveCountInfo
}
return strconv.Itoa(int(aInfo.Epoch)), nil
}
// NewActiveCountCache creates a new active count cache for storing/accessing active validator count.
func NewActiveCountCache() *ActiveCountCache {
return &ActiveCountCache{
activeCountCache: cache.NewFIFO(activeCountKeyFn),
}
}
// ActiveCountInEpoch fetches ActiveCountByEpoch by epoch. Returns true with a
// reference to the ActiveCountInEpoch info, if exists. Otherwise returns false, nil.
func (c *ActiveCountCache) ActiveCountInEpoch(epoch uint64) (uint64, error) {
c.lock.RLock()
defer c.lock.RUnlock()
obj, exists, err := c.activeCountCache.GetByKey(strconv.Itoa(int(epoch)))
if err != nil {
return params.BeaconConfig().FarFutureEpoch, err
}
if exists {
activeCountCacheHit.Inc()
} else {
activeCountCacheMiss.Inc()
return params.BeaconConfig().FarFutureEpoch, nil
}
aInfo, ok := obj.(*ActiveCountByEpoch)
if !ok {
return params.BeaconConfig().FarFutureEpoch, ErrNotActiveCountInfo
}
return aInfo.ActiveCount, nil
}
// AddActiveCount adds ActiveCountByEpoch object to the cache. This method also trims the least
// recently added ActiveCountByEpoch object if the cache size has ready the max cache size limit.
func (c *ActiveCountCache) AddActiveCount(activeCount *ActiveCountByEpoch) error {
c.lock.Lock()
defer c.lock.Unlock()
if err := c.activeCountCache.AddIfNotPresent(activeCount); err != nil {
return err
}
trim(c.activeCountCache, maxActiveCountListSize)
return nil
}

83
beacon-chain/cache/active_count_test.go vendored Normal file
View File

@@ -0,0 +1,83 @@
package cache
import (
"reflect"
"strconv"
"testing"
"github.com/prysmaticlabs/prysm/shared/params"
)
func TestActiveCountKeyFn_OK(t *testing.T) {
aInfo := &ActiveCountByEpoch{
Epoch: 999,
ActiveCount: 10,
}
key, err := activeCountKeyFn(aInfo)
if err != nil {
t.Fatal(err)
}
if key != strconv.Itoa(int(aInfo.Epoch)) {
t.Errorf("Incorrect hash key: %s, expected %s", key, strconv.Itoa(int(aInfo.Epoch)))
}
}
func TestActiveCountKeyFn_InvalidObj(t *testing.T) {
_, err := activeCountKeyFn("bad")
if err != ErrNotActiveCountInfo {
t.Errorf("Expected error %v, got %v", ErrNotActiveCountInfo, err)
}
}
func TestActiveCountCache_ActiveCountByEpoch(t *testing.T) {
cache := NewActiveCountCache()
aInfo := &ActiveCountByEpoch{
Epoch: 99,
ActiveCount: 11,
}
activeCount, err := cache.ActiveCountInEpoch(aInfo.Epoch)
if err != nil {
t.Fatal(err)
}
if activeCount != params.BeaconConfig().FarFutureEpoch {
t.Error("Expected active count not to exist in empty cache")
}
if err := cache.AddActiveCount(aInfo); err != nil {
t.Fatal(err)
}
activeCount, err = cache.ActiveCountInEpoch(aInfo.Epoch)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(activeCount, aInfo.ActiveCount) {
t.Errorf(
"Expected fetched active count to be %v, got %v",
aInfo.ActiveCount,
activeCount,
)
}
}
func TestActiveCount_MaxSize(t *testing.T) {
cache := NewActiveCountCache()
for i := uint64(0); i < 1001; i++ {
aInfo := &ActiveCountByEpoch{
Epoch: i,
}
if err := cache.AddActiveCount(aInfo); err != nil {
t.Fatal(err)
}
}
if len(cache.activeCountCache.ListKeys()) != maxActiveCountListSize {
t.Errorf(
"Expected hash cache key size to be %d, got %d",
maxActiveCountListSize,
len(cache.activeCountCache.ListKeys()),
)
}
}

102
beacon-chain/cache/active_indices.go vendored Normal file
View File

@@ -0,0 +1,102 @@
package cache
import (
"errors"
"strconv"
"sync"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"k8s.io/client-go/tools/cache"
)
var (
// ErrNotActiveIndicesInfo will be returned when a cache object is not a pointer to
// a ActiveIndicesByEpoch struct.
ErrNotActiveIndicesInfo = errors.New("object is not a active indices list")
// maxActiveIndicesListSize defines the max number of active indices can cache.
maxActiveIndicesListSize = 4
// Metrics.
activeIndicesCacheMiss = promauto.NewCounter(prometheus.CounterOpts{
Name: "active_validator_indices_cache_miss",
Help: "The number of active validator indices requests that aren't present in the cache.",
})
activeIndicesCacheHit = promauto.NewCounter(prometheus.CounterOpts{
Name: "active_validator_indices_cache_hit",
Help: "The number of active validator indices requests that are present in the cache.",
})
)
// ActiveIndicesByEpoch defines the active validator indices per epoch.
type ActiveIndicesByEpoch struct {
Epoch uint64
ActiveIndices []uint64
}
// ActiveIndicesCache is a struct with 1 queue for looking up active indices by epoch.
type ActiveIndicesCache struct {
activeIndicesCache *cache.FIFO
lock sync.RWMutex
}
// activeIndicesKeyFn takes the epoch as the key for the active indices of a given epoch.
func activeIndicesKeyFn(obj interface{}) (string, error) {
aInfo, ok := obj.(*ActiveIndicesByEpoch)
if !ok {
return "", ErrNotActiveIndicesInfo
}
return strconv.Itoa(int(aInfo.Epoch)), nil
}
// NewActiveIndicesCache creates a new active indices cache for storing/accessing active validator indices.
func NewActiveIndicesCache() *ActiveIndicesCache {
return &ActiveIndicesCache{
activeIndicesCache: cache.NewFIFO(activeIndicesKeyFn),
}
}
// ActiveIndicesInEpoch fetches ActiveIndicesByEpoch by epoch. Returns true with a
// reference to the ActiveIndicesInEpoch info, if exists. Otherwise returns false, nil.
func (c *ActiveIndicesCache) ActiveIndicesInEpoch(epoch uint64) ([]uint64, error) {
c.lock.RLock()
defer c.lock.RUnlock()
obj, exists, err := c.activeIndicesCache.GetByKey(strconv.Itoa(int(epoch)))
if err != nil {
return nil, err
}
if exists {
activeIndicesCacheHit.Inc()
} else {
activeIndicesCacheMiss.Inc()
return nil, nil
}
aInfo, ok := obj.(*ActiveIndicesByEpoch)
if !ok {
return nil, ErrNotActiveIndicesInfo
}
return aInfo.ActiveIndices, nil
}
// AddActiveIndicesList adds ActiveIndicesByEpoch object to the cache. This method also trims the least
// recently added ActiveIndicesByEpoch object if the cache size has ready the max cache size limit.
func (c *ActiveIndicesCache) AddActiveIndicesList(activeIndices *ActiveIndicesByEpoch) error {
c.lock.Lock()
defer c.lock.Unlock()
if err := c.activeIndicesCache.AddIfNotPresent(activeIndices); err != nil {
return err
}
trim(c.activeIndicesCache, maxActiveIndicesListSize)
return nil
}
// ActiveIndicesKeys returns the keys of the active indices cache.
func (c *ActiveIndicesCache) ActiveIndicesKeys() []string {
return c.activeIndicesCache.ListKeys()
}

View File

@@ -0,0 +1,82 @@
package cache
import (
"reflect"
"strconv"
"testing"
)
func TestActiveIndicesKeyFn_OK(t *testing.T) {
aInfo := &ActiveIndicesByEpoch{
Epoch: 999,
ActiveIndices: []uint64{1, 2, 3, 4, 5},
}
key, err := activeIndicesKeyFn(aInfo)
if err != nil {
t.Fatal(err)
}
if key != strconv.Itoa(int(aInfo.Epoch)) {
t.Errorf("Incorrect hash key: %s, expected %s", key, strconv.Itoa(int(aInfo.Epoch)))
}
}
func TestActiveIndicesKeyFn_InvalidObj(t *testing.T) {
_, err := activeIndicesKeyFn("bad")
if err != ErrNotActiveIndicesInfo {
t.Errorf("Expected error %v, got %v", ErrNotActiveIndicesInfo, err)
}
}
func TestActiveIndicesCache_ActiveIndicesByEpoch(t *testing.T) {
cache := NewActiveIndicesCache()
aInfo := &ActiveIndicesByEpoch{
Epoch: 99,
ActiveIndices: []uint64{1, 2, 3, 4},
}
activeIndices, err := cache.ActiveIndicesInEpoch(aInfo.Epoch)
if err != nil {
t.Fatal(err)
}
if activeIndices != nil {
t.Error("Expected active indices not to exist in empty cache")
}
if err := cache.AddActiveIndicesList(aInfo); err != nil {
t.Fatal(err)
}
activeIndices, err = cache.ActiveIndicesInEpoch(aInfo.Epoch)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(activeIndices, aInfo.ActiveIndices) {
t.Errorf(
"Expected fetched active indices to be %v, got %v",
aInfo.ActiveIndices,
activeIndices,
)
}
}
func TestActiveIndices_MaxSize(t *testing.T) {
cache := NewActiveIndicesCache()
for i := uint64(0); i < 100; i++ {
aInfo := &ActiveIndicesByEpoch{
Epoch: i,
}
if err := cache.AddActiveIndicesList(aInfo); err != nil {
t.Fatal(err)
}
}
if len(cache.activeIndicesCache.ListKeys()) != maxActiveIndicesListSize {
t.Errorf(
"Expected hash cache key size to be %d, got %d",
maxActiveIndicesListSize,
len(cache.activeIndicesCache.ListKeys()),
)
}
}

View File

@@ -10,6 +10,7 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
pb "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1"
"k8s.io/client-go/tools/cache"
)
@@ -57,7 +58,7 @@ func NewAttestationCache() *AttestationCache {
// Get waits for any in progress calculation to complete before returning a
// cached response, if any.
func (c *AttestationCache) Get(ctx context.Context, req *pb.AttestationDataRequest) (*pb.AttestationDataResponse, error) {
func (c *AttestationCache) Get(ctx context.Context, req *pb.AttestationRequest) (*pbp2p.AttestationData, error) {
if req == nil {
return nil, errors.New("nil attestation data request")
}
@@ -105,7 +106,7 @@ func (c *AttestationCache) Get(ctx context.Context, req *pb.AttestationDataReque
// MarkInProgress a request so that any other similar requests will block on
// Get until MarkNotInProgress is called.
func (c *AttestationCache) MarkInProgress(req *pb.AttestationDataRequest) error {
func (c *AttestationCache) MarkInProgress(req *pb.AttestationRequest) error {
c.lock.Lock()
defer c.lock.Unlock()
s, e := reqToKey(req)
@@ -121,7 +122,7 @@ func (c *AttestationCache) MarkInProgress(req *pb.AttestationDataRequest) error
// MarkNotInProgress will release the lock on a given request. This should be
// called after put.
func (c *AttestationCache) MarkNotInProgress(req *pb.AttestationDataRequest) error {
func (c *AttestationCache) MarkNotInProgress(req *pb.AttestationRequest) error {
c.lock.Lock()
defer c.lock.Unlock()
s, e := reqToKey(req)
@@ -133,7 +134,7 @@ func (c *AttestationCache) MarkNotInProgress(req *pb.AttestationDataRequest) err
}
// Put the response in the cache.
func (c *AttestationCache) Put(ctx context.Context, req *pb.AttestationDataRequest, res *pb.AttestationDataResponse) error {
func (c *AttestationCache) Put(ctx context.Context, req *pb.AttestationRequest, res *pbp2p.AttestationData) error {
data := &attestationReqResWrapper{
req,
res,
@@ -158,11 +159,11 @@ func wrapperToKey(i interface{}) (string, error) {
return reqToKey(w.req)
}
func reqToKey(req *pb.AttestationDataRequest) (string, error) {
func reqToKey(req *pb.AttestationRequest) (string, error) {
return fmt.Sprintf("%d-%d", req.Shard, req.Slot), nil
}
type attestationReqResWrapper struct {
req *pb.AttestationDataRequest
res *pb.AttestationDataResponse
req *pb.AttestationRequest
res *pbp2p.AttestationData
}

View File

@@ -6,6 +6,7 @@ import (
"github.com/gogo/protobuf/proto"
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
pb "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1"
)
@@ -13,7 +14,7 @@ func TestAttestationCache_RoundTrip(t *testing.T) {
ctx := context.Background()
c := cache.NewAttestationCache()
req := &pb.AttestationDataRequest{
req := &pb.AttestationRequest{
Shard: 0,
Slot: 1,
}
@@ -31,8 +32,8 @@ func TestAttestationCache_RoundTrip(t *testing.T) {
t.Error(err)
}
res := &pb.AttestationDataResponse{
HeadSlot: 5,
res := &pbp2p.AttestationData{
Target: &pbp2p.Checkpoint{Epoch: 5},
}
if err = c.Put(ctx, req, res); err != nil {

View File

@@ -82,7 +82,7 @@ func (a *AncestorBlockCache) AncestorBySlot(blockHash []byte, height uint64) (*A
aInfo, ok := obj.(*AncestorInfo)
if !ok {
return nil, ErrNotACommitteeInfo
return nil, ErrNotAncestorCacheObj
}
return aInfo, nil

View File

@@ -1,127 +0,0 @@
package cache
import (
"errors"
"strconv"
"sync"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/prysmaticlabs/prysm/shared/params"
"k8s.io/client-go/tools/cache"
)
var (
// ErrNotACommitteeInfo will be returned when a cache object is not a pointer to
// a committeeInfo struct.
ErrNotACommitteeInfo = errors.New("object is not an committee info")
// maxCacheSize is 4x of the epoch length for additional cache padding.
// Requests should be only accessing committees within defined epoch length.
maxCacheSize = int(4 * params.BeaconConfig().SlotsPerEpoch)
// Metrics
committeeCacheMiss = promauto.NewCounter(prometheus.CounterOpts{
Name: "committee_cache_miss",
Help: "The number of committee requests that aren't present in the cache.",
})
committeeCacheHit = promauto.NewCounter(prometheus.CounterOpts{
Name: "committee_cache_hit",
Help: "The number of committee requests that are present in the cache.",
})
committeeCacheSize = promauto.NewGauge(prometheus.GaugeOpts{
Name: "committee_cache_size",
Help: "The number of committees in the committee cache",
})
)
// CommitteeInfo defines the validator committee of slot and shard combinations.
type CommitteeInfo struct {
Committee []uint64
Shard uint64
}
// CommitteesInSlot specifies how many CommitteeInfos are in a given slot.
type CommitteesInSlot struct {
Slot uint64
Committees []*CommitteeInfo
}
// CommitteesCache structs with 1 queue for looking up committees by slot.
type CommitteesCache struct {
committeesCache *cache.FIFO
lock sync.RWMutex
}
// slotKeyFn takes the string representation of the slot number as the key
// for the committees of a given slot (CommitteesInSlot).
func slotKeyFn(obj interface{}) (string, error) {
cInfo, ok := obj.(*CommitteesInSlot)
if !ok {
return "", ErrNotACommitteeInfo
}
return strconv.Itoa(int(cInfo.Slot)), nil
}
// NewCommitteesCache creates a new committee cache for storing/accessing blockInfo from
// memory.
func NewCommitteesCache() *CommitteesCache {
return &CommitteesCache{
committeesCache: cache.NewFIFO(slotKeyFn),
}
}
// CommitteesInfoBySlot fetches CommitteesInSlot by slot. Returns true with a
// reference to the committees info, if exists. Otherwise returns false, nil.
func (c *CommitteesCache) CommitteesInfoBySlot(slot uint64) (*CommitteesInSlot, error) {
c.lock.RLock()
defer c.lock.RUnlock()
obj, exists, err := c.committeesCache.GetByKey(strconv.Itoa(int(slot)))
if err != nil {
return nil, err
}
if exists {
committeeCacheHit.Inc()
} else {
committeeCacheMiss.Inc()
return nil, nil
}
cInfo, ok := obj.(*CommitteesInSlot)
if !ok {
return nil, ErrNotACommitteeInfo
}
return cInfo, nil
}
// AddCommittees adds CommitteesInSlot object to the cache. This method also trims the least
// recently added committeeInfo object if the cache size has ready the max cache size limit.
func (c *CommitteesCache) AddCommittees(committees *CommitteesInSlot) error {
c.lock.Lock()
defer c.lock.Unlock()
if err := c.committeesCache.AddIfNotPresent(committees); err != nil {
return err
}
trim(c.committeesCache, maxCacheSize)
committeeCacheSize.Set(float64(len(c.committeesCache.ListKeys())))
return nil
}
// trim the FIFO queue to the maxSize.
func trim(queue *cache.FIFO, maxSize int) {
for s := len(queue.ListKeys()); s > maxSize; s-- {
// #nosec G104 popProcessNoopFunc never returns an error
_, _ = queue.Pop(popProcessNoopFunc)
}
}
// popProcessNoopFunc is a no-op function that never returns an error.
func popProcessNoopFunc(obj interface{}) error {
return nil
}

View File

@@ -1,96 +0,0 @@
package cache
import (
"reflect"
"strconv"
"testing"
)
func TestSlotKeyFn_OK(t *testing.T) {
cInfo := &CommitteesInSlot{
Slot: 999,
Committees: []*CommitteeInfo{
{Shard: 1, Committee: []uint64{1, 2, 3}},
{Shard: 1, Committee: []uint64{4, 5, 6}},
},
}
key, err := slotKeyFn(cInfo)
if err != nil {
t.Fatal(err)
}
strSlot := strconv.Itoa(int(cInfo.Slot))
if key != strSlot {
t.Errorf("Incorrect hash key: %s, expected %s", key, strSlot)
}
}
func TestSlotKeyFn_InvalidObj(t *testing.T) {
_, err := slotKeyFn("bad")
if err != ErrNotACommitteeInfo {
t.Errorf("Expected error %v, got %v", ErrNotACommitteeInfo, err)
}
}
func TestCommitteesCache_CommitteesInfoBySlot(t *testing.T) {
cache := NewCommitteesCache()
cInfo := &CommitteesInSlot{
Slot: 123,
Committees: []*CommitteeInfo{{Shard: 456}},
}
fetchedInfo, err := cache.CommitteesInfoBySlot(cInfo.Slot)
if err != nil {
t.Fatal(err)
}
if fetchedInfo != nil {
t.Error("Expected committees info not to exist in empty cache")
}
if err := cache.AddCommittees(cInfo); err != nil {
t.Fatal(err)
}
fetchedInfo, err = cache.CommitteesInfoBySlot(cInfo.Slot)
if err != nil {
t.Fatal(err)
}
if fetchedInfo == nil {
t.Error("Expected committee info to exist")
}
if fetchedInfo.Slot != cInfo.Slot {
t.Errorf(
"Expected fetched slot number to be %d, got %d",
cInfo.Slot,
fetchedInfo.Slot,
)
}
if !reflect.DeepEqual(fetchedInfo.Committees, cInfo.Committees) {
t.Errorf(
"Expected fetched info committee to be %v, got %v",
cInfo.Committees,
fetchedInfo.Committees,
)
}
}
func TestBlockCache_maxSize(t *testing.T) {
cache := NewCommitteesCache()
for i := 0; i < maxCacheSize+10; i++ {
cInfo := &CommitteesInSlot{
Slot: uint64(i),
}
if err := cache.AddCommittees(cInfo); err != nil {
t.Fatal(err)
}
}
if len(cache.committeesCache.ListKeys()) != maxCacheSize {
t.Errorf(
"Expected hash cache key size to be %d, got %d",
maxCacheSize,
len(cache.committeesCache.ListKeys()),
)
}
}

25
beacon-chain/cache/common.go vendored Normal file
View File

@@ -0,0 +1,25 @@
package cache
import (
"github.com/prysmaticlabs/prysm/shared/params"
"k8s.io/client-go/tools/cache"
)
var (
// maxCacheSize is 4x of the epoch length for additional cache padding.
// Requests should be only accessing committees within defined epoch length.
maxCacheSize = int(4 * params.BeaconConfig().SlotsPerEpoch)
)
// trim the FIFO queue to the maxSize.
func trim(queue *cache.FIFO, maxSize int) {
for s := len(queue.ListKeys()); s > maxSize; s-- {
// #nosec G104 popProcessNoopFunc never returns an error
_, _ = queue.Pop(popProcessNoopFunc)
}
}
// popProcessNoopFunc is a no-op function that never returns an error.
func popProcessNoopFunc(obj interface{}) error {
return nil
}

121
beacon-chain/cache/eth1_data.go vendored Normal file
View File

@@ -0,0 +1,121 @@
package cache
import (
"errors"
"sync"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"k8s.io/client-go/tools/cache"
)
var (
// ErrNotEth1DataVote will be returned when a cache object is not a pointer to
// a Eth1DataVote struct.
ErrNotEth1DataVote = errors.New("object is not a eth1 data vote obj")
// maxEth1DataVoteSize defines the max number of eth1 data votes can cache.
maxEth1DataVoteSize = 1000
// Metrics.
eth1DataVoteCacheMiss = promauto.NewCounter(prometheus.CounterOpts{
Name: "eth1_data_vote_cache_miss",
Help: "The number of eth1 data vote count requests that aren't present in the cache.",
})
eth1DataVoteCacheHit = promauto.NewCounter(prometheus.CounterOpts{
Name: "eth1_data_vote_cache_hit",
Help: "The number of eth1 data vote count requests that are present in the cache.",
})
)
// Eth1DataVote defines the struct which keeps track of the vote count of individual deposit root.
type Eth1DataVote struct {
DepositRoot []byte
VoteCount uint64
}
// Eth1DataVoteCache is a struct with 1 queue for looking up eth1 data vote count by deposit root.
type Eth1DataVoteCache struct {
eth1DataVoteCache *cache.FIFO
lock sync.RWMutex
}
// eth1DataVoteKeyFn takes the deposit root as the key for the eth1 data vote count of a given root.
func eth1DataVoteKeyFn(obj interface{}) (string, error) {
eInfo, ok := obj.(*Eth1DataVote)
if !ok {
return "", ErrNotEth1DataVote
}
return string(eInfo.DepositRoot), nil
}
// NewEth1DataVoteCache creates a new eth1 data vote count cache for storing/accessing Eth1DataVote.
func NewEth1DataVoteCache() *Eth1DataVoteCache {
return &Eth1DataVoteCache{
eth1DataVoteCache: cache.NewFIFO(eth1DataVoteKeyFn),
}
}
// Eth1DataVote fetches eth1 data vote count by deposit root. Returns vote count,
// if exists. Otherwise returns false, nil.
func (c *Eth1DataVoteCache) Eth1DataVote(depositRoot []byte) (uint64, error) {
c.lock.RLock()
defer c.lock.RUnlock()
obj, exists, err := c.eth1DataVoteCache.GetByKey(string(depositRoot))
if err != nil {
return 0, err
}
if exists {
eth1DataVoteCacheHit.Inc()
} else {
eth1DataVoteCacheMiss.Inc()
return 0, nil
}
eInfo, ok := obj.(*Eth1DataVote)
if !ok {
return 0, ErrNotEth1DataVote
}
return eInfo.VoteCount, nil
}
// AddEth1DataVote adds eth1 data vote object to the cache. This method also trims the least
// recently added Eth1DataVoteByEpoch object if the cache size has ready the max cache size limit.
func (c *Eth1DataVoteCache) AddEth1DataVote(eth1DataVote *Eth1DataVote) error {
c.lock.Lock()
defer c.lock.Unlock()
if err := c.eth1DataVoteCache.Add(eth1DataVote); err != nil {
return err
}
trim(c.eth1DataVoteCache, maxEth1DataVoteSize)
return nil
}
// IncrementEth1DataVote increments the existing eth1 data object's vote count by 1,
// and returns the vote count.
func (c *Eth1DataVoteCache) IncrementEth1DataVote(depositRoot []byte) (uint64, error) {
c.lock.RLock()
defer c.lock.RUnlock()
obj, exists, err := c.eth1DataVoteCache.GetByKey(string(depositRoot))
if err != nil {
return 0, err
}
if !exists {
return 0, errors.New("eth1 data vote object does not exist")
}
eth1DataVoteCacheHit.Inc()
eInfo, _ := obj.(*Eth1DataVote)
eInfo.VoteCount++
if err := c.eth1DataVoteCache.Add(eInfo); err != nil {
return 0, err
}
return eInfo.VoteCount, nil
}

108
beacon-chain/cache/eth1_data_test.go vendored Normal file
View File

@@ -0,0 +1,108 @@
package cache
import (
"strconv"
"testing"
)
func TestEth1DataVoteKeyFn_OK(t *testing.T) {
eInfo := &Eth1DataVote{
VoteCount: 44,
DepositRoot: []byte{'A'},
}
key, err := eth1DataVoteKeyFn(eInfo)
if err != nil {
t.Fatal(err)
}
if key != string(eInfo.DepositRoot) {
t.Errorf("Incorrect hash key: %s, expected %s", key, string(eInfo.DepositRoot))
}
}
func TestEth1DataVoteKeyFn_InvalidObj(t *testing.T) {
_, err := eth1DataVoteKeyFn("bad")
if err != ErrNotEth1DataVote {
t.Errorf("Expected error %v, got %v", ErrNotEth1DataVote, err)
}
}
func TestEth1DataVoteCache_CanAdd(t *testing.T) {
cache := NewEth1DataVoteCache()
eInfo := &Eth1DataVote{
VoteCount: 55,
DepositRoot: []byte{'B'},
}
count, err := cache.Eth1DataVote(eInfo.DepositRoot)
if err != nil {
t.Fatal(err)
}
if count != 0 {
t.Error("Expected seed not to exist in empty cache")
}
if err := cache.AddEth1DataVote(eInfo); err != nil {
t.Fatal(err)
}
count, err = cache.Eth1DataVote(eInfo.DepositRoot)
if err != nil {
t.Fatal(err)
}
if count != eInfo.VoteCount {
t.Errorf(
"Expected vote count to be %d, got %d",
eInfo.VoteCount,
count,
)
}
}
func TestEth1DataVoteCache_CanIncrement(t *testing.T) {
cache := NewEth1DataVoteCache()
eInfo := &Eth1DataVote{
VoteCount: 55,
DepositRoot: []byte{'B'},
}
if err := cache.AddEth1DataVote(eInfo); err != nil {
t.Fatal(err)
}
_, err := cache.IncrementEth1DataVote(eInfo.DepositRoot)
if err != nil {
t.Fatal(err)
}
_, _ = cache.IncrementEth1DataVote(eInfo.DepositRoot)
count, _ := cache.IncrementEth1DataVote(eInfo.DepositRoot)
if count != 58 {
t.Errorf(
"Expected vote count to be %d, got %d",
58,
count,
)
}
}
func TestEth1Data_MaxSize(t *testing.T) {
cache := NewEth1DataVoteCache()
for i := 0; i < maxEth1DataVoteSize+1; i++ {
eInfo := &Eth1DataVote{
DepositRoot: []byte(strconv.Itoa(i)),
}
if err := cache.AddEth1DataVote(eInfo); err != nil {
t.Fatal(err)
}
}
if len(cache.eth1DataVoteCache.ListKeys()) != maxEth1DataVoteSize {
t.Errorf(
"Expected hash cache key size to be %d, got %d",
maxEth1DataVoteSize,
len(cache.eth1DataVoteCache.ListKeys()),
)
}
}

97
beacon-chain/cache/seed.go vendored Normal file
View File

@@ -0,0 +1,97 @@
package cache
import (
"errors"
"strconv"
"sync"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"k8s.io/client-go/tools/cache"
)
var (
// ErrNotSeedInfo will be returned when a cache object is not a pointer to
// a SeedByEpoch struct.
ErrNotSeedInfo = errors.New("object is not a seed obj")
// maxSeedListSize defines the max number of seed can cache.
maxSeedListSize = 1000
// Metrics.
seedCacheMiss = promauto.NewCounter(prometheus.CounterOpts{
Name: "seed_cache_miss",
Help: "The number of seed requests that aren't present in the cache.",
})
seedCacheHit = promauto.NewCounter(prometheus.CounterOpts{
Name: "seed_cache_hit",
Help: "The number of seed requests that are present in the cache.",
})
)
// SeedByEpoch defines the seed of the epoch.
type SeedByEpoch struct {
Epoch uint64
Seed []byte
}
// SeedCache is a struct with 1 queue for looking up seed by epoch.
type SeedCache struct {
seedCache *cache.FIFO
lock sync.RWMutex
}
// seedKeyFn takes the epoch as the key for the seed of a given epoch.
func seedKeyFn(obj interface{}) (string, error) {
sInfo, ok := obj.(*SeedByEpoch)
if !ok {
return "", ErrNotSeedInfo
}
return strconv.Itoa(int(sInfo.Epoch)), nil
}
// NewSeedCache creates a new seed cache for storing/accessing seed.
func NewSeedCache() *SeedCache {
return &SeedCache{
seedCache: cache.NewFIFO(seedKeyFn),
}
}
// SeedInEpoch fetches SeedByEpoch by epoch. Returns true with a
// reference to the SeedInEpoch info, if exists. Otherwise returns false, nil.
func (c *SeedCache) SeedInEpoch(epoch uint64) ([]byte, error) {
c.lock.RLock()
defer c.lock.RUnlock()
obj, exists, err := c.seedCache.GetByKey(strconv.Itoa(int(epoch)))
if err != nil {
return nil, err
}
if exists {
seedCacheHit.Inc()
} else {
seedCacheMiss.Inc()
return nil, nil
}
sInfo, ok := obj.(*SeedByEpoch)
if !ok {
return nil, ErrNotSeedInfo
}
return sInfo.Seed, nil
}
// AddSeed adds SeedByEpoch object to the cache. This method also trims the least
// recently added SeedByEpoch object if the cache size has ready the max cache size limit.
func (c *SeedCache) AddSeed(seed *SeedByEpoch) error {
c.lock.Lock()
defer c.lock.Unlock()
if err := c.seedCache.AddIfNotPresent(seed); err != nil {
return err
}
trim(c.seedCache, maxSeedListSize)
return nil
}

83
beacon-chain/cache/seed_test.go vendored Normal file
View File

@@ -0,0 +1,83 @@
package cache
import (
"reflect"
"strconv"
"testing"
"github.com/prysmaticlabs/prysm/shared/params"
)
func TestSeedKeyFn_OK(t *testing.T) {
tInfo := &SeedByEpoch{
Epoch: 44,
Seed: []byte{'A'},
}
key, err := seedKeyFn(tInfo)
if err != nil {
t.Fatal(err)
}
if key != strconv.Itoa(int(tInfo.Epoch)) {
t.Errorf("Incorrect hash key: %s, expected %s", key, strconv.Itoa(int(tInfo.Epoch)))
}
}
func TestSeedKeyFn_InvalidObj(t *testing.T) {
_, err := seedKeyFn("bad")
if err != ErrNotSeedInfo {
t.Errorf("Expected error %v, got %v", ErrNotSeedInfo, err)
}
}
func TestSeedCache_SeedByEpoch(t *testing.T) {
cache := NewSeedCache()
tInfo := &SeedByEpoch{
Epoch: 55,
Seed: []byte{'B'},
}
seed, err := cache.SeedInEpoch(tInfo.Epoch)
if err != nil {
t.Fatal(err)
}
if seed != nil {
t.Error("Expected seed not to exist in empty cache")
}
if err := cache.AddSeed(tInfo); err != nil {
t.Fatal(err)
}
seed, err = cache.SeedInEpoch(tInfo.Epoch)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(seed, tInfo.Seed) {
t.Errorf(
"Expected fetched seed to be %v, got %v",
tInfo.Seed,
seed,
)
}
}
func TestSeed_MaxSize(t *testing.T) {
cache := NewSeedCache()
for i := uint64(0); i < params.BeaconConfig().EpochsPerHistoricalVector+100; i++ {
tInfo := &SeedByEpoch{
Epoch: i,
}
if err := cache.AddSeed(tInfo); err != nil {
t.Fatal(err)
}
}
if len(cache.seedCache.ListKeys()) != maxSeedListSize {
t.Errorf(
"Expected hash cache key size to be %d, got %d",
maxSeedListSize,
len(cache.seedCache.ListKeys()),
)
}
}

99
beacon-chain/cache/shuffled_indices.go vendored Normal file
View File

@@ -0,0 +1,99 @@
package cache
import (
"errors"
"strconv"
"sync"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"k8s.io/client-go/tools/cache"
)
var (
// ErrNotValidatorListInfo will be returned when a cache object is not a pointer to
// a ValidatorList struct.
ErrNotValidatorListInfo = errors.New("object is not a shuffled validator list")
// maxShuffledListSize defines the max number of shuffled list can cache.
maxShuffledListSize = 1000
// Metrics.
shuffledIndicesCacheMiss = promauto.NewCounter(prometheus.CounterOpts{
Name: "shuffled_validators_cache_miss",
Help: "The number of shuffled validators requests that aren't present in the cache.",
})
shuffledIndicesCacheHit = promauto.NewCounter(prometheus.CounterOpts{
Name: "shuffled_validators_cache_hit",
Help: "The number of shuffled validators requests that are present in the cache.",
})
)
// IndicesByIndexSeed defines the shuffled validator indices per randao seed.
type IndicesByIndexSeed struct {
Index uint64
Seed []byte
ShuffledIndices []uint64
}
// ShuffledIndicesCache is a struct with 1 queue for looking up shuffled validators by seed.
type ShuffledIndicesCache struct {
shuffledIndicesCache *cache.FIFO
lock sync.RWMutex
}
// slotKeyFn takes the randao seed as the key for the shuffled validators of a given epoch.
func shuffleKeyFn(obj interface{}) (string, error) {
sInfo, ok := obj.(*IndicesByIndexSeed)
if !ok {
return "", ErrNotValidatorListInfo
}
return string(sInfo.Seed) + strconv.Itoa(int(sInfo.Index)), nil
}
// NewShuffledIndicesCache creates a new shuffled validators cache for storing/accessing shuffled validator indices
func NewShuffledIndicesCache() *ShuffledIndicesCache {
return &ShuffledIndicesCache{
shuffledIndicesCache: cache.NewFIFO(shuffleKeyFn),
}
}
// IndicesByIndexSeed fetches IndicesByIndexSeed by epoch and seed. Returns true with a
// reference to the ShuffledIndicesInEpoch info, if exists. Otherwise returns false, nil.
func (c *ShuffledIndicesCache) IndicesByIndexSeed(index uint64, seed []byte) ([]uint64, error) {
c.lock.RLock()
defer c.lock.RUnlock()
key := string(seed) + strconv.Itoa(int(index))
obj, exists, err := c.shuffledIndicesCache.GetByKey(key)
if err != nil {
return nil, err
}
if exists {
shuffledIndicesCacheHit.Inc()
} else {
shuffledIndicesCacheMiss.Inc()
return nil, nil
}
cInfo, ok := obj.(*IndicesByIndexSeed)
if !ok {
return nil, ErrNotValidatorListInfo
}
return cInfo.ShuffledIndices, nil
}
// AddShuffledValidatorList adds IndicesByIndexSeed object to the cache. This method also trims the least
// recently added IndicesByIndexSeed object if the cache size has ready the max cache size limit.
func (c *ShuffledIndicesCache) AddShuffledValidatorList(shuffledIndices *IndicesByIndexSeed) error {
c.lock.Lock()
defer c.lock.Unlock()
if err := c.shuffledIndicesCache.AddIfNotPresent(shuffledIndices); err != nil {
return err
}
trim(c.shuffledIndicesCache, maxShuffledListSize)
return nil
}

View File

@@ -0,0 +1,85 @@
package cache
import (
"reflect"
"strconv"
"testing"
)
func TestShuffleKeyFn_OK(t *testing.T) {
sInfo := &IndicesByIndexSeed{
Index: 999,
Seed: []byte{'A'},
ShuffledIndices: []uint64{1, 2, 3, 4, 5},
}
key, err := shuffleKeyFn(sInfo)
if err != nil {
t.Fatal(err)
}
if key != string(sInfo.Seed)+strconv.Itoa(int(sInfo.Index)) {
t.Errorf("Incorrect hash key: %s, expected %s", key, string(sInfo.Seed)+strconv.Itoa(int(sInfo.Index)))
}
}
func TestShuffleKeyFn_InvalidObj(t *testing.T) {
_, err := shuffleKeyFn("bad")
if err != ErrNotValidatorListInfo {
t.Errorf("Expected error %v, got %v", ErrNotValidatorListInfo, err)
}
}
func TestShuffledIndicesCache_ShuffledIndicesBySeed2(t *testing.T) {
cache := NewShuffledIndicesCache()
sInfo := &IndicesByIndexSeed{
Index: 99,
Seed: []byte{'A'},
ShuffledIndices: []uint64{1, 2, 3, 4},
}
shuffledIndices, err := cache.IndicesByIndexSeed(sInfo.Index, sInfo.Seed)
if err != nil {
t.Fatal(err)
}
if shuffledIndices != nil {
t.Error("Expected shuffled indices not to exist in empty cache")
}
if err := cache.AddShuffledValidatorList(sInfo); err != nil {
t.Fatal(err)
}
shuffledIndices, err = cache.IndicesByIndexSeed(sInfo.Index, sInfo.Seed)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(shuffledIndices, sInfo.ShuffledIndices) {
t.Errorf(
"Expected fetched info committee to be %v, got %v",
sInfo.ShuffledIndices,
shuffledIndices,
)
}
}
func TestShuffledIndices_MaxSize(t *testing.T) {
cache := NewShuffledIndicesCache()
for i := uint64(0); i < 1001; i++ {
sInfo := &IndicesByIndexSeed{
Index: i,
Seed: []byte{byte(i)},
}
if err := cache.AddShuffledValidatorList(sInfo); err != nil {
t.Fatal(err)
}
}
if len(cache.shuffledIndicesCache.ListKeys()) != maxShuffledListSize {
t.Errorf(
"Expected hash cache key size to be %d, got %d",
maxShuffledListSize,
len(cache.shuffledIndicesCache.ListKeys()),
)
}
}

98
beacon-chain/cache/start_shard.go vendored Normal file
View File

@@ -0,0 +1,98 @@
package cache
import (
"errors"
"strconv"
"sync"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/prysmaticlabs/prysm/shared/params"
"k8s.io/client-go/tools/cache"
)
var (
// ErrNotStartShardInfo will be returned when a cache object is not a pointer to
// a StartShardByEpoch struct.
ErrNotStartShardInfo = errors.New("object is not a start shard obj")
// maxStartShardListSize defines the max number of start shard can cache.
maxStartShardListSize = int(params.BeaconConfig().ShardCount)
// Metrics.
startShardCacheMiss = promauto.NewCounter(prometheus.CounterOpts{
Name: "start_shard_cache_miss",
Help: "The number of start shard requests that aren't present in the cache.",
})
startShardCacheHit = promauto.NewCounter(prometheus.CounterOpts{
Name: "start_shard_cache_hit",
Help: "The number of start shard requests that are present in the cache.",
})
)
// StartShardByEpoch defines the start shard of the epoch.
type StartShardByEpoch struct {
Epoch uint64
StartShard uint64
}
// StartShardCache is a struct with 1 queue for looking up start shard by epoch.
type StartShardCache struct {
startShardCache *cache.FIFO
lock sync.RWMutex
}
// startShardKeyFn takes the epoch as the key for the start shard of a given epoch.
func startShardKeyFn(obj interface{}) (string, error) {
sInfo, ok := obj.(*StartShardByEpoch)
if !ok {
return "", ErrNotStartShardInfo
}
return strconv.Itoa(int(sInfo.Epoch)), nil
}
// NewStartShardCache creates a new start shard cache for storing/accessing start shard.
func NewStartShardCache() *StartShardCache {
return &StartShardCache{
startShardCache: cache.NewFIFO(startShardKeyFn),
}
}
// StartShardInEpoch fetches StartShardByEpoch by epoch. Returns true with a
// reference to the StartShardInEpoch info, if exists. Otherwise returns false, nil.
func (c *StartShardCache) StartShardInEpoch(epoch uint64) (uint64, error) {
c.lock.RLock()
defer c.lock.RUnlock()
obj, exists, err := c.startShardCache.GetByKey(strconv.Itoa(int(epoch)))
if err != nil {
return params.BeaconConfig().FarFutureEpoch, err
}
if exists {
startShardCacheHit.Inc()
} else {
startShardCacheMiss.Inc()
return params.BeaconConfig().FarFutureEpoch, nil
}
sInfo, ok := obj.(*StartShardByEpoch)
if !ok {
return params.BeaconConfig().FarFutureEpoch, ErrNotStartShardInfo
}
return sInfo.StartShard, nil
}
// AddStartShard adds StartShardByEpoch object to the cache. This method also trims the least
// recently added StartShardByEpoch object if the cache size has ready the max cache size limit.
func (c *StartShardCache) AddStartShard(startShard *StartShardByEpoch) error {
c.lock.Lock()
defer c.lock.Unlock()
if err := c.startShardCache.AddIfNotPresent(startShard); err != nil {
return err
}
trim(c.startShardCache, maxStartShardListSize)
return nil
}

83
beacon-chain/cache/start_shard_test.go vendored Normal file
View File

@@ -0,0 +1,83 @@
package cache
import (
"reflect"
"strconv"
"testing"
"github.com/prysmaticlabs/prysm/shared/params"
)
func TestStartShardKeyFn_OK(t *testing.T) {
tInfo := &StartShardByEpoch{
Epoch: 44,
StartShard: 3,
}
key, err := startShardKeyFn(tInfo)
if err != nil {
t.Fatal(err)
}
if key != strconv.Itoa(int(tInfo.Epoch)) {
t.Errorf("Incorrect hash key: %s, expected %s", key, strconv.Itoa(int(tInfo.Epoch)))
}
}
func TestStartShardKeyFn_InvalidObj(t *testing.T) {
_, err := startShardKeyFn("bad")
if err != ErrNotStartShardInfo {
t.Errorf("Expected error %v, got %v", ErrNotStartShardInfo, err)
}
}
func TestStartShardCache_StartShardByEpoch(t *testing.T) {
cache := NewStartShardCache()
tInfo := &StartShardByEpoch{
Epoch: 55,
StartShard: 3,
}
startShard, err := cache.StartShardInEpoch(tInfo.Epoch)
if err != nil {
t.Fatal(err)
}
if startShard != params.BeaconConfig().FarFutureEpoch {
t.Error("Expected start shard not to exist in empty cache")
}
if err := cache.AddStartShard(tInfo); err != nil {
t.Fatal(err)
}
startShard, err = cache.StartShardInEpoch(tInfo.Epoch)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(startShard, tInfo.StartShard) {
t.Errorf(
"Expected fetched start shard to be %v, got %v",
tInfo.StartShard,
startShard,
)
}
}
func TestStartShard_MaxSize(t *testing.T) {
cache := NewStartShardCache()
for i := uint64(0); i < params.BeaconConfig().ShardCount+1; i++ {
tInfo := &StartShardByEpoch{
Epoch: i,
}
if err := cache.AddStartShard(tInfo); err != nil {
t.Fatal(err)
}
}
if len(cache.startShardCache.ListKeys()) != maxStartShardListSize {
t.Errorf(
"Expected hash cache key size to be %d, got %d",
maxStartShardListSize,
len(cache.startShardCache.ListKeys()),
)
}
}

98
beacon-chain/cache/total_balance.go vendored Normal file
View File

@@ -0,0 +1,98 @@
package cache
import (
"errors"
"strconv"
"sync"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/prysmaticlabs/prysm/shared/params"
"k8s.io/client-go/tools/cache"
)
var (
// ErrNotTotalBalanceInfo will be returned when a cache object is not a pointer to
// a TotalBalanceByEpoch struct.
ErrNotTotalBalanceInfo = errors.New("object is not a total balance obj")
// maxTotalBalanceListSize defines the max number of total balance can cache.
maxTotalBalanceListSize = 1000
// Metrics.
totalBalanceCacheMiss = promauto.NewCounter(prometheus.CounterOpts{
Name: "total_balance_cache_miss",
Help: "The number of total balance requests that aren't present in the cache.",
})
totalBalanceCacheHit = promauto.NewCounter(prometheus.CounterOpts{
Name: "total_balance_cache_hit",
Help: "The number of total balance requests that are present in the cache.",
})
)
// TotalBalanceByEpoch defines the total validator balance per epoch.
type TotalBalanceByEpoch struct {
Epoch uint64
TotalBalance uint64
}
// TotalBalanceCache is a struct with 1 queue for looking up total balance by epoch.
type TotalBalanceCache struct {
totalBalanceCache *cache.FIFO
lock sync.RWMutex
}
// totalBalanceKeyFn takes the epoch as the key for the total balance of a given epoch.
func totalBalanceKeyFn(obj interface{}) (string, error) {
tInfo, ok := obj.(*TotalBalanceByEpoch)
if !ok {
return "", ErrNotTotalBalanceInfo
}
return strconv.Itoa(int(tInfo.Epoch)), nil
}
// NewTotalBalanceCache creates a new total balance cache for storing/accessing total validator balance.
func NewTotalBalanceCache() *TotalBalanceCache {
return &TotalBalanceCache{
totalBalanceCache: cache.NewFIFO(totalBalanceKeyFn),
}
}
// TotalBalanceInEpoch fetches TotalBalanceByEpoch by epoch. Returns true with a
// reference to the TotalBalanceInEpoch info, if exists. Otherwise returns false, nil.
func (c *TotalBalanceCache) TotalBalanceInEpoch(epoch uint64) (uint64, error) {
c.lock.RLock()
defer c.lock.RUnlock()
obj, exists, err := c.totalBalanceCache.GetByKey(strconv.Itoa(int(epoch)))
if err != nil {
return params.BeaconConfig().FarFutureEpoch, err
}
if exists {
totalBalanceCacheHit.Inc()
} else {
totalBalanceCacheMiss.Inc()
return params.BeaconConfig().FarFutureEpoch, nil
}
tInfo, ok := obj.(*TotalBalanceByEpoch)
if !ok {
return params.BeaconConfig().FarFutureEpoch, ErrNotTotalBalanceInfo
}
return tInfo.TotalBalance, nil
}
// AddTotalBalance adds TotalBalanceByEpoch object to the cache. This method also trims the least
// recently added TotalBalanceByEpoch object if the cache size has ready the max cache size limit.
func (c *TotalBalanceCache) AddTotalBalance(totalBalance *TotalBalanceByEpoch) error {
c.lock.Lock()
defer c.lock.Unlock()
if err := c.totalBalanceCache.AddIfNotPresent(totalBalance); err != nil {
return err
}
trim(c.totalBalanceCache, maxTotalBalanceListSize)
return nil
}

View File

@@ -0,0 +1,83 @@
package cache
import (
"reflect"
"strconv"
"testing"
"github.com/prysmaticlabs/prysm/shared/params"
)
func TestTotalBalanceKeyFn_OK(t *testing.T) {
tInfo := &TotalBalanceByEpoch{
Epoch: 333,
TotalBalance: 321321323,
}
key, err := totalBalanceKeyFn(tInfo)
if err != nil {
t.Fatal(err)
}
if key != strconv.Itoa(int(tInfo.Epoch)) {
t.Errorf("Incorrect hash key: %s, expected %s", key, strconv.Itoa(int(tInfo.Epoch)))
}
}
func TestTotalBalanceKeyFn_InvalidObj(t *testing.T) {
_, err := totalBalanceKeyFn("bad")
if err != ErrNotTotalBalanceInfo {
t.Errorf("Expected error %v, got %v", ErrNotTotalBalanceInfo, err)
}
}
func TestTotalBalanceCache_TotalBalanceByEpoch(t *testing.T) {
cache := NewTotalBalanceCache()
tInfo := &TotalBalanceByEpoch{
Epoch: 111,
TotalBalance: 345435435,
}
totalBalance, err := cache.TotalBalanceInEpoch(tInfo.Epoch)
if err != nil {
t.Fatal(err)
}
if totalBalance != params.BeaconConfig().FarFutureEpoch {
t.Error("Expected total balance not to exist in empty cache")
}
if err := cache.AddTotalBalance(tInfo); err != nil {
t.Fatal(err)
}
totalBalance, err = cache.TotalBalanceInEpoch(tInfo.Epoch)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(totalBalance, tInfo.TotalBalance) {
t.Errorf(
"Expected fetched total balance to be %v, got %v",
tInfo.TotalBalance,
totalBalance,
)
}
}
func TestTotalBalance_MaxSize(t *testing.T) {
cache := NewTotalBalanceCache()
for i := uint64(0); i < params.BeaconConfig().EpochsPerHistoricalVector+100; i++ {
tInfo := &TotalBalanceByEpoch{
Epoch: i,
}
if err := cache.AddTotalBalance(tInfo); err != nil {
t.Fatal(err)
}
}
if len(cache.totalBalanceCache.ListKeys()) != maxTotalBalanceListSize {
t.Errorf(
"Expected hash cache key size to be %d, got %d",
maxTotalBalanceListSize,
len(cache.totalBalanceCache.ListKeys()),
)
}
}

View File

@@ -1,33 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = ["main.go"],
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/chaintest",
visibility = ["//visibility:private"],
deps = [
"//beacon-chain/chaintest/backend:go_default_library",
"//shared/featureconfig:go_default_library",
"@com_github_go_yaml_yaml//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@com_github_x_cray_logrus_prefixed_formatter//:go_default_library",
],
)
go_binary(
name = "chaintest",
embed = [":go_default_library"],
visibility = ["//visibility:private"],
)
go_test(
name = "go_default_test",
size = "small",
srcs = ["yaml_test.go"],
data = glob(["tests/**"]),
embed = [":go_default_library"],
deps = [
"//beacon-chain/chaintest/backend:go_default_library",
"//shared/featureconfig:go_default_library",
],
)

View File

@@ -1,238 +0,0 @@
# Ethereum 2.0 E2E Test Suite
This is a test-suite for conformity end-2-end tests for Prysm's implementation of the Ethereum 2.0 specification. Implementation teams have decided to utilize YAML as a general conformity test format for the current beacon chain's runtime functionality.
The test suite opts for YAML due to wide language support and support for inline comments.
# Testing Format
The testing format follows the official ETH2.0 Specification created [here](https://github.com/ethereum/eth2.0-specs/blob/master/specs/test-format.md)
## Stateful Tests
Chain tests check for conformity of a certain client to the beacon chain specification for items such as the fork choice rule and Casper FFG validator rewards & penalties. Stateful tests need to specify a certain configuration of a beacon chain, with items such as the number validators, in the YAML file. Sample tests will all required fields are shown below.
### State Transition
The most important use case for this test format is to verify the ins and outs of the Ethereum Phase 0 Beacon Chain state advancement. The specification details very strict guidelines for blocks to successfully trigger a state transition, including items such as Casper Proof of Stake slashing conditions of validators, pseudorandomness in the form of RANDAO, and attestation on shard blocks being processed all inside each incoming beacon block. The YAML configuration for this test type allows for configuring a state transition run over N slots, triggering slashing conditions, processing deposits of new validators, and more.
An example state transition test for testing slot and block processing will look as follows:
```yaml
title: Sample Ethereum Serenity State Transition Tests
summary: Testing full state transition block processing
test_suite: prysm
fork: sapphire
version: 1.0
test_cases:
- config:
epoch_length: 64
deposits_for_chain_start: 1000
num_slots: 32 # Testing advancing state to slot < SlotsPerEpoch
results:
slot: 32
num_validators: 1000
- config:
epoch_length: 64
deposits_for_chain_start: 16384
num_slots: 64
deposits:
- slot: 1
amount: 32
merkle_index: 0
pubkey: !!binary |
SlAAbShSkUg7PLiPHZI/rTS1uAvKiieOrifPN6Moso0=
- slot: 15
amount: 32
merkle_index: 1
pubkey: !!binary |
Oklajsjdkaklsdlkajsdjlajslkdjlkasjlkdjlajdsd
- slot: 55
amount: 32
merkle_index: 2
pubkey: !!binary |
LkmqmqoodLKAslkjdkajsdljasdkajlksjdasldjasdd
proposer_slashings:
- slot: 16 # At slot 16, we trigger a proposal slashing occurring
proposer_index: 16385 # We penalize the proposer that was just added from slot 15
proposal_1_shard: 0
proposal_1_slot: 15
proposal_1_root: !!binary |
LkmqmqoodLKAslkjdkajsdljasdkajlksjdasldjasdd
proposal_2_shard: 0
proposal_2_slot: 15
proposal_2_root: !!binary |
LkmqmqoodLKAslkjdkajsdljasdkajlksjdasldjasdd
attester_slashings:
- slot: 59 # At slot 59, we trigger a attester slashing
slashable_vote_data_1_slot: 55
slashable_vote_data_2_slot: 55
slashable_vote_data_1_justified_slot: 0
slashable_vote_data_2_justified_slot: 1
slashable_vote_data_1_custody_0_indices: [16386]
slashable_vote_data_1_custody_1_indices: []
slashable_vote_data_2_custody_0_indices: []
slashable_vote_data_2_custody_1_indices: [16386]
results:
slot: 64
num_validators: 16387
penalized_validators: [16385, 16386] # We test that the validators at indices 16385, 16386 were indeed penalized
- config:
skip_slots: [10, 20]
epoch_length: 64
deposits_for_chain_start: 1000
num_slots: 128 # Testing advancing state's slot == 2*SlotsPerEpoch
deposits:
- slot: 10
amount: 32
merkle_index: 0
pubkey: !!binary |
SlAAbShSkUg7PLiPHZI/rTS1uAvKiieOrifPN6Moso0=
- slot: 20
amount: 32
merkle_index: 1
pubkey: !!binary |
Oklajsjdkaklsdlkajsdjlajslkdjlkasjlkdjlajdsd
results:
slot: 128
num_validators: 1000 # Validator registry should not have grown if slots 10 and 20 were skipped
```
#### Test Configuration Options
The following configuration options are available for state transition tests:
**Config**
- **skip_slots**: `[int]` determines which slot numbers to simulate a proposer not submitting a block in the state transition TODO
- **epoch_length**: `int` the number of slots in an epoch
- **deposits_for_chain_start**: `int` the number of eth deposits needed for the beacon chain to initialize (this simulates an initial validator registry based on this number in the test)
- **num_slots**: `int` the number of times we run a state transition in the test
- **deposits**: `[Deposit Config]` trigger a new validator deposit into the beacon state based on configuration options
- **proposer_slashings**: `[Proposer Slashing Config]` trigger a proposer slashing at a certain slot for a certain proposer index
- **attester_slashings**: `[Casper Slashing Config]` trigger a attester slashing at a certain slot
- **validator_exits**: `[Validator Exit Config]` trigger a voluntary validator exit at a certain slot for a validator index
**Deposit Config**
- **slot**: `int` a slot in which to trigger a deposit during a state transition test
- **amount**: `int` the ETH deposit amount to trigger
- **merkle_index**: `int` the index of the deposit in the validator deposit contract's Merkle trie
- **pubkey**: `!!binary` the public key of the validator in the triggered deposit object
**Proposer Slashing Config**
- **slot**: `int` a slot in which to trigger a proposer slashing during a state transition test
- **proposer_index**: `int` the proposer to penalize
- **proposal_1_shard**: `int` the first proposal data's shard id
- **proposal_1_slot**: `int` the first proposal data's slot
- **proposal_1_root**: `!!binary` the second proposal data's block root
- **proposal_2_shard**: `int` the second proposal data's shard id
- **proposal_2_slot**: `int` the second proposal data's slot
- **proposal_2_root**: `!!binary` the second proposal data's block root
**Casper Slashing Config**
- **slot**: `int` a slot in which to trigger a attester slashing during a state transition test
- **slashable_vote_data_1_slot**: `int` the slot of the attestation data of slashableVoteData1
- **slashable_vote_data_2_slot**: `int` the slot of the attestation data of slashableVoteData2
- **slashable_vote_data_1_justified_slot**: `int` the justified slot of the attestation data of slashableVoteData1
- **slashable_vote_data_2_justified_slot**: `int` the justified slot of the attestation data of slashableVoteData2
- **slashable_vote_data_1_custody_0_indices**: `[int]` the custody indices 0 for slashableVoteData1
- **slashable_vote_data_1_custody_1_indices**: `[int]` the custody indices 1 for slashableVoteData1
- **slashable_vote_data_2_custody_0_indices**: `[int]` the custody indices 0 for slashableVoteData2
- **slashable_vote_data_2_custody_1_indices**: `[int]` the custody indices 1 for slashableVoteData2
**Validator Exit Config**
- **slot**: `int` the slot at which a validator wants to voluntarily exit the validator registry
- **validator_index**: `int` the index of the validator in the registry that is exiting
#### Test Results
The following are **mandatory** fields as they correspond to checks done at the end of the test run.
- **slot**: `int` check the slot of the state resulting from applying N state transitions in the test
- **num_validators** `[int]` check the number of validators in the validator registry after applying N state transitions
- **penalized_validators** `[int]` the list of validator indices we verify were penalized during the test
- **exited_validators**: `[int]` the list of validator indices we verify voluntarily exited the registry during the test
## Stateless Tests
Stateless tests represent simple unit test definitions for important invariants in the ETH2.0 runtime. In particular, these test conformity across clients with respect to items such as Simple Serialize (SSZ), Signature Aggregation (BLS), and Validator Shuffling
**Simple Serialize**
TODO
**Signature Aggregation**
TODO
**Validator Shuffling**
```yaml
title: Shuffling Algorithm Tests
summary: Test vectors for shuffling a list based upon a seed using `shuffle`
test_suite: shuffle
fork: tchaikovsky
version: 1.0
test_cases:
- input: []
output: []
seed: !!binary ""
- name: boring_list
description: List with a single element, 0
input: [0]
output: [0]
seed: !!binary ""
- input: [255]
output: [255]
seed: !!binary ""
- input: [4, 6, 2, 6, 1, 4, 6, 2, 1, 5]
output: [1, 6, 4, 1, 6, 6, 2, 2, 4, 5]
seed: !!binary ""
- input: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
output: [4, 7, 10, 13, 3, 1, 2, 9, 12, 6, 11, 8, 5]
seed: !!binary ""
- input: [65, 6, 2, 6, 1, 4, 6, 2, 1, 5]
output: [6, 65, 2, 5, 4, 2, 6, 6, 1, 1]
seed: !!binary |
JlAYJ5H2j8g7PLiPHZI/rTS1uAvKiieOrifPN6Moso0=
```
# Using the Runner
First, create a directory containing the YAML files you wish to test (or use the default `./sampletests` directory included with Prysm).
Then, make sure you have the following folder structure for the directory:
```
yourtestdir/
fork-choice-tests/
*.yaml
...
shuffle-tests/
*.yaml
...
state-tests/
*.yaml
...
```
Then, navigate to the test runner's directory and use the go tool as follows:
```bash
go run main.go -tests-dir /path/to/your/testsdir
```
The runner will then start up a simulated backend and run all your specified YAML tests.
```bash
[2018-11-06 15:01:44] INFO ----Running Chain Tests----
[2018-11-06 15:01:44] INFO Running 4 YAML Tests
[2018-11-06 15:01:44] INFO Title: Sample Ethereum 2.0 Beacon Chain Test
[2018-11-06 15:01:44] INFO Summary: Basic, functioning fork choice rule for Ethereum 2.0
[2018-11-06 15:01:44] INFO Test Suite: prysm
[2018-11-06 15:01:44] INFO Test Runs Finished In: 0.000643545 Seconds
```

View File

@@ -1,43 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"fork_choice_test_format.go",
"helpers.go",
"shuffle_test_format.go",
"simulated_backend.go",
"state_test_format.go",
],
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/chaintest/backend",
visibility = ["//beacon-chain:__subpackages__"],
deps = [
"//beacon-chain/blockchain:go_default_library",
"//beacon-chain/core/blocks:go_default_library",
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/core/state:go_default_library",
"//beacon-chain/db:go_default_library",
"//beacon-chain/utils:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//shared/bls:go_default_library",
"//shared/forkutil:go_default_library",
"//shared/hashutil:go_default_library",
"//shared/params:go_default_library",
"//shared/sliceutil:go_default_library",
"//shared/trieutil:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
],
)
go_test(
name = "go_default_test",
size = "small",
srcs = ["simulated_backend_test.go"],
embed = [":go_default_library"],
deps = [
"//beacon-chain/db:go_default_library",
"//shared/featureconfig:go_default_library",
"//shared/params:go_default_library",
],
)

View File

@@ -1,51 +0,0 @@
package backend
// ForkChoiceTest --
type ForkChoiceTest struct {
Title string
Summary string
TestSuite string `yaml:"test_suite"`
TestCases []*ForkChoiceTestCase `yaml:"test_cases"`
}
// ForkChoiceTestCase --
type ForkChoiceTestCase struct {
Config *ForkChoiceTestConfig `yaml:"config"`
Slots []*ForkChoiceTestSlot `yaml:"slots,flow"`
Results *ForkChoiceTestResult `yaml:"results"`
}
// ForkChoiceTestConfig --
type ForkChoiceTestConfig struct {
ValidatorCount uint64 `yaml:"validator_count"`
CycleLength uint64 `yaml:"cycle_length"`
ShardCount uint64 `yaml:"shard_count"`
MinCommitteeSize uint64 `yaml:"min_committee_size"`
}
// ForkChoiceTestSlot --
type ForkChoiceTestSlot struct {
SlotNumber uint64 `yaml:"slot_number"`
NewBlock *TestBlock `yaml:"new_block"`
Attestations []*TestAttestation `yaml:",flow"`
}
// ForkChoiceTestResult --
type ForkChoiceTestResult struct {
Head string
LastJustifiedBlock string `yaml:"last_justified_block"`
LastFinalizedBlock string `yaml:"last_finalized_block"`
}
// TestBlock --
type TestBlock struct {
ID string `yaml:"ID"`
Parent string `yaml:"parent"`
}
// TestAttestation --
type TestAttestation struct {
Block string `yaml:"block"`
ValidatorRegistry string `yaml:"validators"`
CommitteeSlot uint64 `yaml:"committee_slot"`
}

View File

@@ -1,170 +0,0 @@
package backend
import (
"crypto/rand"
"encoding/binary"
"fmt"
"time"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/forkutil"
"github.com/prysmaticlabs/prysm/shared/hashutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/trieutil"
)
// Generates a simulated beacon block to use
// in the next state transition given the current state,
// the previous beacon block, and previous beacon block root.
func generateSimulatedBlock(
beaconState *pb.BeaconState,
prevBlockRoot [32]byte,
historicalDeposits []*pb.Deposit,
simObjects *SimulatedObjects,
privKeys []*bls.SecretKey,
) (*pb.BeaconBlock, [32]byte, error) {
stateRoot, err := hashutil.HashProto(beaconState)
if err != nil {
return nil, [32]byte{}, fmt.Errorf("could not tree hash state: %v", err)
}
proposerIdx, err := helpers.BeaconProposerIndex(beaconState, beaconState.Slot+1)
if err != nil {
return nil, [32]byte{}, err
}
epoch := helpers.SlotToEpoch(beaconState.Slot + 1)
buf := make([]byte, 32)
binary.LittleEndian.PutUint64(buf, epoch)
domain := forkutil.DomainVersion(beaconState.Fork, epoch, params.BeaconConfig().DomainRandao)
// We make the previous validator's index sign the message instead of the proposer.
epochSignature := privKeys[proposerIdx].Sign(buf, domain)
block := &pb.BeaconBlock{
Slot: beaconState.Slot + 1,
RandaoReveal: epochSignature.Marshal(),
ParentRootHash32: prevBlockRoot[:],
StateRootHash32: stateRoot[:],
Eth1Data: &pb.Eth1Data{
DepositRootHash32: []byte{1},
BlockHash32: []byte{2},
},
Body: &pb.BeaconBlockBody{
ProposerSlashings: []*pb.ProposerSlashing{},
AttesterSlashings: []*pb.AttesterSlashing{},
Attestations: []*pb.Attestation{},
Deposits: []*pb.Deposit{},
VoluntaryExits: []*pb.VoluntaryExit{},
},
}
if simObjects.simDeposit != nil {
depositInput := &pb.DepositInput{
Pubkey: []byte(simObjects.simDeposit.Pubkey),
WithdrawalCredentialsHash32: make([]byte, 32),
ProofOfPossession: make([]byte, 96),
}
data, err := helpers.EncodeDepositData(depositInput, simObjects.simDeposit.Amount, time.Now().Unix())
if err != nil {
return nil, [32]byte{}, fmt.Errorf("could not encode deposit data: %v", err)
}
// We then update the deposits Merkle trie with the deposit data and return
// its Merkle branch leading up to the root of the trie.
historicalDepositData := make([][]byte, len(historicalDeposits))
for i := range historicalDeposits {
historicalDepositData[i] = historicalDeposits[i].DepositData
}
newTrie, err := trieutil.GenerateTrieFromItems(append(historicalDepositData, data), int(params.BeaconConfig().DepositContractTreeDepth))
if err != nil {
return nil, [32]byte{}, fmt.Errorf("could not regenerate trie: %v", err)
}
proof, err := newTrie.MerkleProof(int(simObjects.simDeposit.MerkleIndex))
if err != nil {
return nil, [32]byte{}, fmt.Errorf("could not generate proof: %v", err)
}
root := newTrie.Root()
block.Eth1Data.DepositRootHash32 = root[:]
block.Body.Deposits = append(block.Body.Deposits, &pb.Deposit{
DepositData: data,
MerkleProofHash32S: proof,
MerkleTreeIndex: simObjects.simDeposit.MerkleIndex,
})
}
if simObjects.simProposerSlashing != nil {
block.Body.ProposerSlashings = append(block.Body.ProposerSlashings, &pb.ProposerSlashing{
ProposerIndex: simObjects.simProposerSlashing.ProposerIndex,
ProposalData_1: &pb.ProposalSignedData{
Slot: simObjects.simProposerSlashing.Proposal1Slot,
Shard: simObjects.simProposerSlashing.Proposal1Shard,
BlockRootHash32: []byte(simObjects.simProposerSlashing.Proposal1Root),
},
ProposalData_2: &pb.ProposalSignedData{
Slot: simObjects.simProposerSlashing.Proposal2Slot,
Shard: simObjects.simProposerSlashing.Proposal2Shard,
BlockRootHash32: []byte(simObjects.simProposerSlashing.Proposal2Root),
},
})
}
if simObjects.simAttesterSlashing != nil {
block.Body.AttesterSlashings = append(block.Body.AttesterSlashings, &pb.AttesterSlashing{
SlashableAttestation_1: &pb.SlashableAttestation{
Data: &pb.AttestationData{
Slot: simObjects.simAttesterSlashing.SlashableAttestation1Slot,
JustifiedEpoch: simObjects.simAttesterSlashing.SlashableAttestation1JustifiedEpoch,
},
CustodyBitfield: []byte(simObjects.simAttesterSlashing.SlashableAttestation1CustodyBitField),
ValidatorIndices: simObjects.simAttesterSlashing.SlashableAttestation1ValidatorIndices,
},
SlashableAttestation_2: &pb.SlashableAttestation{
Data: &pb.AttestationData{
Slot: simObjects.simAttesterSlashing.SlashableAttestation2Slot,
JustifiedEpoch: simObjects.simAttesterSlashing.SlashableAttestation2JustifiedEpoch,
},
CustodyBitfield: []byte(simObjects.simAttesterSlashing.SlashableAttestation2CustodyBitField),
ValidatorIndices: simObjects.simAttesterSlashing.SlashableAttestation2ValidatorIndices,
},
})
}
if simObjects.simValidatorExit != nil {
block.Body.VoluntaryExits = append(block.Body.VoluntaryExits, &pb.VoluntaryExit{
Epoch: simObjects.simValidatorExit.Epoch,
ValidatorIndex: simObjects.simValidatorExit.ValidatorIndex,
})
}
blockRoot, err := hashutil.HashBeaconBlock(block)
if err != nil {
return nil, [32]byte{}, fmt.Errorf("could not tree hash new block: %v", err)
}
return block, blockRoot, nil
}
// generateInitialSimulatedDeposits generates initial deposits for creating a beacon state in the simulated
// backend based on the yaml configuration.
func generateInitialSimulatedDeposits(numDeposits uint64) ([]*pb.Deposit, []*bls.SecretKey, error) {
genesisTime := time.Date(2018, 9, 0, 0, 0, 0, 0, time.UTC).Unix()
deposits := make([]*pb.Deposit, numDeposits)
privKeys := make([]*bls.SecretKey, numDeposits)
for i := 0; i < len(deposits); i++ {
priv, err := bls.RandKey(rand.Reader)
if err != nil {
return nil, nil, fmt.Errorf("could not initialize key: %v", err)
}
depositInput := &pb.DepositInput{
Pubkey: priv.PublicKey().Marshal(),
WithdrawalCredentialsHash32: make([]byte, 32),
ProofOfPossession: make([]byte, 96),
}
depositData, err := helpers.EncodeDepositData(
depositInput,
params.BeaconConfig().MaxDepositAmount,
genesisTime,
)
if err != nil {
return nil, nil, fmt.Errorf("could not encode genesis block deposits: %v", err)
}
deposits[i] = &pb.Deposit{DepositData: depositData, MerkleTreeIndex: uint64(i)}
privKeys[i] = priv
}
return deposits, privKeys, nil
}

View File

@@ -1,18 +0,0 @@
package backend
// ShuffleTest --
type ShuffleTest struct {
Title string `yaml:"title"`
Summary string `yaml:"summary"`
TestSuite string `yaml:"test_suite"`
Fork string `yaml:"fork"`
Version string `yaml:"version"`
TestCases []*ShuffleTestCase `yaml:"test_cases"`
}
// ShuffleTestCase --
type ShuffleTestCase struct {
Input []uint64 `yaml:"input,flow"`
Output []uint64 `yaml:"output,flow"`
Seed string
}

View File

@@ -1,393 +0,0 @@
// Package backend contains utilities for simulating an entire
// ETH 2.0 beacon chain for e2e tests and benchmarking
// purposes.
package backend
import (
"context"
"fmt"
"reflect"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
b "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
"github.com/prysmaticlabs/prysm/beacon-chain/db"
"github.com/prysmaticlabs/prysm/beacon-chain/utils"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/hashutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/sliceutil"
log "github.com/sirupsen/logrus"
)
// SimulatedBackend allowing for a programmatic advancement
// of an in-memory beacon chain for client test runs
// and other e2e use cases.
type SimulatedBackend struct {
chainService *blockchain.ChainService
beaconDB *db.BeaconDB
state *pb.BeaconState
prevBlockRoots [][32]byte
inMemoryBlocks []*pb.BeaconBlock
historicalDeposits []*pb.Deposit
}
// SimulatedObjects is a container to hold the
// required primitives for generation of a beacon
// block.
type SimulatedObjects struct {
simDeposit *StateTestDeposit
simProposerSlashing *StateTestProposerSlashing
simAttesterSlashing *StateTestAttesterSlashing
simValidatorExit *StateTestValidatorExit
}
// NewSimulatedBackend creates an instance by initializing a chain service
// utilizing a mockDB which will act according to test run parameters specified
// in the common ETH 2.0 client test YAML format.
func NewSimulatedBackend() (*SimulatedBackend, error) {
db, err := db.SetupDB()
if err != nil {
return nil, fmt.Errorf("could not setup simulated backend db: %v", err)
}
cs, err := blockchain.NewChainService(context.Background(), &blockchain.Config{
BeaconDB: db,
})
if err != nil {
return nil, err
}
return &SimulatedBackend{
chainService: cs,
beaconDB: db,
inMemoryBlocks: make([]*pb.BeaconBlock, 0),
historicalDeposits: make([]*pb.Deposit, 0),
}, nil
}
// SetupBackend sets up the simulated backend with simulated deposits, and initializes the
// state and genesis block.
func (sb *SimulatedBackend) SetupBackend(numOfDeposits uint64) ([]*bls.SecretKey, error) {
initialDeposits, privKeys, err := generateInitialSimulatedDeposits(numOfDeposits)
if err != nil {
return nil, fmt.Errorf("could not simulate initial validator deposits: %v", err)
}
if err := sb.setupBeaconStateAndGenesisBlock(initialDeposits); err != nil {
return nil, fmt.Errorf("could not set up beacon state and initialize genesis block %v", err)
}
return privKeys, nil
}
// DB returns the underlying db instance in the simulated
// backend.
func (sb *SimulatedBackend) DB() *db.BeaconDB {
return sb.beaconDB
}
// GenerateBlockAndAdvanceChain generates a simulated block and runs that block though
// state transition.
func (sb *SimulatedBackend) GenerateBlockAndAdvanceChain(objects *SimulatedObjects, privKeys []*bls.SecretKey) error {
prevBlockRoot := sb.prevBlockRoots[len(sb.prevBlockRoots)-1]
// We generate a new block to pass into the state transition.
newBlock, newBlockRoot, err := generateSimulatedBlock(
sb.state,
prevBlockRoot,
sb.historicalDeposits,
objects,
privKeys,
)
if err != nil {
return fmt.Errorf("could not generate simulated beacon block %v", err)
}
newState := sb.state
newState.LatestEth1Data = newBlock.Eth1Data
newState, err = state.ExecuteStateTransition(
context.Background(),
sb.state,
newBlock,
prevBlockRoot,
state.DefaultConfig(),
)
if err != nil {
return fmt.Errorf("could not execute state transition: %v", err)
}
sb.state = newState
sb.prevBlockRoots = append(sb.prevBlockRoots, newBlockRoot)
sb.inMemoryBlocks = append(sb.inMemoryBlocks, newBlock)
if len(newBlock.Body.Deposits) > 0 {
sb.historicalDeposits = append(sb.historicalDeposits, newBlock.Body.Deposits...)
}
return nil
}
// GenerateNilBlockAndAdvanceChain would trigger a state transition with a nil block.
func (sb *SimulatedBackend) GenerateNilBlockAndAdvanceChain() error {
prevBlockRoot := sb.prevBlockRoots[len(sb.prevBlockRoots)-1]
newState, err := state.ExecuteStateTransition(
context.Background(),
sb.state,
nil,
prevBlockRoot,
state.DefaultConfig(),
)
if err != nil {
return fmt.Errorf("could not execute state transition: %v", err)
}
sb.state = newState
return nil
}
// Shutdown closes the db associated with the simulated backend.
func (sb *SimulatedBackend) Shutdown() error {
return sb.beaconDB.Close()
}
// State is a getter to return the current beacon state
// of the backend.
func (sb *SimulatedBackend) State() *pb.BeaconState {
return sb.state
}
// InMemoryBlocks returns the blocks that have been processed by the simulated
// backend.
func (sb *SimulatedBackend) InMemoryBlocks() []*pb.BeaconBlock {
return sb.inMemoryBlocks
}
// RunForkChoiceTest uses a parsed set of chaintests from a YAML file
// according to the ETH 2.0 client chain test specification and runs them
// against the simulated backend.
func (sb *SimulatedBackend) RunForkChoiceTest(testCase *ForkChoiceTestCase) error {
defer db.TeardownDB(sb.beaconDB)
// Utilize the config parameters in the test case to setup
// the DB and set global config parameters accordingly.
// Config parameters include: ValidatorCount, ShardCount,
// CycleLength, MinCommitteeSize, and more based on the YAML
// test language specification.
c := params.BeaconConfig()
c.ShardCount = testCase.Config.ShardCount
c.SlotsPerEpoch = testCase.Config.CycleLength
c.TargetCommitteeSize = testCase.Config.MinCommitteeSize
params.OverrideBeaconConfig(c)
// Then, we create the validators based on the custom test config.
validators := make([]*pb.Validator, testCase.Config.ValidatorCount)
for i := uint64(0); i < testCase.Config.ValidatorCount; i++ {
validators[i] = &pb.Validator{
ExitEpoch: params.BeaconConfig().ActivationExitDelay,
Pubkey: []byte{},
}
}
// TODO(#718): Next step is to update and save the blocks specified
// in the case case into the DB.
//
// Then, we call the updateHead routine and confirm the
// chain's head is the expected result from the test case.
return nil
}
// RunShuffleTest uses validator set specified from a YAML file, runs the validator shuffle
// algorithm, then compare the output with the expected output from the YAML file.
func (sb *SimulatedBackend) RunShuffleTest(testCase *ShuffleTestCase) error {
defer db.TeardownDB(sb.beaconDB)
seed := common.BytesToHash([]byte(testCase.Seed))
output, err := utils.ShuffleIndices(seed, testCase.Input)
if err != nil {
return err
}
if !reflect.DeepEqual(output, testCase.Output) {
return fmt.Errorf("shuffle result error: expected %v, actual %v", testCase.Output, output)
}
return nil
}
// RunStateTransitionTest advances a beacon chain state transition an N amount of
// slots from a genesis state, with a block being processed at every iteration
// of the state transition function.
func (sb *SimulatedBackend) RunStateTransitionTest(testCase *StateTestCase) error {
defer db.TeardownDB(sb.beaconDB)
setTestConfig(testCase)
privKeys, err := sb.initializeStateTest(testCase)
if err != nil {
return fmt.Errorf("could not initialize state test %v", err)
}
averageTimesPerTransition := []time.Duration{}
startSlot := params.BeaconConfig().GenesisSlot
for i := startSlot; i < startSlot+testCase.Config.NumSlots; i++ {
// If the slot is marked as skipped in the configuration options,
// we simply run the state transition with a nil block argument.
if sliceutil.IsInUint64(i, testCase.Config.SkipSlots) {
if err := sb.GenerateNilBlockAndAdvanceChain(); err != nil {
return fmt.Errorf("could not advance the chain with a nil block %v", err)
}
continue
}
simulatedObjects := sb.generateSimulatedObjects(testCase, i)
startTime := time.Now()
if err := sb.GenerateBlockAndAdvanceChain(simulatedObjects, privKeys); err != nil {
return fmt.Errorf("could not generate the block and advance the chain %v", err)
}
endTime := time.Now()
averageTimesPerTransition = append(averageTimesPerTransition, endTime.Sub(startTime))
}
log.Infof(
"with %d initial deposits, each state transition took average time = %v",
testCase.Config.DepositsForChainStart,
averageDuration(averageTimesPerTransition),
)
if err := sb.compareTestCase(testCase); err != nil {
return err
}
return nil
}
// initializeStateTest sets up the environment by generating all the required objects in order
// to proceed with the state test.
func (sb *SimulatedBackend) initializeStateTest(testCase *StateTestCase) ([]*bls.SecretKey, error) {
initialDeposits, privKeys, err := generateInitialSimulatedDeposits(testCase.Config.DepositsForChainStart)
if err != nil {
return nil, fmt.Errorf("could not simulate initial validator deposits: %v", err)
}
if err := sb.setupBeaconStateAndGenesisBlock(initialDeposits); err != nil {
return nil, fmt.Errorf("could not set up beacon state and initialize genesis block %v", err)
}
return privKeys, nil
}
// setupBeaconStateAndGenesisBlock creates the initial beacon state and genesis block in order to
// proceed with the test.
func (sb *SimulatedBackend) setupBeaconStateAndGenesisBlock(initialDeposits []*pb.Deposit) error {
var err error
genesisTime := time.Date(2018, 9, 0, 0, 0, 0, 0, time.UTC).Unix()
sb.state, err = state.GenesisBeaconState(initialDeposits, uint64(genesisTime), nil)
if err != nil {
return fmt.Errorf("could not initialize simulated beacon state: %v", err)
}
sb.historicalDeposits = initialDeposits
// We do not expect hashing initial beacon state and genesis block to
// fail, so we can safely ignore the error below.
// #nosec G104
stateRoot, err := hashutil.HashProto(sb.state)
if err != nil {
return fmt.Errorf("could not tree hash state: %v", err)
}
genesisBlock := b.NewGenesisBlock(stateRoot[:])
genesisBlockRoot, err := hashutil.HashBeaconBlock(genesisBlock)
if err != nil {
return fmt.Errorf("could not tree hash genesis block: %v", err)
}
// We now keep track of generated blocks for each state transition in
// a slice.
sb.prevBlockRoots = [][32]byte{genesisBlockRoot}
sb.inMemoryBlocks = append(sb.inMemoryBlocks, genesisBlock)
return nil
}
// generateSimulatedObjects generates the simulated objects depending on the testcase and current slot.
func (sb *SimulatedBackend) generateSimulatedObjects(testCase *StateTestCase, slotNumber uint64) *SimulatedObjects {
// If the slot is not skipped, we check if we are simulating a deposit at the current slot.
var simulatedDeposit *StateTestDeposit
for _, deposit := range testCase.Config.Deposits {
if deposit.Slot == slotNumber {
simulatedDeposit = deposit
break
}
}
var simulatedProposerSlashing *StateTestProposerSlashing
for _, pSlashing := range testCase.Config.ProposerSlashings {
if pSlashing.Slot == slotNumber {
simulatedProposerSlashing = pSlashing
break
}
}
var simulatedAttesterSlashing *StateTestAttesterSlashing
for _, cSlashing := range testCase.Config.AttesterSlashings {
if cSlashing.Slot == slotNumber {
simulatedAttesterSlashing = cSlashing
break
}
}
var simulatedValidatorExit *StateTestValidatorExit
for _, exit := range testCase.Config.ValidatorExits {
if exit.Epoch == slotNumber/params.BeaconConfig().SlotsPerEpoch {
simulatedValidatorExit = exit
break
}
}
return &SimulatedObjects{
simDeposit: simulatedDeposit,
simProposerSlashing: simulatedProposerSlashing,
simAttesterSlashing: simulatedAttesterSlashing,
simValidatorExit: simulatedValidatorExit,
}
}
// compareTestCase compares the state in the simulated backend against the values in inputted test case. If
// there are any discrepancies it returns an error.
func (sb *SimulatedBackend) compareTestCase(testCase *StateTestCase) error {
if sb.state.Slot != testCase.Results.Slot {
return fmt.Errorf(
"incorrect state slot after %d state transitions without blocks, wanted %d, received %d",
testCase.Config.NumSlots,
sb.state.Slot,
testCase.Results.Slot,
)
}
if len(sb.state.ValidatorRegistry) != testCase.Results.NumValidators {
return fmt.Errorf(
"incorrect num validators after %d state transitions without blocks, wanted %d, received %d",
testCase.Config.NumSlots,
testCase.Results.NumValidators,
len(sb.state.ValidatorRegistry),
)
}
for _, slashed := range testCase.Results.SlashedValidators {
if sb.state.ValidatorRegistry[slashed].SlashedEpoch == params.BeaconConfig().FarFutureEpoch {
return fmt.Errorf(
"expected validator at index %d to have been slashed",
slashed,
)
}
}
for _, exited := range testCase.Results.ExitedValidators {
if sb.state.ValidatorRegistry[exited].StatusFlags != pb.Validator_INITIATED_EXIT {
return fmt.Errorf(
"expected validator at index %d to have exited",
exited,
)
}
}
return nil
}
func setTestConfig(testCase *StateTestCase) {
// We setup the initial configuration for running state
// transition tests below.
c := params.BeaconConfig()
c.SlotsPerEpoch = testCase.Config.SlotsPerEpoch
c.DepositsForChainStart = testCase.Config.DepositsForChainStart
params.OverrideBeaconConfig(c)
}
func averageDuration(times []time.Duration) time.Duration {
sum := int64(0)
for _, t := range times {
sum += t.Nanoseconds()
}
return time.Duration(sum / int64(len(times)))
}

View File

@@ -1,85 +0,0 @@
package backend
import (
"testing"
"github.com/prysmaticlabs/prysm/beacon-chain/db"
"github.com/prysmaticlabs/prysm/shared/featureconfig"
"github.com/prysmaticlabs/prysm/shared/params"
)
func init() {
featureconfig.InitFeatureConfig(&featureconfig.FeatureFlagConfig{
EnableCrosslinks: true,
})
}
func TestSimulatedBackendStop_ShutsDown(t *testing.T) {
backend, err := NewSimulatedBackend()
if err != nil {
t.Fatalf("Could not create a new simulated backedn %v", err)
}
if err := backend.Shutdown(); err != nil {
t.Errorf("Could not successfully shutdown simulated backend %v", err)
}
db.TeardownDB(backend.beaconDB)
}
func TestGenerateBlockAndAdvanceChain_IncreasesSlot(t *testing.T) {
backend, err := NewSimulatedBackend()
if err != nil {
t.Fatalf("Could not create a new simulated backend %v", err)
}
privKeys, err := backend.SetupBackend(100)
if err != nil {
t.Fatalf("Could not set up backend %v", err)
}
defer backend.Shutdown()
defer db.TeardownDB(backend.beaconDB)
slotLimit := params.BeaconConfig().SlotsPerEpoch + uint64(1)
for i := uint64(0); i < slotLimit; i++ {
if err := backend.GenerateBlockAndAdvanceChain(&SimulatedObjects{}, privKeys); err != nil {
t.Fatalf("Could not generate block and transition state successfully %v for slot %d", err, backend.state.Slot+1)
}
if backend.inMemoryBlocks[len(backend.inMemoryBlocks)-1].Slot != backend.state.Slot {
t.Errorf("In memory Blocks do not have the same last slot as the state, expected %d but got %v",
backend.state.Slot, backend.inMemoryBlocks[len(backend.inMemoryBlocks)-1])
}
}
if backend.state.Slot != params.BeaconConfig().GenesisSlot+uint64(slotLimit) {
t.Errorf("Unequal state slot and expected slot %d %d", backend.state.Slot, slotLimit)
}
}
func TestGenerateNilBlockAndAdvanceChain_IncreasesSlot(t *testing.T) {
backend, err := NewSimulatedBackend()
if err != nil {
t.Fatalf("Could not create a new simulated backedn %v", err)
}
if _, err := backend.SetupBackend(100); err != nil {
t.Fatalf("Could not set up backend %v", err)
}
defer backend.Shutdown()
defer db.TeardownDB(backend.beaconDB)
slotLimit := params.BeaconConfig().SlotsPerEpoch + uint64(1)
for i := uint64(0); i < slotLimit; i++ {
if err := backend.GenerateNilBlockAndAdvanceChain(); err != nil {
t.Fatalf("Could not generate block and transition state successfully %v for slot %d", err, backend.state.Slot+1)
}
}
if backend.state.Slot != params.BeaconConfig().GenesisSlot+uint64(slotLimit) {
t.Errorf("Unequal state slot and expected slot %d %d", backend.state.Slot, slotLimit)
}
}

View File

@@ -1,78 +0,0 @@
package backend
// StateTest --
type StateTest struct {
Title string
Summary string
Fork string `yaml:"fork"`
Version string `yaml:"version"`
TestSuite string `yaml:"test_suite"`
TestCases []*StateTestCase `yaml:"test_cases"`
}
// StateTestCase --
type StateTestCase struct {
Config *StateTestConfig `yaml:"config"`
Results *StateTestResults `yaml:"results"`
}
// StateTestConfig --
type StateTestConfig struct {
SkipSlots []uint64 `yaml:"skip_slots"`
DepositSlots []uint64 `yaml:"deposit_slots"`
Deposits []*StateTestDeposit `yaml:"deposits"`
ProposerSlashings []*StateTestProposerSlashing `yaml:"proposer_slashings"`
AttesterSlashings []*StateTestAttesterSlashing `yaml:"attester_slashings"`
ValidatorExits []*StateTestValidatorExit `yaml:"validator_exits"`
SlotsPerEpoch uint64 `yaml:"slots_per_epoch"`
ShardCount uint64 `yaml:"shard_count"`
DepositsForChainStart uint64 `yaml:"deposits_for_chain_start"`
NumSlots uint64 `yaml:"num_slots"`
}
// StateTestDeposit --
type StateTestDeposit struct {
Slot uint64 `yaml:"slot"`
Amount uint64 `yaml:"amount"`
MerkleIndex uint64 `yaml:"merkle_index"`
Pubkey string `yaml:"pubkey"`
}
// StateTestProposerSlashing --
type StateTestProposerSlashing struct {
Slot uint64 `yaml:"slot"`
ProposerIndex uint64 `yaml:"proposer_index"`
Proposal1Shard uint64 `yaml:"proposal_1_shard"`
Proposal2Shard uint64 `yaml:"proposal_2_shard"`
Proposal1Slot uint64 `yaml:"proposal_1_slot"`
Proposal2Slot uint64 `yaml:"proposal_2_slot"`
Proposal1Root string `yaml:"proposal_1_root"`
Proposal2Root string `yaml:"proposal_2_root"`
}
// StateTestAttesterSlashing --
type StateTestAttesterSlashing struct {
Slot uint64 `yaml:"slot"`
SlashableAttestation1Slot uint64 `yaml:"slashable_attestation_1_slot"`
SlashableAttestation1JustifiedEpoch uint64 `yaml:"slashable_attestation_1_justified_epoch"`
SlashableAttestation1ValidatorIndices []uint64 `yaml:"slashable_attestation_1_validator_indices"`
SlashableAttestation1CustodyBitField string `yaml:"slashable_attestation_1_custody_bitfield"`
SlashableAttestation2Slot uint64 `yaml:"slashable_attestation_2_slot"`
SlashableAttestation2JustifiedEpoch uint64 `yaml:"slashable_attestation_2_justified_epoch"`
SlashableAttestation2ValidatorIndices []uint64 `yaml:"slashable_attestation_2_validator_indices"`
SlashableAttestation2CustodyBitField string `yaml:"slashable_attestation_2_custody_bitfield"`
}
// StateTestValidatorExit --
type StateTestValidatorExit struct {
Epoch uint64 `yaml:"epoch"`
ValidatorIndex uint64 `yaml:"validator_index"`
}
// StateTestResults --
type StateTestResults struct {
Slot uint64
NumValidators int `yaml:"num_validators"`
SlashedValidators []uint64 `yaml:"slashed_validators"`
ExitedValidators []uint64 `yaml:"exited_validators"`
}

View File

@@ -1,145 +0,0 @@
package main
import (
"flag"
"fmt"
"io/ioutil"
"path"
"time"
"github.com/go-yaml/yaml"
"github.com/prysmaticlabs/prysm/beacon-chain/chaintest/backend"
"github.com/prysmaticlabs/prysm/shared/featureconfig"
log "github.com/sirupsen/logrus"
prefixed "github.com/x-cray/logrus-prefixed-formatter"
)
func init() {
featureconfig.InitFeatureConfig(&featureconfig.FeatureFlagConfig{
EnableCrosslinks: false,
})
}
func readTestsFromYaml(yamlDir string) ([]interface{}, error) {
const forkChoiceTestsFolderName = "fork-choice-tests"
const shuffleTestsFolderName = "shuffle-tests"
const stateTestsFolderName = "state-tests"
var tests []interface{}
dirs, err := ioutil.ReadDir(yamlDir)
if err != nil {
return nil, fmt.Errorf("could not read YAML tests directory: %v", err)
}
for _, dir := range dirs {
files, err := ioutil.ReadDir(path.Join(yamlDir, dir.Name()))
if err != nil {
return nil, fmt.Errorf("could not read YAML tests directory: %v", err)
}
for _, file := range files {
filePath := path.Join(yamlDir, dir.Name(), file.Name())
// #nosec G304
data, err := ioutil.ReadFile(filePath)
if err != nil {
return nil, fmt.Errorf("could not read YAML file: %v", err)
}
switch dir.Name() {
case forkChoiceTestsFolderName:
decoded := &backend.ForkChoiceTest{}
if err := yaml.Unmarshal(data, decoded); err != nil {
return nil, fmt.Errorf("could not unmarshal YAML file into test struct: %v", err)
}
tests = append(tests, decoded)
case shuffleTestsFolderName:
decoded := &backend.ShuffleTest{}
if err := yaml.Unmarshal(data, decoded); err != nil {
return nil, fmt.Errorf("could not unmarshal YAML file into test struct: %v", err)
}
tests = append(tests, decoded)
case stateTestsFolderName:
decoded := &backend.StateTest{}
if err := yaml.Unmarshal(data, decoded); err != nil {
return nil, fmt.Errorf("could not unmarshal YAML file into test struct: %v", err)
}
tests = append(tests, decoded)
}
}
}
return tests, nil
}
func runTests(tests []interface{}, sb *backend.SimulatedBackend) error {
for _, tt := range tests {
switch typedTest := tt.(type) {
case *backend.ForkChoiceTest:
log.Infof("Title: %v", typedTest.Title)
log.Infof("Summary: %v", typedTest.Summary)
log.Infof("Test Suite: %v", typedTest.TestSuite)
for _, testCase := range typedTest.TestCases {
if err := sb.RunForkChoiceTest(testCase); err != nil {
return fmt.Errorf("chain test failed: %v", err)
}
}
log.Info("Test PASSED")
case *backend.ShuffleTest:
log.Infof("Title: %v", typedTest.Title)
log.Infof("Summary: %v", typedTest.Summary)
log.Infof("Test Suite: %v", typedTest.TestSuite)
log.Infof("Fork: %v", typedTest.Fork)
log.Infof("Version: %v", typedTest.Version)
for _, testCase := range typedTest.TestCases {
if err := sb.RunShuffleTest(testCase); err != nil {
return fmt.Errorf("chain test failed: %v", err)
}
}
log.Info("Test PASSED")
case *backend.StateTest:
log.Infof("Title: %v", typedTest.Title)
log.Infof("Summary: %v", typedTest.Summary)
log.Infof("Test Suite: %v", typedTest.TestSuite)
log.Infof("Fork: %v", typedTest.Fork)
log.Infof("Version: %v", typedTest.Version)
for _, testCase := range typedTest.TestCases {
if err := sb.RunStateTransitionTest(testCase); err != nil {
return fmt.Errorf("chain test failed: %v", err)
}
}
log.Info("Test PASSED")
default:
return fmt.Errorf("receive unknown test type: %T", typedTest)
}
log.Info("-----------------------------")
}
return nil
}
func main() {
var yamlDir = flag.String("tests-dir", "", "path to directory of yaml tests")
flag.Parse()
customFormatter := new(prefixed.TextFormatter)
customFormatter.TimestampFormat = "2006-01-02 15:04:05"
customFormatter.FullTimestamp = true
log.SetFormatter(customFormatter)
tests, err := readTestsFromYaml(*yamlDir)
if err != nil {
log.Fatalf("Fail to load tests from yaml: %v", err)
}
sb, err := backend.NewSimulatedBackend()
if err != nil {
log.Fatalf("Could not create backend: %v", err)
}
log.Info("----Running Tests----")
startTime := time.Now()
err = runTests(tests, sb)
if err != nil {
log.Fatalf("Test failed %v", err)
}
endTime := time.Now()
log.Infof("Test Runs Finished In: %v", endTime.Sub(startTime))
}

View File

@@ -1,63 +0,0 @@
# Credits to Danny Ryan (Ethereum Foundation)
---
title: Sample Ethereum 2.0 Beacon Chain Test
summary: Basic, functioning fork choice rule for Ethereum 2.0
test_suite: prysm
test_cases:
- config:
validator_count: 100
cycle_length: 8
shard_count: 64
min_committee_size: 8
slots:
# "slot_number" has a minimum of 1
- slot_number: 1
new_block:
id: A
# "*" is used for the genesis block
parent: "*"
attestations:
- block: A
# the following is a shorthand string for [0, 1, 2, 3, 4, 5]
validators: "0-5"
- slot_number: 2
new_block:
id: B
parent: A
attestations:
- block: B
validators: "0-5"
- slot_number: 3
new_block:
id: C
parent: A
attestations:
# attestation "committee_slot" defaults to the slot during which the attestation occurs
- block: C
validators: "2-7"
# default "committee_slot" can be directly overridden
- block: C
committee_slot: 2
validators: "6, 7"
- slot_number: 4
new_block:
id: D
parent: C
attestations:
- block: D
validators: "1-4"
# slots can be skipped entirely (5 in this case)
- slot_number: 6
new_block:
id: E
parent: D
attestations:
- block: E
validators: "0-4"
- block: B
validators: "5, 6, 7"
results:
head: E
last_justified_block: "*"
last_finalized_block: "*"

View File

@@ -1,44 +0,0 @@
# Credits to Danny Ryan (Ethereum Foundation)
---
title: Shuffling Algorithm Tests
summary: Test vectors for shuffling a list based upon a seed using `shuffle`
test_suite: shuffle
fork: tchaikovsky
version: 1.0
test_cases:
- config:
validator_count: 100
cycle_length: 8
shard_count: 32
min_committee_size: 8
- input: []
output: []
seed: !!binary ""
- name: boring_list
description: List with a single element, 0
input: [0]
output: [0]
seed: !!binary ""
- input: [255]
output: [255]
seed: !!binary ""
- input: [4, 6, 2, 6, 1, 4, 6, 2, 1, 5]
output: [2, 1, 6, 1, 4, 5, 6, 4, 6, 2]
seed: !!binary ""
- input: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
output: [4, 9, 1, 13, 8, 3, 5, 10, 7, 6, 11, 2, 12]
seed: !!binary ""
- input: [65, 6, 2, 6, 1, 4, 6, 2, 1, 5]
output: [6, 1, 2, 2, 6, 6, 1, 5, 65, 4]
seed: !!binary |
JlAYJ5H2j8g7PLiPHZI/rTS1uAvKiieOrifPN6Moso0=
- input: [35, 6, 2, 6, 1, 4, 6, 2, 1, 5, 7, 98, 3, 2, 11]
output: [35, 1, 6, 4, 6, 6, 5, 11, 2, 3, 7, 1, 2, 2, 98]
seed: !!binary |
VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIDEzIGxhenkgZG9ncy4=
- input: [35, 6, 2, 6, 1, 4, 6, 2, 1, 5, 7, 98, 3, 2, 11]
output: [98, 6, 6, 11, 5, 35, 2, 7, 2, 6, 4, 2, 1, 3, 1]
seed: !!binary |
rDTbe23J4UA0yLIurjbJqk49VcavAC0Nysas+l5MlwvLc0B/JqQ=

View File

@@ -1,82 +0,0 @@
title: Sample Ethereum Serenity State Transition Tests
summary: Testing full state transition block processing
test_suite: prysm
fork: sapphire
version: 1.0
test_cases:
- config:
slots_per_epoch: 64
deposits_for_chain_start: 64
num_slots: 32 # Testing advancing state to slot < SlotsPerEpoch
results:
slot: 9223372036854775840
num_validators: 64
- config:
slots_per_epoch: 64
deposits_for_chain_start: 64
num_slots: 64 # Testing advancing state to exactly slot == SlotsPerEpoch
deposits:
- slot: 9223372036854775809
amount: 32
merkle_index: 64
pubkey: !!binary |
SlAAbShSkUg7PLiPHZI/rTS1uAvKiieOrifPN6Moso0=
- slot: 9223372036854775823
amount: 32
merkle_index: 65
pubkey: !!binary |
Oklajsjdkaklsdlkajsdjlajslkdjlkasjlkdjlajdsd
- slot: 9223372036854775863
amount: 32
merkle_index: 66
pubkey: !!binary |
LkmqmqoodLKAslkjdkajsdljasdkajlksjdasldjasdd
proposer_slashings:
- slot: 9223372036854775824 # At slot 9223372036854775824, we trigger a proposal slashing occurring
proposer_index: 50 # We penalize the proposer that was just added from slot 15
proposal_1_shard: 0
proposal_1_slot: 15
proposal_1_root: !!binary |
LkmqmqoodLKAslkjdkajsdljasdkajlksjdasldjasdd
proposal_2_shard: 0
proposal_2_slot: 15
proposal_2_root: !!binary |
LkmqmqoodLKAslkjdkajsdljasdkajlksjdasldjasdd
attester_slashings:
- slot: 9223372036854775868 # At slot 59, we trigger a attester slashing
slashable_attestation_1_slot: 9223372036854775864
slashable_attestation_2_slot: 9223372036854775864
slashable_attestation_1_justified_epoch: 0
slashable_attestation_2_justified_epoch: 1
slashable_attestation_1_custody_bitfield: !binary "F"
slashable_attestation_1_validator_indices: [1, 2, 3, 4, 5, 6, 7, 51]
slashable_attestation_2_custody_bitfield: !binary "F"
slashable_attestation_2_validator_indices: [1, 2, 3, 4, 5, 6, 7, 51]
validator_exits:
- epoch: 144115188075855872
validator_index: 45 # At slot 9223372036854775868, validator at index 45 triggers a voluntary exit
results:
slot: 9223372036854775872
num_validators: 67
penalized_validators: [50, 51] # We test that the validators at indices were indeed penalized
exited_validators: [45] # We confirm the indices of validators that willingly exited the registry
# TODO(1387): Waiting for spec to stable to proceed with this test case
# - config:
# skip_slots: [10, 20]
# slots_per_epoch: 64
# deposits_for_chain_start: 1000
# num_slots: 128 # Testing advancing state's slot == 2*SlotsPerEpoch
# deposits:
# - slot: 10
# amount: 32
# merkle_index: 0
# pubkey: !!binary |
# SlAAbShSkUg7PLiPHZI/rTS1uAvKiieOrifPN6Moso0=
# - slot: 20
# amount: 32
# merkle_index: 1
# pubkey: !!binary |
# Oklajsjdkaklsdlkajsdjlajslkdjlkasjlkdjlajdsd
# results:
# slot: 128
# num_validators: 1000 # Validator registry should not have grown if slots 10 and 20 were skipped

View File

@@ -1,49 +0,0 @@
package main
import (
"testing"
"github.com/prysmaticlabs/prysm/beacon-chain/chaintest/backend"
"github.com/prysmaticlabs/prysm/shared/featureconfig"
)
func init() {
featureconfig.InitFeatureConfig(&featureconfig.FeatureFlagConfig{
EnableCrosslinks: true,
})
}
func TestFromYaml_Pass(t *testing.T) {
tests, err := readTestsFromYaml("./tests")
if err != nil {
t.Fatalf("Failed to read yaml files: %v", err)
}
sb, err := backend.NewSimulatedBackend()
if err != nil {
t.Fatalf("Could not create backend: %v", err)
}
if err := runTests(tests, sb); err != nil {
t.Errorf("Failed to run yaml tests %v", err)
}
}
func BenchmarkStateTestFromYaml(b *testing.B) {
tests, err := readTestsFromYaml("./tests")
if err != nil {
b.Fatalf("Failed to read yaml files: %v", err)
}
sb, err := backend.NewSimulatedBackend()
if err != nil {
b.Fatalf("Could not create backend: %v", err)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
if err := runTests(tests, sb); err != nil {
b.Errorf("Failed to run yaml tests %v", err)
}
}
}

View File

@@ -1,27 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = ["rewards_penalties.go"],
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/core/balances",
visibility = ["//beacon-chain:__subpackages__"],
deps = [
"//beacon-chain/core/epoch:go_default_library",
"//beacon-chain/core/helpers:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//shared/params:go_default_library",
"//shared/sliceutil:go_default_library",
],
)
go_test(
name = "go_default_test",
size = "small",
srcs = ["rewards_penalties_test.go"],
embed = [":go_default_library"],
deps = [
"//beacon-chain/core/blocks:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//shared/params:go_default_library",
],
)

View File

@@ -1,379 +0,0 @@
// Package balances contains libraries to calculate reward and
// penalty quotients. It computes new validator balances
// for justifications, crosslinks and attestation inclusions. It
// also computes penalties for the inactive validators.
package balances
import (
"errors"
"fmt"
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/sliceutil"
)
// ExpectedFFGSource applies rewards or penalties
// for an expected FFG source. It uses total justified
// attesting balances, total validator balances and base
// reward quotient to calculate the reward amount.
// Validators who voted for previous justified hash
// will get a reward, everyone else will get a penalty.
//
// Spec pseudocode definition:
// Any validator index in previous_epoch_justified_attester_indices
// gains base_reward(state, index) * previous_epoch_justified_attesting_balance // total_balance.
// Any active validator v not in previous_epoch_justified_attester_indices
// loses base_reward(state, index).
func ExpectedFFGSource(
state *pb.BeaconState,
justifiedAttesterIndices []uint64,
justifiedAttestingBalance uint64,
totalBalance uint64) *pb.BeaconState {
baseRewardQuotient := helpers.BaseRewardQuotient(totalBalance)
for _, index := range justifiedAttesterIndices {
state.ValidatorBalances[index] +=
helpers.BaseReward(state, index, baseRewardQuotient) *
justifiedAttestingBalance /
totalBalance
}
activeValidatorIndices := helpers.ActiveValidatorIndices(state.ValidatorRegistry, helpers.CurrentEpoch(state))
didNotAttestIndices := sliceutil.NotUint64(justifiedAttesterIndices, activeValidatorIndices)
for _, index := range didNotAttestIndices {
state.ValidatorBalances[index] -=
helpers.BaseReward(state, index, baseRewardQuotient)
}
return state
}
// ExpectedFFGTarget applies rewards or penalties
// for an expected FFG target. It uses total boundary
// attesting balances, total validator balances and base
// reward quotient to calculate the reward amount.
// Validators who voted for epoch boundary block
// will get a reward, everyone else will get a penalty.
//
// Spec pseudocode definition:
// Any validator index in previous_epoch_boundary_attester_indices gains
// base_reward(state, index) * previous_epoch_boundary_attesting_balance // total_balance.
// Any active validator index not in previous_epoch_boundary_attester_indices loses
// base_reward(state, index).
func ExpectedFFGTarget(
state *pb.BeaconState,
boundaryAttesterIndices []uint64,
boundaryAttestingBalance uint64,
totalBalance uint64) *pb.BeaconState {
baseRewardQuotient := helpers.BaseRewardQuotient(totalBalance)
for _, index := range boundaryAttesterIndices {
state.ValidatorBalances[index] +=
helpers.BaseReward(state, index, baseRewardQuotient) *
boundaryAttestingBalance /
totalBalance
}
activeValidatorIndices := helpers.ActiveValidatorIndices(state.ValidatorRegistry, helpers.CurrentEpoch(state))
didNotAttestIndices := sliceutil.NotUint64(boundaryAttesterIndices, activeValidatorIndices)
for _, index := range didNotAttestIndices {
state.ValidatorBalances[index] -=
helpers.BaseReward(state, index, baseRewardQuotient)
}
return state
}
// ExpectedBeaconChainHead applies rewards or penalties
// for an expected beacon chain head. It uses total head
// attesting balances, total validator balances and base
// reward quotient to calculate the reward amount.
// Validators who voted for the canonical head block
// will get a reward, everyone else will get a penalty.
//
// Spec pseudocode definition:
// Any validator index in previous_epoch_head_attester_indices gains
// base_reward(state, index) * previous_epoch_head_attesting_balance // total_balance).
// Any active validator index not in previous_epoch_head_attester_indices loses
// base_reward(state, index).
func ExpectedBeaconChainHead(
state *pb.BeaconState,
headAttesterIndices []uint64,
headAttestingBalance uint64,
totalBalance uint64) *pb.BeaconState {
baseRewardQuotient := helpers.BaseRewardQuotient(totalBalance)
for _, index := range headAttesterIndices {
state.ValidatorBalances[index] +=
helpers.BaseReward(state, index, baseRewardQuotient) *
headAttestingBalance /
totalBalance
}
activeValidatorIndices := helpers.ActiveValidatorIndices(state.ValidatorRegistry, helpers.CurrentEpoch(state))
didNotAttestIndices := sliceutil.NotUint64(headAttesterIndices, activeValidatorIndices)
for _, index := range didNotAttestIndices {
state.ValidatorBalances[index] -=
helpers.BaseReward(state, index, baseRewardQuotient)
}
return state
}
// InclusionDistance applies rewards based on
// inclusion distance. It uses calculated inclusion distance
// and base reward quotient to calculate the reward amount.
//
// Spec pseudocode definition:
// Any validator index in previous_epoch_attester_indices gains
// base_reward(state, index) * MIN_ATTESTATION_INCLUSION_DELAY //
// inclusion_distance(state, index)
func InclusionDistance(
state *pb.BeaconState,
attesterIndices []uint64,
totalBalance uint64,
inclusionDistanceByAttester map[uint64]uint64) (*pb.BeaconState, error) {
baseRewardQuotient := helpers.BaseRewardQuotient(totalBalance)
for _, index := range attesterIndices {
inclusionDistance, ok := inclusionDistanceByAttester[index]
if !ok {
return nil, fmt.Errorf("could not get inclusion distance for attester: %d", index)
}
if inclusionDistance == 0 {
return nil, errors.New("could not process inclusion distance: 0")
}
state.ValidatorBalances[index] +=
helpers.BaseReward(state, index, baseRewardQuotient) *
params.BeaconConfig().MinAttestationInclusionDelay /
inclusionDistance
}
return state, nil
}
// InactivityFFGSource applies penalties to inactive
// validators that missed to vote FFG source over an
// extended of time. (epochs_since_finality > 4)
//
// Spec pseudocode definition:
// Any active validator index not in previous_epoch_justified_attester_indices,
// loses inactivity_penalty(state, index, epochs_since_finality)
func InactivityFFGSource(
state *pb.BeaconState,
justifiedAttesterIndices []uint64,
totalBalance uint64,
epochsSinceFinality uint64) *pb.BeaconState {
baseRewardQuotient := helpers.BaseRewardQuotient(totalBalance)
activeValidatorIndices := helpers.ActiveValidatorIndices(state.ValidatorRegistry, helpers.CurrentEpoch(state))
didNotAttestIndices := sliceutil.NotUint64(justifiedAttesterIndices, activeValidatorIndices)
for _, index := range didNotAttestIndices {
state.ValidatorBalances[index] -=
helpers.InactivityPenalty(state, index, baseRewardQuotient, epochsSinceFinality)
}
return state
}
// InactivityFFGTarget applies penalties to inactive
// validators that missed to vote FFG target over an
// extended of time. (epochs_since_finality > 4)
//
// Spec pseudocode definition:
// Any active validator index not in previous_epoch_boundary_attester_indices,
// loses inactivity_penalty(state, index, epochs_since_finality)
func InactivityFFGTarget(
state *pb.BeaconState,
boundaryAttesterIndices []uint64,
totalBalance uint64,
epochsSinceFinality uint64) *pb.BeaconState {
baseRewardQuotient := helpers.BaseRewardQuotient(totalBalance)
activeValidatorIndices := helpers.ActiveValidatorIndices(state.ValidatorRegistry, helpers.CurrentEpoch(state))
didNotAttestIndices := sliceutil.NotUint64(boundaryAttesterIndices, activeValidatorIndices)
for _, index := range didNotAttestIndices {
state.ValidatorBalances[index] -=
helpers.InactivityPenalty(state, index, baseRewardQuotient, epochsSinceFinality)
}
return state
}
// InactivityChainHead applies penalties to inactive validators
// that missed to vote on canonical head over an extended of time.
// (epochs_since_finality > 4)
//
// Spec pseudocode definition:
// Any active validator index not in previous_epoch_head_attester_indices,
// loses base_reward(state, index)
func InactivityChainHead(
state *pb.BeaconState,
headAttesterIndices []uint64,
totalBalance uint64) *pb.BeaconState {
baseRewardQuotient := helpers.BaseRewardQuotient(totalBalance)
activeValidatorIndices := helpers.ActiveValidatorIndices(state.ValidatorRegistry, helpers.CurrentEpoch(state))
didNotAttestIndices := sliceutil.NotUint64(headAttesterIndices, activeValidatorIndices)
for _, index := range didNotAttestIndices {
state.ValidatorBalances[index] -=
helpers.BaseReward(state, index, baseRewardQuotient)
}
return state
}
// InactivityExitedPenalties applies additional (2x) penalties
// to inactive validators with status EXITED_WITH_PENALTY.
//
// Spec pseudocode definition:
// Any active_validator index with validator.slashed_epoch <= current_epoch,
// loses 2 * inactivity_penalty(state, index, epochs_since_finality) +
// base_reward(state, index).
func InactivityExitedPenalties(
state *pb.BeaconState,
totalBalance uint64,
epochsSinceFinality uint64) *pb.BeaconState {
baseRewardQuotient := helpers.BaseRewardQuotient(totalBalance)
currentEpoch := helpers.CurrentEpoch(state)
activeValidatorIndices := helpers.ActiveValidatorIndices(state.ValidatorRegistry, currentEpoch)
for _, index := range activeValidatorIndices {
if state.ValidatorRegistry[index].SlashedEpoch <= currentEpoch {
state.ValidatorBalances[index] -=
2*helpers.InactivityPenalty(state, index, baseRewardQuotient, epochsSinceFinality) +
helpers.BaseReward(state, index, baseRewardQuotient)
}
}
return state
}
// InactivityInclusionDistance applies penalties in relation with
// inclusion delay to inactive validators.
//
// Spec pseudocode definition:
// Any validator index in previous_epoch_attester_indices loses
// base_reward(state, index) - base_reward(state, index) *
// MIN_ATTESTATION_INCLUSION_DELAY // inclusion_distance(state, index)
func InactivityInclusionDistance(
state *pb.BeaconState,
attesterIndices []uint64,
totalBalance uint64,
inclusionDistanceByAttester map[uint64]uint64) (*pb.BeaconState, error) {
baseRewardQuotient := helpers.BaseRewardQuotient(totalBalance)
for _, index := range attesterIndices {
inclusionDistance, ok := inclusionDistanceByAttester[index]
if !ok {
return nil, fmt.Errorf("could not get inclusion distance for attester: %d", index)
}
baseReward := helpers.BaseReward(state, index, baseRewardQuotient)
state.ValidatorBalances[index] -= baseReward -
baseReward*params.BeaconConfig().MinAttestationInclusionDelay/
inclusionDistance
}
return state, nil
}
// AttestationInclusion awards the the beacon
// proposers who included previous epoch attestations.
//
// Spec pseudocode definition:
// For each index in previous_epoch_attester_indices,
// we determine the proposer proposer_index =
// get_beacon_proposer_index(state, inclusion_slot(state, index))
// and set state.validator_balances[proposer_index] +=
// base_reward(state, index) // ATTESTATION_INCLUSION_REWARD_QUOTIENT
func AttestationInclusion(
state *pb.BeaconState,
totalBalance uint64,
prevEpochAttesterIndices []uint64,
inclusionSlotByAttester map[uint64]uint64) (*pb.BeaconState, error) {
baseRewardQuotient := helpers.BaseRewardQuotient(totalBalance)
for _, index := range prevEpochAttesterIndices {
// Get the attestation's inclusion slot using the attestor's index.
slot, ok := inclusionSlotByAttester[index]
if !ok {
return nil, fmt.Errorf("could not get inclusion slot for attester: %d", index)
}
proposerIndex, err := helpers.BeaconProposerIndex(state, slot)
if err != nil {
return nil, fmt.Errorf("could not get proposer index: %v", err)
}
state.ValidatorBalances[proposerIndex] +=
helpers.BaseReward(state, proposerIndex, baseRewardQuotient) /
params.BeaconConfig().AttestationInclusionRewardQuotient
}
return state, nil
}
// Crosslinks awards or slashs attesters
// for attesting shard cross links.
//
// Spec pseudocode definition:
// For slot in range(get_epoch_start_slot(previous_epoch), get_epoch_start_slot(current_epoch)),
// let crosslink_committees_at_slot = get_crosslink_committees_at_slot(slot).
// For every (crosslink_committee, shard) in crosslink_committee_at_slot,
// and every index in crosslink_committee:
// If index in attesting_validators(crosslink_committee),
// state.validator_balances[index] += base_reward(state, index) *
// total_attesting_balance(crosslink_committee) //
// get_total_balance(state, crosslink_committee)).
// If index not in attesting_validators(crosslink_committee),
// state.validator_balances[index] -= base_reward(state, index).
func Crosslinks(
state *pb.BeaconState,
thisEpochAttestations []*pb.PendingAttestation,
prevEpochAttestations []*pb.PendingAttestation) (*pb.BeaconState, error) {
prevEpoch := helpers.PrevEpoch(state)
currentEpoch := helpers.CurrentEpoch(state)
startSlot := helpers.StartSlot(prevEpoch)
endSlot := helpers.StartSlot(currentEpoch)
for i := startSlot; i < endSlot; i++ {
// RegistryChange is a no-op when requesting slot in current and previous epoch.
// Process crosslinks rewards will never request crosslink committees of next epoch.
crosslinkCommittees, err := helpers.CrosslinkCommitteesAtSlot(state, i, false /* registryChange */)
if err != nil {
return nil, fmt.Errorf("could not get shard committees for slot %d: %v",
i-params.BeaconConfig().GenesisSlot, err)
}
for _, crosslinkCommittee := range crosslinkCommittees {
shard := crosslinkCommittee.Shard
committee := crosslinkCommittee.Committee
totalAttestingBalance, err :=
epoch.TotalAttestingBalance(state, shard, thisEpochAttestations, prevEpochAttestations)
if err != nil {
return nil,
fmt.Errorf("could not get attesting balance for shard committee %d: %v", shard, err)
}
totalBalance := epoch.TotalBalance(state, committee)
baseRewardQuotient := helpers.BaseRewardQuotient(totalBalance)
attestingIndices, err := epoch.AttestingValidators(
state,
shard,
thisEpochAttestations,
prevEpochAttestations)
if err != nil {
return nil,
fmt.Errorf("could not get attesting indices for shard committee %d: %v", shard, err)
}
for _, index := range committee {
baseReward := helpers.BaseReward(state, index, baseRewardQuotient)
if sliceutil.IsInUint64(index, attestingIndices) {
state.ValidatorBalances[index] +=
baseReward * totalAttestingBalance / totalBalance
} else {
state.ValidatorBalances[index] -= baseReward
}
}
}
}
return state, nil
}

View File

@@ -1,677 +0,0 @@
package balances
import (
"reflect"
"testing"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/params"
)
func TestFFGSrcRewardsPenalties_AccurateBalances(t *testing.T) {
tests := []struct {
voted []uint64
balanceAfterSrcRewardPenalties []uint64
}{
// voted represents the validator indices that voted for FFG source,
// balanceAfterSrcRewardPenalties represents their final balances,
// validators who voted should get an increase, who didn't should get a decrease.
{[]uint64{}, []uint64{31999427550, 31999427550, 31999427550, 31999427550}},
{[]uint64{0, 1}, []uint64{32000286225, 32000286225, 31999427550, 31999427550}},
{[]uint64{0, 1, 2, 3}, []uint64{32000572450, 32000572450, 32000572450, 32000572450}},
}
for _, tt := range tests {
validatorBalances := make([]uint64, 4)
for i := 0; i < len(validatorBalances); i++ {
validatorBalances[i] = params.BeaconConfig().MaxDepositAmount
}
state := &pb.BeaconState{
ValidatorRegistry: []*pb.Validator{
{ExitEpoch: params.BeaconConfig().FarFutureEpoch},
{ExitEpoch: params.BeaconConfig().FarFutureEpoch},
{ExitEpoch: params.BeaconConfig().FarFutureEpoch},
{ExitEpoch: params.BeaconConfig().FarFutureEpoch},
},
ValidatorBalances: validatorBalances,
}
state = ExpectedFFGSource(
state,
tt.voted,
uint64(len(tt.voted))*params.BeaconConfig().MaxDepositAmount,
uint64(len(validatorBalances))*params.BeaconConfig().MaxDepositAmount)
if !reflect.DeepEqual(state.ValidatorBalances, tt.balanceAfterSrcRewardPenalties) {
t.Errorf("FFGSrcRewardsPenalties(%v) = %v, wanted: %v",
tt.voted, state.ValidatorBalances, tt.balanceAfterSrcRewardPenalties)
}
}
}
func TestFFGTargetRewardsPenalties_AccurateBalances(t *testing.T) {
tests := []struct {
voted []uint64
balanceAfterTgtRewardPenalties []uint64
}{
// voted represents the validator indices that voted for FFG target,
// balanceAfterTgtRewardPenalties represents their final balances,
// validators who voted should get an increase, who didn't should get a decrease.
{[]uint64{}, []uint64{31999427550, 31999427550, 31999427550, 31999427550}},
{[]uint64{0, 1}, []uint64{32000286225, 32000286225, 31999427550, 31999427550}},
{[]uint64{0, 1, 2, 3}, []uint64{32000572450, 32000572450, 32000572450, 32000572450}},
}
for _, tt := range tests {
validatorBalances := make([]uint64, 4)
for i := 0; i < len(validatorBalances); i++ {
validatorBalances[i] = params.BeaconConfig().MaxDepositAmount
}
state := &pb.BeaconState{
ValidatorRegistry: []*pb.Validator{
{ExitEpoch: params.BeaconConfig().FarFutureEpoch},
{ExitEpoch: params.BeaconConfig().FarFutureEpoch},
{ExitEpoch: params.BeaconConfig().FarFutureEpoch},
{ExitEpoch: params.BeaconConfig().FarFutureEpoch},
},
ValidatorBalances: validatorBalances,
}
state = ExpectedFFGTarget(
state,
tt.voted,
uint64(len(tt.voted))*params.BeaconConfig().MaxDepositAmount,
uint64(len(validatorBalances))*params.BeaconConfig().MaxDepositAmount)
if !reflect.DeepEqual(state.ValidatorBalances, tt.balanceAfterTgtRewardPenalties) {
t.Errorf("FFGTargetRewardsPenalties(%v) = %v, wanted: %v",
tt.voted, state.ValidatorBalances, tt.balanceAfterTgtRewardPenalties)
}
}
}
func TestChainHeadRewardsPenalties_AccuratePenalties(t *testing.T) {
tests := []struct {
voted []uint64
balanceAfterHeadRewardPenalties []uint64
}{
// voted represents the validator indices that voted for canonical chain,
// balanceAfterHeadRewardPenalties represents their final balances,
// validators who voted should get an increase, who didn't should get a decrease.
{[]uint64{}, []uint64{31999427550, 31999427550, 31999427550, 31999427550}},
{[]uint64{0, 1}, []uint64{32000286225, 32000286225, 31999427550, 31999427550}},
{[]uint64{0, 1, 2, 3}, []uint64{32000572450, 32000572450, 32000572450, 32000572450}},
}
for _, tt := range tests {
validatorBalances := make([]uint64, 4)
for i := 0; i < len(validatorBalances); i++ {
validatorBalances[i] = params.BeaconConfig().MaxDepositAmount
}
state := &pb.BeaconState{
ValidatorRegistry: []*pb.Validator{
{ExitEpoch: params.BeaconConfig().FarFutureEpoch},
{ExitEpoch: params.BeaconConfig().FarFutureEpoch},
{ExitEpoch: params.BeaconConfig().FarFutureEpoch},
{ExitEpoch: params.BeaconConfig().FarFutureEpoch},
},
ValidatorBalances: validatorBalances,
}
state = ExpectedBeaconChainHead(
state,
tt.voted,
uint64(len(tt.voted))*params.BeaconConfig().MaxDepositAmount,
uint64(len(validatorBalances))*params.BeaconConfig().MaxDepositAmount)
if !reflect.DeepEqual(state.ValidatorBalances, tt.balanceAfterHeadRewardPenalties) {
t.Errorf("ChainHeadRewardsPenalties(%v) = %v, wanted: %v",
tt.voted, state.ValidatorBalances, tt.balanceAfterHeadRewardPenalties)
}
}
}
func TestInclusionDistRewards_AccurateRewards(t *testing.T) {
validators := make([]*pb.Validator, params.BeaconConfig().DepositsForChainStart)
for i := 0; i < len(validators); i++ {
validators[i] = &pb.Validator{
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
}
}
var participationBitfield []byte
// participation byte length = number of validators / target committee size / bits in a byte.
byteLength := int(params.BeaconConfig().DepositsForChainStart / params.BeaconConfig().TargetCommitteeSize / 8)
for i := 0; i < byteLength; i++ {
participationBitfield = append(participationBitfield, byte(0xff))
}
attestations := []*pb.PendingAttestation{
{Data: &pb.AttestationData{
Slot: params.BeaconConfig().GenesisSlot,
JustifiedBlockRootHash32: []byte{},
Shard: 0,
CrosslinkDataRootHash32: params.BeaconConfig().ZeroHash[:],
},
AggregationBitfield: participationBitfield,
InclusionSlot: params.BeaconConfig().GenesisSlot + 5,
},
}
tests := []struct {
voted []uint64
}{
{[]uint64{}},
{[]uint64{251, 192}},
}
for _, tt := range tests {
validatorBalances := make([]uint64, len(validators))
for i := 0; i < len(validatorBalances); i++ {
validatorBalances[i] = params.BeaconConfig().MaxDepositAmount
}
state := &pb.BeaconState{
Slot: params.BeaconConfig().GenesisSlot + 5,
ValidatorRegistry: validators,
ValidatorBalances: validatorBalances,
LatestAttestations: attestations,
PreviousJustifiedRoot: []byte{},
LatestCrosslinks: []*pb.Crosslink{
{
CrosslinkDataRootHash32: params.BeaconConfig().ZeroHash[:],
Epoch: params.BeaconConfig().GenesisEpoch,
},
},
}
block := &pb.BeaconBlock{
Body: &pb.BeaconBlockBody{
Attestations: []*pb.Attestation{
{
Data: attestations[0].Data,
},
},
},
}
if _, err := blocks.ProcessBlockAttestations(state, block, false /* verify sig */); err != nil {
t.Fatal(err)
}
inclusionMap := make(map[uint64]uint64)
for _, voted := range tt.voted {
inclusionMap[voted] = state.Slot
}
state, err := InclusionDistance(
state,
tt.voted,
uint64(len(validatorBalances))*params.BeaconConfig().MaxDepositAmount,
inclusionMap)
if err != nil {
t.Fatalf("could not execute InclusionDistRewards:%v", err)
}
for _, i := range tt.voted {
validatorBalances[i] = 32000055555
}
if !reflect.DeepEqual(state.ValidatorBalances, validatorBalances) {
t.Errorf("InclusionDistRewards(%v) = %v, wanted: %v",
tt.voted, state.ValidatorBalances, validatorBalances)
}
}
}
func TestInclusionDistRewards_OutOfBounds(t *testing.T) {
validators := make([]*pb.Validator, params.BeaconConfig().SlotsPerEpoch*2)
for i := 0; i < len(validators); i++ {
validators[i] = &pb.Validator{
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
}
}
attestation := []*pb.PendingAttestation{
{Data: &pb.AttestationData{Shard: 1, Slot: 0},
AggregationBitfield: []byte{0xff}},
}
tests := []struct {
voted []uint64
balanceAfterInclusionRewards []uint64
}{
{[]uint64{0, 1, 2, 3}, []uint64{}},
}
for _, tt := range tests {
state := &pb.BeaconState{
ValidatorRegistry: validators,
LatestAttestations: attestation,
}
inclusionMap := make(map[uint64]uint64)
_, err := InclusionDistance(state, tt.voted, 0, inclusionMap)
if err == nil {
t.Fatal("InclusionDistRewards should have failed")
}
}
}
func TestInactivityFFGSrcPenalty_AccuratePenalties(t *testing.T) {
tests := []struct {
voted []uint64
balanceAfterFFGSrcPenalty []uint64
epochsSinceFinality uint64
}{
// The higher the epochs since finality, the more penalties applied.
{[]uint64{0, 1}, []uint64{32000000000, 32000000000, 31999422782, 31999422782}, 5},
{[]uint64{}, []uint64{31999422782, 31999422782, 31999422782, 31999422782}, 5},
{[]uint64{}, []uint64{31999418014, 31999418014, 31999418014, 31999418014}, 10},
{[]uint64{}, []uint64{31999408477, 31999408477, 31999408477, 31999408477}, 20},
}
for _, tt := range tests {
validatorBalances := make([]uint64, 4)
for i := 0; i < len(validatorBalances); i++ {
validatorBalances[i] = params.BeaconConfig().MaxDepositAmount
}
state := &pb.BeaconState{
ValidatorRegistry: []*pb.Validator{
{ExitEpoch: params.BeaconConfig().FarFutureEpoch},
{ExitEpoch: params.BeaconConfig().FarFutureEpoch},
{ExitEpoch: params.BeaconConfig().FarFutureEpoch},
{ExitEpoch: params.BeaconConfig().FarFutureEpoch},
},
ValidatorBalances: validatorBalances,
}
state = InactivityFFGSource(
state,
tt.voted,
uint64(len(validatorBalances))*params.BeaconConfig().MaxDepositAmount,
tt.epochsSinceFinality)
if !reflect.DeepEqual(state.ValidatorBalances, tt.balanceAfterFFGSrcPenalty) {
t.Errorf("InactivityFFGSrcPenalty(%v) = %v, wanted: %v",
tt.voted, state.ValidatorBalances, tt.balanceAfterFFGSrcPenalty)
}
}
}
func TestInactivityFFGTargetPenalty_AccuratePenalties(t *testing.T) {
tests := []struct {
voted []uint64
balanceAfterFFGTargetPenalty []uint64
epochsSinceFinality uint64
}{
// The higher the epochs since finality, the more penalties applied.
{[]uint64{0, 1}, []uint64{32000000000, 32000000000, 31999422782, 31999422782}, 5},
{[]uint64{}, []uint64{31999422782, 31999422782, 31999422782, 31999422782}, 5},
{[]uint64{}, []uint64{31999418014, 31999418014, 31999418014, 31999418014}, 10},
{[]uint64{}, []uint64{31999408477, 31999408477, 31999408477, 31999408477}, 20},
}
for _, tt := range tests {
validatorBalances := make([]uint64, 4)
for i := 0; i < len(validatorBalances); i++ {
validatorBalances[i] = params.BeaconConfig().MaxDepositAmount
}
state := &pb.BeaconState{
ValidatorRegistry: []*pb.Validator{
{ExitEpoch: params.BeaconConfig().FarFutureEpoch},
{ExitEpoch: params.BeaconConfig().FarFutureEpoch},
{ExitEpoch: params.BeaconConfig().FarFutureEpoch},
{ExitEpoch: params.BeaconConfig().FarFutureEpoch},
},
ValidatorBalances: validatorBalances,
}
state = InactivityFFGTarget(
state,
tt.voted,
uint64(len(validatorBalances))*params.BeaconConfig().MaxDepositAmount,
tt.epochsSinceFinality)
if !reflect.DeepEqual(state.ValidatorBalances, tt.balanceAfterFFGTargetPenalty) {
t.Errorf("InactivityFFGTargetPenalty(%v) = %v, wanted: %v",
tt.voted, state.ValidatorBalances, tt.balanceAfterFFGTargetPenalty)
}
}
}
func TestInactivityHeadPenalty_AccuratePenalties(t *testing.T) {
tests := []struct {
voted []uint64
balanceAfterInactivityHeadPenalty []uint64
}{
{[]uint64{}, []uint64{31999427550, 31999427550, 31999427550, 31999427550}},
{[]uint64{0, 1}, []uint64{32000000000, 32000000000, 31999427550, 31999427550}},
{[]uint64{0, 1, 2, 3}, []uint64{32000000000, 32000000000, 32000000000, 32000000000}},
}
for _, tt := range tests {
validatorBalances := make([]uint64, 4)
for i := 0; i < len(validatorBalances); i++ {
validatorBalances[i] = params.BeaconConfig().MaxDepositAmount
}
state := &pb.BeaconState{
ValidatorRegistry: []*pb.Validator{
{ExitEpoch: params.BeaconConfig().FarFutureEpoch},
{ExitEpoch: params.BeaconConfig().FarFutureEpoch},
{ExitEpoch: params.BeaconConfig().FarFutureEpoch},
{ExitEpoch: params.BeaconConfig().FarFutureEpoch},
},
ValidatorBalances: validatorBalances,
}
state = InactivityChainHead(
state,
tt.voted,
uint64(len(validatorBalances))*params.BeaconConfig().MaxDepositAmount)
if !reflect.DeepEqual(state.ValidatorBalances, tt.balanceAfterInactivityHeadPenalty) {
t.Errorf("InactivityHeadPenalty(%v) = %v, wanted: %v",
tt.voted, state.ValidatorBalances, tt.balanceAfterInactivityHeadPenalty)
}
}
}
func TestInactivityExitedPenality_AccuratePenalties(t *testing.T) {
tests := []struct {
balanceAfterExitedPenalty []uint64
epochsSinceFinality uint64
}{
{[]uint64{31998273114, 31998273114, 31998273114, 31998273114}, 5},
{[]uint64{31998263578, 31998263578, 31998263578, 31998263578}, 10},
{[]uint64{31997328976, 31997328976, 31997328976, 31997328976}, 500},
}
for _, tt := range tests {
validatorBalances := make([]uint64, 4)
for i := 0; i < len(validatorBalances); i++ {
validatorBalances[i] = params.BeaconConfig().MaxDepositAmount
}
state := &pb.BeaconState{
ValidatorRegistry: []*pb.Validator{
{ExitEpoch: params.BeaconConfig().FarFutureEpoch},
{ExitEpoch: params.BeaconConfig().FarFutureEpoch},
{ExitEpoch: params.BeaconConfig().FarFutureEpoch},
{ExitEpoch: params.BeaconConfig().FarFutureEpoch}},
ValidatorBalances: validatorBalances,
}
state = InactivityExitedPenalties(
state,
uint64(len(validatorBalances))*params.BeaconConfig().MaxDepositAmount,
tt.epochsSinceFinality,
)
if !reflect.DeepEqual(state.ValidatorBalances, tt.balanceAfterExitedPenalty) {
t.Errorf("InactivityExitedPenalty(epochSinceFinality=%v) = %v, wanted: %v",
tt.epochsSinceFinality, state.ValidatorBalances, tt.balanceAfterExitedPenalty)
}
}
}
func TestInactivityInclusionPenalty_AccuratePenalties(t *testing.T) {
validators := make([]*pb.Validator, params.BeaconConfig().DepositsForChainStart)
for i := 0; i < len(validators); i++ {
validators[i] = &pb.Validator{
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
}
}
var participationBitfield []byte
// participation byte length = number of validators / target committee size / bits in a byte.
byteLength := int(params.BeaconConfig().DepositsForChainStart / params.BeaconConfig().TargetCommitteeSize / 8)
for i := 0; i < byteLength; i++ {
participationBitfield = append(participationBitfield, byte(0xff))
}
attestation := []*pb.PendingAttestation{
{Data: &pb.AttestationData{Slot: params.BeaconConfig().GenesisSlot},
AggregationBitfield: participationBitfield,
InclusionSlot: 5},
}
tests := []struct {
voted []uint64
}{
{[]uint64{}},
{[]uint64{251, 192}},
}
for _, tt := range tests {
validatorBalances := make([]uint64, params.BeaconConfig().SlotsPerEpoch*4)
for i := 0; i < len(validatorBalances); i++ {
validatorBalances[i] = params.BeaconConfig().MaxDepositAmount
}
state := &pb.BeaconState{
Slot: params.BeaconConfig().GenesisSlot,
ValidatorRegistry: validators,
ValidatorBalances: validatorBalances,
LatestAttestations: attestation,
}
inclusionMap := make(map[uint64]uint64)
for _, voted := range tt.voted {
inclusionMap[voted] = state.Slot + 1
}
state, err := InactivityInclusionDistance(
state,
tt.voted,
uint64(len(validatorBalances))*params.BeaconConfig().MaxDepositAmount,
inclusionMap)
for _, i := range tt.voted {
validatorBalances[i] = 32000055555
}
if err != nil {
t.Fatalf("could not execute InactivityInclusionPenalty:%v", err)
}
if !reflect.DeepEqual(state.ValidatorBalances, validatorBalances) {
t.Errorf("InactivityInclusionPenalty(%v) = %v, wanted: %v",
tt.voted, state.ValidatorBalances, validatorBalances)
}
}
}
func TestInactivityInclusionPenalty_OutOfBounds(t *testing.T) {
validators := make([]*pb.Validator, params.BeaconConfig().SlotsPerEpoch*2)
for i := 0; i < len(validators); i++ {
validators[i] = &pb.Validator{
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
}
}
attestation := []*pb.PendingAttestation{
{Data: &pb.AttestationData{Shard: 1, Slot: 0},
AggregationBitfield: []byte{0xff}},
}
tests := []struct {
voted []uint64
balanceAfterInclusionRewards []uint64
}{
{[]uint64{0, 1, 2, 3}, []uint64{}},
}
for _, tt := range tests {
state := &pb.BeaconState{
ValidatorRegistry: validators,
LatestAttestations: attestation,
}
inclusionMap := make(map[uint64]uint64)
_, err := InactivityInclusionDistance(state, tt.voted, 0, inclusionMap)
if err == nil {
t.Fatal("InclusionDistRewards should have failed")
}
}
}
func TestAttestationInclusionRewards_AccurateRewards(t *testing.T) {
validators := make([]*pb.Validator, params.BeaconConfig().DepositsForChainStart)
for i := 0; i < len(validators); i++ {
validators[i] = &pb.Validator{
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
}
}
var participationBitfield []byte
// participation byte length = number of validators / target committee size / bits in a byte.
byteLength := int(params.BeaconConfig().DepositsForChainStart / params.BeaconConfig().TargetCommitteeSize / 8)
for i := 0; i < byteLength; i++ {
participationBitfield = append(participationBitfield, byte(0xff))
}
atts := []*pb.Attestation{
{Data: &pb.AttestationData{
Slot: params.BeaconConfig().GenesisSlot,
LatestCrosslink: &pb.Crosslink{},
CrosslinkDataRootHash32: params.BeaconConfig().ZeroHash[:]}}}
pendingAtts := []*pb.PendingAttestation{
{Data: &pb.AttestationData{Slot: params.BeaconConfig().GenesisSlot},
AggregationBitfield: participationBitfield,
InclusionSlot: params.BeaconConfig().GenesisSlot},
}
tests := []struct {
voted []uint64
}{
{[]uint64{}},
{[]uint64{251}},
}
for _, tt := range tests {
validatorBalances := make([]uint64, params.BeaconConfig().DepositsForChainStart)
for i := 0; i < len(validatorBalances); i++ {
validatorBalances[i] = params.BeaconConfig().MaxDepositAmount
}
state := &pb.BeaconState{
Slot: params.BeaconConfig().GenesisSlot + 10,
ValidatorRegistry: validators,
ValidatorBalances: validatorBalances,
LatestAttestations: pendingAtts,
LatestCrosslinks: []*pb.Crosslink{{}},
}
_, err := blocks.ProcessBlockAttestations(state, &pb.BeaconBlock{
Body: &pb.BeaconBlockBody{
Attestations: atts,
},
}, false /* sig verification */)
if err != nil {
t.Fatal(err)
}
inclusionMap := make(map[uint64]uint64)
for _, voted := range tt.voted {
inclusionMap[voted] = state.Slot
}
state, err = AttestationInclusion(
state,
uint64(len(validatorBalances))*params.BeaconConfig().MaxDepositAmount,
tt.voted,
inclusionMap)
for _, i := range tt.voted {
validatorBalances[i] = 32000008680
}
if err != nil {
t.Fatalf("could not execute InactivityInclusionPenalty:%v", err)
}
if !reflect.DeepEqual(state.ValidatorBalances, validatorBalances) {
t.Errorf("AttestationInclusionRewards(%v) = %v, wanted: %v",
tt.voted, state.ValidatorBalances, validatorBalances)
}
}
}
func TestAttestationInclusionRewards_NoInclusionSlot(t *testing.T) {
validators := make([]*pb.Validator, params.BeaconConfig().SlotsPerEpoch*2)
for i := 0; i < len(validators); i++ {
validators[i] = &pb.Validator{
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
}
}
tests := []struct {
voted []uint64
balanceAfterAttestationInclusion []uint64
}{
{[]uint64{0, 1, 2, 3}, []uint64{32000000000, 32000000000, 32000000000, 32000000000}},
}
for _, tt := range tests {
validatorBalances := make([]uint64, 128)
for i := 0; i < len(validatorBalances); i++ {
validatorBalances[i] = params.BeaconConfig().MaxDepositAmount
}
state := &pb.BeaconState{
ValidatorRegistry: validators,
ValidatorBalances: validatorBalances,
}
inclusionMap := make(map[uint64]uint64)
if _, err := AttestationInclusion(state, 0, tt.voted, inclusionMap); err == nil {
t.Fatal("AttestationInclusionRewards should have failed with no inclusion slot")
}
}
}
func TestAttestationInclusionRewards_NoProposerIndex(t *testing.T) {
validators := make([]*pb.Validator, params.BeaconConfig().SlotsPerEpoch*2)
for i := 0; i < len(validators); i++ {
validators[i] = &pb.Validator{
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
}
}
attestation := []*pb.PendingAttestation{
{Data: &pb.AttestationData{Shard: 1, Slot: 0},
AggregationBitfield: []byte{0xff},
InclusionSlot: 0},
}
tests := []struct {
voted []uint64
balanceAfterAttestationInclusion []uint64
}{
{[]uint64{0}, []uint64{32000071022, 32000000000, 32000000000, 32000000000}},
}
for _, tt := range tests {
validatorBalances := make([]uint64, 4)
for i := 0; i < len(validatorBalances); i++ {
validatorBalances[i] = params.BeaconConfig().MaxDepositAmount
}
state := &pb.BeaconState{
Slot: 1000,
ValidatorRegistry: validators,
ValidatorBalances: validatorBalances,
LatestAttestations: attestation,
}
inclusionMap := make(map[uint64]uint64)
if _, err := AttestationInclusion(state, 0, tt.voted, inclusionMap); err == nil {
t.Fatal("AttestationInclusionRewards should have failed with no proposer index")
}
}
}
func TestCrosslinksRewardsPenalties_AccurateBalances(t *testing.T) {
validators := make([]*pb.Validator, params.BeaconConfig().SlotsPerEpoch*4)
for i := 0; i < len(validators); i++ {
validators[i] = &pb.Validator{
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
}
}
tests := []struct {
voted []byte
balanceAfterCrosslinkRewards []uint64
}{
{[]byte{0x0}, []uint64{
32 * 1e9, 32 * 1e9, 32 * 1e9, 32 * 1e9, 32 * 1e9, 32 * 1e9, 32 * 1e9, 32 * 1e9}},
{[]byte{0xF}, []uint64{
31585730498, 31585730498, 31585730498, 31585730498,
32416931985, 32416931985, 32416931985, 32416931985}},
{[]byte{0xFF}, []uint64{
32829149760, 32829149760, 32829149760, 32829149760,
32829149760, 32829149760, 32829149760, 32829149760}},
}
for _, tt := range tests {
validatorBalances := make([]uint64, params.BeaconConfig().SlotsPerEpoch*4)
for i := 0; i < len(validatorBalances); i++ {
validatorBalances[i] = params.BeaconConfig().MaxDepositAmount
}
attestation := []*pb.PendingAttestation{
{Data: &pb.AttestationData{Shard: 1, Slot: 0},
AggregationBitfield: tt.voted,
InclusionSlot: 0},
}
state := &pb.BeaconState{
ValidatorRegistry: validators,
ValidatorBalances: validatorBalances,
LatestAttestations: attestation,
}
state, err := Crosslinks(
state,
attestation,
nil)
if err != nil {
t.Fatalf("Could not apply Crosslinks rewards: %v", err)
}
if !reflect.DeepEqual(state.ValidatorBalances, validatorBalances) {
t.Errorf("CrosslinksRewardsPenalties(%v) = %v, wanted: %v",
tt.voted, state.ValidatorBalances, validatorBalances)
}
}
}

View File

@@ -10,6 +10,7 @@ go_library(
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks",
visibility = ["//beacon-chain:__subpackages__"],
deps = [
"//beacon-chain/cache:go_default_library",
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/core/state/stateutils:go_default_library",
"//beacon-chain/core/validators:go_default_library",
@@ -17,13 +18,14 @@ go_library(
"//proto/beacon/p2p/v1:go_default_library",
"//shared/bls:go_default_library",
"//shared/bytesutil:go_default_library",
"//shared/forkutil:go_default_library",
"//shared/hashutil:go_default_library",
"//shared/params:go_default_library",
"//shared/sliceutil:go_default_library",
"//shared/trieutil:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_ethereum_go_ethereum//core/types:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
],
)
@@ -40,10 +42,10 @@ go_test(
deps = [
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/core/state:go_default_library",
"//beacon-chain/core/state/stateutils:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//shared/bls:go_default_library",
"//shared/featureconfig:go_default_library",
"//shared/forkutil:go_default_library",
"//shared/hashutil:go_default_library",
"//shared/params:go_default_library",
"//shared/testutil:go_default_library",
@@ -51,8 +53,9 @@ go_test(
"@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_ethereum_go_ethereum//core/types:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
"@in_gopkg_d4l3k_messagediff_v1//:go_default_library",
],
)

View File

@@ -6,9 +6,9 @@ package blocks
import (
"fmt"
"github.com/prysmaticlabs/go-ssz"
"github.com/prysmaticlabs/prysm/beacon-chain/utils"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/hashutil"
"github.com/prysmaticlabs/prysm/shared/params"
)
@@ -17,64 +17,49 @@ var clock utils.Clock = &utils.RealClock{}
// NewGenesisBlock returns the canonical, genesis block for the beacon chain protocol.
func NewGenesisBlock(stateRoot []byte) *pb.BeaconBlock {
block := &pb.BeaconBlock{
Slot: params.BeaconConfig().GenesisSlot,
ParentRootHash32: params.BeaconConfig().ZeroHash[:],
StateRootHash32: stateRoot,
RandaoReveal: params.BeaconConfig().ZeroHash[:],
Signature: params.BeaconConfig().EmptySignature[:],
Eth1Data: &pb.Eth1Data{
DepositRootHash32: params.BeaconConfig().ZeroHash[:],
BlockHash32: params.BeaconConfig().ZeroHash[:],
},
Slot: 0,
ParentRoot: params.BeaconConfig().ZeroHash[:],
StateRoot: stateRoot,
Signature: params.BeaconConfig().EmptySignature[:],
Body: &pb.BeaconBlockBody{
RandaoReveal: params.BeaconConfig().ZeroHash[:],
ProposerSlashings: []*pb.ProposerSlashing{},
AttesterSlashings: []*pb.AttesterSlashing{},
Attestations: []*pb.Attestation{},
Deposits: []*pb.Deposit{},
VoluntaryExits: []*pb.VoluntaryExit{},
Eth1Data: &pb.Eth1Data{
DepositRoot: params.BeaconConfig().ZeroHash[:],
BlockHash: params.BeaconConfig().ZeroHash[:],
},
},
}
return block
}
// BlockRoot returns the block root stored in the BeaconState for a given slot.
// It returns an error if the requested block root is not within the BeaconState.
// Spec pseudocode definition:
// def get_block_root(state: BeaconState, slot: int) -> Hash32:
// """
// returns the block root at a recent ``slot``.
// """
// assert state.slot <= slot + LATEST_BLOCK_ROOTS_LENGTH
// assert slot < state.slot
// return state.latest_block_roots[slot % LATEST_BLOCK_ROOTS_LENGTH]
func BlockRoot(state *pb.BeaconState, slot uint64) ([]byte, error) {
earliestSlot := state.Slot - params.BeaconConfig().LatestBlockRootsLength
if slot < earliestSlot || slot >= state.Slot {
if earliestSlot < params.BeaconConfig().GenesisSlot {
earliestSlot = params.BeaconConfig().GenesisSlot
}
return []byte{}, fmt.Errorf("slot %d is not within expected range of %d to %d",
slot-params.BeaconConfig().GenesisSlot,
earliestSlot-params.BeaconConfig().GenesisSlot,
state.Slot-params.BeaconConfig().GenesisSlot,
)
// BlockFromHeader manufactures a block from its header. It contains all its fields,
// expect for the block body.
func BlockFromHeader(header *pb.BeaconBlockHeader) *pb.BeaconBlock {
return &pb.BeaconBlock{
StateRoot: header.StateRoot,
Slot: header.Slot,
Signature: header.Signature,
ParentRoot: header.ParentRoot,
}
return state.LatestBlockRootHash32S[slot%params.BeaconConfig().LatestBlockRootsLength], nil
}
// ProcessBlockRoots processes the previous block root into the state, by appending it
// to the most recent block roots.
// Spec:
// Let previous_block_root be the tree_hash_root of the previous beacon block processed in the chain.
// Set state.latest_block_roots[(state.slot - 1) % LATEST_BLOCK_ROOTS_LENGTH] = previous_block_root.
// If state.slot % LATEST_BLOCK_ROOTS_LENGTH == 0 append merkle_root(state.latest_block_roots) to state.batched_block_roots.
func ProcessBlockRoots(state *pb.BeaconState, parentRoot [32]byte) *pb.BeaconState {
state.LatestBlockRootHash32S[(state.Slot-1)%params.BeaconConfig().LatestBlockRootsLength] = parentRoot[:]
if state.Slot%params.BeaconConfig().LatestBlockRootsLength == 0 {
merkleRoot := hashutil.MerkleRoot(state.LatestBlockRootHash32S)
state.BatchedBlockRootHash32S = append(state.BatchedBlockRootHash32S, merkleRoot)
// HeaderFromBlock extracts the block header from a block.
func HeaderFromBlock(block *pb.BeaconBlock) (*pb.BeaconBlockHeader, error) {
header := &pb.BeaconBlockHeader{
Slot: block.Slot,
ParentRoot: block.ParentRoot,
Signature: block.Signature,
StateRoot: block.StateRoot,
}
return state
root, err := ssz.HashTreeRoot(block.Body)
if err != nil {
return nil, fmt.Errorf("could not tree hash block body %v", err)
}
header.BodyRoot = root[:]
return header, nil
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -2,13 +2,12 @@ package blocks
import (
"bytes"
"fmt"
"reflect"
"testing"
"github.com/gogo/protobuf/proto"
"github.com/prysmaticlabs/go-ssz"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/hashutil"
"github.com/prysmaticlabs/prysm/shared/params"
)
@@ -16,7 +15,7 @@ func TestGenesisBlock_InitializedCorrectly(t *testing.T) {
stateHash := []byte{0}
b1 := NewGenesisBlock(stateHash)
if b1.ParentRootHash32 == nil {
if b1.ParentRoot == nil {
t.Error("genesis block missing ParentHash field")
}
@@ -24,148 +23,79 @@ func TestGenesisBlock_InitializedCorrectly(t *testing.T) {
t.Errorf("genesis block should have 0 attestations")
}
if !bytes.Equal(b1.RandaoReveal, params.BeaconConfig().ZeroHash[:]) {
if !bytes.Equal(b1.Body.RandaoReveal, params.BeaconConfig().ZeroHash[:]) {
t.Error("genesis block missing RandaoReveal field")
}
if !bytes.Equal(b1.StateRootHash32, stateHash) {
if !bytes.Equal(b1.StateRoot, stateHash) {
t.Error("genesis block StateRootHash32 isn't initialized correctly")
}
expectedEth1 := &pb.Eth1Data{
DepositRootHash32: params.BeaconConfig().ZeroHash[:],
BlockHash32: params.BeaconConfig().ZeroHash[:],
DepositRoot: params.BeaconConfig().ZeroHash[:],
BlockHash: params.BeaconConfig().ZeroHash[:],
}
if !proto.Equal(b1.Eth1Data, expectedEth1) {
if !proto.Equal(b1.Body.Eth1Data, expectedEth1) {
t.Error("genesis block Eth1Data isn't initialized correctly")
}
}
func TestBlockRootAtSlot_AccurateBlockRoot(t *testing.T) {
if params.BeaconConfig().SlotsPerEpoch != 64 {
t.Errorf("slotsPerEpoch should be 64 for these tests to pass")
}
var blockRoots [][]byte
for i := uint64(0); i < params.BeaconConfig().LatestBlockRootsLength; i++ {
blockRoots = append(blockRoots, []byte{byte(i)})
}
state := &pb.BeaconState{
LatestBlockRootHash32S: blockRoots,
func TestHeaderFromBlock(t *testing.T) {
dummyBody := &pb.BeaconBlockBody{
RandaoReveal: []byte("Reveal"),
}
tests := []struct {
slot uint64
stateSlot uint64
expectedRoot []byte
}{
{
slot: 0,
stateSlot: 1,
expectedRoot: []byte{0},
},
{
slot: 2,
stateSlot: 5,
expectedRoot: []byte{2},
},
{
slot: 64,
stateSlot: 128,
expectedRoot: []byte{64},
}, {
slot: 2999,
stateSlot: 3000,
expectedRoot: []byte{183},
}, {
slot: 2873,
stateSlot: 3000,
expectedRoot: []byte{57},
},
dummyBlock := &pb.BeaconBlock{
Slot: 10,
Signature: []byte{'S'},
ParentRoot: []byte("Parent"),
StateRoot: []byte("State"),
Body: dummyBody,
}
for _, tt := range tests {
state.Slot = tt.stateSlot + params.BeaconConfig().GenesisSlot
wantedSlot := tt.slot + params.BeaconConfig().GenesisSlot
result, err := BlockRoot(state, wantedSlot)
if err != nil {
t.Errorf("failed to get block root at slot %d: %v", wantedSlot, err)
}
if !bytes.Equal(result, tt.expectedRoot) {
t.Errorf(
"result block root was an unexpected value. Wanted %d, got %d",
tt.expectedRoot,
result,
)
}
header, err := HeaderFromBlock(dummyBlock)
if err != nil {
t.Fatal(err)
}
expectedHeader := &pb.BeaconBlockHeader{
Slot: dummyBlock.Slot,
Signature: dummyBlock.Signature,
ParentRoot: dummyBlock.ParentRoot,
StateRoot: dummyBlock.StateRoot,
}
bodyRoot, err := ssz.HashTreeRoot(dummyBody)
if err != nil {
t.Fatal(err)
}
expectedHeader.BodyRoot = bodyRoot[:]
if !proto.Equal(expectedHeader, header) {
t.Errorf("Expected Header not Equal to Retrieved Header. Expected %v , Got %v",
proto.MarshalTextString(expectedHeader), proto.MarshalTextString(header))
}
}
func TestBlockRootAtSlot_OutOfBounds(t *testing.T) {
if params.BeaconConfig().SlotsPerEpoch != 64 {
t.Errorf("slotsPerEpoch should be 64 for these tests to pass")
func TestBlockFromHeader(t *testing.T) {
dummyHeader := &pb.BeaconBlockHeader{
Slot: 10,
Signature: []byte{'S'},
ParentRoot: []byte("Parent"),
StateRoot: []byte("State"),
}
var blockRoots [][]byte
block := BlockFromHeader(dummyHeader)
for i := uint64(0); i < params.BeaconConfig().LatestBlockRootsLength; i++ {
blockRoots = append(blockRoots, []byte{byte(i)})
}
state := &pb.BeaconState{
LatestBlockRootHash32S: blockRoots,
expectedBlock := &pb.BeaconBlock{
Slot: dummyHeader.Slot,
Signature: dummyHeader.Signature,
ParentRoot: dummyHeader.ParentRoot,
StateRoot: dummyHeader.StateRoot,
}
tests := []struct {
slot uint64
stateSlot uint64
expectedErr string
}{
{
slot: params.BeaconConfig().GenesisSlot + 1000,
stateSlot: params.BeaconConfig().GenesisSlot + 500,
expectedErr: fmt.Sprintf("slot %d is not within expected range of %d to %d",
1000,
0,
500),
},
{
slot: params.BeaconConfig().GenesisSlot + 129,
stateSlot: params.BeaconConfig().GenesisSlot + 400,
expectedErr: "slot 129 is not within expected range of 272 to 399",
},
}
for _, tt := range tests {
state.Slot = tt.stateSlot
_, err := BlockRoot(state, tt.slot)
if err != nil && err.Error() != tt.expectedErr {
t.Errorf("Expected error \"%s\" got \"%v\"", tt.expectedErr, err)
}
}
}
func TestProcessBlockRoots_AccurateMerkleTree(t *testing.T) {
state := &pb.BeaconState{}
state.LatestBlockRootHash32S = make([][]byte, params.BeaconConfig().LatestBlockRootsLength)
state.Slot = params.BeaconConfig().LatestBlockRootsLength + 1
testRoot := [32]byte{'a'}
newState := ProcessBlockRoots(state, testRoot)
if !bytes.Equal(newState.LatestBlockRootHash32S[0], testRoot[:]) {
t.Fatalf("Latest Block root hash not saved."+
" Supposed to get %#x , but got %#x", testRoot, newState.LatestBlockRootHash32S[0])
}
newState.Slot = newState.Slot - 1
newState = ProcessBlockRoots(newState, testRoot)
expectedHashes := make([][]byte, params.BeaconConfig().LatestBlockRootsLength)
expectedHashes[0] = testRoot[:]
expectedHashes[params.BeaconConfig().LatestBlockRootsLength-1] = testRoot[:]
expectedRoot := hashutil.MerkleRoot(expectedHashes)
if !bytes.Equal(newState.BatchedBlockRootHash32S[0], expectedRoot[:]) {
t.Errorf("saved merkle root is not equal to expected merkle root"+
"\n expected %#x but got %#x", expectedRoot, newState.BatchedBlockRootHash32S[0])
if !proto.Equal(expectedBlock, block) {
t.Errorf("Expected block not equal to retrieved block. Expected %v , Got %v",
proto.MarshalTextString(expectedBlock), proto.MarshalTextString(block))
}
}

View File

@@ -0,0 +1,48 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
testonly = True,
srcs = [
"attestation_test.yaml.go",
"block_operations.yaml.go",
"blocks_mainnet.yaml.go",
"blocks_minimal.yaml.go",
],
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks/spectest",
visibility = ["//beacon-chain:__subpackages__"],
deps = ["//proto/beacon/p2p/v1:go_default_library"],
)
go_test(
name = "go_default_test",
size = "medium",
srcs = [
"attestation_test.go",
"attester_slashing_test.go",
"block_header_test.go",
"block_processing_test.go",
"deposit_test.go",
"proposer_slashing_test.go",
"transfer_test.go",
"voluntary_exit_test.go",
],
data = glob(["*.yaml"]) + [
"@eth2_spec_tests//:test_data",
],
embed = [":go_default_library"],
shard_count = 4,
tags = ["spectest"],
deps = [
"//beacon-chain/core/blocks:go_default_library",
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/core/state:go_default_library",
"//beacon-chain/core/state/stateutils:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//shared/params/spectest:go_default_library",
"@com_github_ghodss_yaml//:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"@in_gopkg_d4l3k_messagediff_v1//:go_default_library",
"@io_bazel_rules_go//go/tools/bazel:go_default_library",
],
)

View File

@@ -0,0 +1,82 @@
package spectest
import (
"io/ioutil"
"reflect"
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
"github.com/ghodss/yaml"
"github.com/gogo/protobuf/proto"
"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"
"github.com/prysmaticlabs/prysm/shared/params/spectest"
"gopkg.in/d4l3k/messagediff.v1"
)
func runAttestationTest(t *testing.T, filename string) {
filepath, err := bazel.Runfile("/eth2_spec_tests/tests/operations/attestation/" + filename)
if err != nil {
t.Fatal(err)
}
file, err := ioutil.ReadFile(filepath)
if err != nil {
t.Fatalf("Failed to read file: %v", err)
}
test := &AttestationTest{}
if err := yaml.Unmarshal(file, test); err != nil {
t.Fatalf("Failed to unmarshal: %v", err)
}
if err := spectest.SetConfig(test.Config); err != nil {
t.Fatal(err)
}
for _, tt := range test.TestCases {
t.Run(tt.Description, func(t *testing.T) {
helpers.ClearAllCaches()
body := &pb.BeaconBlockBody{
Attestations: []*pb.Attestation{
tt.Attestation,
},
}
post, err := blocks.ProcessAttestations(tt.Pre, body, true /*verify sig*/)
if !reflect.ValueOf(tt.Post).IsValid() {
// Note: This doesn't test anything worthwhile. It essentially tests
// that *any* error has occurred, not any specific error.
if err == nil {
t.Fatal("did not fail when expected")
}
return
}
// Note: This doesn't test anything worthwhile. It essentially tests
// that *any* error has occurred, not any specific error.
if tt.Post == nil {
if err == nil {
t.Fatal("Did not fail when expected")
}
t.Logf("Expected failure; failure reason = %v", err)
return
} else if err != nil {
t.Fatal(err)
}
if !proto.Equal(post, tt.Post) {
diff, _ := messagediff.PrettyDiff(post, tt.Post)
t.Log(diff)
t.Fatal("Post state does not match expected")
}
})
}
}
func TestAttestationMinimal(t *testing.T) {
runAttestationTest(t, "attestation_minimal.yaml")
}
func TestAttestationMainnet(t *testing.T) {
runAttestationTest(t, "attestation_mainnet.yaml")
}

View File

@@ -0,0 +1,23 @@
// Code generated by yaml_to_go. DO NOT EDIT.
// source: attestation_minimal.yaml
package spectest
import pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
type AttestationTest struct {
Title string `json:"title"`
Summary string `json:"summary"`
ForksTimeline string `json:"forks_timeline"`
Forks []string `json:"forks"`
Config string `json:"config"`
Runner string `json:"runner"`
Handler string `json:"handler"`
TestCases []struct {
Description string `json:"description"`
Pre *pb.BeaconState `json:"pre"`
Attestation *pb.Attestation `json:"attestation"`
Post *pb.BeaconState `json:"post"`
BlsSetting uint64 `json:"bls_setting,omitempty"`
} `json:"test_cases"`
}

View File

@@ -0,0 +1,76 @@
package spectest
import (
"io/ioutil"
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
"github.com/ghodss/yaml"
"github.com/gogo/protobuf/proto"
"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"
"github.com/prysmaticlabs/prysm/shared/params/spectest"
"gopkg.in/d4l3k/messagediff.v1"
)
func runAttesterSlashingTest(t *testing.T, filename string) {
file, err := ioutil.ReadFile(filename)
if err != nil {
t.Fatalf("Could not load file %v", err)
}
test := &BlockOperationTest{}
if err := yaml.Unmarshal(file, test); err != nil {
t.Fatalf("Failed to Unmarshal: %v", err)
}
if err := spectest.SetConfig(test.Config); err != nil {
t.Fatal(err)
}
for _, tt := range test.TestCases {
t.Run(tt.Description, func(t *testing.T) {
helpers.ClearAllCaches()
body := &pb.BeaconBlockBody{AttesterSlashings: []*pb.AttesterSlashing{tt.AttesterSlashing}}
postState, err := blocks.ProcessAttesterSlashings(tt.Pre, body, true)
// Note: This doesn't test anything worthwhile. It essentially tests
// that *any* error has occurred, not any specific error.
if tt.Post == nil {
if err == nil {
t.Fatal("Did not fail when expected")
}
return
}
if err != nil {
t.Fatal(err)
}
if !proto.Equal(postState, tt.Post) {
diff, _ := messagediff.PrettyDiff(postState, tt.Post)
t.Log(diff)
t.Fatal("Post state does not match expected")
}
})
}
}
var attesterSlashingPrefix = "eth2_spec_tests/tests/operations/attester_slashing/"
func TestAttesterSlashingMinimal(t *testing.T) {
filepath, err := bazel.Runfile(attesterSlashingPrefix + "attester_slashing_minimal.yaml")
if err != nil {
t.Fatal(err)
}
runAttesterSlashingTest(t, filepath)
}
func TestAttesterSlashingMainnet(t *testing.T) {
filepath, err := bazel.Runfile(attesterSlashingPrefix + "attester_slashing_mainnet.yaml")
if err != nil {
t.Fatal(err)
}
runAttesterSlashingTest(t, filepath)
}

View File

@@ -0,0 +1,78 @@
package spectest
import (
"io/ioutil"
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
"github.com/ghodss/yaml"
"github.com/gogo/protobuf/proto"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/shared/params/spectest"
"gopkg.in/d4l3k/messagediff.v1"
)
// Block header test is actually a full block processing test. Not sure why it
// was named "block_header". The note in the test format readme says "Note that
// block_header is not strictly an operation (and is a full Block), but
// processed in the same manner, and hence included here."
func runBlockHeaderTest(t *testing.T, filename string) {
file, err := ioutil.ReadFile(filename)
if err != nil {
t.Fatalf("Failed to read file: %v", err)
}
test := &BlockOperationTest{}
if err := yaml.Unmarshal(file, test); err != nil {
t.Fatalf("Failed to unmarshal: %v", err)
}
if err := spectest.SetConfig(test.Config); err != nil {
t.Fatal(err)
}
for _, tt := range test.TestCases {
t.Run(tt.Description, func(t *testing.T) {
helpers.ClearAllCaches()
post, err := blocks.ProcessBlockHeader(tt.Pre, tt.Block, true)
if tt.Post == nil {
// Note: This doesn't test anything worthwhile. It essentially tests
// that *any* error has occurred, not any specific error.
if err == nil {
t.Fatal("did not fail when expected")
}
return
}
if err != nil {
t.Fatal(err)
}
if !proto.Equal(post, tt.Post) {
diff, _ := messagediff.PrettyDiff(post, tt.Post)
t.Log(diff)
t.Fatal("Post state does not match expected")
}
})
}
}
var blkHeaderPrefix = "eth2_spec_tests/tests/operations/block_header/"
func TestBlockHeaderMinimal(t *testing.T) {
filepath, err := bazel.Runfile(blkHeaderPrefix + "block_header_minimal.yaml")
if err != nil {
t.Fatal(err)
}
runBlockHeaderTest(t, filepath)
}
func TestBlockHeaderMainnet(t *testing.T) {
filepath, err := bazel.Runfile(blkHeaderPrefix + "block_header_mainnet.yaml")
if err != nil {
t.Fatal(err)
}
runBlockHeaderTest(t, filepath)
}

View File

@@ -0,0 +1,28 @@
// Code generated by yaml_to_go. DO NOT EDIT.
// source: voluntary_exit_minimal.yaml
package spectest
import pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
type BlockOperationTest struct {
Title string `json:"title"`
Summary string `json:"summary"`
ForksTimeline string `json:"forks_timeline"`
Forks []string `json:"forks"`
Config string `json:"config"`
Runner string `json:"runner"`
Handler string `json:"handler"`
TestCases []struct {
BlsSetting uint64 `json:"bls_setting,omitempty"`
Description string `json:"description"`
Pre *pb.BeaconState `json:"pre"`
VoluntaryExit *pb.VoluntaryExit `json:"voluntary_exit"`
ProposerSlashing *pb.ProposerSlashing `json:"proposer_slashing"`
AttesterSlashing *pb.AttesterSlashing `json:"attester_slashing"`
Deposit *pb.Deposit `json:"deposit"`
Transfer *pb.Transfer `json:"transfer"`
Block *pb.BeaconBlock `json:"block"`
Post *pb.BeaconState `json:"post"`
} `json:"test_cases"`
}

View File

@@ -0,0 +1,80 @@
package spectest
import (
"context"
"io/ioutil"
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
"github.com/ghodss/yaml"
"github.com/gogo/protobuf/proto"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
"github.com/prysmaticlabs/prysm/shared/params/spectest"
"gopkg.in/d4l3k/messagediff.v1"
)
func TestBlockProcessingMinimalYaml(t *testing.T) {
t.Skip("Test will fail with mainnet protos")
runBlockProcessingTest(t, "sanity_blocks_minimal.yaml")
}
func TestBlockProcessingMainnetYaml(t *testing.T) {
runBlockProcessingTest(t, "sanity_blocks_mainnet.yaml")
}
func runBlockProcessingTest(t *testing.T, filename string) {
filepath, err := bazel.Runfile("/eth2_spec_tests/tests/sanity/blocks/" + filename)
if err != nil {
t.Fatal(err)
}
file, err := ioutil.ReadFile(filepath)
if err != nil {
t.Fatalf("Could not load file %v", err)
}
s := &BlocksMainnet{}
if err := yaml.Unmarshal(file, s); err != nil {
t.Fatalf("Failed to Unmarshal: %v", err)
}
if err := spectest.SetConfig(s.Config); err != nil {
t.Fatalf("Could not set config: %v", err)
}
for _, tt := range s.TestCases {
t.Run(tt.Description, func(t *testing.T) {
ctx := context.Background()
helpers.ClearAllCaches()
blocks.ClearEth1DataVoteCache()
stateConfig := &state.TransitionConfig{
VerifySignatures: true,
VerifyStateRoot: true,
}
s := tt.Pre
for _, b := range tt.Blocks {
tt.Pre, err = state.ExecuteStateTransition(ctx, tt.Pre, b, stateConfig)
if tt.Post == nil {
if err == nil {
t.Fatal("Transition did not fail despite being invalid")
}
continue
}
if err != nil {
t.Fatalf("Transition failed with block at slot %d: %v", b.Slot, err)
}
}
if tt.Post != nil {
if !proto.Equal(s, tt.Post) {
diff, _ := messagediff.PrettyDiff(s, tt.Post)
t.Log(diff)
t.Fatal("Post state does not match expected")
}
}
})
}
}

View File

@@ -0,0 +1,22 @@
// Code generated by yaml_to_go. DO NOT EDIT.
// source: sanity_blocks_mainnet.yaml
package spectest
import pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
type BlocksMainnet struct {
Title string `json:"title"`
Summary string `json:"summary"`
ForksTimeline string `json:"forks_timeline"`
Forks []string `json:"forks"`
Config string `json:"config"`
Runner string `json:"runner"`
Handler string `json:"handler"`
TestCases []struct {
Description string `json:"description"`
Pre *pb.BeaconState `json:"pre"`
Blocks []*pb.BeaconBlock `json:"blocks"`
Post *pb.BeaconState `json:"post"`
} `json:"test_cases"`
}

View File

@@ -0,0 +1,22 @@
// Code generated by yaml_to_go. DO NOT EDIT.
// source: sanity_blocks_minimal.yaml
package spectest
import pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
type BlocksMinimal struct {
Title string `json:"title"`
Summary string `json:"summary"`
ForksTimeline string `json:"forks_timeline"`
Forks []string `json:"forks"`
Config string `json:"config"`
Runner string `json:"runner"`
Handler string `json:"handler"`
TestCases []struct {
Description string `json:"description"`
Pre *pb.BeaconState `json:"pre"`
Blocks []*pb.BeaconBlock `json:"blocks"`
Post *pb.BeaconState `json:"post"`
} `json:"test_cases"`
}

View File

@@ -0,0 +1,76 @@
package spectest
import (
"io/ioutil"
"reflect"
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
"github.com/ghodss/yaml"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/core/state/stateutils"
"github.com/prysmaticlabs/prysm/shared/params/spectest"
)
func runDepositTest(t *testing.T, filename string) {
file, err := ioutil.ReadFile(filename)
if err != nil {
t.Fatalf("Could not load file %v", err)
}
test := &BlockOperationTest{}
if err := yaml.Unmarshal(file, test); err != nil {
t.Fatalf("Failed to Unmarshal: %v", err)
}
if err := spectest.SetConfig(test.Config); err != nil {
t.Fatal(err)
}
for _, tt := range test.TestCases {
helpers.ClearAllCaches()
t.Run(tt.Description, func(t *testing.T) {
if tt.Description == "invalid_sig_new_deposit" {
// TODO(#2857): uncompressed signature format is not supported
t.Skip("Uncompressed BLS signature format is not supported")
}
valMap := stateutils.ValidatorIndexMap(tt.Pre)
post, err := blocks.ProcessDeposit(tt.Pre, tt.Deposit, valMap, true, true)
// Note: This doesn't test anything worthwhile. It essentially tests
// that *any* error has occurred, not any specific error.
if tt.Post == nil {
if err == nil {
t.Fatal("Did not fail when expected")
}
return
}
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(post, tt.Post) {
t.Error("Post state does not match expected")
}
})
}
}
var depositPrefix = "eth2_spec_tests/tests/operations/deposit/"
func TestDepositMinimalYaml(t *testing.T) {
filepath, err := bazel.Runfile(depositPrefix + "deposit_minimal.yaml")
if err != nil {
t.Fatal(err)
}
runDepositTest(t, filepath)
}
func TestDepositMainnetYaml(t *testing.T) {
filepath, err := bazel.Runfile(depositPrefix + "deposit_mainnet.yaml")
if err != nil {
t.Fatal(err)
}
runDepositTest(t, filepath)
}

View File

@@ -0,0 +1,76 @@
package spectest
import (
"io/ioutil"
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
"github.com/ghodss/yaml"
"github.com/gogo/protobuf/proto"
"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"
"github.com/prysmaticlabs/prysm/shared/params/spectest"
"gopkg.in/d4l3k/messagediff.v1"
)
func runProposerSlashingTest(t *testing.T, filename string) {
file, err := ioutil.ReadFile(filename)
if err != nil {
t.Fatalf("Could not load file %v", err)
}
test := &BlockOperationTest{}
if err := yaml.Unmarshal(file, test); err != nil {
t.Fatalf("Failed to Unmarshal: %v", err)
}
if err := spectest.SetConfig(test.Config); err != nil {
t.Fatal(err)
}
for _, tt := range test.TestCases {
t.Run(tt.Description, func(t *testing.T) {
helpers.ClearAllCaches()
body := &pb.BeaconBlockBody{ProposerSlashings: []*pb.ProposerSlashing{tt.ProposerSlashing}}
postState, err := blocks.ProcessProposerSlashings(tt.Pre, body, true)
// Note: This doesn't test anything worthwhile. It essentially tests
// that *any* error has occurred, not any specific error.
if tt.Post == nil {
if err == nil {
t.Fatal("Did not fail when expected")
}
return
}
if err != nil {
t.Fatal(err)
}
if !proto.Equal(postState, tt.Post) {
diff, _ := messagediff.PrettyDiff(postState, tt.Post)
t.Log(diff)
t.Fatal("Post state does not match expected")
}
})
}
}
var proposerSlashingPrefix = "eth2_spec_tests/tests/operations/proposer_slashing/"
func TestProposerSlashingMinimal(t *testing.T) {
filepath, err := bazel.Runfile(proposerSlashingPrefix + "proposer_slashing_minimal.yaml")
if err != nil {
t.Fatal(err)
}
runProposerSlashingTest(t, filepath)
}
func TestProposerSlashingMainnet(t *testing.T) {
filepath, err := bazel.Runfile(proposerSlashingPrefix + "proposer_slashing_mainnet.yaml")
if err != nil {
t.Fatal(err)
}
runProposerSlashingTest(t, filepath)
}

View File

@@ -0,0 +1,78 @@
package spectest
import (
"io/ioutil"
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
"github.com/ghodss/yaml"
"github.com/gogo/protobuf/proto"
"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"
"github.com/prysmaticlabs/prysm/shared/params/spectest"
"gopkg.in/d4l3k/messagediff.v1"
)
func runTransferTest(t *testing.T, filename string) {
file, err := ioutil.ReadFile(filename)
if err != nil {
t.Fatalf("Could not load file %v", err)
}
test := &BlockOperationTest{}
if err := yaml.Unmarshal(file, test); err != nil {
t.Fatalf("Failed to Unmarshal: %v", err)
}
if err := spectest.SetConfig(test.Config); err != nil {
t.Fatal(err)
}
for _, tt := range test.TestCases {
t.Run(tt.Description, func(t *testing.T) {
helpers.ClearAllCaches()
body := &pb.BeaconBlockBody{Transfers: []*pb.Transfer{tt.Transfer}}
postState, err := blocks.ProcessTransfers(tt.Pre, body, true)
// Note: This doesn't test anything worthwhile. It essentially tests
// that *any* error has occurred, not any specific error.
if tt.Post == nil {
if err == nil {
t.Fatal("Did not fail when expected")
}
return
}
if err != nil {
t.Fatal(err)
}
if !proto.Equal(postState, tt.Post) {
diff, _ := messagediff.PrettyDiff(postState, tt.Post)
t.Log(diff)
t.Fatal("Post state does not match expected")
}
})
}
}
var transferPrefix = "eth2_spec_tests/tests/operations/transfer/"
func TestTransferMinimal(t *testing.T) {
t.Skip("Transfer tests are disabled. See https://github.com/ethereum/eth2.0-specs/pull/1238#issuecomment-507054595")
filepath, err := bazel.Runfile(transferPrefix + "transfer_minimal.yaml")
if err != nil {
t.Fatal(err)
}
runTransferTest(t, filepath)
}
func TestTransferMainnet(t *testing.T) {
t.Skip("Transfer tests are disabled. See https://github.com/ethereum/eth2.0-specs/pull/1238#issuecomment-507054595")
filepath, err := bazel.Runfile(transferPrefix + "transfer_mainnet.yaml")
if err != nil {
t.Fatal(err)
}
runTransferTest(t, filepath)
}

View File

@@ -0,0 +1,76 @@
package spectest
import (
"io/ioutil"
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
"github.com/ghodss/yaml"
"github.com/gogo/protobuf/proto"
"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"
"github.com/prysmaticlabs/prysm/shared/params/spectest"
"gopkg.in/d4l3k/messagediff.v1"
)
func runVoluntaryExitTest(t *testing.T, filename string) {
file, err := ioutil.ReadFile(filename)
if err != nil {
t.Fatalf("Could not load file %v", err)
}
test := &BlockOperationTest{}
if err := yaml.Unmarshal(file, test); err != nil {
t.Fatalf("Failed to Unmarshal: %v", err)
}
if err := spectest.SetConfig(test.Config); err != nil {
t.Fatal(err)
}
for _, tt := range test.TestCases {
t.Run(tt.Description, func(t *testing.T) {
helpers.ClearAllCaches()
body := &pb.BeaconBlockBody{VoluntaryExits: []*pb.VoluntaryExit{tt.VoluntaryExit}}
postState, err := blocks.ProcessVoluntaryExits(tt.Pre, body, true)
// Note: This doesn't test anything worthwhile. It essentially tests
// that *any* error has occurred, not any specific error.
if tt.Post == nil {
if err == nil {
t.Fatal("Did not fail when expected")
}
return
}
if err != nil {
t.Fatal(err)
}
if !proto.Equal(postState, tt.Post) {
diff, _ := messagediff.PrettyDiff(postState, tt.Post)
t.Log(diff)
t.Fatal("Post state does not match expected")
}
})
}
}
var exitPrefix = "eth2_spec_tests/tests/operations/voluntary_exit/"
func TestVoluntaryExitMinimal(t *testing.T) {
filepath, err := bazel.Runfile(exitPrefix + "voluntary_exit_mainnet.yaml")
if err != nil {
t.Fatal(err)
}
runVoluntaryExitTest(t, filepath)
}
func TestVoluntaryExitMainnet(t *testing.T) {
filepath, err := bazel.Runfile(exitPrefix + "voluntary_exit_mainnet.yaml")
if err != nil {
t.Fatal(err)
}
runVoluntaryExitTest(t, filepath)
}

View File

@@ -1,6 +1,3 @@
// Package blocks contains block processing libraries. These libraries
// process and verify block specific messages such as PoW receipt root,
// RANDAO, validator deposits, exits and slashing proofs.
package blocks
import (
@@ -19,12 +16,6 @@ import (
var log = logrus.WithField("prefix", "core/blocks")
// IsValidBlock ensures that the block is compliant with the block processing validity conditions.
// Spec:
// For a beacon chain block, block, to be processed by a node, the following conditions must be met:
// The parent block with root block.parent_root has been processed and accepted.
// The node has processed its state up to slot, block.slot - 1.
// The Ethereum 1.0 block pointed to by the state.processed_pow_receipt_root has been processed and accepted.
// The node's local clock time is greater than or equal to state.genesis_time + block.slot * SECONDS_PER_SLOT.
func IsValidBlock(
ctx context.Context,
state *pb.BeaconState,
@@ -35,13 +26,13 @@ func IsValidBlock(
// Pre-Processing Condition 1:
// Check that the parent Block has been processed and saved.
parentRoot := bytesutil.ToBytes32(block.ParentRootHash32)
parentRoot := bytesutil.ToBytes32(block.ParentRoot)
parentBlock := HasBlock(parentRoot)
if !parentBlock {
return fmt.Errorf("unprocessed parent block as it is not saved in the db: %#x", parentRoot)
}
h := common.BytesToHash(state.LatestEth1Data.BlockHash32)
h := common.BytesToHash(state.Eth1Data.BlockHash)
powBlock, err := GetPOWBlock(ctx, h)
if err != nil {
return fmt.Errorf("unable to retrieve POW chain reference block: %v", err)
@@ -51,14 +42,14 @@ func IsValidBlock(
// The block pointed to by the state in state.processed_pow_receipt_root has
// been processed in the ETH 1.0 chain.
if powBlock == nil {
return fmt.Errorf("proof-of-Work chain reference in state does not exist: %#x", state.LatestEth1Data.BlockHash32)
return fmt.Errorf("proof-of-Work chain reference in state does not exist: %#x", state.Eth1Data.BlockHash)
}
// Pre-Processing Condition 4:
// The node's local time is greater than or equal to
// state.genesis_time + (block.slot-GENESIS_SLOT)* SECONDS_PER_SLOT.
if !IsSlotValid(block.Slot, genesisTime) {
return fmt.Errorf("slot of block is too high: %d", block.Slot-params.BeaconConfig().GenesisSlot)
return fmt.Errorf("slot of block is too high: %d", block.Slot)
}
return nil
@@ -66,7 +57,7 @@ func IsValidBlock(
// IsSlotValid compares the slot to the system clock to determine if the block is valid.
func IsSlotValid(slot uint64, genesisTime time.Time) bool {
secondsPerSlot := time.Duration((slot-params.BeaconConfig().GenesisSlot)*params.BeaconConfig().SecondsPerSlot) * time.Second
secondsPerSlot := time.Duration((slot)*params.BeaconConfig().SecondsPerSlot) * time.Second
validTimeThreshold := genesisTime.Add(secondsPerSlot)
now := clock.Now()
isValid := now.After(validTimeThreshold)

View File

@@ -8,7 +8,6 @@ import (
"github.com/ethereum/go-ethereum/common"
gethTypes "github.com/ethereum/go-ethereum/core/types"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/sirupsen/logrus"
)
@@ -43,10 +42,10 @@ func TestIsValidBlock_NoParent(t *testing.T) {
db := &mockDB{}
powClient := &mockPOWClient{}
beaconState.Slot = params.BeaconConfig().GenesisSlot + 3
beaconState.Slot = 3
block := &pb.BeaconBlock{
Slot: params.BeaconConfig().GenesisSlot + 4,
Slot: 4,
}
genesisTime := time.Unix(0, 0)
@@ -67,20 +66,20 @@ func TestIsValidBlock_InvalidSlot(t *testing.T) {
db := &mockDB{}
powClient := &mockPOWClient{}
beaconState.Slot = params.BeaconConfig().GenesisSlot + 3
beaconState.Slot = 3
block := &pb.BeaconBlock{
Slot: params.BeaconConfig().GenesisSlot + 4,
Slot: 4,
}
genesisTime := time.Unix(0, 0)
block.Slot = params.BeaconConfig().GenesisSlot + 3
block.Slot = 3
db.hasBlock = true
beaconState.LatestEth1Data = &pb.Eth1Data{
DepositRootHash32: []byte{2},
BlockHash32: []byte{3},
beaconState.Eth1Data = &pb.Eth1Data{
DepositRoot: []byte{2},
BlockHash: []byte{3},
}
if err := IsValidBlock(ctx, beaconState, block,
db.HasBlock, powClient.BlockByHash, genesisTime); err == nil {
@@ -96,20 +95,20 @@ func TestIsValidBlock_InvalidPoWReference(t *testing.T) {
db := &mockDB{}
powClient := &mockPOWClient{}
beaconState.Slot = params.BeaconConfig().GenesisSlot + 3
beaconState.Slot = 3
block := &pb.BeaconBlock{
Slot: params.BeaconConfig().GenesisSlot + 4,
Slot: 4,
}
genesisTime := time.Unix(0, 0)
db.hasBlock = true
block.Slot = params.BeaconConfig().GenesisSlot + 4
block.Slot = 4
powClient.blockExists = false
beaconState.LatestEth1Data = &pb.Eth1Data{
DepositRootHash32: []byte{2},
BlockHash32: []byte{3},
beaconState.Eth1Data = &pb.Eth1Data{
DepositRoot: []byte{2},
BlockHash: []byte{3},
}
if err := IsValidBlock(ctx, beaconState, block,
@@ -129,15 +128,15 @@ func TestIsValidBlock_InvalidGenesis(t *testing.T) {
powClient := &mockPOWClient{}
powClient.blockExists = false
beaconState.Slot = params.BeaconConfig().GenesisSlot + 3
beaconState.LatestEth1Data = &pb.Eth1Data{
DepositRootHash32: []byte{2},
BlockHash32: []byte{3},
beaconState.Slot = 3
beaconState.Eth1Data = &pb.Eth1Data{
DepositRoot: []byte{2},
BlockHash: []byte{3},
}
genesisTime := time.Unix(0, 0)
block := &pb.BeaconBlock{
Slot: params.BeaconConfig().GenesisSlot + 4,
Slot: 4,
}
invalidTime := time.Now().AddDate(1, 2, 3)
@@ -159,16 +158,16 @@ func TestIsValidBlock_GoodBlock(t *testing.T) {
powClient := &mockPOWClient{}
powClient.blockExists = true
beaconState.Slot = params.BeaconConfig().GenesisSlot + 3
beaconState.LatestEth1Data = &pb.Eth1Data{
DepositRootHash32: []byte{2},
BlockHash32: []byte{3},
beaconState.Slot = 3
beaconState.Eth1Data = &pb.Eth1Data{
DepositRoot: []byte{2},
BlockHash: []byte{3},
}
genesisTime := time.Unix(0, 0)
block := &pb.BeaconBlock{
Slot: params.BeaconConfig().GenesisSlot + 4,
Slot: 4,
}
if err := IsValidBlock(ctx, beaconState, block,

View File

@@ -2,42 +2,31 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"epoch_operations.go",
"epoch_processing.go",
],
srcs = ["epoch_processing.go"],
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch",
visibility = ["//beacon-chain:__subpackages__"],
deps = [
"//beacon-chain/core/blocks:go_default_library",
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/core/validators:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//shared/bytesutil:go_default_library",
"//shared/featureconfig:go_default_library",
"//shared/hashutil:go_default_library",
"//shared/mathutil:go_default_library",
"//shared/params:go_default_library",
"@com_github_prometheus_client_golang//prometheus:go_default_library",
"@com_github_prometheus_client_golang//prometheus/promauto:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
],
)
go_test(
name = "go_default_test",
size = "small",
srcs = [
"epoch_operations_test.go",
"epoch_processing_test.go",
],
srcs = ["epoch_processing_test.go"],
embed = [":go_default_library"],
deps = [
"//beacon-chain/core/helpers:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//shared/featureconfig:go_default_library",
"//shared/hashutil:go_default_library",
"//shared/params:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
],
)

View File

@@ -1,182 +0,0 @@
// Package epoch contains epoch processing libraries. These libraries
// process new balance for the validators, justify and finalize new
// check points, shuffle and reassign validators to different slots and
// shards.
package epoch
import (
"fmt"
"math"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/core/validators"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
b "github.com/prysmaticlabs/prysm/shared/bytesutil"
)
// TotalBalance returns the total balance at stake of the validators
// from the shard committee regardless of validators attested or not.
//
// Spec pseudocode definition:
// def get_total_balance(state: BeaconState, validators: List[ValidatorIndex]) -> Gwei:
// """
// Return the combined effective balance of an array of validators.
// """
// return sum([get_effective_balance(state, i) for i in validators])
func TotalBalance(
state *pb.BeaconState,
activeValidatorIndices []uint64) uint64 {
var totalBalance uint64
for _, index := range activeValidatorIndices {
totalBalance += helpers.EffectiveBalance(state, index)
}
return totalBalance
}
// InclusionSlot returns the slot number of when the validator's
// attestation gets included in the beacon chain.
//
// Spec pseudocode definition:
// Let inclusion_slot(state, index) =
// a.slot_included for the attestation a where index is in
// get_attestation_participants(state, a.data, a.participation_bitfield)
// If multiple attestations are applicable, the attestation with
// lowest `slot_included` is considered.
func InclusionSlot(state *pb.BeaconState, validatorIndex uint64) (uint64, error) {
lowestSlotIncluded := uint64(math.MaxUint64)
for _, attestation := range state.LatestAttestations {
participatedValidators, err := helpers.AttestationParticipants(state, attestation.Data, attestation.AggregationBitfield)
if err != nil {
return 0, fmt.Errorf("could not get attestation participants: %v", err)
}
for _, index := range participatedValidators {
if index == validatorIndex {
if attestation.InclusionSlot < lowestSlotIncluded {
lowestSlotIncluded = attestation.InclusionSlot
}
}
}
}
if lowestSlotIncluded == math.MaxUint64 {
return 0, fmt.Errorf("could not find inclusion slot for validator index %d", validatorIndex)
}
return lowestSlotIncluded, nil
}
// AttestingValidators returns the validators of the winning root.
//
// Spec pseudocode definition:
// Let `attesting_validators(crosslink_committee)` be equal to
// `attesting_validator_indices(crosslink_committee, winning_root(crosslink_committee))` for convenience
func AttestingValidators(
state *pb.BeaconState,
shard uint64,
currentEpochAttestations []*pb.PendingAttestation,
prevEpochAttestations []*pb.PendingAttestation) ([]uint64, error) {
root, err := winningRoot(
state,
shard,
currentEpochAttestations,
prevEpochAttestations)
if err != nil {
return nil, fmt.Errorf("could not get winning root: %v", err)
}
indices, err := validators.AttestingValidatorIndices(
state,
shard,
root,
currentEpochAttestations,
prevEpochAttestations)
if err != nil {
return nil, fmt.Errorf("could not get attesting validator indices: %v", err)
}
return indices, nil
}
// TotalAttestingBalance returns the total balance at stake of the validators
// attested to the winning root.
//
// Spec pseudocode definition:
// Let total_balance(crosslink_committee) =
// sum([get_effective_balance(state, i) for i in crosslink_committee.committee])
func TotalAttestingBalance(
state *pb.BeaconState,
shard uint64,
currentEpochAttestations []*pb.PendingAttestation,
prevEpochAttestations []*pb.PendingAttestation) (uint64, error) {
var totalBalance uint64
attestedValidatorIndices, err := AttestingValidators(state, shard, currentEpochAttestations, prevEpochAttestations)
if err != nil {
return 0, fmt.Errorf("could not get attesting validator indices: %v", err)
}
for _, index := range attestedValidatorIndices {
totalBalance += helpers.EffectiveBalance(state, index)
}
return totalBalance, nil
}
// SinceFinality calculates and returns how many epoch has it been since
// a finalized slot.
//
// Spec pseudocode definition:
// epochs_since_finality = next_epoch - state.finalized_epoch
func SinceFinality(state *pb.BeaconState) uint64 {
return helpers.NextEpoch(state) - state.FinalizedEpoch
}
// winningRoot returns the shard block root with the most combined validator
// effective balance. The ties broken by favoring lower shard block root values.
//
// Spec pseudocode definition:
// Let winning_root(crosslink_committee) be equal to the value of crosslink_data_root
// such that get_total_balance(state, attesting_validator_indices(crosslink_committee, crosslink_data_root))
// is maximized (ties broken by favoring lexicographically smallest crosslink_data_root).
func winningRoot(
state *pb.BeaconState,
shard uint64,
currentEpochAttestations []*pb.PendingAttestation,
prevEpochAttestations []*pb.PendingAttestation) ([]byte, error) {
var winnerBalance uint64
var winnerRoot []byte
var candidateRoots [][]byte
attestations := append(currentEpochAttestations, prevEpochAttestations...)
for _, attestation := range attestations {
if attestation.Data.Shard == shard {
candidateRoots = append(candidateRoots, attestation.Data.CrosslinkDataRootHash32)
}
}
for _, candidateRoot := range candidateRoots {
indices, err := validators.AttestingValidatorIndices(
state,
shard,
candidateRoot,
currentEpochAttestations,
prevEpochAttestations)
if err != nil {
return nil, fmt.Errorf("could not get attesting validator indices: %v", err)
}
var rootBalance uint64
for _, index := range indices {
rootBalance += helpers.EffectiveBalance(state, index)
}
if rootBalance > winnerBalance ||
(rootBalance == winnerBalance && b.LowerThan(candidateRoot, winnerRoot)) {
winnerBalance = rootBalance
winnerRoot = candidateRoot
}
}
return winnerRoot, nil
}

View File

@@ -1,256 +0,0 @@
package epoch
import (
"bytes"
"fmt"
"reflect"
"strings"
"testing"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/params"
)
func buildState(slot uint64, validatorCount uint64) *pb.BeaconState {
validators := make([]*pb.Validator, validatorCount)
for i := 0; i < len(validators); i++ {
validators[i] = &pb.Validator{
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
}
}
validatorBalances := make([]uint64, len(validators))
for i := 0; i < len(validatorBalances); i++ {
validatorBalances[i] = params.BeaconConfig().MaxDepositAmount
}
return &pb.BeaconState{
ValidatorRegistry: validators,
ValidatorBalances: validatorBalances,
Slot: slot,
}
}
func TestWinningRoot_AccurateRoot(t *testing.T) {
state := buildState(params.BeaconConfig().GenesisSlot, 100)
var participationBitfield []byte
participationBitfield = append(participationBitfield, byte(0x80))
// Generate 10 roots ([]byte{100}...[]byte{110})
var attestations []*pb.PendingAttestation
for i := 0; i < 10; i++ {
attestation := &pb.PendingAttestation{
Data: &pb.AttestationData{
Slot: params.BeaconConfig().GenesisSlot,
CrosslinkDataRootHash32: []byte{byte(i + 100)},
},
AggregationBitfield: participationBitfield,
}
attestations = append(attestations, attestation)
}
// Since all 10 roots have the balance of 64 ETHs
// winningRoot chooses the lowest hash: []byte{100}
winnerRoot, err := winningRoot(
state,
0,
attestations,
nil)
if err != nil {
t.Fatalf("Could not execute winningRoot: %v", err)
}
if !bytes.Equal(winnerRoot, []byte{100}) {
t.Errorf("Incorrect winner root, wanted:[100], got: %v", winnerRoot)
}
}
func TestWinningRoot_EmptyParticipantBitfield(t *testing.T) {
state := buildState(params.BeaconConfig().GenesisSlot, params.BeaconConfig().DepositsForChainStart)
attestations := []*pb.PendingAttestation{
{Data: &pb.AttestationData{
Slot: params.BeaconConfig().GenesisSlot,
CrosslinkDataRootHash32: []byte{},
},
AggregationBitfield: []byte{},
},
}
helpers.RestartCommitteeCache()
want := fmt.Sprintf("wanted participants bitfield length %d, got: %d", 16, 0)
if _, err := winningRoot(state, 0, attestations, nil); !strings.Contains(err.Error(), want) {
t.Errorf("Expected %s, received %v", want, err)
}
}
func TestAttestingValidators_MatchActive(t *testing.T) {
state := buildState(params.BeaconConfig().GenesisSlot, params.BeaconConfig().SlotsPerEpoch*2)
var attestations []*pb.PendingAttestation
for i := 0; i < 10; i++ {
attestation := &pb.PendingAttestation{
Data: &pb.AttestationData{
Slot: params.BeaconConfig().GenesisSlot,
CrosslinkDataRootHash32: []byte{byte(i + 100)},
},
AggregationBitfield: []byte{0xC0},
}
attestations = append(attestations, attestation)
}
helpers.RestartCommitteeCache()
attestedValidators, err := AttestingValidators(
state,
0,
attestations,
nil)
if err != nil {
t.Fatalf("Could not execute AttestingValidators: %v", err)
}
// Verify the winner root is attested by validators based on shuffling.
if !reflect.DeepEqual(attestedValidators, []uint64{123, 65}) {
t.Errorf("Active validators don't match. Wanted:[123,65], Got: %v", attestedValidators)
}
}
func TestAttestingValidators_EmptyWinningRoot(t *testing.T) {
state := buildState(params.BeaconConfig().GenesisSlot, params.BeaconConfig().DepositsForChainStart)
attestation := &pb.PendingAttestation{
Data: &pb.AttestationData{
Slot: params.BeaconConfig().GenesisSlot,
CrosslinkDataRootHash32: []byte{},
},
AggregationBitfield: []byte{},
}
helpers.RestartCommitteeCache()
want := fmt.Sprintf("wanted participants bitfield length %d, got: %d", 16, 0)
if _, err := AttestingValidators(state, 0, []*pb.PendingAttestation{attestation}, nil); !strings.Contains(err.Error(), want) {
t.Errorf("Expected %s, received %v", want, err)
}
}
func TestTotalAttestingBalance_CorrectBalance(t *testing.T) {
validatorsPerCommittee := uint64(2)
state := buildState(params.BeaconConfig().GenesisSlot, 2*params.BeaconConfig().SlotsPerEpoch)
// Generate 10 roots ([]byte{100}...[]byte{110})
var attestations []*pb.PendingAttestation
for i := 0; i < 10; i++ {
attestation := &pb.PendingAttestation{
Data: &pb.AttestationData{
Slot: params.BeaconConfig().GenesisSlot,
CrosslinkDataRootHash32: []byte{byte(i + 100)},
},
// All validators attested to the above roots.
AggregationBitfield: []byte{0xC0},
}
attestations = append(attestations, attestation)
}
helpers.RestartCommitteeCache()
attestedBalance, err := TotalAttestingBalance(
state,
0,
attestations,
nil)
if err != nil {
t.Fatalf("Could not execute totalAttestingBalance: %v", err)
}
if attestedBalance != params.BeaconConfig().MaxDepositAmount*validatorsPerCommittee {
t.Errorf("Incorrect attested balance. Wanted:64*1e9, Got: %d", attestedBalance)
}
}
func TestTotalAttestingBalance_EmptyWinningRoot(t *testing.T) {
state := buildState(params.BeaconConfig().GenesisSlot, params.BeaconConfig().DepositsForChainStart)
attestation := &pb.PendingAttestation{
Data: &pb.AttestationData{
Slot: params.BeaconConfig().GenesisSlot,
CrosslinkDataRootHash32: []byte{},
},
AggregationBitfield: []byte{},
}
helpers.RestartCommitteeCache()
want := fmt.Sprintf("wanted participants bitfield length %d, got: %d", 16, 0)
if _, err := TotalAttestingBalance(state, 0, []*pb.PendingAttestation{attestation}, nil); !strings.Contains(err.Error(), want) {
t.Errorf("Expected %s, received %v", want, err)
}
}
func TestTotalBalance_CorrectBalance(t *testing.T) {
// Assign validators to different balances.
state := &pb.BeaconState{
Slot: 5,
ValidatorBalances: []uint64{20 * 1e9, 25 * 1e9, 30 * 1e9, 30 * 1e9,
32 * 1e9, 34 * 1e9, 50 * 1e9, 50 * 1e9},
}
// 20 + 25 + 30 + 30 + 32 + 32 + 32 + 32 = 233
totalBalance := TotalBalance(state, []uint64{0, 1, 2, 3, 4, 5, 6, 7})
if totalBalance != 233*1e9 {
t.Errorf("Incorrect total balance. Wanted: 233*1e9, got: %d", totalBalance)
}
}
func TestInclusionSlot_GetsCorrectSlot(t *testing.T) {
state := buildState(params.BeaconConfig().GenesisSlot, params.BeaconConfig().DepositsForChainStart)
var participationBitfield []byte
for i := 0; i < 16; i++ {
participationBitfield = append(participationBitfield, byte(0xff))
}
state.LatestAttestations = []*pb.PendingAttestation{
{Data: &pb.AttestationData{Slot: params.BeaconConfig().GenesisSlot},
AggregationBitfield: participationBitfield,
InclusionSlot: 101},
{Data: &pb.AttestationData{Slot: params.BeaconConfig().GenesisSlot},
AggregationBitfield: participationBitfield,
InclusionSlot: 100},
{Data: &pb.AttestationData{Slot: params.BeaconConfig().GenesisSlot},
AggregationBitfield: participationBitfield,
InclusionSlot: 102},
}
slot, err := InclusionSlot(state, 251)
if err != nil {
t.Fatalf("Could not execute InclusionSlot: %v", err)
}
// validator 45's attestation got included in slot 100.
if slot != 100 {
t.Errorf("Incorrect slot. Wanted: 100, got: %d", slot)
}
}
func TestInclusionSlot_InvalidBitfield(t *testing.T) {
state := buildState(params.BeaconConfig().GenesisSlot, params.BeaconConfig().DepositsForChainStart)
state.LatestAttestations = []*pb.PendingAttestation{
{Data: &pb.AttestationData{Slot: params.BeaconConfig().GenesisSlot},
AggregationBitfield: []byte{},
InclusionSlot: 100},
}
want := fmt.Sprintf("wanted participants bitfield length %d, got: %d", 16, 0)
if _, err := InclusionSlot(state, 0); !strings.Contains(err.Error(), want) {
t.Errorf("Expected %s, received %v", want, err)
}
}
func TestInclusionSlot_SlotNotFound(t *testing.T) {
state := buildState(params.BeaconConfig().GenesisSlot, params.BeaconConfig().SlotsPerEpoch)
badIndex := uint64(10000)
want := fmt.Sprintf("could not find inclusion slot for validator index %d", badIndex)
if _, err := InclusionSlot(state, badIndex); !strings.Contains(err.Error(), want) {
t.Errorf("Expected %s, received %v", want, err)
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,39 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = ["epoch_processing_test.yaml.go"],
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/spectest",
visibility = ["//beacon-chain:__subpackages__"],
deps = ["//proto/beacon/p2p/v1:go_default_library"],
)
go_test(
name = "go_default_test",
size = "medium",
srcs = [
"crosslink_test.go",
"final_updates_test.go",
"justification_and_finalization_test.go",
"registry_test.go",
"slashings_test.go",
],
data = [
"@eth2_spec_tests//:test_data",
],
embed = [":go_default_library"],
tags = [
"spectest",
],
deps = [
"//beacon-chain/core/epoch:go_default_library",
"//beacon-chain/core/helpers:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//shared/params/spectest:go_default_library",
"//shared/testutil:go_default_library",
"@com_github_ghodss_yaml//:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"@in_gopkg_d4l3k_messagediff_v1//:go_default_library",
"@io_bazel_rules_go//go/tools/bazel:go_default_library",
],
)

View File

@@ -0,0 +1,62 @@
package spectest
import (
"io/ioutil"
"reflect"
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
"github.com/ghodss/yaml"
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/shared/params/spectest"
)
func runCrosslinkProcessingTests(t *testing.T, filename string) {
file, err := ioutil.ReadFile(filename)
if err != nil {
t.Fatalf("Could not load file %v", err)
}
s := &EpochProcessingTest{}
if err := yaml.Unmarshal(file, s); err != nil {
t.Fatalf("Failed to Unmarshal: %v", err)
}
if err := spectest.SetConfig(s.Config); err != nil {
t.Fatal(err)
}
for _, tt := range s.TestCases {
t.Run(tt.Description, func(t *testing.T) {
postState, err := epoch.ProcessCrosslinks(tt.Pre)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(postState, tt.Post) {
t.Error("Did not get expected state")
}
})
}
}
const crosslinkPrefix = "eth2_spec_tests/tests/epoch_processing/crosslinks/"
func TestCrosslinksProcessingMinimal(t *testing.T) {
filepath, err := bazel.Runfile(crosslinkPrefix + "crosslinks_minimal.yaml")
if err != nil {
t.Fatal(err)
}
runCrosslinkProcessingTests(t, filepath)
}
func TestCrosslinksProcessingMainnet(t *testing.T) {
helpers.ClearAllCaches()
filepath, err := bazel.Runfile(crosslinkPrefix + "crosslinks_mainnet.yaml")
if err != nil {
t.Fatal(err)
}
runCrosslinkProcessingTests(t, filepath)
}

View File

@@ -0,0 +1,19 @@
// Code generated by yaml_to_go. DO NOT EDIT.
package spectest
import pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
type EpochProcessingTest struct {
Title string `json:"title"`
Summary string `json:"summary"`
ForksTimeline string `json:"forks_timeline"`
Forks []string `json:"forks"`
Config string `json:"config"`
Runner string `json:"runner"`
Handler string `json:"handler"`
TestCases []struct {
Description string `json:"description"`
Pre *pb.BeaconState `json:"pre"`
Post *pb.BeaconState `json:"post"`
} `json:"test_cases"`
}

View File

@@ -0,0 +1,81 @@
package spectest
import (
"io/ioutil"
"reflect"
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
"github.com/ghodss/yaml"
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/params/spectest"
"github.com/prysmaticlabs/prysm/shared/testutil"
"gopkg.in/d4l3k/messagediff.v1"
)
func runFinalUpdatesTests(t *testing.T, filename string) {
file, err := ioutil.ReadFile(filename)
if err != nil {
t.Fatalf("Could not load file %v", err)
}
s := &EpochProcessingTest{}
if err := yaml.Unmarshal(file, s); err != nil {
t.Fatalf("Failed to Unmarshal: %v", err)
}
if err := spectest.SetConfig(s.Config); err != nil {
t.Fatal(err)
}
for _, tt := range s.TestCases[0:1] {
t.Run(tt.Description, func(t *testing.T) {
helpers.ClearAllCaches()
preState := &pb.BeaconState{}
if err := testutil.ConvertToPb(tt.Pre, preState); err != nil {
t.Fatal(err)
}
var postState *pb.BeaconState
postState, err = epoch.ProcessFinalUpdates(preState)
if err != nil {
t.Fatal(err)
}
expectedPostState := &pb.BeaconState{}
if err := testutil.ConvertToPb(tt.Post, expectedPostState); err != nil {
t.Fatal(err)
}
if expectedPostState.CurrentEpochAttestations == nil {
expectedPostState.CurrentEpochAttestations = []*pb.PendingAttestation{}
}
if !reflect.DeepEqual(postState, expectedPostState) {
t.Error("Did not get expected state")
diff, _ := messagediff.PrettyDiff(expectedPostState, postState)
t.Log(diff)
}
})
}
}
const finalUpdatesPrefix = "eth2_spec_tests/tests/epoch_processing/final_updates/"
func TestFinalUpdatesMinimal(t *testing.T) {
filepath, err := bazel.Runfile(finalUpdatesPrefix + "final_updates_minimal.yaml")
if err != nil {
t.Fatal(err)
}
runFinalUpdatesTests(t, filepath)
}
func TestFinalUpdatesMainnet(t *testing.T) {
filepath, err := bazel.Runfile(finalUpdatesPrefix + "final_updates_mainnet.yaml")
if err != nil {
t.Fatal(err)
}
runFinalUpdatesTests(t, filepath)
}

View File

@@ -0,0 +1,118 @@
package spectest
import (
"fmt"
"io/ioutil"
"reflect"
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
"github.com/ghodss/yaml"
"github.com/gogo/protobuf/proto"
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/params/spectest"
"github.com/prysmaticlabs/prysm/shared/testutil"
"gopkg.in/d4l3k/messagediff.v1"
)
// This is a subset of state.ProcessEpoch. The spec test defines input data for
// `justification_and_finalization` only.
func processJustificationAndFinalizationWrapper(state *pb.BeaconState) (*pb.BeaconState, error) {
helpers.ClearAllCaches()
// This process mutates the state, so we'll make a copy in order to print debug before/after.
state = proto.Clone(state).(*pb.BeaconState)
prevEpochAtts, err := epoch.MatchAttestations(state, helpers.PrevEpoch(state))
if err != nil {
return nil, fmt.Errorf("could not get target atts prev epoch %d: %v",
helpers.PrevEpoch(state), err)
}
currentEpochAtts, err := epoch.MatchAttestations(state, helpers.CurrentEpoch(state))
if err != nil {
return nil, fmt.Errorf("could not get target atts current epoch %d: %v",
helpers.CurrentEpoch(state), err)
}
prevEpochAttestedBalance, err := epoch.AttestingBalance(state, prevEpochAtts.Target)
if err != nil {
return nil, fmt.Errorf("could not get attesting balance prev epoch: %v", err)
}
currentEpochAttestedBalance, err := epoch.AttestingBalance(state, currentEpochAtts.Target)
if err != nil {
return nil, fmt.Errorf("could not get attesting balance current epoch: %v", err)
}
state, err = epoch.ProcessJustificationAndFinalization(state, prevEpochAttestedBalance, currentEpochAttestedBalance)
if err != nil {
return nil, fmt.Errorf("could not process justification: %v", err)
}
return state, nil
}
func runJustificationAndFinalizationTests(t *testing.T, filename string) {
file, err := ioutil.ReadFile(filename)
if err != nil {
t.Fatalf("Could not load file %v", err)
}
s := &EpochProcessingTest{}
if err := yaml.Unmarshal(file, s); err != nil {
t.Fatalf("Failed to Unmarshal: %v", err)
}
if err := spectest.SetConfig(s.Config); err != nil {
t.Fatal(err)
}
for _, tt := range s.TestCases {
t.Run(tt.Description, func(t *testing.T) {
preState := &pb.BeaconState{}
if err := testutil.ConvertToPb(tt.Pre, preState); err != nil {
t.Fatal(err)
}
postState, err := processJustificationAndFinalizationWrapper(preState)
if err != nil {
t.Fatal(err)
}
expectedPostState := &pb.BeaconState{}
if err := testutil.ConvertToPb(tt.Post, expectedPostState); err != nil {
t.Fatal(err)
}
if postState.JustificationBits[0] != expectedPostState.JustificationBits[0] {
t.Errorf("Justification bits mismatch. PreState.JustificationBits=%v. PostState.JustificationBits=%v. Expected=%v", preState.JustificationBits, postState.JustificationBits, expectedPostState.JustificationBits)
}
if !reflect.DeepEqual(postState, expectedPostState) {
diff, _ := messagediff.PrettyDiff(postState, expectedPostState)
t.Log(diff)
t.Error("Did not get expected state")
}
})
}
}
const justificationAndFinalizationPrefix = "eth2_spec_tests/tests/epoch_processing/justification_and_finalization/"
func TestJustificationAndFinalizationMinimal(t *testing.T) {
// TODO(#2891): Verify with ETH2 spec test.
t.Skip("The input data fails preconditions for matching attestations in the state for the current epoch.")
filepath, err := bazel.Runfile(justificationAndFinalizationPrefix + "justification_and_finalization_minimal.yaml")
if err != nil {
t.Fatal(err)
}
runJustificationAndFinalizationTests(t, filepath)
}
func TestJustificationAndFinalizationMainnet(t *testing.T) {
filepath, err := bazel.Runfile(justificationAndFinalizationPrefix + "justification_and_finalization_mainnet.yaml")
if err != nil {
t.Fatal(err)
}
runJustificationAndFinalizationTests(t, filepath)
}

View File

@@ -0,0 +1,59 @@
package spectest
import (
"io/ioutil"
"reflect"
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
"github.com/ghodss/yaml"
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch"
"github.com/prysmaticlabs/prysm/shared/params/spectest"
)
func runRegisteryProcessingTests(t *testing.T, filename string) {
file, err := ioutil.ReadFile(filename)
if err != nil {
t.Fatalf("Could not load file %v", err)
}
s := &EpochProcessingTest{}
if err := yaml.Unmarshal(file, s); err != nil {
t.Fatalf("Failed to Unmarshal: %v", err)
}
if err := spectest.SetConfig(s.Config); err != nil {
t.Fatal(err)
}
for _, tt := range s.TestCases {
t.Run(tt.Description, func(t *testing.T) {
postState, err := epoch.ProcessRegistryUpdates(tt.Pre)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(postState, tt.Post) {
t.Error("Did not get expected state")
}
})
}
}
const registryUpdatesPrefix = "eth2_spec_tests/tests/epoch_processing/registry_updates/"
func TestRegistryProcessingMinimal(t *testing.T) {
filepath, err := bazel.Runfile(registryUpdatesPrefix + "registry_updates_minimal.yaml")
if err != nil {
t.Fatal(err)
}
runRegisteryProcessingTests(t, filepath)
}
func TestRegistryProcessingMainnet(t *testing.T) {
filepath, err := bazel.Runfile(registryUpdatesPrefix + "registry_updates_mainnet.yaml")
if err != nil {
t.Fatal(err)
}
runRegisteryProcessingTests(t, filepath)
}

View File

@@ -0,0 +1,61 @@
package spectest
import (
"io/ioutil"
"reflect"
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
"github.com/ghodss/yaml"
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/shared/params/spectest"
)
func runSlashingsTests(t *testing.T, filename string) {
file, err := ioutil.ReadFile(filename)
if err != nil {
t.Fatalf("Could not load file %v", err)
}
s := &EpochProcessingTest{}
if err := yaml.Unmarshal(file, s); err != nil {
t.Fatalf("Failed to Unmarshal: %v", err)
}
if err := spectest.SetConfig(s.Config); err != nil {
t.Fatal(err)
}
for _, tt := range s.TestCases {
t.Run(tt.Description, func(t *testing.T) {
helpers.ClearAllCaches()
postState, err := epoch.ProcessSlashings(tt.Pre)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(postState, tt.Post) {
t.Error("Did not get expected state")
}
})
}
}
const slashingsPrefix = "eth2_spec_tests/tests/epoch_processing/slashings/"
func TestSlashingsMinimal(t *testing.T) {
filepath, err := bazel.Runfile(slashingsPrefix + "slashings_minimal.yaml")
if err != nil {
t.Fatal(err)
}
runSlashingsTests(t, filepath)
}
func TestSlashingsMainnet(t *testing.T) {
filepath, err := bazel.Runfile(slashingsPrefix + "slashings_mainnet.yaml")
if err != nil {
t.Fatal(err)
}
runSlashingsTests(t, filepath)
}

View File

@@ -3,8 +3,11 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"attestation.go",
"block.go",
"cache.go",
"committee.go",
"deposits.go",
"eth1data.go",
"randao.go",
"rewards_penalties.go",
"slot_epoch.go",
@@ -16,11 +19,11 @@ go_library(
"//beacon-chain/cache:go_default_library",
"//beacon-chain/utils:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//shared/bitutil: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_prysmaticlabs_go_bitfield//:go_default_library",
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
"@org_golang_google_grpc//codes:go_default_library",
"@org_golang_google_grpc//status:go_default_library",
@@ -31,8 +34,10 @@ go_test(
name = "go_default_test",
size = "small",
srcs = [
"attestation_test.go",
"block_test.go",
"committee_test.go",
"deposits_test.go",
"eth1data_test.go",
"randao_test.go",
"rewards_penalties_test.go",
"slot_epoch_test.go",
@@ -40,11 +45,13 @@ go_test(
],
embed = [":go_default_library"],
deps = [
"//beacon-chain/cache:go_default_library",
"//beacon-chain/internal:go_default_library",
"//beacon-chain/utils:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//shared/featureconfig:go_default_library",
"//shared/bytesutil:go_default_library",
"//shared/params:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"//shared/testutil:go_default_library",
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
"@org_golang_google_grpc//codes:go_default_library",
"@org_golang_google_grpc//status:go_default_library",
],

View File

@@ -0,0 +1,51 @@
package helpers
import (
"errors"
"fmt"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/params"
)
var (
// ErrAttestationDataSlotNilState is returned when a nil state argument
// is provided to AttestationDataSlot.
ErrAttestationDataSlotNilState = errors.New("nil state provided for AttestationDataSlot")
// ErrAttestationDataSlotNilData is returned when a nil attestation data
// argument is provided to AttestationDataSlot.
ErrAttestationDataSlotNilData = errors.New("nil data provided for AttestationDataSlot")
)
// AttestationDataSlot returns current slot of AttestationData for given state
//
// Spec pseudocode definition:
// def get_attestation_data_slot(state: BeaconState, data: AttestationData) -> Slot:
// """
// Return the slot corresponding to the attestation ``data``.
// """
// committee_count = get_committee_count(state, data.target.epoch)
// offset = (data.crosslink.shard + SHARD_COUNT - get_start_shard(state, data.target.epoch)) % SHARD_COUNT
// return Slot(compute_start_slot_of_epoch(data.target.epoch) + offset // (committee_count // SLOTS_PER_EPOCH))
func AttestationDataSlot(state *pb.BeaconState, data *pb.AttestationData) (uint64, error) {
if state == nil {
return 0, ErrAttestationDataSlotNilState
}
if data == nil {
return 0, ErrAttestationDataSlotNilData
}
committeeCount, err := CommitteeCount(state, data.Target.Epoch)
if err != nil {
return 0, err
}
epochStartShardNumber, err := StartShard(state, data.Target.Epoch)
if err != nil { // This should never happen if CommitteeCount was successful
return 0, fmt.Errorf("could not determine epoch start shard: %v", err)
}
offset := (data.Crosslink.Shard + params.BeaconConfig().ShardCount -
epochStartShardNumber) % params.BeaconConfig().ShardCount
return StartSlot(data.Target.Epoch) + (offset / (committeeCount / params.BeaconConfig().SlotsPerEpoch)), nil
}

View File

@@ -0,0 +1,101 @@
package helpers_test
import (
"context"
"testing"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/internal"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
)
func TestAttestationDataSlot_OK(t *testing.T) {
db := internal.SetupDB(t)
defer internal.TeardownDB(t, db)
deposits, _ := testutil.SetupInitialDeposits(t, 100, false)
if err := db.InitializeState(context.Background(), uint64(0), deposits, nil); err != nil {
t.Fatalf("Could not initialize beacon state to disk: %v", err)
}
beaconState, err := db.HeadState(context.Background())
if err != nil {
t.Fatal(err)
}
offset := uint64(0)
committeeCount, _ := helpers.CommitteeCount(beaconState, 0)
expect := offset / (committeeCount / params.BeaconConfig().SlotsPerEpoch)
attSlot, err := helpers.AttestationDataSlot(beaconState, &pb.AttestationData{
Target: &pb.Checkpoint{Epoch: 0},
Crosslink: &pb.Crosslink{
Shard: 0,
},
})
if err != nil {
t.Fatal(err)
}
if attSlot != expect {
t.Errorf("Expected %d, received %d", expect, attSlot)
}
}
func TestAttestationDataSlot_ReturnsErrorWithNilState(t *testing.T) {
s, err := helpers.AttestationDataSlot(nil /*state*/, &pb.AttestationData{
Target: &pb.Checkpoint{Epoch: 0},
Crosslink: &pb.Crosslink{
Shard: 0,
},
})
if err != helpers.ErrAttestationDataSlotNilState {
t.Errorf("Expected an error, but received %v", err)
t.Logf("attestation slot=%v", s)
}
}
func TestAttestationDataSlot_ReturnsErrorWithNilData(t *testing.T) {
s, err := helpers.AttestationDataSlot(&pb.BeaconState{}, nil /*data*/)
if err != helpers.ErrAttestationDataSlotNilData {
t.Errorf("Expected an error, but received %v", err)
t.Logf("attestation slot=%v", s)
}
}
func TestAttestationDataSlot_ReturnsErrorWithErroneousTargetEpoch(t *testing.T) {
db := internal.SetupDB(t)
defer internal.TeardownDB(t, db)
deposits, _ := testutil.SetupInitialDeposits(t, 100, false)
if err := db.InitializeState(context.Background(), uint64(0), deposits, nil); err != nil {
t.Fatalf("Could not initialize beacon state to disk: %v", err)
}
beaconState, err := db.HeadState(context.Background())
if err != nil {
t.Fatal(err)
}
s, err := helpers.AttestationDataSlot(beaconState, &pb.AttestationData{
Target: &pb.Checkpoint{Epoch: 1<<63 - 1 /* Far future epoch */},
})
if err == nil {
t.Error("Expected an error, but received nil")
t.Logf("attestation slot=%v", s)
}
}
func TestAttestationDataSlot_ReturnsErrorWhenTargetEpochLessThanCurrentEpoch(t *testing.T) {
db := internal.SetupDB(t)
defer internal.TeardownDB(t, db)
deposits, _ := testutil.SetupInitialDeposits(t, 100, false)
if err := db.InitializeState(context.Background(), uint64(0), deposits, nil); err != nil {
t.Fatalf("Could not initialize beacon state to disk: %v", err)
}
beaconState, err := db.HeadState(context.Background())
if err != nil {
t.Fatal(err)
}
s, err := helpers.AttestationDataSlot(beaconState, &pb.AttestationData{
Target: &pb.Checkpoint{Epoch: 2},
})
if err == nil {
t.Error("Expected an error, but received nil")
t.Logf("attestation slot=%v", s)
}
}

View File

@@ -0,0 +1,37 @@
package helpers
import (
"errors"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/params"
)
// BlockRootAtSlot returns the block root stored in the BeaconState for a recent slot.
// It returns an error if the requested block root is not within the slot range.
//
// Spec pseudocode definition:
// def get_block_root_at_slot(state: BeaconState, slot: Slot) -> Hash:
// """
// Return the block root at a recent ``slot``.
// """
// assert slot < state.slot <= slot + SLOTS_PER_HISTORICAL_ROOT
// return state.block_roots[slot % SLOTS_PER_HISTORICAL_ROOT]
func BlockRootAtSlot(state *pb.BeaconState, slot uint64) ([]byte, error) {
if !(slot < state.Slot && state.Slot <= slot+params.BeaconConfig().HistoricalRootsLimit) {
return []byte{}, errors.New("slot out of bounds")
}
return state.BlockRoots[slot%params.BeaconConfig().HistoricalRootsLimit], nil
}
// BlockRoot returns the block root stored in the BeaconState for epoch start slot.
//
// Spec pseudocode definition:
// def get_block_root(state: BeaconState, epoch: Epoch) -> Hash:
// """
// Return the block root at the start of a recent ``epoch``.
// """
// return get_block_root_at_slot(state, compute_start_slot_of_epoch(epoch))
func BlockRoot(state *pb.BeaconState, epoch uint64) ([]byte, error) {
return BlockRootAtSlot(state, StartSlot(epoch))
}

View File

@@ -0,0 +1,116 @@
package helpers
import (
"bytes"
"testing"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/params"
)
func TestBlockRootAtSlot_CorrectBlockRoot(t *testing.T) {
var blockRoots [][]byte
for i := uint64(0); i < params.BeaconConfig().HistoricalRootsLimit; i++ {
blockRoots = append(blockRoots, []byte{byte(i)})
}
s := &pb.BeaconState{
BlockRoots: blockRoots,
}
tests := []struct {
slot uint64
stateSlot uint64
expectedRoot []byte
}{
{
slot: 0,
stateSlot: 1,
expectedRoot: []byte{0},
},
{
slot: 2,
stateSlot: 5,
expectedRoot: []byte{2},
},
{
slot: 64,
stateSlot: 128,
expectedRoot: []byte{64},
}, {
slot: 2999,
stateSlot: 3000,
expectedRoot: []byte{183},
}, {
slot: 2873,
stateSlot: 3000,
expectedRoot: []byte{57},
},
{
slot: 0,
stateSlot: params.BeaconConfig().HistoricalRootsLimit,
expectedRoot: []byte{0},
},
}
for _, tt := range tests {
s.Slot = tt.stateSlot
wantedSlot := tt.slot
result, err := BlockRootAtSlot(s, wantedSlot)
if err != nil {
t.Fatalf("failed to get block root at slot %d: %v",
wantedSlot, err)
}
if !bytes.Equal(result, tt.expectedRoot) {
t.Errorf(
"result block root was an unexpected value, wanted %v, got %v",
tt.expectedRoot,
result,
)
}
}
}
func TestBlockRootAtSlot_OutOfBounds(t *testing.T) {
var blockRoots [][]byte
for i := uint64(0); i < params.BeaconConfig().HistoricalRootsLimit; i++ {
blockRoots = append(blockRoots, []byte{byte(i)})
}
state := &pb.BeaconState{
BlockRoots: blockRoots,
}
tests := []struct {
slot uint64
stateSlot uint64
expectedErr string
}{
{
slot: 1000,
stateSlot: 500,
expectedErr: "slot out of bounds",
},
{
slot: 3000,
stateSlot: 3000,
expectedErr: "slot out of bounds",
},
{
// Edge case where stateSlot is over slots per historical root and
// slot is not within (stateSlot - HistoricalRootsLimit, statSlot]
slot: 1,
stateSlot: params.BeaconConfig().HistoricalRootsLimit + 2,
expectedErr: "slot out of bounds",
},
}
for _, tt := range tests {
state.Slot = tt.stateSlot
_, err := BlockRootAtSlot(state, tt.slot)
if err == nil {
t.Errorf("Expected error %s, got nil", tt.expectedErr)
}
if err != nil && err.Error() != tt.expectedErr {
t.Errorf("Expected error \"%s\" got \"%v\"", tt.expectedErr, err)
}
}
}

View File

@@ -0,0 +1,50 @@
package helpers
import (
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
)
// ClearShuffledValidatorCache clears the shuffled indices cache from scratch.
func ClearShuffledValidatorCache() {
shuffledIndicesCache = cache.NewShuffledIndicesCache()
}
// ClearStartShardCache clears the start shard cache from scratch.
func ClearStartShardCache() {
startShardCache = cache.NewStartShardCache()
}
// ClearTotalActiveBalanceCache restarts the total active validator balance cache from scratch.
func ClearTotalActiveBalanceCache() {
totalActiveBalanceCache = cache.NewActiveBalanceCache()
}
// ClearCurrentEpochSeed clears the current epoch seed.
func ClearCurrentEpochSeed() {
currentEpochSeed = cache.NewSeedCache()
}
// ClearActiveCountCache restarts the active validator count cache from scratch.
func ClearActiveCountCache() {
activeCountCache = cache.NewActiveCountCache()
}
// ClearActiveIndicesCache restarts the active validator indices cache from scratch.
func ClearActiveIndicesCache() {
activeIndicesCache = cache.NewActiveIndicesCache()
}
// ActiveIndicesKeys returns the keys of the active indices cache.
func ActiveIndicesKeys() []string {
return activeIndicesCache.ActiveIndicesKeys()
}
// ClearAllCaches clears all the helpers caches from scratch.
func ClearAllCaches() {
ClearActiveIndicesCache()
ClearActiveCountCache()
ClearStartShardCache()
ClearShuffledValidatorCache()
ClearTotalActiveBalanceCache()
ClearCurrentEpochSeed()
}

File diff suppressed because it is too large Load Diff

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