Compare commits

...

351 Commits

Author SHA1 Message Date
Raul Jordan
551b03d6e6 Resolve Web UI Beta Testing Bugs (#7471)
* more descriptive password validation error

* include change wallet password fixes

* balance and jwt improvements

* allow for different wallet dirs specified on startup

* ensure wallet password is always validated

* fix up prysm tests

* gaz

* test pass

* pass balances tests

* wrap up fixes

* radek feedback

* fix up tests

* cors fix

* add tests for validator status

* pass tests

* fix n

* skip content type test

* package level cache and send over feed

* package level cache for derived

* all tests passing

* gofmt

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-10-10 02:07:28 +00:00
Potuz
c4e64afd07 Report on duplicate validator keys during imports (#7459)
* Fix #7393

* fix go fmt

* Add a test

* Convert to map of strings

* @terencechain fixes

* Update validator/keymanager/v2/direct/import.go

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

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
Co-authored-by: Victor Farazdagi <simple.square@gmail.com>
2020-10-10 01:45:26 +00:00
Victor Farazdagi
d98a6dda8f Verify interface compliance using typed nil instead of dereferencing and conversion (#7489)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-10-10 00:36:48 +00:00
terence tsao
8aaa5b6ad0 Refactor ancestor lookup (#7472)
* Add ancestor root fall back to DB check

* Add a warning message

* Refactor ancestor lookups into seperate functions

* Update error string

* Fix has parent check and add a regression test

* Add a conext error test

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-10-10 00:07:56 +00:00
Victor Farazdagi
f92244d497 Remove redundant err checking (#7488)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-10-09 23:39:23 +00:00
Preston Van Loon
e91165b0b4 Update validator UI to 0.0.1-alpha (#7486)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-10-09 22:06:23 +00:00
terence tsao
e15a0b08aa Remove duplicated StartSlot (#7484)
* Remove duplicated StartSlot

* Update existing tests

* Gazelle

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-10-09 21:23:49 +00:00
Raul Jordan
a3a77ab5a8 Open Web UI in Browser Automatically (#7481)
* open web

* Update shared/browser/browser_test.go

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

* Update shared/browser/browser.go

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

* add to depz.bazel

* run gazelle

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-10-09 19:51:46 +00:00
terence tsao
650ec797da Add missing mainet spec test (#7482) 2020-10-09 18:58:19 +00:00
Nishant Das
f629c72107 Tighten Up Snappy Framing (#7479)
* fix framing

* fix up conditions

* fix

* clean up

* change back

* simpler

* no need to cast

* Use math.MaxInt64

* gaz, gofmt

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-10-09 16:50:18 +00:00
Preston Van Loon
98a20766c9 Enable coverage for deepsource (#7441)
* Enable coverage for deepsource

* Add gocovmerge tool

* go mod tidy
2020-10-09 09:15:55 -07:00
Preston Van Loon
1f707842d2 Serve Prysm Web UI from Validator (#7470)
* Prysm web UI basic idea

* Refactor to use shared.Service interface, add sanity test

* register web server

* Determine mimetype

* Use 4242 as port for web

* Allow localhost or 127.0.0.1 for CORS. More tests, commentary

* Add flags, add site_data.go

* ignore site data

* Add sha

* gofmt

* gofmt

* fix script

* Lints

* fix vis

Co-authored-by: Victor Farazdagi <simple.square@gmail.com>
2020-10-09 09:58:30 -05:00
dv8silencer
c944f29c7c Fix --clear-db on Windows (#7474)
* fix with text

* fix also for validator and add test

* handle error

* fix another test

* handle error

* gazelle

* fix bug in slasher as well

* gazelle
2020-10-09 09:28:35 +00:00
terence tsao
6b5265d2d4 Update slashing precompute to use config instead of hardcoded value (#7473) 2020-10-08 19:49:20 -07:00
terence tsao
8f64eb622e Optimize IsValidAttestationIndices unique sorted indices check (#7458)
* Optimize unique sorted indices check

* Add err handling for benchmark

* Gazelle

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-10-08 23:20:18 +00:00
Preston Van Loon
4ddacd57c6 fix blst build tag (#7443)
* fix blst build tag

* fix fuzz build

* remove buildkite specific bazelrc line

* remove conflicting kafka gotag in CI

* fix again

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2020-10-08 18:37:12 +00:00
Nishant Das
a66f434236 Listen to all Network Interfaces for discovery (#7434)
* listen to all ifaces for discovery

* fix test

* fix tests

* fix all tests

* Revert "fix all tests"

This reverts commit a5d6fffd45.

* Revert "fix tests"

This reverts commit b7a0cf5609.

* Revert "fix test"

This reverts commit 57e6218c68.

* fix and use loopback

* do properly

* fix

* listen to all ifaces

* fix bootnode

* make it trace

* make it loopback

* swap out

* change back

* fix e2e

* fix

* Update beacon-chain/p2p/discovery.go

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

Co-authored-by: Victor Farazdagi <simple.square@gmail.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-10-08 15:16:18 +00:00
dv8silencer
796c336a29 Fix wallet check for Windows by addresses differences in error message text (#7461)
* fix

* test

Co-authored-by: dv8silencer <15720668+dv8silencer@users.noreply.github.com>
Co-authored-by: Radosław Kapka <rkapka@wp.pl>
Co-authored-by: Victor Farazdagi <simple.square@gmail.com>
2020-10-08 14:30:08 +00:00
Nishant Das
48fcb08ebc Eth1 Handling Cleanup (#7467)
* clean up

* remove test
2020-10-08 13:47:16 +00:00
Shay Zluf
1315a15d9d Import proposal protection (#7430)
* Import proposals protection db

* Import old proposal protection data structure to new one

* test empty slots

* Update validator/db/kv/new_proposal_history.go

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

* Update validator/db/kv/new_proposal_history_test.go

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
Co-authored-by: Victor Farazdagi <simple.square@gmail.com>
2020-10-08 11:51:50 +00:00
Radosław Kapka
25ebed9a70 Cache deposits only up to finalized block (#7453)
* cache deposits until finalized block

* take deposit index from state instead of block

* use stateByRoot

* use eth1data deposit count

* use depositCount-1

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-10-08 10:12:21 +00:00
terence tsao
703907bd99 Move ComputeProposerIndexWithValidators to test (#7460)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-10-08 09:24:17 +00:00
Preston Van Loon
d4e6ce6998 Fix deepsource findings (#7457)
* remove unused code

* Incomplete condition fix

* club append to single call

* anti-pattern fix 'should use for range instead of for { select {} }'

* use strings.ReplaceAll

* replace `len(parts[0]) == 0` with `parts[0] == ""`

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-10-08 08:36:47 +00:00
Preston Van Loon
390a589afb Disable BES in CI (#7462)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-10-08 07:17:35 +00:00
terence tsao
d34156bfe6 Add close to the body for e2e test (#7450)
* Add close to the body for e2e test

* Add error handling to defer

* Remove extra line

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-10-08 05:55:53 +00:00
bidlocode
7c8492e83f Add medalla flag (#7399)
* add --medalla flag for uniformity

* add enforcing testnet flag

* fix

* fix comments

* fix sufficient err msg

* fix shared method

* fix

* fix name

* fix name

* add test

* fix e2e

* fix gofmt

* fix test

* add warning

* fix warning

* fix warning test

* fix

* fix

* fix

* fix

* fix gofmt

* fix refactor to func

* add func description

* fix exported

* fix

* fix

* fix

Co-authored-by: Victor Farazdagi <simple.square@gmail.com>
Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
2020-10-07 23:04:19 +00:00
Preston Van Loon
668163d740 Revert PR #7429 to fix building on windows (#7456)
* Revert PR #7429 to fix building on windows

* Revert PR #7429 to fix building on windows

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-10-07 19:09:40 +00:00
terence tsao
7ad2929f0f Revamp proposer cache to fix lookahead bug (#7442)
* Add and test proposer indices cache

* Remove proposer indices usages from committee cache

* Adopt the new proposer indices cache

* Add comments on why genesis epoch is skipped

* Fix the failing tests

* Update beacon-chain/blockchain/process_block.go

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

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

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

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

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

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

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

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

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

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

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

* Address additional feedbacks from @prestonvanloon

* Add comments on why genesis epoch is skipped

* Refactor EndSlot to use StartSlot within

* Add proposer indices disabled

* Add libfuzz tags

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
2020-10-07 17:25:08 +00:00
Victor Farazdagi
9ce64e2428 Refactor peer scorer into peerdata + scorers (#7452)
* updates comment

* manager -> service

* rename receiver

* refacgtor bad_responses

* refactor store

* update status service

* extends data service

* status service test

* refactor block provider scorer

* misc updates

* fix tests

* data -> peerdata

* gazelle

* peerdata/store test

* limit the visibility scope

* Nishant's suggestion

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-10-07 13:08:51 +00:00
terence tsao
ae78546323 Add Zinken flag to slasher (#7451)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-10-07 09:44:50 +00:00
Raul Jordan
23bce8d0c5 Include Deposit Data JSON in Wallet Create RPC Response (#7444)
* return deposit data for hd wallet create

* test added for deposit data json

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-10-07 02:15:54 +00:00
terence tsao
29137f7b39 Remove unused SlotSignature function (#7447)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-10-06 23:55:37 +00:00
Raul Jordan
bf4a8dcee9 Fix E2E Readme to Include Bazel Define Flag (#7449)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-10-06 20:49:29 +00:00
Shay Zluf
7b5f71229e New attestation store for local protection (#7248)
* Update attestation with new marshal unmarshal

* Add db methods to handle new slashing protection schema

* lint

* add tests

* goimports

* Apply suggestions from code review

Co-authored-by: Ivan Martinez <ivanthegreatdev@gmail.com>

* const fix

* fix ineffectual assignments

* goimports

* fix import issue

* victor feedback fixes

* victor feedback fixes

* receiver methods

* receiver methods

* Update validator/db/kv/attestation_history_new.go

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

* Update validator/db/kv/attestation_history_new.go

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

* Update validator/db/kv/attestation_history_new.go

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

* Update validator/db/kv/attestation_history_new.go

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

* Update validator/db/kv/attestation_history_new_test.go

* type change

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: Ivan Martinez <ivanthegreatdev@gmail.com>
Co-authored-by: Victor Farazdagi <simple.square@gmail.com>
2020-10-06 19:59:36 +00:00
Raul Jordan
4d7797827e Concurrent Websocket Handlers for Log Streaming (#7428)
* concurrent conn with mutex

* add buffer size

* only localhost

* clarify caller needs to hold lock

* Update shared/logutil/stream.go

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

* Update shared/logutil/stream.go

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

* fix up tests

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-10-06 13:32:48 +00:00
terence tsao
c0ed43d920 Refactor head info for better usages for lock (#7432)
* Refactor head info for better usages for lock

* Fix headroot test to use [32]byte{}

* go fmt: issue introduced in #7429

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
Co-authored-by: Victor Farazdagi <simple.square@gmail.com>
2020-10-06 10:57:18 +00:00
Victor Farazdagi
842c15856b Apply go fmt + tidy: issue introduced in #7429 (#7446) 2020-10-06 09:05:32 +00:00
Potuz
20ac925ee4 Add a journald log format option. (#7429)
* Add a journald log format option.

Add an accepted value "journald" for the --log-format flag so that
logs are directed to journald with the correct error level.

* fix docker images

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
2020-10-06 04:37:16 +00:00
Raul Jordan
6e8ff10003 deep source toml (#7439) 2020-10-05 14:07:49 -07:00
Victor Farazdagi
419fad07cd Handle nil header properly in powchain service tests (#7435) 2020-10-05 10:10:31 +00:00
Ivan Martinez
cf1c346beb Eth2 API: Add outline for beacon endpoints (#7408)
* Start Beacon API outline

* Rename to v1

* Add impl

* Change to outline

* Add comments

* Remove unneeded items

* Fix linting

* tidy

* Fix visibility

* go.sum

* Fix deps

* Tidy

* Add check for interface type and fix pointers

* Fix pointer name

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
2020-10-05 00:15:27 +00:00
Radosław Kapka
3e0b20529b Miscellaneous code quality improvements (#7414)
* anti-patterns

* performance issues

* handle skipped defer

* gazelle fix

* misc bug risks

* make logging of proposer slashings more robust

* simplify calling span.End()

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-10-04 15:03:10 +00:00
Raul Jordan
d9ae2073e2 Pagination Added to ListAccounts Validator RPC Call (#7422)
* Pagination tests to list accounts

* fetch all

* gaz

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-10-03 17:26:39 -05:00
terence tsao
7b3efcf62b Move read lock after hasHeadState (#7427)
* Move read lock before hasHeadState

* Export the locked version

* Update beacon-chain/blockchain/head.go

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

* Update beacon-chain/blockchain/chain_info.go

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

* Update beacon-chain/blockchain/chain_info.go

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

* Update beacon-chain/blockchain/chain_info.go

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

Co-authored-by: Victor Farazdagi <simple.square@gmail.com>
2020-10-03 20:53:05 +00:00
terence tsao
c7d01fd73c Add lock around fork choice store votes (#7426)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-10-03 05:48:34 +00:00
Preston Van Loon
2916d183e8 Pubsub: ensure better TopicIDs validation (#7418)
* Ensure better topicIDs validation, add tests

* go mod tidy

* fix tests

Co-authored-by: Victor Farazdagi <simple.square@gmail.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-10-03 01:51:58 +00:00
terence tsao
c24fb792cb Add locks around head getters (#7423) 2020-10-03 00:45:59 +00:00
Raul Jordan
70f3fcdbd9 Implement Create Account via RPC (#7400)
* add ssz rules

* regenerate protos to include deposit message

* built to match the deposit cli

* derived test

* fix up nil item

* fix up more nil items

* preston suggestion

* comment

* add missing tests to build file

* fix busted tests

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
Co-authored-by: Victor Farazdagi <simple.square@gmail.com>
2020-10-02 16:35:28 -05:00
Victor Farazdagi
ecfdb354a7 Add new static analyzer: ineffassign (#7413)
* test defined

* first working impl

* register analyzer

* cleanup

* removes unused code

* secure rand in slasher/detection/testing

* Updates test

* fixes ineffassign type checks

* one more

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
2020-10-02 23:56:18 +03:00
terence tsao
690fa12f1a Check block attestation length for operation pool (#7420)
Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
2020-10-02 20:08:06 +00:00
Nishant Das
63c1057ae6 add bootnode (#7415)
Co-authored-by: Victor Farazdagi <simple.square@gmail.com>
Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
2020-10-02 12:28:09 -07:00
Preston Van Loon
1eee1948bb Fall back to ValidationIgnore in the event of a validation panic (#7419)
Co-authored-by: Victor Farazdagi <simple.square@gmail.com>
2020-10-02 11:33:45 -07:00
Victor Farazdagi
e36e9250f1 enable cryptorand analyzer in slasher (#7417) 2020-10-02 19:32:21 +03:00
Nishant Das
b589ddd774 use full hash (#7416) 2020-10-02 23:08:51 +08:00
Nishant Das
ba01abbc8f use valid build tags (#7411) 2020-10-02 12:45:58 +03:00
Nishant Das
fa82b09cec Optimize Fetching of Eth1 Blocks (#7386)
* optimize fetching

* tests and clean up

* improve comment

* more cleanup

* lint

* dont terminate lookup

* shay and radek's review

* fix test

* Update beacon-chain/powchain/block_reader.go

* gofmt

* cleanup

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
Co-authored-by: Victor Farazdagi <simple.square@gmail.com>
Co-authored-by: rkapka <rkapka@wp.pl>
2020-10-02 15:31:05 +08:00
dv8silencer
7d9a706cfa Warn if user is not using a supported platform (#7381)
* Add prereqs package

* Incorporate prereq check into the clients

* gazelle

* gazelle fix

* linter

* Add tests

* minor change in test

* finish up tests

* gazelle

* error during platform detection does not cause client to fail fast

Co-authored-by: dv8silencer <15720668+dv8silencer@users.noreply.github.com>
2020-10-02 09:45:34 +03:00
Raul Jordan
437bab7df0 Update EthereumAPIs (#7409)
* handle unknown validator

* tests passing

* tidy
2020-10-01 22:04:48 -04:00
bidlocode
ee747ca6d4 add display contract (#7407)
* add display contract
2020-10-01 22:55:49 +00:00
terence tsao
de93551332 Ensure span ends (#7405)
* Ensure span ends
* Merge refs/heads/master into span-ends
* Merge refs/heads/master into span-ends
* Add missed span end
* Merge branch 'span-ends' of github.com:prysmaticlabs/prysm into span-ends
* Merge refs/heads/master into span-ends
2020-10-01 21:13:27 +00:00
terence tsao
0839f10dbc Add lock around feature config (#7406)
* Add lock
2020-10-01 20:35:44 +00:00
Victor Farazdagi
d169b490fa Fix ineffectual assignments (#7403)
* update rpc/beacon
* more fixes to beacon-chain/rpc
* update beacon-chain/sync
* Merge refs/heads/master into fix-ineffectual-assignments
* updates beacon-chain/p2p
* Merge branch 'fix-ineffectual-assignments' of github.com:prysmaticlabs/prysm into fix-ineffectual-assignments
* update beacon-chain/*
* fix imports
* update beacon-chain/blockchain
* more updates
* Merge refs/heads/master into fix-ineffectual-assignments
* Merge branch 'master' into fix-ineffectual-assignments
* Merge refs/heads/master into fix-ineffectual-assignments
* next round of updated
* Merge branch 'fix-ineffectual-assignments' of github.com:prysmaticlabs/prysm into fix-ineffectual-assignments
* wrap up remaining items
2020-10-01 18:53:36 +00:00
terence tsao
490cf9b7ba Remove logging of password if fails (#7404)
* Remove logging of password if fails
2020-10-01 17:41:23 +00:00
Victor Farazdagi
95a5b4945b Fixes incorrect checks for errors in several tests (#7392)
* fixes TestServer_ListAssignments_Pagination_InputOutOfRange
* fixes TestServer_ListValidatorBalances_PaginationOutOfRange
* fix TestServer_ListAttestations_Genesis
* remove redundant TestServer_GetValidatorParticipation_DoesntExist and TestGetDuties_NextEpoch_CantFindValidatorIdx
* Merge branch 'master' into fix-invalid-errcheck-tests
* remove unnecessary import
* fix TestStore_OnAttestation
* fix TestStore_OnAttestationUsingCheckptCache
* fix TestVerifyBlkDescendant
* fix pagination tests
* fix account v2 tests
* fix account v2 tests (remote)
* fix TestServer_JWTInterceptor_BadToken
* Merge refs/heads/master into fix-invalid-errcheck-tests
2020-10-01 14:38:53 +00:00
Victor Farazdagi
4aea039324 Remove unused constant in round robin (#7402)
* remove unused constant
2020-10-01 13:02:47 +00:00
Raul Jordan
23181c8629 Implement Backup and Delete Accounts via RPC (#7397)
* begin with delete accounts impl

* delete tests passing

* started backup, delete tests all passing

* implement backup using zip

* backup implementation done with unzip tests

* full tests done

* used proper error codes

* remove comment

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-09-30 22:37:38 -05:00
Preston Van Loon
d23b247a82 DB: Return error when saving nil eth1data (#7396)
* Return an error on saving nil eth1data
* gofmt
* Merge branch 'master' into return-error-on-nil
* Merge refs/heads/master into return-error-on-nil
* Merge refs/heads/master into return-error-on-nil
2020-09-30 23:23:22 +00:00
terence tsao
5178474280 Check err for filterAttestationsForBlockInclusion (#7398)
* Check err for
* Merge refs/heads/master into check-err
2020-09-30 22:45:17 +00:00
terence tsao
d5caee35fa Update min genesis time for Zinken (#7395)
* Update min genesis time
* Merge refs/heads/master into update-zinken-config
2020-09-30 22:09:23 +00:00
bidlocode
558ee2678b Optional services flags (#7358)
* add DisableMonitoringFlag(--disable-monitoring) to validator
* add EnableRPCFlag(--rpc) to validator (now rpc and grpc-gateway disabled by default)
* add DisableMonitoringFlag(--disable-monitoring) to slasher
* Merge branch 'master' of https://github.com/prysmaticlabs/prysm into optional-services-flags
* Merge branch 'master' of https://github.com/prysmaticlabs/prysm into optional-services-flags
* Merge branch 'master' into optional-services-flags
2020-09-30 20:55:56 +00:00
Raul Jordan
e1f8a37710 Import Accounts RPC Implementation (#7389)
* implement the import function

* begin tests for import keystores and add preconditions

* import implementation done

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-09-30 14:03:54 -05:00
terence tsao
e07b71b81d Add Zinken config (#7391) 2020-09-30 11:19:05 -07:00
Victor Farazdagi
db92d90309 Removes unused validator flags (#7388)
* removes unused validator flags
* Merge branch 'master' into remove-unused-validator-flags
2020-09-30 16:55:18 +00:00
terence tsao
e2eb2fb0d8 Ensure genesis state retrieval doesn't use zero hashes root (#7378)
* Cover genesis zero hashes case
* Merge branch 'master' into genesis-zero-hashes
* Cover an edge case pre genesis with fresh db
* Move state by root outside of the if
* Merge refs/heads/master into genesis-zero-hashes
* Clarify comments on why zero hashes used
* Merge branch 'genesis-zero-hashes' of github.com:prysmaticlabs/prysm into genesis-zero-hashes
* Merge refs/heads/master into genesis-zero-hashes
* Merge refs/heads/master into genesis-zero-hashes
* Merge refs/heads/master into genesis-zero-hashes
2020-09-30 15:41:09 +00:00
Shay Zluf
953960c860 Add slasher support for different testnets (#7385)
* Add slasher support for different testnets
* Merge branch 'master' into slasher_testnet_support
2020-09-30 15:08:03 +00:00
dv8silencer
7664eab32d Introduce checks for existing wallets into two edge cases (#7349)
* Add check for preexisting wallet

* Reminder

* Create another check.  Adjust tests

* Wording in comment

* Remove unnecessary logic.  Add another regression test.

* Spacing

* Prepare to merge master

* Refactor wallet checks

* Fixed test

* Revert back to original location of check

* Fix test

* Fix test

* Address linter feedback

* Align CreateWallet() with recent changes

* Align RecoverWallet with recent changes

* Correct test error message

* Refactor test to minimize duplication

* rename to isValid and adjust function code

* refactor

* Improve IsValid()

* Fix tests

* Remove comment

* Fix documentation of IsValid()

* Align behavior of OpenWalletOrElseCli

* Fix tests

* Realigning error msg with prior behavior

* Fix another test

* Correct logic

* small change in logic

* Fix err messages

* Create consts for repeated strings

* Add comments to new constants

* gofmt

* Adjust WalletConfig behavior so it is closer to prior-to-PR.  Adjust test accordingly

* adjust error messages

Co-authored-by: dv8silencer <15720668+dv8silencer@users.noreply.github.com>
2020-09-30 16:13:37 +02:00
Raul Jordan
16cdcf5dec Remove Deposit Command from Validator Client (#7379)
* remove deposit code
* Merge refs/heads/master into remove-deposit
2020-09-30 06:42:16 +00:00
Nishant Das
3b5ef50733 Fix Finalized Epoch Checks (#7364)
* fix up epoch checks

* build

* comp tests

* preston's comment
2020-09-30 08:25:25 +08:00
George Carder
529554f3f9 accommodate systems that use sha256sum (#7370)
* accommodate systems that use sha256sum
* cleaner use of checkSum
* Merge branch 'master' into shell_script_support4_sha256sum
* Merge branch 'master' into shell_script_support4_sha256sum
2020-09-29 12:22:35 +00:00
Radosław Kapka
fe9921457c Fix failing static analyzer tests (#7363)
* add "want" expectations
* add build step with analyzer tests
* add colon to yml
* Merge refs/heads/master into fix-analyzer-test-expectations
* Merge refs/heads/master into fix-analyzer-test-expectations
* Merge refs/heads/master into fix-analyzer-test-expectations
* Merge refs/heads/master into fix-analyzer-test-expectations
* remove tests from CI
* readme file
* change header size
2020-09-29 11:29:40 +00:00
terence tsao
bedb16cfb0 Update badge to v0.12.3 (#7367)
* Update badge to v0.12.3
* Merge refs/heads/master into terencechain-patch-1
* Merge refs/heads/master into terencechain-patch-1
2020-09-29 06:10:11 +00:00
Preston Van Loon
0921c00094 Remove processSlots from slashing check (#7357)
* Remove processSlots from slashing check

* imports

* imports

* PR feedback from @nisdas

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-09-29 13:22:55 +08:00
Raul Jordan
6ef4995329 Remaining Proto Definitions for Validator RPC Methods (#7368)
* import, delete, backup, and create acct
* Merge branch 'master' into rpc-changes
* impl methods
* Merge branch 'rpc-changes' of github.com:prysmaticlabs/prysm into rpc-changes
* wallet import comment
2020-09-29 01:58:14 +00:00
Victor Farazdagi
1e0b4e150e Fixes NotNil assertion (#7365)
* fixes NotNil assertion
* cover case of basic types
* removes redundant line
* Update TestStore_UpdateCheckpointState
* fixes TestPruneHistoryBlkHdr
2020-09-28 21:32:58 +00:00
Radosław Kapka
951c139cff Fix URL to voluntary exit documentation (#7361)
* fix documentation URL
2020-09-27 22:12:28 +00:00
terence tsao
eb3e4944e9 Ensure block root is non zeros for setting head before genesis (#7359)
* Ensure block root is non zeros for setting head
* Merge branch 'master' into can-set-head-genesis
* Merge refs/heads/master into can-set-head-genesis
2020-09-27 21:09:08 +00:00
terence tsao
bb98046608 Fix ListValidators inactive check (#7354)
* Fix ListValidators inactive check
* Updated an existing test
* Merge refs/heads/master into fix-list-validators
2020-09-27 20:30:03 +00:00
Eduard Klementiev
4ac0bbca19 gRPC load balancing (#7133)
* gRPC load balancing
* Fix typo
* Merge branch 'master' into 5132-gRPC-client-load-balancing
* Add doc about load balancer
* Update validator/client/multiple_endpoints_grpc_resolver.go
* Merge branch 'master' into 5132-gRPC-client-load-balancing
* gofmt
* Merge branch 'master' into 5132-gRPC-client-load-balancing
* Merge branch 'master' into 5132-gRPC-client-load-balancing
2020-09-27 18:08:28 +00:00
dv8silencer
c0c34f3d3a Fix panic that happens if you wallet-v2 recover 1 account (#7351)
* Bugfix
* Regression test.
* Remove unnecessary code.
* Merge branch 'master' into dv8-i7350
2020-09-26 10:13:56 +00:00
Nishant Das
77c95f3051 Add New Compiler Flags for BLST (#7352)
* add new c opts
* remove
* add to asm
* fix up benchamrks
* Merge refs/heads/master into addNewOpts
2020-09-26 08:48:02 +00:00
terence tsao
68d0c09daf Add, use and test VerifyWeakSubjectivityRoot (#7344)
* Add, use and test `VerifyWeakSubjectivityRoot`
* Comments
* Make bazel test happy
* Merge branch 'master' into verify-ws
* Add flag to help
* Merge branch 'verify-ws' of github.com:prysmaticlabs/prysm into verify-ws
* Merge refs/heads/master into verify-ws
* Merge refs/heads/master into verify-ws
* Merge refs/heads/master into verify-ws
* Merge branch 'master' of github.com:prysmaticlabs/prysm into verify-ws
* Update beacon-chain/blockchain/service.go

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
* Update beacon-chain/blockchain/weak_subjectivity_checks.go

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
* Merge branch 'verify-ws' of github.com:prysmaticlabs/prysm into verify-ws
* s/&&/|| for VerifyWeakSubjectivityRoot circuit breaker
* Merge refs/heads/master into verify-ws
* Merge refs/heads/master into verify-ws
2020-09-26 08:04:07 +00:00
Raul Jordan
282f3eec01 Display More Info for Validating Keys on Startup (#7347)
* display more info for wallet
* Merge refs/heads/master into display-info-for-keys
2020-09-25 20:43:12 +00:00
Raul Jordan
4a549ffe2b Warn About Deprecation of Accounts-V1 Within the Next 2 Releases (#7348)
* deprecation of accounts v1 error log
2020-09-25 18:24:31 +00:00
Nishant Das
d138c608bc Disable Libp2p Protocols (#7345)
* disable
2020-09-25 12:33:28 +00:00
Nishant Das
c7ff3a4f22 Better Chainstart Logging (#7336)
* better chainstart logging
* single threaded
* Merge branch 'master' into betterChainstartLogging
* Merge refs/heads/master into betterChainstartLogging
* Merge refs/heads/master into betterChainstartLogging
* Merge refs/heads/master into betterChainstartLogging
* Merge refs/heads/master into betterChainstartLogging
* Merge refs/heads/master into betterChainstartLogging
* Merge refs/heads/master into betterChainstartLogging
* Merge refs/heads/master into betterChainstartLogging
* improve formatting
2020-09-25 04:31:23 +00:00
Nishant Das
7a96412ef2 Reject Messages With Invalid Fields in GossipSub (#7337)
* strict no sign
* Merge branch 'master' into StrictNoSign
2020-09-24 23:53:15 +00:00
Raul Jordan
5821454ac7 Implement Wallet Config and HasWallet Endpoints (#7341)
* fix the wallet config implementation

* implemented wallet config endpoint and tests

* better error messages

* fix nil pointer

* more nil issues fix

* gazelle

* fix interceptor

* revise

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-09-24 15:37:59 -05:00
terence tsao
90978cd22e Reset hot state cache size to 32 (#7340)
* Reset hot state cache size to 32
* Merge refs/heads/master into revert-hot-state-cache-size
2020-09-24 18:10:02 +00:00
Raul Jordan
76a3070fd7 Fix Change Wallet Password Logic (#7324)
* fix change password logic
* gaz
* Merge refs/heads/master into change-password-fix
* Merge refs/heads/master into change-password-fix
* Merge refs/heads/master into change-password-fix
* Merge refs/heads/master into change-password-fix
* Merge refs/heads/master into change-password-fix
* Merge refs/heads/master into change-password-fix
* Merge refs/heads/master into change-password-fix
* Merge refs/heads/master into change-password-fix
* Merge refs/heads/master into change-password-fix
* Merge refs/heads/master into change-password-fix
2020-09-24 16:47:13 +00:00
terence tsao
1bc0cc7049 Skip duplicated aggregated attestation in pending queue (#7326)
* Skip duplicated aggregated atts
* Test
* Fixed a regression test
* Merge branch 'master' of github.com:prysmaticlabs/prysm into skip-dup-aggregator
* Go fmt
* Merge refs/heads/master into skip-dup-aggregator
2020-09-24 15:47:03 +00:00
terence tsao
ff69375fbd Revert 7242: Opt out --use-check-point-cache (#7338)
* revert bb37436
2020-09-24 15:03:35 +00:00
Victor Farazdagi
5b814009fa Improves test coverage of init-sync queue (#7320)
* basic invariants for all state transition handlers

* TestBlocksQueue_onCheckStaleEvent extended

* TestBlocksQueue_onScheduleEvent extended

* TestBlocksQueue_onDataReceivedEvent extended

* removes redundant ctx setting

* TestBlocksQueue_onReadyToSendEvent extended

* TestBlocksQueue_onProcessSkippedEvent extended

* test to highest slot update

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-09-24 21:39:46 +08:00
Radosław Kapka
99164761f5 Make voluntary exits release-ready (#7305)
* phrase validation utility
* use passphrase from docs portal
* enable voluntary exits
* Merge branch 'master' into enable-exits
* rename 'voluntary-exit' to 'exit'
* change passphrase
* gazelle
* change constant to error variable
* Merge branch 'master' into enable-exits
* rename error variable
* build fix
* Merge refs/heads/master into enable-exits
* do not remove whitespace in the middle
* Merge refs/heads/master into enable-exits
* Merge refs/heads/master into enable-exits
* Merge refs/heads/master into enable-exits
* Merge refs/heads/master into enable-exits
* code review changes
* Merge refs/heads/master into enable-exits
* Merge refs/heads/master into enable-exits
2020-09-24 11:00:44 +00:00
Radosław Kapka
e1cd9143e0 Package-level comments for static analyzers (#7332)
* package-level comments
* Merge refs/heads/master into analyzer-package-comments
2020-09-24 10:25:55 +00:00
Nishant Das
4d232feda8 Add Spadina Bootnodes (#7330)
* add spadina bootnodes
* add in bootnode
2020-09-24 09:49:24 +00:00
Nishant Das
d687270a89 Update BLST to Latest Commit (#7328)
* update blst
* Merge branch 'master' into updateBLST
2020-09-24 08:34:09 +00:00
Nishant Das
6d8207801c Update Bootnode With New Flags (#7327)
* update bootnode
* gaz
* Update BUILD.bazel
2020-09-24 07:02:36 +00:00
Preston Van Loon
6ad117b175 Return an error when any of the eth1 clients are nil (#7323)
* Return an error when any of the eth1 clients are nil
* return error if eth1DataFetcher is nil
* Annotate span
* gaz
* fix build and add tests
* dear linter, please accept this commit as tribute and let my PR pass
* Merge refs/heads/master into fix-7322
2020-09-23 23:16:06 +00:00
terence tsao
f9e062407f Fix an edge case when loading replay start state by slot (#7313)
* Ensure start state is the parent of the first block
* Regression test
* Merge branch 'master' into state-by-slot-state-state
* Add back the line
* Merge branch 'state-by-slot-state-state' of github.com:prysmaticlabs/prysm into state-by-slot-state-state
* Add a test for lower slot block condition
2020-09-23 21:39:16 +00:00
Radosław Kapka
dca93ce641 Unnecessary Slice-to-Slice Conversion analyzer (#7321)
* analyzer with tests
* fix bazel file
* modify analyzer to fix build issues
* add analyzer to tool chain
* remove arrays from inspections
* fix redundant [:] operator
* Merge branch 'master' into use-slice-directly
* Merge branch 'master' into use-slice-directly
* fix another inspection
* add package-level comment
2020-09-23 16:14:34 +00:00
Nishant Das
347aa14a28 Fix Bazel Reference For Go-Ethereum (#7318)
* fix api change
2020-09-23 10:20:08 +00:00
Victor Farazdagi
3621b2ff25 Better naming for constructor funcs (#7316)
* sync/initial-sync
* NewBeaconClientService -> NewService
* NewSlashingProtectionService -> NewService
* NewPrometheusService -> NewService
* NewColdStartService -> NewService
* NewRegularSync -> NewService
* NewDetectionService -> NewService
* NewWallet -> New
* NewKeystore -> New
* Merge branch 'master' into better-naming
* Merge branch 'master' into better-naming
* NewDepositCache -> New
2020-09-23 08:59:49 +00:00
Nishant Das
49ae42c249 Fix Validator For Spadina (#7314)
* fix commands
* Merge refs/heads/master into fixSpadina
2020-09-23 08:03:13 +00:00
Victor Farazdagi
1ce7cd5f50 Init sync: minor refactoring and more tests for Service (#7286)
* removes redundant code
* removes redundant code
* removes redundant db
* removes redundant p2p
* servive - test future genesis
* more tests for service.Start()
* service - already synced test
* Merge branch 'master' into init-sync-more-service-tests
* Merge branch 'master' into init-sync-more-service-tests
* NewInitialSync to New (avoid stutter)
* TestService_markSynced
* more assertions
* TestService_Resync
* renames test
* Merge branch 'master' into init-sync-more-service-tests
* Merge refs/heads/master into init-sync-more-service-tests
* Merge branch 'master' into init-sync-more-service-tests
* Merge refs/heads/master into init-sync-more-service-tests
* Merge branch 'master' into init-sync-more-service-tests
* fixes e2e test
* Merge branch 'init-sync-more-service-tests' of github.com:prysmaticlabs/prysm into init-sync-more-service-tests
* Merge refs/heads/master into init-sync-more-service-tests
* Merge refs/heads/master into init-sync-more-service-tests
* Merge refs/heads/master into init-sync-more-service-tests
* Merge refs/heads/master into init-sync-more-service-tests
* New -> NewInitialSync
2020-09-23 07:24:33 +00:00
terence tsao
305fdd2e1b Add spadina network name (#7309)
* Update spadina network name
* Merge refs/heads/master into update-config
* Merge refs/heads/master into update-config
* Merge refs/heads/master into update-config
* Merge refs/heads/master into update-config
2020-09-22 23:20:20 +00:00
terence tsao
984cb38680 Remove long deprecated historical regen states in DB (#7308)
* Remove long deprecated db state gen
* Remove long deprecated db state gen
* gazelle
* Delete pass through
* Merge refs/heads/master into rm-deprecated-regen
* Merge refs/heads/master into rm-deprecated-regen
* Merge refs/heads/master into rm-deprecated-regen
2020-09-22 22:57:50 +00:00
terence tsao
bbdd20e898 Log grpc error chain (#7307)
* Log error chain
* Merge refs/heads/master into error-msgs
* Merge refs/heads/master into error-msgs
2020-09-22 22:23:01 +00:00
Victor Farazdagi
568cd3c9ec Fixes e2e "chain started" check (#7311)
* fixes e2e test
2020-09-22 21:34:38 +00:00
Raul Jordan
b09b1f3fa5 Disallow Creation of Multiple Wallets at Wallet Path (#7290)
* disallow multiple wallet creation
* imports
* Merge branch 'master' into disallow-multiple-wallets
* resolve conflicting test
* Merge branch 'disallow-multiple-wallets' of github.com:prysmaticlabs/prysm into disallow-multiple-wallets
* test passes
* Merge refs/heads/master into disallow-multiple-wallets
* Merge refs/heads/master into disallow-multiple-wallets
* Merge refs/heads/master into disallow-multiple-wallets
* Merge refs/heads/master into disallow-multiple-wallets
* Merge refs/heads/master into disallow-multiple-wallets
* Merge refs/heads/master into disallow-multiple-wallets
* radek feedback
* Merge branch 'master' into disallow-multiple-wallets
2020-09-22 19:02:13 +00:00
Nishant Das
22bcfd2c34 Update Message ID (#7304)
* shorten message id
* Merge refs/heads/master into updateMessageID
* Merge refs/heads/master into updateMessageID
2020-09-22 15:23:33 +00:00
Raul Jordan
ba440abe2d Store Hashed Password to Wallet Path (#7295)
* store wallet pass on creation
* store wallet hash
* save hash to wallet dir
* initialize wallet hash
* gaz
* imports spacing
* remove mentions of hashed pass from db schema
* simplify the wallet hash code
* comment removal
* Merge branch 'master' into fix-password-override
* pass tests
* test fix
* Merge branch 'fix-password-override' of github.com:prysmaticlabs/prysm into fix-password-override
* remove extraneous printfs
* tests passing
* require auth for create wallet
* gaz
* fix signup logic
* Merge refs/heads/master into fix-password-override
* Merge refs/heads/master into fix-password-override
* Merge refs/heads/master into fix-password-override
* Merge refs/heads/master into fix-password-override
* Merge branch 'master' into fix-password-override
2020-09-22 14:49:07 +00:00
Nishant Das
09640ae22d Update Go-Ethereum Fork (#7303)
* update
* tidy
* Merge refs/heads/master into updateGeth
* remove metaData
* remove cloudflare
* Revert "remove cloudflare"

This reverts commit 687210f70f.
2020-09-22 13:23:45 +00:00
Nishant Das
719e99ffd9 Replace Roughtime With Timeutils Across Prysm (#7301)
* remove roughtime

* change all references

* rename

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-09-22 19:49:58 +08:00
Shay Zluf
1a4129f5a6 Fix prompt default handling (#7300)
* Fix prompt default handling
* Merge branch 'master' of github.com:prysmaticlabs/prysm into default_handling
* added test
* Merge branch 'master' of github.com:prysmaticlabs/prysm into default_handling
* Merge branch 'master' of github.com:prysmaticlabs/prysm into default_handling
2020-09-22 06:35:15 +00:00
Nishant Das
de3f112a05 Remove Roughtime Usage From Prysm (#7299)
* remove roughtime
* Merge branch 'master' into removeRoughtime
* Merge refs/heads/master into removeRoughtime
2020-09-22 05:47:01 +00:00
terence tsao
3734bfacce Add target epoch and slot consistency check (#7288)
* Add target epoch and slot consistency
* Remove debug logs
* Merge refs/heads/master into att-epoch-consistency
* Merge refs/heads/master into att-epoch-consistency
* Merge refs/heads/master into att-epoch-consistency
2020-09-22 05:13:12 +00:00
Shay Zluf
d5e2b51d66 Add slasher grpc logs (#7289)
* Add grpc logs
* gaz
* Merge refs/heads/master into add-connection-error-handling
* try to restart connection on status unavailable
* Merge branch 'add-connection-error-handling' of github.com:prysmaticlabs/prysm into add-connection-error-handling
* add retry on dial
* goimports
* Merge refs/heads/master into add-connection-error-handling
* gaz
* Merge branch 'add-connection-error-handling' of github.com:prysmaticlabs/prysm into add-connection-error-handling
* Merge branch 'master' of github.com:prysmaticlabs/prysm into add-connection-error-handling
2020-09-22 04:39:34 +00:00
terence tsao
cdd28abc4b Remove renovate.json (#7291)
* Remove renovate.json
* Merge refs/heads/master into rm-renovate
2020-09-21 22:54:24 +00:00
Preston Van Loon
8c8f59e242 Fix sha after v0.12.3 tarballs were re-uploaded. Unskip test to resolve #7277. (#7292)
* Fix sha after v0.12.3 tarballs were re-uploaded. Unskip test to resolve #7277.
2020-09-21 22:22:19 +00:00
Raul Jordan
b1f9f97062 Implement ChangeWalletPassword API Endpoint (#7273)
* allow changing wallet password

* wallet change password logic

* tests for wallet password changes

* more unit tests

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-09-21 14:44:43 -05:00
Victor Farazdagi
7545d3f2b3 Init sync refactor state initialization check + tests (#7285)
* refactor state initialization into waitForStateInitialization
* more tests
* redundant blank line
* Merge branch 'master' into init-sync-refactor-state-init
* moves comment up
* Nishant's suggestions + bit more refactoring
* Explicitly process error (Nishant's suggestion)
2020-09-21 12:20:26 +00:00
dv8silencer
bdf8bf7be2 Fix accounts-v2 backup so that it can backup HD wallet accounts (#7284)
* Bugfix

* Added test
2020-09-21 10:50:05 +02:00
terence tsao
b928e9531c Two more gossip validations for unaggregated atts subnet (#7278)
* Add two more gossip validations for unaggregated attestations

* Removed a typo log

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-09-20 08:31:10 +08:00
terence tsao
1f6afa8547 Add config PROPORTIONAL_SLASHING_MULTIPLIER (#7275)
* Add config
* Merge refs/heads/master into prop-slashing-mul
* Fixed a typo reported by Radek
* Merge branch 'prop-slashing-mul' of github.com:prysmaticlabs/prysm into prop-slashing-mul
2020-09-19 22:04:24 +00:00
terence tsao
303edbde58 Update spec tests to v0.12.3 (#7276)
* Update urls
* Update sha tags
* Fix paths
* Delete removed test
* Skipping  with an issue
2020-09-19 18:00:28 +00:00
dv8silencer
208ea56a9c Improve error message when creating a wallet in place of one that already exists (#7268)
* Tell user if content already exists at wallet create destination
* Added test
* changed wording
* capitalization
* Merge branch 'master' into dv8-i7264
* Merge branch 'master' into dv8-i7264
* Address PR comments

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

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

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

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

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
* Minor fix
* Improve test by addressing PR feedback.  Change variable name
* address PR comments
2020-09-18 21:01:46 +00:00
Victor Farazdagi
c8b91ba7b0 Attestation proposing: more tests (#7267)
* refactors test
* Merge branch 'master' into optimize-proposals
* more filtering and sorting proposer atts
* Merge branch 'master' into optimize-att-proposer
* Merge branch 'master' into optimize-att-proposer
* revert
* Terence's suggestion on naming
2020-09-18 17:16:31 +00:00
terence tsao
268df90ddd Update weak subjectivity check point computation (#7251) 2020-09-18 08:06:00 -07:00
Nishant Das
749aba8d09 Fix Blst Signature Copy Test (#7272)
* fix signature test
* Merge branch 'master' into fixLastTest
2020-09-18 12:04:39 +00:00
Shay Zluf
7920afb12e Add missing error handling in slasher (#7270)
* Add missing error handling in slasher
* Merge branch 'master' into missing_error
* Merge refs/heads/master into missing_error
2020-09-18 10:09:29 +00:00
Radosław Kapka
cc147c7097 Align eth1data Majority Vote with the spec (#7200)
* align voting with the spec
* Merge branch 'master' into eth1vote-spec-align
* remove redundant else statements
* add comment to exported variable
* Merge refs/heads/master into eth1vote-spec-align
* Merge refs/heads/master into eth1vote-spec-align
* Merge refs/heads/master into eth1vote-spec-align
* Merge refs/heads/master into eth1vote-spec-align
* Merge refs/heads/master into eth1vote-spec-align
* Merge refs/heads/master into eth1vote-spec-align
* Merge refs/heads/master into eth1vote-spec-align
* Merge refs/heads/master into eth1vote-spec-align
* Merge refs/heads/master into eth1vote-spec-align
* Merge refs/heads/master into eth1vote-spec-align
* Merge refs/heads/master into eth1vote-spec-align
* Merge refs/heads/master into eth1vote-spec-align
* Merge refs/heads/master into eth1vote-spec-align
* Merge refs/heads/master into eth1vote-spec-align
* Merge refs/heads/master into eth1vote-spec-align
* Merge refs/heads/master into eth1vote-spec-align
* Merge branch 'master' into eth1vote-spec-align

# Conflicts:
#	beacon-chain/rpc/validator/proposer_test.go
* refactor tests
* Merge refs/heads/master into eth1vote-spec-align
* Merge refs/heads/master into eth1vote-spec-align
* Merge refs/heads/master into eth1vote-spec-align
* Merge refs/heads/master into eth1vote-spec-align
* Merge refs/heads/master into eth1vote-spec-align
* Merge refs/heads/master into eth1vote-spec-align
* Merge refs/heads/master into eth1vote-spec-align
* Merge refs/heads/master into eth1vote-spec-align
* Merge refs/heads/master into eth1vote-spec-align
* Merge refs/heads/master into eth1vote-spec-align
* Merge refs/heads/master into eth1vote-spec-align
* Merge refs/heads/master into eth1vote-spec-align
* Merge refs/heads/master into eth1vote-spec-align
* Merge refs/heads/master into eth1vote-spec-align
* Merge refs/heads/master into eth1vote-spec-align
* fix mock POWChain
* move last block's time check and add more test cases
* Merge refs/heads/master into eth1vote-spec-align
* Merge refs/heads/master into eth1vote-spec-align
* Merge refs/heads/master into eth1vote-spec-align
* Merge refs/heads/master into eth1vote-spec-align
* Merge refs/heads/master into eth1vote-spec-align
* Merge refs/heads/master into eth1vote-spec-align
* Merge refs/heads/master into eth1vote-spec-align
2020-09-18 09:46:31 +00:00
Preston Van Loon
852082cdb4 Check that the headers are equal while ignoring the signature for proposer slashings (#7252)
* Check that the headers are equal while ignoring the signature for proposer slashings. Resolves https://github.com/sigp/beacon-fuzz/issues/74

* fix test

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-09-18 17:10:14 +08:00
Preston Van Loon
e927a3d170 Streaming logs: add backfill of messages for new connections" (#7265)
* add backfill of logs

* Add test and gofmt
2020-09-17 19:34:03 -05:00
Raul Jordan
7c2096f209 Websocket Connection Fixes (#7263)
* socket improvements
* Merge branch 'master' into socket-fix
* Merge refs/heads/master into socket-fix
2020-09-17 19:55:34 +00:00
terence tsao
dcdf5d0eac Add and verify weak-subjectivity-checkpoint flag (#7256)
* Handle weak subjectivity input

* Typo

* Feedbacks

* Better error string @rauljordan

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-09-17 14:32:40 -05:00
terence tsao
3db6784990 Update Spadina fork version to 0x02 (#7261)
* Update Spadina fork version to 0x02
2020-09-17 18:50:01 +00:00
terence tsao
d51ead76eb Implement and test GetWeakSubjectivityCheckpoint (#7216)
* Implement and test GetWeakSubjectivityCheckpoint

* Go mod tidy

* Add mock

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-09-17 12:50:31 -05:00
Radosław Kapka
a2cf235687 No-op Instruction analyzer (#7249)
* analyzer, tests and fixes
* error check
* gazelle
* add more asserts
* Merge branch 'master' into nop-analyzer
* Merge refs/heads/master into nop-analyzer
* fix no-op in blst package
* Merge refs/heads/master into nop-analyzer
* add assert after mutation
* mark test as TODO
* add issue number to TODO
2020-09-17 16:18:19 +00:00
Victor Farazdagi
e1e233a6d0 Fix gazelle warning when fuzzing_enabled is not provided (#7260)
* adds fuzzing_enabled configurable files to gazelle ignore list
* more fine grained
2020-09-17 12:58:03 +00:00
Victor Farazdagi
76bac74562 Disables resync when init-sync is disabled (#7259)
* disables resync when init-sync is disabled
2020-09-17 11:42:57 +00:00
Nishant Das
a335bbbb61 Add Flag To Disable Initial Sync (#7258)
* add new flag
* terence's review
2020-09-17 06:11:21 +00:00
Nishant Das
913e4aa538 Fix IPV6 Address Retrieval (#7257)
* fix
2020-09-17 03:02:20 +00:00
Raul Jordan
4b4641bae3 Restructure Prysm Wallet V2 Package to Prevent Import Cycles (#7247)
* fix up tests

* fix test build

* tests pass

* imports and remove shadowing

* lint

* visibility

* lint fix

* wallet init

* remove v22

* fix imports

* fixed broken password test

* Update validator/accounts/v2/wallet_create.go

Co-authored-by: Ivan Martinez <ivanthegreatdev@gmail.com>

* Update validator/rpc/server.go

Co-authored-by: Ivan Martinez <ivanthegreatdev@gmail.com>

* Update validator/node/node.go

Co-authored-by: Ivan Martinez <ivanthegreatdev@gmail.com>

* fmt

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
Co-authored-by: Ivan Martinez <ivanthegreatdev@gmail.com>
2020-09-16 20:34:42 -05:00
Raul Jordan
6bfb2b1e46 Use Bufio Large Buffer Instead of Scanner for Large Files in E2E (#7254)
* use readline
* Fix
* max file buffer size
2020-09-16 23:41:41 +00:00
dv8silencer
a97de0d474 Use passphrase for HD-wallets (#7222)
* Use wallet password
* Fix test
* Address another test
* Address linter's feedback.
* Merge branch 'master' into dv8-i7213
* Merge branch 'master' into dv8-i7213
* Delete temp file
* Merge branch 'master' into dv8-i7213
* Merge branch 'master' into dv8-i7213
* Merge branch 'master' into dv8-i7213
* Merge branch 'dv8-i7213' of https://github.com/dv8silencer/prysm into dv8-i7213
* Merge branch 'master' into dv8-i7213
* Add regression test.
* Skip mnemonic confirmation
* Merge branch 'master' into dv8-i7213
* Merge branch 'master' into dv8-i7213
* Merge branch 'master' into dv8-i7213
* Merge branch 'master' into dv8-i7213
2020-09-16 20:12:16 +00:00
terence tsao
f6d3c28ae1 Save cached blocks before Stop() in blockchains service (#7245)
* Save cached blocks before Stop()
* Merge refs/heads/master into save-cached-blocks
* Merge refs/heads/master into save-cached-blocks
* Merge refs/heads/master into save-cached-blocks
* Merge refs/heads/master into save-cached-blocks
* Merge refs/heads/master into save-cached-blocks
* Regression test
* Merge branch 'save-cached-blocks' of github.com:prysmaticlabs/prysm into save-cached-blocks
2020-09-16 16:55:14 +00:00
Raul Jordan
3197748240 Streaming Logs via Websocket Server (#7240)
* Log streaming proof of concept

* fix broken imports

* imports

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-09-16 09:03:52 -05:00
Preston Van Loon
14dbc2b74d Add blst for BLS (#6539)
* Add blst third party dep

* initial build

* add init

* blst passing tests

* add feature flag

* blst and herumi for spec tests

* maybe this works for mac

* Actually set feature flag

* Add stub for VerifyMultipleSignatures for blst

* verifyCompressed

* use correct cores sizes

* aggregate public keys

* add multi-sig verification

* encode not hash

* revert back

* go mod tidy

* update blst to latest commit

* add batch decompress

* fix

* add test

* gofmt

* update blst

* go mod tidy

* remove kubesec, fix

* mod tidy

* disable some remote cache

* disable some remote cache

* disable some remote cache

* disable some remote cache

* Switch to -D__ADX__

* update

* tidy

* fix build

* Make blst for only linux,amd64

* gofmt

* lint

* lint

* gazelle

* fix build tag

* more stub methods

* shift adx instructions to x86

* fix arm64

* Revert "fix arm64"

This reverts commit 4d34ac21b7.

* add one more in

* Revert "Revert "fix arm64""

This reverts commit 1c8ae24ad1.

* try darwin now

* Revert "try darwin now"

This reverts commit 6f884714b8.

* Add sha256

* remove TODO

* checkpoint

* finally builds

* fix up

* add tag

* try again

* explicit disabling

* remove

* select properly

* fix

* better

* make CI happy too

* Update .bazelrc

* Update .bazelrc

* fix tests

* revert back

* Update shared/bls/blst/public_key.go

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

* Update shared/bls/blst/public_key.go

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

* clean up tests

* more clean up

* clean up

* add

* Update shared/bls/blst/signature.go

* Update shared/bls/blst/signature.go

* Update .buildkite-bazelrc

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

* try again

* remove go tag

* revert change

* gaz

* gazelle ignore

Co-authored-by: nisdas <nishdas93@gmail.com>
Co-authored-by: Victor Farazdagi <simple.square@gmail.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-09-16 21:28:28 +08:00
terence tsao
b0917db4c7 Core pkg: properly return errs (#7246)
* Return errs instead of nils

* Update a few more tests

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-09-15 22:55:57 -05:00
terence tsao
ee4ebe4c38 Opt out batch verify (#7244) 2020-09-15 18:53:51 -07:00
Nishant Das
56d6e05196 QSP-16 Fix Support for IPv6 (#6363)
* checkpoint changes

* new changes

* comment

* clean up

* set

* fix

* fix more

* more stuff

* clean up

* clean up

* remove

* clean up

* clean up

* comment

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-09-16 08:17:22 +08:00
terence tsao
bb374362e4 Opt out --use-check-point-cache (#7242)
* Make check point info cache an opt-out
* Typo
* Merge branch 'master' of github.com:prysmaticlabs/prysm into cp-cache-opt-out
2020-09-15 17:14:04 +00:00
dv8silencer
c1114fa6be Fix issue with direct wallet's password being overwritten by incorrect password during import. (#7212)
* Maintain working password instead of overwriting it.

* Check for error first

* fix test

* Address linter

* TEMP, INCOMPLETE;  Working on regression test

* WORK IN PROGRESS - changed promptutil to create a mock password reader

* Test working now

* Address testing bugs

* Spacing

* Comments.  Fixed counter bug.

* gazelle fix

Co-authored-by: dv8silencer <15720668+dv8silencer@users.noreply.github.com>
2020-09-15 09:52:07 -05:00
terence tsao
36c921c601 Add spadina config (#7235) 2020-09-14 21:21:46 -07:00
dv8silencer
f31f49582b Fix accounts-v2 deposit and related bugs (#7219) 2020-09-14 16:04:22 -07:00
Preston Van Loon
cebb62997d Add beacon state unmarshal fuzzer, afl support (#6625)
* Add AFL third_party libraries

* add beacon state fuzzing, add afl fuzz bundle

* rm fuzzing engine

* fix and lint

* Check for array out of bounds when calculating proposer delta

* failing test

* fix

* Checkpoint progress

* Add requirement that inclusion distance is not zero, add regression test

* No need for HTR since that is covered in process slots

* Removing some fuzzit logic, old fuzz tests

* Add ssz encoder test and fix

* Fuzzing checkpoint, adding fuzzing to the p2p layer

* ignore some libfuzzer files

* Full testing of p2p processing of blocks, with some mocked stuff

* use tmpdir and always process blocks

* use checkptr

* Update ethereumapis

* go mod tidy

* benchmarks for ferran's fast ssz hash tree root

* Update fastssz

* fmt

* gaz

* goimports

* Fix

* fix ethereumapis

* fix again

* kafka

* fix gen file

* fix compute signing root

* gofmt

* checkpoint progress

* progress

* checkpoint

* updates

* updates

* merge fix

* WIP

* merge

* fix build

* fix merge related issues

* cleanup

* revert unrelated

* lint

* lint

* lint

* manual tags for fuzz

* Commentary on upload script

* some import fixes, but not all

* fix //fuzz:fuzz_tests

* rm unused test

* update generated ssz

* Set // +build libfuzzer

* remove debug code

* A bit of refactoring ot explain why there is a committee_disabled file

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-09-14 11:42:08 -07:00
Victor Farazdagi
e477df321c Updates proposer tests namings (#7234)
* adds proposer_ namespacing
* remove redundant string
* Merge branch 'master' into proposer-test-fix-naming
* Merge refs/heads/master into proposer-test-fix-naming
2020-09-14 12:55:20 +00:00
Radosław Kapka
828156b9d4 fix exit comment (#7233)
* fix exit comment
* Merge branch 'master' into fix-exit-comment
* Merge refs/heads/master into fix-exit-comment
2020-09-14 11:44:50 +00:00
Radosław Kapka
aaa3abf630 Shadowed Predeclared Indentifier analyzer (#7215)
* wip

* working for some ast nodes

* works for all but assignment

* works for all but mixed assignments

* change test name

* plug in the analyzer

* remove `copy` from predeclared list

* rename few shadowing names

* rename `len` to `length`

* add one more test case

* rename `panic` to `panicResult`

* replace `panic` with `panicResult` in error message

* remove test case not covered by the tool

* add `byte` to predeclared list

* additional test cases

* rename `copy` to `copyHandler`

* exclude functions with receivers

* revert to good names

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-09-14 12:49:15 +02:00
terence tsao
e1aa920fc6 Fix out of bound check in AncestorRoot (#7226)
* Move out of bound check to the correct scope
* Merge refs/heads/master into store-out-of-bound
2020-09-14 09:10:52 +00:00
Shay Zluf
fcfd828725 Local protection proposal schema update (#7197)
* Local protection schema update
* Merge branch 'master' of github.com:prysmaticlabs/prysm into proposal_protection_schema_update
* fix interface issue
* fix lint
* gaz
* Merge refs/heads/master into proposal_protection_schema_update
* Merge refs/heads/master into proposal_protection_schema_update
* Merge refs/heads/master into proposal_protection_schema_update
* Merge refs/heads/master into proposal_protection_schema_update
* Merge refs/heads/master into proposal_protection_schema_update
* Merge refs/heads/master into proposal_protection_schema_update
* Merge refs/heads/master into proposal_protection_schema_update
* Merge refs/heads/master into proposal_protection_schema_update
* Merge refs/heads/master into proposal_protection_schema_update
* Merge refs/heads/master into proposal_protection_schema_update
* Merge refs/heads/master into proposal_protection_schema_update
* Update validator/db/kv/new_proposal_history_test.go
2020-09-14 01:55:33 +00:00
terence tsao
3374a06f63 Skip initial roughtime result when EnableRoughtime is disabled (#7221) 2020-09-13 08:53:14 -07:00
Jim McDonald
0b497e57e4 Reverse error condition. (#7217)
* Reverse error condition.
2020-09-11 20:21:50 +00:00
Shay Zluf
af46fc7707 Fix propose protect error handling (#7188)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-09-11 09:53:53 -05:00
Radosław Kapka
b1e2238df9 Invert enable-finalized-deposits-cache (#7214)
* make flag opt-out
2020-09-11 09:49:24 +00:00
Shay Zluf
acddb6035a Fix rename issue (#7205)
* Fix rename issue

* nishant feedback

* add test

* Update shared/fileutil/fileutil.go

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

* preston feedback

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-09-11 00:56:58 +03:00
terence tsao
3147a5ee01 Check attestation slot before broadcast (#7209) 2020-09-10 13:16:35 -07:00
Victor Farazdagi
572227d25e Removes attestation pool pruning from UnaggregatedAttestations getter (#7204)
* removes att pool changing in getter
* test
* add prunning
* Merge refs/heads/master into no-pruning-in-unagg-att-getter
* Merge refs/heads/master into no-pruning-in-unagg-att-getter
* Merge refs/heads/master into no-pruning-in-unagg-att-getter
* Merge refs/heads/master into no-pruning-in-unagg-att-getter
2020-09-10 18:35:57 +00:00
terence tsao
84273e9a34 Implement helper method WeakSubjectivityCheckptEpoch (#7201)
* Implement and test WeakSubjectivityCheckptEpoch
* Merge refs/heads/master into get-wss
* Merge refs/heads/master into get-wss
* Merge refs/heads/master into get-wss
* Merge refs/heads/master into get-wss
* Update beacon-chain/core/helpers/slot_epoch.go

Co-authored-by: Victor Farazdagi <simple.square@gmail.com>
2020-09-10 17:37:52 +00:00
Victor Farazdagi
114fac5149 Att aggregator filter by slot and index (#7206)
* Adds AggregateUnaggregatedAttestationsBySlotIndex method
* tests
* filter attestations by slot/index for aggregator to process
* Merge branch 'master' into att-aggregator-filter-by-slot-and-index
* Merge refs/heads/master into att-aggregator-filter-by-slot-and-index
* Merge refs/heads/master into att-aggregator-filter-by-slot-and-index
2020-09-10 15:55:45 +00:00
Victor Farazdagi
2d9fe5f2cf Disallows bitlist duplicates in seen_bits cache (#7203)
* disallows bitlist duplicates in seen_bits cache
* Merge refs/heads/master into upd-has-seen
2020-09-10 15:24:23 +00:00
Radosław Kapka
6daf45cb8f Correct accounts and validator error messages (#7207)
* incorrect account password
* misleading exit error
2020-09-10 14:49:13 +00:00
terence tsao
c8e93f8789 Verify indices in no verify method (#7199) 2020-09-09 13:38:19 -07:00
Radosław Kapka
94fa046ce1 Voluntary exit CLI/Client integration (#7162)
* rewrite of ProposeExit

# Conflicts:
#	validator/accounts/v2/accounts_exit.go

* translate todos to English

* use node client to calculate current epoch

* resolve dependency cycle

* add missing dependencies

* changed required epochs error message

* fix ProposeExit tests

* remove unused metrics

* simplify public-keys flag name

* organize CLI function

* fix incorrect list of exited keys

* fix formatting of non-exited keys

* add exit root to span attributes

* use errors instead of logs

* log info when all exits failed

* do not log stack trace for non-critical errors

* modify test asserts

* use standard way of displaying errors

* remove todo

* add missing function to wallet mock

* gazelle

* gazelle after stash

* move creating clients to separate function

* gazelle
2020-09-09 13:29:17 -05:00
Preston Van Loon
a74cf5de90 Replace context.Background() with more appropriate context (#7136)
* Replace context.Background() with more appropriate context
* replace a few context.TODO
* Merge refs/heads/master into fix-ctx
* Update validator/accounts/v2/accounts_create.go

Co-authored-by: terence tsao <terence@prysmaticlabs.com>
* Fix tests
* fix stream tests
* gofmt
* Merge refs/heads/master into fix-ctx
* Merge refs/heads/master into fix-ctx
* Merge refs/heads/master into fix-ctx
* Merge refs/heads/master into fix-ctx
* Merge refs/heads/master into fix-ctx
* Merge refs/heads/master into fix-ctx
* Merge refs/heads/master into fix-ctx
* Merge refs/heads/master into fix-ctx
* fix conflicts and remove ctx background uses
* fix broken test
* Merge branch 'master' into fix-ctx
* imports
* Merge branch 'fix-ctx' of github.com:prysmaticlabs/prysm into fix-ctx
* Merge refs/heads/master into fix-ctx
* Merge refs/heads/master into fix-ctx
* fix conflicts
* Merge refs/heads/master into fix-ctx
* fmt
* Merge refs/heads/master into fix-ctx
* Merge refs/heads/master into fix-ctx
* Merge refs/heads/master into fix-ctx
* Merge refs/heads/master into fix-ctx
* Merge refs/heads/master into fix-ctx
* fixes tests
2020-09-09 09:48:52 +00:00
Raul Jordan
6d83770534 Fix Small Issue in Validator RPC Health Endpoint (#7195)
* amend node connection response
* imports
* fix err
* fix conf
* err
* test fix
* Merge branch 'master' into fix-health-endpoint
2020-09-08 22:35:31 +00:00
terence tsao
593442a0fa Fix span names in transition.go (#7192)
* Fix span names

* Go fmt

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-09-08 14:36:02 -07:00
Raul Jordan
bd46abc71d Add Chain Genesis Info to Node Connection Response (#7194)
* amend node connection response
* imports
2020-09-08 20:54:56 +00:00
Raul Jordan
cb1f44872d Fix Health Reporting for Validator Client Node Connection (#7181)
* fix health reporting
* import
* Merge refs/heads/master into fix-health
* account test
* Merge branch 'fix-health' of github.com:prysmaticlabs/prysm into fix-health
* Merge refs/heads/master into fix-health
* Merge refs/heads/master into fix-health
* Merge refs/heads/master into fix-health
* Merge refs/heads/master into fix-health
* Merge branch 'fix-health' of github.com:prysmaticlabs/prysm into fix-health
* Merge refs/heads/master into fix-health
* Merge branch 'fix-health' of github.com:prysmaticlabs/prysm into fix-health
* Merge refs/heads/master into fix-health
* fmt
* Merge refs/heads/master into fix-health
2020-09-08 20:02:12 +00:00
Victor Farazdagi
8baa22f065 Fix unclosed tickers/timers (#7190)
* fix resource leak
* fixes leak in blocks fetcher
* client/validator release ticker resorces
* powchain, more straightforward ticker closing
* adds missing ticker.stop() calls
* more straightforward ticker closing
* Merge refs/heads/master into fix-unclosed-tickers-timers
* Merge refs/heads/master into fix-unclosed-tickers-timers
* Merge refs/heads/master into fix-unclosed-tickers-timers
* gofmt issues introduced in https://github.com/prysmaticlabs/prysm/pull/7176
2020-09-08 18:05:38 +00:00
Shay Zluf
f4848e46d4 Safer validator protection db dir (#7176)
* Safer validator protection db dir
* handle old account structure
* Merge refs/heads/master into move_validator_protection_db
* Merge refs/heads/master into move_validator_protection_db
* Merge refs/heads/master into move_validator_protection_db
* Merge refs/heads/master into move_validator_protection_db
* fix e2e issue
* separate function
* Merge branch 'move_validator_protection_db' of github.com:prysmaticlabs/prysm into move_validator_protection_db
* Merge branch 'master' of github.com:prysmaticlabs/prysm into move_validator_protection_db
* Merge refs/heads/master into move_validator_protection_db
* Merge refs/heads/master into move_validator_protection_db
* Merge refs/heads/master into move_validator_protection_db
* Update shared/fileutil/fileutil.go
* Merge refs/heads/master into move_validator_protection_db
2020-09-08 16:42:06 +00:00
terence tsao
f04fffb5fe Revert "Pipelines for ProcessBlockNoVerifyAttSigs and ProcessBlockStateRoot" (#7191)
* Revert "Pipelines for `ProcessBlockNoVerifyAttSigs` and `ProcessBlockStateRoot` (#7180)"

This reverts commit 9219dc77ff.
2020-09-08 15:45:20 +00:00
Victor Farazdagi
51f2cc18e5 Improves asyncutils/Debounce (#7189)
* improves asyncutils/debounce
* better handling of timeout test
* more tests
2020-09-08 14:49:28 +00:00
terence tsao
3de626f0d0 Prevent zero hashes sigs get submitted (#7187) 2020-09-07 12:53:30 -07:00
Nishant Das
a81214219d Hash Pubsub Messages Correctly (#7177)
* check message id

* gaz

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-09-07 02:05:16 +08:00
terence tsao
245c18784e Ensure aggregateAndProofSig returns when err'ing (#7182)
* Return if sign fails
2020-09-06 06:56:17 +00:00
terence tsao
9219dc77ff Pipelines for ProcessBlockNoVerifyAttSigs and ProcessBlockStateRoot (#7180) 2020-09-04 16:24:43 -07:00
Raul Jordan
1de230110d Add Beacon Gateway Flag to Validator Client (#7179)
* add in cors for web ui in val client and gateway flag
* Merge branch 'master' into add-default-beacon-gateway
* gateway cors value
* Merge branch 'add-default-beacon-gateway' of github.com:prysmaticlabs/prysm into add-default-beacon-gateway
* fix tests
* Merge refs/heads/master into add-default-beacon-gateway
2020-09-04 19:03:18 +00:00
Victor Farazdagi
b6607fac25 Fixes timer resources leak in CountdownToGenesis (#7175)
* fixes timer leak in CountdownToGenesis
* Merge branch 'master' into fix-unclosed-timer-in-countdown
* Merge refs/heads/master into fix-unclosed-timer-in-countdown
2020-09-04 18:07:50 +00:00
terence tsao
e6277ec536 Revert 6966 (#7178)
* revert 6966

* Fix build
2020-09-04 12:25:42 -05:00
Raul Jordan
0961fef727 Implement Create and List Accounts Validator RPC (#7172)
* impl of accounts RPCs
* create and list accounts impls
* impl create account and list accounts
* tests pass
* imports
* fix test
2020-09-04 00:58:36 +00:00
Raul Jordan
366b98ac83 Add Node Connection Endpoint to Validator Client (#7171)
* add sync status checker
* register healthz
* simplify
2020-09-03 23:25:56 +00:00
terence tsao
c2425e81d7 Remove deprecated health end points (#7170)
* Remove deprecated health end points

* Remove fields
2020-09-03 17:39:30 -05:00
terence tsao
8f2950d374 Prevent far future target epoch for attestation state (#7169)
* Prevent far future target epoch

* Regression tests
2020-09-03 13:18:38 -05:00
Raul Jordan
f4a6864343 Prepare Validator Client for Web Usage (#7158)
* prepare validator for web usage
* wallet exists func in rpc server
* only initialize wallet if feed exists and wallet also exists
* enabling web via a feed
* wallet creation works but needs to be able to recover from mnemonic via api
* ensure logic works
* Merge branch 'master' into validator-web
* fix up tests
* test file
* wallet rpc tests
* add all tests to create wallet
* Merge branch 'master' into validator-web
* imports
* Merge branch 'validator-web' of github.com:prysmaticlabs/prysm into validator-web
* Merge refs/heads/master into validator-web
* Merge refs/heads/master into validator-web
2020-09-03 15:11:17 +00:00
Shay Zluf
c1a7c65e05 Deprecate beacon chain slasher flags (#7031)
* Deprecate beacon chain slasher flags
* Merge branch 'master' into deprecate_beacon_slasher_flags
* remove comments
* Merge branch 'deprecate_beacon_slasher_flags' of github.com:prysmaticlabs/prysm into deprecate_beacon_slasher_flags
* hidden
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* remove start slasher client
* de-depracate an in use flag in validator
* Merge branch 'master' of github.com:prysmaticlabs/prysm into deprecate_beacon_slasher_flags

# Conflicts:
#	shared/featureconfig/flags.go
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
* Merge refs/heads/master into deprecate_beacon_slasher_flags
2020-09-03 14:12:43 +00:00
Victor Farazdagi
7fd2536d54 Hardens block validation in init-sync (#7168)
* assert response invariants in beaconBlocksByRange
* Merge branch 'master' into assert-invariants-in-beaconblocksbyrange
* enforce specs invariant in requestBlocks
* blocks queue: onDataReceivedEvent - part1
* Merge branch 'master' into init-sync-block-validation
* blocks queue: onDataReceivedEvent - part2
* Merge branch 'master' into init-sync-block-validation
* block fetcher: test returned blocks validation
* gazelle
* Nishant's suggestion to not loop more than req.count of times
* combine checks
* enforce slot ordering
* enforce skip increments
2020-09-03 07:07:42 +00:00
terence tsao
0e6797d80d Set head as finalized root (instead of archived root) on start (#7167)
* Set head to finalized
* Merge branch 'master' into set-head-to-finalized
* Fixed testtttts
* Merge branch 'set-head-to-finalized' of github.com:prysmaticlabs/prysm into set-head-to-finalized
* Merge refs/heads/master into set-head-to-finalized
2020-09-02 22:43:40 +00:00
Victor Farazdagi
b2b4c2660d Asserts response invariants in beaconBlocksByRange (#7166)
* assert response invariants in beaconBlocksByRange
* Merge branch 'master' into assert-invariants-in-beaconblocksbyrange
2020-09-02 21:59:57 +00:00
Nishant Das
787857c38b Verify Attestation Time Correctly (#7160)
* add changes
* add unit test
* Merge refs/heads/master into fixVerifyAttTime
2020-09-02 19:21:52 +00:00
terence tsao
1cc21ed3c4 Check finalized ancestor (#7165) 2020-09-02 13:38:03 -05:00
terence tsao
7588e491ab Add overflow check for StartSlot (#7149)
* Add overflow checks
* More fixes
* Typos
* Merge branch 'master' into fix-overflow
* One more regression test
* Merge branch 'fix-overflow' of github.com:prysmaticlabs/prysm into fix-overflow
* Gazelle
* Merge branch 'master' into fix-overflow
* Nishant's feedback
* Merge refs/heads/master into fix-overflow
2020-09-02 02:52:36 +00:00
Raul Jordan
afce363e00 Update Protos for Wallet Creation (#7157)
* web api changes
* Merge branch 'master' into wallet-creation-protos
* protos checked in
* Merge branch 'wallet-creation-protos' of github.com:prysmaticlabs/prysm into wallet-creation-protos
2020-09-02 02:13:42 +00:00
Nishant Das
7de3ce0b31 Fix Snappy Framed Reader (#7152)
* add checks
* Merge refs/heads/master into fixFramedSnappy
* Merge refs/heads/master into fixFramedSnappy
* Merge refs/heads/master into fixFramedSnappy
* Merge refs/heads/master into fixFramedSnappy
2020-09-02 01:29:46 +00:00
terence tsao
6e6b871cc1 Use state slot to verify exit signature (#7155)
* Use state slot
* TestValidateVoluntaryExit_InvalidExitSlot
* Fixed TestProposeExit_NoPanic
* Merge refs/heads/master into use-correct-slot
2020-09-02 00:57:52 +00:00
Nishant Das
2349012bd0 Handle Zero Root Requests (#7151)
* handle zero root requests
* clean up
* Merge refs/heads/master into handleZeroRoots
* Merge refs/heads/master into handleZeroRoots
* Merge branch 'master' into handleZeroRoots
2020-09-01 19:09:09 +00:00
RoBiK75
b4c0a89d49 Fixes incorrect output produced by the ListAccounts function (#6976) (#7095)
Co-authored-by: Ivan Martinez <ivanthegreatdev@gmail.com>
Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2020-09-01 13:13:44 -05:00
Nishant Das
d368156a08 Remove Deprecated Request Type (#7153)
* remove deprecated type
* fix build and tests
* update log
* Merge refs/heads/master into removeBlocksByRootType
2020-09-01 13:35:30 +00:00
Victor Farazdagi
63149a3dc3 Removes redundant SignedAggregateAndProof declaration (#7154)
* removes redundant SignedAggregateAndProof declaration
2020-09-01 13:11:05 +00:00
terence tsao
fbe088625a Update ProcessBlock to use a pipeline (#7148) 2020-08-31 18:29:27 -07:00
Raul Jordan
ecbab20bad Begin Dynamic Rescan of Validating Keys (#6963)
* begin on dynamic key rescan
* Merge branch 'master' into dynamic-rescan
* begin dynamic rescan
* fsnotify to listen for rescan dir changes
* recheck for slashing protection
* lint
* Merge branch 'master' into dynamic-rescan
* less aggressive recheck interval
* imports
* Merge branch 'dynamic-rescan' of github.com:prysmaticlabs/prysm into dynamic-rescan
* resolve confs
* listen for file changes for accounts file
* reload accounts from keystore
* begin fixing rescan test
* add event feed
* fix confs
* fix conf
* fix broken tests
* Merge branch 'master' into dynamic-rescan
* simplify lines
* do nothing if no subscribers
* Merge branch 'dynamic-rescan' of github.com:prysmaticlabs/prysm into dynamic-rescan
* Merge refs/heads/master into dynamic-rescan
* Merge refs/heads/master into dynamic-rescan
* Merge refs/heads/master into dynamic-rescan
* Merge refs/heads/master into dynamic-rescan
* Merge refs/heads/master into dynamic-rescan
* Merge refs/heads/master into dynamic-rescan
* Merge refs/heads/master into dynamic-rescan
* Merge refs/heads/master into dynamic-rescan
* fix tests
* Merge refs/heads/master into dynamic-rescan
* Merge refs/heads/master into dynamic-rescan
* Merge refs/heads/master into dynamic-rescan
* Merge refs/heads/master into dynamic-rescan
* Merge refs/heads/master into dynamic-rescan
* gaz
* Merge branch 'dynamic-rescan' of github.com:prysmaticlabs/prysm into dynamic-rescan
* ident
* Update WORKSPACE
* gaz
* Merge branch 'dynamic-rescan' of github.com:prysmaticlabs/prysm into dynamic-rescan
* add keys on service start
* Merge refs/heads/master into dynamic-rescan
* Merge refs/heads/master into dynamic-rescan
* Merge refs/heads/master into dynamic-rescan
* Merge refs/heads/master into dynamic-rescan
* Merge refs/heads/master into dynamic-rescan
* Merge refs/heads/master into dynamic-rescan
* Merge refs/heads/master into dynamic-rescan
* Merge refs/heads/master into dynamic-rescan
* ensure debounce util works
* Merge branch 'dynamic-rescan' of github.com:prysmaticlabs/prysm into dynamic-rescan
* Merge refs/heads/master into dynamic-rescan
* complete refresh, debounce test, and ensure works at runtime
* Merge branch 'dynamic-rescan' of github.com:prysmaticlabs/prysm into dynamic-rescan
* imports and remove log
* Merge refs/heads/master into dynamic-rescan
* Merge refs/heads/master into dynamic-rescan
* Merge refs/heads/master into dynamic-rescan
* Merge refs/heads/master into dynamic-rescan
* Merge refs/heads/master into dynamic-rescan
* Merge refs/heads/master into dynamic-rescan
* Merge refs/heads/master into dynamic-rescan
* Merge refs/heads/master into dynamic-rescan
* Merge refs/heads/master into dynamic-rescan
* Merge refs/heads/master into dynamic-rescan
* Merge refs/heads/master into dynamic-rescan
* Merge refs/heads/master into dynamic-rescan
* Merge refs/heads/master into dynamic-rescan
* resolve confs
* fix up e2e tests
* Merge branch 'dynamic-rescan' of github.com:prysmaticlabs/prysm into dynamic-rescan
* fix up e2e
* Merge refs/heads/master into dynamic-rescan
2020-08-31 23:38:20 +00:00
Michael Huang
381b5be0fc Fix partially deposited status bug (#7138)
* Fix paritally deposited bug
* Replace conditional logic with depositStatus
* Add test
* Merge branch 'master' into fix-partial-dep-bug
* Merge branch 'master' into fix-partial-dep-bug
* Merge branch 'master' into fix-partial-dep-bug
* Merge branch 'master' into fix-partial-dep-bug
* Merge branch 'master' into fix-partial-dep-bug
2020-08-31 22:45:20 +00:00
Radosław Kapka
6803f3308a Implement exit proposal in validator client (#7125)
* Create mocks for updated ethereumapis

* Revert "Create mocks for updated ethereumapis"

This reverts commit 0da06d5158.

* update ethereumapis

* new metrics

* ProposeExit implementation and tests

* fix comments for metrics

* assert errors

* added one more error assert

* remove redundant comments

* make metric names compliant with best practices

* change root calculation

* fix test assertion

* fix test assertion

* check if domain is not nil

* extract error messages

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-08-31 15:18:22 -05:00
Raul Jordan
60558b7970 Refactor Accounts and Keymanager Methods to Not Rely on CLI (#7135)
* keymanagers no longer use cli ctx
* rename important values to keymanageropts
* further refactor accounts methods to reduce cli dependency
* separating cli vs non cli methods for various accounts functions
* recover wallet cli vs non-cli mode
* ensure half of tests build
* accounts v2 package now builds
* full revamp wallet creation or opening wallets
* everything builds
* tests pass finally
* Merge branch 'master' into no-cli-keymanagers
* ensure commands work as expected
* Merge branch 'no-cli-keymanagers' of github.com:prysmaticlabs/prysm into no-cli-keymanagers
* further fix build
* account creation comments
* fix imports and comments
* fix up failing test
* fix build
* Update derived.go
* Update direct.go
* Update remote.go
* Fixed variable
* fix up red tests
* use Cli instead of CLI, fix tests, and address Radek's feedback
* Merge refs/heads/master into no-cli-keymanagers
* Merge refs/heads/master into no-cli-keymanagers
* Merge refs/heads/master into no-cli-keymanagers
* Merge refs/heads/master into no-cli-keymanagers
* Merge refs/heads/master into no-cli-keymanagers
* Merge refs/heads/master into no-cli-keymanagers
* Merge refs/heads/master into no-cli-keymanagers
* Merge refs/heads/master into no-cli-keymanagers
2020-08-31 19:46:45 +00:00
Ivan Martinez
7854b91ae0 E2E: Change metrics detection to use regex (#7145)
* Change metrics detection to use regex

* Fixes, remove println

* Forgot a println

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-08-31 13:35:26 -05:00
Victor Farazdagi
c9c7cc7b93 Fixes comments in params/config (#7147)
* fixes comments in params/config
* Merge refs/heads/master into params-doc-fix
* Merge refs/heads/master into params-doc-fix
2020-08-31 15:25:05 +00:00
terence tsao
b538f5073d Add metrics (#7142)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-08-31 07:51:47 -07:00
Nishant Das
3ed7b23ed7 Handle Saved Genesis Interop States (#7146)
* handle interop states
* lint
* Merge refs/heads/master into handleInteropCase
* fix test
* Merge branch 'handleInteropCase' of https://github.com/prysmaticlabs/geth-sharding into handleInteropCase
2020-08-31 13:45:03 +00:00
Nishant Das
c2b94d04ed Deprecate DisableNewStateMgmt Flag (#7124)
* deprecate flag
* gaz
* Merge refs/heads/master into deprecateFlag
* Merge refs/heads/master into deprecateFlag
* Merge refs/heads/master into deprecateFlag
* Merge refs/heads/master into deprecateFlag
* Merge refs/heads/master into deprecateFlag
* Merge refs/heads/master into deprecateFlag
* Merge refs/heads/master into deprecateFlag
* Merge refs/heads/master into deprecateFlag
* Merge refs/heads/master into deprecateFlag
* Merge refs/heads/master into deprecateFlag
* Merge refs/heads/master into deprecateFlag
* Merge refs/heads/master into deprecateFlag
* Merge refs/heads/master into deprecateFlag
* Merge refs/heads/master into deprecateFlag
* add check back
2020-08-31 06:59:13 +00:00
Nishant Das
3316516d22 Harden Slot Time Verification (#7139)
* checkpoint

* lint

* terence's review

* fix test

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-08-31 12:51:15 +08:00
Ivan Martinez
12c1daaf2b Verify deposits made and show network deposit is for (#6996)
* Verify deposits made and show network deposit is for
* Merge branch 'master' of github.com:prysmaticlabs/prysm into verify-deposit-netowrk
* Fix formatting
* gofmt
* Merge branch 'master' of github.com:prysmaticlabs/prysm into verify-deposit-netowrk
* Improve deposit sig failure error
* Merge branch 'master' of github.com:prysmaticlabs/prysm into verify-deposit-netowrk
* Fix fmt
* Add "verified for" text
* Update shared/params/config.go
* Merge branch 'master' into verify-deposit-netowrk
* Merge branch 'master' into verify-deposit-netowrk
2020-08-30 16:39:53 +00:00
terence tsao
f09620c9f6 Don't include orphaned atts (#7134)
* Don't include orphaned atts
* gazelle
* Merge refs/heads/master into orphaned-atts
2020-08-30 15:13:21 +00:00
Radosław Kapka
e47e7067c4 Update rpc validator exit tests (#7122)
* Create mocks for updated ethereumapis

* Revert "Create mocks for updated ethereumapis"

This reverts commit 0da06d5158.

* update ethereumapis

* change root calculation

* fix test assertion

* fix test assertion
2020-08-28 15:52:40 -05:00
Nishant Das
4edcf92140 Validate Beacon Block By Range Requests Better (#7132)
* checkpoint
* clean up
* new changes
* clean up
* victor's review
* victor's review
* fix test
2020-08-28 13:50:38 +00:00
terence tsao
7463f2cffd Update participation response (#7129)
* Sync with ethapi
* Implementation and test
* Handle mock
* Fix ProposeExit for e2e
* Merge refs/heads/master into participation
* Preston's feedback
* Merge branch 'participation' of github.com:prysmaticlabs/prysm into participation
2020-08-27 23:57:11 +00:00
terence tsao
fea2cc9e2f Cleanup stategen pkg (#7127)
* Clean up stategen
* Sync with master
* Fix tests
* Merge refs/heads/master into cleanup-newstate
* Merge refs/heads/master into cleanup-newstate
* Rename file
* Merge branch 'cleanup-newstate' of github.com:prysmaticlabs/prysm into cleanup-newstate
* gaz
* Forgot to add metrics page back
2020-08-27 22:29:59 +00:00
Victor Farazdagi
bd489e345a Fixes docs.go -> doc.go file name (#7128)
* fixes doc file name
* Merge refs/heads/master into fix-doc-file-name
2020-08-27 20:28:54 +00:00
Michael Huang
b98b9b740b Add PARTIALLY_DEPOSITED status (#7071)
* Update ethereumapis

* Add PARTIALLY_DEPOSITED status

* go mod tidy

* Fix bug

* Fixup

* Fixup

* Fix tests

* Revert fast ssz bump

* Pending status if deposit amount is 0

* go mod tidy

* More tests

* Trigger Buildkite

* Fix TestMultipleValidatorStatus_Indices

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2020-08-27 14:41:32 -05:00
Preston Van Loon
b7175b3482 Update fastssz: Attempt 2 (#7115)
* Revert "Revert "Update fastssz" (#7100)"

This reverts commit b954db9704.
* Preston's patch
* Merge branch 'master' of github.com:prysmaticlabs/prysm into revert-7100-revert-6760-update-fssz
* Update fssz, add regression test case
* more HTR with fssz
* fix some tests
* only one test left
* Make it so that HTR will work
* gofmt, imports
* gofmt, imports
* fix
* Merge branch 'master' of github.com:prysmaticlabs/prysm into revert-7100-revert-6760-update-fssz
* fix
* Merge branch 'master' into revert-7100-revert-6760-update-fssz
* Merge refs/heads/master into revert-7100-revert-6760-update-fssz
* gaz
* Merge branch 'revert-7100-revert-6760-update-fssz' of github.com:prysmaticlabs/prysm into revert-7100-revert-6760-update-fssz
* Merge refs/heads/master into revert-7100-revert-6760-update-fssz
* fix test
* Merge branch 'revert-7100-revert-6760-update-fssz' of github.com:prysmaticlabs/prysm into revert-7100-revert-6760-update-fssz
* Merge refs/heads/master into revert-7100-revert-6760-update-fssz
2020-08-27 18:13:32 +00:00
Preston Van Loon
7d28146e1e Return an error if no eth1 endpoint defined and we do not have genesis state (#7126)
* Return an error if no eth1 endpoint defined and we do not have genesis state
* Merge refs/heads/master into fail-without-genesis-state-and-no-eth1-node
2020-08-27 17:18:17 +00:00
Nishant Das
5bfc457904 Request Headers From ETH1 Node Instead of Blocks (#7121)
* request headers instead of blocks
* Merge branch 'master' into changeToHeader
* Apply suggestions from code review

Co-authored-by: Victor Farazdagi <simple.square@gmail.com>
* change references
* one more change
* last one
* Merge refs/heads/master into changeToHeader
2020-08-27 16:27:08 +00:00
Nishant Das
13324674ba disable default goerli endpoint (#7120)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-08-27 10:17:21 -05:00
Nishant Das
c78bfab69d Fix Go Builds (#7123)
* change to ssz DeepEqual
* gaz
2020-08-27 13:12:49 +00:00
terence tsao
2ee025ee88 Participation: count atts from orphaned blocks (#7117)
* Cound attestations from orphaned blocks

* Use next epoch's end slot

* Fixed a test

* Fixed a test

* Nishant's feedback

* Typo

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-08-27 16:19:55 +08:00
Radosław Kapka
0410b14260 Add deposit cache and majority vote to dev mode flags (#6768)
* enableFinalizedDepositsCache and enableEth1DataMajorityVote flags
* Merge branch 'master' into add-dev-mode-flags
* Merge branch 'master' into add-dev-mode-flags
* Merge branch 'master' into add-dev-mode-flags
2020-08-27 04:10:36 +00:00
terence tsao
2c3558e449 Remove new state mgmt (#7119) 2020-08-26 21:39:47 -05:00
Nishant Das
e95393f671 fix non existent validators (#7114) 2020-08-26 06:30:30 -07:00
Nishant Das
73cb6daf46 Listens For State Initialized Event (#7112)
* listen for state initialized event
* reg test
* fmt
* Merge refs/heads/master into handleNilHeadState
2020-08-26 10:54:33 +00:00
Nishant Das
8a8edf3743 Clean Up Metadata logs (#7109)
* clean errors

* cleaner

* gazelle

* go check

* Update beacon-chain/sync/error.go

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

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
Co-authored-by: Victor Farazdagi <simple.square@gmail.com>
2020-08-26 17:59:16 +08:00
Fabrice Cheng
900e7114da Update VerifyMerkleBranch to match ETH2.0 spec (#6767)
* update VerifyMerkleBranch to match ETH2.0 spec
* Merge branch 'master' into 6705-refactor-verify-merkle-branch
* Make depth a parameter of VerifyMerkleBranch
* Merge branch '6705-refactor-verify-merkle-branch' of github.com-fabdarice:fabdarice/prysm into 6705-refactor-verify-merkle-branch
* Merge branch 'master' into 6705-refactor-verify-merkle-branch
* loop instead of appending
* Merge branch 'master' of https://github.com/prysmaticlabs/prysm into 6705-refactor-verify-merkle-branch
* Merge branch 'master' of https://github.com/prysmaticlabs/prysm into 6705-refactor-verify-merkle-branch
* fix int conversion
* Merge branch 'master' of https://github.com/prysmaticlabs/prysm into 6705-refactor-verify-merkle-branch
* Merge branch '6705-refactor-verify-merkle-branch' of github.com-fabdarice:fabdarice/prysm into 6705-refactor-verify-merkle-branch
* Merge branch 'master' into 6705-refactor-verify-merkle-branch
* fix keymanagerv2 tests
* revert print
* merge conflict
* fix bug during merge
* Merge branch 'master' into 6705-refactor-verify-merkle-branch
* Merge branch 'master' into 6705-refactor-verify-merkle-branch
2020-08-25 20:57:41 +00:00
Ivan Martinez
ba00c55f95 Accounts-V2: Fix wallet-v2 recover and wallet-v2 create for derived (#7104)
* Fix derived to create seed on wallet-v2 create
* Fix derived wallet recover
* Fix comment
* Merge branch 'master' of github.com:prysmaticlabs/prysm into fix-derived-phrase
* Merge refs/heads/master into fix-derived-phrase
* Merge refs/heads/master into fix-derived-phrase
* Merge refs/heads/master into fix-derived-phrase
* Merge refs/heads/master into fix-derived-phrase
* Merge refs/heads/master into fix-derived-phrase
* Update validator/accounts/v2/wallet_create.go
* Merge refs/heads/master into fix-derived-phrase
2020-08-25 19:30:26 +00:00
Victor Farazdagi
8240eb0416 updates bazel-toolchains 3.1.1 -> 3.2.0 (#7107)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-08-25 13:28:37 -05:00
Victor Farazdagi
ba07ccb484 Apply testutils assertions: final cleanup (#7003)
* slasher/beaconclient tests
* slasher/db/kv tests
* Merge branch 'master' into apply-testutils-assertions-to-slasher
* fix build
* slasher/detection tests
* rest of the tests
* misc tests
* tools tests
* Merge refs/heads/master into apply-testutils-assertions-misc
* Merge branch 'master' into apply-testutils-assertions-misc
* agg tests
* Merge refs/heads/master into apply-testutils-assertions-misc
* Merge refs/heads/master into apply-testutils-assertions-misc
* Merge refs/heads/master into apply-testutils-assertions-misc
* Merge refs/heads/master into apply-testutils-assertions-misc
* Merge refs/heads/master into apply-testutils-assertions-misc
* Merge refs/heads/master into apply-testutils-assertions-misc
* Merge refs/heads/master into apply-testutils-assertions-misc
* Merge refs/heads/master into apply-testutils-assertions-misc
* Merge refs/heads/master into apply-testutils-assertions-misc
* Merge refs/heads/master into apply-testutils-assertions-misc
* Merge refs/heads/master into apply-testutils-assertions-misc
* Merge refs/heads/master into apply-testutils-assertions-misc
* Merge refs/heads/master into apply-testutils-assertions-misc
* Merge refs/heads/master into apply-testutils-assertions-misc
* Merge refs/heads/master into apply-testutils-assertions-misc
* Merge refs/heads/master into apply-testutils-assertions-misc
* Merge refs/heads/master into apply-testutils-assertions-misc
* Merge refs/heads/master into apply-testutils-assertions-misc
* Merge refs/heads/master into apply-testutils-assertions-misc
* Merge branch 'master' into apply-testutils-assertions-misc
* Merge branch 'apply-testutils-assertions-misc' of github.com:prysmaticlabs/prysm into apply-testutils-assertions-misc
* updates aggregated_test
* beacon-chain/operations/attestations/kv/* tests updated
* beacon-chain/operations/attestations tests updated
* beacon-chain/operations/slashings tests updated
* Merge branch 'master' into apply-testutils-assertions-misc
* gazelle
* beacon-chain/core tests updated
* fixes test
* Merge refs/heads/master into apply-testutils-assertions-misc
* Merge refs/heads/master into apply-testutils-assertions-misc
* Merge branch 'apply-testutils-assertions-misc' of github.com:prysmaticlabs/prysm into apply-testutils-assertions-misc
* beacon-chain/rpc tests updated
* beacon-chain/sync/initial-sync tests
* misc tests
* optimizes error message parsing in testutils
* Merge branch 'assertutils-optimize-processing' into apply-testutils-assertions-misc
* Merge refs/heads/master into apply-testutils-assertions-misc
* endtoend tests
* Merge branch 'apply-testutils-assertions-misc' of github.com:prysmaticlabs/prysm into apply-testutils-assertions-misc
* gazelle
* Merge refs/heads/master into apply-testutils-assertions-misc
* Merge refs/heads/master into apply-testutils-assertions-misc
* beacon-chain/blockchain tests updated
* Merge branch 'apply-testutils-assertions-misc' of github.com:prysmaticlabs/prysm into apply-testutils-assertions-misc
* beacon-chain/state/stategen tests updated
* beacon-chain all left-over tests are done
* Merge refs/heads/master into apply-testutils-assertions-misc
* validator tests updated
* slasher tests
* Merge branch 'master' into apply-testutils-assertions-misc
* gofmt
* gazelle
* Merge refs/heads/master into apply-testutils-assertions-misc
* shared upd
* end2end tests deps fixed
* Merge branch 'apply-testutils-assertions-misc' of github.com:prysmaticlabs/prysm into apply-testutils-assertions-misc
* Merge refs/heads/master into apply-testutils-assertions-misc
* misc
* all tests are updated
* Merge branch 'apply-testutils-assertions-misc' of github.com:prysmaticlabs/prysm into apply-testutils-assertions-misc
2020-08-25 15:23:06 +00:00
rkapka
3d9cde3e1c Modify majority vote rules (#6818)
* add deposit guard clauses to majority vote
* Merge branch 'origin-master' into majority-vote-deposit-count
* Merge branch 'master' into majority-vote-deposit-count
* uncommented e2e flag
* fix deposit comparison
* Merge branch 'origin-master' into majority-vote-deposit-count
* changed block height used for 0 deposits
* Merge branch 'master' into majority-vote-deposit-count
* exclude previous period's initial block
* rename first and last blocks
* renamed inRangeVotes arguments
* reorder arguments
* Comments explaining valid range calculation
* Merge branch 'master' into majority-vote-deposit-count
* Comments explaining deposit check
* logging
* process slots before voting for eth1data
* Merge branch 'origin-master' into majority-vote-deposit-count

# Conflicts:
#	beacon-chain/rpc/validator/proposer.go
* Merge branch 'master' into majority-vote-deposit-count
* Merge branch 'master' into majority-vote-deposit-count
* rollback changes to eth1data and randomETH1DataVote
* Merge branch 'master' into majority-vote-deposit-count
* Merge branch 'master' into majority-vote-deposit-count
2020-08-25 14:10:04 +00:00
Nishant Das
b291eb7953 Unset From,Sequence Number and Signature For Pubsub Messages (#7093)
* add new options
* Merge refs/heads/master into removePubsubFields
* Merge refs/heads/master into removePubsubFields
* Merge refs/heads/master into removePubsubFields
* Merge refs/heads/master into removePubsubFields
* Merge refs/heads/master into removePubsubFields
* Merge refs/heads/master into removePubsubFields
* Merge refs/heads/master into removePubsubFields
* Merge refs/heads/master into removePubsubFields
* Merge refs/heads/master into removePubsubFields
* Merge refs/heads/master into removePubsubFields
* Merge refs/heads/master into removePubsubFields
* Merge refs/heads/master into removePubsubFields
2020-08-25 11:08:42 +00:00
terence tsao
f61f02e59b First take of applying assertion funcs to shared tests (#6666)
* cmd tests
* deposit util tests
* feature config tests
* hashutil tests
* htr util tests
* interop tests
* ip util tests
* Update BLS
* Update cmd
* Update bytesutil and depositutil
* Update event
* Update keystore
* Update mathutil
* Update mputil
* Update pagination
* Update params
* Upate prome
* Update testutil
* Update trieutil
* Merge branch 'master' of github.com:prysmaticlabs/prysm into testutil-shared
* Sync with master
* Mod
* Typo
* Revert
* gazelle
* Merge refs/heads/master into testutil-shared
* Merge refs/heads/master into testutil-shared
* Merge refs/heads/master into testutil-shared
* Merge refs/heads/master into testutil-shared
* Gaz
* Merge refs/heads/master into testutil-shared
* Merge refs/heads/master into testutil-shared
* Merge refs/heads/master into testutil-shared
* Merge refs/heads/master into testutil-shared
* Merge refs/heads/master into testutil-shared
* Merge refs/heads/master into testutil-shared
* Merge refs/heads/master into testutil-shared
* fixes build error
* Merge refs/heads/master into testutil-shared
2020-08-25 10:18:29 +00:00
Nishant Das
48fd40e35b fix interop (#7106) 2020-08-25 17:17:06 +08:00
Ivan Martinez
d8ea41ce35 Make Interop keys functional for accounts-v2 (#7103)
* Make Interop functional for accounts v2
* Merge branch 'master' into e2e-accounts-v2
* Fix e2e and account name fetch
* Merge branch 'e2e-accounts-v2' of github.com:prysmaticlabs/prysm into e2e-accounts-v2
* Enable metrics check
* Fix lint
* Merge branch 'master' into e2e-accounts-v2
2020-08-25 01:37:25 +00:00
Nishant Das
e556ac348a Add Shared Field Metrics (#7081)
* add metrics
* Merge branch 'master' into sharedFieldMetrics
* Merge branch 'master' into sharedFieldMetrics
* Merge branch 'master' into sharedFieldMetrics
* Merge branch 'master' into sharedFieldMetrics
2020-08-24 23:03:23 +00:00
terence tsao
c764099231 Use checkpoint info cache (#7098)
* Use checkpoint cache

* Add it to dev

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-08-24 17:11:45 -05:00
terence tsao
b954db9704 Revert "Update fastssz" (#7100)
* Revert "Update fastssz (#6760)"

This reverts commit 78a25f99c3.
* Merge refs/heads/master into revert-6760-update-fssz
2020-08-24 20:06:28 +00:00
Raul Jordan
c9c4cd9f87 Create Validator Accounts V2 Send Deposit (#7080)
* add in deposit logic
* create the deposit functionality
* import formatting and create deposit config
* proceed with retrieving user input for calling the deposit func
* actually send our the deposits
* better handling and comments
* programmatically send all
* lint
* gaz
* add progress bar
* deposit test
* better error handling
* Update validator/accounts/v2/accounts_deposit.go

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
* Merge refs/heads/master into send-deposit
* Merge refs/heads/master into send-deposit
* Merge refs/heads/master into send-deposit
* Merge refs/heads/master into send-deposit
* Merge refs/heads/master into send-deposit
* Merge refs/heads/master into send-deposit
* Merge refs/heads/master into send-deposit
* Merge refs/heads/master into send-deposit
2020-08-24 19:19:21 +00:00
Victor Farazdagi
880298d844 Optimizes error message parsing in testutils (#7096)
* optimizes error message parsing in testutils
* Merge refs/heads/master into assertutils-optimize-processing
* Merge refs/heads/master into assertutils-optimize-processing
2020-08-24 15:15:39 +00:00
Nishant Das
21a56d5419 Handle Nil Signature in Pending Queue (#7097)
* add fix and test

* Update beacon-chain/sync/pending_attestations_queue_test.go

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

Co-authored-by: terence tsao <terence@prysmaticlabs.com>
Co-authored-by: Victor Farazdagi <simple.square@gmail.com>
2020-08-24 22:54:58 +08:00
Victor Farazdagi
5c9830f0c3 More conservative selection of non-finalized peers (#7086)
* more conservative selection of non-finalized peers
* Merge refs/heads/master into init-sync-non-finalized-loop
* Nishant's suggestion on possible overflow
* Merge branch 'init-sync-non-finalized-loop' of github.com:prysmaticlabs/prysm into init-sync-non-finalized-loop
* Merge refs/heads/master into init-sync-non-finalized-loop
* Merge refs/heads/master into init-sync-non-finalized-loop
2020-08-24 14:07:21 +00:00
Victor Farazdagi
5d0f6c5b16 Fixes errNoPeersWithFinalizedBlocks naming (#7087)
* fixes errNoPeersWithFinalizedBlocks naming
* Merge refs/heads/master into init-sync-queue-fix-err-naming
* Merge refs/heads/master into init-sync-queue-fix-err-naming
2020-08-24 10:48:52 +00:00
Victor Farazdagi
5cee10f28e Adds DeepNotEqual assertion (#7092)
* adds deepnotequal func
2020-08-24 10:14:13 +00:00
Preston Van Loon
78a25f99c3 Update fastssz (#6760)
* Update fastssz
* Merge branch 'master' of github.com:prysmaticlabs/prysm into update-fssz
* fmt
* gaz
* Merge refs/heads/master into update-fssz
* goimports
* Merge refs/heads/master into update-fssz
* Merge refs/heads/master into update-fssz
* Merge refs/heads/master into update-fssz
* Merge refs/heads/master into update-fssz
* Merge refs/heads/master into update-fssz
* Fix
* fix ethereumapis
* fix again
* kafka
* fix gen file
* fix compute signing root
* gofmt
* checkpoint progress
* progress
* checkpoint
* progress
* Fix build
* checkpoint
* helpers
* Another test fixed
* gaz
* another test fix
* gofmt
* some fixes
* Merge branch 'master' of github.com:prysmaticlabs/prysm into update-fssz
* fix one test
* Merge branch 'master' of github.com:prysmaticlabs/prysm into update-fssz
* fill empty checkpoint roots
* more padding
* more padding
* Fix //beacon-chain/rpc/debug:go_default_test
* fix //beacon-chain/core/state:go_default_test
* fix //beacon-chain/core/state:go_default_test
* fix some htr errors
* fix //slasher/rpc:go_default_test
* Progress on //beacon-chain/core/blocks:go_default_test
* Progress on //beacon-chain/core/blocks:go_default_test
* Progress on //beacon-chain/core/blocks:go_default_test
* fix //slasher/db/kv:go_default_test
* progress
* fix //beacon-chain/sync/initial-sync:go_raceon_test
* gofmt and gaz
* fix one more test, taking a break
* Fix //beacon-chain/core/blocks:go_default_test
* Complete beacon-chain/powchain
* Do most of beacon-chain/rpc/beacon/
* Do most of beacon-chain/blockchain
* fix //beacon-chain/operations/attestations/kv:go_default_test
* Fix //beacon-chain/cache/depositcache:go_default_test
* Fix //slasher/detection:go_default_test
* Progress
* fix //beacon-chain/rpc/validator:go_default_test
* gofmt
* fix //validator/client:go_default_test
* fix
* fix //beacon-chain/blockchain:go_raceoff_test
* fix //beacon-chain/rpc/beacon:go_default_test
* fix 1 of 4 shards in //beacon-chain/sync:go_default_test
* Fix //beacon-chain/sync:go_default_test and gofmt
* prevent panic
* fix //beacon-chain/state/stategen:go_default_test
* fix
* Merge branch 'master' of github.com:prysmaticlabs/prysm into update-fssz
* fix most tests
* Self review, go mod tidy, run regen scripts
* fix slasher
* Update ethereumapis
* disable spawn strategy override
* Merge refs/heads/master into update-fssz
* Merge refs/heads/master into update-fssz
* Remove extra line in imports
* Remove extra line in imports
* Gofmt
* PR feedback from @nisdas
2020-08-24 01:46:17 +00:00
Preston Van Loon
706f375aed Healthz: Move header before write. Fixes #7029 (#7084)
* Healthz: Move header before write. Fixes #7029
* Merge refs/heads/master into fix-7029
2020-08-22 21:12:17 +00:00
terence tsao
5977343a0d UnaggregatedAttestations use helper hasSeenBit (#7083) 2020-08-22 13:42:55 -07:00
terence tsao
f2afeed9da Pool: Use a TTL cache for seen bits (#7015) 2020-08-21 16:27:51 -07:00
Raul Jordan
e69ed7c778 Accounts V2: Implement Backup for Derived Keymanager (#7067)
* backup for derived complete
* Merge refs/heads/master into derived-backup
* Merge refs/heads/master into derived-backup
* Merge refs/heads/master into derived-backup
* Merge refs/heads/master into derived-backup
* Merge refs/heads/master into derived-backup
* Merge refs/heads/master into derived-backup
* Merge refs/heads/master into derived-backup
* Merge refs/heads/master into derived-backup
* Merge refs/heads/master into derived-backup
2020-08-21 19:43:03 +00:00
Raul Jordan
c9caf5dfc5 Set Healthz to Return Error if Chain Has Not Yet Started (#7077)
* healthz in sync when chain not started
* Merge refs/heads/master into fix-healthz-when-process-deposits
* Merge refs/heads/master into fix-healthz-when-process-deposits
* Merge refs/heads/master into fix-healthz-when-process-deposits
2020-08-21 19:09:52 +00:00
Raul Jordan
b4c7a14759 Do Not Unset Rate Limiter Before Node Shutdown (#7078)
* reset rate limiter before shutdown
* Merge refs/heads/master into empty-rate-limit
* Merge refs/heads/master into empty-rate-limit
* Update beacon-chain/sync/service.go
2020-08-21 18:48:43 +00:00
Ivan Martinez
92e1a996cc Slasher: Optimize span marshal and unmarshal (#7062)
* Optimize marshal and unmarshal
* Merge branch 'master' into slasher-optimize-span
* Merge branch 'master' into slasher-optimize-span
* Add tests and comments
* Merge branch 'slasher-optimize-span' of github.com:prysmaticlabs/prysm into slasher-optimize-span
* Merge branch 'master' of github.com:prysmaticlabs/prysm into slasher-optimize-span
* Merge refs/heads/master into slasher-optimize-span
* Merge refs/heads/master into slasher-optimize-span
* Merge refs/heads/master into slasher-optimize-span
2020-08-21 17:29:11 +00:00
rkapka
6228b3cd9f Identical expression comparison analyzer (#7066)
* static analyzer with tests
* Merge branch 'origin-master' into identical-expression-comparison-analyzer
* resolve analyzer errors
* Merge branch 'origin-master' into identical-expression-comparison-analyzer
* change excluded file in nogo_config
* remove tests from bazel file
* exclude test file explicitly
* extracted common code to helper file
* Revert "extracted common code to helper file"

This reverts commit e9ccea7360.
* Merge refs/heads/master into identical-expression-comparison-analyzer
* Merge refs/heads/master into identical-expression-comparison-analyzer
2020-08-21 16:48:27 +00:00
terence tsao
8686a81304 Implement checkpt info cache (#7070) 2020-08-21 08:50:21 -07:00
Victor Farazdagi
05d6dc7a10 Improves block deduplication on batch processing (#7075)
* fixes block deduplication on batch processing
* Nishant's suggestions
2020-08-21 10:51:27 +00:00
terence tsao
ec1dd85c44 Fix identical expressions (#7069)
* Fix ident exps
* Merge refs/heads/master into fix-ident-exp
2020-08-20 22:34:52 +00:00
Roy
7b0b8ee126 Add prysm.sh1 for native Windows support via PowerShell (#6829)
* Add prysm.sh1 for native Windows support via PowerShell
* Remove unused variable
* Merge branch 'master' into master
* Merge branch 'master' into master
* Merge branch 'master' into master
* Merge branch 'master' into master
2020-08-20 20:52:59 +00:00
terence tsao
55074bcc6c Tidying up a few core functions (#6995)
* DB: add block roots test
* Merge branch 'master' of github.com:prysmaticlabs/prysm
* Merge branch 'master' of github.com:prysmaticlabs/prysm
* Pool: add seen atts map
* Pool: use seen atts map
* Pool: clear seen map
* Merge branch 'master' of github.com:prysmaticlabs/prysm
* Core: clean up unused noverify and tidy up namings
* Gaz
* Merge refs/heads/master into rm-no-verify
* Merge refs/heads/master into rm-no-verify
* Core: Add no verify back. Better namings
* Merge branch 'rm-no-verify' of github.com:prysmaticlabs/prysm into rm-no-verify
* Merge refs/heads/master into rm-no-verify
* Core: fixed a test
* Merge branch 'rm-no-verify' of github.com:prysmaticlabs/prysm into rm-no-verify
* Merge refs/heads/master into rm-no-verify
* Merge refs/heads/master into rm-no-verify
* Merge refs/heads/master into rm-no-verify
* Merge refs/heads/master into rm-no-verify
* Merge refs/heads/master into rm-no-verify
* Merge refs/heads/master into rm-no-verify
* Merge refs/heads/master into rm-no-verify
* Merge refs/heads/master into rm-no-verify
* Merge refs/heads/master into rm-no-verify
* Merge refs/heads/master into rm-no-verify
* Merge refs/heads/master into rm-no-verify
* Merge refs/heads/master into rm-no-verify
* Merge refs/heads/master into rm-no-verify
* Merge refs/heads/master into rm-no-verify
* Merge refs/heads/master into rm-no-verify
* Merge refs/heads/master into rm-no-verify
* Merge refs/heads/master into rm-no-verify
* Merge refs/heads/master into rm-no-verify
* Merge refs/heads/master into rm-no-verify
* Merge refs/heads/master into rm-no-verify
* Merge refs/heads/master into rm-no-verify
* Merge refs/heads/master into rm-no-verify
* Merge refs/heads/master into rm-no-verify
* Merge refs/heads/master into rm-no-verify
* Merge refs/heads/master into rm-no-verify
* Merge refs/heads/master into rm-no-verify
* Merge refs/heads/master into rm-no-verify
* Merge refs/heads/master into rm-no-verify
* Merge refs/heads/master into rm-no-verify
* Merge refs/heads/master into rm-no-verify
* Merge refs/heads/master into rm-no-verify
* Merge refs/heads/master into rm-no-verify
* Merge refs/heads/master into rm-no-verify
* Merge refs/heads/master into rm-no-verify
* Merge refs/heads/master into rm-no-verify
* Merge refs/heads/master into rm-no-verify
2020-08-20 19:53:22 +00:00
rkapka
89e279f9c8 Account commands cleanup (#7065)
* initial implementation of command
* Add second confirmation step
* Merge branch 'origin-master' into voluntary-exit-command
* fix variable name
* added unit tests
* Merge branch 'origin-master' into voluntary-exit-command
* add comment about stdin
* remove backup-related code from accounts_delete_test
* fix comments
* move filterPublicKeysFromUserInput to new account helper
* remove SkipMnemonicConfirmFlag
* Merge refs/heads/master into voluntary-exit-command
* Merge refs/heads/master into voluntary-exit-command
* Merge refs/heads/master into voluntary-exit-command
* Merge refs/heads/master into voluntary-exit-command
* Merge refs/heads/master into voluntary-exit-command
* Merge refs/heads/master into voluntary-exit-command
* Merge refs/heads/master into voluntary-exit-command
* code review fixes
* removed commented-out code
* Merge branch 'voluntary-exit-command' into account-commands-cleanup

# Conflicts:
#	shared/promptutil/prompt.go
* Merge branch 'origin-master' into account-commands-cleanup

# Conflicts:
#	shared/promptutil/prompt.go
#	validator/accounts/v2/BUILD.bazel
#	validator/accounts/v2/accounts_exit.go
#	validator/accounts/v2/accounts_exit_test.go
* Merge refs/heads/master into account-commands-cleanup
2020-08-20 19:14:03 +00:00
terence tsao
40db6cb0cf Add slot in epoch (#7064)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-08-20 13:43:03 -05:00
rkapka
45e4ed25a3 Voluntary exit CLI command (#7046)
* initial implementation of command

* Add second confirmation step

* fix variable name

* added unit tests

* add comment about stdin

* code review fixes

* removed commented-out code

* added log assert

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-08-20 19:53:09 +02:00
terence tsao
e93d31c60e Use hot state cache for replay (#7063) 2020-08-20 08:53:10 -07:00
terence tsao
8bdf9db147 Add replay block count metric (#7060) 2020-08-20 06:20:26 -07:00
Shay Zluf
2bf1332e5c Slasher improvements (#7061)
* Slasher loging and span removal

* merge and reconnect fix

* ivan feedback
2020-08-20 10:31:16 +03:00
Nishant Das
7744c3ae47 Batch Block Roots Requesting (#7027)
* checkpoint
* Merge branch 'master' of https://github.com/prysmaticlabs/geth-sharding into batchRootReq
* test
* gaz
* fix test
* comment
* Merge refs/heads/master into multipleBranchProcessing
* Merge refs/heads/master into multipleBranchProcessing
* Merge refs/heads/master into multipleBranchProcessing
* Merge refs/heads/master into multipleBranchProcessing
* Merge refs/heads/master into multipleBranchProcessing
* Merge branch 'master' of https://github.com/prysmaticlabs/geth-sharding into batchRootReq
* terence's review
* Merge branch 'multipleBranchProcessing' of https://github.com/prysmaticlabs/geth-sharding into batchRootReq
2020-08-20 04:50:14 +00:00
Nishant Das
ba5da21026 Shift Sync Warn and Error Messages To Debug (#7059)
* change

* change
2020-08-20 11:30:41 +08:00
Preston Van Loon
395ea76f44 Save finalized checkpoint before migrate to cold (#7055)
* Save finalized checkpoint before migrate to cold
* Save finalized checkpoint before migrate to cold
* Merge branch 'master' into save-checkpoint-first
2020-08-19 21:11:44 +00:00
Preston Van Loon
3aa95b9c16 Use correct context for IsFinalizedBlock call (#7053)
* Use correct context for IsFinalizedBlock call
* Merge branch 'master' into use-correct-ctx
2020-08-19 19:55:39 +00:00
Ivan Martinez
bc20591b72 Accounts-V2: Change ListDirs() to Exists(), fix bug for derived (#7038)
* Change ListDirs() to Exists()
* Merge branch 'master' into fix-derived-pass
* Make function more accurate
* Merge branch 'fix-derived-pass' of github.com:prysmaticlabs/prysm into fix-derived-pass
* Merge refs/heads/master into fix-derived-pass
* Merge refs/heads/master into fix-derived-pass
* Merge refs/heads/master into fix-derived-pass
* Merge refs/heads/master into fix-derived-pass
* Merge refs/heads/master into fix-derived-pass
* Merge refs/heads/master into fix-derived-pass
* Merge refs/heads/master into fix-derived-pass
* Merge refs/heads/master into fix-derived-pass
* Merge refs/heads/master into fix-derived-pass
* Merge refs/heads/master into fix-derived-pass
2020-08-19 16:46:26 +00:00
Nishant Das
85a040bfd2 Default To Mainnet Config When Parsing Chain Config (#7052)
* add reg test
* Merge branch 'master' into defaultToMainnet
2020-08-19 15:42:24 +00:00
terence tsao
399dc85737 Use map to reject seen pending block (#7045) 2020-08-18 09:21:25 -07:00
Victor Farazdagi
9bf80219c9 Applies assertion funcs to slasher/* tests (#6998)
* slasher/beaconclient tests
* slasher/db/kv tests
* Merge branch 'master' into apply-testutils-assertions-to-slasher
* fix build
* slasher/detection tests
* rest of the tests
* misc tests
* Merge refs/heads/master into apply-testutils-assertions-to-slasher
* Merge refs/heads/master into apply-testutils-assertions-to-slasher
* Merge refs/heads/master into apply-testutils-assertions-to-slasher
* Merge refs/heads/master into apply-testutils-assertions-to-slasher
* Merge refs/heads/master into apply-testutils-assertions-to-slasher
* Merge refs/heads/master into apply-testutils-assertions-to-slasher
* Merge refs/heads/master into apply-testutils-assertions-to-slasher
* Merge refs/heads/master into apply-testutils-assertions-to-slasher
* Merge refs/heads/master into apply-testutils-assertions-to-slasher
* Merge refs/heads/master into apply-testutils-assertions-to-slasher
* Merge refs/heads/master into apply-testutils-assertions-to-slasher
* Merge refs/heads/master into apply-testutils-assertions-to-slasher
* Merge refs/heads/master into apply-testutils-assertions-to-slasher
* Merge refs/heads/master into apply-testutils-assertions-to-slasher
* Merge refs/heads/master into apply-testutils-assertions-to-slasher
* Merge refs/heads/master into apply-testutils-assertions-to-slasher
* Merge refs/heads/master into apply-testutils-assertions-to-slasher
* Merge refs/heads/master into apply-testutils-assertions-to-slasher
* Update slasher/db/kv/spanner_test.go

Co-authored-by: Shay Zluf <thezluf@gmail.com>
* Update slasher/node/node_test.go

Co-authored-by: Shay Zluf <thezluf@gmail.com>
* Merge refs/heads/master into apply-testutils-assertions-to-slasher
* Update slasher/db/kv/spanner_test.go
* Merge refs/heads/master into apply-testutils-assertions-to-slasher
2020-08-18 12:41:25 +00:00
Shay Zluf
14cd25f9dc Slasher span cache size flag (#7043)
* Span cache size by using flag
* Merge refs/heads/master into set_span_cache_size
2020-08-18 11:18:33 +00:00
Nishant Das
d81c9ffcfc Reject Duplicate Blocks From Being Saved (#7044)
* check for duplicates

* add test
2020-08-18 18:47:44 +08:00
Shay Zluf
27c8402ae0 Validator recheck slasher client status (#7041)
* Validator recheck slasher client status
* Merge branch 'master' into slasher_status_fix
* Merge branch 'master' into slasher_status_fix
* Merge refs/heads/master into slasher_status_fix
* Merge refs/heads/master into slasher_status_fix
2020-08-18 03:04:39 +00:00
Victor Farazdagi
0a5ec502b0 Updates resyncIfBehind() functionality (#7039)
* defines BestNonFinalized
* updates blocks_fetcher
* updates blocks_queue
* Merge branch 'master' into fix-resync
* Nishant's suggestion
* Merge branch 'fix-resync' of github.com:prysmaticlabs/prysm into fix-resync
* unit test
* Merge branch 'master' into fix-resync
* fixes test
* Merge refs/heads/master into fix-resync
2020-08-18 02:10:45 +00:00
Preston Van Loon
4d463c4a85 Don't ban blocks for context deadlines (#7040)
* Don't ban blocks for context deadlines
* Don't ban blocks for context deadlines
* Add test
* Merge branch 'master' into dont-ban-ctx-deadline2
* fmt
2020-08-18 01:21:10 +00:00
terence tsao
9caa92cae4 Pending queue to handle same slot blocks (#7036)
* Pending queue: rough draft
* Removed extra RUnlock
* apply diff
* Update pending queue tests
* Merge branch 'fix-pending-blocks' of github.com:prysmaticlabs/prysm into fix-pending-blocks
* Merge branch 'master' into fix-pending-blocks
* Comments
* Merge branch 'fix-pending-blocks' of github.com:prysmaticlabs/prysm into fix-pending-blocks
2020-08-18 00:01:32 +00:00
terence tsao
dbd1e8c247 Only cache check point state if it hasn't existed in other cache (#7037)
* Only cache epoch boundary state in the event of skipped epoch boundary slot

* checkpoint

* remove lods

* checkppoint again

* Cache: fill if empty

* Don't include the sync fixes

* Update sync utils

* Avoid extra process slots

Co-authored-by: nisdas <nishdas93@gmail.com>
2020-08-17 16:20:34 -05:00
Victor Farazdagi
bde3073bd6 Wait interval, before finalized peers re-checked (#7032)
* wait on no finalized peers
* Merge branch 'master' into better-no-finalized-peers-handling
2020-08-17 16:01:16 +00:00
Nishant Das
f193dc2f54 Do Not Retrieve From DB For Block Roots (#7028)
* don't use db
2020-08-17 08:41:45 +00:00
terence tsao
a2f781522f Update committee cache size to 32 (#7018)
* Update committee cache size to 32
* Merge branch 'master' into update-committee-cache-size
* Cache: fixed rotating test
* Merge branch 'update-committee-cache-size' of github.com:prysmaticlabs/prysm into update-committee-cache-size
* Merge refs/heads/master into update-committee-cache-size
* Merge refs/heads/master into update-committee-cache-size
* Merge refs/heads/master into update-committee-cache-size
2020-08-17 03:17:46 +00:00
Preston Van Loon
d66f72939e Ignore subscription cancelled warning (#7020)
* Resolve TODO #6449
* Merge refs/heads/master into fix-6449
2020-08-17 01:58:30 +00:00
Preston Van Loon
c3725d11f2 Revert "Sync: Dont ban block roots for context.DeadlineExceeded" (#7017)
* Revert "Sync: Dont ban block roots for context.DeadlineExceeded (#7016)"

This reverts commit a4bbd82a45.
* Merge refs/heads/master into revert-7016-dont-ban-ctx-deadline
2020-08-17 01:18:38 +00:00
terence tsao
715cd40f56 Sync: check blocks and roots lengths (#7019) 2020-08-16 16:48:39 -07:00
Preston Van Loon
a4bbd82a45 Sync: Dont ban block roots for context.DeadlineExceeded (#7016)
* Dont set bad block root if it was context deadline with processing
2020-08-16 19:24:34 +00:00
Nishant Das
0be1957c28 Use Stage 1 For Non Finalized Sync (#7012)
* checkpoint
* dont cancel
* remove
* sync mode
* fixes build
* cap max retries when no finalized peers are found
* use max peers
* change it
* fixes TestService_roundRobinSync/Multiple_peers_with_different_finalized_epoch
* fixes blocks fetcher tests
* fixes blocks queue tests
* fixes TestService_blockProviderScoring test
* gofmt
* Merge branch 'master' into useStage1
* Update round_robin.go

preston's review
* Preston's suggestions
* Merge branch 'useStage1' of github.com:prysmaticlabs/prysm into useStage1
* fixes test
2020-08-16 17:51:14 +00:00
terence tsao
9ebd90c324 Use LRU for checkpoint state cache (#7010)
* DB: add block roots test

* Pool: add seen atts map

* Pool: use seen atts map

* Pool: clear seen map

* Core: optimize InitiateValidatorExit

* Cache: checkpoint state uses LRU

* Cache: use it

* Cache: update tests

* Cache: typo

* Gaz
2020-08-16 07:36:37 -07:00
terence tsao
03c3f06288 Core: optimize InitiateValidatorExit and ProcessAttesterSlashings (#7008)
* Core: optimize InitiateValidatorExit

* Core: optimize

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-08-15 14:01:46 -05:00
terence tsao
c47d18aa0b Featureflag test: reset init (#7007)
* Featureflag: properly init test
* Merge refs/heads/master into fix-feature-test
2020-08-15 15:48:12 +00:00
Nishant Das
17b810f24e Fix 2nd Stage of Sync (#7006)
* handle 2nd stage better
* 2 stage sort
* add warning
* better processing
* victor's review
* fix one test
* Update beacon-chain/blockchain/receive_block.go
* fixes TestService_roundRobinSync/Multiple_peers_with_many_skipped_slots
* Merge branch 'fixSync' of github.com:prysmaticlabs/prysm into fixSync
* fixes TestService_process
* fixes TestService_blockProviderScoring
* Preston's suggestion
* increase number of available slots, allowing 2nd phase to wrap up
* more concise limits
2020-08-15 15:14:59 +00:00
Nishant Das
ee2ba721ab Initialize Config Correctly (#7004)
* initialize correctly
2020-08-15 01:37:57 +00:00
Noah Citron
d24f99d66d added flag to enable roughtime syncing, with it disabled by default (#6898)
* added flag to enable roughtime syncing, with it disabled by defaults

* gofmt

* switched to feature flag

* enable-roughtime works correctly

* enable-roughtime works correctly

* Gaz

* Remove conflict

* fix roughtime enable

Co-authored-by: Ivan Martinez <ivanthegreatdev@gmail.com>
Co-authored-by: rauljordan <raul@prysmaticlabs.com>
2020-08-14 14:22:58 -05:00
Raul Jordan
3c776f4e76 Fix Validator RPC JWT Response (#7001)
* fix jwt response
* fix jwt parse
* ken naming
* gaz
2020-08-14 16:30:11 +00:00
terence tsao
b981442022 Register health APIs handler (#6999)
* DB: add block roots test
* Merge branch 'master' of github.com:prysmaticlabs/prysm
* Merge branch 'master' of github.com:prysmaticlabs/prysm
* Pool: add seen atts map
* Pool: use seen atts map
* Pool: clear seen map
* Merge branch 'master' of github.com:prysmaticlabs/prysm
* Merge branch 'master' of github.com:prysmaticlabs/prysm
* RPC: register health endpoint
* Gazelle
2020-08-14 15:18:04 +00:00
Victor Farazdagi
6db448a81d Uncomments tests in kv/unaggregated_test (#6997)
* uncomments tests in kv/unaggregated_test
2020-08-14 07:23:42 +00:00
Raul Jordan
f5a1a8b4ed Integrate Validator RPC Server Into Runtime + Add Gateway (#6994) 2020-08-13 19:49:57 -07:00
terence tsao
3df2980cba Add and utilize seen atts map (#6993)
* DB: add block roots test

* Pool: add seen atts map

* Pool: use seen atts map

* Pool: clear seen map

* Gazelle

* Fixed an existing test

Co-authored-by: rauljordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-08-13 16:52:27 -05:00
Raul Jordan
16c34b627f Add Authentication Functions to Validator RPC (#6968)
* define auth endpoints
* add intercepter with tests
* auth functions
* fix up the auth functions
* add functions for storing and saving the hashed password from the validator db
* validate strong password input and simplify jwt claims
* tests for db funcs
* comments for db funcs
* wrap up the authentication tests
* register auth srv
* use proper db iface package and check if existing password
* fix broken tests and add new test to check if password already exists
* use roughtime
* rlock to check the auth paths
* Merge refs/heads/master into auth-rpc
* Merge refs/heads/master into auth-rpc
* Merge refs/heads/master into auth-rpc
* leave out the stream interceptor
* resolve confs
* Merge branch 'master' into auth-rpc
* confs
* Merge branch 'auth-rpc' of github.com:prysmaticlabs/prysm into auth-rpc
* Merge refs/heads/master into auth-rpc
* Merge refs/heads/master into auth-rpc
* Merge refs/heads/master into auth-rpc
* Merge refs/heads/master into auth-rpc
2020-08-13 20:27:42 +00:00
Ivan Martinez
6ed0539723 Acconuts-V2: Allow importing from any valid keystore, regardless of name (#6992)
* Allow importing from any file

* Fix log

* Add test

* Fix test
2020-08-13 14:45:56 -05:00
Victor Farazdagi
4de0b9fe69 Peer scoring: init sync (#6709)
* refactors redundant part of varname
* introduces score_block_providers
* Merge branch 'master' into init-sync-peer-scoring-slow-peers
* gazelle
* adds comment
* Merge branch 'master' into init-sync-peer-scoring-slow-peers
* removes redundant checks
* add block provider decay test
* Merge branch 'master' into init-sync-peer-scoring-slow-peers
* adds case
* penalize inactive peers
* adds scorebadresponses test
* inroduces no-activity penalty
* gazelle
* gofmt
* Merge branch 'master' into init-sync-peer-scoring-slow-peers
* expanded tests
* implement SortBlockProviders
* change -> update
* updates block fetcher peer filter
* fixes test
* allows to keep track of peer id
* updates scoring coefficients
* fixes test
* block fetcher update
* Merge branch 'master' into init-sync-peer-scoring-slow-peers
* disables empty batch penalty
* Merge branch 'master' into init-sync-peer-scoring-slow-peers
* Merge branch 'master' into init-sync-peer-scoring-slow-peers
* removes outdated code
* update filterPeers
* gazelle
* updates var
* revert changes to var name
* updates blocks_fetcher
* minor fix to import name
* Merge branch 'master' into init-sync-peer-scoring-slow-peers
* add max processed blocks cap
* impoves scoring of stale peers
* Merge branch 'master' into init-sync-peer-scoring-slow-peers
* fixes test
* adds weight sorting to scored peers
* return pid when fetching batches
* updates round robin
* gazelle
* Merge branch 'master' into init-sync-peer-scoring-slow-peers
* updates block provider decay count
* go tidy
* cherry pick
* fixes test
* go tidy
* Merge branch 'peer-scorer-weighted-sorter' into init-sync-peer-scoring-slow-peers
* Merge branch 'master' into init-sync-peer-scoring-slow-peers
* Merge branch 'master' into init-sync-peer-scoring-slow-peers
* refactors blocks fetcher: repackage methods
* Merge branch 'refactor-blocks-fetcher' into init-sync-peer-scoring-slow-peers
* minor fixes
* Merge branch 'master' into init-sync-peer-scoring-slow-peers
* Merge branch 'master' into init-sync-peer-scoring-slow-peers
* allow scores in range (0;1) in weighted filter
* filterScoredPeers improve test suite
* puts feature behind the flag
* Merge branch 'master' into init-sync-peer-scoring-slow-peers
* Merge refs/heads/master into init-sync-peer-scoring-slow-peers
* fixes tests
* Merge branch 'init-sync-peer-scoring-slow-peers' of github.com:prysmaticlabs/prysm into init-sync-peer-scoring-slow-peers
* Merge refs/heads/master into init-sync-peer-scoring-slow-peers
* Merge branch 'master' into init-sync-peer-scoring-slow-peers
* Merge refs/heads/master into init-sync-peer-scoring-slow-peers
* Update beacon-chain/sync/initial-sync/blocks_fetcher_test.go

Co-authored-by: Shay Zluf <thezluf@gmail.com>
* Nishant's suggestion on peer limit variable
* better explanation of non-blocking peer scoring
* Shay's sugession on peer naming
* Merge refs/heads/master into init-sync-peer-scoring-slow-peers
* Merge refs/heads/master into init-sync-peer-scoring-slow-peers
* Update beacon-chain/sync/initial-sync/blocks_fetcher.go

Co-authored-by: Nishant Das <nishdas93@gmail.com>
* Merge refs/heads/master into init-sync-peer-scoring-slow-peers
* gofmt
* Merge refs/heads/master into init-sync-peer-scoring-slow-peers
* Merge refs/heads/master into init-sync-peer-scoring-slow-peers
* Merge refs/heads/master into init-sync-peer-scoring-slow-peers
2020-08-13 17:33:57 +00:00
Nishant Das
282398fd13 Add in Attestation Validity Check (#6983)
* fix bad bug
* add test
* Merge refs/heads/master into fixAttestationNoVerify
* Merge refs/heads/master into fixAttestationNoVerify
* target
* Merge branch 'fixAttestationNoVerify' of https://github.com/prysmaticlabs/geth-sharding into fixAttestationNoVerify
* add cheap check
* Merge refs/heads/master into fixAttestationNoVerify
* Merge refs/heads/master into fixAttestationNoVerify
* Merge refs/heads/master into fixAttestationNoVerify
* Merge refs/heads/master into fixAttestationNoVerify
* Merge refs/heads/master into fixAttestationNoVerify
2020-08-13 16:58:28 +00:00
Victor Farazdagi
74101612ce Moves AssertLogsContains to assertions package (#6985)
* first working implementation
* assertions tests
* adds to requires
* merges assert and require tests into a single suite
* gazelle
* Merge branch 'merge-assert-require-tests' into assert-logs-contains-move-to-assertions
* gazelle
* updates references
* fixes build issue
* Merge branch 'master' into assert-logs-contains-move-to-assertions
* Merge refs/heads/master into assert-logs-contains-move-to-assertions
* Merge branch 'master' into assert-logs-contains-move-to-assertions
* fixes build issue
* Merge branch 'assert-logs-contains-move-to-assertions' of github.com:prysmaticlabs/prysm into assert-logs-contains-move-to-assertions
* Merge refs/heads/master into assert-logs-contains-move-to-assertions
* Merge refs/heads/master into assert-logs-contains-move-to-assertions
2020-08-13 16:22:25 +00:00
terence tsao
308dbc4272 ListStatuses for validator RPC (#6987)
* DB: add block roots test
* Merge branch 'master' of github.com:prysmaticlabs/prysm
* Client: support ValidatorPubkeysToStatuses getter
* RPC: implement ListStatuses
* RPC: tests
* Merge branch 'master' into health-apis
* Update an existing test
* Merge branch 'health-apis' of github.com:prysmaticlabs/prysm into health-apis
* Merge refs/heads/master into health-apis
2020-08-13 15:52:56 +00:00
Ivan Martinez
5705a9a1f9 Accounts-V2: Add test for DeleteAccounts (#6982)
* Add test for DeleteAccounts
* attempt to fix
* Try to fix test
* Remove
* fixed Ivan's test
* Merge branch 'master' into add-delete-test
2020-08-13 15:23:08 +00:00
Nishant Das
72bbc33a65 Fix Validator Exits (#6986)
* add change
* Update beacon-chain/core/blocks/exit.go

Co-authored-by: Shay Zluf <thezluf@gmail.com>
* Merge refs/heads/master into fixExits
2020-08-13 14:37:38 +00:00
Victor Farazdagi
dc752fb945 Merges assert and require tests into a single suite (#6984)
* merges assert and require tests into a single suite
* gazelle
2020-08-13 13:57:29 +00:00
Victor Farazdagi
0c94298847 Peer scorer: fix weighted sorting (#6981)
* peer scorer: fix weighted sorting
* Merge refs/heads/master into minor-fixes-to-peer-scorer
* Merge refs/heads/master into minor-fixes-to-peer-scorer
2020-08-13 09:36:50 +00:00
Victor Farazdagi
7611f6d84a injects peer.ID into requested/queued/fetched batches (#6979)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-08-13 16:42:21 +08:00
terence tsao
49549f4687 ListBalances for validator RPC (#6975)
* DB: add block roots test

* Node: register RPC service

* RPC: access to client service

* Client: add balances and pubkeys -> indices getters

* Update validator/client/metrics.go

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

* Lint and feedbacks

* Fix lock to prevent a run time panic

* Fixes existing tests

* Validator: add mock for testing

* Validator: Add pubkeys to indices getter

* RPC: tests tests tests

* Lint

* Lint

* Lint

* Lint

* Lint

* Gazelle

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2020-08-12 18:33:15 -05:00
terence tsao
0d7ea33298 DB: add block roots test (#6974) 2020-08-12 11:28:52 -05:00
Javed Khan
2400536a8e Update sendDepositTx tool (#6972)
* Update sendDepositTx contract address

* Use Medalla config in sendDepositTx

* Update sendDepositTx  - geth not necessary
2020-08-12 22:15:37 +08:00
Victor Farazdagi
da4e96047b go syntax representation of the value in DeepEqual assertions (#6970) 2020-08-12 17:46:56 +08:00
terence tsao
f4d808a542 Validator web RPC skeleton (#6967)
* Proto: remove unused ethapi imports
* Validator: web rpc
* Lint
* Sync with master
* Merge refs/heads/master into web-rpc
* rename
2020-08-12 01:38:01 +00:00
Raul Jordan
86b2bd5edd Implement Accounts-V2 Backup for Direct Keymanager (#6936)
* progress on export feature
* Merge branch 'master' into impl-export
* rename func
* imports
* confs
* export single works
* impl export
* Merge branch 'master' into impl-export
* cleanup exports code
* rename to backup
* rename to backup
* Merge branch 'master' into impl-export
* full test for backup
* Merge branch 'impl-export' of github.com:prysmaticlabs/prysm into impl-export
* gazelle fix
* terence feedback
* merge confs
* Merge branch 'master' into impl-export
* refactor into single select accounts function
* gaz
* Merge refs/heads/master into impl-export
* victor's feedback
* validate yes or no
* confs
* close the zip file in defer
* Merge refs/heads/master into impl-export
* Merge refs/heads/master into impl-export
2020-08-11 23:15:06 +00:00
terence tsao
682401c6b0 Health related web api protos (#6965)
* Proto: first attempt of account related web api protos
* Proto: health related web api protos
* Merge branch 'master' of github.com:prysmaticlabs/prysm into validator-protos-1
* Merge branch 'master' of github.com:prysmaticlabs/prysm into validator-protos-1
* Sync with master
* @rauljordan's feedback
2020-08-11 22:33:03 +00:00
terence tsao
4499fb2ed0 First attempt of account related web api protos (#6964) 2020-08-11 13:23:16 -07:00
terence tsao
46cb3abe2e Add and use genesis time in config (#6966)
* Config: add genesis time and update medalla

* Helper: add GenesisTime getter

* Rest: use the helper
2020-08-11 14:36:32 -05:00
Raul Jordan
11c9699129 Allow Importing One-Off, Private Keys Into Accounts-v2 (#6929)
* import privkey done
* rem print
* tidy
* Merge refs/heads/master into import-priv-key
* Merge refs/heads/master into import-priv-key
* Merge branch 'master' into import-priv-key
* tests pass
* Merge refs/heads/master into import-priv-key
* Merge refs/heads/master into import-priv-key
* resolve confs
* Merge refs/heads/master into import-priv-key
* confs
* Merge refs/heads/master into import-priv-key
* better feedback mechanism
2020-08-11 16:32:05 +00:00
Victor Farazdagi
c24666e02e refactors blocks fetcher: repackage methods (#6962) 2020-08-11 10:15:18 -05:00
Victor Farazdagi
a279f374bc Move to opt-out attestation-aggregation-strategy flag (#6960)
* inverts attestation-aggregation-strategy flag
* Merge refs/heads/master into att-aggregation-opt-out-flag
* marks deprected flag as hidden
* Merge branch 'att-aggregation-opt-out-flag' of github.com:prysmaticlabs/prysm into att-aggregation-opt-out-flag
* Merge refs/heads/master into att-aggregation-opt-out-flag
2020-08-11 12:42:08 +00:00
rkapka
a5f0fd29fc Fix antipatterns (#6961)
* Merge variable declaration and assignment
* Use result of type assertion to simplify cases
* Replace call to bytes.Compare with bytes.Equal
* Drop unnecessary use of the blank identifier
* Replace x.Sub(time.Now()) with time.Until(x)
* Function literal can be simplified
* Use a single append to concatenate two slices
* Replace time.Now().Sub(x) with time.Since(x)
* Omit comparison with boolean constant
* Omit redundant nil check on slices
* Nested if can be replaced with else-if
* Function call can be replaced with helper function
* Omit redundant control flow
* Use plain channel send or receive
* Simplify returning boolean expression
* Merge branch 'origin-master' into fix-antipatterns
* Merge branch 'master' into fix-antipatterns
* Merge branch 'origin-master' into revert-single-channel-antipattern
* Revert "Use plain channel send or receive"

This reverts commit b3108fdc3a.
2020-08-11 12:14:28 +00:00
Nishant Das
b32ccce23d Remove Checked In Metadata File (#6959)
* Delete metaData
2020-08-11 11:26:59 +00:00
Nishant Das
3893ee43f9 support domains in discoveryV5 (#6958) 2020-08-11 18:33:27 +08:00
Ivan Martinez
ea9bb88d13 Accounts-V2: Add command to delete accounts (#6941)
* Add accounts-v2 delete
* Merge branch 'master' of github.com:prysmaticlabs/prysm into add-delete-command
* Gaz
* Add confirmation
* Fix build
* Fix test
* Merge branch 'master' into add-delete-command
* Add more cases for exit
* Merge branch 'master' of github.com:prysmaticlabs/prysm into add-delete-command
* Fix usage
* Fix logs
* Change to DeleteAccounts
* Remove flag
* Fix comment
2020-08-11 03:54:37 +00:00
terence tsao
537fe3f721 Fix loading historical blocks to replay cold state (#6956)
* Replay: cold state only uses finalized blocks
* Replay: regression test
* Merge refs/heads/master into fix-finalized-replay
2020-08-10 23:35:28 +00:00
Ivan Martinez
8b9138a76a Accounts V2: Log and UX cleanup (#6955)
* Clena up password entry for importing
* Merge branch 'master' of github.com:prysmaticlabs/prysm into accounts-v2-cleanup
* Fix password entry
* Clean
* Merge branch 'master' of github.com:prysmaticlabs/prysm into accounts-v2-cleanup
* Change color
* Merge branch 'master' of github.com:prysmaticlabs/prysm into accounts-v2-cleanup
* Fix
* Merge branch 'master' of github.com:prysmaticlabs/prysm into accounts-v2-cleanup
* Fix
* Merge branch 'master' of github.com:prysmaticlabs/prysm into accounts-v2-cleanup
* Cleanup
* Clean go.mod
* Fix
2020-08-10 22:35:30 +00:00
terence tsao
ceb11f432e Proposer: log graffiti (#6954)
* Proposer: log graffiti
* Merge refs/heads/master into log-graffiti
2020-08-10 19:17:59 +00:00
854 changed files with 57773 additions and 16472 deletions

View File

@@ -33,9 +33,17 @@ build --define kafka_enabled=false
test --define kafka_enabled=false
run --define kafka_enabled=false
# Enable blst by default, we use a config so that our fuzzer stops complaining.
build --config=blst_enabled
test --config=blst_enabled
run --config=blst_enabled
build:kafka_enabled --define kafka_enabled=true
build:kafka_enabled --define gotags=kafka_enabled
build:blst_enabled --define blst_enabled=true
build:blst_enabled --define gotags=blst_enabled
# Release flags
build:release --workspace_status_command=./scripts/workspace_status.sh
build:release --stamp
@@ -69,18 +77,13 @@ build:fuzz --copt=-fno-omit-frame-pointer
build:fuzz --define=FUZZING_ENGINE=libfuzzer
build:fuzz --copt=-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
build:fuzz --linkopt -Wl,--no-as-needed
build:fuzz --define=gc_goopts=-d=libfuzzer
build:fuzz --define=gc_goopts=-d=libfuzzer,checkptr
build:fuzz --run_under=//tools:fuzz_wrapper
build:fuzz --compilation_mode=opt
build:fuzz --define=blst_enabled=false
test:fuzz --local_test_jobs="HOST_CPUS*.5"
test:fuzzit --config=fuzz
test:fuzzit --test_env=FUZZIT_API_KEY
test:fuzzit --test_env=PRYSM_BUILD_IMAGE=gcr.io/prysmaticlabs/prysm-fuzzit:v0.11.0
test:fuzzit --test_timeout=1200
test:fuzzit --run_under=//tools:fuzzit_wrapper
# Build binary with cgo symbolizer for debugging / profiling.
build:cgo_symbolizer --config=llvm
build:cgo_symbolizer --copt=-g

View File

@@ -3,10 +3,10 @@
#
# This config is loaded from https://github.com/bazelbuild/bazel-toolchains/blob/master/bazelrc/latest.bazelrc
build:remote-cache --remote_timeout=3600
build:remote-cache --spawn_strategy=standalone
build:remote-cache --strategy=Javac=standalone
build:remote-cache --strategy=Closure=standalone
build:remote-cache --strategy=Genrule=standalone
#build:remote-cache --spawn_strategy=standalone
#build:remote-cache --strategy=Javac=standalone
#build:remote-cache --strategy=Closure=standalone
#build:remote-cache --strategy=Genrule=standalone
# Prysm specific remote-cache properties.
#build:remote-cache --disk_cache=
@@ -34,16 +34,5 @@ build --flaky_test_attempts=5
# Disabled race detection due to unstable test results under constrained environment build kite
# build --features=race
# Enable kafka for CI tests only.
test --config=kafka_enabled
build --bes_backend=grpcs://builds.prylabs.net:1985
build --bes_results_url=https://builds.prylabs.net/invocation/
# Disable flaky test detection for fuzzing.
test:fuzz --flaky_test_attempts=1
# Expose test environment variables in CI
test:fuzzit --test_env=GITHUB_REF
test:fuzzit --test_env=GITHUB_SHA
test:fuzzit --test_env=DOCKER_HOST

12
.deepsource.toml Normal file
View File

@@ -0,0 +1,12 @@
version = 1
[[analyzers]]
name = "go"
enabled = true
[analyzers.meta]
import_paths = ["github.com/prysmaticlabs/prysm"]
[[analyzers]]
name = "test-coverage"
enabled = true

View File

@@ -43,7 +43,8 @@ jobs:
go get -v -t -d ./...
- name: Build
run: go build -v ./...
# Use blst tag to allow go and bazel builds for blst.
run: go build -v --tags=blst_enabled ./...
# Tests run via Bazel for now...
# - name: Test

4
.gitignore vendored
View File

@@ -29,3 +29,7 @@ password.txt
# Dist files
dist
# libfuzzer
oom-*
crash-*

View File

@@ -104,10 +104,14 @@ nogo(
"@org_golang_x_tools//go/analysis/passes/inspect:go_tool_library",
"@org_golang_x_tools//go/analysis/passes/asmdecl:go_tool_library",
"//tools/analyzers/maligned:go_tool_library",
"//tools/analyzers/roughtime:go_tool_library",
"//tools/analyzers/cryptorand:go_tool_library",
"//tools/analyzers/errcheck:go_tool_library",
"//tools/analyzers/featureconfig:go_tool_library",
"//tools/analyzers/comparesame:go_tool_library",
"//tools/analyzers/shadowpredecl:go_tool_library",
"//tools/analyzers/nop:go_tool_library",
"//tools/analyzers/slicedirect:go_tool_library",
"//tools/analyzers/ineffassign:go_tool_library",
] + select({
# nogo checks that fail with coverage enabled.
":coverage_enabled": [],

View File

@@ -1,7 +1,7 @@
# Prysm: An Ethereum 2.0 Client Written in Go
[![Build status](https://badge.buildkite.com/b555891daf3614bae4284dcf365b2340cefc0089839526f096.svg?branch=master)](https://buildkite.com/prysmatic-labs/prysm)
[![ETH2.0_Spec_Version 0.12.2](https://img.shields.io/badge/ETH2.0%20Spec%20Version-v0.12.2-blue.svg)](https://github.com/ethereum/eth2.0-specs/tree/v0.12.2)
[![ETH2.0_Spec_Version 0.12.3](https://img.shields.io/badge/ETH2.0%20Spec%20Version-v0.12.3-blue.svg)](https://github.com/ethereum/eth2.0-specs/tree/v0.12.3)
[![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

@@ -5,11 +5,11 @@ load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
http_archive(
name = "bazel_toolchains",
sha256 = "144290c4166bd67e76a54f96cd504ed86416ca3ca82030282760f0823c10be48",
strip_prefix = "bazel-toolchains-3.1.1",
sha256 = "db48eed61552e25d36fe051a65d2a329cc0fb08442627e8f13960c5ab087a44e",
strip_prefix = "bazel-toolchains-3.2.0",
urls = [
"https://github.com/bazelbuild/bazel-toolchains/releases/download/3.1.1/bazel-toolchains-3.1.1.tar.gz",
"https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/archive/3.1.1.tar.gz",
"https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/releases/download/3.2.0/bazel-toolchains-3.2.0.tar.gz",
"https://github.com/bazelbuild/bazel-toolchains/releases/download/3.2.0/bazel-toolchains-3.2.0.tar.gz",
],
)
@@ -161,6 +161,10 @@ load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies")
gazelle_dependencies()
load("@io_bazel_rules_go//extras:embed_data_deps.bzl", "go_embed_data_dependencies")
go_embed_data_dependencies()
load("@com_github_atlassian_bazel_tools//gometalinter:deps.bzl", "gometalinter_dependencies")
gometalinter_dependencies()
@@ -215,8 +219,8 @@ filegroup(
visibility = ["//visibility:public"],
)
""",
sha256 = "9e09ada15c5f494388ecdb3ab49f4554d9ed53ce904cd21c42c350e6d7b2f323",
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.12.2/general.tar.gz",
sha256 = "7e5f838e0f9110471ef8be9401ea687a8ed4d499664dc0eac34ecfdfd03c2ac3",
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.12.3/general.tar.gz",
)
http_archive(
@@ -231,8 +235,8 @@ filegroup(
visibility = ["//visibility:public"],
)
""",
sha256 = "5fc930e200af7682a176d6025db56cec79807112bb860dca2e1e91fb160312de",
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.12.2/minimal.tar.gz",
sha256 = "72c2f561db879ddcdf729fef93d10e0f9162b4cf3a697c513ef8935b93f6165a",
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.12.3/minimal.tar.gz",
)
http_archive(
@@ -247,8 +251,8 @@ filegroup(
visibility = ["//visibility:public"],
)
""",
sha256 = "fbab14605a0178ef4c8f7efea0de275a22b815a8d3245099f0f5525f7a33faf8",
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.12.2/mainnet.tar.gz",
sha256 = "63eca02503692a0b6a2d7b70118e0dd62dff094153a3a542af6dbea721841b0d",
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.12.3/mainnet.tar.gz",
)
http_archive(
@@ -336,6 +340,22 @@ go_binary(
urls = ["https://github.com/ferranbt/fastssz/archive/06015a5d84f9e4eefe2c21377ca678fa8f1a1b09.tar.gz"],
)
http_archive(
name = "prysm_web_ui",
build_file_content = """
filegroup(
name = "site",
srcs = glob(["**/*"]),
visibility = ["//visibility:public"],
)
""",
sha256 = "507d574be56a63d5a30a28b4426b9ece89cf70bbb29739e982e0a8fdf1285e3a",
urls = [
"https://prysmaticlabs.com/uploads/prysm-web-ui.0.0.1-alpha.tar.gz",
"https://github.com/prysmaticlabs/prysm-web-ui/releases/download/0.0.1-alpha/prysm-web-ui.tar.gz",
],
)
load("//:deps.bzl", "prysm_deps")
# gazelle:repository_macro deps.bzl%prysm_deps

View File

@@ -5,6 +5,7 @@ go_library(
name = "go_default_library",
srcs = [
"chain_info.go",
"checkpoint_info_cache.go",
"head.go",
"info.go",
"init_sync_process_block.go",
@@ -17,9 +18,13 @@ go_library(
"receive_attestation.go",
"receive_block.go",
"service.go",
"weak_subjectivity_checks.go",
],
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/blockchain",
visibility = ["//beacon-chain:__subpackages__"],
visibility = [
"//beacon-chain:__subpackages__",
"//fuzz:__pkg__",
],
deps = [
"//beacon-chain/cache:go_default_library",
"//beacon-chain/cache/depositcache:go_default_library",
@@ -30,6 +35,7 @@ go_library(
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/core/state:go_default_library",
"//beacon-chain/db:go_default_library",
"//beacon-chain/db/filters:go_default_library",
"//beacon-chain/flags:go_default_library",
"//beacon-chain/forkchoice:go_default_library",
"//beacon-chain/forkchoice/protoarray:go_default_library",
@@ -40,17 +46,18 @@ go_library(
"//beacon-chain/powchain:go_default_library",
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/stategen:go_default_library",
"//beacon-chain/state/stateutil:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//shared/attestationutil:go_default_library",
"//shared/bls:go_default_library",
"//shared/bytesutil:go_default_library",
"//shared/featureconfig:go_default_library",
"//shared/hashutil:go_default_library",
"//shared/params:go_default_library",
"//shared/roughtime:go_default_library",
"//shared/slotutil:go_default_library",
"//shared/timeutils:go_default_library",
"//shared/traceutil:go_default_library",
"@com_github_emicklei_dot//:go_default_library",
"@com_github_hashicorp_golang_lru//:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_prometheus_client_golang//prometheus:go_default_library",
"@com_github_prometheus_client_golang//prometheus/promauto:go_default_library",
@@ -73,6 +80,7 @@ go_test(
size = "medium",
srcs = [
"chain_info_test.go",
"checkpoint_info_cache_test.go",
"head_test.go",
"info_test.go",
"process_attestation_test.go",
@@ -80,6 +88,7 @@ go_test(
"receive_attestation_test.go",
"receive_block_test.go",
"service_test.go",
"weak_subjectivity_checks_test.go",
],
embed = [":go_default_library"],
deps = [

View File

@@ -5,14 +5,14 @@ import (
"time"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"go.opencensus.io/trace"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
"go.opencensus.io/trace"
)
// ChainInfoFetcher defines a common interface for methods in blockchain service which
@@ -97,6 +97,9 @@ func (s *Service) PreviousJustifiedCheckpt() *ethpb.Checkpoint {
// HeadSlot returns the slot of the head of the chain.
func (s *Service) HeadSlot() uint64 {
s.headLock.RLock()
defer s.headLock.RUnlock()
if !s.hasHeadState() {
return 0
}
@@ -106,6 +109,9 @@ func (s *Service) HeadSlot() uint64 {
// HeadRoot returns the root of the head of the chain.
func (s *Service) HeadRoot(ctx context.Context) ([]byte, error) {
s.headLock.RLock()
defer s.headLock.RUnlock()
if s.headRoot() != params.BeaconConfig().ZeroHash {
r := s.headRoot()
return r[:], nil
@@ -119,7 +125,7 @@ func (s *Service) HeadRoot(ctx context.Context) ([]byte, error) {
return params.BeaconConfig().ZeroHash[:], nil
}
r, err := stateutil.BlockRoot(b.Block)
r, err := b.Block.HashTreeRoot()
if err != nil {
return nil, err
}
@@ -131,6 +137,9 @@ func (s *Service) HeadRoot(ctx context.Context) ([]byte, error) {
// If the head is nil from service struct,
// it will attempt to get the head block from DB.
func (s *Service) HeadBlock(ctx context.Context) (*ethpb.SignedBeaconBlock, error) {
s.headLock.RLock()
defer s.headLock.RUnlock()
if s.hasHeadState() {
return s.headBlock(), nil
}
@@ -144,6 +153,8 @@ func (s *Service) HeadBlock(ctx context.Context) (*ethpb.SignedBeaconBlock, erro
func (s *Service) HeadState(ctx context.Context) (*state.BeaconState, error) {
ctx, span := trace.StartSpan(ctx, "blockChain.HeadState")
defer span.End()
s.headLock.RLock()
defer s.headLock.RUnlock()
ok := s.hasHeadState()
span.AddAttributes(trace.BoolAttribute("cache_hit", ok))
@@ -157,6 +168,9 @@ func (s *Service) HeadState(ctx context.Context) (*state.BeaconState, error) {
// HeadValidatorsIndices returns a list of active validator indices from the head view of a given epoch.
func (s *Service) HeadValidatorsIndices(ctx context.Context, epoch uint64) ([]uint64, error) {
s.headLock.RLock()
defer s.headLock.RUnlock()
if !s.hasHeadState() {
return []uint64{}, nil
}
@@ -165,6 +179,9 @@ func (s *Service) HeadValidatorsIndices(ctx context.Context, epoch uint64) ([]ui
// HeadSeed returns the seed from the head view of a given epoch.
func (s *Service) HeadSeed(ctx context.Context, epoch uint64) ([32]byte, error) {
s.headLock.RLock()
defer s.headLock.RUnlock()
if !s.hasHeadState() {
return [32]byte{}, nil
}
@@ -174,6 +191,9 @@ func (s *Service) HeadSeed(ctx context.Context, epoch uint64) ([32]byte, error)
// HeadGenesisValidatorRoot returns genesis validator root of the head state.
func (s *Service) HeadGenesisValidatorRoot() [32]byte {
s.headLock.RLock()
defer s.headLock.RUnlock()
if !s.hasHeadState() {
return [32]byte{}
}
@@ -183,6 +203,9 @@ func (s *Service) HeadGenesisValidatorRoot() [32]byte {
// HeadETH1Data returns the eth1data of the current head state.
func (s *Service) HeadETH1Data() *ethpb.Eth1Data {
s.headLock.RLock()
defer s.headLock.RUnlock()
if !s.hasHeadState() {
return &ethpb.Eth1Data{}
}
@@ -202,6 +225,9 @@ func (s *Service) GenesisTime() time.Time {
// GenesisValidatorRoot returns the genesis validator
// root of the chain.
func (s *Service) GenesisValidatorRoot() [32]byte {
s.headLock.RLock()
defer s.headLock.RUnlock()
if !s.hasHeadState() {
return [32]byte{}
}
@@ -210,6 +236,9 @@ func (s *Service) GenesisValidatorRoot() [32]byte {
// CurrentFork retrieves the latest fork information of the beacon chain.
func (s *Service) CurrentFork() *pb.Fork {
s.headLock.RLock()
defer s.headLock.RUnlock()
if !s.hasHeadState() {
return &pb.Fork{
PreviousVersion: params.BeaconConfig().GenesisForkVersion,

View File

@@ -1,7 +1,6 @@
package blockchain
import (
"bytes"
"context"
"testing"
"time"
@@ -11,22 +10,22 @@ import (
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
)
// Ensure Service implements chain info interface.
var _ = ChainInfoFetcher(&Service{})
var _ = TimeFetcher(&Service{})
var _ = ForkFetcher(&Service{})
var _ ChainInfoFetcher = (*Service)(nil)
var _ TimeFetcher = (*Service)(nil)
var _ ForkFetcher = (*Service)(nil)
func TestFinalizedCheckpt_Nil(t *testing.T) {
db, sc := testDB.SetupDB(t)
c := setupBeaconChain(t, db, sc)
if !bytes.Equal(c.FinalizedCheckpt().Root, params.BeaconConfig().ZeroHash[:]) {
t.Error("Incorrect pre chain start value")
}
assert.DeepEqual(t, params.BeaconConfig().ZeroHash[:], c.FinalizedCheckpt().Root, "Incorrect pre chain start value")
}
func TestHeadRoot_Nil(t *testing.T) {
@@ -34,15 +33,13 @@ func TestHeadRoot_Nil(t *testing.T) {
c := setupBeaconChain(t, db, sc)
headRoot, err := c.HeadRoot(context.Background())
require.NoError(t, err)
if !bytes.Equal(headRoot, params.BeaconConfig().ZeroHash[:]) {
t.Error("Incorrect pre chain start value")
}
assert.DeepEqual(t, params.BeaconConfig().ZeroHash[:], headRoot, "Incorrect pre chain start value")
}
func TestFinalizedCheckpt_CanRetrieve(t *testing.T) {
db, sc := testDB.SetupDB(t)
cp := &ethpb.Checkpoint{Epoch: 5, Root: []byte("foo")}
cp := &ethpb.Checkpoint{Epoch: 5, Root: bytesutil.PadTo([]byte("foo"), 32)}
c := setupBeaconChain(t, db, sc)
c.finalizedCheckpt = cp
@@ -57,16 +54,13 @@ func TestFinalizedCheckpt_GenesisRootOk(t *testing.T) {
c := setupBeaconChain(t, db, sc)
c.finalizedCheckpt = cp
c.genesisRoot = genesisRoot
if !bytes.Equal(c.FinalizedCheckpt().Root, c.genesisRoot[:]) {
t.Errorf("Got: %v, wanted: %v", c.FinalizedCheckpt().Root, c.genesisRoot[:])
}
assert.DeepEqual(t, c.genesisRoot[:], c.FinalizedCheckpt().Root)
}
func TestCurrentJustifiedCheckpt_CanRetrieve(t *testing.T) {
db, sc := testDB.SetupDB(t)
cp := &ethpb.Checkpoint{Epoch: 6, Root: []byte("foo")}
cp := &ethpb.Checkpoint{Epoch: 6, Root: bytesutil.PadTo([]byte("foo"), 32)}
c := setupBeaconChain(t, db, sc)
c.justifiedCheckpt = cp
@@ -81,19 +75,15 @@ func TestJustifiedCheckpt_GenesisRootOk(t *testing.T) {
c := setupBeaconChain(t, db, sc)
c.justifiedCheckpt = cp
c.genesisRoot = genesisRoot
if !bytes.Equal(c.CurrentJustifiedCheckpt().Root, c.genesisRoot[:]) {
t.Errorf("Got: %v, wanted: %v", c.CurrentJustifiedCheckpt().Root, c.genesisRoot[:])
}
assert.DeepEqual(t, c.genesisRoot[:], c.CurrentJustifiedCheckpt().Root)
}
func TestPreviousJustifiedCheckpt_CanRetrieve(t *testing.T) {
db, sc := testDB.SetupDB(t)
cp := &ethpb.Checkpoint{Epoch: 7, Root: []byte("foo")}
cp := &ethpb.Checkpoint{Epoch: 7, Root: bytesutil.PadTo([]byte("foo"), 32)}
c := setupBeaconChain(t, db, sc)
c.prevJustifiedCheckpt = cp
assert.Equal(t, cp.Epoch, c.PreviousJustifiedCheckpt().Epoch, "Unexpected previous justified epoch")
}
@@ -105,30 +95,28 @@ func TestPrevJustifiedCheckpt_GenesisRootOk(t *testing.T) {
c := setupBeaconChain(t, db, sc)
c.prevJustifiedCheckpt = cp
c.genesisRoot = genesisRoot
if !bytes.Equal(c.PreviousJustifiedCheckpt().Root, c.genesisRoot[:]) {
t.Errorf("Got: %v, wanted: %v", c.PreviousJustifiedCheckpt().Root, c.genesisRoot[:])
}
assert.DeepEqual(t, c.genesisRoot[:], c.PreviousJustifiedCheckpt().Root)
}
func TestHeadSlot_CanRetrieve(t *testing.T) {
c := &Service{}
s, err := state.InitializeFromProto(&pb.BeaconState{})
if err != nil {
t.Fatal(err)
}
require.NoError(t, err)
c.head = &head{slot: 100, state: s}
assert.Equal(t, uint64(100), c.headSlot())
assert.Equal(t, uint64(100), c.HeadSlot())
}
func TestHeadRoot_CanRetrieve(t *testing.T) {
c := &Service{}
c.head = &head{root: [32]byte{'A'}}
assert.Equal(t, [32]byte{'A'}, c.headRoot())
r, err := c.HeadRoot(context.Background())
require.NoError(t, err)
assert.Equal(t, [32]byte{'A'}, bytesutil.ToBytes32(r))
}
func TestHeadBlock_CanRetrieve(t *testing.T) {
b := &ethpb.SignedBeaconBlock{Block: &ethpb.BeaconBlock{Slot: 1}}
b := testutil.NewBeaconBlock()
b.Block.Slot = 1
s, err := state.InitializeFromProto(&pb.BeaconState{})
require.NoError(t, err)
c := &Service{}
@@ -146,9 +134,7 @@ func TestHeadState_CanRetrieve(t *testing.T) {
c.head = &head{state: s}
headState, err := c.HeadState(context.Background())
require.NoError(t, err)
if !proto.Equal(s.InnerStateUnsafe(), headState.InnerStateUnsafe()) {
t.Error("incorrect head state received")
}
assert.DeepEqual(t, headState.InnerStateUnsafe(), s.InnerStateUnsafe(), "Incorrect head state received")
}
func TestGenesisTime_CanRetrieve(t *testing.T) {

View File

@@ -0,0 +1,83 @@
package blockchain
import (
"sync"
lru "github.com/hashicorp/golang-lru"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/hashutil"
)
var (
// This defines the max number of checkpoint info this cache can store.
// Each cache is calculated at 3MB(30K validators), the total cache size is around 100MB.
// Due to reorgs and long finality, it's good to keep the old cache around for quickly switch over.
maxInfoSize = 32
// This tracks the number of check point info requests that aren't present in the cache.
infoMiss = promauto.NewCounter(prometheus.CounterOpts{
Name: "check_point_info_cache_miss",
Help: "The number of check point info requests that aren't present in the cache.",
})
// This tracks the number of check point info requests that are in the cache.
infoHit = promauto.NewCounter(prometheus.CounterOpts{
Name: "check_point_info_cache_hit",
Help: "The number of check point info requests that are present in the cache.",
})
)
// checkPtInfoCache is a struct with 1 LRU cache for looking up check point info by checkpoint.
type checkPtInfoCache struct {
cache *lru.Cache
lock sync.RWMutex
}
// newCheckPointInfoCache creates a new checkpoint info cache for storing/accessing processed check point info object.
func newCheckPointInfoCache() *checkPtInfoCache {
cache, err := lru.New(maxInfoSize)
if err != nil {
panic(err)
}
return &checkPtInfoCache{
cache: cache,
}
}
// get fetches check point info by check point. Returns the reference of the CheckPtInfo, nil if doesn't exist.
func (c *checkPtInfoCache) get(cp *ethpb.Checkpoint) (*pb.CheckPtInfo, error) {
c.lock.RLock()
defer c.lock.RUnlock()
h, err := hashutil.HashProto(cp)
if err != nil {
return nil, err
}
item, exists := c.cache.Get(h)
if exists && item != nil {
infoHit.Inc()
// Copy here is unnecessary since the returned check point info object
// will only be used to verify attestation signature.
return item.(*pb.CheckPtInfo), nil
}
infoMiss.Inc()
return nil, nil
}
// put adds CheckPtInfo object to the cache. This method also trims the least
// recently added CheckPtInfo object if the cache size has ready the max cache size limit.
func (c *checkPtInfoCache) put(cp *ethpb.Checkpoint, info *pb.CheckPtInfo) error {
c.lock.Lock()
defer c.lock.Unlock()
h, err := hashutil.HashProto(cp)
if err != nil {
return err
}
c.cache.Add(h, info)
return nil
}

View File

@@ -0,0 +1,41 @@
package blockchain
import (
"testing"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
)
func TestHotStateCache_RoundTrip(t *testing.T) {
c := newCheckPointInfoCache()
cp := &ethpb.Checkpoint{
Epoch: 1,
Root: bytesutil.PadTo([]byte{'a'}, 32),
}
info, err := c.get(cp)
require.NoError(t, err)
require.Equal(t, (*pb.CheckPtInfo)(nil), info)
i := &pb.CheckPtInfo{
Seed: bytesutil.PadTo([]byte{'c'}, 32),
GenesisRoot: bytesutil.PadTo([]byte{'d'}, 32),
ActiveIndices: []uint64{0, 1, 2, 3},
}
require.NoError(t, c.put(cp, i))
info, err = c.get(cp)
require.NoError(t, err)
require.DeepEqual(t, info, i)
}
func TestHotStateCache_CanPrune(t *testing.T) {
c := newCheckPointInfoCache()
for i := 0; i < maxInfoSize+1; i++ {
cp := &ethpb.Checkpoint{Epoch: uint64(i), Root: make([]byte, 32)}
require.NoError(t, c.put(cp, &pb.CheckPtInfo{}))
}
require.Equal(t, len(c.cache.Keys()), maxInfoSize)
}

View File

@@ -72,7 +72,11 @@ func (s *Service) saveHead(ctx context.Context, headRoot [32]byte) error {
defer span.End()
// Do nothing if head hasn't changed.
if headRoot == s.headRoot() {
r, err := s.HeadRoot(ctx)
if err != nil {
return err
}
if headRoot == bytesutil.ToBytes32(r) {
return nil
}
@@ -101,16 +105,17 @@ func (s *Service) saveHead(ctx context.Context, headRoot [32]byte) error {
}
// A chain re-org occurred, so we fire an event notifying the rest of the services.
if bytesutil.ToBytes32(newHeadBlock.Block.ParentRoot) != s.headRoot() {
headSlot := s.HeadSlot()
if bytesutil.ToBytes32(newHeadBlock.Block.ParentRoot) != bytesutil.ToBytes32(r) {
log.WithFields(logrus.Fields{
"newSlot": fmt.Sprintf("%d", newHeadBlock.Block.Slot),
"oldSlot": fmt.Sprintf("%d", s.headSlot()),
"oldSlot": fmt.Sprintf("%d", headSlot),
}).Debug("Chain reorg occurred")
s.stateNotifier.StateFeed().Send(&feed.Event{
Type: statefeed.Reorg,
Data: &statefeed.ReorgData{
NewSlot: newHeadBlock.Block.Slot,
OldSlot: s.headSlot(),
OldSlot: headSlot,
},
})
@@ -179,60 +184,56 @@ func (s *Service) setHeadInitialSync(root [32]byte, block *ethpb.SignedBeaconBlo
}
// This returns the head slot.
// This is a lock free version.
func (s *Service) headSlot() uint64 {
s.headLock.RLock()
defer s.headLock.RUnlock()
return s.head.slot
}
// This returns the head root.
// It does a full copy on head root for immutability.
// This is a lock free version.
func (s *Service) headRoot() [32]byte {
if s.head == nil {
return params.BeaconConfig().ZeroHash
}
s.headLock.RLock()
defer s.headLock.RUnlock()
return s.head.root
}
// This returns the head block.
// It does a full copy on head block for immutability.
// This is a lock free version.
func (s *Service) headBlock() *ethpb.SignedBeaconBlock {
s.headLock.RLock()
defer s.headLock.RUnlock()
return stateTrie.CopySignedBeaconBlock(s.head.block)
}
// This returns the head state.
// It does a full copy on head state for immutability.
// This is a lock free version.
func (s *Service) headState(ctx context.Context) *stateTrie.BeaconState {
ctx, span := trace.StartSpan(ctx, "blockChain.headState")
defer span.End()
s.headLock.RLock()
defer s.headLock.RUnlock()
return s.head.state.Copy()
}
// This returns the genesis validator root of the head state.
// This is a lock free version.
func (s *Service) headGenesisValidatorRoot() [32]byte {
s.headLock.RLock()
defer s.headLock.RUnlock()
return bytesutil.ToBytes32(s.head.state.GenesisValidatorRoot())
}
// Returns true if head state exists.
func (s *Service) hasHeadState() bool {
// HasHeadState returns true if head state exists.
func (s *Service) HasHeadState() bool {
s.headLock.RLock()
defer s.headLock.RUnlock()
return s.hasHeadState()
}
// Returns true if head state exists.
// This is the lock free version.
func (s *Service) hasHeadState() bool {
return s.head != nil && s.head.state != nil
}

View File

@@ -5,9 +5,7 @@ import (
"context"
"testing"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
@@ -35,11 +33,12 @@ func TestSaveHead_Different(t *testing.T) {
oldRoot := [32]byte{'A'}
service.head = &head{slot: 0, root: oldRoot}
newHeadBlock := &ethpb.BeaconBlock{Slot: 1}
newHeadSignedBlock := &ethpb.SignedBeaconBlock{Block: newHeadBlock}
newHeadSignedBlock := testutil.NewBeaconBlock()
newHeadSignedBlock.Block.Slot = 1
newHeadBlock := newHeadSignedBlock.Block
require.NoError(t, service.beaconDB.SaveBlock(context.Background(), newHeadSignedBlock))
newRoot, err := stateutil.BlockRoot(newHeadBlock)
newRoot, err := newHeadBlock.HashTreeRoot()
require.NoError(t, err)
headState := testutil.NewBeaconState()
require.NoError(t, headState.SetSlot(1))
@@ -68,14 +67,13 @@ func TestSaveHead_Different_Reorg(t *testing.T) {
service.head = &head{slot: 0, root: oldRoot}
reorgChainParent := [32]byte{'B'}
newHeadBlock := &ethpb.BeaconBlock{
Slot: 1,
ParentRoot: reorgChainParent[:],
}
newHeadSignedBlock := &ethpb.SignedBeaconBlock{Block: newHeadBlock}
newHeadSignedBlock := testutil.NewBeaconBlock()
newHeadSignedBlock.Block.Slot = 1
newHeadSignedBlock.Block.ParentRoot = reorgChainParent[:]
newHeadBlock := newHeadSignedBlock.Block
require.NoError(t, service.beaconDB.SaveBlock(context.Background(), newHeadSignedBlock))
newRoot, err := stateutil.BlockRoot(newHeadBlock)
newRoot, err := newHeadBlock.HashTreeRoot()
require.NoError(t, err)
headState := testutil.NewBeaconState()
require.NoError(t, headState.SetSlot(1))
@@ -92,7 +90,7 @@ func TestSaveHead_Different_Reorg(t *testing.T) {
}
assert.DeepEqual(t, newHeadSignedBlock, service.headBlock(), "Head did not change")
assert.DeepEqual(t, headState.CloneInnerState(), service.headState(ctx).CloneInnerState(), "Head did not change")
testutil.AssertLogsContain(t, hook, "Chain reorg occurred")
require.LogsContain(t, hook, "Chain reorg occurred")
}
func TestUpdateRecentCanonicalBlocks_CanUpdateWithoutParent(t *testing.T) {

View File

@@ -34,7 +34,12 @@ const template = `<html>
// TreeHandler is a handler to serve /tree page in metrics.
func (s *Service) TreeHandler(w http.ResponseWriter, r *http.Request) {
if s.headState(r.Context()) == nil {
headState, err := s.HeadState(r.Context())
if err != nil {
log.WithError(err).Error("Could not get head state")
return
}
if headState == nil {
if _, err := w.Write([]byte("Unavailable during initial syncing")); err != nil {
log.WithError(err).Error("Failed to render p2p info page")
}
@@ -47,7 +52,7 @@ func (s *Service) TreeHandler(w http.ResponseWriter, r *http.Request) {
graph.Attr("labeljust", "l")
dotNodes := make([]*dot.Node, len(nodes))
avgBalance := uint64(averageBalance(s.headState(r.Context()).Balances()))
avgBalance := uint64(averageBalance(headState.Balances()))
for i := len(nodes) - 1; i >= 0; i-- {
// Construct label for each node.
@@ -63,7 +68,7 @@ func (s *Service) TreeHandler(w http.ResponseWriter, r *http.Request) {
dotN = graph.Node(index).Box().Attr("label", label)
}
if nodes[i].Slot() == s.headSlot() &&
if nodes[i].Slot() == s.HeadSlot() &&
nodes[i].BestDescendant() == ^uint64(0) &&
nodes[i].Parent() != ^uint64(0) {
dotN = dotN.Attr("color", "green")

View File

@@ -33,6 +33,7 @@ func TestService_TreeHandler(t *testing.T) {
StateGen: stategen.New(db, sCache),
}
s, err := NewService(ctx, cfg)
require.NoError(t, err)
require.NoError(t, s.forkChoiceStore.ProcessBlock(ctx, 0, [32]byte{'a'}, [32]byte{'g'}, [32]byte{'c'}, 0, 0))
require.NoError(t, s.forkChoiceStore.ProcessBlock(ctx, 1, [32]byte{'b'}, [32]byte{'a'}, [32]byte{'c'}, 0, 0))
s.setHead([32]byte{'a'}, testutil.NewBeaconBlock(), headState)

View File

@@ -6,6 +6,7 @@ import (
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/sirupsen/logrus"
)
@@ -25,9 +26,10 @@ func logStateTransitionData(b *ethpb.BeaconBlock) {
func logBlockSyncStatus(block *ethpb.BeaconBlock, blockRoot [32]byte, finalized *ethpb.Checkpoint) {
log.WithFields(logrus.Fields{
"slot": block.Slot,
"slotInEpoch": block.Slot % params.BeaconConfig().SlotsPerEpoch,
"block": fmt.Sprintf("0x%s...", hex.EncodeToString(blockRoot[:])[:8]),
"epoch": helpers.SlotToEpoch(block.Slot),
"finalizedEpoch": finalized.Epoch,
"finalizedRoot": fmt.Sprintf("0x%s...", hex.EncodeToString(finalized.Root[:])[:8]),
"finalizedRoot": fmt.Sprintf("0x%s...", hex.EncodeToString(finalized.Root)[:8]),
}).Info("Synced new block")
}

View File

@@ -11,7 +11,7 @@ import (
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/roughtime"
"github.com/prysmaticlabs/prysm/shared/timeutils"
)
var (
@@ -76,14 +76,26 @@ var (
Name: "current_eth1_data_deposit_count",
Help: "The current eth1 deposit count in the last processed state eth1data field.",
})
totalEligibleBalances = promauto.NewGauge(prometheus.GaugeOpts{
Name: "total_eligible_balances",
Help: "The total amount of ether, in gwei, that is eligible for voting of previous epoch",
stateTrieReferences = promauto.NewGaugeVec(prometheus.GaugeOpts{
Name: "field_references",
Help: "The number of states a particular field is shared with.",
}, []string{"state"})
prevEpochActiveBalances = promauto.NewGauge(prometheus.GaugeOpts{
Name: "beacon_prev_epoch_active_gwei",
Help: "The total amount of ether, in gwei, that was active for voting of previous epoch",
})
totalVotedTargetBalances = promauto.NewGauge(prometheus.GaugeOpts{
Name: "total_voted_target_balances",
prevEpochSourceBalances = promauto.NewGauge(prometheus.GaugeOpts{
Name: "beacon_prev_epoch_source_gwei",
Help: "The total amount of ether, in gwei, that has been used in voting attestation source of previous epoch",
})
prevEpochTargetBalances = promauto.NewGauge(prometheus.GaugeOpts{
Name: "beacon_prev_epoch_target_gwei",
Help: "The total amount of ether, in gwei, that has been used in voting attestation target of previous epoch",
})
prevEpochHeadBalances = promauto.NewGauge(prometheus.GaugeOpts{
Name: "beacon_prev_epoch_head_gwei",
Help: "The total amount of ether, in gwei, that has been used in voting attestation head of previous epoch",
})
reorgCount = promauto.NewCounter(prometheus.CounterOpts{
Name: "beacon_reorg_total",
Help: "Count the number of times beacon chain has a reorg",
@@ -102,6 +114,15 @@ var (
Buckets: []float64{1, 2, 3, 4, 6, 32, 64},
},
)
// TODO(7141): Remove deprecated metrics below.
totalEligibleBalances = promauto.NewGauge(prometheus.GaugeOpts{
Name: "total_eligible_balances",
Help: "The total amount of ether, in gwei, that is eligible for voting of previous epoch",
})
totalVotedTargetBalances = promauto.NewGauge(prometheus.GaugeOpts{
Name: "total_voted_target_balances",
Help: "The total amount of ether, in gwei, that has been used in voting attestation target of previous epoch",
})
)
// reportSlotMetrics reports slot related metrics.
@@ -201,6 +222,14 @@ func reportEpochMetrics(state *stateTrie.BeaconState) {
if precompute.Balances != nil {
totalEligibleBalances.Set(float64(precompute.Balances.ActivePrevEpoch))
totalVotedTargetBalances.Set(float64(precompute.Balances.PrevEpochTargetAttested))
prevEpochActiveBalances.Set(float64(precompute.Balances.ActivePrevEpoch))
prevEpochSourceBalances.Set(float64(precompute.Balances.PrevEpochAttested))
prevEpochTargetBalances.Set(float64(precompute.Balances.PrevEpochTargetAttested))
prevEpochHeadBalances.Set(float64(precompute.Balances.PrevEpochHeadAttested))
}
refMap := state.FieldReferencesCount()
for name, val := range refMap {
stateTrieReferences.WithLabelValues(name).Set(float64(val))
}
}
@@ -210,7 +239,7 @@ func captureSentTimeMetric(genesisTime uint64, currentSlot uint64) error {
if err != nil {
return err
}
diffMs := roughtime.Now().Sub(startTime) / time.Millisecond
diffMs := timeutils.Now().Sub(startTime) / time.Millisecond
sentBlockPropagationHistogram.Observe(float64(diffMs))
return nil

View File

@@ -8,9 +8,12 @@ import (
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/shared/attestationutil"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/featureconfig"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/roughtime"
"github.com/prysmaticlabs/prysm/shared/timeutils"
"go.opencensus.io/trace"
)
@@ -66,6 +69,53 @@ func (s *Service) onAttestation(ctx context.Context, a *ethpb.Attestation) ([]ui
return nil, ErrTargetRootNotInDB
}
if featureconfig.Get().UseCheckPointInfoCache {
c, err := s.AttestationCheckPtInfo(ctx, a)
if err != nil {
return nil, err
}
if err := s.verifyAttTargetEpoch(ctx, uint64(s.genesisTime.Unix()), uint64(timeutils.Now().Unix()), tgt); err != nil {
return nil, err
}
if err := s.verifyBeaconBlock(ctx, a.Data); err != nil {
return nil, errors.Wrap(err, "could not verify attestation beacon block")
}
if err := s.verifyLMDFFGConsistent(ctx, a.Data.Target.Epoch, a.Data.Target.Root, a.Data.BeaconBlockRoot); err != nil {
return nil, errors.Wrap(err, "could not verify attestation beacon block")
}
if err := helpers.VerifySlotTime(uint64(s.genesisTime.Unix()), a.Data.Slot+1, params.BeaconNetworkConfig().MaximumGossipClockDisparity); err != nil {
return nil, err
}
committee, err := helpers.BeaconCommittee(c.ActiveIndices, bytesutil.ToBytes32(c.Seed), a.Data.Slot, a.Data.CommitteeIndex)
if err != nil {
return nil, err
}
indexedAtt := attestationutil.ConvertToIndexed(ctx, a, committee)
if err := attestationutil.IsValidAttestationIndices(ctx, indexedAtt); err != nil {
return nil, err
}
domain, err := helpers.Domain(c.Fork, indexedAtt.Data.Target.Epoch, params.BeaconConfig().DomainBeaconAttester, c.GenesisRoot)
if err != nil {
return nil, err
}
indices := indexedAtt.AttestingIndices
pubkeys := []bls.PublicKey{}
for i := 0; i < len(indices); i++ {
pubkeyAtIdx := c.PubKeys[indices[i]]
pk, err := bls.PublicKeyFromBytes(pubkeyAtIdx)
if err != nil {
return nil, err
}
pubkeys = append(pubkeys, pk)
}
if err := attestationutil.VerifyIndexedAttestationSig(ctx, indexedAtt, pubkeys, domain); err != nil {
return nil, err
}
s.forkChoiceStore.ProcessAttestation(ctx, indexedAtt.AttestingIndices, bytesutil.ToBytes32(a.Data.BeaconBlockRoot), a.Data.Target.Epoch)
return indexedAtt.AttestingIndices, nil
}
// Retrieve attestation's data beacon block pre state. Advance pre state to latest epoch if necessary and
// save it to the cache.
baseState, err := s.getAttPreState(ctx, tgt)
@@ -76,7 +126,7 @@ func (s *Service) onAttestation(ctx context.Context, a *ethpb.Attestation) ([]ui
genesisTime := baseState.GenesisTime()
// Verify attestation target is from current epoch or previous epoch.
if err := s.verifyAttTargetEpoch(ctx, genesisTime, uint64(roughtime.Now().Unix()), tgt); err != nil {
if err := s.verifyAttTargetEpoch(ctx, genesisTime, uint64(timeutils.Now().Unix()), tgt); err != nil {
return nil, err
}

View File

@@ -7,11 +7,11 @@ import (
"github.com/pkg/errors"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/attestationutil"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
@@ -21,6 +21,7 @@ import (
func (s *Service) getAttPreState(ctx context.Context, c *ethpb.Checkpoint) (*stateTrie.BeaconState, error) {
s.checkpointStateLock.Lock()
defer s.checkpointStateLock.Unlock()
cachedState, err := s.checkpointState.StateByCheckpoint(c)
if err != nil {
return nil, errors.Wrap(err, "could not get cached checkpoint state")
@@ -31,28 +32,99 @@ func (s *Service) getAttPreState(ctx context.Context, c *ethpb.Checkpoint) (*sta
baseState, err := s.stateGen.StateByRoot(ctx, bytesutil.ToBytes32(c.Root))
if err != nil {
return nil, errors.Wrapf(err, "could not get pre state for slot %d", helpers.StartSlot(c.Epoch))
return nil, errors.Wrapf(err, "could not get pre state for epoch %d", c.Epoch)
}
if helpers.StartSlot(c.Epoch) > baseState.Slot() {
epochStartSlot, err := helpers.StartSlot(c.Epoch)
if err != nil {
return nil, err
}
if epochStartSlot > baseState.Slot() {
baseState = baseState.Copy()
baseState, err = state.ProcessSlots(ctx, baseState, helpers.StartSlot(c.Epoch))
baseState, err = state.ProcessSlots(ctx, baseState, epochStartSlot)
if err != nil {
return nil, errors.Wrapf(err, "could not process slots up to %d", helpers.StartSlot(c.Epoch))
return nil, errors.Wrapf(err, "could not process slots up to epoch %d", c.Epoch)
}
if err := s.checkpointState.AddCheckpointState(c, baseState); err != nil {
return nil, errors.Wrap(err, "could not saved checkpoint state to cache")
}
return baseState, nil
}
has, err := s.stateGen.HasState(ctx, bytesutil.ToBytes32(c.Root))
if err != nil {
return nil, err
}
if !has {
if err := s.checkpointState.AddCheckpointState(c, baseState); err != nil {
return nil, errors.Wrap(err, "could not saved checkpoint state to cache")
}
}
if err := s.checkpointState.AddCheckpointState(&cache.CheckpointState{
Checkpoint: c,
State: baseState,
}); err != nil {
return nil, errors.Wrap(err, "could not saved checkpoint state to cache")
}
return baseState, nil
}
// getAttCheckPtInfo retrieves the check point info given a check point. Check point info enables the node
// to efficiently verify attestation signature without using beacon state. This function utilizes
// the checkpoint info cache and will update the check point info cache on miss.
func (s *Service) getAttCheckPtInfo(ctx context.Context, c *ethpb.Checkpoint, e uint64) (*pb.CheckPtInfo, error) {
// Return checkpoint info if exists in cache.
info, err := s.checkPtInfoCache.get(c)
if err != nil {
return nil, errors.Wrap(err, "could not get cached checkpoint state")
}
if info != nil {
return info, nil
}
// Retrieve checkpoint state to compute checkpoint info.
baseState, err := s.stateGen.StateByRoot(ctx, bytesutil.ToBytes32(c.Root))
if err != nil {
return nil, errors.Wrapf(err, "could not get pre state for epoch %d", c.Epoch)
}
epochStartSlot, err := helpers.StartSlot(c.Epoch)
if err != nil {
return nil, err
}
if epochStartSlot > baseState.Slot() {
baseState = baseState.Copy()
baseState, err = state.ProcessSlots(ctx, baseState, epochStartSlot)
if err != nil {
return nil, errors.Wrapf(err, "could not process slots up to epoch %d", c.Epoch)
}
}
f := baseState.Fork()
g := bytesutil.ToBytes32(baseState.GenesisValidatorRoot())
seed, err := helpers.Seed(baseState, e, params.BeaconConfig().DomainBeaconAttester)
if err != nil {
return nil, err
}
indices, err := helpers.ActiveValidatorIndices(baseState, e)
if err != nil {
return nil, err
}
validators := baseState.ValidatorsReadOnly()
pks := make([][]byte, len(validators))
for i := 0; i < len(pks); i++ {
pk := validators[i].PublicKey()
pks[i] = pk[:]
}
// Cache and return the checkpoint info.
info = &pb.CheckPtInfo{
Fork: f,
GenesisRoot: g[:],
Seed: seed[:],
ActiveIndices: indices,
PubKeys: pks,
}
if err := s.checkPtInfoCache.put(c, info); err != nil {
return nil, err
}
return info, nil
}
// verifyAttTargetEpoch validates attestation is from the current or previous epoch.
func (s *Service) verifyAttTargetEpoch(ctx context.Context, genesisTime uint64, nowTime uint64, c *ethpb.Checkpoint) error {
currentSlot := (nowTime - genesisTime) / params.BeaconConfig().SecondsPerSlot
@@ -91,7 +163,10 @@ func (s *Service) verifyBeaconBlock(ctx context.Context, data *ethpb.Attestation
// verifyLMDFFGConsistent verifies LMD GHOST and FFG votes are consistent with each other.
func (s *Service) verifyLMDFFGConsistent(ctx context.Context, ffgEpoch uint64, ffgRoot []byte, lmdRoot []byte) error {
ffgSlot := helpers.StartSlot(ffgEpoch)
ffgSlot, err := helpers.StartSlot(ffgEpoch)
if err != nil {
return err
}
r, err := s.ancestor(ctx, lmdRoot, ffgSlot)
if err != nil {
return err

View File

@@ -2,20 +2,19 @@ package blockchain
import (
"context"
"strings"
"testing"
"github.com/gogo/protobuf/proto"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/featureconfig"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
@@ -37,103 +36,207 @@ func TestStore_OnAttestation(t *testing.T) {
_, err = blockTree1(db, []byte{'g'})
require.NoError(t, err)
BlkWithOutState := &ethpb.SignedBeaconBlock{Block: &ethpb.BeaconBlock{Slot: 0}}
BlkWithOutState := testutil.NewBeaconBlock()
BlkWithOutState.Block.Slot = 0
require.NoError(t, db.SaveBlock(ctx, BlkWithOutState))
BlkWithOutStateRoot, err := stateutil.BlockRoot(BlkWithOutState.Block)
BlkWithOutStateRoot, err := BlkWithOutState.Block.HashTreeRoot()
require.NoError(t, err)
BlkWithStateBadAtt := &ethpb.SignedBeaconBlock{Block: &ethpb.BeaconBlock{Slot: 1}}
BlkWithStateBadAtt := testutil.NewBeaconBlock()
BlkWithStateBadAtt.Block.Slot = 1
require.NoError(t, db.SaveBlock(ctx, BlkWithStateBadAtt))
BlkWithStateBadAttRoot, err := stateutil.BlockRoot(BlkWithStateBadAtt.Block)
BlkWithStateBadAttRoot, err := BlkWithStateBadAtt.Block.HashTreeRoot()
require.NoError(t, err)
s := testutil.NewBeaconState()
require.NoError(t, s.SetSlot(100*params.BeaconConfig().SlotsPerEpoch))
require.NoError(t, service.beaconDB.SaveState(ctx, s, BlkWithStateBadAttRoot))
BlkWithValidState := &ethpb.SignedBeaconBlock{Block: &ethpb.BeaconBlock{Slot: 2}}
BlkWithValidState := testutil.NewBeaconBlock()
BlkWithValidState.Block.Slot = 2
require.NoError(t, db.SaveBlock(ctx, BlkWithValidState))
BlkWithValidStateRoot, err := stateutil.BlockRoot(BlkWithValidState.Block)
BlkWithValidStateRoot, err := BlkWithValidState.Block.HashTreeRoot()
require.NoError(t, err)
s = testutil.NewBeaconState()
if err := s.SetFork(&pb.Fork{
err = s.SetFork(&pb.Fork{
Epoch: 0,
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
}); err != nil {
t.Fatal(err)
}
})
require.NoError(t, err)
require.NoError(t, service.beaconDB.SaveState(ctx, s, BlkWithValidStateRoot))
tests := []struct {
name string
a *ethpb.Attestation
s *pb.BeaconState
wantErr bool
wantErrString string
name string
a *ethpb.Attestation
wantedErr string
}{
{
name: "attestation's data slot not aligned with target vote",
a: &ethpb.Attestation{Data: &ethpb.AttestationData{Slot: params.BeaconConfig().SlotsPerEpoch, Target: &ethpb.Checkpoint{}}},
s: &pb.BeaconState{},
wantErr: true,
wantErrString: "data slot is not in the same epoch as target 1 != 0",
name: "attestation's data slot not aligned with target vote",
a: &ethpb.Attestation{Data: &ethpb.AttestationData{Slot: params.BeaconConfig().SlotsPerEpoch, Target: &ethpb.Checkpoint{Root: make([]byte, 32)}}},
wantedErr: "data slot is not in the same epoch as target 1 != 0",
},
{
name: "attestation's target root not in db",
a: &ethpb.Attestation{Data: &ethpb.AttestationData{Target: &ethpb.Checkpoint{Root: []byte{'A'}}}},
s: &pb.BeaconState{},
wantErr: true,
wantErrString: "target root does not exist in db",
name: "attestation's target root not in db",
a: &ethpb.Attestation{Data: &ethpb.AttestationData{Target: &ethpb.Checkpoint{Root: bytesutil.PadTo([]byte{'A'}, 32)}}},
wantedErr: "target root does not exist in db",
},
{
name: "no pre state for attestations's target block",
a: &ethpb.Attestation{Data: &ethpb.AttestationData{Target: &ethpb.Checkpoint{Root: BlkWithOutStateRoot[:]}}},
s: &pb.BeaconState{},
wantErr: true,
wantErrString: "could not get pre state for slot 0",
name: "no pre state for attestations's target block",
a: &ethpb.Attestation{Data: &ethpb.AttestationData{Target: &ethpb.Checkpoint{Root: BlkWithOutStateRoot[:]}}},
wantedErr: "could not get pre state for epoch 0",
},
{
name: "process attestation doesn't match current epoch",
a: &ethpb.Attestation{Data: &ethpb.AttestationData{Slot: 100 * params.BeaconConfig().SlotsPerEpoch, Target: &ethpb.Checkpoint{Epoch: 100,
Root: BlkWithStateBadAttRoot[:]}}},
s: &pb.BeaconState{Slot: 100 * params.BeaconConfig().SlotsPerEpoch},
wantErr: true,
wantErrString: "target epoch 100 does not match current epoch",
wantedErr: "target epoch 100 does not match current epoch",
},
{
name: "process nil field (a.Target) in attestation",
a: nil,
s: &pb.BeaconState{},
wantErr: true,
wantErrString: "nil attestation",
name: "process nil attestation",
a: nil,
wantedErr: "nil attestation",
},
{
name: "process nil field (a.Data) in attestation",
a: &ethpb.Attestation{},
s: &pb.BeaconState{},
wantErr: true,
wantErrString: "nil attestation.Data field",
name: "process nil field (a.Data) in attestation",
a: &ethpb.Attestation{},
wantedErr: "nil attestation.Data field",
},
{
name: "process nil field (a.Target) in attestation",
a: &ethpb.Attestation{Data: &ethpb.AttestationData{}},
s: &pb.BeaconState{},
wantErr: true,
wantErrString: "nil attestation.Data.Target field",
name: "process nil field (a.Target) in attestation",
a: &ethpb.Attestation{
Data: &ethpb.AttestationData{
BeaconBlockRoot: make([]byte, 32),
Target: nil,
Source: &ethpb.Checkpoint{Root: make([]byte, 32)},
},
AggregationBits: make([]byte, 1),
Signature: make([]byte, 96),
},
wantedErr: "nil attestation.Data.Target field",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, err := service.onAttestation(ctx, tt.a)
if tt.wantErr {
if err == nil || !strings.Contains(err.Error(), tt.wantErrString) {
t.Errorf("Store.onAttestation() error = %v, wantErr = %v", err, tt.wantErrString)
}
if tt.wantedErr != "" {
assert.ErrorContains(t, tt.wantedErr, err)
} else {
t.Error(err)
assert.NoError(t, err)
}
})
}
}
func TestStore_OnAttestationUsingCheckptCache(t *testing.T) {
resetCfg := featureconfig.InitWithReset(&featureconfig.Flags{UseCheckPointInfoCache: true})
defer resetCfg()
ctx := context.Background()
db, sc := testDB.SetupDB(t)
cfg := &Config{
BeaconDB: db,
ForkChoiceStore: protoarray.New(0, 0, [32]byte{}),
StateGen: stategen.New(db, sc),
}
service, err := NewService(ctx, cfg)
require.NoError(t, err)
_, err = blockTree1(db, []byte{'g'})
require.NoError(t, err)
BlkWithOutState := testutil.NewBeaconBlock()
BlkWithOutState.Block.Slot = 0
require.NoError(t, db.SaveBlock(ctx, BlkWithOutState))
BlkWithOutStateRoot, err := BlkWithOutState.Block.HashTreeRoot()
require.NoError(t, err)
BlkWithStateBadAtt := testutil.NewBeaconBlock()
BlkWithStateBadAtt.Block.Slot = 1
require.NoError(t, db.SaveBlock(ctx, BlkWithStateBadAtt))
BlkWithStateBadAttRoot, err := BlkWithStateBadAtt.Block.HashTreeRoot()
require.NoError(t, err)
s := testutil.NewBeaconState()
require.NoError(t, s.SetSlot(100*params.BeaconConfig().SlotsPerEpoch))
require.NoError(t, service.beaconDB.SaveState(ctx, s, BlkWithStateBadAttRoot))
BlkWithValidState := testutil.NewBeaconBlock()
BlkWithValidState.Block.Slot = 2
require.NoError(t, db.SaveBlock(ctx, BlkWithValidState))
BlkWithValidStateRoot, err := BlkWithValidState.Block.HashTreeRoot()
require.NoError(t, err)
s = testutil.NewBeaconState()
err = s.SetFork(&pb.Fork{
Epoch: 0,
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
})
require.NoError(t, err)
require.NoError(t, service.beaconDB.SaveState(ctx, s, BlkWithValidStateRoot))
tests := []struct {
name string
a *ethpb.Attestation
wantedErr string
}{
{
name: "attestation's data slot not aligned with target vote",
a: &ethpb.Attestation{Data: &ethpb.AttestationData{Slot: params.BeaconConfig().SlotsPerEpoch, Target: &ethpb.Checkpoint{Root: make([]byte, 32)}}},
wantedErr: "data slot is not in the same epoch as target 1 != 0",
},
{
name: "attestation's target root not in db",
a: &ethpb.Attestation{Data: &ethpb.AttestationData{Target: &ethpb.Checkpoint{Root: bytesutil.PadTo([]byte{'A'}, 32)}}},
wantedErr: "target root does not exist in db",
},
{
name: "no pre state for attestations's target block",
a: &ethpb.Attestation{Data: &ethpb.AttestationData{Target: &ethpb.Checkpoint{Root: BlkWithOutStateRoot[:]}}},
wantedErr: "could not get pre state for epoch 0",
},
{
name: "process attestation doesn't match current epoch",
a: &ethpb.Attestation{Data: &ethpb.AttestationData{Slot: 100 * params.BeaconConfig().SlotsPerEpoch, Target: &ethpb.Checkpoint{Epoch: 100,
Root: BlkWithStateBadAttRoot[:]}}},
wantedErr: "target epoch 100 does not match current epoch",
},
{
name: "process nil attestation",
a: nil,
wantedErr: "nil attestation",
},
{
name: "process nil field (a.Data) in attestation",
a: &ethpb.Attestation{},
wantedErr: "nil attestation.Data field",
},
{
name: "process nil field (a.Target) in attestation",
a: &ethpb.Attestation{
Data: &ethpb.AttestationData{
BeaconBlockRoot: make([]byte, 32),
Target: nil,
Source: &ethpb.Checkpoint{Root: make([]byte, 32)},
},
AggregationBits: make([]byte, 1),
Signature: make([]byte, 96),
},
wantedErr: "nil attestation.Data.Target field",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, err := service.onAttestation(ctx, tt.a)
if tt.wantedErr != "" {
assert.ErrorContains(t, tt.wantedErr, err)
} else {
assert.NoError(t, err)
}
})
}
@@ -150,22 +253,16 @@ func TestStore_SaveCheckpointState(t *testing.T) {
service, err := NewService(ctx, cfg)
require.NoError(t, err)
s, err := stateTrie.InitializeFromProto(&pb.BeaconState{
Fork: &pb.Fork{
Epoch: 0,
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
},
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
StateRoots: make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot),
BlockRoots: make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot),
LatestBlockHeader: &ethpb.BeaconBlockHeader{},
JustificationBits: []byte{0},
Slashings: make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector),
FinalizedCheckpoint: &ethpb.Checkpoint{Root: bytesutil.PadTo([]byte{'A'}, 32)},
Validators: []*ethpb.Validator{{PublicKey: bytesutil.PadTo([]byte("foo"), 48)}},
Balances: []uint64{0},
})
s := testutil.NewBeaconState()
err = s.SetFinalizedCheckpoint(&ethpb.Checkpoint{Root: bytesutil.PadTo([]byte{'A'}, 32)})
require.NoError(t, err)
val := &ethpb.Validator{
PublicKey: bytesutil.PadTo([]byte("foo"), 48),
WithdrawalCredentials: bytesutil.PadTo([]byte("bar"), 32),
}
err = s.SetValidators([]*ethpb.Validator{val})
require.NoError(t, err)
err = s.SetBalances([]uint64{0})
require.NoError(t, err)
r := [32]byte{'g'}
require.NoError(t, service.beaconDB.SaveState(ctx, s, r))
@@ -229,23 +326,24 @@ func TestStore_UpdateCheckpointState(t *testing.T) {
epoch := uint64(1)
baseState, _ := testutil.DeterministicGenesisState(t, 1)
require.NoError(t, baseState.SetSlot(epoch*params.BeaconConfig().SlotsPerEpoch))
checkpoint := &ethpb.Checkpoint{Epoch: epoch}
checkpoint := &ethpb.Checkpoint{Epoch: epoch, Root: bytesutil.PadTo([]byte("hi"), 32)}
require.NoError(t, service.beaconDB.SaveState(ctx, baseState, bytesutil.ToBytes32(checkpoint.Root)))
returned, err := service.getAttPreState(ctx, checkpoint)
require.NoError(t, err)
assert.Equal(t, returned.Slot(), baseState.Slot(), "Incorrectly returned base state")
assert.Equal(t, returned.Slot(), checkpoint.Epoch*params.BeaconConfig().SlotsPerEpoch, "Incorrectly returned base state")
cached, err := service.checkpointState.StateByCheckpoint(checkpoint)
require.NoError(t, err)
assert.NotNil(t, cached, "State should have been cached")
assert.Equal(t, returned.Slot(), cached.Slot(), "State should have been cached")
epoch = uint64(2)
newCheckpoint := &ethpb.Checkpoint{Epoch: epoch}
newCheckpoint := &ethpb.Checkpoint{Epoch: epoch, Root: bytesutil.PadTo([]byte("bye"), 32)}
require.NoError(t, service.beaconDB.SaveState(ctx, baseState, bytesutil.ToBytes32(newCheckpoint.Root)))
returned, err = service.getAttPreState(ctx, newCheckpoint)
require.NoError(t, err)
baseState, err = state.ProcessSlots(ctx, baseState, helpers.StartSlot(newCheckpoint.Epoch))
s, err := helpers.StartSlot(newCheckpoint.Epoch)
require.NoError(t, err)
baseState, err = state.ProcessSlots(ctx, baseState, s)
require.NoError(t, err)
assert.Equal(t, returned.Slot(), baseState.Slot(), "Incorrectly returned base state")
@@ -264,13 +362,8 @@ func TestAttEpoch_MatchPrevEpoch(t *testing.T) {
service, err := NewService(ctx, cfg)
require.NoError(t, err)
if err := service.verifyAttTargetEpoch(
ctx,
0,
params.BeaconConfig().SlotsPerEpoch*params.BeaconConfig().SecondsPerSlot,
&ethpb.Checkpoint{}); err != nil {
t.Error(err)
}
nowTime := params.BeaconConfig().SlotsPerEpoch * params.BeaconConfig().SecondsPerSlot
require.NoError(t, service.verifyAttTargetEpoch(ctx, 0, nowTime, &ethpb.Checkpoint{Root: make([]byte, 32)}))
}
func TestAttEpoch_MatchCurrentEpoch(t *testing.T) {
@@ -281,13 +374,8 @@ func TestAttEpoch_MatchCurrentEpoch(t *testing.T) {
service, err := NewService(ctx, cfg)
require.NoError(t, err)
if err := service.verifyAttTargetEpoch(
ctx,
0,
params.BeaconConfig().SlotsPerEpoch*params.BeaconConfig().SecondsPerSlot,
&ethpb.Checkpoint{Epoch: 1}); err != nil {
t.Error(err)
}
nowTime := params.BeaconConfig().SlotsPerEpoch * params.BeaconConfig().SecondsPerSlot
require.NoError(t, service.verifyAttTargetEpoch(ctx, 0, nowTime, &ethpb.Checkpoint{Epoch: 1}))
}
func TestAttEpoch_NotMatch(t *testing.T) {
@@ -298,14 +386,9 @@ func TestAttEpoch_NotMatch(t *testing.T) {
service, err := NewService(ctx, cfg)
require.NoError(t, err)
if err := service.verifyAttTargetEpoch(
ctx,
0,
2*params.BeaconConfig().SlotsPerEpoch*params.BeaconConfig().SecondsPerSlot,
&ethpb.Checkpoint{}); !strings.Contains(err.Error(),
"target epoch 0 does not match current epoch 2 or prev epoch 1") {
t.Error("Did not receive wanted error")
}
nowTime := 2 * params.BeaconConfig().SlotsPerEpoch * params.BeaconConfig().SecondsPerSlot
err = service.verifyAttTargetEpoch(ctx, 0, nowTime, &ethpb.Checkpoint{Root: make([]byte, 32)})
assert.ErrorContains(t, "target epoch 0 does not match current epoch 2 or prev epoch 1", err)
}
func TestVerifyBeaconBlock_NoBlock(t *testing.T) {
@@ -316,8 +399,12 @@ func TestVerifyBeaconBlock_NoBlock(t *testing.T) {
service, err := NewService(ctx, cfg)
require.NoError(t, err)
d := &ethpb.AttestationData{}
assert.ErrorContains(t, "beacon block does not exist", service.verifyBeaconBlock(ctx, d))
d := &ethpb.AttestationData{
BeaconBlockRoot: make([]byte, 32),
Target: &ethpb.Checkpoint{Root: make([]byte, 32)},
Source: &ethpb.Checkpoint{Root: make([]byte, 32)},
}
assert.ErrorContains(t, "beacon block 0x000000000000 does not exist", service.verifyBeaconBlock(ctx, d))
}
func TestVerifyBeaconBlock_futureBlock(t *testing.T) {
@@ -328,9 +415,10 @@ func TestVerifyBeaconBlock_futureBlock(t *testing.T) {
service, err := NewService(ctx, cfg)
require.NoError(t, err)
b := &ethpb.SignedBeaconBlock{Block: &ethpb.BeaconBlock{Slot: 2}}
b := testutil.NewBeaconBlock()
b.Block.Slot = 2
require.NoError(t, service.beaconDB.SaveBlock(ctx, b))
r, err := stateutil.BlockRoot(b.Block)
r, err := b.Block.HashTreeRoot()
require.NoError(t, err)
d := &ethpb.AttestationData{Slot: 1, BeaconBlockRoot: r[:]}
@@ -345,9 +433,10 @@ func TestVerifyBeaconBlock_OK(t *testing.T) {
service, err := NewService(ctx, cfg)
require.NoError(t, err)
b := &ethpb.SignedBeaconBlock{Block: &ethpb.BeaconBlock{Slot: 2}}
b := testutil.NewBeaconBlock()
b.Block.Slot = 2
require.NoError(t, service.beaconDB.SaveBlock(ctx, b))
r, err := stateutil.BlockRoot(b.Block)
r, err := b.Block.HashTreeRoot()
require.NoError(t, err)
d := &ethpb.AttestationData{Slot: 2, BeaconBlockRoot: r[:]}
@@ -362,13 +451,16 @@ func TestVerifyLMDFFGConsistent_NotOK(t *testing.T) {
service, err := NewService(ctx, cfg)
require.NoError(t, err)
b32 := &ethpb.SignedBeaconBlock{Block: &ethpb.BeaconBlock{Slot: 32}}
b32 := testutil.NewBeaconBlock()
b32.Block.Slot = 32
require.NoError(t, service.beaconDB.SaveBlock(ctx, b32))
r32, err := stateutil.BlockRoot(b32.Block)
r32, err := b32.Block.HashTreeRoot()
require.NoError(t, err)
b33 := &ethpb.SignedBeaconBlock{Block: &ethpb.BeaconBlock{Slot: 33, ParentRoot: r32[:]}}
b33 := testutil.NewBeaconBlock()
b33.Block.Slot = 33
b33.Block.ParentRoot = r32[:]
require.NoError(t, service.beaconDB.SaveBlock(ctx, b33))
r33, err := stateutil.BlockRoot(b33.Block)
r33, err := b33.Block.HashTreeRoot()
require.NoError(t, err)
wanted := "FFG and LMD votes are not consistent"
@@ -383,15 +475,62 @@ func TestVerifyLMDFFGConsistent_OK(t *testing.T) {
service, err := NewService(ctx, cfg)
require.NoError(t, err)
b32 := &ethpb.SignedBeaconBlock{Block: &ethpb.BeaconBlock{Slot: 32}}
b32 := testutil.NewBeaconBlock()
b32.Block.Slot = 32
require.NoError(t, service.beaconDB.SaveBlock(ctx, b32))
r32, err := stateutil.BlockRoot(b32.Block)
r32, err := b32.Block.HashTreeRoot()
require.NoError(t, err)
b33 := &ethpb.SignedBeaconBlock{Block: &ethpb.BeaconBlock{Slot: 33, ParentRoot: r32[:]}}
b33 := testutil.NewBeaconBlock()
b33.Block.Slot = 33
b33.Block.ParentRoot = r32[:]
require.NoError(t, service.beaconDB.SaveBlock(ctx, b33))
r33, err := stateutil.BlockRoot(b33.Block)
r33, err := b33.Block.HashTreeRoot()
require.NoError(t, err)
err = service.verifyLMDFFGConsistent(context.Background(), 1, r32[:], r33[:])
assert.NoError(t, err, "Could not verify LMD and FFG votes to be consistent")
}
func TestGetAttCheckptInfo(t *testing.T) {
ctx := context.Background()
db, _ := testDB.SetupDB(t)
cfg := &Config{BeaconDB: db, StateGen: stategen.New(db, cache.NewStateSummaryCache())}
service, err := NewService(ctx, cfg)
require.NoError(t, err)
baseState, _ := testutil.DeterministicGenesisState(t, 128)
b := testutil.NewBeaconBlock()
r, err := b.Block.HashTreeRoot()
require.NoError(t, err)
require.NoError(t, service.beaconDB.SaveState(ctx, baseState, r))
require.NoError(t, service.beaconDB.SaveBlock(ctx, b))
require.NoError(t, service.beaconDB.SaveGenesisBlockRoot(ctx, r))
checkpoint := &ethpb.Checkpoint{Root: r[:]}
returned, err := service.getAttCheckPtInfo(ctx, checkpoint, 0)
require.NoError(t, err)
seed, err := helpers.Seed(baseState, 0, params.BeaconConfig().DomainBeaconAttester)
require.NoError(t, err)
indices, err := helpers.ActiveValidatorIndices(baseState, 0)
require.NoError(t, err)
validators := baseState.ValidatorsReadOnly()
pks := make([][]byte, len(validators))
for i := 0; i < len(pks); i++ {
pk := validators[i].PublicKey()
pks[i] = pk[:]
}
wanted := &pb.CheckPtInfo{
Fork: baseState.Fork(),
GenesisRoot: baseState.GenesisValidatorRoot(),
Seed: seed[:],
ActiveIndices: indices,
PubKeys: pks,
}
require.DeepEqual(t, wanted, returned)
cached, err := service.checkPtInfoCache.get(checkpoint)
require.NoError(t, err)
require.DeepEqual(t, wanted, cached)
}

View File

@@ -121,7 +121,11 @@ func (s *Service) onBlock(ctx context.Context, signed *ethpb.SignedBeaconBlock,
}
// Update deposit cache.
s.depositCache.InsertFinalizedDeposits(ctx, int64(postState.Eth1DepositIndex()))
finalizedState, err := s.stateGen.StateByRoot(ctx, fRoot)
if err != nil {
return errors.Wrap(err, "could not fetch finalized state")
}
s.depositCache.InsertFinalizedDeposits(ctx, int64(finalizedState.Eth1Data().DepositCount-1))
}
defer reportAttestationInclusion(b)
@@ -231,11 +235,11 @@ func (s *Service) onBlockBatch(ctx context.Context, blks []*ethpb.SignedBeaconBl
jCheckpoints := make([]*ethpb.Checkpoint, len(blks))
fCheckpoints := make([]*ethpb.Checkpoint, len(blks))
sigSet := &bls.SignatureSet{
Signatures: []bls.Signature{},
Signatures: [][]byte{},
PublicKeys: []bls.PublicKey{},
Messages: [][32]byte{},
}
set := new(bls.SignatureSet)
var set *bls.SignatureSet
boundaries := make(map[[32]byte]*stateTrie.BeaconState)
for i, b := range blks {
set, preState, err = state.ExecuteStateTransitionNoVerifyAnySig(ctx, preState, b)
@@ -246,14 +250,14 @@ func (s *Service) onBlockBatch(ctx context.Context, blks []*ethpb.SignedBeaconBl
if helpers.IsEpochStart(preState.Slot()) {
boundaries[blockRoots[i]] = preState.Copy()
if err := s.handleEpochBoundary(preState); err != nil {
return nil, nil, fmt.Errorf("could not handle epoch boundary state")
return nil, nil, errors.Wrap(err, "could not handle epoch boundary state")
}
}
jCheckpoints[i] = preState.CurrentJustifiedCheckpoint()
fCheckpoints[i] = preState.FinalizedCheckpoint()
sigSet.Join(set)
}
verify, err := bls.VerifyMultipleSignatures(sigSet.Signatures, sigSet.Messages, sigSet.PublicKeys)
verify, err := sigSet.Verify()
if err != nil {
return nil, nil, err
}
@@ -316,8 +320,11 @@ func (s *Service) handleBlockAfterBatchVerify(ctx context.Context, signed *ethpb
func (s *Service) handleEpochBoundary(postState *stateTrie.BeaconState) error {
if postState.Slot() >= s.nextEpochBoundarySlot {
reportEpochMetrics(postState)
s.nextEpochBoundarySlot = helpers.StartSlot(helpers.NextEpoch(postState))
var err error
s.nextEpochBoundarySlot, err = helpers.StartSlot(helpers.NextEpoch(postState))
if err != nil {
return err
}
// Update committees cache at epoch boundary slot.
if err := helpers.UpdateCommitteeCache(postState, helpers.CurrentEpoch(postState)); err != nil {
return err

View File

@@ -9,23 +9,16 @@ import (
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
"github.com/prysmaticlabs/prysm/shared/attestationutil"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/roughtime"
"github.com/prysmaticlabs/prysm/shared/traceutil"
"go.opencensus.io/trace"
)
// CurrentSlot returns the current slot based on time.
func (s *Service) CurrentSlot() uint64 {
now := roughtime.Now().Unix()
genesis := s.genesisTime.Unix()
if now < genesis {
return 0
}
return uint64(now-genesis) / params.BeaconConfig().SecondsPerSlot
return helpers.CurrentSlot(uint64(s.genesisTime.Unix()))
}
// getBlockPreState returns the pre state of an incoming block. It uses the parent root of the block
@@ -53,11 +46,6 @@ func (s *Service) getBlockPreState(ctx context.Context, b *ethpb.BeaconBlock) (*
return nil, err
}
// Verify block is a descendent of a finalized block.
if err := s.VerifyBlkDescendant(ctx, bytesutil.ToBytes32(b.ParentRoot)); err != nil {
return nil, err
}
// Verify block is later than the finalized epoch slot.
if err := s.verifyBlkFinalizedSlot(b); err != nil {
return nil, err
@@ -78,7 +66,16 @@ func (s *Service) verifyBlkPreState(ctx context.Context, b *ethpb.BeaconBlock) e
if !s.stateGen.StateSummaryExists(ctx, parentRoot) && !s.beaconDB.HasBlock(ctx, parentRoot) {
return errors.New("could not reconstruct parent state")
}
if !s.stateGen.HasState(ctx, parentRoot) {
if err := s.VerifyBlkDescendant(ctx, bytesutil.ToBytes32(b.ParentRoot)); err != nil {
return err
}
has, err := s.stateGen.HasState(ctx, parentRoot)
if err != nil {
return err
}
if !has {
if err := s.beaconDB.SaveBlocks(ctx, s.getInitSyncBlocks()); err != nil {
return errors.Wrap(err, "could not save initial sync blocks")
}
@@ -122,7 +119,10 @@ func (s *Service) VerifyBlkDescendant(ctx context.Context, root [32]byte) error
// verifyBlkFinalizedSlot validates input block is not less than or equal
// to current finalized slot.
func (s *Service) verifyBlkFinalizedSlot(b *ethpb.BeaconBlock) error {
finalizedSlot := helpers.StartSlot(s.finalizedCheckpt.Epoch)
finalizedSlot, err := helpers.StartSlot(s.finalizedCheckpt.Epoch)
if err != nil {
return err
}
if finalizedSlot >= b.Slot {
return fmt.Errorf("block is equal or earlier than finalized block, slot %d < slot %d", b.Slot, finalizedSlot)
}
@@ -153,7 +153,11 @@ func (s *Service) shouldUpdateCurrentJustified(ctx context.Context, newJustified
}
newJustifiedBlock := newJustifiedBlockSigned.Block
if newJustifiedBlock.Slot <= helpers.StartSlot(s.justifiedCheckpt.Epoch) {
jSlot, err := helpers.StartSlot(s.justifiedCheckpt.Epoch)
if err != nil {
return false, err
}
if newJustifiedBlock.Slot <= jSlot {
return false, nil
}
var justifiedBlockSigned *ethpb.SignedBeaconBlock
@@ -223,6 +227,10 @@ func (s *Service) updateFinalized(ctx context.Context, cp *ethpb.Checkpoint) err
}
s.clearInitSyncBlocks()
if err := s.beaconDB.SaveFinalizedCheckpoint(ctx, cp); err != nil {
return err
}
s.prevFinalizedCheckpt = s.finalizedCheckpt
s.finalizedCheckpt = cp
@@ -231,7 +239,7 @@ func (s *Service) updateFinalized(ctx context.Context, cp *ethpb.Checkpoint) err
return errors.Wrap(err, "could not migrate to cold")
}
return s.beaconDB.SaveFinalizedCheckpoint(ctx, cp)
return nil
}
// ancestor returns the block root of an ancestry block from the input block root.
@@ -250,16 +258,35 @@ func (s *Service) ancestor(ctx context.Context, root []byte, slot uint64) ([]byt
ctx, span := trace.StartSpan(ctx, "forkChoice.ancestor")
defer span.End()
// Stop recursive ancestry lookup if context is cancelled.
if ctx.Err() != nil {
return nil, ctx.Err()
}
r := bytesutil.ToBytes32(root)
// Get ancestor root from fork choice store instead of recursively looking up blocks in DB.
// This is most optimal outcome.
if s.forkChoiceStore.HasParent(r) {
return s.forkChoiceStore.AncestorRoot(ctx, r, slot)
ar, err := s.ancestorByForkChoiceStore(ctx, r, slot)
if err != nil {
// Try getting ancestor root from DB when failed to retrieve from fork choice store.
// This is the second line of defense for retrieving ancestor root.
ar, err = s.ancestorByDB(ctx, r, slot)
if err != nil {
return nil, err
}
}
return ar, nil
}
// This retrieves an ancestor root using fork choice store. The look up is looping through the a flat array structure.
func (s *Service) ancestorByForkChoiceStore(ctx context.Context, r [32]byte, slot uint64) ([]byte, error) {
if !s.forkChoiceStore.HasParent(r) {
return nil, errors.New("could not find root in fork choice store")
}
return s.forkChoiceStore.AncestorRoot(ctx, r, slot)
}
// This retrieves an ancestor root using DB. The look up is recursively looking up DB. Slower than `ancestorByForkChoiceStore`.
func (s *Service) ancestorByDB(ctx context.Context, r [32]byte, slot uint64) ([]byte, error) {
// Stop recursive ancestry lookup if context is cancelled.
if ctx.Err() != nil {
return nil, ctx.Err()
}
signed, err := s.beaconDB.Block(ctx, r)
@@ -276,10 +303,10 @@ func (s *Service) ancestor(ctx context.Context, root []byte, slot uint64) ([]byt
}
b := signed.Block
if b.Slot == slot || b.Slot < slot {
return root, nil
return r[:], nil
}
return s.ancestor(ctx, b.ParentRoot, slot)
return s.ancestorByDB(ctx, bytesutil.ToBytes32(b.ParentRoot), slot)
}
// This updates justified check point in store, if the new justified is later than stored justified or
@@ -302,14 +329,14 @@ func (s *Service) finalizedImpliesNewJustified(ctx context.Context, state *state
if !attestationutil.CheckPointIsEqual(s.justifiedCheckpt, state.CurrentJustifiedCheckpoint()) {
if state.CurrentJustifiedCheckpoint().Epoch > s.justifiedCheckpt.Epoch {
s.justifiedCheckpt = state.CurrentJustifiedCheckpoint()
if err := s.cacheJustifiedStateBalances(ctx, bytesutil.ToBytes32(s.justifiedCheckpt.Root)); err != nil {
return err
}
return nil
return s.cacheJustifiedStateBalances(ctx, bytesutil.ToBytes32(s.justifiedCheckpt.Root))
}
// Update justified if store justified is not in chain with finalized check point.
finalizedSlot := helpers.StartSlot(s.finalizedCheckpt.Epoch)
finalizedSlot, err := helpers.StartSlot(s.finalizedCheckpt.Epoch)
if err != nil {
return err
}
justifiedRoot := s.ensureRootNotZeros(bytesutil.ToBytes32(s.justifiedCheckpt.Root))
anc, err := s.ancestor(ctx, justifiedRoot[:], finalizedSlot)
if err != nil {
@@ -334,7 +361,11 @@ func (s *Service) fillInForkChoiceMissingBlocks(ctx context.Context, blk *ethpb.
parentRoot := bytesutil.ToBytes32(blk.ParentRoot)
slot := blk.Slot
// Fork choice only matters from last finalized slot.
higherThanFinalized := slot > helpers.StartSlot(s.finalizedCheckpt.Epoch)
fSlot, err := helpers.StartSlot(s.finalizedCheckpt.Epoch)
if err != nil {
return err
}
higherThanFinalized := slot > fSlot
// As long as parent node is not in fork choice store, and parent node is in DB.
for !s.forkChoiceStore.HasNode(parentRoot) && s.beaconDB.HasBlock(ctx, parentRoot) && higherThanFinalized {
b, err := s.beaconDB.Block(ctx, parentRoot)
@@ -345,14 +376,14 @@ func (s *Service) fillInForkChoiceMissingBlocks(ctx context.Context, blk *ethpb.
pendingNodes = append(pendingNodes, b.Block)
parentRoot = bytesutil.ToBytes32(b.Block.ParentRoot)
slot = b.Block.Slot
higherThanFinalized = slot > helpers.StartSlot(s.finalizedCheckpt.Epoch)
higherThanFinalized = slot > fSlot
}
// Insert parent nodes to fork choice store in reverse order.
// Lower slots should be at the end of the list.
for i := len(pendingNodes) - 1; i >= 0; i-- {
b := pendingNodes[i]
r, err := stateutil.BlockRoot(b)
r, err := b.HashTreeRoot()
if err != nil {
return err
}

View File

@@ -2,12 +2,11 @@ package blockchain
import (
"context"
"strings"
"testing"
"time"
"github.com/pkg/errors"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/go-ssz"
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
@@ -16,16 +15,14 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/attestationutil"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/featureconfig"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/roughtime"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
"github.com/prysmaticlabs/prysm/shared/timeutils"
)
func TestStore_OnBlock(t *testing.T) {
@@ -42,50 +39,66 @@ func TestStore_OnBlock(t *testing.T) {
genesisStateRoot := [32]byte{}
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
assert.NoError(t, db.SaveBlock(ctx, genesis))
validGenesisRoot, err := stateutil.BlockRoot(genesis.Block)
validGenesisRoot, err := genesis.Block.HashTreeRoot()
require.NoError(t, err)
st := testutil.NewBeaconState()
require.NoError(t, service.beaconDB.SaveState(ctx, st.Copy(), validGenesisRoot))
roots, err := blockTree1(db, validGenesisRoot[:])
require.NoError(t, err)
random := &ethpb.SignedBeaconBlock{Block: &ethpb.BeaconBlock{Slot: 1, ParentRoot: validGenesisRoot[:]}}
random := testutil.NewBeaconBlock()
random.Block.Slot = 1
random.Block.ParentRoot = validGenesisRoot[:]
assert.NoError(t, db.SaveBlock(ctx, random))
randomParentRoot, err := stateutil.BlockRoot(random.Block)
randomParentRoot, err := random.Block.HashTreeRoot()
assert.NoError(t, err)
require.NoError(t, service.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{Slot: st.Slot(), Root: randomParentRoot[:]}))
require.NoError(t, service.beaconDB.SaveState(ctx, st.Copy(), randomParentRoot))
randomParentRoot2 := roots[1]
require.NoError(t, service.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{Slot: st.Slot(), Root: randomParentRoot2[:]}))
require.NoError(t, service.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{Slot: st.Slot(), Root: randomParentRoot2}))
require.NoError(t, service.beaconDB.SaveState(ctx, st.Copy(), bytesutil.ToBytes32(randomParentRoot2)))
tests := []struct {
name string
blk *ethpb.BeaconBlock
blk *ethpb.SignedBeaconBlock
s *stateTrie.BeaconState
time uint64
wantErrString string
}{
{
name: "parent block root does not have a state",
blk: &ethpb.BeaconBlock{},
blk: testutil.NewBeaconBlock(),
s: st.Copy(),
wantErrString: "could not reconstruct parent state",
},
{
name: "block is from the future",
blk: &ethpb.BeaconBlock{ParentRoot: randomParentRoot[:], Slot: params.BeaconConfig().FarFutureEpoch},
name: "block is from the future",
blk: func() *ethpb.SignedBeaconBlock {
b := testutil.NewBeaconBlock()
b.Block.ParentRoot = randomParentRoot2
b.Block.Slot = params.BeaconConfig().FarFutureEpoch
return b
}(),
s: st.Copy(),
wantErrString: "far distant future",
wantErrString: "is in the far distant future",
},
{
name: "could not get finalized block",
blk: &ethpb.BeaconBlock{ParentRoot: randomParentRoot[:]},
name: "could not get finalized block",
blk: func() *ethpb.SignedBeaconBlock {
b := testutil.NewBeaconBlock()
b.Block.ParentRoot = randomParentRoot[:]
return b
}(),
s: st.Copy(),
wantErrString: "is not a descendent of the current finalized block",
},
{
name: "same slot as finalized block",
blk: &ethpb.BeaconBlock{Slot: 0, ParentRoot: randomParentRoot2},
name: "same slot as finalized block",
blk: func() *ethpb.SignedBeaconBlock {
b := testutil.NewBeaconBlock()
b.Block.Slot = 0
b.Block.ParentRoot = randomParentRoot2
return b
}(),
s: st.Copy(),
wantErrString: "block is equal or earlier than finalized block, slot 0 < slot 0",
},
@@ -99,9 +112,9 @@ func TestStore_OnBlock(t *testing.T) {
service.prevFinalizedCheckpt = &ethpb.Checkpoint{Root: validGenesisRoot[:]}
service.finalizedCheckpt.Root = roots[0]
root, err := stateutil.BlockRoot(tt.blk)
root, err := tt.blk.Block.HashTreeRoot()
assert.NoError(t, err)
err = service.onBlock(ctx, &ethpb.SignedBeaconBlock{Block: tt.blk}, root)
err = service.onBlock(ctx, tt.blk, root)
assert.ErrorContains(t, tt.wantErrString, err)
})
}
@@ -121,6 +134,13 @@ func TestStore_OnBlockBatch(t *testing.T) {
genesisStateRoot := [32]byte{}
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
assert.NoError(t, db.SaveBlock(ctx, genesis))
gRoot, err := genesis.Block.HashTreeRoot()
require.NoError(t, err)
service.finalizedCheckpt = &ethpb.Checkpoint{
Root: gRoot[:],
}
service.forkChoiceStore = protoarray.New(0, 0, [32]byte{})
service.saveInitSyncBlock(gRoot, genesis)
st, keys := testutil.DeterministicGenesisState(t, 64)
@@ -137,11 +157,14 @@ func TestStore_OnBlockBatch(t *testing.T) {
if i == 1 {
firstState = bState.Copy()
}
root, err := stateutil.BlockRoot(b.Block)
root, err := b.Block.HashTreeRoot()
require.NoError(t, err)
service.saveInitSyncBlock(root, b)
blks = append(blks, b)
blkRoots = append(blkRoots, root)
}
blks[0].Block.ParentRoot = gRoot[:]
require.NoError(t, db.SaveBlock(context.Background(), blks[0]))
require.NoError(t, service.stateGen.SaveState(ctx, blkRoots[0], firstState))
_, _, err = service.onBlockBatch(ctx, blks[1:], blkRoots[1:])
@@ -159,17 +182,17 @@ func TestRemoveStateSinceLastFinalized_EmptyStartSlot(t *testing.T) {
require.NoError(t, err)
service.genesisTime = time.Now()
update, err := service.shouldUpdateCurrentJustified(ctx, &ethpb.Checkpoint{})
update, err := service.shouldUpdateCurrentJustified(ctx, &ethpb.Checkpoint{Root: make([]byte, 32)})
require.NoError(t, err)
assert.Equal(t, true, update, "Should be able to update justified")
lastJustifiedBlk := testutil.NewBeaconBlock()
lastJustifiedBlk.Block.ParentRoot = bytesutil.PadTo([]byte{'G'}, 32)
lastJustifiedRoot, err := stateutil.BlockRoot(lastJustifiedBlk.Block)
lastJustifiedRoot, err := lastJustifiedBlk.Block.HashTreeRoot()
require.NoError(t, err)
newJustifiedBlk := testutil.NewBeaconBlock()
newJustifiedBlk.Block.Slot = 1
newJustifiedBlk.Block.ParentRoot = bytesutil.PadTo(lastJustifiedRoot[:], 32)
newJustifiedRoot, err := stateutil.BlockRoot(newJustifiedBlk.Block)
newJustifiedRoot, err := newJustifiedBlk.Block.HashTreeRoot()
require.NoError(t, err)
require.NoError(t, service.beaconDB.SaveBlock(ctx, newJustifiedBlk))
require.NoError(t, service.beaconDB.SaveBlock(ctx, lastJustifiedBlk))
@@ -193,11 +216,11 @@ func TestShouldUpdateJustified_ReturnFalse(t *testing.T) {
require.NoError(t, err)
lastJustifiedBlk := testutil.NewBeaconBlock()
lastJustifiedBlk.Block.ParentRoot = bytesutil.PadTo([]byte{'G'}, 32)
lastJustifiedRoot, err := stateutil.BlockRoot(lastJustifiedBlk.Block)
lastJustifiedRoot, err := lastJustifiedBlk.Block.HashTreeRoot()
require.NoError(t, err)
newJustifiedBlk := testutil.NewBeaconBlock()
newJustifiedBlk.Block.ParentRoot = bytesutil.PadTo(lastJustifiedRoot[:], 32)
newJustifiedRoot, err := stateutil.BlockRoot(newJustifiedBlk.Block)
newJustifiedRoot, err := newJustifiedBlk.Block.HashTreeRoot()
require.NoError(t, err)
require.NoError(t, service.beaconDB.SaveBlock(ctx, newJustifiedBlk))
require.NoError(t, service.beaconDB.SaveBlock(ctx, lastJustifiedBlk))
@@ -212,9 +235,6 @@ func TestShouldUpdateJustified_ReturnFalse(t *testing.T) {
}
func TestCachedPreState_CanGetFromStateSummary(t *testing.T) {
resetCfg := featureconfig.InitWithReset(&featureconfig.Flags{NewStateMgmt: true})
defer resetCfg()
ctx := context.Background()
db, sc := testDB.SetupDB(t)
@@ -227,17 +247,27 @@ func TestCachedPreState_CanGetFromStateSummary(t *testing.T) {
s, err := stateTrie.InitializeFromProto(&pb.BeaconState{Slot: 1, GenesisValidatorsRoot: params.BeaconConfig().ZeroHash[:]})
require.NoError(t, err)
r := [32]byte{'A'}
b := &ethpb.BeaconBlock{Slot: 1, ParentRoot: r[:]}
require.NoError(t, service.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{Slot: 1, Root: r[:]}))
require.NoError(t, service.stateGen.SaveState(ctx, r, s))
require.NoError(t, service.verifyBlkPreState(ctx, b))
genesisStateRoot := [32]byte{}
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
assert.NoError(t, db.SaveBlock(ctx, genesis))
gRoot, err := genesis.Block.HashTreeRoot()
require.NoError(t, err)
service.finalizedCheckpt = &ethpb.Checkpoint{
Root: gRoot[:],
}
service.forkChoiceStore = protoarray.New(0, 0, [32]byte{})
service.saveInitSyncBlock(gRoot, genesis)
b := testutil.NewBeaconBlock()
b.Block.Slot = 1
b.Block.ParentRoot = gRoot[:]
require.NoError(t, service.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{Slot: 1, Root: gRoot[:]}))
require.NoError(t, service.stateGen.SaveState(ctx, gRoot, s))
require.NoError(t, service.verifyBlkPreState(ctx, b.Block))
}
func TestCachedPreState_CanGetFromDB(t *testing.T) {
resetCfg := featureconfig.InitWithReset(&featureconfig.Flags{NewStateMgmt: true})
defer resetCfg()
ctx := context.Background()
db, sc := testDB.SetupDB(t)
@@ -248,19 +278,30 @@ func TestCachedPreState_CanGetFromDB(t *testing.T) {
service, err := NewService(ctx, cfg)
require.NoError(t, err)
r := [32]byte{'A'}
b := &ethpb.BeaconBlock{Slot: 1, ParentRoot: r[:]}
genesisStateRoot := [32]byte{}
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
assert.NoError(t, db.SaveBlock(ctx, genesis))
gRoot, err := genesis.Block.HashTreeRoot()
require.NoError(t, err)
service.finalizedCheckpt = &ethpb.Checkpoint{
Root: gRoot[:],
}
service.forkChoiceStore = protoarray.New(0, 0, [32]byte{})
service.saveInitSyncBlock(gRoot, genesis)
service.finalizedCheckpt = &ethpb.Checkpoint{Root: r[:]}
err = service.verifyBlkPreState(ctx, b)
b := testutil.NewBeaconBlock()
b.Block.Slot = 1
service.finalizedCheckpt = &ethpb.Checkpoint{Root: gRoot[:]}
err = service.verifyBlkPreState(ctx, b.Block)
wanted := "could not reconstruct parent state"
assert.ErrorContains(t, wanted, err)
b.Block.ParentRoot = gRoot[:]
s, err := stateTrie.InitializeFromProto(&pb.BeaconState{Slot: 1})
require.NoError(t, err)
require.NoError(t, service.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{Slot: 1, Root: r[:]}))
require.NoError(t, service.stateGen.SaveState(ctx, r, s))
require.NoError(t, service.verifyBlkPreState(ctx, b))
require.NoError(t, service.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{Slot: 1, Root: gRoot[:]}))
require.NoError(t, service.stateGen.SaveState(ctx, gRoot, s))
require.NoError(t, service.verifyBlkPreState(ctx, b.Block))
}
func TestUpdateJustified_CouldUpdateBest(t *testing.T) {
@@ -271,9 +312,9 @@ func TestUpdateJustified_CouldUpdateBest(t *testing.T) {
service, err := NewService(ctx, cfg)
require.NoError(t, err)
signedBlock := &ethpb.SignedBeaconBlock{Block: &ethpb.BeaconBlock{}}
signedBlock := testutil.NewBeaconBlock()
require.NoError(t, db.SaveBlock(ctx, signedBlock))
r, err := stateutil.BlockRoot(signedBlock.Block)
r, err := signedBlock.Block.HashTreeRoot()
require.NoError(t, err)
service.justifiedCheckpt = &ethpb.Checkpoint{Root: []byte{'A'}}
service.bestJustifiedCheckpt = &ethpb.Checkpoint{Root: []byte{'A'}}
@@ -303,12 +344,12 @@ func TestFillForkChoiceMissingBlocks_CanSave(t *testing.T) {
service, err := NewService(ctx, cfg)
require.NoError(t, err)
service.forkChoiceStore = protoarray.New(0, 0, [32]byte{'A'})
service.finalizedCheckpt = &ethpb.Checkpoint{}
service.finalizedCheckpt = &ethpb.Checkpoint{Root: make([]byte, 32)}
genesisStateRoot := [32]byte{}
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
require.NoError(t, db.SaveBlock(ctx, genesis))
validGenesisRoot, err := stateutil.BlockRoot(genesis.Block)
validGenesisRoot, err := genesis.Block.HashTreeRoot()
require.NoError(t, err)
st := testutil.NewBeaconState()
@@ -317,10 +358,12 @@ func TestFillForkChoiceMissingBlocks_CanSave(t *testing.T) {
require.NoError(t, err)
beaconState, _ := testutil.DeterministicGenesisState(t, 32)
block := &ethpb.BeaconBlock{Slot: 9, ParentRoot: roots[8], Body: &ethpb.BeaconBlockBody{Graffiti: []byte{}}}
block := testutil.NewBeaconBlock()
block.Block.Slot = 9
block.Block.ParentRoot = roots[8]
err = service.fillInForkChoiceMissingBlocks(
context.Background(), block, beaconState.FinalizedCheckpoint(), beaconState.CurrentJustifiedCheckpoint())
context.Background(), block.Block, beaconState.FinalizedCheckpoint(), beaconState.CurrentJustifiedCheckpoint())
require.NoError(t, err)
// 5 nodes from the block tree 1. B0 - B3 - B4 - B6 - B8
@@ -344,22 +387,27 @@ func TestFillForkChoiceMissingBlocks_FilterFinalized(t *testing.T) {
genesisStateRoot := [32]byte{}
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
assert.NoError(t, db.SaveBlock(ctx, genesis))
validGenesisRoot, err := stateutil.BlockRoot(genesis.Block)
validGenesisRoot, err := genesis.Block.HashTreeRoot()
assert.NoError(t, err)
st := testutil.NewBeaconState()
require.NoError(t, service.beaconDB.SaveState(ctx, st.Copy(), validGenesisRoot))
// Define a tree branch, slot 63 <- 64 <- 65
b63 := &ethpb.SignedBeaconBlock{Block: &ethpb.BeaconBlock{Slot: 63, Body: &ethpb.BeaconBlockBody{}}}
b63 := testutil.NewBeaconBlock()
b63.Block.Slot = 63
require.NoError(t, service.beaconDB.SaveBlock(ctx, b63))
r63, err := stateutil.BlockRoot(b63.Block)
r63, err := b63.Block.HashTreeRoot()
require.NoError(t, err)
b64 := &ethpb.SignedBeaconBlock{Block: &ethpb.BeaconBlock{Slot: 64, ParentRoot: r63[:], Body: &ethpb.BeaconBlockBody{}}}
b64 := testutil.NewBeaconBlock()
b64.Block.Slot = 64
b64.Block.ParentRoot = r63[:]
require.NoError(t, service.beaconDB.SaveBlock(ctx, b64))
r64, err := stateutil.BlockRoot(b64.Block)
r64, err := b64.Block.HashTreeRoot()
require.NoError(t, err)
b65 := &ethpb.SignedBeaconBlock{Block: &ethpb.BeaconBlock{Slot: 65, ParentRoot: r64[:], Body: &ethpb.BeaconBlockBody{}}}
b65 := testutil.NewBeaconBlock()
b65.Block.Slot = 65
b65.Block.ParentRoot = r64[:]
require.NoError(t, service.beaconDB.SaveBlock(ctx, b65))
beaconState, _ := testutil.DeterministicGenesisState(t, 32)
@@ -380,58 +428,74 @@ func TestFillForkChoiceMissingBlocks_FilterFinalized(t *testing.T) {
// \- B3 - B4 - B6 - B8
// (B1, and B3 are all from the same slots)
func blockTree1(db db.Database, genesisRoot []byte) ([][]byte, error) {
b0 := &ethpb.BeaconBlock{Slot: 0, ParentRoot: genesisRoot}
r0, err := ssz.HashTreeRoot(b0)
genesisRoot = bytesutil.PadTo(genesisRoot, 32)
b0 := testutil.NewBeaconBlock()
b0.Block.Slot = 0
b0.Block.ParentRoot = genesisRoot
r0, err := b0.Block.HashTreeRoot()
if err != nil {
return nil, err
}
b1 := &ethpb.BeaconBlock{Slot: 1, ParentRoot: r0[:]}
r1, err := ssz.HashTreeRoot(b1)
b1 := testutil.NewBeaconBlock()
b1.Block.Slot = 1
b1.Block.ParentRoot = r0[:]
r1, err := b1.Block.HashTreeRoot()
if err != nil {
return nil, err
}
b3 := &ethpb.BeaconBlock{Slot: 3, ParentRoot: r0[:]}
r3, err := ssz.HashTreeRoot(b3)
b3 := testutil.NewBeaconBlock()
b3.Block.Slot = 3
b3.Block.ParentRoot = r0[:]
r3, err := b3.Block.HashTreeRoot()
if err != nil {
return nil, err
}
b4 := &ethpb.BeaconBlock{Slot: 4, ParentRoot: r3[:]}
r4, err := ssz.HashTreeRoot(b4)
b4 := testutil.NewBeaconBlock()
b4.Block.Slot = 4
b4.Block.ParentRoot = r3[:]
r4, err := b4.Block.HashTreeRoot()
if err != nil {
return nil, err
}
b5 := &ethpb.BeaconBlock{Slot: 5, ParentRoot: r4[:]}
r5, err := ssz.HashTreeRoot(b5)
b5 := testutil.NewBeaconBlock()
b5.Block.Slot = 5
b5.Block.ParentRoot = r4[:]
r5, err := b5.Block.HashTreeRoot()
if err != nil {
return nil, err
}
b6 := &ethpb.BeaconBlock{Slot: 6, ParentRoot: r4[:]}
r6, err := ssz.HashTreeRoot(b6)
b6 := testutil.NewBeaconBlock()
b6.Block.Slot = 6
b6.Block.ParentRoot = r4[:]
r6, err := b6.Block.HashTreeRoot()
if err != nil {
return nil, err
}
b7 := &ethpb.BeaconBlock{Slot: 7, ParentRoot: r5[:]}
r7, err := ssz.HashTreeRoot(b7)
b7 := testutil.NewBeaconBlock()
b7.Block.Slot = 7
b7.Block.ParentRoot = r5[:]
r7, err := b7.Block.HashTreeRoot()
if err != nil {
return nil, err
}
b8 := &ethpb.BeaconBlock{Slot: 8, ParentRoot: r6[:]}
r8, err := ssz.HashTreeRoot(b8)
b8 := testutil.NewBeaconBlock()
b8.Block.Slot = 8
b8.Block.ParentRoot = r6[:]
r8, err := b8.Block.HashTreeRoot()
if err != nil {
return nil, err
}
st := testutil.NewBeaconState()
for _, b := range []*ethpb.BeaconBlock{b0, b1, b3, b4, b5, b6, b7, b8} {
for _, b := range []*ethpb.SignedBeaconBlock{b0, b1, b3, b4, b5, b6, b7, b8} {
beaconBlock := testutil.NewBeaconBlock()
beaconBlock.Block.Slot = b.Slot
beaconBlock.Block.ParentRoot = bytesutil.PadTo(b.ParentRoot, 32)
beaconBlock.Block.Body = &ethpb.BeaconBlockBody{}
beaconBlock.Block.Slot = b.Block.Slot
beaconBlock.Block.ParentRoot = bytesutil.PadTo(b.Block.ParentRoot, 32)
if err := db.SaveBlock(context.Background(), beaconBlock); err != nil {
return nil, err
}
if err := db.SaveState(context.Background(), st.Copy(), bytesutil.ToBytes32(beaconBlock.Block.ParentRoot)); err != nil {
return nil, err
return nil, errors.Wrap(err, "could not save state")
}
}
if err := db.SaveState(context.Background(), st.Copy(), r1); err != nil {
@@ -447,11 +511,20 @@ func blockTree1(db db.Database, genesisRoot []byte) ([][]byte, error) {
}
func TestCurrentSlot_HandlesOverflow(t *testing.T) {
svc := Service{genesisTime: roughtime.Now().Add(1 * time.Hour)}
svc := Service{genesisTime: timeutils.Now().Add(1 * time.Hour)}
slot := svc.CurrentSlot()
require.Equal(t, uint64(0), slot, "Unexpected slot")
}
func TestAncestorByDB_CtxErr(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
service, err := NewService(ctx, &Config{})
require.NoError(t, err)
cancel()
_, err = service.ancestorByDB(ctx, [32]byte{}, 0)
require.ErrorContains(t, "context canceled", err)
}
func TestAncestor_HandleSkipSlot(t *testing.T) {
ctx := context.Background()
@@ -461,20 +534,25 @@ func TestAncestor_HandleSkipSlot(t *testing.T) {
service, err := NewService(ctx, cfg)
require.NoError(t, err)
b1 := &ethpb.BeaconBlock{Slot: 1, ParentRoot: []byte{'a'}}
r1, err := ssz.HashTreeRoot(b1)
b1 := testutil.NewBeaconBlock()
b1.Block.Slot = 1
b1.Block.ParentRoot = bytesutil.PadTo([]byte{'a'}, 32)
r1, err := b1.Block.HashTreeRoot()
require.NoError(t, err)
b100 := &ethpb.BeaconBlock{Slot: 100, ParentRoot: r1[:]}
r100, err := ssz.HashTreeRoot(b100)
b100 := testutil.NewBeaconBlock()
b100.Block.Slot = 100
b100.Block.ParentRoot = r1[:]
r100, err := b100.Block.HashTreeRoot()
require.NoError(t, err)
b200 := &ethpb.BeaconBlock{Slot: 200, ParentRoot: r100[:]}
r200, err := ssz.HashTreeRoot(b200)
b200 := testutil.NewBeaconBlock()
b200.Block.Slot = 200
b200.Block.ParentRoot = r100[:]
r200, err := b200.Block.HashTreeRoot()
require.NoError(t, err)
for _, b := range []*ethpb.BeaconBlock{b1, b100, b200} {
for _, b := range []*ethpb.SignedBeaconBlock{b1, b100, b200} {
beaconBlock := testutil.NewBeaconBlock()
beaconBlock.Block.Slot = b.Slot
beaconBlock.Block.ParentRoot = bytesutil.PadTo(b.ParentRoot, 32)
beaconBlock.Block.Body = &ethpb.BeaconBlockBody{}
beaconBlock.Block.Slot = b.Block.Slot
beaconBlock.Block.ParentRoot = bytesutil.PadTo(b.Block.ParentRoot, 32)
require.NoError(t, db.SaveBlock(context.Background(), beaconBlock))
}
@@ -493,6 +571,82 @@ func TestAncestor_HandleSkipSlot(t *testing.T) {
}
}
func TestAncestor_CanUseForkchoice(t *testing.T) {
ctx := context.Background()
cfg := &Config{ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}
service, err := NewService(ctx, cfg)
require.NoError(t, err)
b1 := testutil.NewBeaconBlock()
b1.Block.Slot = 1
b1.Block.ParentRoot = bytesutil.PadTo([]byte{'a'}, 32)
r1, err := b1.Block.HashTreeRoot()
require.NoError(t, err)
b100 := testutil.NewBeaconBlock()
b100.Block.Slot = 100
b100.Block.ParentRoot = r1[:]
r100, err := b100.Block.HashTreeRoot()
require.NoError(t, err)
b200 := testutil.NewBeaconBlock()
b200.Block.Slot = 200
b200.Block.ParentRoot = r100[:]
r200, err := b200.Block.HashTreeRoot()
require.NoError(t, err)
for _, b := range []*ethpb.SignedBeaconBlock{b1, b100, b200} {
beaconBlock := testutil.NewBeaconBlock()
beaconBlock.Block.Slot = b.Block.Slot
beaconBlock.Block.ParentRoot = bytesutil.PadTo(b.Block.ParentRoot, 32)
r, err := b.Block.HashTreeRoot()
require.NoError(t, err)
require.NoError(t, service.forkChoiceStore.ProcessBlock(context.Background(), b.Block.Slot, r, bytesutil.ToBytes32(b.Block.ParentRoot), [32]byte{}, 0, 0)) // Saves blocks to fork choice store.
}
r, err := service.ancestor(context.Background(), r200[:], 150)
require.NoError(t, err)
if bytesutil.ToBytes32(r) != r100 {
t.Error("Did not get correct root")
}
}
func TestAncestor_CanUseDB(t *testing.T) {
ctx := context.Background()
db, _ := testDB.SetupDB(t)
cfg := &Config{BeaconDB: db, ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}
service, err := NewService(ctx, cfg)
require.NoError(t, err)
b1 := testutil.NewBeaconBlock()
b1.Block.Slot = 1
b1.Block.ParentRoot = bytesutil.PadTo([]byte{'a'}, 32)
r1, err := b1.Block.HashTreeRoot()
require.NoError(t, err)
b100 := testutil.NewBeaconBlock()
b100.Block.Slot = 100
b100.Block.ParentRoot = r1[:]
r100, err := b100.Block.HashTreeRoot()
require.NoError(t, err)
b200 := testutil.NewBeaconBlock()
b200.Block.Slot = 200
b200.Block.ParentRoot = r100[:]
r200, err := b200.Block.HashTreeRoot()
require.NoError(t, err)
for _, b := range []*ethpb.SignedBeaconBlock{b1, b100, b200} {
beaconBlock := testutil.NewBeaconBlock()
beaconBlock.Block.Slot = b.Block.Slot
beaconBlock.Block.ParentRoot = bytesutil.PadTo(b.Block.ParentRoot, 32)
require.NoError(t, db.SaveBlock(context.Background(), beaconBlock)) // Saves blocks to DB.
}
require.NoError(t, service.forkChoiceStore.ProcessBlock(context.Background(), 200, r200, r200, [32]byte{}, 0, 0))
r, err := service.ancestor(context.Background(), r200[:], 150)
require.NoError(t, err)
if bytesutil.ToBytes32(r) != r100 {
t.Error("Did not get correct root")
}
}
func TestEnsureRootNotZeroHashes(t *testing.T) {
ctx := context.Background()
cfg := &Config{}
@@ -557,16 +711,20 @@ func TestFinalizedImpliesNewJustified(t *testing.T) {
require.NoError(t, service.beaconDB.SaveState(ctx, genesisState, bytesutil.ToBytes32(test.want.Root)))
if test.args.diffFinalizedCheckPoint {
b1 := &ethpb.BeaconBlock{Slot: 1, ParentRoot: []byte{'a'}}
r1, err := ssz.HashTreeRoot(b1)
b1 := testutil.NewBeaconBlock()
b1.Block.Slot = 1
b1.Block.ParentRoot = bytesutil.PadTo([]byte{'a'}, 32)
r1, err := b1.Block.HashTreeRoot()
require.NoError(t, err)
b100 := &ethpb.BeaconBlock{Slot: 100, ParentRoot: r1[:]}
r100, err := ssz.HashTreeRoot(b100)
b100 := testutil.NewBeaconBlock()
b100.Block.Slot = 100
b100.Block.ParentRoot = r1[:]
r100, err := b100.Block.HashTreeRoot()
require.NoError(t, err)
for _, b := range []*ethpb.BeaconBlock{b1, b100} {
for _, b := range []*ethpb.SignedBeaconBlock{b1, b100} {
beaconBlock := testutil.NewBeaconBlock()
beaconBlock.Block.Slot = b.Slot
beaconBlock.Block.ParentRoot = bytesutil.PadTo(b.ParentRoot, 32)
beaconBlock.Block.Slot = b.Block.Slot
beaconBlock.Block.ParentRoot = bytesutil.PadTo(b.Block.ParentRoot, 32)
require.NoError(t, service.beaconDB.SaveBlock(context.Background(), beaconBlock))
}
service.finalizedCheckpt = &ethpb.Checkpoint{Root: []byte{'c'}, Epoch: 1}
@@ -584,14 +742,14 @@ func TestVerifyBlkDescendant(t *testing.T) {
b := testutil.NewBeaconBlock()
b.Block.Slot = 1
r, err := stateutil.BlockRoot(b.Block)
r, err := b.Block.HashTreeRoot()
require.NoError(t, err)
require.NoError(t, db.SaveBlock(ctx, b))
b1 := testutil.NewBeaconBlock()
b1.Block.Slot = 1
b1.Block.Body.Graffiti = bytesutil.PadTo([]byte{'a'}, 32)
r1, err := stateutil.BlockRoot(b1.Block)
r1, err := b1.Block.HashTreeRoot()
require.NoError(t, err)
require.NoError(t, db.SaveBlock(ctx, b1))
@@ -601,18 +759,16 @@ func TestVerifyBlkDescendant(t *testing.T) {
finalizedSlot uint64
}
tests := []struct {
name string
args args
shouldError bool
err string
name string
args args
wantedErr string
}{
{
name: "could not get finalized block in block service cache",
args: args{
finalizedRoot: [32]byte{'a'},
},
shouldError: true,
err: "nil finalized block",
wantedErr: "nil finalized block",
},
{
name: "could not get finalized block root in DB",
@@ -620,8 +776,7 @@ func TestVerifyBlkDescendant(t *testing.T) {
finalizedRoot: r,
parentRoot: [32]byte{'a'},
},
shouldError: true,
err: "could not get finalized block root",
wantedErr: "could not get finalized block root",
},
{
name: "is not descendant",
@@ -629,8 +784,7 @@ func TestVerifyBlkDescendant(t *testing.T) {
finalizedRoot: r1,
parentRoot: r,
},
shouldError: true,
err: "is not a descendent of the current finalized block slot",
wantedErr: "is not a descendent of the current finalized block slot",
},
{
name: "is descendant",
@@ -638,22 +792,19 @@ func TestVerifyBlkDescendant(t *testing.T) {
finalizedRoot: r,
parentRoot: r,
},
shouldError: false,
},
}
for _, test := range tests {
for _, tt := range tests {
service, err := NewService(ctx, &Config{BeaconDB: db, StateGen: stategen.New(db, sc), ForkChoiceStore: protoarray.New(0, 0, [32]byte{})})
require.NoError(t, err)
service.finalizedCheckpt = &ethpb.Checkpoint{
Root: test.args.finalizedRoot[:],
Root: tt.args.finalizedRoot[:],
}
err = service.VerifyBlkDescendant(ctx, test.args.parentRoot)
if test.shouldError {
if err == nil || !strings.Contains(err.Error(), test.err) {
t.Error("Did not get wanted error")
}
err = service.VerifyBlkDescendant(ctx, tt.args.parentRoot)
if tt.wantedErr != "" {
assert.ErrorContains(t, tt.wantedErr, err)
} else if err != nil {
t.Error(err)
assert.NoError(t, err)
}
}
}
@@ -665,8 +816,8 @@ func TestUpdateJustifiedInitSync(t *testing.T) {
service, err := NewService(ctx, cfg)
require.NoError(t, err)
gBlk := &ethpb.SignedBeaconBlock{Block: &ethpb.BeaconBlock{}}
gRoot, err := stateutil.BlockRoot(gBlk.Block)
gBlk := testutil.NewBeaconBlock()
gRoot, err := gBlk.Block.HashTreeRoot()
require.NoError(t, err)
require.NoError(t, service.beaconDB.SaveBlock(ctx, gBlk))
require.NoError(t, service.beaconDB.SaveGenesisBlockRoot(ctx, gRoot))
@@ -683,8 +834,6 @@ func TestUpdateJustifiedInitSync(t *testing.T) {
assert.DeepEqual(t, currentCp, service.prevJustifiedCheckpt, "Incorrect previous justified checkpoint")
assert.DeepEqual(t, newCp, service.CurrentJustifiedCheckpt(), "Incorrect current justified checkpoint in cache")
cp, err := service.beaconDB.JustifiedCheckpoint(ctx)
if err != nil {
t.Fatal(err)
}
require.NoError(t, err)
assert.DeepEqual(t, newCp, cp, "Incorrect current justified checkpoint in db")
}

View File

@@ -10,11 +10,12 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/featureconfig"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/roughtime"
"github.com/prysmaticlabs/prysm/shared/slotutil"
"github.com/prysmaticlabs/prysm/shared/timeutils"
"github.com/sirupsen/logrus"
"go.opencensus.io/trace"
)
@@ -24,6 +25,8 @@ type AttestationReceiver interface {
ReceiveAttestationNoPubsub(ctx context.Context, att *ethpb.Attestation) error
IsValidAttestation(ctx context.Context, att *ethpb.Attestation) bool
AttestationPreState(ctx context.Context, att *ethpb.Attestation) (*state.BeaconState, error)
AttestationCheckPtInfo(ctx context.Context, att *ethpb.Attestation) (*pb.CheckPtInfo, error)
VerifyLmdFfgConsistency(ctx context.Context, att *ethpb.Attestation) error
}
// ReceiveAttestationNoPubsub is a function that defines the operations that are performed on
@@ -61,7 +64,7 @@ func (s *Service) IsValidAttestation(ctx context.Context, att *ethpb.Attestation
return false
}
if err := blocks.VerifyAttestation(ctx, baseState, att); err != nil {
if err := blocks.VerifyAttestationSignature(ctx, baseState, att); err != nil {
log.WithError(err).Error("Failed to validate attestation")
return false
}
@@ -71,9 +74,34 @@ func (s *Service) IsValidAttestation(ctx context.Context, att *ethpb.Attestation
// AttestationPreState returns the pre state of attestation.
func (s *Service) AttestationPreState(ctx context.Context, att *ethpb.Attestation) (*state.BeaconState, error) {
ss, err := helpers.StartSlot(att.Data.Target.Epoch)
if err != nil {
return nil, err
}
if err := helpers.ValidateSlotClock(ss, uint64(s.genesisTime.Unix())); err != nil {
return nil, err
}
return s.getAttPreState(ctx, att.Data.Target)
}
// AttestationCheckPtInfo returns the check point info of attestation that can be used to verify the attestation
// contents and signatures.
func (s *Service) AttestationCheckPtInfo(ctx context.Context, att *ethpb.Attestation) (*pb.CheckPtInfo, error) {
ss, err := helpers.StartSlot(att.Data.Target.Epoch)
if err != nil {
return nil, err
}
if err := helpers.ValidateSlotClock(ss, uint64(s.genesisTime.Unix())); err != nil {
return nil, err
}
return s.getAttCheckPtInfo(ctx, att.Data.Target, helpers.SlotToEpoch(att.Data.Slot))
}
// VerifyLmdFfgConsistency verifies that attestation's LMD and FFG votes are consistency to each other.
func (s *Service) VerifyLmdFfgConsistency(ctx context.Context, a *ethpb.Attestation) error {
return s.verifyLMDFFGConsistent(ctx, a.Data.Target.Epoch, a.Data.Target.Root, a.Data.BeaconBlockRoot)
}
// This processes attestations from the attestation pool to account for validator votes and fork choice.
func (s *Service) processAttestation(subscribedToStateEvents chan struct{}) {
// Wait for state to be initialized.
@@ -89,7 +117,7 @@ func (s *Service) processAttestation(subscribedToStateEvents chan struct{}) {
case <-s.ctx.Done():
return
case <-st.C():
ctx := context.Background()
ctx := s.ctx
atts := s.attPool.ForkchoiceAttestations()
for _, a := range atts {
// Based on the spec, don't process the attestation until the subsequent slot.
@@ -131,7 +159,7 @@ func (s *Service) processAttestation(subscribedToStateEvents chan struct{}) {
// This verifies the epoch of input checkpoint is within current epoch and previous epoch
// with respect to current time. Returns true if it's within, false if it's not.
func (s *Service) verifyCheckpointEpoch(c *ethpb.Checkpoint) bool {
now := uint64(roughtime.Now().Unix())
now := uint64(timeutils.Now().Unix())
genesisTime := uint64(s.genesisTime.Unix())
currentSlot := (now - genesisTime) / params.BeaconConfig().SecondsPerSlot
currentEpoch := helpers.SlotToEpoch(currentSlot)

View File

@@ -1,13 +1,16 @@
package blockchain
import (
"context"
"testing"
"time"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
)
func TestVerifyCheckpointEpoch_Ok(t *testing.T) {
@@ -17,6 +20,30 @@ func TestVerifyCheckpointEpoch_Ok(t *testing.T) {
chainService := setupBeaconChain(t, db, sc)
chainService.genesisTime = time.Now()
assert.Equal(t, true, chainService.verifyCheckpointEpoch(&ethpb.Checkpoint{}))
assert.Equal(t, true, chainService.verifyCheckpointEpoch(&ethpb.Checkpoint{Root: make([]byte, 32)}))
assert.Equal(t, false, chainService.verifyCheckpointEpoch(&ethpb.Checkpoint{Epoch: 1}))
}
func TestAttestationPreState_FarFutureSlot(t *testing.T) {
helpers.ClearCache()
db, sc := testDB.SetupDB(t)
chainService := setupBeaconChain(t, db, sc)
chainService.genesisTime = time.Now()
e := helpers.MaxSlotBuffer/params.BeaconConfig().SlotsPerEpoch + 1
_, err := chainService.AttestationCheckPtInfo(context.Background(), &ethpb.Attestation{Data: &ethpb.AttestationData{Target: &ethpb.Checkpoint{Epoch: e}}})
require.ErrorContains(t, "exceeds max allowed value relative to the local clock", err)
}
func TestAttestationCheckPtInfo_FarFutureSlot(t *testing.T) {
helpers.ClearCache()
db, sc := testDB.SetupDB(t)
chainService := setupBeaconChain(t, db, sc)
chainService.genesisTime = time.Now()
e := helpers.MaxSlotBuffer/params.BeaconConfig().SlotsPerEpoch + 1
_, err := chainService.AttestationPreState(context.Background(), &ethpb.Attestation{Data: &ethpb.AttestationData{Target: &ethpb.Checkpoint{Epoch: e}}})
require.ErrorContains(t, "exceeds max allowed value relative to the local clock", err)
}

View File

@@ -40,7 +40,7 @@ func (s *Service) ReceiveBlock(ctx context.Context, block *ethpb.SignedBeaconBlo
// Update and save head block after fork choice.
if err := s.updateHead(ctx, s.getJustifiedBalances()); err != nil {
return errors.Wrap(err, "could not update head")
log.WithError(err).Warn("Could not update head")
}
// Send notification of the processed block to the state feed.
@@ -59,7 +59,7 @@ func (s *Service) ReceiveBlock(ctx context.Context, block *ethpb.SignedBeaconBlo
}
// Reports on block and fork choice metrics.
reportSlotMetrics(blockCopy.Block.Slot, s.headSlot(), s.CurrentSlot(), s.finalizedCheckpt)
reportSlotMetrics(blockCopy.Block.Slot, s.HeadSlot(), s.CurrentSlot(), s.finalizedCheckpt)
// Log block sync status.
logBlockSyncStatus(blockCopy.Block, blockRoot, s.finalizedCheckpt)
@@ -95,7 +95,7 @@ func (s *Service) ReceiveBlockInitialSync(ctx context.Context, block *ethpb.Sign
})
// Reports on blockCopy and fork choice metrics.
reportSlotMetrics(blockCopy.Block.Slot, s.headSlot(), s.CurrentSlot(), s.finalizedCheckpt)
reportSlotMetrics(blockCopy.Block.Slot, s.HeadSlot(), s.CurrentSlot(), s.finalizedCheckpt)
// Log state transition data.
log.WithFields(logrus.Fields{
@@ -139,7 +139,14 @@ func (s *Service) ReceiveBlockBatch(ctx context.Context, blocks []*ethpb.SignedB
})
// Reports on blockCopy and fork choice metrics.
reportSlotMetrics(blockCopy.Block.Slot, s.headSlot(), s.CurrentSlot(), s.finalizedCheckpt)
reportSlotMetrics(blockCopy.Block.Slot, s.HeadSlot(), s.CurrentSlot(), s.finalizedCheckpt)
}
if err := s.VerifyWeakSubjectivityRoot(s.ctx); err != nil {
// log.Fatalf will prevent defer from being called
span.End()
// Exit run time if the node failed to verify weak subjectivity checkpoint.
log.Fatalf("Could not verify weak subjectivity checkpoint: %v", err)
}
return nil

View File

@@ -12,7 +12,6 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/operations/attestations"
"github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
@@ -37,10 +36,10 @@ func TestService_ReceiveBlock(t *testing.T) {
block *ethpb.SignedBeaconBlock
}
tests := []struct {
name string
args args
wantErr bool
check func(*testing.T, *Service)
name string
args args
wantedErr string
check func(*testing.T, *Service)
}{
{
name: "applies block with state transition",
@@ -139,13 +138,16 @@ func TestService_ReceiveBlock(t *testing.T) {
require.NoError(t, s.saveGenesisData(ctx, genesis))
gBlk, err := s.beaconDB.GenesisBlock(ctx)
require.NoError(t, err)
gRoot, err := stateutil.BlockRoot(gBlk.Block)
s.finalizedCheckpt = &ethpb.Checkpoint{Root: gRoot[:]}
root, err := stateutil.BlockRoot(tt.args.block.Block)
gRoot, err := gBlk.Block.HashTreeRoot()
require.NoError(t, err)
if err := s.ReceiveBlock(ctx, tt.args.block, root); (err != nil) != tt.wantErr {
t.Errorf("ReceiveBlock() error = %v, wantErr %v", err, tt.wantErr)
s.finalizedCheckpt = &ethpb.Checkpoint{Root: gRoot[:]}
root, err := tt.args.block.Block.HashTreeRoot()
require.NoError(t, err)
err = s.ReceiveBlock(ctx, tt.args.block, root)
if tt.wantedErr != "" {
assert.ErrorContains(t, tt.wantedErr, err)
} else {
assert.NoError(t, err)
tt.check(t, s)
}
})
@@ -177,9 +179,10 @@ func TestService_ReceiveBlockUpdateHead(t *testing.T) {
require.NoError(t, s.saveGenesisData(ctx, genesis))
gBlk, err := s.beaconDB.GenesisBlock(ctx)
require.NoError(t, err)
gRoot, err := stateutil.BlockRoot(gBlk.Block)
gRoot, err := gBlk.Block.HashTreeRoot()
require.NoError(t, err)
s.finalizedCheckpt = &ethpb.Checkpoint{Root: gRoot[:]}
root, err := stateutil.BlockRoot(b.Block)
root, err := b.Block.HashTreeRoot()
require.NoError(t, err)
wg := sync.WaitGroup{}
wg.Add(1)
@@ -201,9 +204,7 @@ func TestService_ReceiveBlockInitialSync(t *testing.T) {
genesis, keys := testutil.DeterministicGenesisState(t, 64)
genFullBlock := func(t *testing.T, conf *testutil.BlockGenConfig, slot uint64) *ethpb.SignedBeaconBlock {
blk, err := testutil.GenerateFullBlock(genesis, keys, conf, slot)
if err != nil {
t.Error(err)
}
assert.NoError(t, err)
return blk
}
@@ -211,10 +212,10 @@ func TestService_ReceiveBlockInitialSync(t *testing.T) {
block *ethpb.SignedBeaconBlock
}
tests := []struct {
name string
args args
wantErr bool
check func(*testing.T, *Service)
name string
args args
wantedErr string
check func(*testing.T, *Service)
}{
{
name: "applies block with state transition",
@@ -261,14 +262,17 @@ func TestService_ReceiveBlockInitialSync(t *testing.T) {
gBlk, err := s.beaconDB.GenesisBlock(ctx)
require.NoError(t, err)
gRoot, err := stateutil.BlockRoot(gBlk.Block)
gRoot, err := gBlk.Block.HashTreeRoot()
require.NoError(t, err)
s.finalizedCheckpt = &ethpb.Checkpoint{Root: gRoot[:]}
root, err := stateutil.BlockRoot(tt.args.block.Block)
root, err := tt.args.block.Block.HashTreeRoot()
require.NoError(t, err)
if err := s.ReceiveBlockInitialSync(ctx, tt.args.block, root); (err != nil) != tt.wantErr {
t.Errorf("ReceiveBlockInitialSync() error = %v, wantErr %v", err, tt.wantErr)
err = s.ReceiveBlockInitialSync(ctx, tt.args.block, root)
if tt.wantedErr != "" {
assert.ErrorContains(t, tt.wantedErr, err)
} else {
assert.NoError(t, err)
tt.check(t, s)
}
})
@@ -281,9 +285,7 @@ func TestService_ReceiveBlockBatch(t *testing.T) {
genesis, keys := testutil.DeterministicGenesisState(t, 64)
genFullBlock := func(t *testing.T, conf *testutil.BlockGenConfig, slot uint64) *ethpb.SignedBeaconBlock {
blk, err := testutil.GenerateFullBlock(genesis, keys, conf, slot)
if err != nil {
t.Error(err)
}
assert.NoError(t, err)
return blk
}
@@ -291,10 +293,10 @@ func TestService_ReceiveBlockBatch(t *testing.T) {
block *ethpb.SignedBeaconBlock
}
tests := []struct {
name string
args args
wantErr bool
check func(*testing.T, *Service)
name string
args args
wantedErr string
check func(*testing.T, *Service)
}{
{
name: "applies block with state transition",
@@ -322,8 +324,8 @@ func TestService_ReceiveBlockBatch(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
db, stateSummaryCache := testDB.SetupDB(t)
genesisBlockRoot := bytesutil.ToBytes32(nil)
genesisBlockRoot, err := genesis.HashTreeRoot(ctx)
require.NoError(t, err)
cfg := &Config{
BeaconDB: db,
ForkChoiceStore: protoarray.New(
@@ -341,15 +343,18 @@ func TestService_ReceiveBlockBatch(t *testing.T) {
gBlk, err := s.beaconDB.GenesisBlock(ctx)
require.NoError(t, err)
gRoot, err := stateutil.BlockRoot(gBlk.Block)
gRoot, err := gBlk.Block.HashTreeRoot()
require.NoError(t, err)
s.finalizedCheckpt = &ethpb.Checkpoint{Root: gRoot[:]}
root, err := stateutil.BlockRoot(tt.args.block.Block)
root, err := tt.args.block.Block.HashTreeRoot()
require.NoError(t, err)
blks := []*ethpb.SignedBeaconBlock{tt.args.block}
roots := [][32]byte{root}
if err := s.ReceiveBlockBatch(ctx, blks, roots); (err != nil) != tt.wantErr {
t.Errorf("ReceiveBlockBatch() error = %v, wantErr %v", err, tt.wantErr)
err = s.ReceiveBlockBatch(ctx, blks, roots)
if tt.wantedErr != "" {
assert.ErrorContains(t, tt.wantedErr, err)
} else {
assert.NoError(t, err)
tt.check(t, s)
}
})

View File

@@ -30,7 +30,6 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
@@ -75,6 +74,10 @@ type Service struct {
recentCanonicalBlocksLock sync.RWMutex
justifiedBalances []uint64
justifiedBalancesLock sync.RWMutex
checkPtInfoCache *checkPtInfoCache
wsEpoch uint64
wsRoot []byte
wsVerified bool
}
// Config options for the service.
@@ -92,6 +95,8 @@ type Config struct {
ForkChoiceStore f.ForkChoicer
OpsService *attestations.Service
StateGen *stategen.State
WspBlockRoot []byte
WspEpoch uint64
}
// NewService instantiates a new block service instance that will
@@ -119,6 +124,9 @@ func NewService(ctx context.Context, cfg *Config) (*Service, error) {
initSyncBlocks: make(map[[32]byte]*ethpb.SignedBeaconBlock),
recentCanonicalBlocks: make(map[[32]byte]bool),
justifiedBalances: make([]uint64, 0),
checkPtInfoCache: newCheckPointInfoCache(),
wsEpoch: cfg.WspEpoch,
wsRoot: cfg.WspBlockRoot,
}, nil
}
@@ -138,7 +146,23 @@ func (s *Service) Start() {
}
if beaconState == nil {
beaconState, err = s.stateGen.StateByRoot(s.ctx, bytesutil.ToBytes32(cp.Root))
r := bytesutil.ToBytes32(cp.Root)
// Before the first finalized epoch, in the current epoch,
// the finalized root is defined as zero hashes instead of genesis root hash.
// We want to use genesis root to retrieve for state.
if r == params.BeaconConfig().ZeroHash {
genesisBlock, err := s.beaconDB.GenesisBlock(s.ctx)
if err != nil {
log.Fatalf("Could not fetch finalized cp: %v", err)
}
if genesisBlock != nil {
r, err = genesisBlock.Block.HashTreeRoot()
if err != nil {
log.Fatalf("Could not tree hash genesis block: %v", err)
}
}
}
beaconState, err = s.stateGen.StateByRoot(s.ctx, r)
if err != nil {
log.Fatalf("Could not fetch beacon state by root: %v", err)
}
@@ -183,6 +207,11 @@ func (s *Service) Start() {
s.prevFinalizedCheckpt = stateTrie.CopyCheckpoint(finalizedCheckpoint)
s.resumeForkChoice(justifiedCheckpoint, finalizedCheckpoint)
if err := s.VerifyWeakSubjectivityRoot(s.ctx); err != nil {
// Exit run time if the node failed to verify weak subjectivity checkpoint.
log.Fatalf("Could not verify weak subjectivity checkpoint: %v", err)
}
s.stateNotifier.StateFeed().Send(&feed.Event{
Type: statefeed.Initialized,
Data: &statefeed.InitializedData{
@@ -258,7 +287,7 @@ func (s *Service) initializeBeaconChain(
genesisTime time.Time,
preGenesisState *stateTrie.BeaconState,
eth1data *ethpb.Eth1Data) (*stateTrie.BeaconState, error) {
_, span := trace.StartSpan(context.Background(), "beacon-chain.Service.initializeBeaconChain")
ctx, span := trace.StartSpan(ctx, "beacon-chain.Service.initializeBeaconChain")
defer span.End()
s.genesisTime = genesisTime
unixTime := uint64(genesisTime.Unix())
@@ -295,9 +324,13 @@ func (s *Service) Stop() error {
defer s.cancel()
if s.stateGen != nil && s.head != nil && s.head.state != nil {
return s.stateGen.ForceCheckpoint(s.ctx, s.head.state.FinalizedCheckpoint().Root)
if err := s.stateGen.ForceCheckpoint(s.ctx, s.head.state.FinalizedCheckpoint().Root); err != nil {
return err
}
}
return nil
// Save initial sync cached blocks to the DB before stop.
return s.beaconDB.SaveBlocks(s.ctx, s.getInitSyncBlocks())
}
// Status always returns nil unless there is an error condition that causes
@@ -322,7 +355,7 @@ func (s *Service) saveGenesisData(ctx context.Context, genesisState *stateTrie.B
return err
}
genesisBlk := blocks.NewGenesisBlock(stateRoot[:])
genesisBlkRoot, err := stateutil.BlockRoot(genesisBlk.Block)
genesisBlkRoot, err := genesisBlk.Block.HashTreeRoot()
if err != nil {
return errors.Wrap(err, "could not get genesis block root")
}
@@ -386,7 +419,7 @@ func (s *Service) initializeChainInfo(ctx context.Context) error {
if genesisBlock == nil {
return errors.New("no genesis block in db")
}
genesisBlkRoot, err := stateutil.BlockRoot(genesisBlock.Block)
genesisBlkRoot, err := genesisBlock.Block.HashTreeRoot()
if err != nil {
return errors.Wrap(err, "could not get signing root of genesis block")
}
@@ -397,7 +430,7 @@ func (s *Service) initializeChainInfo(ctx context.Context) error {
if err != nil {
return errors.Wrap(err, "could not retrieve head block")
}
headRoot, err := stateutil.BlockRoot(headBlock.Block)
headRoot, err := headBlock.Block.HashTreeRoot()
if err != nil {
return errors.Wrap(err, "could not hash head block")
}
@@ -418,17 +451,13 @@ func (s *Service) initializeChainInfo(ctx context.Context) error {
// would be the genesis state and block.
return errors.New("no finalized epoch in the database")
}
finalizedRoot := bytesutil.ToBytes32(finalized.Root)
finalizedRoot := s.ensureRootNotZeros(bytesutil.ToBytes32(finalized.Root))
var finalizedState *stateTrie.BeaconState
finalizedState, err = s.stateGen.Resume(ctx)
if err != nil {
return errors.Wrap(err, "could not get finalized state from db")
}
finalizedRoot = s.beaconDB.LastArchivedRoot(ctx)
if finalizedRoot == params.BeaconConfig().ZeroHash {
finalizedRoot = bytesutil.ToBytes32(finalized.Root)
}
finalizedBlock, err := s.beaconDB.Block(ctx, finalizedRoot)
if err != nil {

View File

@@ -11,7 +11,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/gogo/protobuf/proto"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/go-ssz"
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
b "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
@@ -25,7 +24,6 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
protodb "github.com/prysmaticlabs/prysm/proto/beacon/db"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
@@ -69,7 +67,7 @@ func (mb *mockBroadcaster) BroadcastAttestation(_ context.Context, _ uint64, _ *
return nil
}
var _ = p2p.Broadcaster(&mockBroadcaster{})
var _ p2p.Broadcaster = (*mockBroadcaster)(nil)
func setupBeaconChain(t *testing.T, beaconDB db.Database, sc *cache.StateSummaryCache) *Service {
endpoint := "http://127.0.0.1"
@@ -103,7 +101,7 @@ func setupBeaconChain(t *testing.T, beaconDB db.Database, sc *cache.StateSummary
opsService, err := attestations.NewService(ctx, &attestations.Config{Pool: attestations.NewPool()})
require.NoError(t, err)
depositCache, err := depositcache.NewDepositCache()
depositCache, err := depositcache.New()
require.NoError(t, err)
cfg := &Config{
@@ -120,9 +118,7 @@ func setupBeaconChain(t *testing.T, beaconDB db.Database, sc *cache.StateSummary
}
// Safe a state in stategen to purposes of testing a service stop / shutdown.
if err := cfg.StateGen.SaveState(ctx, bytesutil.ToBytes32(bState.FinalizedCheckpoint().Root), bState); err != nil {
t.Fatal(err)
}
require.NoError(t, cfg.StateGen.SaveState(ctx, bytesutil.ToBytes32(bState.FinalizedCheckpoint().Root), bState))
chainService, err := NewService(ctx, cfg)
require.NoError(t, err, "Unable to setup chain service")
@@ -139,7 +135,7 @@ func TestChainStartStop_Initialized(t *testing.T) {
chainService := setupBeaconChain(t, db, sc)
genesisBlk := testutil.NewBeaconBlock()
blkRoot, err := stateutil.BlockRoot(genesisBlk.Block)
blkRoot, err := genesisBlk.Block.HashTreeRoot()
require.NoError(t, err)
require.NoError(t, db.SaveBlock(ctx, genesisBlk))
s := testutil.NewBeaconState()
@@ -148,6 +144,7 @@ func TestChainStartStop_Initialized(t *testing.T) {
require.NoError(t, db.SaveHeadBlockRoot(ctx, blkRoot))
require.NoError(t, db.SaveGenesisBlockRoot(ctx, blkRoot))
require.NoError(t, db.SaveJustifiedCheckpoint(ctx, &ethpb.Checkpoint{Root: blkRoot[:]}))
require.NoError(t, db.SaveFinalizedCheckpoint(ctx, &ethpb.Checkpoint{Root: blkRoot[:]}))
// Test the start function.
chainService.Start()
@@ -156,7 +153,33 @@ func TestChainStartStop_Initialized(t *testing.T) {
// The context should have been canceled.
assert.Equal(t, context.Canceled, chainService.ctx.Err(), "Context was not canceled")
testutil.AssertLogsContain(t, hook, "data already exists")
require.LogsContain(t, hook, "data already exists")
}
func TestChainStartStop_GenesisZeroHashes(t *testing.T) {
hook := logTest.NewGlobal()
ctx := context.Background()
db, sc := testDB.SetupDB(t)
chainService := setupBeaconChain(t, db, sc)
genesisBlk := testutil.NewBeaconBlock()
blkRoot, err := genesisBlk.Block.HashTreeRoot()
require.NoError(t, err)
require.NoError(t, db.SaveBlock(ctx, genesisBlk))
s := testutil.NewBeaconState()
require.NoError(t, db.SaveState(ctx, s, blkRoot))
require.NoError(t, db.SaveGenesisBlockRoot(ctx, blkRoot))
require.NoError(t, db.SaveJustifiedCheckpoint(ctx, &ethpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]}))
// Test the start function.
chainService.Start()
require.NoError(t, chainService.Stop(), "Unable to stop chain service")
// The context should have been canceled.
assert.Equal(t, context.Canceled, chainService.ctx.Err(), "Context was not canceled")
require.LogsContain(t, hook, "data already exists")
}
func TestChainService_InitializeBeaconChain(t *testing.T) {
@@ -179,11 +202,13 @@ func TestChainService_InitializeBeaconChain(t *testing.T) {
err = genState.SetEth1Data(&ethpb.Eth1Data{
DepositRoot: hashTreeRoot[:],
DepositCount: uint64(len(deposits)),
BlockHash: make([]byte, 32),
})
require.NoError(t, err)
genState, err = b.ProcessPreGenesisDeposits(ctx, genState, deposits)
require.NoError(t, err)
_, err = bc.initializeBeaconChain(ctx, time.Unix(0, 0), genState, &ethpb.Eth1Data{DepositRoot: hashTreeRoot[:]})
_, err = bc.initializeBeaconChain(ctx, time.Unix(0, 0), genState, &ethpb.Eth1Data{DepositRoot: hashTreeRoot[:], BlockHash: make([]byte, 32)})
require.NoError(t, err)
_, err = bc.HeadState(ctx)
@@ -193,7 +218,9 @@ func TestChainService_InitializeBeaconChain(t *testing.T) {
if headBlk == nil {
t.Error("Head state can't be nil after initialize beacon chain")
}
if bc.headRoot() == params.BeaconConfig().ZeroHash {
r, err := bc.HeadRoot(ctx)
require.NoError(t, err)
if bytesutil.ToBytes32(r) == params.BeaconConfig().ZeroHash {
t.Error("Canonical root for slot 0 can't be zeros after initialize beacon chain")
}
}
@@ -205,7 +232,7 @@ func TestChainService_CorrectGenesisRoots(t *testing.T) {
chainService := setupBeaconChain(t, db, sc)
genesisBlk := testutil.NewBeaconBlock()
blkRoot, err := stateutil.BlockRoot(genesisBlk.Block)
blkRoot, err := genesisBlk.Block.HashTreeRoot()
require.NoError(t, err)
require.NoError(t, db.SaveBlock(ctx, genesisBlk))
s := testutil.NewBeaconState()
@@ -213,10 +240,12 @@ func TestChainService_CorrectGenesisRoots(t *testing.T) {
require.NoError(t, db.SaveState(ctx, s, blkRoot))
require.NoError(t, db.SaveHeadBlockRoot(ctx, blkRoot))
require.NoError(t, db.SaveGenesisBlockRoot(ctx, blkRoot))
require.NoError(t, db.SaveFinalizedCheckpoint(ctx, &ethpb.Checkpoint{Root: blkRoot[:]}))
// Test the start function.
chainService.Start()
require.DeepEqual(t, params.BeaconConfig().ZeroHash[:], chainService.finalizedCheckpt.Root, "Finalize Checkpoint root is incorrect")
require.DeepEqual(t, blkRoot[:], chainService.finalizedCheckpt.Root, "Finalize Checkpoint root is incorrect")
require.DeepEqual(t, params.BeaconConfig().ZeroHash[:], chainService.justifiedCheckpt.Root, "Justified Checkpoint root is incorrect")
require.NoError(t, chainService.Stop(), "Unable to stop chain service")
@@ -228,7 +257,7 @@ func TestChainService_InitializeChainInfo(t *testing.T) {
ctx := context.Background()
genesis := testutil.NewBeaconBlock()
genesisRoot, err := stateutil.BlockRoot(genesis.Block)
genesisRoot, err := genesis.Block.HashTreeRoot()
require.NoError(t, err)
require.NoError(t, db.SaveGenesisBlockRoot(ctx, genesisRoot))
require.NoError(t, db.SaveBlock(ctx, genesis))
@@ -240,17 +269,12 @@ func TestChainService_InitializeChainInfo(t *testing.T) {
headState := testutil.NewBeaconState()
require.NoError(t, headState.SetSlot(finalizedSlot))
require.NoError(t, headState.SetGenesisValidatorRoot(params.BeaconConfig().ZeroHash[:]))
headRoot, err := stateutil.BlockRoot(headBlock.Block)
headRoot, err := headBlock.Block.HashTreeRoot()
require.NoError(t, err)
require.NoError(t, db.SaveState(ctx, headState, headRoot))
require.NoError(t, db.SaveState(ctx, headState, genesisRoot))
require.NoError(t, db.SaveBlock(ctx, headBlock))
if err := db.SaveFinalizedCheckpoint(ctx, &ethpb.Checkpoint{
Epoch: helpers.SlotToEpoch(finalizedSlot),
Root: headRoot[:],
}); err != nil {
t.Fatal(err)
}
require.NoError(t, db.SaveFinalizedCheckpoint(ctx, &ethpb.Checkpoint{Epoch: helpers.SlotToEpoch(finalizedSlot), Root: headRoot[:]}))
c := &Service{beaconDB: db, stateGen: stategen.New(db, sc)}
require.NoError(t, c.initializeChainInfo(ctx))
headBlk, err := c.HeadBlock(ctx)
@@ -268,6 +292,37 @@ func TestChainService_InitializeChainInfo(t *testing.T) {
assert.Equal(t, genesisRoot, c.genesisRoot, "Genesis block root incorrect")
}
func TestChainService_InitializeChainInfo_SetHeadAtGenesis(t *testing.T) {
db, sc := testDB.SetupDB(t)
ctx := context.Background()
genesis := testutil.NewBeaconBlock()
genesisRoot, err := genesis.Block.HashTreeRoot()
require.NoError(t, err)
require.NoError(t, db.SaveGenesisBlockRoot(ctx, genesisRoot))
require.NoError(t, db.SaveBlock(ctx, genesis))
finalizedSlot := params.BeaconConfig().SlotsPerEpoch*2 + 1
headBlock := testutil.NewBeaconBlock()
headBlock.Block.Slot = finalizedSlot
headBlock.Block.ParentRoot = bytesutil.PadTo(genesisRoot[:], 32)
headState := testutil.NewBeaconState()
require.NoError(t, headState.SetSlot(finalizedSlot))
require.NoError(t, headState.SetGenesisValidatorRoot(params.BeaconConfig().ZeroHash[:]))
headRoot, err := headBlock.Block.HashTreeRoot()
require.NoError(t, err)
require.NoError(t, db.SaveState(ctx, headState, headRoot))
require.NoError(t, db.SaveState(ctx, headState, genesisRoot))
require.NoError(t, db.SaveBlock(ctx, headBlock))
c := &Service{beaconDB: db, stateGen: stategen.New(db, sc)}
require.NoError(t, c.initializeChainInfo(ctx))
s, err := c.HeadState(ctx)
require.NoError(t, err)
assert.DeepEqual(t, headState.InnerStateUnsafe(), s.InnerStateUnsafe(), "Head state incorrect")
assert.Equal(t, genesisRoot, c.genesisRoot, "Genesis block root incorrect")
assert.DeepEqual(t, genesis, c.head.block)
}
func TestChainService_SaveHeadNoDB(t *testing.T) {
db, sc := testDB.SetupDB(t)
ctx := context.Background()
@@ -275,8 +330,9 @@ func TestChainService_SaveHeadNoDB(t *testing.T) {
beaconDB: db,
stateGen: stategen.New(db, sc),
}
b := &ethpb.SignedBeaconBlock{Block: &ethpb.BeaconBlock{Slot: 1}}
r, err := ssz.HashTreeRoot(b)
b := testutil.NewBeaconBlock()
b.Block.Slot = 1
r, err := b.HashTreeRoot()
require.NoError(t, err)
newState := testutil.NewBeaconState()
require.NoError(t, s.stateGen.SaveState(ctx, r, newState))
@@ -294,30 +350,45 @@ func TestHasBlock_ForkChoiceAndDB(t *testing.T) {
db, _ := testDB.SetupDB(t)
s := &Service{
forkChoiceStore: protoarray.New(0, 0, [32]byte{}),
finalizedCheckpt: &ethpb.Checkpoint{},
finalizedCheckpt: &ethpb.Checkpoint{Root: make([]byte, 32)},
beaconDB: db,
}
block := &ethpb.SignedBeaconBlock{Block: &ethpb.BeaconBlock{Body: &ethpb.BeaconBlockBody{}}}
r, err := stateutil.BlockRoot(block.Block)
require.NoError(t, err)
bs := &pb.BeaconState{FinalizedCheckpoint: &ethpb.Checkpoint{}, CurrentJustifiedCheckpoint: &ethpb.Checkpoint{}}
state, err := beaconstate.InitializeFromProto(bs)
block := testutil.NewBeaconBlock()
r, err := block.Block.HashTreeRoot()
require.NoError(t, err)
state := testutil.NewBeaconState()
require.NoError(t, s.insertBlockAndAttestationsToForkChoiceStore(ctx, block.Block, r, state))
assert.Equal(t, false, s.hasBlock(ctx, [32]byte{}), "Should not have block")
assert.Equal(t, true, s.hasBlock(ctx, r), "Should have block")
}
func TestServiceStop_SaveCachedBlocks(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
db, _ := testDB.SetupDB(t)
s := &Service{
ctx: ctx,
cancel: cancel,
beaconDB: db,
initSyncBlocks: make(map[[32]byte]*ethpb.SignedBeaconBlock),
}
b := testutil.NewBeaconBlock()
r, err := b.Block.HashTreeRoot()
require.NoError(t, err)
s.saveInitSyncBlock(r, b)
require.NoError(t, s.Stop())
require.Equal(t, true, s.beaconDB.HasBlock(ctx, r))
}
func BenchmarkHasBlockDB(b *testing.B) {
db, _ := testDB.SetupDB(b)
ctx := context.Background()
s := &Service{
beaconDB: db,
}
block := &ethpb.SignedBeaconBlock{Block: &ethpb.BeaconBlock{}}
block := testutil.NewBeaconBlock()
require.NoError(b, s.beaconDB.SaveBlock(ctx, block))
r, err := stateutil.BlockRoot(block.Block)
r, err := block.Block.HashTreeRoot()
require.NoError(b, err)
b.ResetTimer()
@@ -331,13 +402,13 @@ func BenchmarkHasBlockForkChoiceStore(b *testing.B) {
db, _ := testDB.SetupDB(b)
s := &Service{
forkChoiceStore: protoarray.New(0, 0, [32]byte{}),
finalizedCheckpt: &ethpb.Checkpoint{},
finalizedCheckpt: &ethpb.Checkpoint{Root: make([]byte, 32)},
beaconDB: db,
}
block := &ethpb.SignedBeaconBlock{Block: &ethpb.BeaconBlock{Body: &ethpb.BeaconBlockBody{}}}
r, err := stateutil.BlockRoot(block.Block)
r, err := block.Block.HashTreeRoot()
require.NoError(b, err)
bs := &pb.BeaconState{FinalizedCheckpoint: &ethpb.Checkpoint{}, CurrentJustifiedCheckpoint: &ethpb.Checkpoint{}}
bs := &pb.BeaconState{FinalizedCheckpoint: &ethpb.Checkpoint{Root: make([]byte, 32)}, CurrentJustifiedCheckpoint: &ethpb.Checkpoint{Root: make([]byte, 32)}}
state, err := beaconstate.InitializeFromProto(bs)
require.NoError(b, err)
require.NoError(b, s.insertBlockAndAttestationsToForkChoiceStore(ctx, block.Block, r, state))

View File

@@ -19,8 +19,8 @@ go_library(
"//beacon-chain/db:go_default_library",
"//beacon-chain/forkchoice/protoarray:go_default_library",
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/stateutil:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//shared/bytesutil:go_default_library",
"//shared/event:go_default_library",
"//shared/params:go_default_library",
"@com_github_pkg_errors//:go_default_library",

View File

@@ -19,8 +19,8 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/db"
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/event"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/sirupsen/logrus"
@@ -152,7 +152,7 @@ func (ms *ChainService) ReceiveBlockInitialSync(ctx context.Context, block *ethp
return err
}
ms.BlocksReceived = append(ms.BlocksReceived, block)
signingRoot, err := stateutil.BlockRoot(block.Block)
signingRoot, err := block.Block.HashTreeRoot()
if err != nil {
return err
}
@@ -180,7 +180,7 @@ func (ms *ChainService) ReceiveBlockBatch(ctx context.Context, blks []*ethpb.Sig
return err
}
ms.BlocksReceived = append(ms.BlocksReceived, block)
signingRoot, err := stateutil.BlockRoot(block.Block)
signingRoot, err := block.Block.HashTreeRoot()
if err != nil {
return err
}
@@ -208,7 +208,7 @@ func (ms *ChainService) ReceiveBlock(ctx context.Context, block *ethpb.SignedBea
return err
}
ms.BlocksReceived = append(ms.BlocksReceived, block)
signingRoot, err := stateutil.BlockRoot(block.Block)
signingRoot, err := block.Block.HashTreeRoot()
if err != nil {
return err
}
@@ -233,8 +233,10 @@ func (ms *ChainService) HeadSlot() uint64 {
// HeadRoot mocks HeadRoot method in chain service.
func (ms *ChainService) HeadRoot(ctx context.Context) ([]byte, error) {
return ms.Root, nil
if len(ms.Root) > 0 {
return ms.Root, nil
}
return make([]byte, 32), nil
}
// HeadBlock mocks HeadBlock method in chain service.
@@ -353,3 +355,38 @@ func (ms *ChainService) HeadGenesisValidatorRoot() [32]byte {
func (ms *ChainService) VerifyBlkDescendant(ctx context.Context, root [32]byte) error {
return ms.VerifyBlkDescendantErr
}
// VerifyLmdFfgConsistency mocks VerifyLmdFfgConsistency and always returns nil.
func (ms *ChainService) VerifyLmdFfgConsistency(ctx context.Context, att *ethpb.Attestation) error {
return nil
}
// AttestationCheckPtInfo mocks AttestationCheckPtInfo and always returns nil.
func (ms *ChainService) AttestationCheckPtInfo(ctx context.Context, att *ethpb.Attestation) (*pb.CheckPtInfo, error) {
f := ms.State.Fork()
g := bytesutil.ToBytes32(ms.State.GenesisValidatorRoot())
seed, err := helpers.Seed(ms.State, helpers.SlotToEpoch(att.Data.Slot), params.BeaconConfig().DomainBeaconAttester)
if err != nil {
return nil, err
}
indices, err := helpers.ActiveValidatorIndices(ms.State, helpers.SlotToEpoch(att.Data.Slot))
if err != nil {
return nil, err
}
validators := ms.State.ValidatorsReadOnly()
pks := make([][]byte, len(validators))
for i := 0; i < len(pks); i++ {
pk := validators[i].PublicKey()
pks[i] = pk[:]
}
info := &pb.CheckPtInfo{
Fork: f,
GenesisRoot: g[:],
Seed: seed[:],
ActiveIndices: indices,
PubKeys: pks,
}
return info, nil
}

View File

@@ -0,0 +1,60 @@
package blockchain
import (
"context"
"fmt"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/db/filters"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
)
// VerifyWeakSubjectivityRoot verifies the weak subjectivity root in the service struct.
// Reference design: https://github.com/ethereum/eth2.0-specs/blob/master/specs/phase0/weak-subjectivity.md#weak-subjectivity-sync-procedure
func (s *Service) VerifyWeakSubjectivityRoot(ctx context.Context) error {
// TODO(7342): Remove the following to fully use weak subjectivity in production.
if len(s.wsRoot) == 0 || s.wsEpoch == 0 {
return nil
}
// Do nothing if the weak subjectivity has previously been verified,
// or weak subjectivity epoch is higher than last finalized epoch.
if s.wsVerified {
return nil
}
if s.wsEpoch > s.finalizedCheckpt.Epoch {
return nil
}
r := bytesutil.ToBytes32(s.wsRoot)
log.Infof("Performing weak subjectivity check for root %#x in epoch %d", r, s.wsEpoch)
// Save initial sync cached blocks to DB.
if err := s.beaconDB.SaveBlocks(ctx, s.getInitSyncBlocks()); err != nil {
return err
}
// A node should have the weak subjectivity block in the DB.
if !s.beaconDB.HasBlock(ctx, r) {
return fmt.Errorf("node does not have root in DB: %#x", r)
}
startSlot, err := helpers.StartSlot(s.wsEpoch)
if err != nil {
return err
}
// A node should have the weak subjectivity block corresponds to the correct epoch in the DB.
filter := filters.NewFilter().SetStartSlot(startSlot).SetEndSlot(startSlot + params.BeaconConfig().SlotsPerEpoch)
roots, err := s.beaconDB.BlockRoots(ctx, filter)
if err != nil {
return err
}
for _, root := range roots {
if r == root {
log.Info("Weak subjectivity check has passed")
s.wsVerified = true
return nil
}
}
return fmt.Errorf("node does not have root in db corresponding to epoch: %#x %d", r, s.wsEpoch)
}

View File

@@ -0,0 +1,85 @@
package blockchain
import (
"context"
"testing"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
)
func TestService_VerifyWeakSubjectivityRoot(t *testing.T) {
db, _ := testDB.SetupDB(t)
b := testutil.NewBeaconBlock()
b.Block.Slot = 32
require.NoError(t, db.SaveBlock(context.Background(), b))
r, err := b.Block.HashTreeRoot()
require.NoError(t, err)
tests := []struct {
wsVerified bool
wantErr bool
wsRoot [32]byte
wsEpoch uint64
finalizedEpoch uint64
errString string
name string
}{
{
name: "nil root and epoch",
wantErr: false,
},
{
name: "already verified",
wsEpoch: 2,
finalizedEpoch: 2,
wsVerified: true,
wantErr: false,
},
{
name: "not yet to verify, ws epoch higher than finalized epoch",
wsEpoch: 2,
finalizedEpoch: 1,
wantErr: false,
},
{
name: "can't find the block in DB",
wsEpoch: 1,
wsRoot: [32]byte{'a'},
finalizedEpoch: 3,
wantErr: true,
errString: "node does not have root in DB",
},
{
name: "can't find the block corresponds to ws epoch in DB",
wsEpoch: 2,
wsRoot: r, // Root belongs in epoch 1.
finalizedEpoch: 3,
wantErr: true,
errString: "node does not have root in db corresponding to epoch",
},
{
name: "can verify and pass",
wsEpoch: 1,
wsRoot: r,
finalizedEpoch: 3,
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := &Service{
beaconDB: db,
wsRoot: tt.wsRoot[:],
wsEpoch: tt.wsEpoch,
wsVerified: tt.wsVerified,
finalizedCheckpt: &ethpb.Checkpoint{Epoch: tt.finalizedEpoch},
}
if err := s.VerifyWeakSubjectivityRoot(context.Background()); (err != nil) != tt.wantErr {
require.ErrorContains(t, tt.errString, err)
}
})
}
}

View File

@@ -1,19 +1,31 @@
load("@prysm//tools/go:def.bzl", "go_library")
load("@io_bazel_rules_go//go:def.bzl", "go_test")
# gazelle:ignore committee_disabled.go
# gazelle:ignore proposer_indices_disabled.go
go_library(
name = "go_default_library",
srcs = [
"attestation_data.go",
"checkpoint_state.go",
"committee.go",
"committees.go",
"common.go",
"doc.go",
"hot_state_cache.go",
"skip_slot_cache.go",
"state_summary.go",
"subnet_ids.go",
],
"proposer_indices_type.go",
] + select({
"//fuzz:fuzzing_enabled": [
"committee_disabled.go",
"proposer_indices_disabled.go"
],
"//conditions:default": [
"committee.go",
"proposer_indices.go",
],
}),
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/cache",
visibility = [
"//beacon-chain:__subpackages__",
@@ -49,6 +61,7 @@ go_test(
"hot_state_cache_test.go",
"skip_slot_cache_test.go",
"subnet_ids_test.go",
"proposer_indices_test.go"
],
embed = [":go_default_library"],
deps = [
@@ -56,7 +69,6 @@ go_test(
"//proto/beacon/p2p/v1:go_default_library",
"//shared/bytesutil:go_default_library",
"//shared/featureconfig:go_default_library",
"//shared/hashutil:go_default_library",
"//shared/params:go_default_library",
"//shared/testutil/assert:go_default_library",
"//shared/testutil/require:go_default_library",

View File

@@ -26,7 +26,7 @@ func TestAttestationCache_RoundTrip(t *testing.T) {
assert.NoError(t, c.MarkInProgress(req))
res := &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 5},
Target: &ethpb.Checkpoint{Epoch: 5, Root: make([]byte, 32)},
}
assert.NoError(t, c.Put(ctx, req, res))

View File

@@ -4,12 +4,12 @@ import (
"errors"
"sync"
lru "github.com/hashicorp/golang-lru"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/shared/hashutil"
"k8s.io/client-go/tools/cache"
)
var (
@@ -20,11 +20,11 @@ var (
// maxCheckpointStateSize defines the max number of entries check point to state cache can contain.
// Choosing 10 to account for multiple forks, this allows 5 forks per epoch boundary with 2 epochs
// window to accept attestation based on latest spec.
maxCheckpointStateSize = uint64(10)
maxCheckpointStateSize = 10
// Metrics.
checkpointStateMiss = promauto.NewCounter(prometheus.CounterOpts{
Name: "check_point_statecache_miss",
Name: "check_point_state_cache_miss",
Help: "The number of check point state requests that aren't present in the cache.",
})
checkpointStateHit = promauto.NewCounter(prometheus.CounterOpts{
@@ -33,36 +33,20 @@ var (
})
)
// CheckpointState defines the active validator indices per epoch.
type CheckpointState struct {
Checkpoint *ethpb.Checkpoint
State *stateTrie.BeaconState
}
// CheckpointStateCache is a struct with 1 queue for looking up state by checkpoint.
type CheckpointStateCache struct {
cache *cache.FIFO
cache *lru.Cache
lock sync.RWMutex
}
// checkpointState takes the checkpoint as the key of the resulting state.
func checkpointState(obj interface{}) (string, error) {
info, ok := obj.(*CheckpointState)
if !ok {
return "", ErrNotCheckpointState
}
h, err := hashutil.HashProto(info.Checkpoint)
if err != nil {
return "", err
}
return string(h[:]), nil
}
// NewCheckpointStateCache creates a new checkpoint state cache for storing/accessing processed state.
func NewCheckpointStateCache() *CheckpointStateCache {
cache, err := lru.New(maxCheckpointStateSize)
if err != nil {
panic(err)
}
return &CheckpointStateCache{
cache: cache.NewFIFO(checkpointState),
cache: cache,
}
}
@@ -76,44 +60,27 @@ func (c *CheckpointStateCache) StateByCheckpoint(cp *ethpb.Checkpoint) (*stateTr
return nil, err
}
obj, exists, err := c.cache.GetByKey(string(h[:]))
if err != nil {
return nil, err
}
item, exists := c.cache.Get(h)
if exists {
if exists && item != nil {
checkpointStateHit.Inc()
} else {
checkpointStateMiss.Inc()
return nil, nil
// Copy here is unnecessary since the return will only be used to verify attestation signature.
return item.(*stateTrie.BeaconState), nil
}
info, ok := obj.(*CheckpointState)
if !ok {
return nil, ErrNotCheckpointState
}
// Copy here is unnecessary since the return will only be used to verify attestation signature.
return info.State, nil
checkpointStateMiss.Inc()
return nil, nil
}
// AddCheckpointState adds CheckpointState object to the cache. This method also trims the least
// recently added CheckpointState object if the cache size has ready the max cache size limit.
func (c *CheckpointStateCache) AddCheckpointState(cp *CheckpointState) error {
func (c *CheckpointStateCache) AddCheckpointState(cp *ethpb.Checkpoint, s *stateTrie.BeaconState) error {
c.lock.Lock()
defer c.lock.Unlock()
if err := c.cache.AddIfNotPresent(&CheckpointState{
Checkpoint: stateTrie.CopyCheckpoint(cp.Checkpoint),
State: cp.State.Copy(),
}); err != nil {
h, err := hashutil.HashProto(cp)
if err != nil {
return err
}
trim(c.cache, maxCheckpointStateSize)
c.cache.Add(h, s)
return nil
}
// CheckpointStateKeys returns the keys of the state in cache.
func (c *CheckpointStateCache) CheckpointStateKeys() []string {
return c.cache.ListKeys()
}

View File

@@ -8,36 +8,11 @@ import (
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/hashutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
)
func TestCheckpointStateCacheKeyFn_OK(t *testing.T) {
cp := &ethpb.Checkpoint{Epoch: 1, Root: bytesutil.PadTo([]byte{'A'}, 32)}
st, err := stateTrie.InitializeFromProto(&pb.BeaconState{
Slot: 64,
})
require.NoError(t, err)
info := &CheckpointState{
Checkpoint: cp,
State: st,
}
key, err := checkpointState(info)
require.NoError(t, err)
wantedKey, err := hashutil.HashProto(cp)
require.NoError(t, err)
assert.Equal(t, string(wantedKey[:]), key)
}
func TestCheckpointStateCacheKeyFn_InvalidObj(t *testing.T) {
_, err := checkpointState("bad")
assert.Equal(t, ErrNotCheckpointState, err)
}
func TestCheckpointStateCache_StateByCheckpoint(t *testing.T) {
cache := NewCheckpointStateCache()
@@ -48,20 +23,16 @@ func TestCheckpointStateCache_StateByCheckpoint(t *testing.T) {
})
require.NoError(t, err)
info1 := &CheckpointState{
Checkpoint: cp1,
State: st,
}
state, err := cache.StateByCheckpoint(cp1)
require.NoError(t, err)
assert.Equal(t, (*stateTrie.BeaconState)(nil), state, "Expected state not to exist in empty cache")
require.NoError(t, cache.AddCheckpointState(info1))
require.NoError(t, cache.AddCheckpointState(cp1, st))
state, err = cache.StateByCheckpoint(cp1)
require.NoError(t, err)
if !proto.Equal(state.InnerStateUnsafe(), info1.State.InnerStateUnsafe()) {
if !proto.Equal(state.InnerStateUnsafe(), st.InnerStateUnsafe()) {
t.Error("incorrectly cached state")
}
@@ -70,20 +41,15 @@ func TestCheckpointStateCache_StateByCheckpoint(t *testing.T) {
Slot: 128,
})
require.NoError(t, err)
info2 := &CheckpointState{
Checkpoint: cp2,
State: st2,
}
require.NoError(t, cache.AddCheckpointState(info2))
require.NoError(t, cache.AddCheckpointState(cp2, st2))
state, err = cache.StateByCheckpoint(cp2)
require.NoError(t, err)
assert.DeepEqual(t, info2.State.CloneInnerState(), state.CloneInnerState(), "incorrectly cached state")
assert.DeepEqual(t, st2.CloneInnerState(), state.CloneInnerState(), "incorrectly cached state")
state, err = cache.StateByCheckpoint(cp1)
require.NoError(t, err)
assert.DeepEqual(t, info1.State.CloneInnerState(), state.CloneInnerState(), "incorrectly cached state")
assert.DeepEqual(t, st.CloneInnerState(), state.CloneInnerState(), "incorrectly cached state")
}
func TestCheckpointStateCache_MaxSize(t *testing.T) {
@@ -93,15 +59,10 @@ func TestCheckpointStateCache_MaxSize(t *testing.T) {
})
require.NoError(t, err)
for i := uint64(0); i < maxCheckpointStateSize+100; i++ {
for i := uint64(0); i < uint64(maxCheckpointStateSize+100); i++ {
require.NoError(t, st.SetSlot(i))
info := &CheckpointState{
Checkpoint: &ethpb.Checkpoint{Epoch: i},
State: st,
}
require.NoError(t, c.AddCheckpointState(info))
require.NoError(t, c.AddCheckpointState(&ethpb.Checkpoint{Epoch: i, Root: make([]byte, 32)}, st))
}
assert.Equal(t, maxCheckpointStateSize, uint64(len(c.cache.ListKeys())))
assert.Equal(t, maxCheckpointStateSize, len(c.cache.Keys()))
}

View File

@@ -1,3 +1,5 @@
// +build !libfuzzer
package cache
import (
@@ -12,14 +14,9 @@ import (
)
var (
// ErrNotCommittee will be returned when a cache object is not a pointer to
// a Committee struct.
ErrNotCommittee = errors.New("object is not a committee struct")
// maxCommitteesCacheSize defines the max number of shuffled committees on per randao basis can cache.
// Due to reorgs, it's good to keep the old cache around for quickly switch over. 10 is a generous
// cache size as it considers 3 concurrent branches over 3 epochs.
maxCommitteesCacheSize = uint64(10)
// Due to reorgs and long finality, it's good to keep the old cache around for quickly switch over.
maxCommitteesCacheSize = uint64(32)
// CommitteeCacheMiss tracks the number of committee requests that aren't present in the cache.
CommitteeCacheMiss = promauto.NewCounter(prometheus.CounterOpts{
@@ -33,15 +30,6 @@ var (
})
)
// Committees defines the shuffled committees seed.
type Committees struct {
CommitteeCount uint64
Seed [32]byte
ShuffledIndices []uint64
SortedIndices []uint64
ProposerIndices []uint64
}
// CommitteeCache is a struct with 1 queue for looking up shuffled indices list by seed.
type CommitteeCache struct {
CommitteeCache *cache.FIFO
@@ -116,35 +104,6 @@ func (c *CommitteeCache) AddCommitteeShuffledList(committees *Committees) error
return nil
}
// AddProposerIndicesList updates the committee shuffled list with proposer indices.
func (c *CommitteeCache) AddProposerIndicesList(seed [32]byte, indices []uint64) error {
c.lock.Lock()
defer c.lock.Unlock()
obj, exists, err := c.CommitteeCache.GetByKey(key(seed))
if err != nil {
return err
}
if !exists {
committees := &Committees{ProposerIndices: indices}
if err := c.CommitteeCache.Add(committees); err != nil {
return err
}
} else {
committees, ok := obj.(*Committees)
if !ok {
return ErrNotCommittee
}
committees.ProposerIndices = indices
if err := c.CommitteeCache.Add(committees); err != nil {
return err
}
}
trim(c.CommitteeCache, maxCommitteesCacheSize)
return nil
}
// ActiveIndices returns the active indices of a given seed stored in cache.
func (c *CommitteeCache) ActiveIndices(seed [32]byte) ([]uint64, error) {
c.lock.RLock()
@@ -193,28 +152,10 @@ func (c *CommitteeCache) ActiveIndicesCount(seed [32]byte) (int, error) {
return len(item.SortedIndices), nil
}
// ProposerIndices returns the proposer indices of a given seed.
func (c *CommitteeCache) ProposerIndices(seed [32]byte) ([]uint64, error) {
c.lock.RLock()
defer c.lock.RUnlock()
obj, exists, err := c.CommitteeCache.GetByKey(key(seed))
if err != nil {
return nil, err
}
if exists {
CommitteeCacheHit.Inc()
} else {
CommitteeCacheMiss.Inc()
return nil, nil
}
item, ok := obj.(*Committees)
if !ok {
return nil, ErrNotCommittee
}
return item.ProposerIndices, nil
// HasEntry returns true if the committee cache has a value.
func (c *CommitteeCache) HasEntry(seed string) bool {
_, ok, err := c.CommitteeCache.GetByKey(seed)
return err == nil && ok
}
func startEndIndices(c *Committees, index uint64) (uint64, uint64) {

View File

@@ -0,0 +1,50 @@
// +build libfuzzer
// This file is used in fuzzer builds to bypass global committee caches.
package cache
// FakeCommitteeCache is a struct with 1 queue for looking up shuffled indices list by seed.
type FakeCommitteeCache struct {
}
// NewCommitteesCache creates a new committee cache for storing/accessing shuffled indices of a committee.
func NewCommitteesCache() *FakeCommitteeCache {
return &FakeCommitteeCache{}
}
// Committee fetches the shuffled indices by slot and committee index. Every list of indices
// represent one committee. Returns true if the list exists with slot and committee index. Otherwise returns false, nil.
func (c *FakeCommitteeCache) Committee(slot uint64, seed [32]byte, index uint64) ([]uint64, error) {
return nil, nil
}
// AddCommitteeShuffledList adds Committee shuffled list object to the cache. T
// his method also trims the least recently list if the cache size has ready the max cache size limit.
func (c *FakeCommitteeCache) AddCommitteeShuffledList(committees *Committees) error {
return nil
}
// AddProposerIndicesList updates the committee shuffled list with proposer indices.
func (c *FakeCommitteeCache) AddProposerIndicesList(seed [32]byte, indices []uint64) error {
return nil
}
// ActiveIndices returns the active indices of a given seed stored in cache.
func (c *FakeCommitteeCache) ActiveIndices(seed [32]byte) ([]uint64, error) {
return nil, nil
}
// ActiveIndicesCount returns the active indices count of a given seed stored in cache.
func (c *FakeCommitteeCache) ActiveIndicesCount(seed [32]byte) (int, error) {
return 0, nil
}
// ProposerIndices returns the proposer indices of a given seed.
func (c *FakeCommitteeCache) ProposerIndices(seed [32]byte) ([]uint64, error) {
return nil, nil
}
// HasEntry returns true if the committee cache has a value.
func (c *FakeCommitteeCache) HasEntry(string) bool {
return false
}

View File

@@ -87,42 +87,13 @@ func TestCommitteeCache_ActiveCount(t *testing.T) {
assert.Equal(t, len(item.SortedIndices), count)
}
func TestCommitteeCache_AddProposerIndicesList(t *testing.T) {
cache := NewCommitteesCache()
seed := [32]byte{'A'}
indices := []uint64{1, 2, 3, 4, 5}
indices, err := cache.ProposerIndices(seed)
require.NoError(t, err)
if indices != nil {
t.Error("Expected committee count not to exist in empty cache")
}
require.NoError(t, cache.AddProposerIndicesList(seed, indices))
received, err := cache.ProposerIndices(seed)
require.NoError(t, err)
assert.DeepEqual(t, received, indices)
item := &Committees{Seed: [32]byte{'B'}, SortedIndices: []uint64{1, 2, 3, 4, 5, 6}}
require.NoError(t, cache.AddCommitteeShuffledList(item))
indices, err = cache.ProposerIndices(item.Seed)
require.NoError(t, err)
if indices != nil {
t.Error("Expected committee count not to exist in empty cache")
}
require.NoError(t, cache.AddProposerIndicesList(item.Seed, indices))
received, err = cache.ProposerIndices(item.Seed)
require.NoError(t, err)
assert.DeepEqual(t, received, indices)
}
func TestCommitteeCache_CanRotate(t *testing.T) {
cache := NewCommitteesCache()
// Should rotate out all the epochs except 190 through 199.
for i := 100; i < 200; i++ {
start := 100
end := 200
for i := start; i < end; i++ {
s := []byte(strconv.Itoa(i))
item := &Committees{Seed: bytesutil.ToBytes32(s)}
require.NoError(t, cache.AddCommitteeShuffledList(item))
@@ -134,7 +105,8 @@ func TestCommitteeCache_CanRotate(t *testing.T) {
sort.Slice(k, func(i, j int) bool {
return k[i] < k[j]
})
s := bytesutil.ToBytes32([]byte(strconv.Itoa(190)))
wanted := end - int(maxCommitteesCacheSize)
s := bytesutil.ToBytes32([]byte(strconv.Itoa(wanted)))
assert.Equal(t, key(s), k[0], "incorrect key received for slot 190")
s = bytesutil.ToBytes32([]byte(strconv.Itoa(199)))
@@ -149,7 +121,6 @@ func TestCommitteeCacheOutOfRange(t *testing.T) {
Seed: seed,
ShuffledIndices: []uint64{0},
SortedIndices: []uint64{},
ProposerIndices: []uint64{},
})
require.NoError(t, err)

15
beacon-chain/cache/committees.go vendored Normal file
View File

@@ -0,0 +1,15 @@
package cache
import "errors"
// ErrNotCommittee will be returned when a cache object is not a pointer to
// a Committee struct.
var ErrNotCommittee = errors.New("object is not a committee struct")
// Committees defines the shuffled committees seed.
type Committees struct {
CommitteeCount uint64
Seed [32]byte
ShuffledIndices []uint64
SortedIndices []uint64
}

View File

@@ -18,7 +18,6 @@ go_library(
"@com_github_prometheus_client_golang//prometheus:go_default_library",
"@com_github_prometheus_client_golang//prometheus/promauto:go_default_library",
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@io_opencensus_go//trace:go_default_library",
],
@@ -40,7 +39,6 @@ go_test(
"//shared/trieutil:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
],
)

View File

@@ -15,7 +15,6 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/go-ssz"
dbpb "github.com/prysmaticlabs/prysm/proto/beacon/db"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
@@ -59,8 +58,8 @@ type DepositCache struct {
chainStartPubkeys map[string]bool
}
// NewDepositCache instantiates a new deposit cache
func NewDepositCache() (*DepositCache, error) {
// New instantiates a new deposit cache
func New() (*DepositCache, error) {
finalizedDepositsTrie, err := trieutil.NewTrie(int(params.BeaconConfig().DepositContractTreeDepth))
if err != nil {
return nil, err
@@ -128,7 +127,7 @@ func (dc *DepositCache) InsertFinalizedDeposits(ctx context.Context, eth1Deposit
if d.Index > eth1DepositIndex {
break
}
depHash, err := ssz.HashTreeRoot(d.Deposit.Data)
depHash, err := d.Deposit.Data.HashTreeRoot()
if err != nil {
log.WithError(err).Error("Could not hash deposit data. Finalized deposit cache not updated.")
return

View File

@@ -8,7 +8,6 @@ import (
"testing"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/go-ssz"
dbpb "github.com/prysmaticlabs/prysm/proto/beacon/db"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
@@ -20,11 +19,11 @@ import (
const nilDepositErr = "Ignoring nil deposit insertion"
var _ = DepositFetcher(&DepositCache{})
var _ DepositFetcher = (*DepositCache)(nil)
func TestInsertDeposit_LogsOnNilDepositInsertion(t *testing.T) {
hook := logTest.NewGlobal()
dc, err := NewDepositCache()
dc, err := New()
require.NoError(t, err)
dc.InsertDeposit(context.Background(), nil, 1, 0, [32]byte{})
@@ -34,7 +33,7 @@ func TestInsertDeposit_LogsOnNilDepositInsertion(t *testing.T) {
}
func TestInsertDeposit_MaintainsSortedOrderByIndex(t *testing.T) {
dc, err := NewDepositCache()
dc, err := New()
require.NoError(t, err)
insertions := []struct {
@@ -76,7 +75,7 @@ func TestInsertDeposit_MaintainsSortedOrderByIndex(t *testing.T) {
}
func TestAllDeposits_ReturnsAllDeposits(t *testing.T) {
dc, err := NewDepositCache()
dc, err := New()
require.NoError(t, err)
deposits := []*dbpb.DepositContainer{
@@ -116,7 +115,7 @@ func TestAllDeposits_ReturnsAllDeposits(t *testing.T) {
}
func TestAllDeposits_FiltersDepositUpToAndIncludingBlockNumber(t *testing.T) {
dc, err := NewDepositCache()
dc, err := New()
require.NoError(t, err)
deposits := []*dbpb.DepositContainer{
@@ -156,38 +155,80 @@ func TestAllDeposits_FiltersDepositUpToAndIncludingBlockNumber(t *testing.T) {
}
func TestDepositsNumberAndRootAtHeight_ReturnsAppropriateCountAndRoot(t *testing.T) {
dc, err := NewDepositCache()
dc, err := New()
require.NoError(t, err)
dc.deposits = []*dbpb.DepositContainer{
{
Eth1BlockHeight: 10,
Deposit: &ethpb.Deposit{},
Deposit: &ethpb.Deposit{
Data: &ethpb.Deposit_Data{
PublicKey: make([]byte, 48),
WithdrawalCredentials: make([]byte, 32),
Signature: make([]byte, 96),
},
},
},
{
Eth1BlockHeight: 10,
Deposit: &ethpb.Deposit{},
Deposit: &ethpb.Deposit{
Data: &ethpb.Deposit_Data{
PublicKey: make([]byte, 48),
WithdrawalCredentials: make([]byte, 32),
Signature: make([]byte, 96),
},
},
},
{
Eth1BlockHeight: 10,
Deposit: &ethpb.Deposit{},
Deposit: &ethpb.Deposit{
Data: &ethpb.Deposit_Data{
PublicKey: make([]byte, 48),
WithdrawalCredentials: make([]byte, 32),
Signature: make([]byte, 96),
},
},
},
{
Eth1BlockHeight: 10,
Deposit: &ethpb.Deposit{},
Deposit: &ethpb.Deposit{
Data: &ethpb.Deposit_Data{
PublicKey: make([]byte, 48),
WithdrawalCredentials: make([]byte, 32),
Signature: make([]byte, 96),
},
},
},
{
Eth1BlockHeight: 11,
Deposit: &ethpb.Deposit{},
DepositRoot: []byte("root"),
Deposit: &ethpb.Deposit{
Data: &ethpb.Deposit_Data{
PublicKey: make([]byte, 48),
WithdrawalCredentials: make([]byte, 32),
Signature: make([]byte, 96),
},
},
DepositRoot: bytesutil.PadTo([]byte("root"), 32),
},
{
Eth1BlockHeight: 12,
Deposit: &ethpb.Deposit{},
Deposit: &ethpb.Deposit{
Data: &ethpb.Deposit_Data{
PublicKey: make([]byte, 48),
WithdrawalCredentials: make([]byte, 32),
Signature: make([]byte, 96),
},
},
},
{
Eth1BlockHeight: 12,
Deposit: &ethpb.Deposit{},
Deposit: &ethpb.Deposit{
Data: &ethpb.Deposit_Data{
PublicKey: make([]byte, 48),
WithdrawalCredentials: make([]byte, 32),
Signature: make([]byte, 96),
},
},
},
}
@@ -197,19 +238,31 @@ func TestDepositsNumberAndRootAtHeight_ReturnsAppropriateCountAndRoot(t *testing
}
func TestDepositsNumberAndRootAtHeight_ReturnsEmptyTrieIfBlockHeightLessThanOldestDeposit(t *testing.T) {
dc, err := NewDepositCache()
dc, err := New()
require.NoError(t, err)
dc.deposits = []*dbpb.DepositContainer{
{
Eth1BlockHeight: 10,
Deposit: &ethpb.Deposit{},
DepositRoot: []byte("root"),
Deposit: &ethpb.Deposit{
Data: &ethpb.Deposit_Data{
PublicKey: make([]byte, 48),
WithdrawalCredentials: make([]byte, 32),
Signature: make([]byte, 96),
},
},
DepositRoot: bytesutil.PadTo([]byte("root"), 32),
},
{
Eth1BlockHeight: 11,
Deposit: &ethpb.Deposit{},
DepositRoot: []byte("root"),
Deposit: &ethpb.Deposit{
Data: &ethpb.Deposit_Data{
PublicKey: make([]byte, 48),
WithdrawalCredentials: make([]byte, 32),
Signature: make([]byte, 96),
},
},
DepositRoot: bytesutil.PadTo([]byte("root"), 32),
},
}
@@ -219,7 +272,7 @@ func TestDepositsNumberAndRootAtHeight_ReturnsEmptyTrieIfBlockHeightLessThanOlde
}
func TestDepositByPubkey_ReturnsFirstMatchingDeposit(t *testing.T) {
dc, err := NewDepositCache()
dc, err := New()
require.NoError(t, err)
dc.deposits = []*dbpb.DepositContainer{
@@ -227,7 +280,9 @@ func TestDepositByPubkey_ReturnsFirstMatchingDeposit(t *testing.T) {
Eth1BlockHeight: 9,
Deposit: &ethpb.Deposit{
Data: &ethpb.Deposit_Data{
PublicKey: []byte("pk0"),
PublicKey: bytesutil.PadTo([]byte("pk0"), 48),
WithdrawalCredentials: make([]byte, 32),
Signature: make([]byte, 96),
},
},
},
@@ -235,7 +290,9 @@ func TestDepositByPubkey_ReturnsFirstMatchingDeposit(t *testing.T) {
Eth1BlockHeight: 10,
Deposit: &ethpb.Deposit{
Data: &ethpb.Deposit_Data{
PublicKey: []byte("pk1"),
PublicKey: bytesutil.PadTo([]byte("pk1"), 48),
WithdrawalCredentials: make([]byte, 32),
Signature: make([]byte, 96),
},
},
},
@@ -243,7 +300,9 @@ func TestDepositByPubkey_ReturnsFirstMatchingDeposit(t *testing.T) {
Eth1BlockHeight: 11,
Deposit: &ethpb.Deposit{
Data: &ethpb.Deposit_Data{
PublicKey: []byte("pk1"),
PublicKey: bytesutil.PadTo([]byte("pk1"), 48),
WithdrawalCredentials: make([]byte, 32),
Signature: make([]byte, 96),
},
},
},
@@ -251,15 +310,18 @@ func TestDepositByPubkey_ReturnsFirstMatchingDeposit(t *testing.T) {
Eth1BlockHeight: 12,
Deposit: &ethpb.Deposit{
Data: &ethpb.Deposit_Data{
PublicKey: []byte("pk2"),
PublicKey: bytesutil.PadTo([]byte("pk2"), 48),
WithdrawalCredentials: make([]byte, 32),
Signature: make([]byte, 96),
},
},
},
}
dep, blkNum := dc.DepositByPubkey(context.Background(), []byte("pk1"))
pk1 := bytesutil.PadTo([]byte("pk1"), 48)
dep, blkNum := dc.DepositByPubkey(context.Background(), pk1)
if !bytes.Equal(dep.Data.PublicKey, []byte("pk1")) {
if dep == nil || !bytes.Equal(dep.Data.PublicKey, pk1) {
t.Error("Returned wrong deposit")
}
assert.Equal(t, 0, blkNum.Cmp(big.NewInt(10)),
@@ -267,14 +329,16 @@ func TestDepositByPubkey_ReturnsFirstMatchingDeposit(t *testing.T) {
}
func TestFinalizedDeposits_DepositsCachedCorrectly(t *testing.T) {
dc, err := NewDepositCache()
dc, err := New()
require.NoError(t, err)
finalizedDeposits := []*dbpb.DepositContainer{
{
Deposit: &ethpb.Deposit{
Data: &ethpb.Deposit_Data{
PublicKey: []byte{0},
PublicKey: bytesutil.PadTo([]byte{0}, 48),
WithdrawalCredentials: make([]byte, 32),
Signature: make([]byte, 96),
},
},
Index: 0,
@@ -282,7 +346,9 @@ func TestFinalizedDeposits_DepositsCachedCorrectly(t *testing.T) {
{
Deposit: &ethpb.Deposit{
Data: &ethpb.Deposit_Data{
PublicKey: []byte{1},
PublicKey: bytesutil.PadTo([]byte{1}, 48),
WithdrawalCredentials: make([]byte, 32),
Signature: make([]byte, 96),
},
},
Index: 1,
@@ -290,7 +356,9 @@ func TestFinalizedDeposits_DepositsCachedCorrectly(t *testing.T) {
{
Deposit: &ethpb.Deposit{
Data: &ethpb.Deposit_Data{
PublicKey: []byte{2},
PublicKey: bytesutil.PadTo([]byte{2}, 48),
WithdrawalCredentials: make([]byte, 32),
Signature: make([]byte, 96),
},
},
Index: 2,
@@ -299,7 +367,9 @@ func TestFinalizedDeposits_DepositsCachedCorrectly(t *testing.T) {
dc.deposits = append(finalizedDeposits, &dbpb.DepositContainer{
Deposit: &ethpb.Deposit{
Data: &ethpb.Deposit_Data{
PublicKey: []byte{3},
PublicKey: bytesutil.PadTo([]byte{3}, 48),
WithdrawalCredentials: make([]byte, 32),
Signature: make([]byte, 96),
},
},
Index: 3,
@@ -313,7 +383,7 @@ func TestFinalizedDeposits_DepositsCachedCorrectly(t *testing.T) {
var deps [][]byte
for _, d := range finalizedDeposits {
hash, err := ssz.HashTreeRoot(d.Deposit.Data)
hash, err := d.Deposit.Data.HashTreeRoot()
require.NoError(t, err, "Could not hash deposit data")
deps = append(deps, hash[:])
}
@@ -323,14 +393,16 @@ func TestFinalizedDeposits_DepositsCachedCorrectly(t *testing.T) {
}
func TestFinalizedDeposits_UtilizesPreviouslyCachedDeposits(t *testing.T) {
dc, err := NewDepositCache()
dc, err := New()
require.NoError(t, err)
oldFinalizedDeposits := []*dbpb.DepositContainer{
{
Deposit: &ethpb.Deposit{
Data: &ethpb.Deposit_Data{
PublicKey: []byte{0},
PublicKey: bytesutil.PadTo([]byte{0}, 48),
WithdrawalCredentials: make([]byte, 32),
Signature: make([]byte, 96),
},
},
Index: 0,
@@ -338,7 +410,9 @@ func TestFinalizedDeposits_UtilizesPreviouslyCachedDeposits(t *testing.T) {
{
Deposit: &ethpb.Deposit{
Data: &ethpb.Deposit_Data{
PublicKey: []byte{1},
PublicKey: bytesutil.PadTo([]byte{1}, 48),
WithdrawalCredentials: make([]byte, 32),
Signature: make([]byte, 96),
},
},
Index: 1,
@@ -347,7 +421,9 @@ func TestFinalizedDeposits_UtilizesPreviouslyCachedDeposits(t *testing.T) {
newFinalizedDeposit := dbpb.DepositContainer{
Deposit: &ethpb.Deposit{
Data: &ethpb.Deposit_Data{
PublicKey: []byte{2},
PublicKey: bytesutil.PadTo([]byte{2}, 48),
WithdrawalCredentials: make([]byte, 32),
Signature: make([]byte, 96),
},
},
Index: 2,
@@ -365,7 +441,7 @@ func TestFinalizedDeposits_UtilizesPreviouslyCachedDeposits(t *testing.T) {
var deps [][]byte
for _, d := range append(oldFinalizedDeposits, &newFinalizedDeposit) {
hash, err := ssz.HashTreeRoot(d.Deposit.Data)
hash, err := d.Deposit.Data.HashTreeRoot()
require.NoError(t, err, "Could not hash deposit data")
deps = append(deps, hash[:])
}
@@ -375,7 +451,7 @@ func TestFinalizedDeposits_UtilizesPreviouslyCachedDeposits(t *testing.T) {
}
func TestFinalizedDeposits_InitializedCorrectly(t *testing.T) {
dc, err := NewDepositCache()
dc, err := New()
require.NoError(t, err)
finalizedDeposits := dc.finalizedDeposits
@@ -385,7 +461,7 @@ func TestFinalizedDeposits_InitializedCorrectly(t *testing.T) {
}
func TestNonFinalizedDeposits_ReturnsAllNonFinalizedDeposits(t *testing.T) {
dc, err := NewDepositCache()
dc, err := New()
require.NoError(t, err)
finalizedDeposits := []*dbpb.DepositContainer{
@@ -393,7 +469,9 @@ func TestNonFinalizedDeposits_ReturnsAllNonFinalizedDeposits(t *testing.T) {
Eth1BlockHeight: 10,
Deposit: &ethpb.Deposit{
Data: &ethpb.Deposit_Data{
PublicKey: []byte{0},
PublicKey: bytesutil.PadTo([]byte{0}, 48),
WithdrawalCredentials: make([]byte, 32),
Signature: make([]byte, 96),
},
},
Index: 0,
@@ -402,7 +480,9 @@ func TestNonFinalizedDeposits_ReturnsAllNonFinalizedDeposits(t *testing.T) {
Eth1BlockHeight: 10,
Deposit: &ethpb.Deposit{
Data: &ethpb.Deposit_Data{
PublicKey: []byte{1},
PublicKey: bytesutil.PadTo([]byte{1}, 48),
WithdrawalCredentials: make([]byte, 32),
Signature: make([]byte, 96),
},
},
Index: 1,
@@ -413,7 +493,9 @@ func TestNonFinalizedDeposits_ReturnsAllNonFinalizedDeposits(t *testing.T) {
Eth1BlockHeight: 10,
Deposit: &ethpb.Deposit{
Data: &ethpb.Deposit_Data{
PublicKey: []byte{2},
PublicKey: bytesutil.PadTo([]byte{2}, 48),
WithdrawalCredentials: make([]byte, 32),
Signature: make([]byte, 96),
},
},
Index: 2,
@@ -422,7 +504,9 @@ func TestNonFinalizedDeposits_ReturnsAllNonFinalizedDeposits(t *testing.T) {
Eth1BlockHeight: 11,
Deposit: &ethpb.Deposit{
Data: &ethpb.Deposit_Data{
PublicKey: []byte{3},
PublicKey: bytesutil.PadTo([]byte{3}, 48),
WithdrawalCredentials: make([]byte, 32),
Signature: make([]byte, 96),
},
},
Index: 3,
@@ -434,7 +518,7 @@ func TestNonFinalizedDeposits_ReturnsAllNonFinalizedDeposits(t *testing.T) {
}
func TestNonFinalizedDeposits_ReturnsNonFinalizedDepositsUpToBlockNumber(t *testing.T) {
dc, err := NewDepositCache()
dc, err := New()
require.NoError(t, err)
finalizedDeposits := []*dbpb.DepositContainer{
@@ -442,7 +526,9 @@ func TestNonFinalizedDeposits_ReturnsNonFinalizedDepositsUpToBlockNumber(t *test
Eth1BlockHeight: 10,
Deposit: &ethpb.Deposit{
Data: &ethpb.Deposit_Data{
PublicKey: []byte{0},
PublicKey: bytesutil.PadTo([]byte{0}, 48),
WithdrawalCredentials: make([]byte, 32),
Signature: make([]byte, 96),
},
},
Index: 0,
@@ -451,7 +537,9 @@ func TestNonFinalizedDeposits_ReturnsNonFinalizedDepositsUpToBlockNumber(t *test
Eth1BlockHeight: 10,
Deposit: &ethpb.Deposit{
Data: &ethpb.Deposit_Data{
PublicKey: []byte{1},
PublicKey: bytesutil.PadTo([]byte{1}, 48),
WithdrawalCredentials: make([]byte, 32),
Signature: make([]byte, 96),
},
},
Index: 1,
@@ -462,7 +550,9 @@ func TestNonFinalizedDeposits_ReturnsNonFinalizedDepositsUpToBlockNumber(t *test
Eth1BlockHeight: 10,
Deposit: &ethpb.Deposit{
Data: &ethpb.Deposit_Data{
PublicKey: []byte{2},
PublicKey: bytesutil.PadTo([]byte{2}, 48),
WithdrawalCredentials: make([]byte, 32),
Signature: make([]byte, 96),
},
},
Index: 2,
@@ -471,7 +561,9 @@ func TestNonFinalizedDeposits_ReturnsNonFinalizedDepositsUpToBlockNumber(t *test
Eth1BlockHeight: 11,
Deposit: &ethpb.Deposit{
Data: &ethpb.Deposit_Data{
PublicKey: []byte{3},
PublicKey: bytesutil.PadTo([]byte{3}, 48),
WithdrawalCredentials: make([]byte, 32),
Signature: make([]byte, 96),
},
},
Index: 3,

View File

@@ -13,7 +13,7 @@ import (
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
)
var _ = PendingDepositsFetcher(&DepositCache{})
var _ PendingDepositsFetcher = (*DepositCache)(nil)
func TestInsertPendingDeposit_OK(t *testing.T) {
dc := DepositCache{}
@@ -29,14 +29,28 @@ func TestInsertPendingDeposit_ignoresNilDeposit(t *testing.T) {
assert.Equal(t, 0, len(dc.pendingDeposits))
}
func makeDepositProof() [][]byte {
proof := make([][]byte, int(params.BeaconConfig().DepositContractTreeDepth)+1)
for i := range proof {
proof[i] = make([]byte, 32)
}
return proof
}
func TestRemovePendingDeposit_OK(t *testing.T) {
db := DepositCache{}
proof1 := make([][]byte, int(params.BeaconConfig().DepositContractTreeDepth)+1)
proof1 := makeDepositProof()
proof1[0] = bytesutil.PadTo([]byte{'A'}, 32)
proof2 := make([][]byte, int(params.BeaconConfig().DepositContractTreeDepth)+1)
proof2 := makeDepositProof()
proof2[0] = bytesutil.PadTo([]byte{'A'}, 32)
depToRemove := &ethpb.Deposit{Proof: proof1}
otherDep := &ethpb.Deposit{Proof: proof2}
data := &ethpb.Deposit_Data{
PublicKey: make([]byte, 48),
WithdrawalCredentials: make([]byte, 32),
Amount: 0,
Signature: make([]byte, 96),
}
depToRemove := &ethpb.Deposit{Proof: proof1, Data: data}
otherDep := &ethpb.Deposit{Proof: proof2, Data: data}
db.pendingDeposits = []*dbpb.DepositContainer{
{Deposit: depToRemove, Index: 1},
{Deposit: otherDep, Index: 5},
@@ -57,9 +71,15 @@ func TestRemovePendingDeposit_IgnoresNilDeposit(t *testing.T) {
func TestPendingDeposit_RoundTrip(t *testing.T) {
dc := DepositCache{}
proof := make([][]byte, int(params.BeaconConfig().DepositContractTreeDepth)+1)
proof := makeDepositProof()
proof[0] = bytesutil.PadTo([]byte{'A'}, 32)
dep := &ethpb.Deposit{Proof: proof}
data := &ethpb.Deposit_Data{
PublicKey: make([]byte, 48),
WithdrawalCredentials: make([]byte, 32),
Amount: 0,
Signature: make([]byte, 96),
}
dep := &ethpb.Deposit{Proof: proof, Data: data}
dc.InsertPendingDeposit(context.Background(), dep, 111, 100, [32]byte{})
dc.RemovePendingDeposit(context.Background(), dep)
assert.Equal(t, 0, len(dc.pendingDeposits), "Failed to insert & delete a pending deposit")

View File

@@ -10,5 +10,8 @@ import (
func TestMain(m *testing.M) {
resetCfg := featureconfig.InitWithReset(&featureconfig.Flags{EnableEth1DataVoteCache: true})
defer resetCfg()
os.Exit(m.Run())
code := m.Run()
// os.Exit will prevent defer from being called
resetCfg()
os.Exit(code)
}

88
beacon-chain/cache/proposer_indices.go vendored Normal file
View File

@@ -0,0 +1,88 @@
// +build !libfuzzer
package cache
import (
"sync"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"k8s.io/client-go/tools/cache"
)
var (
// maxProposerIndicesCacheSize defines the max number of proposer indices on per block root basis can cache.
// Due to reorgs and long finality, it's good to keep the old cache around for quickly switch over.
maxProposerIndicesCacheSize = uint64(8)
// ProposerIndicesCacheMiss tracks the number of proposerIndices requests that aren't present in the cache.
ProposerIndicesCacheMiss = promauto.NewCounter(prometheus.CounterOpts{
Name: "proposer_indices_cache_miss",
Help: "The number of proposer indices requests that aren't present in the cache.",
})
// ProposerIndicesCacheHit tracks the number of proposerIndices requests that are in the cache.
ProposerIndicesCacheHit = promauto.NewCounter(prometheus.CounterOpts{
Name: "proposer_indices_cache_hit",
Help: "The number of proposer indices requests that are present in the cache.",
})
)
// ProposerIndicesCache is a struct with 1 queue for looking up proposer indices by root.
type ProposerIndicesCache struct {
ProposerIndicesCache *cache.FIFO
lock sync.RWMutex
}
// proposerIndicesKeyFn takes the block root as the key to retrieve proposer indices in a given epoch.
func proposerIndicesKeyFn(obj interface{}) (string, error) {
info, ok := obj.(*ProposerIndices)
if !ok {
return "", ErrNotProposerIndices
}
return key(info.BlockRoot), nil
}
// NewProposerIndicesCache creates a new proposer indices cache for storing/accessing proposer index assignments of an epoch.
func NewProposerIndicesCache() *ProposerIndicesCache {
return &ProposerIndicesCache{
ProposerIndicesCache: cache.NewFIFO(proposerIndicesKeyFn),
}
}
// AddProposerIndices adds ProposerIndices object to the cache.
// This method also trims the least recently list if the cache size has ready the max cache size limit.
func (c *ProposerIndicesCache) AddProposerIndices(p *ProposerIndices) error {
c.lock.Lock()
defer c.lock.Unlock()
if err := c.ProposerIndicesCache.AddIfNotPresent(p); err != nil {
return err
}
trim(c.ProposerIndicesCache, maxProposerIndicesCacheSize)
return nil
}
// ProposerIndices returns the proposer indices of a block root seed.
func (c *ProposerIndicesCache) ProposerIndices(r [32]byte) ([]uint64, error) {
c.lock.RLock()
defer c.lock.RUnlock()
obj, exists, err := c.ProposerIndicesCache.GetByKey(key(r))
if err != nil {
return nil, err
}
if exists {
ProposerIndicesCacheHit.Inc()
} else {
ProposerIndicesCacheMiss.Inc()
return nil, nil
}
item, ok := obj.(*ProposerIndices)
if !ok {
return nil, ErrNotProposerIndices
}
return item.ProposerIndices, nil
}

View File

@@ -0,0 +1,24 @@
// +build libfuzzer
// This file is used in fuzzer builds to bypass proposer indices caches.
package cache
// FakeProposerIndicesCache is a struct with 1 queue for looking up proposer indices by root.
type FakeProposerIndicesCache struct {
}
// NewProposerIndicesCache creates a new proposer indices cache for storing/accessing proposer index assignments of an epoch.
func NewProposerIndicesCache() *FakeProposerIndicesCache {
return &FakeProposerIndicesCache{}
}
// AddProposerIndices adds ProposerIndices object to the cache.
// This method also trims the least recently list if the cache size has ready the max cache size limit.
func (c *FakeProposerIndicesCache) AddProposerIndices(p *ProposerIndices) error {
return nil
}
// ProposerIndices returns the proposer indices of a block root seed.
func (c *FakeProposerIndicesCache) ProposerIndices(r [32]byte) ([]uint64, error) {
return nil, nil
}

View File

@@ -0,0 +1,63 @@
package cache
import (
"strconv"
"testing"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
)
func TestProposerKeyFn_OK(t *testing.T) {
item := &ProposerIndices{
BlockRoot: [32]byte{'A'},
ProposerIndices: []uint64{1, 2, 3, 4, 5},
}
k, err := proposerIndicesKeyFn(item)
require.NoError(t, err)
assert.Equal(t, key(item.BlockRoot), k)
}
func TestProposerKeyFn_InvalidObj(t *testing.T) {
_, err := proposerIndicesKeyFn("bad")
assert.Equal(t, ErrNotProposerIndices, err)
}
func TestProposerCache_AddProposerIndicesList(t *testing.T) {
cache := NewProposerIndicesCache()
bRoot := [32]byte{'A'}
indices, err := cache.ProposerIndices(bRoot)
require.NoError(t, err)
if indices != nil {
t.Error("Expected committee count not to exist in empty cache")
}
require.NoError(t, cache.AddProposerIndices(&ProposerIndices{
ProposerIndices: indices,
BlockRoot: bRoot,
}))
received, err := cache.ProposerIndices(bRoot)
require.NoError(t, err)
assert.DeepEqual(t, received, indices)
item := &ProposerIndices{BlockRoot: [32]byte{'B'}, ProposerIndices: []uint64{1, 2, 3, 4, 5, 6}}
require.NoError(t, cache.AddProposerIndices(item))
received, err = cache.ProposerIndices(item.BlockRoot)
require.NoError(t, err)
assert.DeepEqual(t, item.ProposerIndices, received)
}
func TestProposerCache_CanRotate(t *testing.T) {
cache := NewProposerIndicesCache()
for i := 0; i < int(maxProposerIndicesCacheSize)+1; i++ {
s := []byte(strconv.Itoa(i))
item := &ProposerIndices{BlockRoot: bytesutil.ToBytes32(s)}
require.NoError(t, cache.AddProposerIndices(item))
}
k := cache.ProposerIndicesCache.ListKeys()
assert.Equal(t, maxProposerIndicesCacheSize, uint64(len(k)))
}

View File

@@ -0,0 +1,13 @@
package cache
import "errors"
// ErrNotProposerIndices will be returned when a cache object is not a pointer to
// a ProposerIndices struct.
var ErrNotProposerIndices = errors.New("object is not a proposer indices struct")
// ProposerIndices defines the cached struct for proposer indices.
type ProposerIndices struct {
BlockRoot [32]byte
ProposerIndices []uint64
}

View File

@@ -42,12 +42,10 @@ func TestSubnetIDsCache_RoundTrip(t *testing.T) {
}
func TestSubnetIDsCache_PersistentCommitteeRoundtrip(t *testing.T) {
pubkeySet := [][48]byte{}
c := newSubnetIDs()
for i := 0; i < 20; i++ {
pubkey := [48]byte{byte(i)}
pubkeySet = append(pubkeySet, pubkey)
c.AddPersistentCommittee(pubkey[:], []uint64{uint64(i)}, 0)
}

View File

@@ -26,7 +26,6 @@ go_library(
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/core/validators:go_default_library",
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/stateutil:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//shared/attestationutil:go_default_library",
"//shared/bls:go_default_library",
@@ -63,10 +62,10 @@ go_test(
"randao_test.go",
],
embed = [":go_default_library"],
shard_count = 2,
deps = [
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/stateutil:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//shared/aggregation:go_default_library",
"//shared/aggregation/attestations:go_default_library",
@@ -82,7 +81,6 @@ go_test(
"@com_github_google_gofuzz//:go_default_library",
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
],
)

View File

@@ -12,6 +12,7 @@ import (
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/attestationutil"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
"go.opencensus.io/trace"
)
@@ -21,10 +22,14 @@ import (
func ProcessAttestations(
ctx context.Context,
beaconState *stateTrie.BeaconState,
body *ethpb.BeaconBlockBody,
b *ethpb.SignedBeaconBlock,
) (*stateTrie.BeaconState, error) {
if b.Block == nil || b.Block.Body == nil {
return nil, errors.New("block and block body can't be nil")
}
var err error
for idx, attestation := range body.Attestations {
for idx, attestation := range b.Block.Body.Attestations {
beaconState, err = ProcessAttestation(ctx, beaconState, attestation)
if err != nil {
return nil, errors.Wrapf(err, "could not verify attestation at index %d in block", idx)
@@ -67,23 +72,27 @@ func ProcessAttestation(
beaconState *stateTrie.BeaconState,
att *ethpb.Attestation,
) (*stateTrie.BeaconState, error) {
beaconState, err := ProcessAttestationNoVerify(ctx, beaconState, att)
beaconState, err := ProcessAttestationNoVerifySignature(ctx, beaconState, att)
if err != nil {
return nil, err
}
return beaconState, VerifyAttestation(ctx, beaconState, att)
return beaconState, VerifyAttestationSignature(ctx, beaconState, att)
}
// ProcessAttestationsNoVerify applies processing operations to a block's inner attestation
// ProcessAttestationsNoVerifySignature applies processing operations to a block's inner attestation
// records. The only difference would be that the attestation signature would not be verified.
func ProcessAttestationsNoVerify(
func ProcessAttestationsNoVerifySignature(
ctx context.Context,
beaconState *stateTrie.BeaconState,
body *ethpb.BeaconBlockBody,
b *ethpb.SignedBeaconBlock,
) (*stateTrie.BeaconState, error) {
if b.Block == nil || b.Block.Body == nil {
return nil, errors.New("block and block body can't be nil")
}
body := b.Block.Body
var err error
for idx, attestation := range body.Attestations {
beaconState, err = ProcessAttestationNoVerify(ctx, beaconState, attestation)
beaconState, err = ProcessAttestationNoVerifySignature(ctx, beaconState, attestation)
if err != nil {
return nil, errors.Wrapf(err, "could not verify attestation at index %d in block", idx)
}
@@ -91,14 +100,14 @@ func ProcessAttestationsNoVerify(
return beaconState, nil
}
// ProcessAttestationNoVerify processes the attestation without verifying the attestation signature. This
// ProcessAttestationNoVerifySignature processes the attestation without verifying the attestation signature. This
// method is used to validate attestations whose signatures have already been verified.
func ProcessAttestationNoVerify(
func ProcessAttestationNoVerifySignature(
ctx context.Context,
beaconState *stateTrie.BeaconState,
att *ethpb.Attestation,
) (*stateTrie.BeaconState, error) {
ctx, span := trace.StartSpan(ctx, "core.ProcessAttestationNoVerify")
ctx, span := trace.StartSpan(ctx, "core.ProcessAttestationNoVerifySignature")
defer span.End()
if att == nil || att.Data == nil || att.Data.Target == nil {
@@ -196,9 +205,87 @@ func ProcessAttestationNoVerify(
return nil, fmt.Errorf("expected target epoch %d, received %d", ffgTargetEpoch, data.Target.Epoch)
}
// Verify attesting indices are correct.
committee, err := helpers.BeaconCommitteeFromState(beaconState, att.Data.Slot, att.Data.CommitteeIndex)
if err != nil {
return nil, err
}
indexedAtt := attestationutil.ConvertToIndexed(ctx, att, committee)
if err := attestationutil.IsValidAttestationIndices(ctx, indexedAtt); err != nil {
return nil, err
}
return beaconState, nil
}
// VerifyAttestationsSignatures will verify the signatures of the provided attestations. This method performs
// a single BLS verification call to verify the signatures of all of the provided attestations. All
// of the provided attestations must have valid signatures or this method will return an error.
// This method does not determine which attestation signature is invalid, only that one or more
// attestation signatures were not valid.
func VerifyAttestationsSignatures(ctx context.Context, beaconState *stateTrie.BeaconState, b *ethpb.SignedBeaconBlock) error {
ctx, span := trace.StartSpan(ctx, "core.VerifyAttestationsSignatures")
defer span.End()
atts := b.Block.Body.Attestations
span.AddAttributes(trace.Int64Attribute("attestations", int64(len(atts))))
if len(atts) == 0 {
return nil
}
fork := beaconState.Fork()
gvr := beaconState.GenesisValidatorRoot()
dt := params.BeaconConfig().DomainBeaconAttester
// Split attestations by fork. Note: the signature domain will differ based on the fork.
var preForkAtts []*ethpb.Attestation
var postForkAtts []*ethpb.Attestation
for _, a := range atts {
if helpers.SlotToEpoch(a.Data.Slot) < fork.Epoch {
preForkAtts = append(preForkAtts, a)
} else {
postForkAtts = append(postForkAtts, a)
}
}
// Check attestations from before the fork.
if fork.Epoch > 0 { // Check to prevent underflow.
prevDomain, err := helpers.Domain(fork, fork.Epoch-1, dt, gvr)
if err != nil {
return err
}
if err := verifyAttestationsSigWithDomain(ctx, beaconState, preForkAtts, prevDomain); err != nil {
return err
}
} else if len(preForkAtts) > 0 {
// This is a sanity check that preForkAtts were not ignored when fork.Epoch == 0. This
// condition is not possible, but it doesn't hurt to check anyway.
return errors.New("some attestations were not verified from previous fork before genesis")
}
// Then check attestations from after the fork.
currDomain, err := helpers.Domain(fork, fork.Epoch, dt, gvr)
if err != nil {
return err
}
return verifyAttestationsSigWithDomain(ctx, beaconState, postForkAtts, currDomain)
}
// VerifyAttestationSignature converts and attestation into an indexed attestation and verifies
// the signature in that attestation.
func VerifyAttestationSignature(ctx context.Context, beaconState *stateTrie.BeaconState, att *ethpb.Attestation) error {
if att == nil || att.Data == nil || att.AggregationBits.Count() == 0 {
return fmt.Errorf("nil or missing attestation data: %v", att)
}
committee, err := helpers.BeaconCommitteeFromState(beaconState, att.Data.Slot, att.Data.CommitteeIndex)
if err != nil {
return err
}
indexedAtt := attestationutil.ConvertToIndexed(ctx, att, committee)
return VerifyIndexedAttestation(ctx, beaconState, indexedAtt)
}
// VerifyIndexedAttestation determines the validity of an indexed attestation.
//
// Spec pseudocode definition:
@@ -239,76 +326,9 @@ func VerifyIndexedAttestation(ctx context.Context, beaconState *stateTrie.Beacon
return attestationutil.VerifyIndexedAttestationSig(ctx, indexedAtt, pubkeys, domain)
}
// VerifyAttestation converts and attestation into an indexed attestation and verifies
// the signature in that attestation.
func VerifyAttestation(ctx context.Context, beaconState *stateTrie.BeaconState, att *ethpb.Attestation) error {
if att == nil || att.Data == nil {
return fmt.Errorf("nil or missing attestation data: %v", att)
}
committee, err := helpers.BeaconCommitteeFromState(beaconState, att.Data.Slot, att.Data.CommitteeIndex)
if err != nil {
return err
}
indexedAtt := attestationutil.ConvertToIndexed(ctx, att, committee)
return VerifyIndexedAttestation(ctx, beaconState, indexedAtt)
}
// VerifyAttestations will verify the signatures of the provided attestations. This method performs
// a single BLS verification call to verify the signatures of all of the provided attestations. All
// of the provided attestations must have valid signatures or this method will return an error.
// This method does not determine which attestation signature is invalid, only that one or more
// attestation signatures were not valid.
func VerifyAttestations(ctx context.Context, beaconState *stateTrie.BeaconState, atts []*ethpb.Attestation) error {
ctx, span := trace.StartSpan(ctx, "core.VerifyAttestations")
defer span.End()
span.AddAttributes(trace.Int64Attribute("attestations", int64(len(atts))))
if len(atts) == 0 {
return nil
}
fork := beaconState.Fork()
gvr := beaconState.GenesisValidatorRoot()
dt := params.BeaconConfig().DomainBeaconAttester
// Split attestations by fork. Note: the signature domain will differ based on the fork.
var preForkAtts []*ethpb.Attestation
var postForkAtts []*ethpb.Attestation
for _, a := range atts {
if helpers.SlotToEpoch(a.Data.Slot) < fork.Epoch {
preForkAtts = append(preForkAtts, a)
} else {
postForkAtts = append(postForkAtts, a)
}
}
// Check attestations from before the fork.
if fork.Epoch > 0 { // Check to prevent underflow.
prevDomain, err := helpers.Domain(fork, fork.Epoch-1, dt, gvr)
if err != nil {
return err
}
if err := verifyAttestationsWithDomain(ctx, beaconState, preForkAtts, prevDomain); err != nil {
return err
}
} else if len(preForkAtts) > 0 {
// This is a sanity check that preForkAtts were not ignored when fork.Epoch == 0. This
// condition is not possible, but it doesn't hurt to check anyway.
return errors.New("some attestations were not verified from previous fork before genesis")
}
// Then check attestations from after the fork.
currDomain, err := helpers.Domain(fork, fork.Epoch, dt, gvr)
if err != nil {
return err
}
return verifyAttestationsWithDomain(ctx, beaconState, postForkAtts, currDomain)
}
// Inner method to verify attestations. This abstraction allows for the domain to be provided as an
// argument.
func verifyAttestationsWithDomain(ctx context.Context, beaconState *stateTrie.BeaconState, atts []*ethpb.Attestation, domain []byte) error {
func verifyAttestationsSigWithDomain(ctx context.Context, beaconState *stateTrie.BeaconState, atts []*ethpb.Attestation, domain []byte) error {
if len(atts) == 0 {
return nil
}
@@ -316,7 +336,7 @@ func verifyAttestationsWithDomain(ctx context.Context, beaconState *stateTrie.Be
if err != nil {
return err
}
verify, err := bls.VerifyMultipleSignatures(set.Signatures, set.Messages, set.PublicKeys)
verify, err := set.Verify()
if err != nil {
return errors.Errorf("got error in multiple verification: %v", err)
}
@@ -325,3 +345,35 @@ func verifyAttestationsWithDomain(ctx context.Context, beaconState *stateTrie.Be
}
return nil
}
// VerifyAttSigUseCheckPt uses the checkpoint info object to verify attestation signature.
func VerifyAttSigUseCheckPt(ctx context.Context, c *pb.CheckPtInfo, att *ethpb.Attestation) error {
if att == nil || att.Data == nil || att.AggregationBits.Count() == 0 {
return fmt.Errorf("nil or missing attestation data: %v", att)
}
seed := bytesutil.ToBytes32(c.Seed)
committee, err := helpers.BeaconCommittee(c.ActiveIndices, seed, att.Data.Slot, att.Data.CommitteeIndex)
if err != nil {
return err
}
indexedAtt := attestationutil.ConvertToIndexed(ctx, att, committee)
if err := attestationutil.IsValidAttestationIndices(ctx, indexedAtt); err != nil {
return err
}
domain, err := helpers.Domain(c.Fork, indexedAtt.Data.Target.Epoch, params.BeaconConfig().DomainBeaconAttester, c.GenesisRoot)
if err != nil {
return err
}
indices := indexedAtt.AttestingIndices
pubkeys := []bls.PublicKey{}
for i := 0; i < len(indices); i++ {
pubkeyAtIdx := c.PubKeys[indices[i]]
pk, err := bls.PublicKeyFromBytes(pubkeyAtIdx)
if err != nil {
return errors.Wrap(err, "could not deserialize validator public key")
}
pubkeys = append(pubkeys, pk)
}
return attestationutil.VerifyIndexedAttestationSig(ctx, indexedAtt, pubkeys, domain)
}

View File

@@ -15,6 +15,7 @@ import (
attaggregation "github.com/prysmaticlabs/prysm/shared/aggregation/attestations"
"github.com/prysmaticlabs/prysm/shared/attestationutil"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
@@ -25,12 +26,13 @@ func TestProcessAttestations_InclusionDelayFailure(t *testing.T) {
attestations := []*ethpb.Attestation{
{
Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 0},
Target: &ethpb.Checkpoint{Epoch: 0, Root: make([]byte, 32)},
Slot: 5,
},
},
}
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
Attestations: attestations,
},
@@ -43,7 +45,7 @@ func TestProcessAttestations_InclusionDelayFailure(t *testing.T) {
params.BeaconConfig().MinAttestationInclusionDelay,
beaconState.Slot(),
)
_, err := blocks.ProcessAttestations(context.Background(), beaconState, block.Body)
_, err := blocks.ProcessAttestations(context.Background(), beaconState, b)
assert.ErrorContains(t, want, err)
}
@@ -53,7 +55,8 @@ func TestProcessAttestations_NeitherCurrentNorPrevEpoch(t *testing.T) {
Source: &ethpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
Target: &ethpb.Checkpoint{Epoch: 0}}}
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
Attestations: []*ethpb.Attestation{att},
},
@@ -72,7 +75,7 @@ func TestProcessAttestations_NeitherCurrentNorPrevEpoch(t *testing.T) {
helpers.PrevEpoch(beaconState),
helpers.CurrentEpoch(beaconState),
)
_, err = blocks.ProcessAttestations(context.Background(), beaconState, block.Body)
_, err = blocks.ProcessAttestations(context.Background(), beaconState, b)
assert.ErrorContains(t, want, err)
}
@@ -81,13 +84,14 @@ func TestProcessAttestations_CurrentEpochFFGDataMismatches(t *testing.T) {
attestations := []*ethpb.Attestation{
{
Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 0},
Source: &ethpb.Checkpoint{Epoch: 1},
Target: &ethpb.Checkpoint{Epoch: 0, Root: make([]byte, 32)},
Source: &ethpb.Checkpoint{Epoch: 1, Root: make([]byte, 32)},
},
AggregationBits: aggBits,
},
}
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
Attestations: attestations,
},
@@ -104,18 +108,18 @@ func TestProcessAttestations_CurrentEpochFFGDataMismatches(t *testing.T) {
helpers.CurrentEpoch(beaconState),
attestations[0].Data.Source.Epoch,
)
_, err := blocks.ProcessAttestations(context.Background(), beaconState, block.Body)
_, err := blocks.ProcessAttestations(context.Background(), beaconState, b)
assert.ErrorContains(t, want, err)
block.Body.Attestations[0].Data.Source.Epoch = helpers.CurrentEpoch(beaconState)
block.Body.Attestations[0].Data.Source.Root = []byte{}
b.Block.Body.Attestations[0].Data.Source.Epoch = helpers.CurrentEpoch(beaconState)
b.Block.Body.Attestations[0].Data.Source.Root = []byte{}
want = fmt.Sprintf(
"expected source root %#x, received %#x",
beaconState.CurrentJustifiedCheckpoint().Root,
attestations[0].Data.Source.Root,
)
_, err = blocks.ProcessAttestations(context.Background(), beaconState, block.Body)
_, err = blocks.ProcessAttestations(context.Background(), beaconState, b)
assert.ErrorContains(t, want, err)
}
@@ -127,14 +131,15 @@ func TestProcessAttestations_PrevEpochFFGDataMismatches(t *testing.T) {
attestations := []*ethpb.Attestation{
{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 1},
Target: &ethpb.Checkpoint{Epoch: 1},
Source: &ethpb.Checkpoint{Epoch: 1, Root: make([]byte, 32)},
Target: &ethpb.Checkpoint{Epoch: 1, Root: make([]byte, 32)},
Slot: params.BeaconConfig().SlotsPerEpoch,
},
AggregationBits: aggBits,
},
}
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
Attestations: attestations,
},
@@ -152,19 +157,19 @@ func TestProcessAttestations_PrevEpochFFGDataMismatches(t *testing.T) {
helpers.PrevEpoch(beaconState),
attestations[0].Data.Source.Epoch,
)
_, err = blocks.ProcessAttestations(context.Background(), beaconState, block.Body)
_, err = blocks.ProcessAttestations(context.Background(), beaconState, b)
assert.ErrorContains(t, want, err)
block.Body.Attestations[0].Data.Source.Epoch = helpers.PrevEpoch(beaconState)
block.Body.Attestations[0].Data.Target.Epoch = helpers.CurrentEpoch(beaconState)
block.Body.Attestations[0].Data.Source.Root = []byte{}
b.Block.Body.Attestations[0].Data.Source.Epoch = helpers.PrevEpoch(beaconState)
b.Block.Body.Attestations[0].Data.Target.Epoch = helpers.CurrentEpoch(beaconState)
b.Block.Body.Attestations[0].Data.Source.Root = []byte{}
want = fmt.Sprintf(
"expected source root %#x, received %#x",
beaconState.CurrentJustifiedCheckpoint().Root,
attestations[0].Data.Source.Root,
)
_, err = blocks.ProcessAttestations(context.Background(), beaconState, block.Body)
_, err = blocks.ProcessAttestations(context.Background(), beaconState, b)
assert.ErrorContains(t, want, err)
}
@@ -179,7 +184,8 @@ func TestProcessAttestations_InvalidAggregationBitsLength(t *testing.T) {
AggregationBits: aggBits,
}
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
Attestations: []*ethpb.Attestation{att},
},
@@ -194,7 +200,7 @@ func TestProcessAttestations_InvalidAggregationBitsLength(t *testing.T) {
require.NoError(t, beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{}))
expected := "failed to verify aggregation bitfield: wanted participants bitfield length 3, got: 4"
_, err = blocks.ProcessAttestations(context.Background(), beaconState, block.Body)
_, err = blocks.ProcessAttestations(context.Background(), beaconState, b)
assert.ErrorContains(t, expected, err)
}
@@ -207,10 +213,12 @@ func TestProcessAttestations_OK(t *testing.T) {
copy(mockRoot[:], "hello-world")
att := &ethpb.Attestation{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0, Root: mockRoot[:]},
Target: &ethpb.Checkpoint{Epoch: 0, Root: mockRoot[:]},
Source: &ethpb.Checkpoint{Epoch: 0, Root: mockRoot[:]},
Target: &ethpb.Checkpoint{Epoch: 0, Root: mockRoot[:]},
BeaconBlockRoot: make([]byte, 32),
},
AggregationBits: aggBits,
Signature: make([]byte, 96),
}
cfc := beaconState.CurrentJustifiedCheckpoint()
@@ -230,25 +238,23 @@ func TestProcessAttestations_OK(t *testing.T) {
require.NoError(t, err)
sigs[i] = sig
}
att.Signature = bls.AggregateSignatures(sigs).Marshal()[:]
att.Signature = bls.AggregateSignatures(sigs).Marshal()
block := &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
Attestations: []*ethpb.Attestation{att},
},
}
block := testutil.NewBeaconBlock()
block.Block.Body.Attestations = []*ethpb.Attestation{att}
err = beaconState.SetSlot(beaconState.Slot() + params.BeaconConfig().MinAttestationInclusionDelay)
require.NoError(t, err)
_, err = blocks.ProcessAttestations(context.Background(), beaconState, block.Body)
_, err = blocks.ProcessAttestations(context.Background(), beaconState, block)
assert.NoError(t, err)
}
func TestProcessAggregatedAttestation_OverlappingBits(t *testing.T) {
beaconState, privKeys := testutil.DeterministicGenesisState(t, 100)
data := &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
Target: &ethpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
Source: &ethpb.Checkpoint{Epoch: 0, Root: bytesutil.PadTo([]byte("hello-world"), 32)},
Target: &ethpb.Checkpoint{Epoch: 0, Root: bytesutil.PadTo([]byte("hello-world"), 32)},
BeaconBlockRoot: make([]byte, 32),
}
aggBits1 := bitfield.NewBitlist(4)
aggBits1.SetBitAt(0, true)
@@ -260,7 +266,7 @@ func TestProcessAggregatedAttestation_OverlappingBits(t *testing.T) {
}
cfc := beaconState.CurrentJustifiedCheckpoint()
cfc.Root = []byte("hello-world")
cfc.Root = bytesutil.PadTo([]byte("hello-world"), 32)
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(cfc))
require.NoError(t, beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{}))
@@ -276,7 +282,7 @@ func TestProcessAggregatedAttestation_OverlappingBits(t *testing.T) {
require.NoError(t, err)
sigs[i] = sig
}
att1.Signature = bls.AggregateSignatures(sigs).Marshal()[:]
att1.Signature = bls.AggregateSignatures(sigs).Marshal()
aggBits2 := bitfield.NewBitlist(4)
aggBits2.SetBitAt(1, true)
@@ -299,7 +305,7 @@ func TestProcessAggregatedAttestation_OverlappingBits(t *testing.T) {
require.NoError(t, err)
sigs[i] = sig
}
att2.Signature = bls.AggregateSignatures(sigs).Marshal()[:]
att2.Signature = bls.AggregateSignatures(sigs).Marshal()
_, err = attaggregation.AggregatePair(att1, att2)
assert.ErrorContains(t, aggregation.ErrBitsOverlap.Error(), err)
@@ -311,8 +317,9 @@ func TestProcessAggregatedAttestation_NoOverlappingBits(t *testing.T) {
var mockRoot [32]byte
copy(mockRoot[:], "hello-world")
data := &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0, Root: mockRoot[:]},
Target: &ethpb.Checkpoint{Epoch: 0, Root: mockRoot[:]},
Source: &ethpb.Checkpoint{Epoch: 0, Root: mockRoot[:]},
Target: &ethpb.Checkpoint{Epoch: 0, Root: mockRoot[:]},
BeaconBlockRoot: make([]byte, 32),
}
aggBits1 := bitfield.NewBitlist(9)
aggBits1.SetBitAt(0, true)
@@ -320,6 +327,7 @@ func TestProcessAggregatedAttestation_NoOverlappingBits(t *testing.T) {
att1 := &ethpb.Attestation{
Data: data,
AggregationBits: aggBits1,
Signature: make([]byte, 32),
}
cfc := beaconState.CurrentJustifiedCheckpoint()
@@ -339,7 +347,7 @@ func TestProcessAggregatedAttestation_NoOverlappingBits(t *testing.T) {
require.NoError(t, err)
sigs[i] = sig
}
att1.Signature = bls.AggregateSignatures(sigs).Marshal()[:]
att1.Signature = bls.AggregateSignatures(sigs).Marshal()
aggBits2 := bitfield.NewBitlist(9)
aggBits2.SetBitAt(2, true)
@@ -347,6 +355,7 @@ func TestProcessAggregatedAttestation_NoOverlappingBits(t *testing.T) {
att2 := &ethpb.Attestation{
Data: data,
AggregationBits: aggBits2,
Signature: make([]byte, 32),
}
committee, err = helpers.BeaconCommitteeFromState(beaconState, att2.Data.Slot, att2.Data.CommitteeIndex)
@@ -361,20 +370,17 @@ func TestProcessAggregatedAttestation_NoOverlappingBits(t *testing.T) {
require.NoError(t, err)
sigs[i] = sig
}
att2.Signature = bls.AggregateSignatures(sigs).Marshal()[:]
att2.Signature = bls.AggregateSignatures(sigs).Marshal()
aggregatedAtt, err := attaggregation.AggregatePair(att1, att2)
require.NoError(t, err)
block := &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
Attestations: []*ethpb.Attestation{aggregatedAtt},
},
}
block := testutil.NewBeaconBlock()
block.Block.Body.Attestations = []*ethpb.Attestation{aggregatedAtt}
err = beaconState.SetSlot(beaconState.Slot() + params.BeaconConfig().MinAttestationInclusionDelay)
require.NoError(t, err)
_, err = blocks.ProcessAttestations(context.Background(), beaconState, block.Body)
_, err = blocks.ProcessAttestations(context.Background(), beaconState, block)
assert.NoError(t, err)
}
@@ -384,11 +390,11 @@ func TestProcessAttestationsNoVerify_IncorrectSlotTargetEpoch(t *testing.T) {
att := &ethpb.Attestation{
Data: &ethpb.AttestationData{
Slot: params.BeaconConfig().SlotsPerEpoch,
Target: &ethpb.Checkpoint{},
Target: &ethpb.Checkpoint{Root: make([]byte, 32)},
},
}
wanted := fmt.Sprintf("data slot is not in the same epoch as target %d != %d", helpers.SlotToEpoch(att.Data.Slot), att.Data.Target.Epoch)
_, err := blocks.ProcessAttestationNoVerify(context.TODO(), beaconState, att)
_, err := blocks.ProcessAttestationNoVerifySignature(context.TODO(), beaconState, att)
assert.ErrorContains(t, wanted, err)
}
@@ -404,7 +410,7 @@ func TestProcessAttestationsNoVerify_OK(t *testing.T) {
att := &ethpb.Attestation{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0, Root: mockRoot[:]},
Target: &ethpb.Checkpoint{Epoch: 0},
Target: &ethpb.Checkpoint{Epoch: 0, Root: make([]byte, 32)},
},
AggregationBits: aggBits,
}
@@ -419,7 +425,7 @@ func TestProcessAttestationsNoVerify_OK(t *testing.T) {
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(ckp))
require.NoError(t, beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{}))
_, err = blocks.ProcessAttestationNoVerify(context.TODO(), beaconState, att)
_, err = blocks.ProcessAttestationNoVerifySignature(context.TODO(), beaconState, att)
assert.NoError(t, err)
}
@@ -433,7 +439,7 @@ func TestProcessAttestationsNoVerify_BadAttIdx(t *testing.T) {
Data: &ethpb.AttestationData{
CommitteeIndex: 100,
Source: &ethpb.Checkpoint{Epoch: 0, Root: mockRoot[:]},
Target: &ethpb.Checkpoint{Epoch: 0},
Target: &ethpb.Checkpoint{Epoch: 0, Root: make([]byte, 32)},
},
AggregationBits: aggBits,
}
@@ -444,7 +450,7 @@ func TestProcessAttestationsNoVerify_BadAttIdx(t *testing.T) {
copy(ckp.Root, "hello-world")
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(ckp))
require.NoError(t, beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{}))
_, err := blocks.ProcessAttestationNoVerify(context.TODO(), beaconState, att)
_, err := blocks.ProcessAttestationNoVerifySignature(context.TODO(), beaconState, att)
require.ErrorContains(t, "committee index 100 >= committee count 1", err)
}
@@ -486,8 +492,8 @@ func TestConvertToIndexed_OK(t *testing.T) {
attestation := &ethpb.Attestation{
Signature: sig[:],
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0},
Target: &ethpb.Checkpoint{Epoch: 0},
Source: &ethpb.Checkpoint{Epoch: 0, Root: make([]byte, 32)},
Target: &ethpb.Checkpoint{Epoch: 0, Root: make([]byte, 32)},
},
}
for _, tt := range tests {
@@ -512,8 +518,9 @@ func TestVerifyIndexedAttestation_OK(t *testing.T) {
require.NoError(t, err)
for i := 0; i < len(validators); i++ {
validators[i] = &ethpb.Validator{
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
PublicKey: keys[i].PublicKey().Marshal(),
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
PublicKey: keys[i].PublicKey().Marshal(),
WithdrawalCredentials: make([]byte, 32),
}
}
@@ -535,33 +542,57 @@ func TestVerifyIndexedAttestation_OK(t *testing.T) {
Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{
Epoch: 2,
Root: make([]byte, 32),
},
Source: &ethpb.Checkpoint{
Root: make([]byte, 32),
},
BeaconBlockRoot: make([]byte, 32),
},
AttestingIndices: []uint64{1},
Signature: make([]byte, 96),
}},
{attestation: &ethpb.IndexedAttestation{
Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{
Epoch: 1,
Root: make([]byte, 32),
},
Source: &ethpb.Checkpoint{
Root: make([]byte, 32),
},
BeaconBlockRoot: make([]byte, 32),
},
AttestingIndices: []uint64{47, 99, 101},
Signature: make([]byte, 96),
}},
{attestation: &ethpb.IndexedAttestation{
Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{
Epoch: 4,
Root: make([]byte, 32),
},
Source: &ethpb.Checkpoint{
Root: make([]byte, 32),
},
BeaconBlockRoot: make([]byte, 32),
},
AttestingIndices: []uint64{21, 72},
Signature: make([]byte, 96),
}},
{attestation: &ethpb.IndexedAttestation{
Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{
Epoch: 7,
Root: make([]byte, 32),
},
Source: &ethpb.Checkpoint{
Root: make([]byte, 32),
},
BeaconBlockRoot: make([]byte, 32),
},
AttestingIndices: []uint64{100, 121, 122},
Signature: make([]byte, 96),
}},
}
@@ -603,6 +634,48 @@ func TestValidateIndexedAttestation_AboveMaxLength(t *testing.T) {
assert.ErrorContains(t, want, err)
}
func TestValidateIndexedAttestation_BadAttestationsSignatureSet(t *testing.T) {
beaconState, keys := testutil.DeterministicGenesisState(t, 1000)
sig := keys[0].Sign([]byte{'t', 'e', 's', 't'})
list := bitfield.Bitlist{0b11111111}
atts := []*ethpb.Attestation{}
for i := uint64(0); i < 1000; i++ {
atts = append(atts, &ethpb.Attestation{
Data: &ethpb.AttestationData{
CommitteeIndex: 1,
Slot: 1,
},
Signature: sig.Marshal(),
AggregationBits: list,
})
}
want := "nil or missing indexed attestation data"
_, err := blocks.AttestationSignatureSet(context.Background(), beaconState, atts)
assert.ErrorContains(t, want, err)
atts = []*ethpb.Attestation{}
list = bitfield.Bitlist{0b00000000}
for i := uint64(0); i < 1000; i++ {
atts = append(atts, &ethpb.Attestation{
Data: &ethpb.AttestationData{
CommitteeIndex: 1,
Slot: 1,
Target: &ethpb.Checkpoint{
Root: []byte{},
},
},
Signature: sig.Marshal(),
AggregationBits: list,
})
}
want = "expected non-empty attesting indices"
_, err = blocks.AttestationSignatureSet(context.Background(), beaconState, atts)
assert.ErrorContains(t, want, err)
}
func TestVerifyAttestations_VerifiesMultipleAttestations(t *testing.T) {
ctx := context.Background()
numOfValidators := 4 * params.BeaconConfig().SlotsPerEpoch
@@ -611,31 +684,28 @@ func TestVerifyAttestations_VerifiesMultipleAttestations(t *testing.T) {
require.NoError(t, err)
for i := 0; i < len(validators); i++ {
validators[i] = &ethpb.Validator{
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
PublicKey: keys[i].PublicKey().Marshal(),
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
PublicKey: keys[i].PublicKey().Marshal(),
WithdrawalCredentials: make([]byte, 32),
}
}
st, err := stateTrie.InitializeFromProto(&pb.BeaconState{
Slot: 5,
Validators: validators,
Fork: &pb.Fork{
Epoch: 0,
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
},
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
})
st := testutil.NewBeaconState()
require.NoError(t, st.SetSlot(5))
require.NoError(t, st.SetValidators(validators))
comm1, err := helpers.BeaconCommitteeFromState(st, 1 /*slot*/, 0 /*committeeIndex*/)
require.NoError(t, err)
att1 := &ethpb.Attestation{
AggregationBits: bitfield.NewBitlist(uint64(len(comm1))),
Data: &ethpb.AttestationData{
Slot: 1,
CommitteeIndex: 0,
Slot: 1,
CommitteeIndex: 0,
BeaconBlockRoot: make([]byte, 32),
Target: &ethpb.Checkpoint{Root: make([]byte, 32)},
Source: &ethpb.Checkpoint{Root: make([]byte, 32)},
},
Signature: nil,
Signature: make([]byte, 96),
}
domain, err := helpers.Domain(st.Fork(), st.Fork().Epoch, params.BeaconConfig().DomainBeaconAttester, st.GenesisValidatorRoot())
require.NoError(t, err)
@@ -653,10 +723,13 @@ func TestVerifyAttestations_VerifiesMultipleAttestations(t *testing.T) {
att2 := &ethpb.Attestation{
AggregationBits: bitfield.NewBitlist(uint64(len(comm2))),
Data: &ethpb.AttestationData{
Slot: 1,
CommitteeIndex: 1,
Slot: 1,
CommitteeIndex: 1,
BeaconBlockRoot: make([]byte, 32),
Target: &ethpb.Checkpoint{Root: make([]byte, 32)},
Source: &ethpb.Checkpoint{Root: make([]byte, 32)},
},
Signature: nil,
Signature: make([]byte, 96),
}
root, err = helpers.ComputeSigningRoot(att2.Data, domain)
require.NoError(t, err)
@@ -667,7 +740,9 @@ func TestVerifyAttestations_VerifiesMultipleAttestations(t *testing.T) {
}
att2.Signature = bls.AggregateSignatures(sigs).Marshal()
require.NoError(t, blocks.VerifyAttestations(ctx, st, []*ethpb.Attestation{att1, att2}))
b := testutil.NewBeaconBlock()
b.Block.Body.Attestations = []*ethpb.Attestation{att1, att2}
require.NoError(t, blocks.VerifyAttestationsSignatures(ctx, st, b))
}
func TestVerifyAttestations_HandlesPlannedFork(t *testing.T) {
@@ -679,31 +754,33 @@ func TestVerifyAttestations_HandlesPlannedFork(t *testing.T) {
require.NoError(t, err)
for i := 0; i < len(validators); i++ {
validators[i] = &ethpb.Validator{
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
PublicKey: keys[i].PublicKey().Marshal(),
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
PublicKey: keys[i].PublicKey().Marshal(),
WithdrawalCredentials: make([]byte, 32),
}
}
st, err := stateTrie.InitializeFromProto(&pb.BeaconState{
Slot: 35,
Validators: validators,
Fork: &pb.Fork{
Epoch: 1,
CurrentVersion: []byte{0, 1, 2, 3},
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
},
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
})
st := testutil.NewBeaconState()
require.NoError(t, st.SetSlot(35))
require.NoError(t, st.SetValidators(validators))
require.NoError(t, st.SetFork(&pb.Fork{
Epoch: 1,
CurrentVersion: []byte{0, 1, 2, 3},
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
}))
comm1, err := helpers.BeaconCommitteeFromState(st, 1 /*slot*/, 0 /*committeeIndex*/)
require.NoError(t, err)
att1 := &ethpb.Attestation{
AggregationBits: bitfield.NewBitlist(uint64(len(comm1))),
Data: &ethpb.AttestationData{
Slot: 1,
CommitteeIndex: 0,
Slot: 1,
CommitteeIndex: 0,
BeaconBlockRoot: make([]byte, 32),
Source: &ethpb.Checkpoint{Root: make([]byte, 32)},
Target: &ethpb.Checkpoint{Root: make([]byte, 32)},
},
Signature: nil,
Signature: make([]byte, 96),
}
prevDomain, err := helpers.Domain(st.Fork(), st.Fork().Epoch-1, params.BeaconConfig().DomainBeaconAttester, st.GenesisValidatorRoot())
require.NoError(t, err)
@@ -721,12 +798,16 @@ func TestVerifyAttestations_HandlesPlannedFork(t *testing.T) {
att2 := &ethpb.Attestation{
AggregationBits: bitfield.NewBitlist(uint64(len(comm2))),
Data: &ethpb.AttestationData{
Slot: 1*params.BeaconConfig().SlotsPerEpoch + 1,
CommitteeIndex: 1,
Slot: 1*params.BeaconConfig().SlotsPerEpoch + 1,
CommitteeIndex: 1,
BeaconBlockRoot: make([]byte, 32),
Source: &ethpb.Checkpoint{Root: make([]byte, 32)},
Target: &ethpb.Checkpoint{Root: make([]byte, 32)},
},
Signature: nil,
Signature: make([]byte, 96),
}
currDomain, err := helpers.Domain(st.Fork(), st.Fork().Epoch, params.BeaconConfig().DomainBeaconAttester, st.GenesisValidatorRoot())
require.NoError(t, err)
root, err = helpers.ComputeSigningRoot(att2.Data, currDomain)
require.NoError(t, err)
sigs = nil
@@ -736,7 +817,9 @@ func TestVerifyAttestations_HandlesPlannedFork(t *testing.T) {
}
att2.Signature = bls.AggregateSignatures(sigs).Marshal()
require.NoError(t, blocks.VerifyAttestations(ctx, st, []*ethpb.Attestation{att1, att2}))
b := testutil.NewBeaconBlock()
b.Block.Body.Attestations = []*ethpb.Attestation{att1, att2}
require.NoError(t, blocks.VerifyAttestationsSignatures(ctx, st, b))
}
func TestRetrieveAttestationSignatureSet_VerifiesMultipleAttestations(t *testing.T) {
@@ -747,31 +830,28 @@ func TestRetrieveAttestationSignatureSet_VerifiesMultipleAttestations(t *testing
require.NoError(t, err)
for i := 0; i < len(validators); i++ {
validators[i] = &ethpb.Validator{
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
PublicKey: keys[i].PublicKey().Marshal(),
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
PublicKey: keys[i].PublicKey().Marshal(),
WithdrawalCredentials: make([]byte, 32),
}
}
st, err := stateTrie.InitializeFromProto(&pb.BeaconState{
Slot: 5,
Validators: validators,
Fork: &pb.Fork{
Epoch: 0,
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
},
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
})
st := testutil.NewBeaconState()
require.NoError(t, st.SetSlot(5))
require.NoError(t, st.SetValidators(validators))
comm1, err := helpers.BeaconCommitteeFromState(st, 1 /*slot*/, 0 /*committeeIndex*/)
require.NoError(t, err)
att1 := &ethpb.Attestation{
AggregationBits: bitfield.NewBitlist(uint64(len(comm1))),
Data: &ethpb.AttestationData{
Slot: 1,
CommitteeIndex: 0,
Slot: 1,
CommitteeIndex: 0,
BeaconBlockRoot: make([]byte, 32),
Target: &ethpb.Checkpoint{Root: make([]byte, 32)},
Source: &ethpb.Checkpoint{Root: make([]byte, 32)},
},
Signature: nil,
Signature: make([]byte, 96),
}
domain, err := helpers.Domain(st.Fork(), st.Fork().Epoch, params.BeaconConfig().DomainBeaconAttester, st.GenesisValidatorRoot())
require.NoError(t, err)
@@ -789,10 +869,13 @@ func TestRetrieveAttestationSignatureSet_VerifiesMultipleAttestations(t *testing
att2 := &ethpb.Attestation{
AggregationBits: bitfield.NewBitlist(uint64(len(comm2))),
Data: &ethpb.AttestationData{
Slot: 1,
CommitteeIndex: 1,
Slot: 1,
CommitteeIndex: 1,
BeaconBlockRoot: make([]byte, 32),
Target: &ethpb.Checkpoint{Root: make([]byte, 32)},
Source: &ethpb.Checkpoint{Root: make([]byte, 32)},
},
Signature: nil,
Signature: make([]byte, 96),
}
root, err = helpers.ComputeSigningRoot(att2.Data, domain)
require.NoError(t, err)

View File

@@ -35,8 +35,13 @@ import (
func ProcessAttesterSlashings(
ctx context.Context,
beaconState *stateTrie.BeaconState,
body *ethpb.BeaconBlockBody,
b *ethpb.SignedBeaconBlock,
) (*stateTrie.BeaconState, error) {
if b.Block == nil || b.Block.Body == nil {
return nil, errors.New("block and block body can't be nil")
}
body := b.Block.Body
for idx, slashing := range body.AttesterSlashings {
if err := VerifyAttesterSlashing(ctx, beaconState, slashing); err != nil {
return nil, errors.Wrapf(err, "could not verify attester slashing %d", idx)
@@ -48,13 +53,13 @@ func ProcessAttesterSlashings(
currentEpoch := helpers.SlotToEpoch(beaconState.Slot())
var err error
var slashedAny bool
var val *ethpb.Validator
var val *stateTrie.ReadOnlyValidator
for _, validatorIndex := range slashableIndices {
val, err = beaconState.ValidatorAtIndex(validatorIndex)
val, err = beaconState.ValidatorAtIndexReadOnly(validatorIndex)
if err != nil {
return nil, err
}
if helpers.IsSlashableValidator(val, currentEpoch) {
if helpers.IsSlashableValidator(val.ActivationEpoch(), val.WithdrawableEpoch(), val.Slashed(), currentEpoch) {
beaconState, err = v.SlashValidator(beaconState, validatorIndex)
if err != nil {
return nil, errors.Wrapf(err, "could not slash validator index %d",

View File

@@ -11,6 +11,7 @@ import (
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
@@ -19,12 +20,14 @@ import (
func TestSlashableAttestationData_CanSlash(t *testing.T) {
att1 := &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 1},
Source: &ethpb.Checkpoint{Root: []byte{'A'}},
Target: &ethpb.Checkpoint{Epoch: 1, Root: make([]byte, 32)},
Source: &ethpb.Checkpoint{Root: bytesutil.PadTo([]byte{'A'}, 32)},
BeaconBlockRoot: make([]byte, 32),
}
att2 := &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 1},
Source: &ethpb.Checkpoint{Root: []byte{'B'}},
Target: &ethpb.Checkpoint{Epoch: 1, Root: make([]byte, 32)},
Source: &ethpb.Checkpoint{Root: bytesutil.PadTo([]byte{'B'}, 32)},
BeaconBlockRoot: make([]byte, 32),
}
assert.Equal(t, true, blocks.IsSlashableAttestationData(att1, att2), "Atts should have been slashable")
att1.Target.Epoch = 4
@@ -38,15 +41,19 @@ func TestProcessAttesterSlashings_DataNotSlashable(t *testing.T) {
{
Attestation_1: &ethpb.IndexedAttestation{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0},
Target: &ethpb.Checkpoint{Epoch: 0},
Source: &ethpb.Checkpoint{Epoch: 0, Root: make([]byte, 32)},
Target: &ethpb.Checkpoint{Epoch: 0, Root: make([]byte, 32)},
BeaconBlockRoot: make([]byte, 32),
},
Signature: make([]byte, 96),
},
Attestation_2: &ethpb.IndexedAttestation{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 1},
Target: &ethpb.Checkpoint{Epoch: 1},
Source: &ethpb.Checkpoint{Epoch: 1, Root: make([]byte, 32)},
Target: &ethpb.Checkpoint{Epoch: 1, Root: make([]byte, 32)},
BeaconBlockRoot: make([]byte, 32),
},
Signature: make([]byte, 96),
},
},
}
@@ -58,13 +65,14 @@ func TestProcessAttesterSlashings_DataNotSlashable(t *testing.T) {
Slot: currentSlot,
})
require.NoError(t, err)
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
AttesterSlashings: slashings,
},
}
want := fmt.Sprint("attestations are not slashable")
_, err = blocks.ProcessAttesterSlashings(context.Background(), beaconState, block.Body)
_, err = blocks.ProcessAttesterSlashings(context.Background(), beaconState, b)
assert.ErrorContains(t, want, err)
}
@@ -82,29 +90,34 @@ func TestProcessAttesterSlashings_IndexedAttestationFailedToVerify(t *testing.T)
{
Attestation_1: &ethpb.IndexedAttestation{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 1},
Target: &ethpb.Checkpoint{Epoch: 0},
Source: &ethpb.Checkpoint{Epoch: 1, Root: make([]byte, 32)},
Target: &ethpb.Checkpoint{Epoch: 0, Root: make([]byte, 32)},
BeaconBlockRoot: make([]byte, 32),
},
AttestingIndices: make([]uint64, params.BeaconConfig().MaxValidatorsPerCommittee+1),
Signature: make([]byte, 96),
},
Attestation_2: &ethpb.IndexedAttestation{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0},
Target: &ethpb.Checkpoint{Epoch: 0},
Source: &ethpb.Checkpoint{Epoch: 0, Root: make([]byte, 32)},
Target: &ethpb.Checkpoint{Epoch: 0, Root: make([]byte, 32)},
BeaconBlockRoot: make([]byte, 32),
},
AttestingIndices: make([]uint64, params.BeaconConfig().MaxValidatorsPerCommittee+1),
Signature: make([]byte, 96),
},
},
}
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
AttesterSlashings: slashings,
},
}
want := fmt.Sprint("validator indices count exceeds MAX_VALIDATORS_PER_COMMITTEE")
_, err = blocks.ProcessAttesterSlashings(context.Background(), beaconState, block.Body)
_, err = blocks.ProcessAttesterSlashings(context.Background(), beaconState, b)
assert.ErrorContains(t, want, err)
}
@@ -116,8 +129,9 @@ func TestProcessAttesterSlashings_AppliesCorrectStatus(t *testing.T) {
att1 := &ethpb.IndexedAttestation{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 1},
Target: &ethpb.Checkpoint{Epoch: 0},
Source: &ethpb.Checkpoint{Epoch: 1, Root: make([]byte, 32)},
Target: &ethpb.Checkpoint{Epoch: 0, Root: make([]byte, 32)},
BeaconBlockRoot: make([]byte, 32),
},
AttestingIndices: []uint64{0, 1},
}
@@ -128,12 +142,13 @@ func TestProcessAttesterSlashings_AppliesCorrectStatus(t *testing.T) {
sig0 := privKeys[0].Sign(signingRoot[:])
sig1 := privKeys[1].Sign(signingRoot[:])
aggregateSig := bls.AggregateSignatures([]bls.Signature{sig0, sig1})
att1.Signature = aggregateSig.Marshal()[:]
att1.Signature = aggregateSig.Marshal()
att2 := &ethpb.IndexedAttestation{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0},
Target: &ethpb.Checkpoint{Epoch: 0},
Source: &ethpb.Checkpoint{Epoch: 0, Root: make([]byte, 32)},
Target: &ethpb.Checkpoint{Epoch: 0, Root: make([]byte, 32)},
BeaconBlockRoot: make([]byte, 32),
},
AttestingIndices: []uint64{0, 1},
}
@@ -142,7 +157,7 @@ func TestProcessAttesterSlashings_AppliesCorrectStatus(t *testing.T) {
sig0 = privKeys[0].Sign(signingRoot[:])
sig1 = privKeys[1].Sign(signingRoot[:])
aggregateSig = bls.AggregateSignatures([]bls.Signature{sig0, sig1})
att2.Signature = aggregateSig.Marshal()[:]
att2.Signature = aggregateSig.Marshal()
slashings := []*ethpb.AttesterSlashing{
{
@@ -154,13 +169,14 @@ func TestProcessAttesterSlashings_AppliesCorrectStatus(t *testing.T) {
currentSlot := 2 * params.BeaconConfig().SlotsPerEpoch
require.NoError(t, beaconState.SetSlot(currentSlot))
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
AttesterSlashings: slashings,
},
}
newState, err := blocks.ProcessAttesterSlashings(context.Background(), beaconState, block.Body)
newState, err := blocks.ProcessAttesterSlashings(context.Background(), beaconState, b)
require.NoError(t, err)
newRegistry := newState.Validators()

View File

@@ -6,13 +6,12 @@ import (
fuzz "github.com/google/gofuzz"
eth "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
ethereum_beacon_p2p_v1 "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/params"
//"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
ethereum_beacon_p2p_v1 "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
)
func TestFuzzProcessAttestationNoVerify_10000(t *testing.T) {
@@ -25,7 +24,8 @@ func TestFuzzProcessAttestationNoVerify_10000(t *testing.T) {
fuzzer.Fuzz(state)
fuzzer.Fuzz(att)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
_, err = ProcessAttestationNoVerify(ctx, s, att)
require.NoError(t, err)
_, err = ProcessAttestationNoVerifySignature(ctx, s, att)
_ = err
}
}
@@ -40,7 +40,8 @@ func TestFuzzProcessBlockHeader_10000(t *testing.T) {
fuzzer.Fuzz(block)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
_, err = ProcessBlockHeader(s, block)
require.NoError(t, err)
_, err = ProcessBlockHeader(context.Background(), s, block)
_ = err
}
}
@@ -63,6 +64,7 @@ func TestFuzzverifyDepositDataSigningRoot_10000(t *testing.T) {
fuzzer.Fuzz(&s)
fuzzer.Fuzz(&d)
err := verifySignature(ba, pubkey[:], sig[:], domain[:])
_ = err
err = verifySignature(ba, p, s, d)
_ = err
}
@@ -70,14 +72,14 @@ func TestFuzzverifyDepositDataSigningRoot_10000(t *testing.T) {
func TestFuzzProcessEth1DataInBlock_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
block := &eth.BeaconBlock{}
b := &eth.SignedBeaconBlock{}
state := &stateTrie.BeaconState{}
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(block)
s, err := ProcessEth1DataInBlock(state, block)
fuzzer.Fuzz(b)
s, err := ProcessEth1DataInBlock(context.Background(), state, b)
if err != nil && s != nil {
t.Fatalf("state should be nil on err. found: %v on error: %v for state: %v and block: %v", s, err, state, block)
t.Fatalf("state should be nil on err. found: %v on error: %v for state: %v and block: %v", s, err, state, b)
}
}
}
@@ -105,6 +107,7 @@ func TestFuzzEth1DataHasEnoughSupport_10000(t *testing.T) {
s, err := beaconstate.InitializeFromProto(&ethereum_beacon_p2p_v1.BeaconState{
Eth1DataVotes: stateVotes,
})
require.NoError(t, err)
_, err = Eth1DataHasEnoughSupport(s, eth1data)
_ = err
}
@@ -120,6 +123,7 @@ func TestFuzzProcessBlockHeaderNoVerify_10000(t *testing.T) {
fuzzer.Fuzz(state)
fuzzer.Fuzz(block)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
require.NoError(t, err)
_, err = ProcessBlockHeaderNoVerify(s, block)
_ = err
}
@@ -128,15 +132,16 @@ func TestFuzzProcessBlockHeaderNoVerify_10000(t *testing.T) {
func TestFuzzProcessRandao_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &ethereum_beacon_p2p_v1.BeaconState{}
blockBody := &eth.BeaconBlockBody{}
b := &eth.SignedBeaconBlock{}
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(blockBody)
fuzzer.Fuzz(b)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
r, err := ProcessRandao(s, blockBody)
require.NoError(t, err)
r, err := ProcessRandao(context.Background(), s, b)
if err != nil && r != nil {
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, blockBody)
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, b)
}
}
}
@@ -150,6 +155,7 @@ func TestFuzzProcessRandaoNoVerify_10000(t *testing.T) {
fuzzer.Fuzz(state)
fuzzer.Fuzz(blockBody)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
require.NoError(t, err)
r, err := ProcessRandaoNoVerify(s, blockBody)
if err != nil && r != nil {
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, blockBody)
@@ -160,15 +166,16 @@ func TestFuzzProcessRandaoNoVerify_10000(t *testing.T) {
func TestFuzzProcessProposerSlashings_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &ethereum_beacon_p2p_v1.BeaconState{}
blockBody := &eth.BeaconBlockBody{}
b := &eth.SignedBeaconBlock{}
ctx := context.Background()
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(blockBody)
fuzzer.Fuzz(b)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
r, err := ProcessProposerSlashings(ctx, s, blockBody)
require.NoError(t, err)
r, err := ProcessProposerSlashings(ctx, s, b)
if err != nil && r != nil {
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, blockBody)
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, b)
}
}
}
@@ -181,6 +188,7 @@ func TestFuzzVerifyProposerSlashing_10000(t *testing.T) {
fuzzer.Fuzz(state)
fuzzer.Fuzz(proposerSlashing)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
require.NoError(t, err)
err = VerifyProposerSlashing(s, proposerSlashing)
_ = err
}
@@ -189,15 +197,16 @@ func TestFuzzVerifyProposerSlashing_10000(t *testing.T) {
func TestFuzzProcessAttesterSlashings_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &ethereum_beacon_p2p_v1.BeaconState{}
blockBody := &eth.BeaconBlockBody{}
b := &eth.SignedBeaconBlock{}
ctx := context.Background()
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(blockBody)
fuzzer.Fuzz(b)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
r, err := ProcessAttesterSlashings(ctx, s, blockBody)
require.NoError(t, err)
r, err := ProcessAttesterSlashings(ctx, s, b)
if err != nil && r != nil {
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, blockBody)
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, b)
}
}
}
@@ -211,6 +220,7 @@ func TestFuzzVerifyAttesterSlashing_10000(t *testing.T) {
fuzzer.Fuzz(state)
fuzzer.Fuzz(attesterSlashing)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
require.NoError(t, err)
err = VerifyAttesterSlashing(ctx, s, attesterSlashing)
_ = err
}
@@ -241,15 +251,16 @@ func TestFuzzslashableAttesterIndices_10000(t *testing.T) {
func TestFuzzProcessAttestations_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &ethereum_beacon_p2p_v1.BeaconState{}
blockBody := &eth.BeaconBlockBody{}
b := &eth.SignedBeaconBlock{}
ctx := context.Background()
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(blockBody)
fuzzer.Fuzz(b)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
r, err := ProcessAttestations(ctx, s, blockBody)
require.NoError(t, err)
r, err := ProcessAttestations(ctx, s, b)
if err != nil && r != nil {
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, blockBody)
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, b)
}
}
}
@@ -257,15 +268,16 @@ func TestFuzzProcessAttestations_10000(t *testing.T) {
func TestFuzzProcessAttestationsNoVerify_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &ethereum_beacon_p2p_v1.BeaconState{}
blockBody := &eth.BeaconBlockBody{}
b := &eth.SignedBeaconBlock{}
ctx := context.Background()
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(blockBody)
fuzzer.Fuzz(b)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
r, err := ProcessAttestationsNoVerify(ctx, s, blockBody)
require.NoError(t, err)
r, err := ProcessAttestationsNoVerifySignature(ctx, s, b)
if err != nil && r != nil {
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, blockBody)
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, b)
}
}
}
@@ -279,6 +291,7 @@ func TestFuzzProcessAttestation_10000(t *testing.T) {
fuzzer.Fuzz(state)
fuzzer.Fuzz(attestation)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
require.NoError(t, err)
r, err := ProcessAttestation(ctx, s, attestation)
if err != nil && r != nil {
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, attestation)
@@ -295,6 +308,7 @@ func TestFuzzVerifyIndexedAttestationn_10000(t *testing.T) {
fuzzer.Fuzz(state)
fuzzer.Fuzz(idxAttestation)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
require.NoError(t, err)
err = VerifyIndexedAttestation(ctx, s, idxAttestation)
_ = err
}
@@ -309,7 +323,8 @@ func TestFuzzVerifyAttestation_10000(t *testing.T) {
fuzzer.Fuzz(state)
fuzzer.Fuzz(attestation)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
err = VerifyAttestation(ctx, s, attestation)
require.NoError(t, err)
err = VerifyAttestationSignature(ctx, s, attestation)
_ = err
}
}
@@ -317,15 +332,16 @@ func TestFuzzVerifyAttestation_10000(t *testing.T) {
func TestFuzzProcessDeposits_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &ethereum_beacon_p2p_v1.BeaconState{}
blockBody := &eth.BeaconBlockBody{}
b := &eth.SignedBeaconBlock{}
ctx := context.Background()
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(blockBody)
fuzzer.Fuzz(b)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
r, err := ProcessDeposits(ctx, s, blockBody.Deposits)
require.NoError(t, err)
r, err := ProcessDeposits(ctx, s, b)
if err != nil && r != nil {
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, blockBody)
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, b)
}
}
}
@@ -340,6 +356,7 @@ func TestFuzzProcessPreGenesisDeposit_10000(t *testing.T) {
fuzzer.Fuzz(state)
fuzzer.Fuzz(deposit)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
require.NoError(t, err)
r, err := ProcessPreGenesisDeposits(ctx, s, []*eth.Deposit{deposit})
if err != nil && r != nil {
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, deposit)
@@ -356,6 +373,7 @@ func TestFuzzProcessDeposit_10000(t *testing.T) {
fuzzer.Fuzz(state)
fuzzer.Fuzz(deposit)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
require.NoError(t, err)
r, err := ProcessDeposit(s, deposit, true)
if err != nil && r != nil {
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, deposit)
@@ -371,6 +389,7 @@ func TestFuzzverifyDeposit_10000(t *testing.T) {
fuzzer.Fuzz(state)
fuzzer.Fuzz(deposit)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
require.NoError(t, err)
err = verifyDeposit(s, deposit)
_ = err
}
@@ -379,15 +398,16 @@ func TestFuzzverifyDeposit_10000(t *testing.T) {
func TestFuzzProcessVoluntaryExits_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &ethereum_beacon_p2p_v1.BeaconState{}
blockBody := &eth.BeaconBlockBody{}
b := &eth.SignedBeaconBlock{}
ctx := context.Background()
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(blockBody)
fuzzer.Fuzz(b)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
r, err := ProcessVoluntaryExits(ctx, s, blockBody)
require.NoError(t, err)
r, err := ProcessVoluntaryExits(ctx, s, b)
if err != nil && r != nil {
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, blockBody)
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, b)
}
}
}
@@ -395,14 +415,15 @@ func TestFuzzProcessVoluntaryExits_10000(t *testing.T) {
func TestFuzzProcessVoluntaryExitsNoVerify_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
state := &ethereum_beacon_p2p_v1.BeaconState{}
blockBody := &eth.BeaconBlockBody{}
b := &eth.SignedBeaconBlock{}
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(blockBody)
fuzzer.Fuzz(b)
s, err := beaconstate.InitializeFromProtoUnsafe(state)
r, err := ProcessVoluntaryExitsNoVerify(s, blockBody)
require.NoError(t, err)
r, err := ProcessVoluntaryExits(context.Background(), s, b)
if err != nil && r != nil {
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, blockBody)
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, b)
}
}
}
@@ -419,7 +440,7 @@ func TestFuzzVerifyExit_10000(t *testing.T) {
fuzzer.Fuzz(val)
fuzzer.Fuzz(fork)
fuzzer.Fuzz(&slot)
err := VerifyExit(val, slot, fork, ve, params.BeaconConfig().ZeroHash[:])
err := VerifyExitAndSignature(val, slot, fork, ve, params.BeaconConfig().ZeroHash[:])
_ = err
}
}

View File

@@ -39,10 +39,12 @@ func TestProcessAttesterSlashings_RegressionSlashableIndices(t *testing.T) {
root1 := [32]byte{'d', 'o', 'u', 'b', 'l', 'e', '1'}
att1 := &ethpb.IndexedAttestation{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0},
Target: &ethpb.Checkpoint{Epoch: 0, Root: root1[:]},
Source: &ethpb.Checkpoint{Epoch: 0, Root: make([]byte, 32)},
Target: &ethpb.Checkpoint{Epoch: 0, Root: root1[:]},
BeaconBlockRoot: make([]byte, 32),
},
AttestingIndices: setA,
Signature: make([]byte, 96),
}
domain, err := helpers.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorRoot())
require.NoError(t, err)
@@ -54,15 +56,17 @@ func TestProcessAttesterSlashings_RegressionSlashableIndices(t *testing.T) {
aggSigs = append(aggSigs, sig)
}
aggregateSig := bls.AggregateSignatures(aggSigs)
att1.Signature = aggregateSig.Marshal()[:]
att1.Signature = aggregateSig.Marshal()
root2 := [32]byte{'d', 'o', 'u', 'b', 'l', 'e', '2'}
att2 := &ethpb.IndexedAttestation{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0},
Target: &ethpb.Checkpoint{Epoch: 0, Root: root2[:]},
Source: &ethpb.Checkpoint{Epoch: 0, Root: make([]byte, 32)},
Target: &ethpb.Checkpoint{Epoch: 0, Root: root2[:]},
BeaconBlockRoot: make([]byte, 32),
},
AttestingIndices: setB,
Signature: make([]byte, 96),
}
signingRoot, err = helpers.ComputeSigningRoot(att2.Data, domain)
assert.NoError(t, err, "Could not get signing root of beacon block header")
@@ -72,7 +76,7 @@ func TestProcessAttesterSlashings_RegressionSlashableIndices(t *testing.T) {
aggSigs = append(aggSigs, sig)
}
aggregateSig = bls.AggregateSignatures(aggSigs)
att2.Signature = aggregateSig.Marshal()[:]
att2.Signature = aggregateSig.Marshal()
slashings := []*ethpb.AttesterSlashing{
{
@@ -84,13 +88,14 @@ func TestProcessAttesterSlashings_RegressionSlashableIndices(t *testing.T) {
currentSlot := 2 * params.BeaconConfig().SlotsPerEpoch
require.NoError(t, beaconState.SetSlot(currentSlot))
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
AttesterSlashings: slashings,
},
}
newState, err := blocks.ProcessAttesterSlashings(context.Background(), beaconState, block.Body)
newState, err := blocks.ProcessAttesterSlashings(context.Background(), beaconState, b)
require.NoError(t, err)
newRegistry := newState.Validators()
if !newRegistry[expectedSlashedVal].Slashed {

View File

@@ -25,7 +25,8 @@ func ProcessPreGenesisDeposits(
deposits []*ethpb.Deposit,
) (*stateTrie.BeaconState, error) {
var err error
beaconState, err = ProcessDeposits(ctx, beaconState, deposits)
beaconState, err = ProcessDeposits(ctx, beaconState, &ethpb.SignedBeaconBlock{
Block: &ethpb.BeaconBlock{Body: &ethpb.BeaconBlockBody{Deposits: deposits}}})
if err != nil {
return nil, errors.Wrap(err, "could not process deposit")
}
@@ -66,10 +67,14 @@ func ProcessPreGenesisDeposits(
func ProcessDeposits(
ctx context.Context,
beaconState *stateTrie.BeaconState,
deposits []*ethpb.Deposit,
b *ethpb.SignedBeaconBlock,
) (*stateTrie.BeaconState, error) {
var err error
if b.Block == nil || b.Block.Body == nil {
return nil, errors.New("block and block body can't be nil")
}
deposits := b.Block.Body.Deposits
var err error
domain, err := helpers.ComputeDomain(params.BeaconConfig().DomainDeposit, nil, nil)
if err != nil {
return nil, err
@@ -197,7 +202,7 @@ func verifyDeposit(beaconState *stateTrie.BeaconState, deposit *ethpb.Deposit) e
}
receiptRoot := eth1Data.DepositRoot
leaf, err := ssz.HashTreeRoot(deposit.Data)
leaf, err := deposit.Data.HashTreeRoot()
if err != nil {
return errors.Wrap(err, "could not tree hash deposit data")
}
@@ -206,12 +211,14 @@ func verifyDeposit(beaconState *stateTrie.BeaconState, deposit *ethpb.Deposit) e
leaf[:],
int(beaconState.Eth1DepositIndex()),
deposit.Proof,
params.BeaconConfig().DepositContractTreeDepth,
); !ok {
return fmt.Errorf(
"deposit merkle branch of deposit root did not verify for root: %#x",
receiptRoot,
)
}
return nil
}
@@ -225,7 +232,7 @@ func verifyDepositDataWithDomain(ctx context.Context, deps []*ethpb.Deposit, dom
return nil
}
pks := make([]bls.PublicKey, len(deps))
sigs := make([]bls.Signature, len(deps))
sigs := make([][]byte, len(deps))
msgs := make([][32]byte, len(deps))
for i, dep := range deps {
if ctx.Err() != nil {
@@ -234,17 +241,12 @@ func verifyDepositDataWithDomain(ctx context.Context, deps []*ethpb.Deposit, dom
if dep == nil || dep.Data == nil {
return errors.New("nil deposit")
}
dpk, err := bls.PublicKeyFromBytes(dep.Data.PublicKey)
if err != nil {
return err
}
pks[i] = dpk
dsig, err := bls.SignatureFromBytes(dep.Data.Signature)
if err != nil {
return err
}
sigs[i] = dsig
sigs[i] = dep.Data.Signature
root, err := ssz.SigningRoot(dep.Data)
if err != nil {
return errors.Wrap(err, "could not get signing root")
@@ -253,7 +255,7 @@ func verifyDepositDataWithDomain(ctx context.Context, deps []*ethpb.Deposit, dom
ObjectRoot: root[:],
Domain: domain,
}
ctrRoot, err := ssz.HashTreeRoot(signingData)
ctrRoot, err := signingData.HashTreeRoot()
if err != nil {
return errors.Wrap(err, "could not get container root")
}

View File

@@ -5,7 +5,6 @@ import (
"testing"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/go-ssz"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
@@ -26,7 +25,8 @@ func TestProcessDeposits_SameValidatorMultipleDepositsSameBlock(t *testing.T) {
require.NoError(t, err)
eth1Data, err := testutil.DeterministicEth1Data(len(dep))
require.NoError(t, err)
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
// 3 deposits from the same validator
Deposits: []*ethpb.Deposit{dep[0], dep[1], dep[2]},
@@ -49,7 +49,7 @@ func TestProcessDeposits_SameValidatorMultipleDepositsSameBlock(t *testing.T) {
},
})
require.NoError(t, err)
newState, err := blocks.ProcessDeposits(context.Background(), beaconState, block.Body.Deposits)
newState, err := blocks.ProcessDeposits(context.Background(), beaconState, b)
require.NoError(t, err, "Expected block deposits to process correctly")
assert.Equal(t, 2, len(newState.Validators()), "Incorrect validator count")
@@ -58,11 +58,12 @@ func TestProcessDeposits_SameValidatorMultipleDepositsSameBlock(t *testing.T) {
func TestProcessDeposits_MerkleBranchFailsVerification(t *testing.T) {
deposit := &ethpb.Deposit{
Data: &ethpb.Deposit_Data{
PublicKey: []byte{1, 2, 3},
Signature: make([]byte, 96),
PublicKey: bytesutil.PadTo([]byte{1, 2, 3}, 48),
WithdrawalCredentials: make([]byte, 32),
Signature: make([]byte, 96),
},
}
leaf, err := ssz.HashTreeRoot(deposit.Data)
leaf, err := deposit.Data.HashTreeRoot()
require.NoError(t, err)
// We then create a merkle branch for the test.
@@ -72,7 +73,8 @@ func TestProcessDeposits_MerkleBranchFailsVerification(t *testing.T) {
require.NoError(t, err, "Could not generate proof")
deposit.Proof = proof
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
Deposits: []*ethpb.Deposit{deposit},
},
@@ -85,7 +87,7 @@ func TestProcessDeposits_MerkleBranchFailsVerification(t *testing.T) {
})
require.NoError(t, err)
want := "deposit root did not verify"
_, err = blocks.ProcessDeposits(context.Background(), beaconState, block.Body.Deposits)
_, err = blocks.ProcessDeposits(context.Background(), beaconState, b)
assert.ErrorContains(t, want, err)
}
@@ -95,7 +97,8 @@ func TestProcessDeposits_AddsNewValidatorDeposit(t *testing.T) {
eth1Data, err := testutil.DeterministicEth1Data(len(dep))
require.NoError(t, err)
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
Deposits: []*ethpb.Deposit{dep[0]},
},
@@ -117,7 +120,7 @@ func TestProcessDeposits_AddsNewValidatorDeposit(t *testing.T) {
},
})
require.NoError(t, err)
newState, err := blocks.ProcessDeposits(context.Background(), beaconState, block.Body.Deposits)
newState, err := blocks.ProcessDeposits(context.Background(), beaconState, b)
require.NoError(t, err, "Expected block deposits to process correctly")
if newState.Balances()[1] != dep[0].Data.Amount {
t.Errorf(
@@ -132,15 +135,17 @@ func TestProcessDeposits_RepeatedDeposit_IncreasesValidatorBalance(t *testing.T)
sk := bls.RandKey()
deposit := &ethpb.Deposit{
Data: &ethpb.Deposit_Data{
PublicKey: sk.PublicKey().Marshal(),
Amount: 1000,
PublicKey: sk.PublicKey().Marshal(),
Amount: 1000,
WithdrawalCredentials: make([]byte, 32),
Signature: make([]byte, 96),
},
}
sr, err := helpers.ComputeSigningRoot(deposit.Data, bytesutil.ToBytes(3, 8))
sr, err := helpers.ComputeSigningRoot(deposit.Data, bytesutil.ToBytes(3, 32))
require.NoError(t, err)
sig := sk.Sign(sr[:])
deposit.Data.Signature = sig.Marshal()
leaf, err := ssz.HashTreeRoot(deposit.Data)
leaf, err := deposit.Data.HashTreeRoot()
require.NoError(t, err)
// We then create a merkle branch for the test.
@@ -150,7 +155,8 @@ func TestProcessDeposits_RepeatedDeposit_IncreasesValidatorBalance(t *testing.T)
require.NoError(t, err, "Could not generate proof")
deposit.Proof = proof
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
Deposits: []*ethpb.Deposit{deposit},
},
@@ -175,7 +181,7 @@ func TestProcessDeposits_RepeatedDeposit_IncreasesValidatorBalance(t *testing.T)
},
})
require.NoError(t, err)
newState, err := blocks.ProcessDeposits(context.Background(), beaconState, block.Body.Deposits)
newState, err := blocks.ProcessDeposits(context.Background(), beaconState, b)
require.NoError(t, err, "Process deposit failed")
assert.Equal(t, uint64(1000+50), newState.Balances()[1], "Expected balance at index 1 to be 1050")
}

View File

@@ -2,6 +2,7 @@ package blocks
import (
"bytes"
"context"
"errors"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
@@ -18,7 +19,8 @@ import (
// state.eth1_data_votes.append(body.eth1_data)
// if state.eth1_data_votes.count(body.eth1_data) * 2 > EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH:
// state.latest_eth1_data = body.eth1_data
func ProcessEth1DataInBlock(beaconState *stateTrie.BeaconState, block *ethpb.BeaconBlock) (*stateTrie.BeaconState, error) {
func ProcessEth1DataInBlock(ctx context.Context, beaconState *stateTrie.BeaconState, b *ethpb.SignedBeaconBlock) (*stateTrie.BeaconState, error) {
block := b.Block
if beaconState == nil {
return nil, errors.New("nil state")
}

View File

@@ -1,6 +1,7 @@
package blocks_test
import (
"context"
"fmt"
"testing"
@@ -9,7 +10,9 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
)
@@ -19,7 +22,7 @@ func FakeDeposits(n uint64) []*ethpb.Eth1Data {
for i := uint64(0); i < n; i++ {
deposits[i] = &ethpb.Eth1Data{
DepositCount: 1,
DepositRoot: []byte("root"),
DepositRoot: bytesutil.PadTo([]byte("root"), 32),
}
}
return deposits
@@ -36,7 +39,7 @@ func TestEth1DataHasEnoughSupport(t *testing.T) {
stateVotes: FakeDeposits(4 * params.BeaconConfig().SlotsPerEpoch),
data: &ethpb.Eth1Data{
DepositCount: 1,
DepositRoot: []byte("root"),
DepositRoot: bytesutil.PadTo([]byte("root"), 32),
},
hasSupport: true,
votingPeriodLength: 7,
@@ -44,7 +47,7 @@ func TestEth1DataHasEnoughSupport(t *testing.T) {
stateVotes: FakeDeposits(4 * params.BeaconConfig().SlotsPerEpoch),
data: &ethpb.Eth1Data{
DepositCount: 1,
DepositRoot: []byte("root"),
DepositRoot: bytesutil.PadTo([]byte("root"), 32),
},
hasSupport: false,
votingPeriodLength: 8,
@@ -52,7 +55,7 @@ func TestEth1DataHasEnoughSupport(t *testing.T) {
stateVotes: FakeDeposits(4 * params.BeaconConfig().SlotsPerEpoch),
data: &ethpb.Eth1Data{
DepositCount: 1,
DepositRoot: []byte("root"),
DepositRoot: bytesutil.PadTo([]byte("root"), 32),
},
hasSupport: false,
votingPeriodLength: 10,
@@ -161,7 +164,8 @@ func TestProcessEth1Data_SetsCorrectly(t *testing.T) {
})
require.NoError(t, err)
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
Eth1Data: &ethpb.Eth1Data{
DepositRoot: []byte{2},
@@ -172,7 +176,7 @@ func TestProcessEth1Data_SetsCorrectly(t *testing.T) {
period := params.BeaconConfig().EpochsPerEth1VotingPeriod * params.BeaconConfig().SlotsPerEpoch
for i := uint64(0); i < period; i++ {
beaconState, err = blocks.ProcessEth1DataInBlock(beaconState, block)
beaconState, err = blocks.ProcessEth1DataInBlock(context.Background(), beaconState, b)
require.NoError(t, err)
}
@@ -180,10 +184,10 @@ func TestProcessEth1Data_SetsCorrectly(t *testing.T) {
if len(newETH1DataVotes) <= 1 {
t.Error("Expected new ETH1 data votes to have length > 1")
}
if !proto.Equal(beaconState.Eth1Data(), beaconstate.CopyETH1Data(block.Body.Eth1Data)) {
if !proto.Equal(beaconState.Eth1Data(), beaconstate.CopyETH1Data(b.Block.Body.Eth1Data)) {
t.Errorf(
"Expected latest eth1 data to have been set to %v, received %v",
block.Body.Eth1Data,
b.Block.Body.Eth1Data,
beaconState.Eth1Data(),
)
}

View File

@@ -39,8 +39,13 @@ import (
func ProcessVoluntaryExits(
ctx context.Context,
beaconState *stateTrie.BeaconState,
body *ethpb.BeaconBlockBody,
b *ethpb.SignedBeaconBlock,
) (*stateTrie.BeaconState, error) {
if b.Block == nil || b.Block.Body == nil {
return nil, errors.New("block and block body can't be nil")
}
body := b.Block.Body
exits := body.VoluntaryExits
for idx, exit := range exits {
if exit == nil || exit.Exit == nil {
@@ -50,7 +55,7 @@ func ProcessVoluntaryExits(
if err != nil {
return nil, err
}
if err := VerifyExit(val, beaconState.Slot(), beaconState.Fork(), exit, beaconState.GenesisValidatorRoot()); err != nil {
if err := VerifyExitAndSignature(val, beaconState.Slot(), beaconState.Fork(), exit, beaconState.GenesisValidatorRoot()); err != nil {
return nil, errors.Wrapf(err, "could not verify exit %d", idx)
}
beaconState, err = v.InitiateValidatorExit(beaconState, exit.Exit.ValidatorIndex)
@@ -61,19 +66,31 @@ func ProcessVoluntaryExits(
return beaconState, nil
}
// ProcessVoluntaryExitsNoVerify processes all the voluntary exits in
// ProcessVoluntaryExitsNoVerifySignature processes all the voluntary exits in
// a block body, without verifying their BLS signatures.
func ProcessVoluntaryExitsNoVerify(
// This function is here to satisfy fuzz tests.
func ProcessVoluntaryExitsNoVerifySignature(
beaconState *stateTrie.BeaconState,
body *ethpb.BeaconBlockBody,
) (*stateTrie.BeaconState, error) {
var err error
exits := body.VoluntaryExits
for idx, exit := range exits {
if exit == nil || exit.Exit == nil {
return nil, errors.New("nil exit")
}
val, err := beaconState.ValidatorAtIndexReadOnly(exit.Exit.ValidatorIndex)
if err != nil {
return nil, err
}
if err := verifyExitConditions(val, beaconState.Slot(), exit.Exit); err != nil {
return nil, err
}
// Validate that fork and genesis root are valid.
_, err = helpers.Domain(beaconState.Fork(), exit.Exit.Epoch, params.BeaconConfig().DomainVoluntaryExit, beaconState.GenesisValidatorRoot())
if err != nil {
return nil, err
}
beaconState, err = v.InitiateValidatorExit(beaconState, exit.Exit.ValidatorIndex)
if err != nil {
return nil, errors.Wrapf(err, "failed to process voluntary exit at index %d", idx)
@@ -82,7 +99,7 @@ func ProcessVoluntaryExitsNoVerify(
return beaconState, nil
}
// VerifyExit implements the spec defined validation for voluntary exits.
// VerifyExitAndSignature implements the spec defined validation for voluntary exits.
//
// Spec pseudocode definition:
// def process_voluntary_exit(state: BeaconState, exit: VoluntaryExit) -> None:
@@ -101,32 +118,14 @@ func ProcessVoluntaryExitsNoVerify(
// # Verify signature
// domain = get_domain(state, DOMAIN_VOLUNTARY_EXIT, exit.epoch)
// assert bls_verify(validator.pubkey, signing_root(exit), exit.signature, domain)
func VerifyExit(validator *stateTrie.ReadOnlyValidator, currentSlot uint64, fork *pb.Fork, signed *ethpb.SignedVoluntaryExit, genesisRoot []byte) error {
func VerifyExitAndSignature(validator *stateTrie.ReadOnlyValidator, currentSlot uint64, fork *pb.Fork, signed *ethpb.SignedVoluntaryExit, genesisRoot []byte) error {
if signed == nil || signed.Exit == nil {
return errors.New("nil exit")
}
exit := signed.Exit
currentEpoch := helpers.SlotToEpoch(currentSlot)
// Verify the validator is active.
if !helpers.IsActiveValidatorUsingTrie(validator, currentEpoch) {
return errors.New("non-active validator cannot exit")
}
// Verify the validator has not yet exited.
if validator.ExitEpoch() != params.BeaconConfig().FarFutureEpoch {
return fmt.Errorf("validator has already exited at epoch: %v", validator.ExitEpoch())
}
// Exits must specify an epoch when they become valid; they are not valid before then.
if currentEpoch < exit.Epoch {
return fmt.Errorf("expected current epoch >= exit epoch, received %d < %d", currentEpoch, exit.Epoch)
}
// Verify the validator has been active long enough.
if currentEpoch < validator.ActivationEpoch()+params.BeaconConfig().ShardCommitteePeriod {
return fmt.Errorf(
"validator has not been active long enough to exit, wanted epoch %d >= %d",
currentEpoch,
validator.ActivationEpoch()+params.BeaconConfig().ShardCommitteePeriod,
)
if err := verifyExitConditions(validator, currentSlot, exit); err != nil {
return err
}
domain, err := helpers.Domain(fork, exit.Epoch, params.BeaconConfig().DomainVoluntaryExit, genesisRoot)
if err != nil {
@@ -138,3 +137,46 @@ func VerifyExit(validator *stateTrie.ReadOnlyValidator, currentSlot uint64, fork
}
return nil
}
// verifyExitConditions implements the spec defined validation for voluntary exits(excluding signatures).
//
// Spec pseudocode definition:
// def process_voluntary_exit(state: BeaconState, exit: VoluntaryExit) -> None:
// """
// Process ``VoluntaryExit`` operation.
// """
// validator = state.validator_registry[exit.validator_index]
// # Verify the validator is active
// assert is_active_validator(validator, get_current_epoch(state))
// # Verify the validator has not yet exited
// assert validator.exit_epoch == FAR_FUTURE_EPOCH
// # Exits must specify an epoch when they become valid; they are not valid before then
// assert get_current_epoch(state) >= exit.epoch
// # Verify the validator has been active long enough
// assert get_current_epoch(state) >= validator.activation_epoch + SHARD_COMMITTEE_PERIOD
func verifyExitConditions(validator *stateTrie.ReadOnlyValidator, currentSlot uint64, exit *ethpb.VoluntaryExit) error {
currentEpoch := helpers.SlotToEpoch(currentSlot)
// Verify the validator is active.
if !helpers.IsActiveValidatorUsingTrie(validator, currentEpoch) {
return errors.New("non-active validator cannot exit")
}
// Verify the validator has not yet submitted an exit.
if validator.ExitEpoch() != params.BeaconConfig().FarFutureEpoch {
return fmt.Errorf(
"validator has already submitted an exit, which will take place at epoch: %v",
validator.ExitEpoch())
}
// Exits must specify an epoch when they become valid; they are not valid before then.
if currentEpoch < exit.Epoch {
return fmt.Errorf("expected current epoch >= exit epoch, received %d < %d", currentEpoch, exit.Epoch)
}
// Verify the validator has been active long enough.
if currentEpoch < validator.ActivationEpoch()+params.BeaconConfig().ShardCommitteePeriod {
return fmt.Errorf(
"validator has not been active long enough to exit: %d epochs vs required %d epochs",
currentEpoch,
validator.ActivationEpoch()+params.BeaconConfig().ShardCommitteePeriod,
)
}
return nil
}

View File

@@ -11,6 +11,7 @@ import (
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
)
@@ -32,14 +33,19 @@ func TestProcessVoluntaryExits_ValidatorNotActive(t *testing.T) {
Validators: registry,
})
require.NoError(t, err)
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
VoluntaryExits: exits,
},
}
want := "non-active validator cannot exit"
_, err = blocks.ProcessVoluntaryExits(context.Background(), state, block.Body)
_, err = blocks.ProcessVoluntaryExits(context.Background(), state, b)
assert.ErrorContains(t, want, err)
// Check conformance of no verify method.
_, err = blocks.ProcessVoluntaryExitsNoVerifySignature(state, b.Block.Body)
assert.ErrorContains(t, want, err)
}
@@ -61,14 +67,19 @@ func TestProcessVoluntaryExits_InvalidExitEpoch(t *testing.T) {
Slot: 0,
})
require.NoError(t, err)
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
VoluntaryExits: exits,
},
}
want := "expected current epoch >= exit epoch"
_, err = blocks.ProcessVoluntaryExits(context.Background(), state, block.Body)
_, err = blocks.ProcessVoluntaryExits(context.Background(), state, b)
assert.ErrorContains(t, want, err)
// Check conformance of no verify method.
_, err = blocks.ProcessVoluntaryExitsNoVerifySignature(state, b.Block.Body)
assert.ErrorContains(t, want, err)
}
@@ -91,14 +102,45 @@ func TestProcessVoluntaryExits_NotActiveLongEnoughToExit(t *testing.T) {
Slot: 10,
})
require.NoError(t, err)
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
VoluntaryExits: exits,
},
}
want := "validator has not been active long enough to exit"
_, err = blocks.ProcessVoluntaryExits(context.Background(), state, block.Body)
_, err = blocks.ProcessVoluntaryExits(context.Background(), state, b)
assert.ErrorContains(t, want, err)
}
func TestProcessVoluntaryExits_ExitAlreadySubmitted(t *testing.T) {
exits := []*ethpb.SignedVoluntaryExit{
{
Exit: &ethpb.VoluntaryExit{
Epoch: 10,
},
},
}
registry := []*ethpb.Validator{
{
ExitEpoch: 10,
},
}
state, err := stateTrie.InitializeFromProto(&pb.BeaconState{
Validators: registry,
Slot: 0,
})
require.NoError(t, err)
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
VoluntaryExits: exits,
},
}
want := "validator has already submitted an exit, which will take place at epoch: 10"
_, err = blocks.ProcessVoluntaryExits(context.Background(), state, b)
assert.ErrorContains(t, want, err)
}
@@ -132,22 +174,33 @@ func TestProcessVoluntaryExits_AppliesCorrectStatus(t *testing.T) {
priv := bls.RandKey()
val, err := state.ValidatorAtIndex(0)
require.NoError(t, err)
val.PublicKey = priv.PublicKey().Marshal()[:]
val.PublicKey = priv.PublicKey().Marshal()
require.NoError(t, state.UpdateValidatorAtIndex(0, val))
exits[0].Signature, err = helpers.ComputeDomainAndSign(state, helpers.CurrentEpoch(state), exits[0].Exit, params.BeaconConfig().DomainVoluntaryExit, priv)
require.NoError(t, err)
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
VoluntaryExits: exits,
},
}
newState, err := blocks.ProcessVoluntaryExits(context.Background(), state, block.Body)
stateCopy := state.Copy()
newState, err := blocks.ProcessVoluntaryExits(context.Background(), state, b)
require.NoError(t, err, "Could not process exits")
newRegistry := newState.Validators()
if newRegistry[0].ExitEpoch != helpers.ActivationExitEpoch(state.Slot()/params.BeaconConfig().SlotsPerEpoch) {
t.Errorf("Expected validator exit epoch to be %d, got %d",
helpers.ActivationExitEpoch(state.Slot()/params.BeaconConfig().SlotsPerEpoch), newRegistry[0].ExitEpoch)
}
// Check conformance with NoVerify Exit Method.
newState, err = blocks.ProcessVoluntaryExitsNoVerifySignature(stateCopy, b.Block.Body)
require.NoError(t, err, "Could not process exits")
newRegistry = newState.Validators()
if newRegistry[0].ExitEpoch != helpers.ActivationExitEpoch(stateCopy.Slot()/params.BeaconConfig().SlotsPerEpoch) {
t.Errorf("Expected validator exit epoch to be %d, got %d",
helpers.ActivationExitEpoch(stateCopy.Slot()/params.BeaconConfig().SlotsPerEpoch), newRegistry[0].ExitEpoch)
}
}

View File

@@ -4,19 +4,27 @@ package blocks
import (
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
)
// NewGenesisBlock returns the canonical, genesis block for the beacon chain protocol.
func NewGenesisBlock(stateRoot []byte) *ethpb.SignedBeaconBlock {
zeroHash := params.BeaconConfig().ZeroHash[:]
genBlock := &ethpb.BeaconBlock{
ParentRoot: zeroHash,
StateRoot: stateRoot,
Body: &ethpb.BeaconBlockBody{},
}
return &ethpb.SignedBeaconBlock{
Block: genBlock,
block := &ethpb.SignedBeaconBlock{
Block: &ethpb.BeaconBlock{
ParentRoot: zeroHash,
StateRoot: bytesutil.PadTo(stateRoot, 32),
Body: &ethpb.BeaconBlockBody{
RandaoReveal: make([]byte, 96),
Eth1Data: &ethpb.Eth1Data{
DepositRoot: make([]byte, 32),
BlockHash: make([]byte, 32),
},
Graffiti: make([]byte, 32),
},
},
Signature: params.BeaconConfig().EmptySignature[:],
}
return block
}

View File

@@ -4,11 +4,12 @@ import (
"testing"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
)
func TestGenesisBlock_InitializedCorrectly(t *testing.T) {
stateHash := []byte{0}
stateHash := bytesutil.PadTo([]byte{0}, 32)
b1 := blocks.NewGenesisBlock(stateHash)
assert.NotNil(t, b1.Block.ParentRoot, "Genesis block missing ParentHash field")

View File

@@ -2,13 +2,13 @@ package blocks
import (
"bytes"
"context"
"fmt"
"github.com/pkg/errors"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
"github.com/prysmaticlabs/prysm/shared/params"
)
@@ -37,6 +37,7 @@ import (
// # Verify proposer signature
// assert bls_verify(proposer.pubkey, signing_root(block), block.signature, get_domain(state, DOMAIN_BEACON_PROPOSER))
func ProcessBlockHeader(
ctx context.Context,
beaconState *stateTrie.BeaconState,
block *ethpb.SignedBeaconBlock,
) (*stateTrie.BeaconState, error) {
@@ -99,7 +100,7 @@ func ProcessBlockHeaderNoVerify(
if parentHeader.Slot >= block.Slot {
return nil, fmt.Errorf("block.Slot %d must be greater than state.LatestBlockHeader.Slot %d", block.Slot, parentHeader.Slot)
}
parentRoot, err := stateutil.BlockHeaderRoot(parentHeader)
parentRoot, err := parentHeader.HashTreeRoot()
if err != nil {
return nil, err
}
@@ -118,7 +119,7 @@ func ProcessBlockHeaderNoVerify(
return nil, fmt.Errorf("proposer at index %d was previously slashed", idx)
}
bodyRoot, err := stateutil.BlockBodyRoot(block.Body)
bodyRoot, err := block.Body.HashTreeRoot()
if err != nil {
return nil, err
}

View File

@@ -1,23 +1,22 @@
package blocks_test
import (
"context"
"io/ioutil"
"testing"
"github.com/gogo/protobuf/proto"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/go-ssz"
"github.com/sirupsen/logrus"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
"github.com/sirupsen/logrus"
)
func init() {
@@ -28,40 +27,35 @@ func TestProcessBlockHeader_ImproperBlockSlot(t *testing.T) {
validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount)
for i := 0; i < len(validators); i++ {
validators[i] = &ethpb.Validator{
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
Slashed: true,
PublicKey: make([]byte, 32),
WithdrawalCredentials: make([]byte, 32),
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
Slashed: true,
}
}
state, err := stateTrie.InitializeFromProto(&pb.BeaconState{
Validators: validators,
Slot: 10,
LatestBlockHeader: &ethpb.BeaconBlockHeader{Slot: 10}, // Must be less than block.Slot
Fork: &pb.Fork{
PreviousVersion: []byte{0, 0, 0, 0},
CurrentVersion: []byte{0, 0, 0, 0},
},
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
})
require.NoError(t, err)
state := testutil.NewBeaconState()
require.NoError(t, state.SetSlot(10))
require.NoError(t, state.SetValidators(validators))
require.NoError(t, state.SetLatestBlockHeader(&ethpb.BeaconBlockHeader{
Slot: 10, // Must be less than block.Slot
ParentRoot: make([]byte, 32),
StateRoot: make([]byte, 32),
BodyRoot: make([]byte, 32),
}))
latestBlockSignedRoot, err := stateutil.BlockHeaderRoot(state.LatestBlockHeader())
latestBlockSignedRoot, err := state.LatestBlockHeader().HashTreeRoot()
require.NoError(t, err)
currentEpoch := helpers.CurrentEpoch(state)
priv := bls.RandKey()
pID, err := helpers.BeaconProposerIndex(state)
require.NoError(t, err)
block := &ethpb.SignedBeaconBlock{
Block: &ethpb.BeaconBlock{
ProposerIndex: pID,
Slot: 10,
Body: &ethpb.BeaconBlockBody{
RandaoReveal: []byte{'A', 'B', 'C'},
},
ParentRoot: latestBlockSignedRoot[:],
},
}
block := testutil.NewBeaconBlock()
block.Block.ProposerIndex = pID
block.Block.Slot = 10
block.Block.Body.RandaoReveal = bytesutil.PadTo([]byte{'A', 'B', 'C'}, 96)
block.Block.ParentRoot = latestBlockSignedRoot[:]
block.Signature, err = helpers.ComputeDomainAndSign(state, currentEpoch, block.Block, params.BeaconConfig().DomainBeaconProposer, priv)
require.NoError(t, err)
@@ -72,36 +66,36 @@ func TestProcessBlockHeader_ImproperBlockSlot(t *testing.T) {
err = state.UpdateValidatorAtIndex(proposerIdx, validators[proposerIdx])
require.NoError(t, err)
_, err = blocks.ProcessBlockHeader(state, block)
_, err = blocks.ProcessBlockHeader(context.Background(), state, block)
assert.ErrorContains(t, "block.Slot 10 must be greater than state.LatestBlockHeader.Slot 10", err)
}
func TestProcessBlockHeader_WrongProposerSig(t *testing.T) {
testutil.ResetCache()
beaconState, privKeys := testutil.DeterministicGenesisState(t, 100)
require.NoError(t, beaconState.SetLatestBlockHeader(&ethpb.BeaconBlockHeader{Slot: 9}))
require.NoError(t, beaconState.SetLatestBlockHeader(&ethpb.BeaconBlockHeader{
Slot: 9,
ParentRoot: make([]byte, 32),
StateRoot: make([]byte, 32),
BodyRoot: make([]byte, 32),
}))
require.NoError(t, beaconState.SetSlot(10))
lbhdr, err := stateutil.BlockHeaderRoot(beaconState.LatestBlockHeader())
lbhdr, err := beaconState.LatestBlockHeader().HashTreeRoot()
require.NoError(t, err)
proposerIdx, err := helpers.BeaconProposerIndex(beaconState)
require.NoError(t, err)
block := &ethpb.SignedBeaconBlock{
Block: &ethpb.BeaconBlock{
ProposerIndex: proposerIdx,
Slot: 10,
Body: &ethpb.BeaconBlockBody{
RandaoReveal: []byte{'A', 'B', 'C'},
},
ParentRoot: lbhdr[:],
},
}
block := testutil.NewBeaconBlock()
block.Block.ProposerIndex = proposerIdx
block.Block.Slot = 10
block.Block.Body.RandaoReveal = bytesutil.PadTo([]byte{'A', 'B', 'C'}, 96)
block.Block.ParentRoot = lbhdr[:]
block.Signature, err = helpers.ComputeDomainAndSign(beaconState, 0, block.Block, params.BeaconConfig().DomainBeaconProposer, privKeys[proposerIdx+1])
require.NoError(t, err)
_, err = blocks.ProcessBlockHeader(beaconState, block)
_, err = blocks.ProcessBlockHeader(context.Background(), beaconState, block)
want := "signature did not verify"
assert.ErrorContains(t, want, err)
}
@@ -110,24 +104,25 @@ func TestProcessBlockHeader_DifferentSlots(t *testing.T) {
validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount)
for i := 0; i < len(validators); i++ {
validators[i] = &ethpb.Validator{
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
Slashed: true,
PublicKey: make([]byte, 32),
WithdrawalCredentials: make([]byte, 32),
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
Slashed: true,
}
}
state, err := stateTrie.InitializeFromProto(&pb.BeaconState{
Validators: validators,
Slot: 10,
LatestBlockHeader: &ethpb.BeaconBlockHeader{Slot: 9},
Fork: &pb.Fork{
PreviousVersion: []byte{0, 0, 0, 0},
CurrentVersion: []byte{0, 0, 0, 0},
},
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
})
require.NoError(t, err)
state := testutil.NewBeaconState()
require.NoError(t, state.SetValidators(validators))
require.NoError(t, state.SetSlot(10))
require.NoError(t, state.SetLatestBlockHeader(&ethpb.BeaconBlockHeader{
Slot: 9,
ProposerIndex: 0,
ParentRoot: make([]byte, 32),
StateRoot: make([]byte, 32),
BodyRoot: make([]byte, 32),
}))
lbhsr, err := ssz.HashTreeRoot(state.LatestBlockHeader())
lbhsr, err := state.LatestBlockHeader().HashTreeRoot()
require.NoError(t, err)
currentEpoch := helpers.CurrentEpoch(state)
@@ -146,7 +141,7 @@ func TestProcessBlockHeader_DifferentSlots(t *testing.T) {
Signature: blockSig,
}
_, err = blocks.ProcessBlockHeader(state, block)
_, err = blocks.ProcessBlockHeader(context.Background(), state, block)
want := "is different than block slot"
assert.ErrorContains(t, want, err)
}
@@ -155,23 +150,19 @@ func TestProcessBlockHeader_PreviousBlockRootNotSignedRoot(t *testing.T) {
validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount)
for i := 0; i < len(validators); i++ {
validators[i] = &ethpb.Validator{
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
Slashed: true,
PublicKey: make([]byte, 48),
WithdrawalCredentials: make([]byte, 32),
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
Slashed: true,
}
}
state, err := stateTrie.InitializeFromProto(&pb.BeaconState{
Validators: validators,
Slot: 10,
LatestBlockHeader: &ethpb.BeaconBlockHeader{Slot: 9},
Fork: &pb.Fork{
PreviousVersion: []byte{0, 0, 0, 0},
CurrentVersion: []byte{0, 0, 0, 0},
},
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
})
require.NoError(t, err)
state := testutil.NewBeaconState()
require.NoError(t, state.SetValidators(validators))
require.NoError(t, state.SetSlot(10))
bh := state.LatestBlockHeader()
bh.Slot = 9
require.NoError(t, state.SetLatestBlockHeader(bh))
currentEpoch := helpers.CurrentEpoch(state)
priv := bls.RandKey()
blockSig, err := helpers.ComputeDomainAndSign(state, currentEpoch, []byte("hello"), params.BeaconConfig().DomainBeaconProposer, priv)
@@ -179,19 +170,14 @@ func TestProcessBlockHeader_PreviousBlockRootNotSignedRoot(t *testing.T) {
validators[5896].PublicKey = priv.PublicKey().Marshal()
pID, err := helpers.BeaconProposerIndex(state)
require.NoError(t, err)
block := &ethpb.SignedBeaconBlock{
Block: &ethpb.BeaconBlock{
ProposerIndex: pID,
Slot: 10,
Body: &ethpb.BeaconBlockBody{
RandaoReveal: []byte{'A', 'B', 'C'},
},
ParentRoot: []byte{'A'},
},
Signature: blockSig,
}
block := testutil.NewBeaconBlock()
block.Block.Slot = 10
block.Block.ProposerIndex = pID
block.Block.Body.RandaoReveal = bytesutil.PadTo([]byte{'A', 'B', 'C'}, 96)
block.Block.ParentRoot = bytesutil.PadTo([]byte{'A'}, 32)
block.Signature = blockSig
_, err = blocks.ProcessBlockHeader(state, block)
_, err = blocks.ProcessBlockHeader(context.Background(), state, block)
want := "does not match"
assert.ErrorContains(t, want, err)
}
@@ -200,24 +186,20 @@ func TestProcessBlockHeader_SlashedProposer(t *testing.T) {
validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount)
for i := 0; i < len(validators); i++ {
validators[i] = &ethpb.Validator{
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
Slashed: true,
PublicKey: make([]byte, 48),
WithdrawalCredentials: make([]byte, 32),
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
Slashed: true,
}
}
state, err := stateTrie.InitializeFromProto(&pb.BeaconState{
Validators: validators,
Slot: 10,
LatestBlockHeader: &ethpb.BeaconBlockHeader{Slot: 9},
Fork: &pb.Fork{
PreviousVersion: []byte{0, 0, 0, 0},
CurrentVersion: []byte{0, 0, 0, 0},
},
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
})
require.NoError(t, err)
parentRoot, err := stateutil.BlockHeaderRoot(state.LatestBlockHeader())
state := testutil.NewBeaconState()
require.NoError(t, state.SetValidators(validators))
require.NoError(t, state.SetSlot(10))
bh := state.LatestBlockHeader()
bh.Slot = 9
require.NoError(t, state.SetLatestBlockHeader(bh))
parentRoot, err := state.LatestBlockHeader().HashTreeRoot()
require.NoError(t, err)
currentEpoch := helpers.CurrentEpoch(state)
priv := bls.RandKey()
@@ -227,19 +209,14 @@ func TestProcessBlockHeader_SlashedProposer(t *testing.T) {
validators[12683].PublicKey = priv.PublicKey().Marshal()
pID, err := helpers.BeaconProposerIndex(state)
require.NoError(t, err)
block := &ethpb.SignedBeaconBlock{
Block: &ethpb.BeaconBlock{
ProposerIndex: pID,
Slot: 10,
Body: &ethpb.BeaconBlockBody{
RandaoReveal: []byte{'A', 'B', 'C'},
},
ParentRoot: parentRoot[:],
},
Signature: blockSig,
}
block := testutil.NewBeaconBlock()
block.Block.Slot = 10
block.Block.ProposerIndex = pID
block.Block.Body.RandaoReveal = bytesutil.PadTo([]byte{'A', 'B', 'C'}, 96)
block.Block.ParentRoot = parentRoot[:]
block.Signature = blockSig
_, err = blocks.ProcessBlockHeader(state, block)
_, err = blocks.ProcessBlockHeader(context.Background(), state, block)
want := "was previously slashed"
assert.ErrorContains(t, want, err)
}
@@ -248,43 +225,39 @@ func TestProcessBlockHeader_OK(t *testing.T) {
validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount)
for i := 0; i < len(validators); i++ {
validators[i] = &ethpb.Validator{
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
Slashed: true,
PublicKey: make([]byte, 32),
WithdrawalCredentials: make([]byte, 32),
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
Slashed: true,
}
}
state, err := stateTrie.InitializeFromProto(&pb.BeaconState{
Validators: validators,
Slot: 10,
LatestBlockHeader: &ethpb.BeaconBlockHeader{Slot: 9},
Fork: &pb.Fork{
PreviousVersion: []byte{0, 0, 0, 0},
CurrentVersion: []byte{0, 0, 0, 0},
},
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
})
require.NoError(t, err)
state := testutil.NewBeaconState()
require.NoError(t, state.SetValidators(validators))
require.NoError(t, state.SetSlot(10))
require.NoError(t, state.SetLatestBlockHeader(&ethpb.BeaconBlockHeader{
Slot: 9,
ProposerIndex: 0,
ParentRoot: make([]byte, 32),
StateRoot: make([]byte, 32),
BodyRoot: make([]byte, 32),
}))
latestBlockSignedRoot, err := stateutil.BlockHeaderRoot(state.LatestBlockHeader())
latestBlockSignedRoot, err := state.LatestBlockHeader().HashTreeRoot()
require.NoError(t, err)
currentEpoch := helpers.CurrentEpoch(state)
priv := bls.RandKey()
pID, err := helpers.BeaconProposerIndex(state)
require.NoError(t, err)
block := &ethpb.SignedBeaconBlock{
Block: &ethpb.BeaconBlock{
ProposerIndex: pID,
Slot: 10,
Body: &ethpb.BeaconBlockBody{
RandaoReveal: []byte{'A', 'B', 'C'},
},
ParentRoot: latestBlockSignedRoot[:],
},
}
block := testutil.NewBeaconBlock()
block.Block.ProposerIndex = pID
block.Block.Slot = 10
block.Block.Body.RandaoReveal = bytesutil.PadTo([]byte{'A', 'B', 'C'}, 96)
block.Block.ParentRoot = latestBlockSignedRoot[:]
block.Signature, err = helpers.ComputeDomainAndSign(state, currentEpoch, block.Block, params.BeaconConfig().DomainBeaconProposer, priv)
require.NoError(t, err)
bodyRoot, err := stateutil.BlockBodyRoot(block.Block.Body)
bodyRoot, err := block.Block.Body.HashTreeRoot()
require.NoError(t, err, "Failed to hash block bytes got")
proposerIdx, err := helpers.BeaconProposerIndex(state)
@@ -294,7 +267,7 @@ func TestProcessBlockHeader_OK(t *testing.T) {
err = state.UpdateValidatorAtIndex(proposerIdx, validators[proposerIdx])
require.NoError(t, err)
newState, err := blocks.ProcessBlockHeader(state, block)
newState, err := blocks.ProcessBlockHeader(context.Background(), state, block)
require.NoError(t, err, "Failed to process block header got")
var zeroHash [32]byte
nsh := newState.LatestBlockHeader()
@@ -312,40 +285,36 @@ func TestBlockSignatureSet_OK(t *testing.T) {
validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount)
for i := 0; i < len(validators); i++ {
validators[i] = &ethpb.Validator{
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
Slashed: true,
PublicKey: make([]byte, 32),
WithdrawalCredentials: make([]byte, 32),
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
Slashed: true,
}
}
state, err := stateTrie.InitializeFromProto(&pb.BeaconState{
Validators: validators,
Slot: 10,
LatestBlockHeader: &ethpb.BeaconBlockHeader{Slot: 9},
Fork: &pb.Fork{
PreviousVersion: []byte{0, 0, 0, 0},
CurrentVersion: []byte{0, 0, 0, 0},
},
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
})
require.NoError(t, err)
state := testutil.NewBeaconState()
require.NoError(t, state.SetValidators(validators))
require.NoError(t, state.SetSlot(10))
require.NoError(t, state.SetLatestBlockHeader(&ethpb.BeaconBlockHeader{
Slot: 9,
ProposerIndex: 0,
ParentRoot: make([]byte, 32),
StateRoot: make([]byte, 32),
BodyRoot: make([]byte, 32),
}))
latestBlockSignedRoot, err := stateutil.BlockHeaderRoot(state.LatestBlockHeader())
latestBlockSignedRoot, err := state.LatestBlockHeader().HashTreeRoot()
require.NoError(t, err)
currentEpoch := helpers.CurrentEpoch(state)
priv := bls.RandKey()
pID, err := helpers.BeaconProposerIndex(state)
require.NoError(t, err)
block := &ethpb.SignedBeaconBlock{
Block: &ethpb.BeaconBlock{
ProposerIndex: pID,
Slot: 10,
Body: &ethpb.BeaconBlockBody{
RandaoReveal: []byte{'A', 'B', 'C'},
},
ParentRoot: latestBlockSignedRoot[:],
},
}
block := testutil.NewBeaconBlock()
block.Block.Slot = 10
block.Block.ProposerIndex = pID
block.Block.Body.RandaoReveal = bytesutil.PadTo([]byte{'A', 'B', 'C'}, 96)
block.Block.ParentRoot = latestBlockSignedRoot[:]
block.Signature, err = helpers.ComputeDomainAndSign(state, currentEpoch, block.Block, params.BeaconConfig().DomainBeaconProposer, priv)
require.NoError(t, err)
proposerIdx, err := helpers.BeaconProposerIndex(state)

View File

@@ -38,8 +38,13 @@ import (
func ProcessProposerSlashings(
ctx context.Context,
beaconState *stateTrie.BeaconState,
body *ethpb.BeaconBlockBody,
b *ethpb.SignedBeaconBlock,
) (*stateTrie.BeaconState, error) {
if b.Block == nil || b.Block.Body == nil {
return nil, errors.New("block and block body can't be nil")
}
body := b.Block.Body
var err error
for idx, slashing := range body.ProposerSlashings {
if slashing == nil {
@@ -74,14 +79,14 @@ func VerifyProposerSlashing(
if pIdx != slashing.Header_2.Header.ProposerIndex {
return fmt.Errorf("mismatched indices, received %d == %d", slashing.Header_1.Header.ProposerIndex, slashing.Header_2.Header.ProposerIndex)
}
if proto.Equal(slashing.Header_1, slashing.Header_2) {
if proto.Equal(slashing.Header_1.Header, slashing.Header_2.Header) {
return errors.New("expected slashing headers to differ")
}
proposer, err := beaconState.ValidatorAtIndexReadOnly(slashing.Header_1.Header.ProposerIndex)
if err != nil {
return err
}
if !helpers.IsSlashableValidatorUsingTrie(proposer, helpers.SlotToEpoch(beaconState.Slot())) {
if !helpers.IsSlashableValidatorUsingTrie(proposer, helpers.SlotToEpoch(hSlot)) {
return fmt.Errorf("validator with key %#x is not slashable", proposer.PublicKey())
}
headers := []*ethpb.SignedBeaconBlockHeader{slashing.Header_1, slashing.Header_2}

View File

@@ -10,6 +10,7 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
@@ -39,13 +40,14 @@ func TestProcessProposerSlashings_UnmatchedHeaderSlots(t *testing.T) {
}
require.NoError(t, beaconState.SetSlot(currentSlot))
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
ProposerSlashings: slashings,
},
}
want := "mismatched header slots"
_, err := blocks.ProcessProposerSlashings(context.Background(), beaconState, block.Body)
_, err := blocks.ProcessProposerSlashings(context.Background(), beaconState, b)
assert.ErrorContains(t, want, err)
}
@@ -71,13 +73,14 @@ func TestProcessProposerSlashings_SameHeaders(t *testing.T) {
}
require.NoError(t, beaconState.SetSlot(currentSlot))
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
ProposerSlashings: slashings,
},
}
want := "expected slashing headers to differ"
_, err := blocks.ProcessProposerSlashings(context.Background(), beaconState, block.Body)
_, err := blocks.ProcessProposerSlashings(context.Background(), beaconState, b)
assert.ErrorContains(t, want, err)
}
@@ -97,15 +100,17 @@ func TestProcessProposerSlashings_ValidatorNotSlashable(t *testing.T) {
Header: &ethpb.BeaconBlockHeader{
ProposerIndex: 0,
Slot: 0,
BodyRoot: []byte("foo"),
},
Signature: []byte("A"),
Signature: bytesutil.PadTo([]byte("A"), 96),
},
Header_2: &ethpb.SignedBeaconBlockHeader{
Header: &ethpb.BeaconBlockHeader{
ProposerIndex: 0,
Slot: 0,
BodyRoot: []byte("bar"),
},
Signature: []byte("B"),
Signature: bytesutil.PadTo([]byte("B"), 96),
},
},
}
@@ -115,7 +120,8 @@ func TestProcessProposerSlashings_ValidatorNotSlashable(t *testing.T) {
Slot: currentSlot,
})
require.NoError(t, err)
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
ProposerSlashings: slashings,
},
@@ -124,7 +130,7 @@ func TestProcessProposerSlashings_ValidatorNotSlashable(t *testing.T) {
"validator with key %#x is not slashable",
bytesutil.ToBytes48(beaconState.Validators()[0].PublicKey),
)
_, err = blocks.ProcessProposerSlashings(context.Background(), beaconState, block.Body)
_, err = blocks.ProcessProposerSlashings(context.Background(), beaconState, b)
assert.ErrorContains(t, want, err)
}
@@ -138,7 +144,9 @@ func TestProcessProposerSlashings_AppliesCorrectStatus(t *testing.T) {
Header: &ethpb.BeaconBlockHeader{
ProposerIndex: proposerIdx,
Slot: 0,
StateRoot: []byte("A"),
ParentRoot: make([]byte, 32),
BodyRoot: make([]byte, 32),
StateRoot: bytesutil.PadTo([]byte("A"), 32),
},
}
var err error
@@ -149,7 +157,9 @@ func TestProcessProposerSlashings_AppliesCorrectStatus(t *testing.T) {
Header: &ethpb.BeaconBlockHeader{
ProposerIndex: proposerIdx,
Slot: 0,
StateRoot: []byte("B"),
ParentRoot: make([]byte, 32),
BodyRoot: make([]byte, 32),
StateRoot: bytesutil.PadTo([]byte("B"), 32),
},
}
header2.Signature, err = helpers.ComputeDomainAndSign(beaconState, 0, header2.Header, params.BeaconConfig().DomainBeaconProposer, privKeys[proposerIdx])
@@ -162,13 +172,10 @@ func TestProcessProposerSlashings_AppliesCorrectStatus(t *testing.T) {
},
}
block := &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
ProposerSlashings: slashings,
},
}
block := testutil.NewBeaconBlock()
block.Block.Body.ProposerSlashings = slashings
newState, err := blocks.ProcessProposerSlashings(context.Background(), beaconState, block.Body)
newState, err := blocks.ProcessProposerSlashings(context.Background(), beaconState, block)
require.NoError(t, err)
newStateVals := newState.Validators()
@@ -177,3 +184,125 @@ func TestProcessProposerSlashings_AppliesCorrectStatus(t *testing.T) {
newStateVals[1].ExitEpoch, beaconState.Validators()[1].ExitEpoch)
}
}
func TestVerifyProposerSlashing(t *testing.T) {
type args struct {
beaconState *stateTrie.BeaconState
slashing *ethpb.ProposerSlashing
}
beaconState, sks := testutil.DeterministicGenesisState(t, 2)
currentSlot := uint64(0)
require.NoError(t, beaconState.SetSlot(currentSlot))
tests := []struct {
name string
args args
wantErr string
}{
{
name: "same header, same slot as state",
args: args{
slashing: &ethpb.ProposerSlashing{
Header_1: &ethpb.SignedBeaconBlockHeader{
Header: &ethpb.BeaconBlockHeader{
ProposerIndex: 1,
Slot: currentSlot,
StateRoot: bytesutil.PadTo([]byte{}, 32),
BodyRoot: bytesutil.PadTo([]byte{}, 32),
ParentRoot: bytesutil.PadTo([]byte{}, 32),
},
},
Header_2: &ethpb.SignedBeaconBlockHeader{
Header: &ethpb.BeaconBlockHeader{
ProposerIndex: 1,
Slot: currentSlot,
StateRoot: bytesutil.PadTo([]byte{}, 32),
BodyRoot: bytesutil.PadTo([]byte{}, 32),
ParentRoot: bytesutil.PadTo([]byte{}, 32),
},
},
},
beaconState: beaconState,
},
wantErr: "expected slashing headers to differ",
},
{ // Regression test for https://github.com/sigp/beacon-fuzz/issues/74
name: "same header, different signatures",
args: args{
slashing: &ethpb.ProposerSlashing{
Header_1: &ethpb.SignedBeaconBlockHeader{
Header: &ethpb.BeaconBlockHeader{
ProposerIndex: 1,
Slot: 0,
StateRoot: bytesutil.PadTo([]byte{}, 32),
BodyRoot: bytesutil.PadTo([]byte{}, 32),
ParentRoot: bytesutil.PadTo([]byte{}, 32),
},
Signature: bls.RandKey().Sign([]byte("foo")).Marshal(),
},
Header_2: &ethpb.SignedBeaconBlockHeader{
Header: &ethpb.BeaconBlockHeader{
ProposerIndex: 1,
Slot: 0,
StateRoot: bytesutil.PadTo([]byte{}, 32),
BodyRoot: bytesutil.PadTo([]byte{}, 32),
ParentRoot: bytesutil.PadTo([]byte{}, 32),
},
Signature: bls.RandKey().Sign([]byte("bar")).Marshal(),
},
},
beaconState: beaconState,
},
wantErr: "expected slashing headers to differ",
},
{
name: "slashing in future epoch",
args: args{
slashing: &ethpb.ProposerSlashing{
Header_1: &ethpb.SignedBeaconBlockHeader{
Header: &ethpb.BeaconBlockHeader{
ProposerIndex: 1,
Slot: 65,
StateRoot: bytesutil.PadTo([]byte{}, 32),
BodyRoot: bytesutil.PadTo([]byte{}, 32),
ParentRoot: bytesutil.PadTo([]byte("foo"), 32),
},
},
Header_2: &ethpb.SignedBeaconBlockHeader{
Header: &ethpb.BeaconBlockHeader{
ProposerIndex: 1,
Slot: 65,
StateRoot: bytesutil.PadTo([]byte{}, 32),
BodyRoot: bytesutil.PadTo([]byte{}, 32),
ParentRoot: bytesutil.PadTo([]byte("bar"), 32),
},
},
},
beaconState: beaconState,
},
wantErr: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
testutil.ResetCache()
sk := sks[tt.args.slashing.Header_1.Header.ProposerIndex]
d, err := helpers.Domain(tt.args.beaconState.Fork(), helpers.SlotToEpoch(tt.args.slashing.Header_1.Header.Slot), params.BeaconConfig().DomainBeaconProposer, tt.args.beaconState.GenesisValidatorRoot())
require.NoError(t, err)
if tt.args.slashing.Header_1.Signature == nil {
sr, err := helpers.ComputeSigningRoot(tt.args.slashing.Header_1.Header, d)
require.NoError(t, err)
tt.args.slashing.Header_1.Signature = sk.Sign(sr[:]).Marshal()
}
if tt.args.slashing.Header_2.Signature == nil {
sr, err := helpers.ComputeSigningRoot(tt.args.slashing.Header_2.Header, d)
require.NoError(t, err)
tt.args.slashing.Header_2.Signature = sk.Sign(sr[:]).Marshal()
}
if err := blocks.VerifyProposerSlashing(tt.args.beaconState, tt.args.slashing); (err != nil || tt.wantErr != "") && err.Error() != tt.wantErr {
t.Errorf("VerifyProposerSlashing() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}

View File

@@ -1,6 +1,8 @@
package blocks
import (
"context"
"github.com/pkg/errors"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
@@ -24,14 +26,20 @@ import (
// mix = xor(get_randao_mix(state, epoch), hash(body.randao_reveal))
// state.randao_mixes[epoch % EPOCHS_PER_HISTORICAL_VECTOR] = mix
func ProcessRandao(
ctx context.Context,
beaconState *stateTrie.BeaconState,
body *ethpb.BeaconBlockBody,
b *ethpb.SignedBeaconBlock,
) (*stateTrie.BeaconState, error) {
if b.Block == nil || b.Block.Body == nil {
return nil, errors.New("block and block body can't be nil")
}
body := b.Block.Body
buf, proposerPub, domain, err := randaoSigningData(beaconState)
if err != nil {
return nil, err
}
if err := verifySignature(buf, proposerPub[:], body.RandaoReveal, domain); err != nil {
if err := verifySignature(buf, proposerPub, body.RandaoReveal, domain); err != nil {
return nil, errors.Wrap(err, "could not verify block randao")
}

View File

@@ -2,11 +2,11 @@ package blocks_test
import (
"bytes"
"context"
"encoding/binary"
"testing"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/go-ssz"
"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"
@@ -26,18 +26,19 @@ func TestProcessRandao_IncorrectProposerFailsVerification(t *testing.T) {
binary.LittleEndian.PutUint64(buf, epoch)
domain, err := helpers.Domain(beaconState.Fork(), epoch, params.BeaconConfig().DomainRandao, beaconState.GenesisValidatorRoot())
require.NoError(t, err)
root, err := ssz.HashTreeRoot(&pb.SigningData{ObjectRoot: buf, Domain: domain})
root, err := (&pb.SigningData{ObjectRoot: buf, Domain: domain}).HashTreeRoot()
require.NoError(t, err)
// We make the previous validator's index sign the message instead of the proposer.
epochSignature := privKeys[proposerIdx-1].Sign(root[:])
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
RandaoReveal: epochSignature.Marshal(),
},
}
want := "block randao: signature did not verify"
_, err = blocks.ProcessRandao(beaconState, block.Body)
_, err = blocks.ProcessRandao(context.Background(), beaconState, b)
assert.ErrorContains(t, want, err)
}
@@ -48,15 +49,17 @@ func TestProcessRandao_SignatureVerifiesAndUpdatesLatestStateMixes(t *testing.T)
epochSignature, err := testutil.RandaoReveal(beaconState, epoch, privKeys)
require.NoError(t, err)
block := &ethpb.BeaconBlock{
b := testutil.NewBeaconBlock()
b.Block = &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
RandaoReveal: epochSignature,
},
}
newState, err := blocks.ProcessRandao(
context.Background(),
beaconState,
block.Body,
b,
)
require.NoError(t, err, "Unexpected error processing block randao")
currentEpoch := helpers.CurrentEpoch(beaconState)

View File

@@ -6,7 +6,6 @@ import (
"github.com/pkg/errors"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/go-ssz"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
@@ -21,20 +20,16 @@ func retrieveSignatureSet(signedData []byte, pub []byte, signature []byte, domai
if err != nil {
return nil, errors.Wrap(err, "could not convert bytes to public key")
}
sig, err := bls.SignatureFromBytes(signature)
if err != nil {
return nil, errors.Wrap(err, "could not convert bytes to signature")
}
signingData := &pb.SigningData{
ObjectRoot: signedData,
Domain: domain,
}
root, err := ssz.HashTreeRoot(signingData)
root, err := signingData.HashTreeRoot()
if err != nil {
return nil, errors.Wrap(err, "could not hash container")
}
return &bls.SignatureSet{
Signatures: []bls.Signature{sig},
Signatures: [][]byte{signature},
PublicKeys: []bls.PublicKey{publicKey},
Messages: [][32]byte{root},
}, nil
@@ -53,7 +48,11 @@ func verifySignature(signedData []byte, pub []byte, signature []byte, domain []b
sig := set.Signatures[0]
publicKey := set.PublicKeys[0]
root := set.Messages[0]
if !sig.Verify(publicKey, root[:]) {
rSig, err := bls.SignatureFromBytes(sig)
if err != nil {
return err
}
if !rSig.Verify(publicKey, root[:]) {
return helpers.ErrSigFailedToVerify
}
return nil
@@ -71,7 +70,7 @@ func VerifyBlockSignature(beaconState *stateTrie.BeaconState, block *ethpb.Signe
return err
}
proposerPubKey := proposer.PublicKey
return helpers.VerifyBlockSigningRoot(block.Block, proposerPubKey[:], block.Signature, domain)
return helpers.VerifyBlockSigningRoot(block.Block, proposerPubKey, block.Signature, domain)
}
// BlockSignatureSet retrieves the block signature set from the provided block and its corresponding state.
@@ -98,7 +97,7 @@ func RandaoSignatureSet(beaconState *stateTrie.BeaconState,
if err != nil {
return nil, nil, err
}
set, err := retrieveSignatureSet(buf, proposerPub[:], body.RandaoReveal, domain)
set, err := retrieveSignatureSet(buf, proposerPub, body.RandaoReveal, domain)
if err != nil {
return nil, nil, err
}
@@ -130,35 +129,30 @@ func createAttestationSignatureSet(ctx context.Context, beaconState *stateTrie.B
return nil, nil
}
sigs := make([]bls.Signature, len(atts))
sigs := make([][]byte, len(atts))
pks := make([]bls.PublicKey, len(atts))
msgs := make([][32]byte, len(atts))
for i, a := range atts {
sig, err := bls.SignatureFromBytes(a.Signature)
if err != nil {
return nil, err
}
sigs[i] = sig
sigs[i] = a.Signature
c, err := helpers.BeaconCommitteeFromState(beaconState, a.Data.Slot, a.Data.CommitteeIndex)
if err != nil {
return nil, err
}
ia := attestationutil.ConvertToIndexed(ctx, a, c)
if err := attestationutil.IsValidAttestationIndices(ctx, ia); err != nil {
return nil, err
}
indices := ia.AttestingIndices
var pk bls.PublicKey
pubkeys := make([][]byte, len(indices))
for i := 0; i < len(indices); i++ {
pubkeyAtIdx := beaconState.PubkeyAtIndex(indices[i])
p, err := bls.PublicKeyFromBytes(pubkeyAtIdx[:])
if err != nil {
return nil, errors.Wrap(err, "could not deserialize validator public key")
}
if pk == nil {
pk = p
} else {
pk.Aggregate(p)
}
pubkeys[i] = pubkeyAtIdx[:]
}
pks[i] = pk
aggP, err := bls.AggregatePublicKeys(pubkeys)
if err != nil {
return nil, err
}
pks[i] = aggP
root, err := helpers.ComputeSigningRoot(ia.Data, domain)
if err != nil {

View File

@@ -41,8 +41,8 @@ func runBlockHeaderTest(t *testing.T, config string) {
postSSZExists := true
if err != nil && strings.Contains(err.Error(), "could not locate file") {
postSSZExists = false
} else if err != nil {
t.Fatal(err)
} else {
require.NoError(t, err)
}
// Spectest blocks are not signed, so we'll call NoVerify to skip sig verification.

View File

@@ -1,13 +1,11 @@
package spectest
import (
"context"
"path"
"testing"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/shared/params/spectest"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
@@ -26,9 +24,7 @@ func runDepositTest(t *testing.T, config string) {
require.NoError(t, deposit.UnmarshalSSZ(depositFile), "Failed to unmarshal")
body := &ethpb.BeaconBlockBody{Deposits: []*ethpb.Deposit{deposit}}
testutil.RunBlockOperationTest(t, folderPath, body, func(ctx context.Context, state *state.BeaconState, body *ethpb.BeaconBlockBody) (*state.BeaconState, error) {
return blocks.ProcessDeposits(ctx, state, body.Deposits)
})
testutil.RunBlockOperationTest(t, folderPath, body, blocks.ProcessDeposits)
})
}
}

View File

@@ -16,7 +16,6 @@ go_library(
"//shared/params:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
],
)
@@ -33,6 +32,7 @@ go_test(
"//beacon-chain/state:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//shared/params:go_default_library",
"//shared/testutil:go_default_library",
"//shared/testutil/assert:go_default_library",
"//shared/testutil/require:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",

View File

@@ -10,7 +10,6 @@ import (
"github.com/pkg/errors"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/go-ssz"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/core/validators"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
@@ -46,7 +45,7 @@ func (s sortableIndices) Less(i, j int) bool {
// def get_attesting_balance(state: BeaconState, attestations: List[PendingAttestation]) -> Gwei:
// return get_total_balance(state, get_unslashed_attesting_indices(state, attestations))
func AttestingBalance(state *stateTrie.BeaconState, atts []*pb.PendingAttestation) (uint64, error) {
indices, err := unslashedAttestingIndices(state, atts)
indices, err := UnslashedAttestingIndices(state, atts)
if err != nil {
return 0, errors.Wrap(err, "could not get attesting indices")
}
@@ -148,10 +147,11 @@ func ProcessRegistryUpdates(state *stateTrie.BeaconState) (*stateTrie.BeaconStat
// def process_slashings(state: BeaconState) -> None:
// epoch = get_current_epoch(state)
// total_balance = get_total_active_balance(state)
// adjusted_total_slashing_balance = min(sum(state.slashings) * PROPORTIONAL_SLASHING_MULTIPLIER, total_balance)
// for index, validator in enumerate(state.validators):
// if validator.slashed and epoch + EPOCHS_PER_SLASHINGS_VECTOR // 2 == validator.withdrawable_epoch:
// increment = EFFECTIVE_BALANCE_INCREMENT # Factored out from penalty numerator to avoid uint64 overflow
// penalty_numerator = validator.effective_balance // increment * min(sum(state.slashings) * 3, total_balance)
// penalty_numerator = validator.effective_balance // increment * adjusted_total_slashing_balance
// penalty = penalty_numerator // total_balance * increment
// decrease_balance(state, ValidatorIndex(index), penalty)
func ProcessSlashings(state *stateTrie.BeaconState) (*stateTrie.BeaconState, error) {
@@ -174,10 +174,10 @@ func ProcessSlashings(state *stateTrie.BeaconState) (*stateTrie.BeaconState, err
// a callback is used here to apply the following actions to all validators
// below equally.
increment := params.BeaconConfig().EffectiveBalanceIncrement
minSlashing := mathutil.Min(totalSlashing*params.BeaconConfig().ProportionalSlashingMultiplier, totalBalance)
err = state.ApplyToEveryValidator(func(idx int, val *ethpb.Validator) (bool, error) {
correctEpoch := (currentEpoch + exitLength/2) == val.WithdrawableEpoch
if val.Slashed && correctEpoch {
minSlashing := mathutil.Min(totalSlashing*3, totalBalance)
penaltyNumerator := val.EffectiveBalance / increment * minSlashing
penalty := penaltyNumerator / totalBalance * increment
if err := helpers.DecreaseBalance(state, uint64(idx), penalty); err != nil {
@@ -311,7 +311,7 @@ func ProcessFinalUpdates(state *stateTrie.BeaconState) (*stateTrie.BeaconState,
BlockRoots: state.BlockRoots(),
StateRoots: state.StateRoots(),
}
batchRoot, err := ssz.HashTreeRoot(historicalBatch)
batchRoot, err := historicalBatch.HashTreeRoot()
if err != nil {
return nil, errors.Wrap(err, "could not hash historical batch")
}
@@ -330,7 +330,7 @@ func ProcessFinalUpdates(state *stateTrie.BeaconState) (*stateTrie.BeaconState,
return state, nil
}
// unslashedAttestingIndices returns all the attesting indices from a list of attestations,
// UnslashedAttestingIndices returns all the attesting indices from a list of attestations,
// it sorts the indices and filters out the slashed ones.
//
// Spec pseudocode definition:
@@ -340,7 +340,7 @@ func ProcessFinalUpdates(state *stateTrie.BeaconState) (*stateTrie.BeaconState,
// for a in attestations:
// output = output.union(get_attesting_indices(state, a.data, a.aggregation_bits))
// return set(filter(lambda index: not state.validators[index].slashed, output))
func unslashedAttestingIndices(state *stateTrie.BeaconState, atts []*pb.PendingAttestation) ([]uint64, error) {
func UnslashedAttestingIndices(state *stateTrie.BeaconState, atts []*pb.PendingAttestation) ([]uint64, error) {
var setIndices []uint64
seen := make(map[uint64]bool)

View File

@@ -18,5 +18,6 @@ func TestFuzzFinalUpdates_10000(t *testing.T) {
s, err := beaconstate.InitializeFromProtoUnsafe(base)
require.NoError(t, err)
_, err = ProcessFinalUpdates(s)
_ = err
}
}

View File

@@ -1,16 +1,17 @@
package epoch
package epoch_test
import (
"bytes"
"testing"
"github.com/gogo/protobuf/proto"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/go-bitfield"
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
)
@@ -20,8 +21,8 @@ func TestUnslashedAttestingIndices_CanSortAndFilter(t *testing.T) {
atts := make([]*pb.PendingAttestation, 2)
for i := 0; i < len(atts); i++ {
atts[i] = &pb.PendingAttestation{
Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{},
Target: &ethpb.Checkpoint{Epoch: 0},
Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{Root: make([]byte, 32)},
Target: &ethpb.Checkpoint{Epoch: 0, Root: make([]byte, 32)},
},
AggregationBits: bitfield.Bitlist{0xFF, 0xFF, 0xFF},
}
@@ -42,7 +43,7 @@ func TestUnslashedAttestingIndices_CanSortAndFilter(t *testing.T) {
state, err := state.InitializeFromProto(base)
require.NoError(t, err)
indices, err := unslashedAttestingIndices(state, atts)
indices, err := epoch.UnslashedAttestingIndices(state, atts)
require.NoError(t, err)
for i := 0; i < len(indices)-1; i++ {
if indices[i] >= indices[i+1] {
@@ -55,7 +56,7 @@ func TestUnslashedAttestingIndices_CanSortAndFilter(t *testing.T) {
validators = state.Validators()
validators[slashedValidator].Slashed = true
require.NoError(t, state.SetValidators(validators))
indices, err = unslashedAttestingIndices(state, atts)
indices, err = epoch.UnslashedAttestingIndices(state, atts)
require.NoError(t, err)
for i := 0; i < len(indices); i++ {
assert.NotEqual(t, slashedValidator, indices[i], "Slashed validator %d is not filtered", slashedValidator)
@@ -67,7 +68,7 @@ func TestUnslashedAttestingIndices_DuplicatedAttestations(t *testing.T) {
atts := make([]*pb.PendingAttestation, 5)
for i := 0; i < len(atts); i++ {
atts[i] = &pb.PendingAttestation{
Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{},
Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{Root: make([]byte, 32)},
Target: &ethpb.Checkpoint{Epoch: 0}},
AggregationBits: bitfield.Bitlist{0xFF, 0xFF, 0xFF},
}
@@ -88,7 +89,7 @@ func TestUnslashedAttestingIndices_DuplicatedAttestations(t *testing.T) {
state, err := state.InitializeFromProto(base)
require.NoError(t, err)
indices, err := unslashedAttestingIndices(state, atts)
indices, err := epoch.UnslashedAttestingIndices(state, atts)
require.NoError(t, err)
for i := 0; i < len(indices)-1; i++ {
@@ -105,8 +106,8 @@ func TestAttestingBalance_CorrectBalance(t *testing.T) {
for i := 0; i < len(atts); i++ {
atts[i] = &pb.PendingAttestation{
Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{},
Source: &ethpb.Checkpoint{},
Target: &ethpb.Checkpoint{Root: make([]byte, 32)},
Source: &ethpb.Checkpoint{Root: make([]byte, 32)},
Slot: uint64(i),
},
AggregationBits: bitfield.Bitlist{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
@@ -134,7 +135,7 @@ func TestAttestingBalance_CorrectBalance(t *testing.T) {
state, err := state.InitializeFromProto(base)
require.NoError(t, err)
balance, err := AttestingBalance(state, atts)
balance, err := epoch.AttestingBalance(state, atts)
require.NoError(t, err)
wanted := 256 * params.BeaconConfig().MaxEffectiveBalance
assert.Equal(t, wanted, balance)
@@ -159,9 +160,9 @@ func TestBaseReward_AccurateRewards(t *testing.T) {
}
state, err := state.InitializeFromProto(base)
require.NoError(t, err)
c, err := BaseReward(state, 0)
c, err := epoch.BaseReward(state, 0)
require.NoError(t, err)
assert.Equal(t, tt.c, c, "BaseReward(%d)", tt.a)
assert.Equal(t, tt.c, c, "epoch.BaseReward(%d)", tt.a)
}
}
@@ -174,7 +175,7 @@ func TestProcessSlashings_NotSlashed(t *testing.T) {
}
s, err := state.InitializeFromProto(base)
require.NoError(t, err)
newState, err := ProcessSlashings(s)
newState, err := epoch.ProcessSlashings(s)
require.NoError(t, err)
wanted := params.BeaconConfig().MaxEffectiveBalance
assert.Equal(t, wanted, newState.Balances()[0], "Unexpected slashed balance")
@@ -252,7 +253,7 @@ func TestProcessSlashings_SlashedLess(t *testing.T) {
original := proto.Clone(tt.state)
s, err := state.InitializeFromProto(tt.state)
require.NoError(t, err)
newState, err := ProcessSlashings(s)
newState, err := epoch.ProcessSlashings(s)
require.NoError(t, err)
assert.Equal(t, tt.want, newState.Balances()[0], "ProcessSlashings({%v}) = newState; newState.Balances[0] = %d", original, newState.Balances()[0])
})
@@ -260,7 +261,7 @@ func TestProcessSlashings_SlashedLess(t *testing.T) {
}
func TestProcessFinalUpdates_CanProcess(t *testing.T) {
s := buildState(params.BeaconConfig().SlotsPerHistoricalRoot-1, params.BeaconConfig().SlotsPerEpoch)
s := buildState(t, params.BeaconConfig().SlotsPerHistoricalRoot-1, params.BeaconConfig().SlotsPerEpoch)
ce := helpers.CurrentEpoch(s)
ne := ce + 1
require.NoError(t, s.SetEth1DataVotes([]*ethpb.Eth1Data{}))
@@ -275,7 +276,7 @@ func TestProcessFinalUpdates_CanProcess(t *testing.T) {
mixes := s.RandaoMixes()
mixes[ce] = []byte{'A'}
require.NoError(t, s.SetRandaoMixes(mixes))
newS, err := ProcessFinalUpdates(s)
newS, err := epoch.ProcessFinalUpdates(s)
require.NoError(t, err)
// Verify effective balance is correctly updated.
@@ -286,9 +287,9 @@ func TestProcessFinalUpdates_CanProcess(t *testing.T) {
assert.Equal(t, newS.Slashings()[ce], newS.Slashings()[ne], "Unexpected slashed balance")
// Verify randao is correctly updated in the right position.
if mix, err := newS.RandaoMixAtIndex(ne); err != nil || bytes.Equal(mix, params.BeaconConfig().ZeroHash[:]) {
t.Error("latest RANDAO still zero hashes")
}
mix, err := newS.RandaoMixAtIndex(ne)
assert.NoError(t, err)
assert.DeepNotEqual(t, params.BeaconConfig().ZeroHash[:], mix, "latest RANDAO still zero hashes")
// Verify historical root accumulator was appended.
assert.Equal(t, 1, len(newS.HistoricalRoots()), "Unexpected slashed balance")
@@ -306,11 +307,11 @@ func TestProcessRegistryUpdates_NoRotation(t *testing.T) {
params.BeaconConfig().MaxEffectiveBalance,
params.BeaconConfig().MaxEffectiveBalance,
},
FinalizedCheckpoint: &ethpb.Checkpoint{},
FinalizedCheckpoint: &ethpb.Checkpoint{Root: make([]byte, 32)},
}
state, err := state.InitializeFromProto(base)
require.NoError(t, err)
newState, err := ProcessRegistryUpdates(state)
newState, err := epoch.ProcessRegistryUpdates(state)
require.NoError(t, err)
for i, validator := range newState.Validators() {
assert.Equal(t, params.BeaconConfig().MaxSeedLookahead, validator.ExitEpoch, "Could not update registry %d", i)
@@ -320,7 +321,7 @@ func TestProcessRegistryUpdates_NoRotation(t *testing.T) {
func TestProcessRegistryUpdates_EligibleToActivate(t *testing.T) {
base := &pb.BeaconState{
Slot: 5 * params.BeaconConfig().SlotsPerEpoch,
FinalizedCheckpoint: &ethpb.Checkpoint{Epoch: 6},
FinalizedCheckpoint: &ethpb.Checkpoint{Epoch: 6, Root: make([]byte, 32)},
}
limit, err := helpers.ValidatorChurnLimit(0)
require.NoError(t, err)
@@ -332,8 +333,9 @@ func TestProcessRegistryUpdates_EligibleToActivate(t *testing.T) {
})
}
state, err := state.InitializeFromProto(base)
require.NoError(t, err)
currentEpoch := helpers.CurrentEpoch(state)
newState, err := ProcessRegistryUpdates(state)
newState, err := epoch.ProcessRegistryUpdates(state)
require.NoError(t, err)
for i, validator := range newState.Validators() {
assert.Equal(t, currentEpoch+1, validator.ActivationEligibilityEpoch, "Could not update registry %d, unexpected activation eligibility epoch", i)
@@ -357,11 +359,11 @@ func TestProcessRegistryUpdates_ActivationCompletes(t *testing.T) {
{ExitEpoch: params.BeaconConfig().MaxSeedLookahead,
ActivationEpoch: 5 + params.BeaconConfig().MaxSeedLookahead + 1},
},
FinalizedCheckpoint: &ethpb.Checkpoint{},
FinalizedCheckpoint: &ethpb.Checkpoint{Root: make([]byte, 32)},
}
state, err := state.InitializeFromProto(base)
require.NoError(t, err)
newState, err := ProcessRegistryUpdates(state)
newState, err := epoch.ProcessRegistryUpdates(state)
require.NoError(t, err)
for i, validator := range newState.Validators() {
assert.Equal(t, params.BeaconConfig().MaxSeedLookahead, validator.ExitEpoch, "Could not update registry %d, unexpected exit slot", i)
@@ -381,11 +383,11 @@ func TestProcessRegistryUpdates_ValidatorsEjected(t *testing.T) {
EffectiveBalance: params.BeaconConfig().EjectionBalance - 1,
},
},
FinalizedCheckpoint: &ethpb.Checkpoint{},
FinalizedCheckpoint: &ethpb.Checkpoint{Root: make([]byte, 32)},
}
state, err := state.InitializeFromProto(base)
require.NoError(t, err)
newState, err := ProcessRegistryUpdates(state)
newState, err := epoch.ProcessRegistryUpdates(state)
require.NoError(t, err)
for i, validator := range newState.Validators() {
assert.Equal(t, params.BeaconConfig().MaxSeedLookahead+1, validator.ExitEpoch, "Could not update registry %d, unexpected exit slot", i)
@@ -393,11 +395,11 @@ func TestProcessRegistryUpdates_ValidatorsEjected(t *testing.T) {
}
func TestProcessRegistryUpdates_CanExits(t *testing.T) {
epoch := uint64(5)
exitEpoch := helpers.ActivationExitEpoch(epoch)
e := uint64(5)
exitEpoch := helpers.ActivationExitEpoch(e)
minWithdrawalDelay := params.BeaconConfig().MinValidatorWithdrawabilityDelay
base := &pb.BeaconState{
Slot: epoch * params.BeaconConfig().SlotsPerEpoch,
Slot: e * params.BeaconConfig().SlotsPerEpoch,
Validators: []*ethpb.Validator{
{
ExitEpoch: exitEpoch,
@@ -406,18 +408,18 @@ func TestProcessRegistryUpdates_CanExits(t *testing.T) {
ExitEpoch: exitEpoch,
WithdrawableEpoch: exitEpoch + minWithdrawalDelay},
},
FinalizedCheckpoint: &ethpb.Checkpoint{},
FinalizedCheckpoint: &ethpb.Checkpoint{Root: make([]byte, 32)},
}
state, err := state.InitializeFromProto(base)
require.NoError(t, err)
newState, err := ProcessRegistryUpdates(state)
newState, err := epoch.ProcessRegistryUpdates(state)
require.NoError(t, err)
for i, validator := range newState.Validators() {
assert.Equal(t, exitEpoch, validator.ExitEpoch, "Could not update registry %d, unexpected exit slot", i)
}
}
func buildState(slot uint64, validatorCount uint64) *state.BeaconState {
func buildState(t testing.TB, slot uint64, validatorCount uint64) *state.BeaconState {
validators := make([]*ethpb.Validator, validatorCount)
for i := 0; i < len(validators); i++ {
validators[i] = &ethpb.Validator{
@@ -443,19 +445,15 @@ func buildState(slot uint64, validatorCount uint64) *state.BeaconState {
for i := 0; i < len(latestRandaoMixes); i++ {
latestRandaoMixes[i] = params.BeaconConfig().ZeroHash[:]
}
s, err := state.InitializeFromProto(&pb.BeaconState{
Slot: slot,
Balances: validatorBalances,
Validators: validators,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
Slashings: make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector),
BlockRoots: make([][]byte, params.BeaconConfig().SlotsPerEpoch*10),
FinalizedCheckpoint: &ethpb.Checkpoint{},
PreviousJustifiedCheckpoint: &ethpb.Checkpoint{},
CurrentJustifiedCheckpoint: &ethpb.Checkpoint{},
})
if err != nil {
panic(err)
s := testutil.NewBeaconState()
if err := s.SetSlot(slot); err != nil {
t.Error(err)
}
if err := s.SetBalances(validatorBalances); err != nil {
t.Error(err)
}
if err := s.SetValidators(validators); err != nil {
t.Error(err)
}
return s
}

View File

@@ -178,8 +178,7 @@ func TestProcessAttestations(t *testing.T) {
for i := 0; i < len(pVals); i++ {
pVals[i] = &precompute.Validator{CurrentEpochEffectiveBalance: 100}
}
pBal := &precompute.Balance{}
pVals, pBal, err = precompute.ProcessAttestations(context.Background(), beaconState, pVals, pBal)
pVals, _, err = precompute.ProcessAttestations(context.Background(), beaconState, pVals, &precompute.Balance{})
require.NoError(t, err)
committee, err := helpers.BeaconCommitteeFromState(beaconState, att1.Data.Slot, att1.Data.CommitteeIndex)

View File

@@ -49,7 +49,11 @@ import (
// if all(bits[0:2]) and old_current_justified_checkpoint.epoch + 1 == current_epoch:
// state.finalized_checkpoint = old_current_justified_checkpoint
func ProcessJustificationAndFinalizationPreCompute(state *stateTrie.BeaconState, pBal *Balance) (*stateTrie.BeaconState, error) {
if state.Slot() <= helpers.StartSlot(2) {
canProcessSlot, err := helpers.StartSlot(2 /*epoch*/)
if err != nil {
return nil, err
}
if state.Slot() <= canProcessSlot {
return state, nil
}

View File

@@ -30,7 +30,7 @@ func TestProcessJustificationAndFinalizationPreCompute_ConsecutiveEpochs(t *test
Epoch: 0,
Root: params.BeaconConfig().ZeroHash[:],
},
FinalizedCheckpoint: &ethpb.Checkpoint{},
FinalizedCheckpoint: &ethpb.Checkpoint{Root: make([]byte, 32)},
JustificationBits: bitfield.Bitvector4{0x0F}, // 0b1111
Validators: []*ethpb.Validator{{ExitEpoch: e}, {ExitEpoch: e}, {ExitEpoch: e}, {ExitEpoch: e}},
Balances: []uint64{a, a, a, a}, // validator total balance should be 128000000000
@@ -67,7 +67,7 @@ func TestProcessJustificationAndFinalizationPreCompute_JustifyCurrentEpoch(t *te
Epoch: 0,
Root: params.BeaconConfig().ZeroHash[:],
},
FinalizedCheckpoint: &ethpb.Checkpoint{},
FinalizedCheckpoint: &ethpb.Checkpoint{Root: make([]byte, 32)},
JustificationBits: bitfield.Bitvector4{0x03}, // 0b0011
Validators: []*ethpb.Validator{{ExitEpoch: e}, {ExitEpoch: e}, {ExitEpoch: e}, {ExitEpoch: e}},
Balances: []uint64{a, a, a, a}, // validator total balance should be 128000000000
@@ -107,7 +107,7 @@ func TestProcessJustificationAndFinalizationPreCompute_JustifyPrevEpoch(t *testi
JustificationBits: bitfield.Bitvector4{0x03}, // 0b0011
Validators: []*ethpb.Validator{{ExitEpoch: e}, {ExitEpoch: e}, {ExitEpoch: e}, {ExitEpoch: e}},
Balances: []uint64{a, a, a, a}, // validator total balance should be 128000000000
BlockRoots: blockRoots, FinalizedCheckpoint: &ethpb.Checkpoint{},
BlockRoots: blockRoots, FinalizedCheckpoint: &ethpb.Checkpoint{Root: make([]byte, 32)},
}
state, err := beaconstate.InitializeFromProto(base)
require.NoError(t, err)

View File

@@ -24,8 +24,8 @@ func TestProcessRewardsAndPenaltiesPrecompute(t *testing.T) {
for i := 0; i < len(atts); i++ {
atts[i] = &pb.PendingAttestation{
Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{},
Source: &ethpb.Checkpoint{},
Target: &ethpb.Checkpoint{Root: make([]byte, 32)},
Source: &ethpb.Checkpoint{Root: make([]byte, 32)},
},
AggregationBits: bitfield.Bitlist{0xC0, 0xC0, 0xC0, 0xC0, 0x01},
InclusionDelay: 1,
@@ -202,7 +202,7 @@ func TestAttestationDeltas_ZeroInclusionDelay(t *testing.T) {
pVals, pBal, err := New(context.Background(), state)
require.NoError(t, err)
pVals, pBal, err = ProcessAttestations(context.Background(), state, pVals, pBal)
_, _, err = ProcessAttestations(context.Background(), state, pVals, pBal)
require.ErrorContains(t, "attestation with inclusion delay of 0", err)
}
@@ -214,8 +214,8 @@ func TestProcessRewardsAndPenaltiesPrecompute_SlashedInactivePenalty(t *testing.
for i := 0; i < len(atts); i++ {
atts[i] = &pb.PendingAttestation{
Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{},
Source: &ethpb.Checkpoint{},
Target: &ethpb.Checkpoint{Root: make([]byte, 32)},
Source: &ethpb.Checkpoint{Root: make([]byte, 32)},
},
AggregationBits: bitfield.Bitlist{0xC0, 0xC0, 0xC0, 0xC0, 0x01},
InclusionDelay: 1,
@@ -287,9 +287,9 @@ func buildState(slot uint64, validatorCount uint64) *pb.BeaconState {
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
Slashings: make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector),
BlockRoots: make([][]byte, params.BeaconConfig().SlotsPerEpoch*10),
FinalizedCheckpoint: &ethpb.Checkpoint{},
PreviousJustifiedCheckpoint: &ethpb.Checkpoint{},
CurrentJustifiedCheckpoint: &ethpb.Checkpoint{},
FinalizedCheckpoint: &ethpb.Checkpoint{Root: make([]byte, 32)},
PreviousJustifiedCheckpoint: &ethpb.Checkpoint{Root: make([]byte, 32)},
CurrentJustifiedCheckpoint: &ethpb.Checkpoint{Root: make([]byte, 32)},
}
}

View File

@@ -21,7 +21,7 @@ func ProcessSlashingsPrecompute(state *stateTrie.BeaconState, pBal *Balance) err
totalSlashing += slashing
}
minSlashing := mathutil.Min(totalSlashing*3, pBal.ActiveCurrentEpoch)
minSlashing := mathutil.Min(totalSlashing*params.BeaconConfig().ProportionalSlashingMultiplier, pBal.ActiveCurrentEpoch)
epochToWithdraw := currentEpoch + exitLength/2
increment := params.BeaconConfig().EffectiveBalanceIncrement
validatorFunc := func(idx int, val *ethpb.Validator) (bool, error) {

View File

@@ -26,14 +26,16 @@ var deltaFiles = []string{"source_deltas.yaml", "target_deltas.yaml", "head_delt
func runPrecomputeRewardsAndPenaltiesTests(t *testing.T, config string) {
require.NoError(t, spectest.SetConfig(t, config))
testPath := "rewards/core/pyspec_tests"
testFolders, testsFolderPath := testutil.TestFolders(t, config, testPath)
for _, folder := range testFolders {
helpers.ClearCache()
t.Run(folder.Name(), func(t *testing.T) {
folderPath := path.Join(testsFolderPath, folder.Name())
runPrecomputeRewardsAndPenaltiesTest(t, folderPath)
})
testPaths := []string{"rewards/basic/pyspec_tests", "rewards/leak/pyspec_tests", "rewards/random/pyspec_tests"}
for _, testPath := range testPaths {
testFolders, testsFolderPath := testutil.TestFolders(t, config, testPath)
for _, folder := range testFolders {
helpers.ClearCache()
t.Run(folder.Name(), func(t *testing.T) {
folderPath := path.Join(testsFolderPath, folder.Name())
runPrecomputeRewardsAndPenaltiesTest(t, folderPath)
})
}
}
}
@@ -55,7 +57,7 @@ func runPrecomputeRewardsAndPenaltiesTest(t *testing.T, testFolderPath string) {
require.NoError(t, err)
pRewards, err := precompute.ProposersDelta(preBeaconState, bp, vp)
require.NoError(t, err)
if len(rewards) != len(penalties) && len(pRewards) != len(pRewards) {
if len(rewards) != len(penalties) && len(rewards) != len(pRewards) {
t.Fatal("Incorrect lengths")
}
for i, reward := range rewards {

View File

@@ -0,0 +1,9 @@
package spectest
import (
"testing"
)
func TestRewardsAndPenaltiesMainnet(t *testing.T) {
runRewardsAndPenaltiesTests(t, "mainnet")
}

View File

@@ -4,5 +4,8 @@ go_library(
name = "go_default_library",
srcs = ["event.go"],
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/core/feed",
visibility = ["//beacon-chain:__subpackages__"],
visibility = [
"//beacon-chain:__subpackages__",
"//shared:__subpackages__",
],
)

View File

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

View File

@@ -18,12 +18,13 @@ go_library(
visibility = [
"//beacon-chain:__subpackages__",
"//endtoend/evaluators:__pkg__",
"//fuzz:__pkg__",
"//shared/attestationutil:__pkg__",
"//shared/benchutil/benchmark_files:__subpackages__",
"//shared/depositutil:__pkg__",
"//shared/interop:__pkg__",
"//shared/keystore:__pkg__",
"//shared/depositutil:__pkg__",
"//shared/p2putils:__pkg__",
"//shared/attestationutil:__pkg__",
"//shared/testutil:__pkg__",
"//slasher:__subpackages__",
"//tools:__subpackages__",
@@ -32,14 +33,16 @@ go_library(
deps = [
"//beacon-chain/cache:go_default_library",
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/stateutil:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//shared/bls:go_default_library",
"//shared/bytesutil:go_default_library",
"//shared/featureconfig:go_default_library",
"//shared/hashutil:go_default_library",
"//shared/mathutil:go_default_library",
"//shared/params:go_default_library",
"//shared/roughtime:go_default_library",
"//shared/sliceutil:go_default_library",
"//shared/timeutils:go_default_library",
"@com_github_ferranbt_fastssz//:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
@@ -66,17 +69,16 @@ go_test(
deps = [
"//beacon-chain/cache:go_default_library",
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/stateutil:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//shared/bls:go_default_library",
"//shared/bytesutil:go_default_library",
"//shared/hashutil:go_default_library",
"//shared/params:go_default_library",
"//shared/roughtime:go_default_library",
"//shared/sliceutil:go_default_library",
"//shared/testutil:go_default_library",
"//shared/testutil/assert:go_default_library",
"//shared/testutil/require:go_default_library",
"//shared/timeutils:go_default_library",
"@com_github_google_gofuzz//:go_default_library",
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",

View File

@@ -6,32 +6,12 @@ import (
"time"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/hashutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/roughtime"
"github.com/prysmaticlabs/prysm/shared/timeutils"
)
// SlotSignature returns the signed signature of the hash tree root of input slot.
//
// Spec pseudocode definition:
// def get_slot_signature(state: BeaconState, slot: Slot, privkey: int) -> BLSSignature:
// domain = get_domain(state, DOMAIN_SELECTION_PROOF, compute_epoch_at_slot(slot))
// signing_root = compute_signing_root(slot, domain)
// return bls.Sign(privkey, signing_root)
func SlotSignature(state *stateTrie.BeaconState, slot uint64, privKey bls.SecretKey) (bls.Signature, error) {
d, err := Domain(state.Fork(), CurrentEpoch(state), params.BeaconConfig().DomainBeaconAttester, state.GenesisValidatorRoot())
if err != nil {
return nil, err
}
s, err := ComputeSigningRoot(slot, d)
if err != nil {
return nil, err
}
return privKey.Sign(s[:]), nil
}
// IsAggregator returns true if the signature is from the input validator. The committee
// count is provided as an argument rather than direct implementation from spec. Having
// committee count as an argument allows cheaper computation at run time.
@@ -124,7 +104,13 @@ func ComputeSubnetFromCommitteeAndSlot(activeValCount, comIdx, attSlot uint64) u
// valid_attestation_slot = 98
// In the attestation must be within the range of 95 to 100 in the example above.
func ValidateAttestationTime(attSlot uint64, genesisTime time.Time) error {
attTime := genesisTime.Add(time.Duration(attSlot*params.BeaconConfig().SecondsPerSlot) * time.Second)
if err := ValidateSlotClock(attSlot, uint64(genesisTime.Unix())); err != nil {
return err
}
attTime, err := SlotToTime(uint64(genesisTime.Unix()), attSlot)
if err != nil {
return err
}
currentSlot := SlotsSince(genesisTime)
// A clock disparity allows for minor tolerances outside of the expected range. This value is
@@ -133,7 +119,7 @@ func ValidateAttestationTime(attSlot uint64, genesisTime time.Time) error {
// An attestation cannot be from the future, so the upper bounds is set to now, with a minor
// tolerance for peer clock disparity.
upperBounds := roughtime.Now().Add(clockDisparity)
upperBounds := timeutils.Now().Add(clockDisparity)
// An attestation cannot be older than the current slot - attestation propagation slot range
// with a minor tolerance for peer clock disparity.
@@ -141,9 +127,11 @@ func ValidateAttestationTime(attSlot uint64, genesisTime time.Time) error {
if currentSlot > params.BeaconNetworkConfig().AttestationPropagationSlotRange {
lowerBoundsSlot = currentSlot - params.BeaconNetworkConfig().AttestationPropagationSlotRange
}
lowerBounds := genesisTime.Add(
time.Duration(lowerBoundsSlot*params.BeaconConfig().SecondsPerSlot) * time.Second,
).Add(-clockDisparity)
lowerTime, err := SlotToTime(uint64(genesisTime.Unix()), lowerBoundsSlot)
if err != nil {
return err
}
lowerBounds := lowerTime.Add(-clockDisparity)
// Verify attestation slot within the time range.
if attTime.Before(lowerBounds) || attTime.After(upperBounds) {

View File

@@ -12,33 +12,12 @@ import (
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/roughtime"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
"github.com/prysmaticlabs/prysm/shared/timeutils"
)
func TestAttestation_SlotSignature(t *testing.T) {
priv := bls.RandKey()
pub := priv.PublicKey()
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{
Validators: []*ethpb.Validator{{PublicKey: pub.Marshal()}},
Fork: &pb.Fork{
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
Epoch: 0,
},
Slot: 100,
})
require.NoError(t, err)
slot := uint64(101)
sig, err := helpers.SlotSignature(state, slot, priv)
require.NoError(t, err)
require.NoError(t, helpers.ComputeDomainVerifySigningRoot(state, 0, helpers.CurrentEpoch(state), slot,
params.BeaconConfig().DomainBeaconAttester, sig.Marshal()))
}
func TestAttestation_IsAggregator(t *testing.T) {
t.Run("aggregator", func(t *testing.T) {
beaconState, privKeys := testutil.DeterministicGenesisState(t, 100)
@@ -89,7 +68,7 @@ func TestAttestation_AggregateSignature(t *testing.T) {
for i := 0; i < 100; i++ {
priv := bls.RandKey()
pub := priv.PublicKey()
sig := priv.Sign(msg[:])
sig := priv.Sign(msg)
pubkeys = append(pubkeys, pub)
att := &ethpb.Attestation{Signature: sig.Marshal()}
atts = append(atts, att)
@@ -154,77 +133,83 @@ func Test_ValidateAttestationTime(t *testing.T) {
genesisTime time.Time
}
tests := []struct {
name string
args args
wantErr bool
name string
args args
wantedErr string
}{
{
name: "attestation.slot == current_slot",
args: args{
attSlot: 15,
genesisTime: roughtime.Now().Add(-15 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second),
genesisTime: timeutils.Now().Add(-15 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second),
},
wantErr: false,
},
{
name: "attestation.slot == current_slot, received in middle of slot",
args: args{
attSlot: 15,
genesisTime: roughtime.Now().Add(
genesisTime: timeutils.Now().Add(
-15 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second,
).Add(-(time.Duration(params.BeaconConfig().SecondsPerSlot/2) * time.Second)),
},
wantErr: false,
},
{
name: "attestation.slot == current_slot, received 200ms early",
args: args{
attSlot: 16,
genesisTime: roughtime.Now().Add(
genesisTime: timeutils.Now().Add(
-16 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second,
).Add(-200 * time.Millisecond),
},
wantErr: false,
},
{
name: "attestation.slot > current_slot",
args: args{
attSlot: 16,
genesisTime: roughtime.Now().Add(-15 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second),
genesisTime: timeutils.Now().Add(-15 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second),
},
wantErr: true,
wantedErr: "not within attestation propagation range",
},
{
name: "attestation.slot < current_slot-ATTESTATION_PROPAGATION_SLOT_RANGE",
args: args{
attSlot: 100 - params.BeaconNetworkConfig().AttestationPropagationSlotRange - 1,
genesisTime: roughtime.Now().Add(-100 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second),
genesisTime: timeutils.Now().Add(-100 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second),
},
wantErr: true,
wantedErr: "not within attestation propagation range",
},
{
name: "attestation.slot = current_slot-ATTESTATION_PROPAGATION_SLOT_RANGE",
args: args{
attSlot: 100 - params.BeaconNetworkConfig().AttestationPropagationSlotRange,
genesisTime: roughtime.Now().Add(-100 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second),
genesisTime: timeutils.Now().Add(-100 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second),
},
wantErr: false,
},
{
name: "attestation.slot = current_slot-ATTESTATION_PROPAGATION_SLOT_RANGE, received 200ms late",
args: args{
attSlot: 100 - params.BeaconNetworkConfig().AttestationPropagationSlotRange,
genesisTime: roughtime.Now().Add(
genesisTime: timeutils.Now().Add(
-100 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second,
).Add(200 * time.Millisecond),
},
wantErr: false,
},
{
name: "attestation.slot is well beyond current slot",
args: args{
attSlot: 1 << 32,
genesisTime: timeutils.Now().Add(-15 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second),
},
wantedErr: "which exceeds max allowed value relative to the local clock",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := helpers.ValidateAttestationTime(tt.args.attSlot, tt.args.genesisTime); (err != nil) != tt.wantErr {
t.Errorf("validateAggregateAttTime() error = %v, wantErr %v", err, tt.wantErr)
err := helpers.ValidateAttestationTime(tt.args.attSlot, tt.args.genesisTime)
if tt.wantedErr != "" {
assert.ErrorContains(t, tt.wantedErr, err)
} else {
assert.NoError(t, err)
}
})
}

View File

@@ -32,5 +32,9 @@ func BlockRootAtSlot(state *stateTrie.BeaconState, slot uint64) ([]byte, error)
// """
// return get_block_root_at_slot(state, compute_start_slot_at_epoch(epoch))
func BlockRoot(state *stateTrie.BeaconState, epoch uint64) ([]byte, error) {
return BlockRootAtSlot(state, StartSlot(epoch))
s, err := StartSlot(epoch)
if err != nil {
return nil, err
}
return BlockRootAtSlot(state, s)
}

View File

@@ -12,12 +12,14 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/featureconfig"
"github.com/prysmaticlabs/prysm/shared/hashutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/sliceutil"
)
var committeeCache = cache.NewCommitteesCache()
var proposerIndicesCache = cache.NewProposerIndicesCache()
// SlotCommitteeCount returns the number of crosslink committees of a slot. The
// active validator count is provided as an argument rather than a direct implementation
@@ -143,7 +145,30 @@ func ComputeCommittee(
// for fast computation of committees.
// Reference implementation: https://github.com/protolambda/eth2-shuffle
shuffledList, err := UnshuffleList(shuffledIndices, seed)
return shuffledList[start:end], err
if err != nil {
return nil, err
}
// This updates the cache on a miss.
if featureconfig.Get().UseCheckPointInfoCache {
sortedIndices := make([]uint64, len(indices))
copy(sortedIndices, indices)
sort.Slice(sortedIndices, func(i, j int) bool {
return sortedIndices[i] < sortedIndices[j]
})
count = SlotCommitteeCount(uint64(len(shuffledIndices)))
if err := committeeCache.AddCommitteeShuffledList(&cache.Committees{
ShuffledIndices: shuffledList,
CommitteeCount: count * params.BeaconConfig().SlotsPerEpoch,
Seed: seed,
SortedIndices: sortedIndices,
}); err != nil {
return nil, err
}
}
return shuffledList[start:end], nil
}
// CommitteeAssignmentContainer represents a committee, index, and attester slot for a given epoch.
@@ -176,7 +201,10 @@ func CommitteeAssignments(
// We determine the slots in which proposers are supposed to act.
// Some validators may need to propose multiple times per epoch, so
// we use a map of proposer idx -> []slot to keep track of this possibility.
startSlot := StartSlot(epoch)
startSlot, err := StartSlot(epoch)
if err != nil {
return nil, nil, err
}
proposerIndexToSlots := make(map[uint64][]uint64, params.BeaconConfig().SlotsPerEpoch)
for slot := startSlot; slot < startSlot+params.BeaconConfig().SlotsPerEpoch; slot++ {
// Skip proposer assignment for genesis slot.
@@ -285,7 +313,8 @@ func UpdateCommitteeCache(state *stateTrie.BeaconState, epoch uint64) error {
if err != nil {
return err
}
if _, exists, err := committeeCache.CommitteeCache.GetByKey(string(seed[:])); err == nil && exists {
if committeeCache.HasEntry(string(seed[:])) {
return nil
}
@@ -320,29 +349,38 @@ func UpdateCommitteeCache(state *stateTrie.BeaconState, epoch uint64) error {
// UpdateProposerIndicesInCache updates proposer indices entry of the committee cache.
func UpdateProposerIndicesInCache(state *stateTrie.BeaconState, epoch uint64) error {
// The cache uses the block root at the last epoch slot as key. (e.g. for epoch 1, the key is root at slot 31)
// Which is the reason why we skip genesis epoch.
if epoch <= params.BeaconConfig().GenesisEpoch {
return nil
}
indices, err := ActiveValidatorIndices(state, epoch)
if err != nil {
return nil
return err
}
proposerIndices, err := precomputeProposerIndices(state, indices)
if err != nil {
return err
}
// The committee cache uses attester domain seed as key.
seed, err := Seed(state, epoch, params.BeaconConfig().DomainBeaconAttester)
s, err := EndSlot(PrevEpoch(state))
if err != nil {
return err
}
if err := committeeCache.AddProposerIndicesList(seed, proposerIndices); err != nil {
r, err := BlockRootAtSlot(state, s)
if err != nil {
return err
}
return nil
return proposerIndicesCache.AddProposerIndices(&cache.ProposerIndices{
BlockRoot: bytesutil.ToBytes32(r),
ProposerIndices: proposerIndices,
})
}
// ClearCache clears the committee cache
func ClearCache() {
committeeCache = cache.NewCommitteesCache()
proposerIndicesCache = cache.NewProposerIndicesCache()
}
// This computes proposer indices of the current epoch and returns a list of proposer indices,
@@ -356,7 +394,10 @@ func precomputeProposerIndices(state *stateTrie.BeaconState, activeIndices []uin
if err != nil {
return nil, errors.Wrap(err, "could not generate seed")
}
slot := StartSlot(e)
slot, err := StartSlot(e)
if err != nil {
return nil, err
}
for i := uint64(0); i < params.BeaconConfig().SlotsPerEpoch; i++ {
seedWithSlot := append(seed[:], bytesutil.Bytes8(slot+i)...)
seedWithSlotHash := hashFunc(seedWithSlot)

View File

@@ -230,8 +230,10 @@ func TestCommitteeAssignments_EverySlotHasMin1Proposer(t *testing.T) {
}
}
assert.Equal(t, params.BeaconConfig().SlotsPerEpoch, uint64(len(slotsWithProposers)), "Unexpected slots")
startSlot := StartSlot(epoch)
endSlot := StartSlot(epoch + 1)
startSlot, err := StartSlot(epoch)
require.NoError(t, err)
endSlot, err := StartSlot(epoch + 1)
require.NoError(t, err)
for i := startSlot; i < endSlot; i++ {
hasProposer := slotsWithProposers[i]
assert.Equal(t, true, hasProposer, "Expected every slot in epoch 1 to have a proposer, slot %d did not", i)
@@ -263,7 +265,7 @@ func TestVerifyAttestationBitfieldLengths_OK(t *testing.T) {
AggregationBits: bitfield.Bitlist{0x05},
Data: &ethpb.AttestationData{
CommitteeIndex: 5,
Target: &ethpb.Checkpoint{},
Target: &ethpb.Checkpoint{Root: make([]byte, 32)},
},
},
stateSlot: 5,
@@ -274,7 +276,7 @@ func TestVerifyAttestationBitfieldLengths_OK(t *testing.T) {
AggregationBits: bitfield.Bitlist{0x06},
Data: &ethpb.AttestationData{
CommitteeIndex: 10,
Target: &ethpb.Checkpoint{},
Target: &ethpb.Checkpoint{Root: make([]byte, 32)},
},
},
stateSlot: 10,
@@ -284,7 +286,7 @@ func TestVerifyAttestationBitfieldLengths_OK(t *testing.T) {
AggregationBits: bitfield.Bitlist{0x06},
Data: &ethpb.AttestationData{
CommitteeIndex: 20,
Target: &ethpb.Checkpoint{},
Target: &ethpb.Checkpoint{Root: make([]byte, 32)},
},
},
stateSlot: 20,
@@ -294,7 +296,7 @@ func TestVerifyAttestationBitfieldLengths_OK(t *testing.T) {
AggregationBits: bitfield.Bitlist{0x06},
Data: &ethpb.AttestationData{
CommitteeIndex: 20,
Target: &ethpb.Checkpoint{},
Target: &ethpb.Checkpoint{Root: make([]byte, 32)},
},
},
stateSlot: 20,
@@ -304,7 +306,7 @@ func TestVerifyAttestationBitfieldLengths_OK(t *testing.T) {
AggregationBits: bitfield.Bitlist{0xFF, 0xC0, 0x01},
Data: &ethpb.AttestationData{
CommitteeIndex: 5,
Target: &ethpb.Checkpoint{},
Target: &ethpb.Checkpoint{Root: make([]byte, 32)},
},
},
stateSlot: 5,
@@ -315,7 +317,7 @@ func TestVerifyAttestationBitfieldLengths_OK(t *testing.T) {
AggregationBits: bitfield.Bitlist{0xFF, 0x01},
Data: &ethpb.AttestationData{
CommitteeIndex: 20,
Target: &ethpb.Checkpoint{},
Target: &ethpb.Checkpoint{Root: make([]byte, 32)},
},
},
stateSlot: 20,
@@ -328,14 +330,9 @@ func TestVerifyAttestationBitfieldLengths_OK(t *testing.T) {
require.NoError(t, state.SetSlot(tt.stateSlot))
err := VerifyAttestationBitfieldLengths(state, tt.attestation)
if tt.verificationFailure {
if err == nil {
t.Error("verification succeeded when it was supposed to fail")
}
continue
}
if err != nil {
t.Errorf("%d Failed to verify bitfield: %v", i, err)
continue
assert.NotNil(t, err, "Verification succeeded when it was supposed to fail")
} else {
assert.NoError(t, err, "%d Failed to verify bitfield: %v", i, err)
}
}
}
@@ -395,7 +392,7 @@ func TestUpdateCommitteeCache_CanUpdate(t *testing.T) {
seed, err := Seed(state, epoch, params.BeaconConfig().DomainBeaconAttester)
require.NoError(t, err)
indices, err = committeeCache.Committee(StartSlot(epoch), seed, idx)
indices, err = committeeCache.Committee(epoch*params.BeaconConfig().SlotsPerEpoch, seed, idx)
require.NoError(t, err)
assert.Equal(t, params.BeaconConfig().TargetCommitteeSize, uint64(len(indices)), "Did not save correct indices lengths")
}
@@ -631,3 +628,9 @@ func TestPrecomputeProposerIndices_Ok(t *testing.T) {
}
assert.DeepEqual(t, wantedProposerIndices, proposerIndices, "Did not precompute proposer indices correctly")
}
func TestUpdateProposerIndicesInCache_CouldNotGetActiveIndices(t *testing.T) {
err := UpdateProposerIndicesInCache(&beaconstate.BeaconState{}, 1)
want := "nil inner state"
require.ErrorContains(t, want, err)
}

View File

@@ -1,11 +1,11 @@
package helpers
import (
fssz "github.com/ferranbt/fastssz"
"github.com/pkg/errors"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/go-ssz"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
p2ppb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/bls"
@@ -48,16 +48,14 @@ func ComputeDomainAndSign(state *state.BeaconState, epoch uint64, obj interface{
// domain=domain,
// ))
func ComputeSigningRoot(object interface{}, domain []byte) ([32]byte, error) {
if object == nil {
return [32]byte{}, errors.New("cannot compute signing root of nil")
}
return signingData(func() ([32]byte, error) {
switch t := object.(type) {
case *ethpb.BeaconBlock:
return stateutil.BlockRoot(t)
case *ethpb.AttestationData:
return stateutil.AttestationDataRoot(t)
default:
// utilise generic ssz library
return ssz.HashTreeRoot(object)
if v, ok := object.(fssz.HashRoot); ok {
return v.HashTreeRoot()
}
return ssz.HashTreeRoot(object)
}, domain)
}
@@ -72,7 +70,7 @@ func signingData(rootFunc func() ([32]byte, error), domain []byte) ([32]byte, er
ObjectRoot: objRoot[:],
Domain: domain,
}
return ssz.HashTreeRoot(container)
return container.HashTreeRoot()
}
// ComputeDomainVerifySigningRoot computes domain and verifies signing root of an object given the beacon state, validator index and signature.
@@ -119,7 +117,11 @@ func VerifyBlockSigningRoot(blk *ethpb.BeaconBlock, pub []byte, signature []byte
publicKey := set.PublicKeys[0]
root := set.Messages[0]
if !sig.Verify(publicKey, root[:]) {
rSig, err := bls.SignatureFromBytes(sig)
if err != nil {
return err
}
if !rSig.Verify(publicKey, root[:]) {
return ErrSigFailedToVerify
}
return nil
@@ -132,19 +134,13 @@ func RetrieveBlockSignatureSet(blk *ethpb.BeaconBlock, pub []byte, signature []b
if err != nil {
return nil, errors.Wrap(err, "could not convert bytes to public key")
}
sig, err := bls.SignatureFromBytes(signature)
if err != nil {
return nil, errors.Wrap(err, "could not convert bytes to signature")
}
root, err := signingData(func() ([32]byte, error) {
// utilize custom block hashing function
return stateutil.BlockRoot(blk)
}, domain)
// utilize custom block hashing function
root, err := signingData(blk.HashTreeRoot, domain)
if err != nil {
return nil, errors.Wrap(err, "could not compute signing root")
}
return &bls.SignatureSet{
Signatures: []bls.Signature{sig},
Signatures: [][]byte{signature},
PublicKeys: []bls.PublicKey{publicKey},
Messages: [][32]byte{root},
}, nil
@@ -160,9 +156,7 @@ func VerifyBlockHeaderSigningRoot(blkHdr *ethpb.BeaconBlockHeader, pub []byte, s
if err != nil {
return errors.Wrap(err, "could not convert bytes to signature")
}
root, err := signingData(func() ([32]byte, error) {
return stateutil.BlockHeaderRoot(blkHdr)
}, domain)
root, err := signingData(blkHdr.HashTreeRoot, domain)
if err != nil {
return errors.Wrap(err, "could not compute signing root")
}
@@ -225,10 +219,10 @@ func domain(domainType [DomainByteLength]byte, forkDataRoot []byte) []byte {
// genesis_validators_root=genesis_validators_root,
// ))
func computeForkDataRoot(version []byte, root []byte) ([32]byte, error) {
r, err := ssz.HashTreeRoot(&pb.ForkData{
r, err := (&pb.ForkData{
CurrentVersion: version,
GenesisValidatorsRoot: root,
})
}).HashTreeRoot()
if err != nil {
return [32]byte{}, err
}
@@ -248,7 +242,7 @@ func computeForkDataRoot(version []byte, root []byte) ([32]byte, error) {
func ComputeForkDigest(version []byte, genesisValidatorsRoot []byte) ([4]byte, error) {
dataRoot, err := computeForkDataRoot(version, genesisValidatorsRoot)
if err != nil {
return [4]byte{}, nil
return [4]byte{}, err
}
return bytesutil.ToBytes4(dataRoot[:]), nil
}

View File

@@ -1,21 +1,21 @@
package helpers
package helpers_test
import (
"bytes"
"testing"
fuzz "github.com/google/gofuzz"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
ethereum_beacon_p2p_v1 "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
)
func TestSigningRoot_ComputeOK(t *testing.T) {
emptyBlock := &ethpb.BeaconBlock{}
_, err := ComputeSigningRoot(emptyBlock, []byte{'T', 'E', 'S', 'T'})
emptyBlock := testutil.NewBeaconBlock()
_, err := helpers.ComputeSigningRoot(emptyBlock, bytesutil.PadTo([]byte{'T', 'E', 'S', 'T'}, 32))
assert.NoError(t, err, "Could not compute signing root of block")
}
@@ -25,38 +25,21 @@ func TestComputeDomain_OK(t *testing.T) {
domainType [4]byte
domain []byte
}{
{epoch: 1, domainType: [4]byte{4, 0, 0, 0}, domain: []byte{4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
{epoch: 2, domainType: [4]byte{4, 0, 0, 0}, domain: []byte{4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
{epoch: 2, domainType: [4]byte{5, 0, 0, 0}, domain: []byte{5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
{epoch: 3, domainType: [4]byte{4, 0, 0, 0}, domain: []byte{4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
{epoch: 3, domainType: [4]byte{5, 0, 0, 0}, domain: []byte{5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
{epoch: 1, domainType: [4]byte{4, 0, 0, 0}, domain: []byte{4, 0, 0, 0, 245, 165, 253, 66, 209, 106, 32, 48, 39, 152, 239, 110, 211, 9, 151, 155, 67, 0, 61, 35, 32, 217, 240, 232, 234, 152, 49, 169}},
{epoch: 2, domainType: [4]byte{4, 0, 0, 0}, domain: []byte{4, 0, 0, 0, 245, 165, 253, 66, 209, 106, 32, 48, 39, 152, 239, 110, 211, 9, 151, 155, 67, 0, 61, 35, 32, 217, 240, 232, 234, 152, 49, 169}},
{epoch: 2, domainType: [4]byte{5, 0, 0, 0}, domain: []byte{5, 0, 0, 0, 245, 165, 253, 66, 209, 106, 32, 48, 39, 152, 239, 110, 211, 9, 151, 155, 67, 0, 61, 35, 32, 217, 240, 232, 234, 152, 49, 169}},
{epoch: 3, domainType: [4]byte{4, 0, 0, 0}, domain: []byte{4, 0, 0, 0, 245, 165, 253, 66, 209, 106, 32, 48, 39, 152, 239, 110, 211, 9, 151, 155, 67, 0, 61, 35, 32, 217, 240, 232, 234, 152, 49, 169}},
{epoch: 3, domainType: [4]byte{5, 0, 0, 0}, domain: []byte{5, 0, 0, 0, 245, 165, 253, 66, 209, 106, 32, 48, 39, 152, 239, 110, 211, 9, 151, 155, 67, 0, 61, 35, 32, 217, 240, 232, 234, 152, 49, 169}},
}
for _, tt := range tests {
if !bytes.Equal(domain(tt.domainType, params.BeaconConfig().ZeroHash[:]), tt.domain) {
t.Errorf("wanted domain version: %d, got: %d", tt.domain, domain(tt.domainType, params.BeaconConfig().ZeroHash[:]))
if got, err := helpers.ComputeDomain(tt.domainType, nil, nil); !bytes.Equal(got, tt.domain) {
t.Errorf("wanted domain version: %d, got: %d", tt.domain, got)
} else {
require.NoError(t, err)
}
}
}
func TestSigningRoot_Compatibility(t *testing.T) {
parRoot := [32]byte{'A'}
stateRoot := [32]byte{'B'}
blk := &ethpb.BeaconBlock{
Slot: 20,
ProposerIndex: 20,
ParentRoot: parRoot[:],
StateRoot: stateRoot[:],
Body: &ethpb.BeaconBlockBody{},
}
root, err := ComputeSigningRoot(blk, params.BeaconConfig().DomainBeaconProposer[:])
require.NoError(t, err)
newRoot, err := signingData(func() ([32]byte, error) {
return stateutil.BlockRoot(blk)
}, params.BeaconConfig().DomainBeaconProposer[:])
require.NoError(t, err)
assert.Equal(t, root, newRoot, "Wanted root of %#x but got %#x", root, newRoot)
}
func TestComputeForkDigest_OK(t *testing.T) {
tests := []struct {
version []byte
@@ -68,7 +51,7 @@ func TestComputeForkDigest_OK(t *testing.T) {
{version: []byte{'b', 'w', 'r', 't'}, root: [32]byte{'r', 'd', 'c'}, result: [4]byte{0x83, 0x34, 0x38, 0x88}},
}
for _, tt := range tests {
digest, err := ComputeForkDigest(tt.version, tt.root[:])
digest, err := helpers.ComputeForkDigest(tt.version, tt.root[:])
require.NoError(t, err)
assert.Equal(t, tt.result, digest, "Wanted domain version: %#x, got: %#x", digest, tt.result)
}
@@ -92,8 +75,9 @@ func TestFuzzverifySigningRoot_10000(t *testing.T) {
fuzzer.Fuzz(&p)
fuzzer.Fuzz(&s)
fuzzer.Fuzz(&d)
err := VerifySigningRoot(state, pubkey[:], sig[:], domain[:])
err = VerifySigningRoot(state, p, s, d)
err := helpers.VerifySigningRoot(state, pubkey[:], sig[:], domain[:])
_ = err
err = helpers.VerifySigningRoot(state, p, s, d)
_ = err
}
}

View File

@@ -5,11 +5,17 @@ import (
"math"
"time"
"github.com/pkg/errors"
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/shared/mathutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/roughtime"
"github.com/prysmaticlabs/prysm/shared/timeutils"
)
// MaxSlotBuffer specifies the max buffer given to slots from
// incoming objects. (24 mins with mainnet spec)
const MaxSlotBuffer = uint64(1 << 7)
// SlotToEpoch returns the epoch number of the input slot.
//
// Spec pseudocode definition:
@@ -68,9 +74,26 @@ func NextEpoch(state *stateTrie.BeaconState) uint64 {
// """
// Return the start slot of ``epoch``.
// """
// return Slot(epoch * SLOTS_PER_EPOCH
func StartSlot(epoch uint64) uint64 {
return epoch * params.BeaconConfig().SlotsPerEpoch
// return Slot(epoch * SLOTS_PER_EPOCH)
func StartSlot(epoch uint64) (uint64, error) {
slot, err := mathutil.Mul64(epoch, params.BeaconConfig().SlotsPerEpoch)
if err != nil {
return slot, errors.Errorf("start slot calculation overflows: %v", err)
}
return slot, nil
}
// EndSlot returns the last slot number of the
// current epoch.
func EndSlot(epoch uint64) (uint64, error) {
if epoch == math.MaxUint64 {
return 0, errors.New("start slot calculation overflows")
}
slot, err := StartSlot(epoch + 1)
if err != nil {
return 0, err
}
return slot - 1, nil
}
// IsEpochStart returns true if the given slot number is an epoch starting slot
@@ -87,7 +110,7 @@ func IsEpochEnd(slot uint64) bool {
// SlotsSinceEpochStarts returns number of slots since the start of the epoch.
func SlotsSinceEpochStarts(slot uint64) uint64 {
return slot - StartSlot(SlotToEpoch(slot))
return slot % params.BeaconConfig().SlotsPerEpoch
}
// VerifySlotTime validates the input slot is not from the future.
@@ -96,7 +119,14 @@ func VerifySlotTime(genesisTime uint64, slot uint64, timeTolerance time.Duration
if err != nil {
return err
}
currentTime := roughtime.Now()
// Defensive check to ensure unreasonable slots are rejected
// straight away.
if err := ValidateSlotClock(slot, genesisTime); err != nil {
return err
}
currentTime := timeutils.Now()
diff := slotTime.Sub(currentTime)
if diff > timeTolerance {
@@ -107,16 +137,44 @@ func VerifySlotTime(genesisTime uint64, slot uint64, timeTolerance time.Duration
// SlotToTime takes the given slot and genesis time to determine the start time of the slot.
func SlotToTime(genesisTimeSec uint64, slot uint64) (time.Time, error) {
if slot >= math.MaxInt64 {
return time.Unix(0, 0), fmt.Errorf("slot (%d) is in the far distant future", slot)
timeSinceGenesis, err := mathutil.Mul64(slot, params.BeaconConfig().SecondsPerSlot)
if err != nil {
return time.Unix(0, 0), fmt.Errorf("slot (%d) is in the far distant future: %v", slot, err)
}
timeSinceGenesis := slot * params.BeaconConfig().SecondsPerSlot
return time.Unix(int64(genesisTimeSec+timeSinceGenesis), 0), nil
sTime, err := mathutil.Add64(genesisTimeSec, timeSinceGenesis)
if err != nil {
return time.Unix(0, 0), fmt.Errorf("slot (%d) is in the far distant future: %v", slot, err)
}
return time.Unix(int64(sTime), 0), nil
}
// SlotsSince computes the number of time slots that have occurred since the given timestamp.
func SlotsSince(time time.Time) uint64 {
return uint64(roughtime.Since(time).Seconds()) / params.BeaconConfig().SecondsPerSlot
return CurrentSlot(uint64(time.Unix()))
}
// CurrentSlot returns the current slot as determined by the local clock and
// provided genesis time.
func CurrentSlot(genesisTimeSec uint64) uint64 {
now := timeutils.Now().Unix()
genesis := int64(genesisTimeSec)
if now < genesis {
return 0
}
return uint64(now-genesis) / params.BeaconConfig().SecondsPerSlot
}
// ValidateSlotClock validates a provided slot against the local
// clock to ensure slots that are unreasonable are returned with
// an error.
func ValidateSlotClock(slot uint64, genesisTimeSec uint64) error {
maxPossibleSlot := CurrentSlot(genesisTimeSec) + MaxSlotBuffer
// Defensive check to ensure that we only process slots up to a hard limit
// from our local clock.
if slot > maxPossibleSlot {
return fmt.Errorf("slot %d > %d which exceeds max allowed value relative to the local clock", slot, maxPossibleSlot)
}
return nil
}
// RoundUpToNearestEpoch rounds up the provided slot value to the nearest epoch.
@@ -127,3 +185,36 @@ func RoundUpToNearestEpoch(slot uint64) uint64 {
}
return slot
}
// WeakSubjectivityCheckptEpoch returns the epoch of the latest weak subjectivity checkpoint for the active validator count and
// finalized epoch.
//
// Reference spec implementation:
// https://github.com/ethereum/eth2.0-specs/blob/weak-subjectivity-guide/specs/phase0/weak-subjectivity.md#calculating-the-weak-subjectivity-period
// def compute_weak_subjectivity_period(state):
// weak_subjectivity_period = MIN_VALIDATOR_WITHDRAWABILITY_DELAY
// val_count = len(get_active_validator_indices(state, get_current_epoch(state)))
// if val_count >= MIN_PER_EPOCH_CHURN_LIMIT * CHURN_LIMIT_QUOTIENT:
// weak_subjectivity_period += SAFETY_DECAY*CHURN_LIMIT_QUOTIENT/(2*100)
// else:
// weak_subjectivity_period += SAFETY_DECAY*val_count/(2*100*MIN_PER_EPOCH_CHURN_LIMIT)
// return weak_subjectivity_period
func WeakSubjectivityCheckptEpoch(valCount uint64) (uint64, error) {
wsp := params.BeaconConfig().MinValidatorWithdrawabilityDelay
m := params.BeaconConfig().MinPerEpochChurnLimit
q := params.BeaconConfig().ChurnLimitQuotient
d := params.BeaconConfig().SafetyDecay
if valCount >= m*q {
v := d * q / (2 * 100)
wsp += v
} else {
v, err := mathutil.Mul64(d, valCount)
if err != nil {
return 0, err
}
v = v / (2 * 100 * m)
wsp += v
}
return wsp, nil
}

View File

@@ -2,13 +2,12 @@ package helpers
import (
"math"
"reflect"
"testing"
"time"
"github.com/prysmaticlabs/prysm/shared/roughtime"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
"github.com/prysmaticlabs/prysm/shared/timeutils"
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
@@ -87,14 +86,47 @@ func TestEpochStartSlot_OK(t *testing.T) {
tests := []struct {
epoch uint64
startSlot uint64
error bool
}{
{epoch: 0, startSlot: 0 * params.BeaconConfig().SlotsPerEpoch},
{epoch: 1, startSlot: 1 * params.BeaconConfig().SlotsPerEpoch},
{epoch: 10, startSlot: 10 * params.BeaconConfig().SlotsPerEpoch},
{epoch: 0, startSlot: 0 * params.BeaconConfig().SlotsPerEpoch, error: false},
{epoch: 1, startSlot: 1 * params.BeaconConfig().SlotsPerEpoch, error: false},
{epoch: 10, startSlot: 10 * params.BeaconConfig().SlotsPerEpoch, error: false},
{epoch: 1 << 58, startSlot: 1 << 63, error: false},
{epoch: 1 << 59, startSlot: 1 << 63, error: true},
{epoch: 1 << 60, startSlot: 1 << 63, error: true},
}
for _, tt := range tests {
state := &pb.BeaconState{Slot: tt.epoch}
assert.Equal(t, tt.startSlot, StartSlot(tt.epoch), "StartSlot(%d)", state.Slot)
ss, err := StartSlot(tt.epoch)
if !tt.error {
require.NoError(t, err)
assert.Equal(t, tt.startSlot, ss, "StartSlot(%d)", tt.epoch)
} else {
require.ErrorContains(t, "start slot calculation overflow", err)
}
}
}
func TestEpochEndSlot_OK(t *testing.T) {
tests := []struct {
epoch uint64
startSlot uint64
error bool
}{
{epoch: 0, startSlot: 1*params.BeaconConfig().SlotsPerEpoch - 1, error: false},
{epoch: 1, startSlot: 2*params.BeaconConfig().SlotsPerEpoch - 1, error: false},
{epoch: 10, startSlot: 11*params.BeaconConfig().SlotsPerEpoch - 1, error: false},
{epoch: 1 << 59, startSlot: 1 << 63, error: true},
{epoch: 1 << 60, startSlot: 1 << 63, error: true},
{epoch: math.MaxUint64, startSlot: 0, error: true},
}
for _, tt := range tests {
ss, err := EndSlot(tt.epoch)
if !tt.error {
require.NoError(t, err)
assert.Equal(t, tt.startSlot, ss, "StartSlot(%d)", tt.epoch)
} else {
require.ErrorContains(t, "start slot calculation overflow", err)
}
}
}
@@ -190,10 +222,10 @@ func TestSlotToTime(t *testing.T) {
slot uint64
}
tests := []struct {
name string
args args
want time.Time
wantErr bool
name string
args args
want time.Time
wantedErr string
}{
{
name: "slot_0",
@@ -201,8 +233,7 @@ func TestSlotToTime(t *testing.T) {
genesisTimeSec: 0,
slot: 0,
},
want: time.Unix(0, 0),
wantErr: false,
want: time.Unix(0, 0),
},
{
name: "slot_1",
@@ -210,8 +241,7 @@ func TestSlotToTime(t *testing.T) {
genesisTimeSec: 0,
slot: 1,
},
want: time.Unix(int64(1*params.BeaconConfig().SecondsPerSlot), 0),
wantErr: false,
want: time.Unix(int64(1*params.BeaconConfig().SecondsPerSlot), 0),
},
{
name: "slot_12",
@@ -219,8 +249,7 @@ func TestSlotToTime(t *testing.T) {
genesisTimeSec: 500,
slot: 12,
},
want: time.Unix(500+int64(12*params.BeaconConfig().SecondsPerSlot), 0),
wantErr: false,
want: time.Unix(500+int64(12*params.BeaconConfig().SecondsPerSlot), 0),
},
{
name: "overflow",
@@ -228,13 +257,17 @@ func TestSlotToTime(t *testing.T) {
genesisTimeSec: 500,
slot: math.MaxUint64,
},
wantErr: true,
wantedErr: "is in the far distant future",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got, err := SlotToTime(tt.args.genesisTimeSec, tt.args.slot); (err != nil) != tt.wantErr && !reflect.DeepEqual(got, tt.want) {
t.Errorf("SlotToTime() = %v, want %v", got, tt.want)
got, err := SlotToTime(tt.args.genesisTimeSec, tt.args.slot)
if tt.wantedErr != "" {
assert.ErrorContains(t, tt.wantedErr, err)
} else {
assert.NoError(t, err)
assert.DeepEqual(t, tt.want, got)
}
})
}
@@ -247,40 +280,91 @@ func TestVerifySlotTime(t *testing.T) {
timeTolerance time.Duration
}
tests := []struct {
name string
args args
wantErr bool
name string
args args
wantedErr string
}{
{
name: "Past slot",
args: args{
genesisTime: roughtime.Now().Add(-1 * 5 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second).Unix(),
genesisTime: timeutils.Now().Add(-1 * 5 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second).Unix(),
slot: 3,
},
wantErr: false,
},
{
name: "within tolerance",
args: args{
genesisTime: roughtime.Now().Add(-1 * 5 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second).Add(20 * time.Millisecond).Unix(),
genesisTime: timeutils.Now().Add(-1 * 5 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second).Add(20 * time.Millisecond).Unix(),
slot: 5,
},
wantErr: false,
},
{
name: "future slot",
args: args{
genesisTime: roughtime.Now().Add(-1 * 5 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second).Unix(),
genesisTime: timeutils.Now().Add(-1 * 5 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second).Unix(),
slot: 6,
},
wantErr: true,
wantedErr: "could not process slot from the future",
},
{
name: "max future slot",
args: args{
genesisTime: timeutils.Now().Add(-1 * 5 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second).Unix(),
slot: MaxSlotBuffer + 6,
},
wantedErr: "exceeds max allowed value relative to the local clock",
},
{
name: "evil future slot",
args: args{
genesisTime: timeutils.Now().Add(-1 * 24 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second).Unix(), // 24 slots in the past
// Gets multiplied with slot duration, and results in an overflow. Wraps around to a valid time.
// Lower than max signed int. And chosen specifically to wrap to a valid slot 24
slot: ((^uint64(0)) / params.BeaconConfig().SecondsPerSlot) + 24,
},
wantedErr: "is in the far distant future",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := VerifySlotTime(uint64(tt.args.genesisTime), tt.args.slot, tt.args.timeTolerance); (err != nil) != tt.wantErr {
t.Errorf("VerifySlotTime() error = %v, wantErr %v", err, tt.wantErr)
err := VerifySlotTime(uint64(tt.args.genesisTime), tt.args.slot, tt.args.timeTolerance)
if tt.wantedErr != "" {
assert.ErrorContains(t, tt.wantedErr, err)
} else {
assert.NoError(t, err)
}
})
}
}
func TestValidateSlotClock_HandlesBadSlot(t *testing.T) {
genTime := timeutils.Now().Add(-1 * time.Duration(MaxSlotBuffer) * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second).Unix()
assert.NoError(t, ValidateSlotClock(MaxSlotBuffer, uint64(genTime)), "unexpected error validating slot")
assert.NoError(t, ValidateSlotClock(2*MaxSlotBuffer, uint64(genTime)), "unexpected error validating slot")
assert.ErrorContains(t, "which exceeds max allowed value relative to the local clock", ValidateSlotClock(2*MaxSlotBuffer+1, uint64(genTime)), "no error from bad slot")
assert.ErrorContains(t, "which exceeds max allowed value relative to the local clock", ValidateSlotClock(1<<63, uint64(genTime)), "no error from bad slot")
}
func TestWeakSubjectivityCheckptEpoch(t *testing.T) {
tests := []struct {
valCount uint64
want uint64
}{
// Verifying these numbers aligned with the reference table defined:
// https://github.com/ethereum/eth2.0-specs/blob/weak-subjectivity-guide/specs/phase0/weak-subjectivity.md#calculating-the-weak-subjectivity-period
{valCount: params.BeaconConfig().MinGenesisActiveValidatorCount, want: 460},
{valCount: params.BeaconConfig().MinGenesisActiveValidatorCount * 2, want: 665},
{valCount: params.BeaconConfig().MinGenesisActiveValidatorCount * 4, want: 1075},
{valCount: params.BeaconConfig().MinGenesisActiveValidatorCount * 8, want: 1894},
{valCount: params.BeaconConfig().MinGenesisActiveValidatorCount * 16, want: 3532},
{valCount: params.BeaconConfig().MinGenesisActiveValidatorCount * 32, want: 3532},
}
for _, tt := range tests {
got, err := WeakSubjectivityCheckptEpoch(tt.valCount)
require.NoError(t, err)
if got != tt.want {
t.Errorf("WeakSubjectivityCheckptEpoch() = %v, want %v", got, tt.want)
}
}
}

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