Compare commits

..

240 Commits

Author SHA1 Message Date
terence tsao
80cd539297 Rm uncommented 2022-02-15 06:48:33 -08:00
terence tsao
f47b6af910 Done 2022-02-14 22:09:29 -08:00
terence tsao
443df77bb3 c 2022-02-14 18:25:59 -08:00
terence tsao
94fe3884a0 Merge branch 'develop' of github.com:prysmaticlabs/prysm into kiln 2022-02-14 08:07:12 -08:00
Rootul Patel
f550a964f5 Add path to Keystore (#10152)
* Add failing test

* Add path to keystore

* Assert encoded contains "path"

* Fix lint

Ran `bazel run //:gazelle -- fix`

Co-authored-by: james-prysm <90280386+james-prysm@users.noreply.github.com>
2022-02-14 09:57:15 -06:00
Radosław Kapka
c5c039fd6b Unify GenesisValidator(s)Root throughout the codebase (#10230)
* Unify `GenesisValidator(s)Root` throughout the codebase

* comments and literals

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
Co-authored-by: terence tsao <terence@prysmaticlabs.com>
2022-02-14 13:34:38 +00:00
Radosław Kapka
4d9947543f Native state feature flag (#10232)
* add flag

* working version

* rename flag

Co-authored-by: Nishant Das <nishdas93@gmail.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2022-02-14 12:33:02 +00:00
Michael Neuder
7370c42bae Adding nil error check to connection status for ETH1 nodes (#10186)
Co-authored-by: Radosław Kapka <rkapka@wp.pl>
Co-authored-by: terence tsao <terence@prysmaticlabs.com>
2022-02-14 10:21:45 +00:00
Radosław Kapka
3c76cc3af5 Return state interface from native state constructors (#10208)
Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2022-02-14 17:51:22 +08:00
terence tsao
28af5bc601 Fix eth_getBlockByHash call (#10239)
* Update client.go

* Update client_test.go
2022-02-13 16:33:11 +00:00
terence tsao
c9f299b50a Clean up fork choice (#10226)
* Clean up fork choice

* Update beacon-chain/forkchoice/protoarray/proposer_boost_test.go

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

* Update beacon-chain/forkchoice/protoarray/store_test.go

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

* Update beacon-chain/forkchoice/protoarray/store_test.go

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

* Update store.go

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
Co-authored-by: Radosław Kapka <rkapka@wp.pl>
2022-02-12 03:33:46 +00:00
terence tsao
7d6046276d Merge branch 'develop' of github.com:prysmaticlabs/prysm into kiln 2022-02-11 18:02:58 -08:00
terence tsao
9dfb385160 Pad fields to correct length (#10237)
* Pad fields to correct length

* Use constants

* builds

* Fix test

* Update BUILD.bazel

* tests

* passing

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2022-02-12 01:58:09 +00:00
Raul Jordan
b1774efeb7 Fix JSON Marshal/Unmarshal for Execution Block (#10238) 2022-02-12 01:06:28 +00:00
Potuz
4b3a723166 Do not stop on error loading synced tips (#10235)
* Do not stop on error loading synced tips

* Terence's review

* Update beacon-chain/blockchain/optimistic_sync.go

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

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2022-02-11 21:46:53 +00:00
terence tsao
50f253619e Fix engine client method names (#10234)
* Fix engine client method names

* Typo
2022-02-11 16:12:11 -05:00
james-prysm
753afb4fb2 small fix for web3signer (#10223) 2022-02-11 09:41:31 -05:00
Leo Lara
1835f54197 Refactor for DRY state getters_validator_test and getters_test (#10117)
* Refactor for DRY state getters_validator_test and getters_test

* Add BUILD.bazel to beacon-chain/state/testing

* Handle type assertion error in beacon-chain/state tests

* Fix with gazelle

Co-authored-by: Nishant Das <nishdas93@gmail.com>
2022-02-11 14:48:29 +08:00
terence tsao
26a2311c82 Clean up outdated bellatrix code (#10225)
* Rm outdated merge code

* Update config_test.go

* Native

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2022-02-11 04:40:12 +00:00
Potuz
9f419bee7d Remove unnecessary reassignement (#10224) 2022-02-10 23:51:20 -03:00
james-prysm
d04eaf8fa0 Better DB Logging (#10215)
* initial commit

* initial commit

* reverting change

* reverting change

* Update beacon-chain/node/node.go

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

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

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

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2022-02-10 23:15:01 +00:00
terence tsao
4f77ad20c8 Merge branch 'develop' of github.com:prysmaticlabs/prysm into kiln 2022-02-10 14:24:28 -08:00
terence tsao
1b5a6d4195 Add back get payload 2022-02-10 14:22:35 -08:00
Potuz
82ceb51548 Load Synced Tips when starting from Finalized State (#10196)
* Load Synced Tips when starting from Finalized State

* Terence's review #1

* Fix tests

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2022-02-10 22:18:42 +00:00
terence tsao
eae0db383f Clean ups 2022-02-10 12:29:52 -08:00
terence tsao
b56bd9e9d8 Fix build 2022-02-10 12:21:35 -08:00
Potuz
6a2ef13b87 add metrics for synced tips (#10221)
* add metrics for synced tips

* Update beacon-chain/forkchoice/protoarray/metrics.go

Co-authored-by: terence tsao <terence@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2022-02-10 18:48:46 +00:00
Potuz
72a2dd004b Fix integer overflow (#10222)
Co-authored-by: terence tsao <terence@prysmaticlabs.com>
2022-02-10 15:20:36 -03:00
terence tsao
481d8847c2 Merge branch 'kintsugi' of github.com:prysmaticlabs/prysm into kiln 2022-02-10 08:54:35 -08:00
terence tsao
42d5416658 Merge branch 'develop' of github.com:prysmaticlabs/prysm into kintsugi 2022-02-10 08:51:51 -08:00
terence tsao
a1d8833749 Logs and err handling 2022-02-10 08:47:23 -08:00
Raul Jordan
1a0e16a48b Initialize the Engine API Client in the Beacon Chain's Powchain Service (#10217)
* define engine caller

* gaz

* Update cmd/beacon-chain/flags/base.go

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2022-02-10 16:46:31 +00:00
Nishant Das
bff5c1e1a9 Handle Bellatrix Fork Epochs Correctly (#10219)
* handle it properly

* Update beacon-chain/sync/fork_watcher.go

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

* Update beacon-chain/sync/fork_watcher.go

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

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2022-02-10 16:15:55 +00:00
terence tsao
695389b7bb Merge branch 'develop' of github.com:prysmaticlabs/prysm into kintsugi 2022-02-10 08:04:48 -08:00
Potuz
a67b8610f0 Change optimistic logic (#10194) 2022-02-10 09:59:09 -03:00
Nishant Das
3f5ce0cdca Handle a ZeroHash as our Eth1 Genesis Block Root (#10218) 2022-02-10 11:28:57 +00:00
terence tsao
29eceba4d2 delete deprecated client, update testnet flag 2022-02-09 16:05:42 -08:00
terence tsao
4c34e5d424 Sync with develop 2022-02-09 15:53:01 -08:00
terence tsao
569375286e Merge branch 'develop' of github.com:prysmaticlabs/prysm into kintsugi 2022-02-09 15:25:28 -08:00
terence tsao
d51b52d432 Add pow block protobuf (#10205)
* Add pow_block protobuf

* Revert hash changes

This reverts commit 4afb280385.

* Revert "Add pow_block protobuf"

This reverts commit 4afb280385.

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2022-02-09 22:27:30 +00:00
Raul Jordan
7b5a821c81 Implement Execution Engine Client (#10185)
* add in fixtures

* handle real fixtures

* marshaling issues

* ensure error handling works

* begin http client test

* custom type marshaling

* gaz

* custom type

* marshalers

* builds

* builds

* add to build file

* regen

* only root types

* bytes hash

* regen

* bytes hash

* regen

* regen

* alias magic

* revert proto

* more alias magic

* revert build files

* regen

* define marshal methods

* tests passing

* hexbytes

* rem

* rem

* comment

* gaz

* data

* fix conf

* http tests

* sync

* client tests passing

* deepsource

* gaz

* item

* exec block by hash

* begin tests

* http tests passing

* payload id bytes

* proper json encode decode for payload id

* gaz

* proper marshal

* merge engine client

* use big ints

* passes

* confirmed passing

* add in functional methods

* deepsource

* pb

* Update beacon-chain/powchain/engine-api-client/v1/client_test.go

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

* latest

* tests passing again

Co-authored-by: terence tsao <terence@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2022-02-09 20:54:56 +00:00
Mohamed Zahoor
f89265f2f7 Adding a new method in HeaderFetcher (#10212)
* Is optimisyic for root

* add the function in mock chainservice also

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2022-02-09 20:21:15 +00:00
james-prysm
c731b715ed Keymanager-Kind: fix cli kind parsing and allow for backward compatability (#10211)
* initial commit with unit tests

* reverting and adding in comments
2022-02-09 14:40:52 -05:00
Radosław Kapka
2a68c69d8f Beacon Node API Postman collection (#10213)
Co-authored-by: james-prysm <90280386+james-prysm@users.noreply.github.com>
2022-02-09 18:42:23 +00:00
terence tsao
a82fd7bf68 Fix merge transition configs (#10206)
* Add proper merge configs

* Switch to bytes

* Use string

* Update mainnet_config.go

* Rm unused

* Fix test

* Update config_test.go

* Update beacon-chain/blockchain/pow_block.go

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

* Update pow_block_test.go

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2022-02-09 18:15:29 +00:00
james-prysm
9c540627ab default allowList for validator (#10210)
Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2022-02-09 17:18:49 +00:00
james-prysm
11f50453fc Keymanager api postman test collection (#10209)
* initial commit

* adding keymanager api repo url

* updated postman collection

* removing unused folder

* removing validator build

* Update hack/keymanager-api/README.md

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

* Update hack/keymanager-api/README.md

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

* Update hack/keymanager-api/README.md

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

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
2022-02-09 16:48:08 +00:00
Potuz
5f8b01ccda Make UpdateSyncedTips safe for context cancellation (#10174)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2022-02-09 14:54:27 +00:00
Nishant Das
d800107927 Add Peer Scorer to Dev Mode (#10207) 2022-02-09 13:51:59 +01:00
Nishant Das
d3d5cfca0b Peer Score Evaluator (#9717)
* eval stuff

* change up

* update dep

* go mod tidy

* gaz
2022-02-09 09:53:25 +00:00
terence tsao
924758a557 Merge branch 'develop' of github.com:prysmaticlabs/prysm into kintsugi 2022-02-08 18:28:31 -08:00
Potuz
18ef760ee5 Add DeleteBlock() (#10203)
* Add DeleteBlock()

* Raul review #1

* Update comments

Co-authored-by: terence tsao <terence@prysmaticlabs.com>
2022-02-08 23:26:26 +00:00
james-prysm
14e3e80df3 Keymanager api alignment (#10176)
* keymanager-api

* import updates to standards

* adding in more unit tests and code fixes to improve api experience

* deleting accidently generated files

* deleting accidently generated files

* adding in more test coverage

* fixing linter issue

* removing incorrect unit tests

* improving logic for accounts import

* linter fix

* addressing review comments

* fixing based on comments

* fixing nonzero root

* fixing protos

* regen protos

* adjusting protos again

* updating api specs

* fixing code and unit tests after specs changed

* fixing imports

* adding in required changes for api middleware also adding unit tests to catch changes for protos

* fixing deepsource issues

* fixing linting

* seeing if using pointers helps

* addressing comments

* updating bazel build

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2022-02-08 13:13:36 -06:00
Raul Jordan
3bea0e7896 ExecutionBlock Protobuf Type for the Merge (#10201)
* exec block

* exec block

* base fee

* regen

* exec block test

* fmt

* bytes for big ints

* engine pb

* passing

* add size

* bytes

* size

* size bytes

* passing
2022-02-08 18:06:02 +00:00
terence tsao
eedcb529fd Merge commit '8eaf3919189cd6d5f51904d8e9d74995ab70d4ac' into kintsugi 2022-02-08 07:43:49 -08:00
terence tsao
30e796a4f1 Update proposer.go 2022-02-08 07:29:51 -08:00
terence tsao
ea6ca456e6 Merge branch 'develop' of github.com:prysmaticlabs/prysm into kintsugi 2022-02-08 07:29:47 -08:00
Radosław Kapka
8455656597 Use beacon state interfaces instead of concrete structs (#10195)
* return interface from testing/util

* remove usages of v1

* return interface from InitializeFromProto

* return interface from InitializeFromProto

* fix test

* fix interface visibility

* more fixes

* use InitializeFromProtoUnsafe in testing/util

* return early error from mock

* v2

* fix tests

* remove unnecessary assertion

* use struct in nil state test

* Revert "Auxiliary commit to revert individual files from 6bb528c2c5df2446ad18450009f63f44318d41a9"

This reverts commit 7d70238a301209f6dbfc8ff1d81b16e33b0bd67d.

* use struct in sync committee test

* v3

* use InitializeFromProtoUnsafe in mock

* use version information

* Revert "Auxiliary commit to revert individual files from 6bb528c2c5df2446ad18450009f63f44318d41a9"

This reverts commit 5d5e6f2884d21caec7530c16ad2a0d0d27c44aa1.

* revert changes to ClearPreGenesisData

* fix build error

* remove error from PreGenesisState

* bzl
2022-02-08 09:30:06 +00:00
terence tsao
af8bafd895 Spectest 1.1.9 (#10199) 2022-02-07 20:50:11 -08:00
terence tsao
c538a6c068 Add propose bellatrix block (#10189)
* Add propose bellatrix block

* Update BUILD.bazel
2022-02-08 01:29:11 +00:00
terence tsao
4b75b991dd Fix merge transition block validation 2022-02-07 15:11:05 -08:00
Potuz
8eaf391918 allow optimistic sync 2022-02-07 17:35:17 -03:00
terence tsao
cbdb3c9e86 Merge branch 'develop' of github.com:prysmaticlabs/prysm into kintsugi 2022-02-07 12:02:32 -08:00
Raul Jordan
d5eb8392b6 Engine API Client Custom Marshaling (#10188)
* custom type marshaling

* gaz

* custom type

* marshalers

* builds

* builds

* add to build file

* regen

* only root types

* bytes hash

* regen

* bytes hash

* regen

* regen

* alias magic

* revert proto

* more alias magic

* revert build files

* regen

* define marshal methods

* tests passing

* hexbytes

* rem

* rem

* comment

* gaz

* data

* builds

* passing
2022-02-07 17:13:01 +00:00
Potuz
12754adddc Sync optimistically candidate blocks (#10193) 2022-02-07 07:22:45 -03:00
Potuz
08a5155ee3 Revert "Sync optimistically candidate blocks (#10193)"
This reverts commit f99a0419ef.
2022-02-07 07:20:40 -03:00
Potuz
f99a0419ef Sync optimistically candidate blocks (#10193) 2022-02-07 10:14:25 +00:00
terence tsao
4ad31f9c05 Sync with develop 2022-02-06 19:41:39 -08:00
Potuz
4906a0e6de add isOptimisticCandidateBlock and IsExecutionBlock (#10191)
* add isOptimisticCandidateBlock and IsExecutionBlock

* remove check

* fix tests

* Align with spec, reuse helper `ExecutionBlock`

Co-authored-by: terence tsao <terence@prysmaticlabs.com>
2022-02-07 01:26:20 +00:00
terence tsao
168e06e607 Save sync tips to DB (#10171)
* Save sync tips to DB

* Fix build

* Update process_block_test.go

* Copy map

* Revert back to nil

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2022-02-06 18:00:47 +00:00
terence tsao
26876d64d7 Clean ups 2022-02-04 14:20:37 -08:00
terence tsao
3450923661 Sync with develop 2022-02-04 10:08:46 -08:00
terence tsao
aba628b56b Merge branch 'develop' of github.com:prysmaticlabs/prysm into kintsugi 2022-01-28 13:59:31 -08:00
terence tsao
5effb92d11 Update mainnet_config.go 2022-01-27 11:40:45 -08:00
terence tsao
2b55368c99 sync with develop 2022-01-27 11:40:39 -08:00
terence tsao
327903b7bb Merge branch 'develop' of github.com:prysmaticlabs/prysm into kintsugi 2022-01-27 10:35:38 -08:00
terence tsao
77f815a39f Merge branch 'develop' of github.com:prysmaticlabs/prysm into kintsugi 2022-01-24 09:06:44 -08:00
terence tsao
80dc725412 sync with develop 2022-01-14 18:42:45 -08:00
terence tsao
263c18992e Update generate_keys.go 2022-01-13 15:26:54 -08:00
terence tsao
9e220f9052 Merge branch 'develop' of github.com:prysmaticlabs/prysm into kintsugi 2022-01-13 15:22:58 -08:00
terence tsao
99878d104c Merge branch 'develop' of github.com:prysmaticlabs/prysm into kintsugi 2022-01-12 10:40:04 -08:00
terence tsao
a870bf7a74 Clean up after sync 2022-01-10 18:50:27 -08:00
terence tsao
dc42ff382f Sync with develop 2022-01-10 11:20:05 -08:00
terence tsao
53b78a38a3 Merge branch 'develop' of github.com:prysmaticlabs/prysm into kintsugi 2022-01-10 11:07:23 -08:00
terence tsao
b45826e731 Speed up syncing, hide cosmetic errors 2022-01-04 10:15:40 -08:00
terence tsao
7b59ecac5e Sync with develop, fix payload nil check bug 2022-01-03 07:55:37 -08:00
terence tsao
9149178a9c Merge branch 'develop' of github.com:prysmaticlabs/prysm into kintsugi 2022-01-03 07:54:56 -08:00
terence tsao
51ef502b04 clean ups 2021-12-23 09:29:26 -08:00
terence tsao
8d891821ee Merge branch 'develop' of github.com:prysmaticlabs/prysm into kintsugi 2021-12-23 08:44:36 -08:00
terence tsao
762863ce6a Merge branch 'develop' of github.com:prysmaticlabs/prysm into kintsugi 2021-12-20 08:20:07 -08:00
terence tsao
41f5fa7524 visibility 2021-12-16 12:41:30 -08:00
terence tsao
09744bac70 correct gossip sizes this time 2021-12-16 11:57:17 -08:00
terence tsao
f5db847237 use merge gossip sizes 2021-12-16 11:15:00 -08:00
terence tsao
8600f70b0b sync with develop 2021-12-16 07:25:02 -08:00
terence tsao
6fe430de44 Merge branch 'develop' of github.com:prysmaticlabs/prysm into kintsugi 2021-12-16 07:23:52 -08:00
Zahoor Mohamed
42a5f96d3f ReverseByteOrder function does not mess the input 2021-12-15 22:19:50 +05:30
Mohamed Zahoor
e7f0fcf202 converting base fee to big endian format (#10018) 2021-12-15 06:41:06 -08:00
terence tsao
5ae564f1bf fix conflicts 2021-12-09 09:01:23 +01:00
terence tsao
719109c219 Merge branch 'develop' of github.com:prysmaticlabs/prysm into kintsugi 2021-12-09 08:42:02 +01:00
terence tsao
64533a4b0c Merge branch 'kintsugi' of github.com:prysmaticlabs/prysm into kintsugi 2021-12-08 17:27:01 +01:00
terence tsao
9fecd761d7 latest kintusgi execution api 2021-12-08 17:24:45 +01:00
Zahoor Mohamed
f84c95667c change EP field names 2021-12-08 21:52:03 +05:30
terence tsao
9af081797e Go mod tidy 2021-12-06 09:34:54 +01:00
terence tsao
e4e9f12c8b Merge branch 'develop' of github.com:prysmaticlabs/prysm into kintsugi 2021-12-06 09:24:49 +01:00
terence tsao
2f4e8beae6 Sync 2021-12-04 15:40:18 +01:00
terence tsao
81c7b90d26 Sync 2021-12-04 15:30:59 +01:00
Potuz
dd3d65ff18 Add v2 endpoint for merge blocks (#9802)
* Add V2 blocks endpoint for merge blocks

* Update beacon-chain/rpc/apimiddleware/structs.go

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

* go mod

* fix transactions

* Terence's comments

* add missing file

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
2021-12-01 14:09:28 -03:00
terence tsao
ac5a227aeb Fix transactions root 2021-11-29 13:56:58 -08:00
terence tsao
33f4d5c3cc Fix a bug with loading mainnet state 2021-11-29 09:59:41 -08:00
terence tsao
67d7f8baee State pkg cleanup 2021-11-24 11:29:01 -08:00
terence tsao
3c54aef7b1 Merge branch 'develop' of github.com:prysmaticlabs/prysm into kintsugi 2021-11-23 15:34:47 -08:00
terence tsao
938c28c42e Fix build 2021-11-23 14:55:31 -08:00
terence tsao
8ddb2c26c4 Merge commit '4858de787558c792b01aae44bc3902859b98fcac' of github.com:prysmaticlabs/prysm into kintsugi 2021-11-23 14:35:39 -08:00
terence tsao
cf0e78c2f6 Handle merge test case for update balance 2021-11-23 09:56:38 -08:00
terence tsao
4c0b262fdc Fix state merge 2021-11-23 09:13:50 -08:00
terence tsao
33e675e204 Update config to devnet1 2021-11-23 08:21:44 -08:00
terence tsao
e599f6a8a1 Fix build 2021-11-22 19:58:00 -08:00
terence tsao
49c9ab9fda Clean up conflicts 2021-11-22 19:40:57 -08:00
terence tsao
f90dec287b Merge branch 'develop' of github.com:prysmaticlabs/prysm into kintsugi 2021-11-22 19:29:07 -08:00
terence tsao
12c36cff9d Update state_trie.go 2021-11-17 08:07:26 -08:00
terence tsao
bc565d9ee6 Merge branch 'develop' of github.com:prysmaticlabs/prysm into kintsugi 2021-11-17 08:07:03 -08:00
terence tsao
db67d5bad8 Merge branch 'develop' of github.com:prysmaticlabs/prysm into kintsugi 2021-11-15 11:07:42 -08:00
terence tsao
3bc0c2be54 Merge branch 'develop' into kintsugi 2021-11-15 09:42:21 -08:00
terence tsao
1bed9ef749 Sync with develop 2021-11-15 09:41:24 -08:00
terence tsao
ec772beeaf Merge branch 'develop' of github.com:prysmaticlabs/prysm into kintsugi 2021-11-15 09:35:29 -08:00
Mohamed Zahoor
56407dde02 Change Gossip message size and Chunk SIze from 1 MB t0 10MB (#9860)
* change gossip size and chunk size after merge

* change ssz to accomodate both changes

* gofmt config file

* add testcase for merge MsgId

* Update beacon-chain/p2p/message_id.go

Change MB to Mib in comment

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

* change function name from altairMsgID to postAltairMsgID

Co-authored-by: terence tsao <terence@prysmaticlabs.com>
2021-11-15 10:37:02 +05:30
terence tsao
445f17881e Fix bad hex conversion 2021-11-12 11:56:22 -08:00
terence tsao
183d40d8f1 Merge branch 'develop' of github.com:prysmaticlabs/prysm into kintsugi 2021-11-11 09:36:26 -08:00
terence tsao
87bc6aa5e5 Manually override nil transaction field. M2 works 2021-11-09 16:06:01 -08:00
terence tsao
5b5065b01d Remove unused merge genesis state gen tool 2021-11-09 11:09:59 -08:00
terence tsao
ee1c567561 Remove secp256k1 2021-11-09 08:43:10 -08:00
terence tsao
ff1416c98d Update Kintsugi consensus implementations (#9872) 2021-11-08 21:26:58 -08:00
terence tsao
471c94031f Update spec test shas 2021-11-08 19:39:13 -08:00
terence tsao
9863fb3d6a All spec tests pass 2021-11-08 19:31:28 -08:00
kasey
f3c2d1a00b Kintsugi ssz (#9867) 2021-11-08 18:42:23 -08:00
terence tsao
5d8879a4df Update Kintsugi engine API (#9865) 2021-11-08 09:56:14 -08:00
terence tsao
abea0a11bc Update WORKSPACE 2021-11-05 12:06:19 -07:00
terence tsao
80ce1603bd Merge branch 'kintsugi' of github.com:prysmaticlabs/prysm into kintsugi 2021-11-03 20:40:22 -07:00
terence tsao
ca478244e0 Add and use TBH_ACTIVATION_EPOCH 2021-11-03 20:39:51 -07:00
terence tsao
8a864b66a1 Add and use 2021-11-03 20:38:40 -07:00
terence tsao
72f3b9e84b Remove extraneous p2p condition 2021-11-03 19:17:12 -07:00
terence tsao
493e95060f Fix gossip and tx size limits for the merge part 1 2021-11-03 17:03:06 -07:00
terence tsao
e7e1ecd72f Update penalty params for Merge 2021-11-03 16:37:17 -07:00
terence tsao
c286ac8b87 Remove gas validations 2021-11-03 14:47:33 -07:00
terence tsao
bde315224c Merge branch 'develop' of github.com:prysmaticlabs/prysm into merge-oct 2021-11-03 12:52:50 -07:00
terence tsao
00520705bc Sync with develop 2021-11-02 20:52:33 -07:00
Zahoor Mohamed
c7fcd804d7 all gossip tests passing 2021-10-27 18:48:22 +05:30
terence tsao
985ac2e848 Update htrutils.go 2021-10-24 11:35:59 -07:00
terence tsao
f4a0e98926 Disable genesis ETH1.0 chain header logging 2021-10-19 22:13:59 -07:00
terence tsao
5f93ff10ea Merge: switch from go bindings to raw rpc calls (#9803) 2021-10-19 21:00:11 -07:00
terence tsao
544248f60f Go fmt 2021-10-18 22:38:57 -07:00
terence tsao
3b41968510 Merge branch 'merge-oct' of github.com:prysmaticlabs/prysm into merge-oct 2021-10-18 22:38:21 -07:00
terence tsao
7fc418042a Disable deposit contract lookback 2021-10-18 22:38:09 -07:00
terence tsao
9a03946706 Disable contract lookback 2021-10-18 22:34:50 -07:00
terence tsao
33dd6dd5f2 Use proper receive block path for initial syncing 2021-10-18 21:28:16 -07:00
terence tsao
56542e1958 Correctly upgrade to merge state + object mapping fixes 2021-10-18 17:46:55 -07:00
terence tsao
e82d7b4c0b Use uint64 for ttd 2021-10-18 14:00:45 -07:00
terence tsao
6cb69d8ff0 Merge branch 'develop' of github.com:prysmaticlabs/prysm into merge-oct 2021-10-18 09:26:42 -07:00
terence tsao
70b55a0191 Proper upgrade altair to merge state 2021-10-15 12:48:21 -07:00
terence tsao
50f4951194 Various fixes to pass all spec tests for Merge (#9777) 2021-10-14 15:34:31 -07:00
terence tsao
1a14f2368d Merge branch 'develop' of github.com:prysmaticlabs/prysm into merge-oct 2021-10-14 11:52:28 -07:00
terence tsao
bb8cad58f1 Update beacon_block.pb.go 2021-10-13 13:49:16 -07:00
terence tsao
05412c1f0e Update mainnet_config.go 2021-10-13 13:26:48 -07:00
terence tsao
b03441fed8 Fix finding terminal block hash calculation 2021-10-13 11:29:17 -07:00
terence tsao
fa7d7cef69 Merge: support terminal difficulty override (#9769) 2021-10-12 20:40:01 -07:00
terence tsao
1caa6c969f Merge branch 'develop' of github.com:prysmaticlabs/prysm into merge-oct 2021-10-12 09:43:42 -07:00
Kasey Kirkham
eeb7d5bbfb tell bazel about this new file 2021-10-08 13:31:57 -05:00
Kasey Kirkham
d7c7d150b1 separate ExecutionPayload/Header from codegen 2021-10-08 11:06:21 -05:00
Kasey Kirkham
63c4d2eb2b defensive nil check 2021-10-08 09:18:02 -05:00
Kasey Kirkham
9de1f694a0 restoring generated pb field ordering 2021-10-08 08:16:43 -05:00
terence tsao
8a79d06cbd Fix bazel build //... 2021-10-07 15:31:49 -07:00
terence tsao
5290ad93b8 Merge conflict. Sync with upstream 2021-10-07 15:07:29 -07:00
terence tsao
2128208ef7 M2 works with Geth 🎉 2021-10-07 14:57:20 -07:00
Kasey Kirkham
296323719c get rid of codegen garbage 2021-10-07 16:31:35 -05:00
Kasey Kirkham
5e9583ea85 noisy commit, restoring pb field order codegen 2021-10-07 15:59:28 -05:00
Zahoor Mohamed
17196e0f80 changes test cases per ssz changes 2021-10-08 01:39:30 +05:30
kasey
c50d54000d Merge union debugging (#9751) 2021-10-07 10:44:26 -07:00
terence tsao
85b3061d1b Update go commit 2021-10-07 10:10:46 -07:00
terence tsao
0146c5317a Merge branch 'develop' of github.com:prysmaticlabs/prysm into merge-oct 2021-10-07 09:06:55 -07:00
Zahoor Mohamed
fcbc48ffd9 fix finding Transactions size 2021-10-07 14:16:15 +05:30
terence tsao
76ee51af9d Interop merge beacon state 2021-10-06 17:22:47 -07:00
terence tsao
370b0b97ed Fix beacon chain build 2021-10-06 14:41:43 -07:00
terence tsao
990ebd3fe3 Merge branch 'develop' of github.com:prysmaticlabs/prysm into merge-oct 2021-10-06 14:34:33 -07:00
Zahoor Mohamed
54449c72e8 Merge branch 'merge-oct' of https://github.com/prysmaticlabs/prysm into merge-oct 2021-10-06 23:53:43 +05:30
Zahoor Mohamed
1dbd0b98eb add merge specific checks when receiving a block from gossip 2021-10-06 23:53:24 +05:30
terence tsao
09c3896c6b Go fmt 2021-10-06 09:38:24 -07:00
terence tsao
d494845e19 Merge branch 'develop' of github.com:prysmaticlabs/prysm into merge-oct 2021-10-06 09:36:13 -07:00
terence tsao
4d0c0f7234 Update todo strings 2021-10-05 14:43:01 -07:00
terence tsao
bfe570b1aa Merge branch 'merge-oct-net' of github.com:prysmaticlabs/prysm into merge-oct 2021-10-05 14:41:24 -07:00
terence tsao
56db696823 Clean up and fix a test 2021-10-05 14:38:09 -07:00
terence tsao
d312e15db8 Clean up misc state store 2021-10-05 14:17:44 -07:00
terence tsao
907d4cf7e6 Clean up validator additions 2021-10-05 14:06:03 -07:00
terence tsao
891353d6ad Clean up beacon chain additions 2021-10-05 11:28:36 -07:00
terence tsao
0adc08660c Rest of the validator changes 2021-10-05 10:18:26 -07:00
terence tsao
de31425dcd Add proposer get execution payload helpers 2021-10-04 16:37:22 -07:00
terence tsao
2094e0f21f Update rpc service and proposer get block 2021-10-04 16:37:01 -07:00
terence tsao
2c6f554500 Update process_block.go 2021-10-04 10:45:56 -07:00
terence tsao
18a1e07711 Update and use forked go-ethereum with catalyst go binding 2021-10-04 10:45:39 -07:00
prestonvanloon
5e432f5aaa Use MariusVanDerWijden go-ethereum fork with latest catalyst updates 2021-10-03 22:05:21 -05:00
prestonvanloon
284e2696cb Merge branch 'rm-bazel-go-ethereum' of github.com:prysmaticlabs/prysm into merge-oct 2021-10-03 21:52:13 -05:00
terence tsao
7547aaa6ce Fix build, update comments 2021-10-03 19:11:43 -07:00
prestonvanloon
953315c2cc fix geth e2e flags 2021-10-03 14:01:26 -05:00
terence tsao
9662d06b08 Update catalyst merge commit 2021-10-03 11:51:12 -07:00
prestonvanloon
ecaea26ace fix geth e2e flags 2021-10-03 13:31:52 -05:00
prestonvanloon
63819e2690 move vendor stuff to third_party so that go mod wont be mad anymore 2021-10-03 13:21:27 -05:00
prestonvanloon
a6d0cd06b3 Remove bazel-go-ethereum, use vendored libraries only 2021-10-03 13:11:50 -05:00
prestonvanloon
2dbe4f5e67 viz improvement 2021-10-03 13:11:26 -05:00
prestonvanloon
2689d6814d Add karalabe/usb 2021-10-03 13:11:16 -05:00
prestonvanloon
69a681ddc0 gaz 2021-10-03 12:29:17 -05:00
prestonvanloon
7f9f1fd36c Check in go-ethereum crypto/sepc256k1 package with proper build rules 2021-10-03 12:27:40 -05:00
terence tsao
57c97eb561 Merge branch 'develop' of github.com:prysmaticlabs/prysm into merge-oct 2021-10-03 09:42:34 -07:00
terence tsao
f0f94a8193 Handle more version merge cases 2021-10-02 11:43:50 -07:00
Zahoor Mohamed
87b0bf2c2a fix more merge conflicts 2021-10-02 12:27:12 +05:30
Zahoor Mohamed
d8ad317dec fix mrge conflicts 2021-10-02 12:19:29 +05:30
terence tsao
ab5f488cf4 Fix spectest merge fork 2021-10-01 16:27:21 -07:00
terence tsao
296d7464ad Add powchain execution methods 2021-10-01 16:07:33 -07:00
terence tsao
221c542e4f Go mod tidy and build 2021-10-01 13:43:57 -07:00
terence tsao
7ad32aaa96 Add execution caller engine interface 2021-10-01 12:59:04 -07:00
terence tsao
3dc0969c0c Point go-ethereum to https://github.com/ethereum/go-ethereum/pull/23607 2021-10-01 08:30:15 -07:00
Zahoor Mohamed
0e18e835c3 req/resp structure has not changed. so no need of a new version 2021-09-30 21:34:19 +05:30
terence tsao
8adfbfc382 Update sync_committee.go 2021-09-30 08:21:40 -07:00
Zahoor Mohamed
68b0b5e0ce add merge in fork watcher 2021-09-30 14:09:18 +05:30
terence tsao
eede309e0f Fix build 2021-09-29 16:26:13 -07:00
terence tsao
b11628dc53 Can configure flags 2021-09-29 16:04:39 -07:00
terence tsao
ea3ae22d3b Merge branch 'develop' of github.com:prysmaticlabs/prysm into merge-oct 2021-09-29 14:25:16 -07:00
terence tsao
02bb39ddeb Minor clean up to improve readability 2021-09-29 10:21:00 -07:00
terence tsao
1618c1f55d Fix comment 2021-09-29 07:57:43 -07:00
terence tsao
73c8493fd7 Merge branch 'develop' of github.com:prysmaticlabs/prysm into merge-oct 2021-09-28 14:54:24 -07:00
terence tsao
a4f59a4f15 Forkchoice and upgrade changes 2021-09-28 14:53:11 -07:00
Zahoor Mohamed
3c497efdb8 Merge branch 'merge-oct' of https://github.com/prysmaticlabs/prysm into merge-oct-net 2021-09-28 21:58:22 +05:30
Zahoor Mohamed
9f5daafbb7 initial networking code 2021-09-28 20:02:47 +05:30
terence tsao
11d7ffdfa8 Add merge spec tests 2021-09-26 11:07:31 -07:00
terence tsao
c26b3305e6 Resolve conflict 2021-09-25 09:49:53 -07:00
terence tsao
38d8b63fbf Merge branch 'develop' of github.com:prysmaticlabs/prysm into merge-oct 2021-09-25 09:15:20 -07:00
terence tsao
aea67405c8 Add upgrade to merge path 2021-09-21 14:34:03 -07:00
terence tsao
57d830f8b3 Add wrapper, cloner and interface 2021-09-21 13:34:10 -07:00
terence tsao
ac4b1ef4ea Merge branch 'develop' of github.com:prysmaticlabs/prysm into merge-oct 2021-09-21 13:07:01 -07:00
terence tsao
1d32119f5a can process execution header 2021-09-20 17:08:53 -07:00
terence tsao
3540cc7b05 Add state v3 2021-09-16 21:31:08 -07:00
terence tsao
191e7767a6 Add beacon block and state protos 2021-09-16 16:15:55 -07:00
285 changed files with 7149 additions and 2044 deletions

View File

@@ -222,7 +222,7 @@ filegroup(
url = "https://github.com/eth-clients/slashing-protection-interchange-tests/archive/b8413ca42dc92308019d0d4db52c87e9e125c4e9.tar.gz",
)
consensus_spec_version = "v1.1.8"
consensus_spec_version = "v1.1.9"
bls_test_version = "v0.1.1"
@@ -238,7 +238,7 @@ filegroup(
visibility = ["//visibility:public"],
)
""",
sha256 = "e4d2b7830e85734442d7172887dcd4edc0985d6256bafedb3353ab477a1433c0",
sha256 = "207d9c326ba4fa1f34bab7b6169201c32f2611755db030909a3405873445e0ba",
url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/general.tar.gz" % consensus_spec_version,
)
@@ -254,7 +254,7 @@ filegroup(
visibility = ["//visibility:public"],
)
""",
sha256 = "4a88d01ad12260220ab5c8efdeec6534bac48a47f29ba4f7977ea14c9d07b0fe",
sha256 = "a3995b39f412db236b2f1db909f288218da53cb53b9923b71dda9d144d68f40a",
url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/minimal.tar.gz" % consensus_spec_version,
)
@@ -270,7 +270,7 @@ filegroup(
visibility = ["//visibility:public"],
)
""",
sha256 = "0033fe107d9d2adb8d4fcb60dfb1c43fc5a54f0af970525c962124221757c266",
sha256 = "76cea7a4c8e32d458ad456b54bfbb30bc772481a91954a4cd97e229aa3023b1d",
url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/mainnet.tar.gz" % consensus_spec_version,
)
@@ -285,7 +285,7 @@ filegroup(
visibility = ["//visibility:public"],
)
""",
sha256 = "3fc3b8809d140a1ab61350fbd410f33add2851a63829d874dcb620babba603de",
sha256 = "0fc429684775f943250dce1f9c485ac25e26c6395d7f585c8d1317becec2ace7",
strip_prefix = "consensus-specs-" + consensus_spec_version[1:],
url = "https://github.com/ethereum/consensus-specs/archive/refs/tags/%s.tar.gz" % consensus_spec_version,
)

View File

@@ -12,6 +12,7 @@ go_library(
"log.go",
"metrics.go",
"new_slot.go",
"optimistic_sync.go",
"options.go",
"pow_block.go",
"process_attestation.go",
@@ -38,6 +39,7 @@ go_library(
"//beacon-chain/cache:go_default_library",
"//beacon-chain/cache/depositcache:go_default_library",
"//beacon-chain/core/altair:go_default_library",
"//beacon-chain/core/blocks:go_default_library",
"//beacon-chain/core/epoch/precompute:go_default_library",
"//beacon-chain/core/feed:go_default_library",
"//beacon-chain/core/feed/state:go_default_library",
@@ -54,6 +56,7 @@ go_library(
"//beacon-chain/operations/voluntaryexits:go_default_library",
"//beacon-chain/p2p:go_default_library",
"//beacon-chain/powchain:go_default_library",
"//beacon-chain/powchain/engine-api-client/v1:go_default_library",
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/stategen:go_default_library",
"//cmd/beacon-chain/flags:go_default_library",
@@ -63,6 +66,7 @@ go_library(
"//crypto/bls:go_default_library",
"//encoding/bytesutil:go_default_library",
"//monitoring/tracing:go_default_library",
"//proto/engine/v1:go_default_library",
"//proto/eth/v1:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//proto/prysm/v1alpha1/attestation:go_default_library",
@@ -71,6 +75,7 @@ go_library(
"//time:go_default_library",
"//time/slots:go_default_library",
"@com_github_emicklei_dot//:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_holiman_uint256//:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_prometheus_client_golang//prometheus:go_default_library",
@@ -103,6 +108,7 @@ go_test(
"log_test.go",
"metrics_test.go",
"mock_test.go",
"optimistic_sync_test.go",
"pow_block_test.go",
"process_attestation_test.go",
"process_block_test.go",

View File

@@ -36,7 +36,7 @@ type TimeFetcher interface {
// GenesisFetcher retrieves the Ethereum consensus data related to its genesis.
type GenesisFetcher interface {
GenesisValidatorRoot() [32]byte
GenesisValidatorsRoot() [32]byte
}
// HeadFetcher defines a common interface for methods in blockchain service which
@@ -48,13 +48,14 @@ type HeadFetcher interface {
HeadState(ctx context.Context) (state.BeaconState, error)
HeadValidatorsIndices(ctx context.Context, epoch types.Epoch) ([]types.ValidatorIndex, error)
HeadSeed(ctx context.Context, epoch types.Epoch) ([32]byte, error)
HeadGenesisValidatorRoot() [32]byte
HeadGenesisValidatorsRoot() [32]byte
HeadETH1Data() *ethpb.Eth1Data
HeadPublicKeyToValidatorIndex(pubKey [fieldparams.BLSPubkeyLength]byte) (types.ValidatorIndex, bool)
HeadValidatorIndexToPublicKey(ctx context.Context, index types.ValidatorIndex) ([fieldparams.BLSPubkeyLength]byte, error)
ProtoArrayStore() *protoarray.Store
ChainHeads() ([][32]byte, []types.Slot)
IsOptimistic(ctx context.Context) (bool, error)
IsOptimisticForRoot(ctx context.Context, root [32]byte, slot types.Slot) (bool, error)
HeadSyncCommitteeFetcher
HeadDomainFetcher
}
@@ -213,8 +214,8 @@ func (s *Service) HeadSeed(ctx context.Context, epoch types.Epoch) ([32]byte, er
return helpers.Seed(s.headState(ctx), epoch, params.BeaconConfig().DomainBeaconAttester)
}
// HeadGenesisValidatorRoot returns genesis validator root of the head state.
func (s *Service) HeadGenesisValidatorRoot() [32]byte {
// HeadGenesisValidatorsRoot returns genesis validators root of the head state.
func (s *Service) HeadGenesisValidatorsRoot() [32]byte {
s.headLock.RLock()
defer s.headLock.RUnlock()
@@ -222,7 +223,7 @@ func (s *Service) HeadGenesisValidatorRoot() [32]byte {
return [32]byte{}
}
return s.headGenesisValidatorRoot()
return s.headGenesisValidatorsRoot()
}
// HeadETH1Data returns the eth1data of the current head state.
@@ -246,16 +247,16 @@ func (s *Service) GenesisTime() time.Time {
return s.genesisTime
}
// GenesisValidatorRoot returns the genesis validator
// GenesisValidatorsRoot returns the genesis validator
// root of the chain.
func (s *Service) GenesisValidatorRoot() [32]byte {
func (s *Service) GenesisValidatorsRoot() [32]byte {
s.headLock.RLock()
defer s.headLock.RUnlock()
if !s.hasHeadState() {
return [32]byte{}
}
return bytesutil.ToBytes32(s.head.state.GenesisValidatorRoot())
return bytesutil.ToBytes32(s.head.state.GenesisValidatorsRoot())
}
// CurrentFork retrieves the latest fork information of the beacon chain.
@@ -336,6 +337,12 @@ func (s *Service) IsOptimistic(ctx context.Context) (bool, error) {
return s.cfg.ForkChoiceStore.Optimistic(ctx, s.head.root, s.head.slot)
}
// IsOptimisticForRoot takes the root and slot as aguments instead of the current head
// and returns true if it is optimistic.
func (s *Service) IsOptimisticForRoot(ctx context.Context, root [32]byte, slot types.Slot) (bool, error) {
return s.cfg.ForkChoiceStore.Optimistic(ctx, root, slot)
}
// SetGenesisTime sets the genesis time of beacon chain.
func (s *Service) SetGenesisTime(t time.Time) {
s.genesisTime = t

View File

@@ -185,15 +185,15 @@ func TestCurrentFork_NilHeadSTate(t *testing.T) {
}
}
func TestGenesisValidatorRoot_CanRetrieve(t *testing.T) {
func TestGenesisValidatorsRoot_CanRetrieve(t *testing.T) {
// Should not panic if head state is nil.
c := &Service{}
assert.Equal(t, [32]byte{}, c.GenesisValidatorRoot(), "Did not get correct genesis validator root")
assert.Equal(t, [32]byte{}, c.GenesisValidatorsRoot(), "Did not get correct genesis validators root")
s, err := v1.InitializeFromProto(&ethpb.BeaconState{GenesisValidatorsRoot: []byte{'a'}})
require.NoError(t, err)
c.head = &head{state: s}
assert.Equal(t, [32]byte{'a'}, c.GenesisValidatorRoot(), "Did not get correct genesis validator root")
assert.Equal(t, [32]byte{'a'}, c.GenesisValidatorsRoot(), "Did not get correct genesis validators root")
}
func TestHeadETH1Data_Nil(t *testing.T) {
@@ -265,17 +265,17 @@ func TestService_HeadSeed(t *testing.T) {
require.DeepEqual(t, seed, root)
}
func TestService_HeadGenesisValidatorRoot(t *testing.T) {
func TestService_HeadGenesisValidatorsRoot(t *testing.T) {
s, _ := util.DeterministicGenesisState(t, 1)
c := &Service{}
c.head = &head{}
root := c.HeadGenesisValidatorRoot()
root := c.HeadGenesisValidatorsRoot()
require.Equal(t, [32]byte{}, root)
c.head = &head{state: s}
root = c.HeadGenesisValidatorRoot()
require.DeepEqual(t, root[:], s.GenesisValidatorRoot())
root = c.HeadGenesisValidatorsRoot()
require.DeepEqual(t, root[:], s.GenesisValidatorsRoot())
}
func TestService_ProtoArrayStore(t *testing.T) {
@@ -366,3 +366,14 @@ func TestService_IsOptimistic(t *testing.T) {
require.NoError(t, err)
require.Equal(t, true, opt)
}
func TestService_IsOptimisticForRoot(t *testing.T) {
ctx := context.Background()
c := &Service{cfg: &config{ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}, head: &head{slot: 101, root: [32]byte{'b'}}}
require.NoError(t, c.cfg.ForkChoiceStore.ProcessBlock(ctx, 100, [32]byte{'a'}, [32]byte{}, [32]byte{}, 0, 0))
require.NoError(t, c.cfg.ForkChoiceStore.ProcessBlock(ctx, 101, [32]byte{'b'}, [32]byte{'a'}, [32]byte{}, 0, 0))
opt, err := c.IsOptimisticForRoot(ctx, [32]byte{'a'}, 100)
require.NoError(t, err)
require.Equal(t, true, opt)
}

View File

@@ -265,10 +265,10 @@ func (s *Service) headState(ctx context.Context) state.BeaconState {
return s.head.state.Copy()
}
// This returns the genesis validator root of the head state.
// This returns the genesis validators root of the head state.
// This is a lock free version.
func (s *Service) headGenesisValidatorRoot() [32]byte {
return bytesutil.ToBytes32(s.head.state.GenesisValidatorRoot())
func (s *Service) headGenesisValidatorsRoot() [32]byte {
return bytesutil.ToBytes32(s.head.state.GenesisValidatorsRoot())
}
// This returns the validator referenced by the provided index in

View File

@@ -130,7 +130,7 @@ func (s *Service) domainWithHeadState(ctx context.Context, slot types.Slot, doma
if err != nil {
return nil, err
}
return signing.Domain(headState.Fork(), slots.ToEpoch(headState.Slot()), domain, headState.GenesisValidatorRoot())
return signing.Domain(headState.Fork(), slots.ToEpoch(headState.Slot()), domain, headState.GenesisValidatorsRoot())
}
// returns the head state that is advanced up to `slot`. It utilizes the cache `syncCommitteeHeadState` by retrieving using `slot` as key.

View File

@@ -122,7 +122,7 @@ func TestService_HeadSyncCommitteeDomain(t *testing.T) {
c := &Service{}
c.head = &head{state: s}
wanted, err := signing.Domain(s.Fork(), slots.ToEpoch(s.Slot()), params.BeaconConfig().DomainSyncCommittee, s.GenesisValidatorRoot())
wanted, err := signing.Domain(s.Fork(), slots.ToEpoch(s.Slot()), params.BeaconConfig().DomainSyncCommittee, s.GenesisValidatorsRoot())
require.NoError(t, err)
d, err := c.HeadSyncCommitteeDomain(context.Background(), 0)
@@ -136,7 +136,7 @@ func TestService_HeadSyncContributionProofDomain(t *testing.T) {
c := &Service{}
c.head = &head{state: s}
wanted, err := signing.Domain(s.Fork(), slots.ToEpoch(s.Slot()), params.BeaconConfig().DomainContributionAndProof, s.GenesisValidatorRoot())
wanted, err := signing.Domain(s.Fork(), slots.ToEpoch(s.Slot()), params.BeaconConfig().DomainContributionAndProof, s.GenesisValidatorsRoot())
require.NoError(t, err)
d, err := c.HeadSyncContributionProofDomain(context.Background(), 0)
@@ -150,7 +150,7 @@ func TestService_HeadSyncSelectionProofDomain(t *testing.T) {
c := &Service{}
c.head = &head{state: s}
wanted, err := signing.Domain(s.Fork(), slots.ToEpoch(s.Slot()), params.BeaconConfig().DomainSyncCommitteeSelectionProof, s.GenesisValidatorRoot())
wanted, err := signing.Domain(s.Fork(), slots.ToEpoch(s.Slot()), params.BeaconConfig().DomainSyncCommitteeSelectionProof, s.GenesisValidatorsRoot())
require.NoError(t, err)
d, err := c.HeadSyncSelectionProofDomain(context.Background(), 0)

View File

@@ -51,11 +51,11 @@ func logBlockSyncStatus(block block.BeaconBlock, blockRoot [32]byte, finalized *
log.WithFields(logrus.Fields{
"slot": block.Slot(),
"slotInEpoch": block.Slot() % params.BeaconConfig().SlotsPerEpoch,
"block": fmt.Sprintf("0x%s...", hex.EncodeToString(blockRoot[:])[:8]),
"blockRoot": fmt.Sprintf("0x%s...", hex.EncodeToString(blockRoot[:])[:8]),
"parentRoot": fmt.Sprintf("0x%s...", hex.EncodeToString(blockRoot[:])[:8]),
"epoch": slots.ToEpoch(block.Slot()),
"finalizedEpoch": finalized.Epoch,
"finalizedRoot": fmt.Sprintf("0x%s...", hex.EncodeToString(finalized.Root)[:8]),
"parentRoot": fmt.Sprintf("0x%s...", hex.EncodeToString(block.ParentRoot())[:8]),
"version": version.String(block.Version()),
}).Info("Synced new block")
log.WithFields(logrus.Fields{

View File

@@ -0,0 +1,53 @@
package blockchain
import (
"context"
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/config/params"
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
)
// optimisticCandidateBlock returns true if this block can be optimistically synced.
//
// Spec pseudocode definition:
// def is_optimistic_candidate_block(opt_store: OptimisticStore, current_slot: Slot, block: BeaconBlock) -> bool:
// justified_root = opt_store.block_states[opt_store.head_block_root].current_justified_checkpoint.root
// justified_is_execution_block = is_execution_block(opt_store.blocks[justified_root])
// block_is_deep = block.slot + SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY <= current_slot
// return justified_is_execution_block or block_is_deep
func (s *Service) optimisticCandidateBlock(ctx context.Context, blk block.BeaconBlock) (bool, error) {
if blk.Slot()+params.BeaconConfig().SafeSlotsToImportOptimistically <= s.CurrentSlot() {
return true, nil
}
j := s.store.JustifiedCheckpt()
if j == nil {
return false, errNilJustifiedInStore
}
jBlock, err := s.cfg.BeaconDB.Block(ctx, bytesutil.ToBytes32(j.Root))
if err != nil {
return false, err
}
return blocks.ExecutionBlock(jBlock.Block().Body())
}
// loadSyncedTips loads a previously saved synced Tips from DB
// if no synced tips are saved, then it creates one from the given
// root and slot number.
func (s *Service) loadSyncedTips(root [32]byte, slot types.Slot) error {
// Initialize synced tips
tips, err := s.cfg.BeaconDB.ValidatedTips(s.ctx)
if err != nil || len(tips) == 0 {
tips[root] = slot
if err != nil {
log.WithError(err).Warn("Could not read synced tips from DB, using finalized checkpoint as synced tip")
}
}
if err := s.cfg.ForkChoiceStore.SetSyncedTips(tips); err != nil {
return errors.Wrap(err, "could not set synced tips")
}
return nil
}

View File

@@ -0,0 +1,141 @@
package blockchain
import (
"context"
"testing"
"time"
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
"github.com/prysmaticlabs/prysm/config/params"
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
"github.com/prysmaticlabs/prysm/testing/require"
"github.com/prysmaticlabs/prysm/testing/util"
"github.com/prysmaticlabs/prysm/time/slots"
)
func Test_IsOptimisticCandidateBlock(t *testing.T) {
params.SetupTestConfigCleanup(t)
params.OverrideBeaconConfig(params.MainnetConfig())
ctx := context.Background()
beaconDB := testDB.SetupDB(t)
fcs := protoarray.New(0, 0, [32]byte{'a'})
opts := []Option{
WithDatabase(beaconDB),
WithStateGen(stategen.New(beaconDB)),
WithForkChoiceStore(fcs),
}
service, err := NewService(ctx, opts...)
require.NoError(t, err)
params.BeaconConfig().SafeSlotsToImportOptimistically = 128
service.genesisTime = time.Now().Add(-time.Second * 12 * 2 * 128)
tests := []struct {
name string
blk block.BeaconBlock
justified block.SignedBeaconBlock
want bool
}{
{
name: "deep block",
blk: func(tt *testing.T) block.BeaconBlock {
blk := util.NewBeaconBlockBellatrix()
blk.Block.Slot = 1
wr, err := wrapper.WrappedBellatrixBeaconBlock(blk.Block)
require.NoError(tt, err)
return wr
}(t),
justified: func(tt *testing.T) block.SignedBeaconBlock {
blk := util.NewBeaconBlockBellatrix()
blk.Block.Slot = 32
wr, err := wrapper.WrappedBellatrixSignedBeaconBlock(blk)
require.NoError(tt, err)
return wr
}(t),
want: true,
},
{
name: "shallow block, Altair justified chkpt",
blk: func(tt *testing.T) block.BeaconBlock {
blk := util.NewBeaconBlockAltair()
blk.Block.Slot = 200
wr, err := wrapper.WrappedAltairBeaconBlock(blk.Block)
require.NoError(tt, err)
return wr
}(t),
justified: func(tt *testing.T) block.SignedBeaconBlock {
blk := util.NewBeaconBlockAltair()
blk.Block.Slot = 32
wr, err := wrapper.WrappedAltairSignedBeaconBlock(blk)
require.NoError(tt, err)
return wr
}(t),
want: false,
},
{
name: "shallow block, Bellatrix justified chkpt without execution",
blk: func(tt *testing.T) block.BeaconBlock {
blk := util.NewBeaconBlockBellatrix()
blk.Block.Slot = 200
wr, err := wrapper.WrappedBellatrixBeaconBlock(blk.Block)
require.NoError(tt, err)
return wr
}(t),
justified: func(tt *testing.T) block.SignedBeaconBlock {
blk := util.NewBeaconBlockBellatrix()
blk.Block.Slot = 32
wr, err := wrapper.WrappedBellatrixSignedBeaconBlock(blk)
require.NoError(tt, err)
return wr
}(t),
want: false,
},
{
name: "shallow block, execution enabled justified chkpt",
blk: func(tt *testing.T) block.BeaconBlock {
blk := util.NewBeaconBlockBellatrix()
blk.Block.Slot = 200
wr, err := wrapper.WrappedBellatrixBeaconBlock(blk.Block)
require.NoError(tt, err)
return wr
}(t),
justified: func(tt *testing.T) block.SignedBeaconBlock {
blk := util.NewBeaconBlockBellatrix()
blk.Block.Slot = 32
blk.Block.Body.ExecutionPayload.ParentHash = bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength)
blk.Block.Body.ExecutionPayload.FeeRecipient = bytesutil.PadTo([]byte{'a'}, fieldparams.FeeRecipientLength)
blk.Block.Body.ExecutionPayload.StateRoot = bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength)
blk.Block.Body.ExecutionPayload.ReceiptsRoot = bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength)
blk.Block.Body.ExecutionPayload.LogsBloom = bytesutil.PadTo([]byte{'a'}, fieldparams.LogsBloomLength)
blk.Block.Body.ExecutionPayload.Random = bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength)
blk.Block.Body.ExecutionPayload.BaseFeePerGas = bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength)
blk.Block.Body.ExecutionPayload.BlockHash = bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength)
wr, err := wrapper.WrappedBellatrixSignedBeaconBlock(blk)
require.NoError(tt, err)
return wr
}(t),
want: true,
},
}
for _, tt := range tests {
jroot, err := tt.justified.Block().HashTreeRoot()
require.NoError(t, err)
require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, tt.justified))
service.store.SetJustifiedCheckpt(
&ethpb.Checkpoint{
Root: jroot[:],
Epoch: slots.ToEpoch(tt.justified.Block().Slot()),
})
candidate, err := service.optimisticCandidateBlock(ctx, tt.blk)
require.NoError(t, err)
require.Equal(t, tt.want, candidate, tt.name)
}
}

View File

@@ -11,6 +11,7 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits"
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
v1 "github.com/prysmaticlabs/prysm/beacon-chain/powchain/engine-api-client/v1"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
@@ -50,6 +51,14 @@ func WithChainStartFetcher(f powchain.ChainStartFetcher) Option {
}
}
// WithExecutionEngineCaller to call execution engine.
func WithExecutionEngineCaller(c v1.EngineCaller) Option {
return func(s *Service) error {
s.cfg.ExecutionEngineCaller = c
return nil
}
}
// WithDepositCache for deposit lifecycle after chain inclusion.
func WithDepositCache(c *depositcache.DepositCache) Option {
return func(s *Service) error {

View File

@@ -1,7 +1,10 @@
package blockchain
import (
"math/big"
"github.com/holiman/uint256"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/config/params"
)
@@ -11,9 +14,16 @@ import (
// is_total_difficulty_reached = block.total_difficulty >= TERMINAL_TOTAL_DIFFICULTY
// is_parent_total_difficulty_valid = parent.total_difficulty < TERMINAL_TOTAL_DIFFICULTY
// return is_total_difficulty_reached and is_parent_total_difficulty_valid
func validTerminalPowBlock(currentDifficulty *uint256.Int, parentDifficulty *uint256.Int) bool {
ttd := uint256.NewInt(params.BeaconConfig().TerminalTotalDifficulty)
func validTerminalPowBlock(currentDifficulty *uint256.Int, parentDifficulty *uint256.Int) (bool, error) {
b, ok := new(big.Int).SetString(params.BeaconConfig().TerminalTotalDifficulty, 10)
if !ok {
return false, errors.New("failed to parse terminal total difficulty")
}
ttd, of := uint256.FromBig(b)
if of {
return false, errors.New("overflow terminal total difficulty")
}
totalDifficultyReached := currentDifficulty.Cmp(ttd) >= 0
parentTotalDifficultyValid := ttd.Cmp(parentDifficulty) > 0
return totalDifficultyReached && parentTotalDifficultyValid
return totalDifficultyReached && parentTotalDifficultyValid, nil
}

View File

@@ -1,10 +1,13 @@
package blockchain
import (
"fmt"
"math/big"
"testing"
"github.com/holiman/uint256"
"github.com/prysmaticlabs/prysm/config/params"
"github.com/prysmaticlabs/prysm/testing/require"
)
func Test_validTerminalPowBlock(t *testing.T) {
@@ -61,11 +64,30 @@ func Test_validTerminalPowBlock(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cfg := params.BeaconConfig()
cfg.TerminalTotalDifficulty = tt.ttd
cfg.TerminalTotalDifficulty = fmt.Sprint(tt.ttd)
params.OverrideBeaconConfig(cfg)
if got := validTerminalPowBlock(tt.currentDifficulty, tt.parentDifficulty); got != tt.want {
got, err := validTerminalPowBlock(tt.currentDifficulty, tt.parentDifficulty)
require.NoError(t, err)
if got != tt.want {
t.Errorf("validTerminalPowBlock() = %v, want %v", got, tt.want)
}
})
}
}
func Test_validTerminalPowBlockSpecConfig(t *testing.T) {
cfg := params.BeaconConfig()
cfg.TerminalTotalDifficulty = "115792089237316195423570985008687907853269984665640564039457584007913129638912"
params.OverrideBeaconConfig(cfg)
i, _ := new(big.Int).SetString("115792089237316195423570985008687907853269984665640564039457584007913129638912", 10)
current, of := uint256.FromBig(i)
require.Equal(t, of, false)
i, _ = new(big.Int).SetString("115792089237316195423570985008687907853269984665640564039457584007913129638911", 10)
parent, of := uint256.FromBig(i)
require.Equal(t, of, false)
got, err := validTerminalPowBlock(current, parent)
require.NoError(t, err)
require.Equal(t, true, got)
}

View File

@@ -1,11 +1,15 @@
package blockchain
import (
"bytes"
"context"
"fmt"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/holiman/uint256"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
@@ -17,11 +21,14 @@ import (
"github.com/prysmaticlabs/prysm/crypto/bls"
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/monitoring/tracing"
enginev1 "github.com/prysmaticlabs/prysm/proto/engine/v1"
ethpbv1 "github.com/prysmaticlabs/prysm/proto/eth/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/attestation"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
"github.com/prysmaticlabs/prysm/runtime/version"
"github.com/prysmaticlabs/prysm/time/slots"
"github.com/sirupsen/logrus"
"go.opencensus.io/trace"
)
@@ -97,12 +104,70 @@ func (s *Service) onBlock(ctx context.Context, signed block.SignedBeaconBlock, b
if err != nil {
return err
}
// TODO_MERGE: Optimize this copy.
copiedPreState := preState.Copy()
body := signed.Block().Body()
// TODO_MERGE: Break `ExecuteStateTransition` into per_slot and block processing so we can call `ExecutePayload` in the middle.
postState, err := transition.ExecuteStateTransition(ctx, preState, signed)
if err != nil {
// TODO_MERGE: Notify execution client in the event of invalid conensus block
return err
}
fullyValidated := false
if copiedPreState.Version() == version.Bellatrix || postState.Version() == version.Bellatrix {
executionEnabled, err := blocks.ExecutionEnabled(postState, body)
if err != nil {
return errors.Wrap(err, "could not check if execution is enabled")
}
if executionEnabled {
payload, err := body.ExecutionPayload()
if err != nil {
return errors.Wrap(err, "could not get body execution payload")
}
// This is not the earliest we can call `ExecutePayload`, see above to do as the soonest we can call is after per_slot processing.
status, err := s.cfg.ExecutionEngineCaller.NewPayload(ctx, payload)
if err != nil {
return err
}
switch status.Status {
case enginev1.PayloadStatus_INVALID, enginev1.PayloadStatus_INVALID_BLOCK_HASH, enginev1.PayloadStatus_INVALID_TERMINAL_BLOCK:
// TODO_MERGE walk up the parent chain removing
return fmt.Errorf("could not prcess execution payload with status : %v", status.Status)
case enginev1.PayloadStatus_SYNCING, enginev1.PayloadStatus_ACCEPTED:
candidate, err := s.optimisticCandidateBlock(ctx, b)
if err != nil {
return errors.Wrap(err, "could not check if block is optimistic candidate")
}
if !candidate {
return errors.New("could not optimistically sync block")
}
log.WithFields(logrus.Fields{
"slot": b.Slot(),
"root": fmt.Sprintf("%#x", bytesutil.Trunc(blockRoot[:])),
"payloadHash": fmt.Sprintf("%#x", bytesutil.Trunc(payload.BlockHash)),
}).Info("Block is optimistic candidate")
break
case enginev1.PayloadStatus_VALID:
fullyValidated = true
default:
return errors.New("unknown payload status")
}
if copiedPreState.Version() == version.Bellatrix && fullyValidated {
mergeBlock, err := blocks.MergeTransitionBlock(copiedPreState, body)
if err != nil {
return errors.Wrap(err, "could not check if merge block is terminal")
}
if mergeBlock {
if err := s.validateTerminalBlock(ctx, signed); err != nil {
return err
}
}
}
}
}
// We add a proposer score boost to fork choice for the block root if applicable, right after
// running a successful state transition for the block.
if err := s.cfg.ForkChoiceStore.BoostProposerRoot(
@@ -115,6 +180,20 @@ func (s *Service) onBlock(ctx context.Context, signed block.SignedBeaconBlock, b
return err
}
// update forkchoice synced tips if the block is not optimistic
if fullyValidated {
root, err := b.HashTreeRoot()
if err != nil {
return err
}
if err := s.cfg.ForkChoiceStore.UpdateSyncedTipsWithValidRoot(ctx, root); err != nil {
return err
}
if err := s.saveSyncedTipsDB(ctx); err != nil {
return err
}
}
// If slasher is configured, forward the attestations in the block via
// an event feed for processing.
if features.Get().EnableSlasher {
@@ -175,6 +254,59 @@ func (s *Service) onBlock(ctx context.Context, signed block.SignedBeaconBlock, b
log.WithError(err).Warn("Could not update head")
}
// Notify execution layer with fork choice head update if this is post merge block.
if postState.Version() == version.Bellatrix {
executionEnabled, err := blocks.ExecutionEnabled(postState, body)
if err != nil {
return errors.Wrap(err, "could not check if execution is enabled")
}
if executionEnabled {
headPayload, err := s.headBlock().Block().Body().ExecutionPayload()
if err != nil {
return err
}
// TODO_MERGE: Loading the finalized block from DB on per block is not ideal. Finalized block should be cached here
finalizedBlock, err := s.cfg.BeaconDB.Block(ctx, bytesutil.ToBytes32(finalized.Root))
if err != nil {
return err
}
finalizedBlockHash := params.BeaconConfig().ZeroHash[:]
if finalizedBlock != nil && finalizedBlock.Version() == version.Bellatrix {
finalizedPayload, err := finalizedBlock.Block().Body().ExecutionPayload()
if err != nil {
return err
}
finalizedBlockHash = finalizedPayload.BlockHash
}
fcs := &enginev1.ForkchoiceState{
HeadBlockHash: headPayload.BlockHash,
SafeBlockHash: headPayload.BlockHash,
FinalizedBlockHash: finalizedBlockHash,
}
resp, err := s.cfg.ExecutionEngineCaller.ForkchoiceUpdated(ctx, fcs, nil /* attribute */)
if err != nil {
return err
}
switch resp.Status.Status {
case enginev1.PayloadStatus_INVALID, enginev1.PayloadStatus_INVALID_BLOCK_HASH, enginev1.PayloadStatus_INVALID_TERMINAL_BLOCK:
return fmt.Errorf("could not prcess execution payload with status : %v", resp.Status.Status)
case enginev1.PayloadStatus_SYNCING, enginev1.PayloadStatus_ACCEPTED:
candidate, err := s.optimisticCandidateBlock(ctx, b)
if err != nil {
return errors.Wrap(err, "could not check if block is optimistic candidate")
}
if !candidate {
return errors.Wrap(err, "could not optimistically sync block")
}
break
case enginev1.PayloadStatus_VALID:
default:
return errors.Wrap(err, "could not execute payload")
}
}
}
if err := s.pruneCanonicalAttsFromPool(ctx, blockRoot, signed); err != nil {
return err
}
@@ -247,32 +379,33 @@ func (s *Service) onBlock(ctx context.Context, signed block.SignedBeaconBlock, b
}
func (s *Service) onBlockBatch(ctx context.Context, blks []block.SignedBeaconBlock,
blockRoots [][32]byte) ([]*ethpb.Checkpoint, []*ethpb.Checkpoint, error) {
blockRoots [][32]byte) ([]*ethpb.Checkpoint, []*ethpb.Checkpoint, []bool, error) {
ctx, span := trace.StartSpan(ctx, "blockChain.onBlockBatch")
defer span.End()
if len(blks) == 0 || len(blockRoots) == 0 {
return nil, nil, errors.New("no blocks provided")
return nil, nil, nil, errors.New("no blocks provided")
}
if err := helpers.BeaconBlockIsNil(blks[0]); err != nil {
return nil, nil, err
return nil, nil, nil, err
}
b := blks[0].Block()
// Retrieve incoming block's pre state.
if err := s.verifyBlkPreState(ctx, b); err != nil {
return nil, nil, err
return nil, nil, nil, err
}
preState, err := s.cfg.StateGen.StateByRootInitialSync(ctx, bytesutil.ToBytes32(b.ParentRoot()))
if err != nil {
return nil, nil, err
return nil, nil, nil, err
}
if preState == nil || preState.IsNil() {
return nil, nil, fmt.Errorf("nil pre state for slot %d", b.Slot())
return nil, nil, nil, fmt.Errorf("nil pre state for slot %d", b.Slot())
}
jCheckpoints := make([]*ethpb.Checkpoint, len(blks))
fCheckpoints := make([]*ethpb.Checkpoint, len(blks))
optimistic := make([]bool, len(blks))
sigSet := &bls.SignatureBatch{
Signatures: [][]byte{},
PublicKeys: []bls.PublicKey{},
@@ -281,43 +414,140 @@ func (s *Service) onBlockBatch(ctx context.Context, blks []block.SignedBeaconBlo
var set *bls.SignatureBatch
boundaries := make(map[[32]byte]state.BeaconState)
for i, b := range blks {
preStateCopied := preState.Copy() // TODO_MERGE: Optimize this copy.
set, preState, err = transition.ExecuteStateTransitionNoVerifyAnySig(ctx, preState, b)
if err != nil {
return nil, nil, err
return nil, nil, nil, err
}
// Non merge blocks are never optimistic
optimistic[i] = false
if preState.Version() == version.Bellatrix {
executionEnabled, err := blocks.ExecutionEnabled(preState, b.Block().Body())
if err != nil {
return nil, nil, nil, errors.Wrap(err, "could not check if execution is enabled")
}
if executionEnabled {
payload, err := b.Block().Body().ExecutionPayload()
if err != nil {
return nil, nil, nil, errors.Wrap(err, "could not get body execution payload")
}
status, err := s.cfg.ExecutionEngineCaller.NewPayload(ctx, payload)
if err != nil {
return nil, nil, nil, err
}
switch status.Status {
case enginev1.PayloadStatus_INVALID, enginev1.PayloadStatus_INVALID_BLOCK_HASH, enginev1.PayloadStatus_INVALID_TERMINAL_BLOCK:
// TODO_MERGE walk up the parent chain removing
return nil, nil, nil, fmt.Errorf("could not prcess execution payload with status : %v", status.Status)
case enginev1.PayloadStatus_SYNCING, enginev1.PayloadStatus_ACCEPTED:
candidate, err := s.optimisticCandidateBlock(ctx, b.Block())
if err != nil {
return nil, nil, nil, errors.Wrap(err, "could not check if block is optimistic candidate")
}
if !candidate {
return nil, nil, nil, errors.New("could not optimistically sync block")
}
log.WithFields(logrus.Fields{
"slot": b.Block().Slot(),
"root": fmt.Sprintf("%#x", bytesutil.Trunc(blockRoots[i][:])),
"payloadHash": fmt.Sprintf("%#x", bytesutil.Trunc(payload.BlockHash)),
}).Info("Block is optimistic candidate")
optimistic[i] = true
break
case enginev1.PayloadStatus_VALID:
default:
return nil, nil, nil, errors.New("unknown payload status")
}
if !optimistic[i] {
mergeBlock, err := blocks.MergeTransitionBlock(preStateCopied, b.Block().Body())
if err != nil {
return nil, nil, nil, errors.Wrap(err, "could not check if merge block is terminal")
}
if mergeBlock {
if err := s.validateTerminalBlock(ctx, b); err != nil {
return nil, nil, nil, err
}
}
}
headPayload, err := b.Block().Body().ExecutionPayload()
if err != nil {
return nil, nil, nil, err
}
// TODO_MERGE: Loading the finalized block from DB on per block is not ideal. Finalized block should be cached here
finalizedBlock, err := s.cfg.BeaconDB.Block(ctx, bytesutil.ToBytes32(preState.FinalizedCheckpoint().Root))
if err != nil {
return nil, nil, nil, err
}
finalizedBlockHash := params.BeaconConfig().ZeroHash[:]
if finalizedBlock != nil && finalizedBlock.Version() == version.Bellatrix {
finalizedPayload, err := finalizedBlock.Block().Body().ExecutionPayload()
if err != nil {
return nil, nil, nil, err
}
finalizedBlockHash = finalizedPayload.BlockHash
}
fcs := &enginev1.ForkchoiceState{
HeadBlockHash: headPayload.BlockHash,
SafeBlockHash: headPayload.BlockHash,
FinalizedBlockHash: finalizedBlockHash,
}
resp, err := s.cfg.ExecutionEngineCaller.ForkchoiceUpdated(ctx, fcs, nil /* attribute */)
if err != nil {
return nil, nil, nil, err
}
switch resp.Status.Status {
case enginev1.PayloadStatus_INVALID, enginev1.PayloadStatus_INVALID_BLOCK_HASH, enginev1.PayloadStatus_INVALID_TERMINAL_BLOCK:
return nil, nil, nil, fmt.Errorf("could not prcess execution payload with status : %v", resp.Status.Status)
case enginev1.PayloadStatus_SYNCING, enginev1.PayloadStatus_ACCEPTED:
break
case enginev1.PayloadStatus_VALID:
default:
return nil, nil, nil, errors.Wrap(err, "could not execute payload")
}
}
}
// Save potential boundary states.
if slots.IsEpochStart(preState.Slot()) {
boundaries[blockRoots[i]] = preState.Copy()
if err := s.handleEpochBoundary(ctx, preState); err != nil {
return nil, nil, errors.Wrap(err, "could not handle epoch boundary state")
return nil, nil, nil, errors.Wrap(err, "could not handle epoch boundary state")
}
}
jCheckpoints[i] = preState.CurrentJustifiedCheckpoint()
fCheckpoints[i] = preState.FinalizedCheckpoint()
sigSet.Join(set)
}
verify, err := sigSet.Verify()
if err != nil {
return nil, nil, err
return nil, nil, nil, err
}
if !verify {
return nil, nil, errors.New("batch block signature verification failed")
return nil, nil, nil, errors.New("batch block signature verification failed")
}
for r, st := range boundaries {
if err := s.cfg.StateGen.SaveState(ctx, r, st); err != nil {
return nil, nil, err
return nil, nil, nil, err
}
}
// Also saves the last post state which to be used as pre state for the next batch.
lastB := blks[len(blks)-1]
lastBR := blockRoots[len(blockRoots)-1]
if err := s.cfg.StateGen.SaveState(ctx, lastBR, preState); err != nil {
return nil, nil, err
return nil, nil, nil, err
}
if err := s.saveHeadNoDB(ctx, lastB, lastBR, preState); err != nil {
return nil, nil, err
return nil, nil, nil, err
}
return fCheckpoints, jCheckpoints, nil
return fCheckpoints, jCheckpoints, optimistic, nil
}
// handles a block after the block's batch has been verified, where we can save blocks
@@ -330,7 +560,6 @@ func (s *Service) handleBlockAfterBatchVerify(ctx context.Context, signed block.
if err := s.insertBlockToForkChoiceStore(ctx, b, blockRoot, fCheckpoint, jCheckpoint); err != nil {
return err
}
if err := s.cfg.BeaconDB.SaveStateSummary(ctx, &ethpb.StateSummary{
Slot: signed.Block().Slot(),
Root: blockRoot[:],
@@ -503,11 +732,83 @@ func (s *Service) pruneCanonicalAttsFromPool(ctx context.Context, r [32]byte, b
return nil
}
// validates terminal block hash in the event of manual overrides before checking for total difficulty.
//
// def validate_merge_block(block: BeaconBlock) -> None:
// """
// Check the parent PoW block of execution payload is a valid terminal PoW block.
//
// Note: Unavailable PoW block(s) may later become available,
// and a client software MAY delay a call to ``validate_merge_block``
// until the PoW block(s) become available.
// """
// if TERMINAL_BLOCK_HASH != Hash32():
// # If `TERMINAL_BLOCK_HASH` is used as an override, the activation epoch must be reached.
// assert compute_epoch_at_slot(block.slot) >= TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH
// return block.block_hash == TERMINAL_BLOCK_HASH
//
// pow_block = get_pow_block(block.body.execution_payload.parent_hash)
// # Check if `pow_block` is available
// assert pow_block is not None
// pow_parent = get_pow_block(pow_block.parent_hash)
// # Check if `pow_parent` is available
// assert pow_parent is not None
// # Check if `pow_block` is a valid terminal PoW block
// assert is_valid_terminal_pow_block(pow_block, pow_parent)
func (s *Service) validateTerminalBlock(ctx context.Context, b block.SignedBeaconBlock) error {
payload, err := b.Block().Body().ExecutionPayload()
if err != nil {
return err
}
if bytesutil.ToBytes32(params.BeaconConfig().TerminalBlockHash.Bytes()) != [32]byte{} {
// `TERMINAL_BLOCK_HASH` is used as an override, the activation epoch must be reached.
if params.BeaconConfig().TerminalBlockHashActivationEpoch > slots.ToEpoch(b.Block().Slot()) {
return errors.New("terminal block hash activation epoch not reached")
}
if !bytes.Equal(payload.ParentHash, params.BeaconConfig().TerminalBlockHash.Bytes()) {
return errors.New("parent hash does not match terminal block hash")
}
return nil
}
transitionBlk, err := s.cfg.ExecutionEngineCaller.ExecutionBlockByHash(ctx, common.BytesToHash(payload.ParentHash))
if err != nil {
return errors.Wrap(err, "could not get transition block")
}
parentTransitionBlk, err := s.cfg.ExecutionEngineCaller.ExecutionBlockByHash(ctx, common.BytesToHash(transitionBlk.ParentHash))
if err != nil {
return errors.Wrap(err, "could not get transition parent block")
}
transitionBlkTTD := new(uint256.Int)
transitionBlkTTD.SetBytes(bytesutil.ReverseByteOrder(transitionBlk.TotalDifficulty))
parentTransitionBlkTTD := new(uint256.Int)
parentTransitionBlkTTD.SetBytes(bytesutil.ReverseByteOrder(parentTransitionBlk.TotalDifficulty))
validated, err := validTerminalPowBlock(transitionBlkTTD, parentTransitionBlkTTD)
if err != nil {
return err
}
if !validated {
return errors.New("invalid difficulty for terminal block")
}
log.WithFields(logrus.Fields{
"slot": b.Block().Slot(),
"transitionBlockHash": common.BytesToHash(payload.ParentHash).String(),
"transitionBlockParentHash": common.BytesToHash(transitionBlk.ParentHash).String(),
"terminalTotalDifficulty": params.BeaconConfig().TerminalTotalDifficulty,
"transitionBlockTotalDifficulty": transitionBlkTTD,
"transitionBlockParentTotalDifficulty": parentTransitionBlkTTD,
}).Info("Verified terminal block")
return nil
}
// Saves synced and validated tips to DB.
func (s *Service) saveSyncedTipsDB(ctx context.Context) error {
tips := s.cfg.ForkChoiceStore.SyncedTips()
if len(tips) == 0 {
return errors.New("no tips to save")
return nil
}
return s.cfg.BeaconDB.UpdateValidatedTips(ctx, tips)
}

View File

@@ -113,7 +113,7 @@ func (s *Service) VerifyBlkDescendant(ctx context.Context, root [32]byte) error
}
if !bytes.Equal(bFinalizedRoot, fRoot[:]) {
err := fmt.Errorf("block %#x is not a descendent of the current finalized block slot %d, %#x != %#x",
err := fmt.Errorf("block %#x is not a descendant of the current finalized block slot %d, %#x != %#x",
bytesutil.Trunc(root[:]), finalizedBlk.Slot(), bytesutil.Trunc(bFinalizedRoot),
bytesutil.Trunc(fRoot[:]))
tracing.AnnotateError(span, err)

View File

@@ -100,7 +100,7 @@ func TestStore_OnBlock(t *testing.T) {
return b
}(),
s: st.Copy(),
wantErrString: "is not a descendent of the current finalized block",
wantErrString: "is not a descendant of the current finalized block",
},
{
name: "same slot as finalized block",
@@ -178,7 +178,7 @@ func TestStore_OnBlockBatch(t *testing.T) {
rBlock.Block.ParentRoot = gRoot[:]
require.NoError(t, beaconDB.SaveBlock(context.Background(), blks[0]))
require.NoError(t, service.cfg.StateGen.SaveState(ctx, blkRoots[0], firstState))
_, _, err = service.onBlockBatch(ctx, blks[1:], blkRoots[1:])
_, _, _, err = service.onBlockBatch(ctx, blks[1:], blkRoots[1:])
require.NoError(t, err)
}
@@ -789,7 +789,7 @@ func TestVerifyBlkDescendant(t *testing.T) {
finalizedRoot: r1,
parentRoot: r,
},
wantedErr: "is not a descendent of the current finalized block slot",
wantedErr: "is not a descendant of the current finalized block slot",
},
{
name: "is descendant",

View File

@@ -77,7 +77,7 @@ func (s *Service) ReceiveBlockBatch(ctx context.Context, blocks []block.SignedBe
defer span.End()
// Apply state transition on the incoming newly received blockCopy without verifying its BLS contents.
fCheckpoints, jCheckpoints, err := s.onBlockBatch(ctx, blocks, blkRoots)
fCheckpoints, jCheckpoints, optimistic, err := s.onBlockBatch(ctx, blocks, blkRoots)
if err != nil {
err := errors.Wrap(err, "could not process block in batch")
tracing.AnnotateError(span, err)
@@ -90,6 +90,19 @@ func (s *Service) ReceiveBlockBatch(ctx context.Context, blocks []block.SignedBe
tracing.AnnotateError(span, err)
return err
}
if !optimistic[i] {
root, err := b.Block().HashTreeRoot()
if err != nil {
return err
}
if err := s.cfg.ForkChoiceStore.UpdateSyncedTipsWithValidRoot(ctx, root); err != nil {
return err
}
if err := s.saveSyncedTipsDB(ctx); err != nil {
return errors.Wrap(err, "could not save synced tips")
}
}
// Send notification of the processed block to the state feed.
s.cfg.StateNotifier.StateFeed().Send(&feed.Event{
Type: statefeed.BlockProcessed,

View File

@@ -27,6 +27,7 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits"
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
v1 "github.com/prysmaticlabs/prysm/beacon-chain/powchain/engine-api-client/v1"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
"github.com/prysmaticlabs/prysm/cmd/beacon-chain/flags"
@@ -82,6 +83,8 @@ type config struct {
StateGen *stategen.State
SlasherAttestationsFeed *event.Feed
WeakSubjectivityCheckpt *ethpb.Checkpoint
BlockFetcher powchain.POWBlockFetcher
ExecutionEngineCaller v1.EngineCaller
FinalizedStateAtStartUp state.BeaconState
}
@@ -187,6 +190,10 @@ func (s *Service) startFromSavedState(saved state.BeaconState) error {
store := protoarray.New(justified.Epoch, finalized.Epoch, bytesutil.ToBytes32(finalized.Root))
s.cfg.ForkChoiceStore = store
if err := s.loadSyncedTips(originRoot, saved.Slot()); err != nil {
return err
}
ss, err := slots.EpochStart(finalized.Epoch)
if err != nil {
return errors.Wrap(err, "could not get start slot of finalized epoch")
@@ -213,7 +220,7 @@ func (s *Service) startFromSavedState(saved state.BeaconState) error {
Type: statefeed.Initialized,
Data: &statefeed.InitializedData{
StartTime: s.genesisTime,
GenesisValidatorsRoot: saved.GenesisValidatorRoot(),
GenesisValidatorsRoot: saved.GenesisValidatorsRoot(),
},
})
@@ -375,7 +382,7 @@ func (s *Service) onPowchainStart(ctx context.Context, genesisTime time.Time) {
Type: statefeed.Initialized,
Data: &statefeed.InitializedData{
StartTime: genesisTime,
GenesisValidatorsRoot: initializedState.GenesisValidatorRoot(),
GenesisValidatorsRoot: initializedState.GenesisValidatorsRoot(),
},
})
}

View File

@@ -8,6 +8,7 @@ import (
"time"
"github.com/ethereum/go-ethereum/common"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/async/event"
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain/store"
mock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
@@ -163,6 +164,74 @@ func TestChainStartStop_Initialized(t *testing.T) {
require.LogsContain(t, hook, "data already exists")
}
func TestChainStart_SyncedTipsInDB(t *testing.T) {
ctx := context.Background()
beaconDB := testDB.SetupDB(t)
chainService := setupBeaconChain(t, beaconDB)
genesisBlk := util.NewBeaconBlock()
blkRoot, err := genesisBlk.Block.HashTreeRoot()
require.NoError(t, err)
require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(genesisBlk)))
s, err := util.NewBeaconState()
require.NoError(t, err)
require.NoError(t, s.SetSlot(1))
require.NoError(t, beaconDB.SaveState(ctx, s, blkRoot))
require.NoError(t, beaconDB.SaveHeadBlockRoot(ctx, blkRoot))
require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, blkRoot))
require.NoError(t, beaconDB.SaveJustifiedCheckpoint(ctx, &ethpb.Checkpoint{Root: blkRoot[:]}))
require.NoError(t, beaconDB.SaveFinalizedCheckpoint(ctx, &ethpb.Checkpoint{Root: blkRoot[:]}))
chainService.cfg.FinalizedStateAtStartUp = s
tips := make(map[[32]byte]types.Slot)
tips[bytesutil.ToBytes32([]byte{'a'})] = 1
tips[bytesutil.ToBytes32([]byte{'b'})] = 2
require.NoError(t, beaconDB.UpdateValidatedTips(ctx, tips))
// Test the start function.
chainService.Start()
// Test synced Tips in DB
tips2 := chainService.cfg.ForkChoiceStore.SyncedTips()
require.Equal(t, len(tips2), len(tips))
for k, v := range tips {
v2, ok := tips2[k]
require.Equal(t, true, ok)
require.Equal(t, v, v2)
}
}
func TestChainStart_SyncedTipsNotInDB(t *testing.T) {
ctx := context.Background()
beaconDB := testDB.SetupDB(t)
chainService := setupBeaconChain(t, beaconDB)
genesisBlk := util.NewBeaconBlock()
blkRoot, err := genesisBlk.Block.HashTreeRoot()
require.NoError(t, err)
require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(genesisBlk)))
s, err := util.NewBeaconState()
require.NoError(t, err)
require.NoError(t, s.SetSlot(1))
require.NoError(t, beaconDB.SaveState(ctx, s, blkRoot))
require.NoError(t, beaconDB.SaveHeadBlockRoot(ctx, blkRoot))
require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, blkRoot))
require.NoError(t, beaconDB.SaveJustifiedCheckpoint(ctx, &ethpb.Checkpoint{Root: blkRoot[:]}))
require.NoError(t, beaconDB.SaveFinalizedCheckpoint(ctx, &ethpb.Checkpoint{Root: blkRoot[:]}))
chainService.cfg.FinalizedStateAtStartUp = s
// Test the start function.
chainService.Start()
// Test synced Tips in DB
tips := chainService.cfg.ForkChoiceStore.SyncedTips()
require.Equal(t, 1, len(tips))
slot, ok := tips[blkRoot]
require.Equal(t, true, ok)
require.Equal(t, types.Slot(1), slot)
}
func TestChainStartStop_GenesisZeroHashes(t *testing.T) {
hook := logTest.NewGlobal()
ctx := context.Background()
@@ -278,7 +347,7 @@ func TestChainService_InitializeChainInfo(t *testing.T) {
headState, err := util.NewBeaconState()
require.NoError(t, err)
require.NoError(t, headState.SetSlot(finalizedSlot))
require.NoError(t, headState.SetGenesisValidatorRoot(params.BeaconConfig().ZeroHash[:]))
require.NoError(t, headState.SetGenesisValidatorsRoot(params.BeaconConfig().ZeroHash[:]))
headRoot, err := headBlock.Block.HashTreeRoot()
require.NoError(t, err)
require.NoError(t, beaconDB.SaveState(ctx, headState, headRoot))
@@ -322,7 +391,7 @@ func TestChainService_InitializeChainInfo_SetHeadAtGenesis(t *testing.T) {
headState, err := util.NewBeaconState()
require.NoError(t, err)
require.NoError(t, headState.SetSlot(finalizedSlot))
require.NoError(t, headState.SetGenesisValidatorRoot(params.BeaconConfig().ZeroHash[:]))
require.NoError(t, headState.SetGenesisValidatorsRoot(params.BeaconConfig().ZeroHash[:]))
headRoot, err := headBlock.Block.HashTreeRoot()
require.NoError(t, err)
require.NoError(t, beaconDB.SaveState(ctx, headState, headRoot))
@@ -378,7 +447,7 @@ func TestChainService_InitializeChainInfo_HeadSync(t *testing.T) {
headState, err := util.NewBeaconState()
require.NoError(t, err)
require.NoError(t, headState.SetSlot(headBlock.Block.Slot))
require.NoError(t, headState.SetGenesisValidatorRoot(params.BeaconConfig().ZeroHash[:]))
require.NoError(t, headState.SetGenesisValidatorsRoot(params.BeaconConfig().ZeroHash[:]))
require.NoError(t, beaconDB.SaveState(ctx, headState, genesisRoot))
require.NoError(t, beaconDB.SaveState(ctx, headState, finalizedRoot))
require.NoError(t, beaconDB.SaveState(ctx, headState, headRoot))

View File

@@ -20,7 +20,6 @@ go_library(
"//beacon-chain/db:go_default_library",
"//beacon-chain/forkchoice/protoarray:go_default_library",
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/v1:go_default_library",
"//config/fieldparams:go_default_library",
"//config/params:go_default_library",
"//encoding/bytesutil:go_default_library",

View File

@@ -20,7 +20,6 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/db"
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
"github.com/prysmaticlabs/prysm/config/params"
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
@@ -29,6 +28,8 @@ import (
"github.com/sirupsen/logrus"
)
var ErrNilState = errors.New("nil state")
// ChainService defines the mock interface for testing
type ChainService struct {
State state.BeaconState
@@ -159,7 +160,7 @@ func (mon *MockOperationNotifier) OperationFeed() *event.Feed {
// ReceiveBlockInitialSync mocks ReceiveBlockInitialSync method in chain service.
func (s *ChainService) ReceiveBlockInitialSync(ctx context.Context, block block.SignedBeaconBlock, _ [32]byte) error {
if s.State == nil {
s.State = &v1.BeaconState{}
return ErrNilState
}
if !bytes.Equal(s.Root, block.Block().ParentRoot()) {
return errors.Errorf("wanted %#x but got %#x", s.Root, block.Block().ParentRoot())
@@ -186,7 +187,7 @@ func (s *ChainService) ReceiveBlockInitialSync(ctx context.Context, block block.
// ReceiveBlockBatch processes blocks in batches from initial-sync.
func (s *ChainService) ReceiveBlockBatch(ctx context.Context, blks []block.SignedBeaconBlock, _ [][32]byte) error {
if s.State == nil {
s.State = &v1.BeaconState{}
return ErrNilState
}
for _, block := range blks {
if !bytes.Equal(s.Root, block.Block().ParentRoot()) {
@@ -215,7 +216,7 @@ func (s *ChainService) ReceiveBlockBatch(ctx context.Context, blks []block.Signe
// ReceiveBlock mocks ReceiveBlock method in chain service.
func (s *ChainService) ReceiveBlock(ctx context.Context, block block.SignedBeaconBlock, _ [32]byte) error {
if s.State == nil {
s.State = &v1.BeaconState{}
return ErrNilState
}
if !bytes.Equal(s.Root, block.Block().ParentRoot()) {
return errors.Errorf("wanted %#x but got %#x", s.Root, block.Block().ParentRoot())
@@ -328,8 +329,8 @@ func (s *ChainService) GenesisTime() time.Time {
return s.Genesis
}
// GenesisValidatorRoot mocks the same method in the chain service.
func (s *ChainService) GenesisValidatorRoot() [32]byte {
// GenesisValidatorsRoot mocks the same method in the chain service.
func (s *ChainService) GenesisValidatorsRoot() [32]byte {
return s.ValidatorsRoot
}
@@ -369,8 +370,8 @@ func (s *ChainService) HasInitSyncBlock(rt [32]byte) bool {
return s.InitSyncBlockRoots[rt]
}
// HeadGenesisValidatorRoot mocks HeadGenesisValidatorRoot method in chain service.
func (_ *ChainService) HeadGenesisValidatorRoot() [32]byte {
// HeadGenesisValidatorsRoot mocks HeadGenesisValidatorsRoot method in chain service.
func (_ *ChainService) HeadGenesisValidatorsRoot() [32]byte {
return [32]byte{}
}
@@ -443,3 +444,8 @@ func (s *ChainService) HeadSyncContributionProofDomain(_ context.Context, _ type
func (s *ChainService) IsOptimistic(_ context.Context) (bool, error) {
return false, nil
}
// IsOptimisticForRoot mocks the same method in the chain service.
func (s *ChainService) IsOptimisticForRoot(_ context.Context, _ [32]byte, _ types.Slot) (bool, error) {
return false, nil
}

View File

@@ -30,7 +30,6 @@ go_library(
],
deps = [
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/v1:go_default_library",
"//cache/lru:go_default_library",
"//config/features:go_default_library",
"//config/params:go_default_library",

View File

@@ -6,7 +6,6 @@ import (
lru "github.com/hashicorp/golang-lru"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
lruwrpr "github.com/prysmaticlabs/prysm/cache/lru"
"github.com/prysmaticlabs/prysm/runtime/version"
)
@@ -33,8 +32,7 @@ func (c *SyncCommitteeHeadStateCache) Put(slot types.Slot, st state.BeaconState)
return ErrNilValueProvided
}
_, ok := st.(*v1.BeaconState)
if ok {
if st.Version() == version.Phase0 {
return ErrIncorrectType
}

View File

@@ -102,7 +102,7 @@ func FilterSyncCommitteeVotes(s state.BeaconStateAltair, sync *ethpb.SyncAggrega
// VerifySyncCommitteeSig verifies sync committee signature `syncSig` is valid with respect to public keys `syncKeys`.
func VerifySyncCommitteeSig(s state.BeaconStateAltair, syncKeys []bls.PublicKey, syncSig []byte) error {
ps := slots.PrevSlot(s.Slot())
d, err := signing.Domain(s.Fork(), slots.ToEpoch(ps), params.BeaconConfig().DomainSyncCommittee, s.GenesisValidatorRoot())
d, err := signing.Domain(s.Fork(), slots.ToEpoch(ps), params.BeaconConfig().DomainSyncCommittee, s.GenesisValidatorsRoot())
if err != nil {
return err
}

View File

@@ -8,7 +8,9 @@ import (
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core/altair"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state/v2"
v2 "github.com/prysmaticlabs/prysm/beacon-chain/state/v2"
"github.com/prysmaticlabs/prysm/config/params"
"github.com/prysmaticlabs/prysm/crypto/bls"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
@@ -18,7 +20,7 @@ import (
)
func TestSyncCommitteeIndices_CanGet(t *testing.T) {
getState := func(t *testing.T, count uint64) *stateAltair.BeaconState {
getState := func(t *testing.T, count uint64) state.BeaconStateAltair {
validators := make([]*ethpb.Validator, count)
for i := 0; i < len(validators); i++ {
validators[i] = &ethpb.Validator{
@@ -35,7 +37,7 @@ func TestSyncCommitteeIndices_CanGet(t *testing.T) {
}
type args struct {
state *stateAltair.BeaconState
state state.BeaconStateAltair
epoch types.Epoch
}
tests := []struct {
@@ -45,9 +47,9 @@ func TestSyncCommitteeIndices_CanGet(t *testing.T) {
errString string
}{
{
name: "nil state",
name: "nil inner state",
args: args{
state: nil,
state: &v2.BeaconState{},
},
wantErr: true,
errString: "nil inner state",
@@ -93,7 +95,7 @@ func TestSyncCommitteeIndices_CanGet(t *testing.T) {
func TestSyncCommitteeIndices_DifferentPeriods(t *testing.T) {
helpers.ClearCache()
getState := func(t *testing.T, count uint64) *stateAltair.BeaconState {
getState := func(t *testing.T, count uint64) state.BeaconStateAltair {
validators := make([]*ethpb.Validator, count)
for i := 0; i < len(validators); i++ {
validators[i] = &ethpb.Validator{
@@ -127,7 +129,7 @@ func TestSyncCommitteeIndices_DifferentPeriods(t *testing.T) {
}
func TestSyncCommittee_CanGet(t *testing.T) {
getState := func(t *testing.T, count uint64) *stateAltair.BeaconState {
getState := func(t *testing.T, count uint64) state.BeaconStateAltair {
validators := make([]*ethpb.Validator, count)
for i := 0; i < len(validators); i++ {
blsKey, err := bls.RandKey()
@@ -147,7 +149,7 @@ func TestSyncCommittee_CanGet(t *testing.T) {
}
type args struct {
state *stateAltair.BeaconState
state state.BeaconStateAltair
epoch types.Epoch
}
tests := []struct {
@@ -157,9 +159,9 @@ func TestSyncCommittee_CanGet(t *testing.T) {
errString string
}{
{
name: "nil state",
name: "nil inner state",
args: args{
state: nil,
state: &v2.BeaconState{},
},
wantErr: true,
errString: "nil inner state",
@@ -382,7 +384,7 @@ func Test_ValidateSyncMessageTime(t *testing.T) {
}
}
func getState(t *testing.T, count uint64) *stateAltair.BeaconState {
func getState(t *testing.T, count uint64) state.BeaconStateAltair {
validators := make([]*ethpb.Validator, count)
for i := 0; i < len(validators); i++ {
blsKey, err := bls.RandKey()

View File

@@ -68,7 +68,7 @@ func UpgradeToAltair(ctx context.Context, state state.BeaconState) (state.Beacon
numValidators := state.NumValidators()
s := &ethpb.BeaconStateAltair{
GenesisTime: state.GenesisTime(),
GenesisValidatorsRoot: state.GenesisValidatorRoot(),
GenesisValidatorsRoot: state.GenesisValidatorsRoot(),
Slot: state.Slot(),
Fork: &ethpb.Fork{
PreviousVersion: state.Fork().CurrentVersion,
@@ -137,7 +137,7 @@ func UpgradeToAltair(ctx context.Context, state state.BeaconState) (state.Beacon
// for index in get_attesting_indices(state, data, attestation.aggregation_bits):
// for flag_index in participation_flag_indices:
// epoch_participation[index] = add_flag(epoch_participation[index], flag_index)
func TranslateParticipation(ctx context.Context, state *statealtair.BeaconState, atts []*ethpb.PendingAttestation) (*statealtair.BeaconState, error) {
func TranslateParticipation(ctx context.Context, state state.BeaconStateAltair, atts []*ethpb.PendingAttestation) (state.BeaconStateAltair, error) {
epochParticipation, err := state.PreviousEpochParticipation()
if err != nil {
return nil, err

View File

@@ -9,7 +9,6 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/core/altair"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/core/time"
stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state/v2"
"github.com/prysmaticlabs/prysm/config/params"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/attestation"
@@ -20,12 +19,10 @@ import (
func TestTranslateParticipation(t *testing.T) {
ctx := context.Background()
s, _ := util.DeterministicGenesisStateAltair(t, 64)
st, ok := s.(*stateAltair.BeaconState)
require.Equal(t, true, ok)
require.NoError(t, st.SetSlot(st.Slot()+params.BeaconConfig().MinAttestationInclusionDelay))
require.NoError(t, s.SetSlot(s.Slot()+params.BeaconConfig().MinAttestationInclusionDelay))
var err error
newState, err := altair.TranslateParticipation(ctx, st, nil)
newState, err := altair.TranslateParticipation(ctx, s, nil)
require.NoError(t, err)
participation, err := newState.PreviousEpochParticipation()
require.NoError(t, err)
@@ -56,7 +53,7 @@ func TestTranslateParticipation(t *testing.T) {
require.NoError(t, err)
require.DeepNotSSZEqual(t, make([]byte, 64), participation)
committee, err := helpers.BeaconCommitteeFromState(ctx, st, pendingAtts[0].Data.Slot, pendingAtts[0].Data.CommitteeIndex)
committee, err := helpers.BeaconCommitteeFromState(ctx, s, pendingAtts[0].Data.Slot, pendingAtts[0].Data.CommitteeIndex)
require.NoError(t, err)
indices, err := attestation.AttestingIndices(pendingAtts[0].AggregationBits, committee)
require.NoError(t, err)
@@ -80,7 +77,7 @@ func TestUpgradeToAltair(t *testing.T) {
require.NoError(t, err)
require.Equal(t, preForkState.GenesisTime(), aState.GenesisTime())
require.DeepSSZEqual(t, preForkState.GenesisValidatorRoot(), aState.GenesisValidatorRoot())
require.DeepSSZEqual(t, preForkState.GenesisValidatorsRoot(), aState.GenesisValidatorsRoot())
require.Equal(t, preForkState.Slot(), aState.Slot())
require.DeepSSZEqual(t, preForkState.LatestBlockHeader(), aState.LatestBlockHeader())
require.DeepSSZEqual(t, preForkState.BlockRoots(), aState.BlockRoots())

View File

@@ -98,6 +98,7 @@ go_test(
"//proto/prysm/v1alpha1/attestation/aggregation:go_default_library",
"//proto/prysm/v1alpha1/attestation/aggregation/attestations:go_default_library",
"//proto/prysm/v1alpha1/wrapper:go_default_library",
"//runtime/version:go_default_library",
"//testing/assert:go_default_library",
"//testing/require:go_default_library",
"//testing/util:go_default_library",

View File

@@ -208,7 +208,7 @@ func VerifyIndexedAttestation(ctx context.Context, beaconState state.ReadOnlyBea
beaconState.Fork(),
indexedAtt.Data.Target.Epoch,
params.BeaconConfig().DomainBeaconAttester,
beaconState.GenesisValidatorRoot(),
beaconState.GenesisValidatorsRoot(),
)
if err != nil {
return err

View File

@@ -337,7 +337,9 @@ func TestValidateIndexedAttestation_AboveMaxLength(t *testing.T) {
}
want := "validator indices count exceeds MAX_VALIDATORS_PER_COMMITTEE"
err := blocks.VerifyIndexedAttestation(context.Background(), &v1.BeaconState{}, indexedAtt1)
st, err := v1.InitializeFromProtoUnsafe(&ethpb.BeaconState{})
require.NoError(t, err)
err = blocks.VerifyIndexedAttestation(context.Background(), st, indexedAtt1)
assert.ErrorContains(t, want, err)
}
@@ -415,7 +417,7 @@ func TestVerifyAttestations_HandlesPlannedFork(t *testing.T) {
Slot: 1,
},
})
prevDomain, err := signing.Domain(st.Fork(), st.Fork().Epoch-1, params.BeaconConfig().DomainBeaconAttester, st.GenesisValidatorRoot())
prevDomain, err := signing.Domain(st.Fork(), st.Fork().Epoch-1, params.BeaconConfig().DomainBeaconAttester, st.GenesisValidatorsRoot())
require.NoError(t, err)
root, err := signing.ComputeSigningRoot(att1.Data, prevDomain)
require.NoError(t, err)
@@ -435,7 +437,7 @@ func TestVerifyAttestations_HandlesPlannedFork(t *testing.T) {
CommitteeIndex: 1,
},
})
currDomain, err := signing.Domain(st.Fork(), st.Fork().Epoch, params.BeaconConfig().DomainBeaconAttester, st.GenesisValidatorRoot())
currDomain, err := signing.Domain(st.Fork(), st.Fork().Epoch, params.BeaconConfig().DomainBeaconAttester, st.GenesisValidatorsRoot())
require.NoError(t, err)
root, err = signing.ComputeSigningRoot(att2.Data, currDomain)
require.NoError(t, err)
@@ -474,7 +476,7 @@ func TestRetrieveAttestationSignatureSet_VerifiesMultipleAttestations(t *testing
Slot: 1,
},
})
domain, err := signing.Domain(st.Fork(), st.Fork().Epoch, params.BeaconConfig().DomainBeaconAttester, st.GenesisValidatorRoot())
domain, err := signing.Domain(st.Fork(), st.Fork().Epoch, params.BeaconConfig().DomainBeaconAttester, st.GenesisValidatorsRoot())
require.NoError(t, err)
root, err := signing.ComputeSigningRoot(att1.Data, domain)
require.NoError(t, err)
@@ -538,7 +540,7 @@ func TestRetrieveAttestationSignatureSet_AcrossFork(t *testing.T) {
Slot: 1,
},
})
domain, err := signing.Domain(st.Fork(), st.Fork().Epoch, params.BeaconConfig().DomainBeaconAttester, st.GenesisValidatorRoot())
domain, err := signing.Domain(st.Fork(), st.Fork().Epoch, params.BeaconConfig().DomainBeaconAttester, st.GenesisValidatorsRoot())
require.NoError(t, err)
root, err := signing.ComputeSigningRoot(att1.Data, domain)
require.NoError(t, err)

View File

@@ -108,7 +108,7 @@ func TestProcessAttesterSlashings_AppliesCorrectStatus(t *testing.T) {
},
AttestingIndices: []uint64{0, 1},
})
domain, err := signing.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorRoot())
domain, err := signing.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorsRoot())
require.NoError(t, err)
signingRoot, err := signing.ComputeSigningRoot(att1.Data, domain)
assert.NoError(t, err, "Could not get signing root of beacon block header")
@@ -177,7 +177,7 @@ func TestProcessAttesterSlashings_AppliesCorrectStatusAltair(t *testing.T) {
},
AttestingIndices: []uint64{0, 1},
})
domain, err := signing.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorRoot())
domain, err := signing.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorsRoot())
require.NoError(t, err)
signingRoot, err := signing.ComputeSigningRoot(att1.Data, domain)
assert.NoError(t, err, "Could not get signing root of beacon block header")
@@ -246,7 +246,7 @@ func TestProcessAttesterSlashings_AppliesCorrectStatusBellatrix(t *testing.T) {
},
AttestingIndices: []uint64{0, 1},
})
domain, err := signing.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorRoot())
domain, err := signing.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorsRoot())
require.NoError(t, err)
signingRoot, err := signing.ComputeSigningRoot(att1.Data, domain)
assert.NoError(t, err, "Could not get signing root of beacon block header")

View File

@@ -74,7 +74,8 @@ func TestFuzzverifyDepositDataSigningRoot_10000(_ *testing.T) {
func TestFuzzProcessEth1DataInBlock_10000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
e := &ethpb.Eth1Data{}
state := &v1.BeaconState{}
state, err := v1.InitializeFromProtoUnsafe(&ethpb.BeaconState{})
require.NoError(t, err)
for i := 0; i < 10000; i++ {
fuzzer.Fuzz(state)
fuzzer.Fuzz(e)

View File

@@ -44,7 +44,7 @@ func TestProcessAttesterSlashings_RegressionSlashableIndices(t *testing.T) {
AttestingIndices: setA,
Signature: make([]byte, 96),
}
domain, err := signing.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorRoot())
domain, err := signing.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorsRoot())
require.NoError(t, err)
signingRoot, err := signing.ComputeSigningRoot(att1.Data, domain)
require.NoError(t, err, "Could not get signing root of beacon block header")

View File

@@ -11,6 +11,7 @@ import (
"github.com/prysmaticlabs/prysm/config/params"
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/runtime/version"
"github.com/prysmaticlabs/prysm/testing/assert"
"github.com/prysmaticlabs/prysm/testing/require"
"github.com/prysmaticlabs/prysm/testing/util"
@@ -175,12 +176,10 @@ func TestProcessEth1Data_SetsCorrectly(t *testing.T) {
}
period := uint64(params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().EpochsPerEth1VotingPeriod)))
var ok bool
for i := uint64(0); i < period; i++ {
processedState, err := blocks.ProcessEth1DataInBlock(context.Background(), beaconState, b.Block.Body.Eth1Data)
require.NoError(t, err)
beaconState, ok = processedState.(*v1.BeaconState)
require.Equal(t, true, ok)
require.Equal(t, true, processedState.Version() == version.Phase0)
}
newETH1DataVotes := beaconState.Eth1DataVotes()

View File

@@ -57,7 +57,7 @@ func ProcessVoluntaryExits(
if err != nil {
return nil, err
}
if err := VerifyExitAndSignature(val, beaconState.Slot(), beaconState.Fork(), exit, beaconState.GenesisValidatorRoot()); err != nil {
if err := VerifyExitAndSignature(val, beaconState.Slot(), beaconState.Fork(), exit, beaconState.GenesisValidatorsRoot()); err != nil {
return nil, errors.Wrapf(err, "could not verify exit %d", idx)
}
beaconState, err = v.InitiateValidatorExit(ctx, beaconState, exit.Exit.ValidatorIndex)

View File

@@ -2,6 +2,7 @@ package blocks
import (
"bytes"
"strings"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
@@ -16,13 +17,13 @@ import (
"github.com/prysmaticlabs/prysm/time/slots"
)
// MergeComplete returns true if the transition to Bellatrix has completed.
// MergeTransitionComplete returns true if the transition to Bellatrix has completed.
// Meaning the payload header in beacon state is not `ExecutionPayloadHeader()` (i.e. not empty).
//
// Spec code:
// def is_merge_complete(state: BeaconState) -> bool:
// def is_merge_transition_complete(state: BeaconState) -> bool:
// return state.latest_execution_payload_header != ExecutionPayloadHeader()
func MergeComplete(st state.BeaconState) (bool, error) {
func MergeTransitionComplete(st state.BeaconState) (bool, error) {
h, err := st.LatestExecutionPayloadHeader()
if err != nil {
return false, err
@@ -31,15 +32,15 @@ func MergeComplete(st state.BeaconState) (bool, error) {
return !isEmptyHeader(h), nil
}
// IsMergeBlock returns true if the input block is the terminal merge block.
// MergeTransitionBlock returns true if the input block is the terminal merge block.
// Meaning the header in beacon state is `ExecutionPayloadHeader()` (i.e. empty).
// And the input block has a non-empty header.
//
// Spec code:
// def is_merge_block(state: BeaconState, body: BeaconBlockBody) -> bool:
// return not is_merge_complete(state) and body.execution_payload != ExecutionPayload()
func IsMergeBlock(st state.BeaconState, blk block.BeaconBlockBody) (bool, error) {
mergeComplete, err := MergeComplete(st)
// def is_merge_transition_block(state: BeaconState, body: BeaconBlockBody) -> bool:
// return not is_merge_transition_complete(state) and body.execution_payload != ExecutionPayload()
func MergeTransitionBlock(st state.BeaconState, body block.BeaconBlockBody) (bool, error) {
mergeComplete, err := MergeTransitionComplete(st)
if err != nil {
return false, err
}
@@ -47,8 +48,20 @@ func IsMergeBlock(st state.BeaconState, blk block.BeaconBlockBody) (bool, error)
return false, err
}
payload, err := blk.ExecutionPayload()
return ExecutionBlock(body)
}
// ExecutionBlock returns whether the block has a non-empty ExecutionPayload.
//
// Spec code:
// def is_execution_block(block: BeaconBlock) -> bool:
// return block.body.execution_payload != ExecutionPayload()
func ExecutionBlock(body block.BeaconBlockBody) (bool, error) {
payload, err := body.ExecutionPayload()
if err != nil {
if strings.HasPrefix(err.Error(), "ExecutionPayload is not supported in") {
return false, nil
}
return false, err
}
return !isEmptyPayload(payload), nil
@@ -60,15 +73,15 @@ func IsMergeBlock(st state.BeaconState, blk block.BeaconBlockBody) (bool, error)
// Spec code:
// def is_execution_enabled(state: BeaconState, body: BeaconBlockBody) -> bool:
// return is_merge_block(state, body) or is_merge_complete(state)
func ExecutionEnabled(st state.BeaconState, blk block.BeaconBlockBody) (bool, error) {
mergeBlock, err := IsMergeBlock(st, blk)
func ExecutionEnabled(st state.BeaconState, body block.BeaconBlockBody) (bool, error) {
mergeBlock, err := MergeTransitionBlock(st, body)
if err != nil {
return false, err
}
if mergeBlock {
return true, nil
}
return MergeComplete(st)
return MergeTransitionComplete(st)
}
// ValidatePayloadWhenMergeCompletes validates if payload is valid versus input beacon state.
@@ -79,7 +92,7 @@ func ExecutionEnabled(st state.BeaconState, blk block.BeaconBlockBody) (bool, er
// if is_merge_complete(state):
// assert payload.parent_hash == state.latest_execution_payload_header.block_hash
func ValidatePayloadWhenMergeCompletes(st state.BeaconState, payload *enginev1.ExecutionPayload) error {
complete, err := MergeComplete(st)
complete, err := MergeTransitionComplete(st)
if err != nil {
return err
}
@@ -291,3 +304,16 @@ func isEmptyHeader(h *ethpb.ExecutionPayloadHeader) bool {
}
return true
}
func EmptyPayload() *enginev1.ExecutionPayload {
return &enginev1.ExecutionPayload{
ParentHash: make([]byte, fieldparams.RootLength),
FeeRecipient: make([]byte, fieldparams.FeeRecipientLength),
StateRoot: make([]byte, fieldparams.RootLength),
ReceiptsRoot: make([]byte, fieldparams.RootLength),
LogsBloom: make([]byte, fieldparams.LogsBloomLength),
Random: make([]byte, fieldparams.RootLength),
BaseFeePerGas: make([]byte, fieldparams.RootLength),
BlockHash: make([]byte, fieldparams.RootLength),
}
}

View File

@@ -160,7 +160,7 @@ func Test_MergeComplete(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
st, _ := util.DeterministicGenesisStateBellatrix(t, 1)
require.NoError(t, st.SetLatestExecutionPayloadHeader(tt.payload))
got, err := blocks.MergeComplete(st)
got, err := blocks.MergeTransitionComplete(st)
require.NoError(t, err)
if got != tt.want {
t.Errorf("mergeComplete() got = %v, want %v", got, tt.want)
@@ -341,15 +341,49 @@ func Test_MergeBlock(t *testing.T) {
blk.Block.Body.ExecutionPayload = tt.payload
body, err := wrapper.WrappedBellatrixBeaconBlockBody(blk.Block.Body)
require.NoError(t, err)
got, err := blocks.IsMergeBlock(st, body)
got, err := blocks.MergeTransitionBlock(st, body)
require.NoError(t, err)
if got != tt.want {
t.Errorf("IsMergeBlock() got = %v, want %v", got, tt.want)
t.Errorf("MergeTransitionBlock() got = %v, want %v", got, tt.want)
}
})
}
}
func Test_IsExecutionBlock(t *testing.T) {
tests := []struct {
name string
payload *enginev1.ExecutionPayload
want bool
}{
{
name: "empty payload",
payload: emptyPayload(),
want: false,
},
{
name: "non-empty payload",
payload: func() *enginev1.ExecutionPayload {
p := emptyPayload()
p.ParentHash = bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength)
return p
}(),
want: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
blk := util.NewBeaconBlockBellatrix()
blk.Block.Body.ExecutionPayload = tt.payload
wrappedBlock, err := wrapper.WrappedBellatrixBeaconBlock(blk.Block)
require.NoError(t, err)
got, err := blocks.ExecutionBlock(wrappedBlock.Body())
require.NoError(t, err)
require.Equal(t, tt.want, got)
})
}
}
func Test_ExecutionEnabled(t *testing.T) {
tests := []struct {
name string
@@ -617,7 +651,7 @@ func BenchmarkBellatrixComplete(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := blocks.MergeComplete(st)
_, err := blocks.MergeTransitionComplete(st)
require.NoError(b, err)
}
}

View File

@@ -378,7 +378,7 @@ func TestVerifyProposerSlashing(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
sk := sks[tt.args.slashing.Header_1.Header.ProposerIndex]
d, err := signing.Domain(tt.args.beaconState.Fork(), slots.ToEpoch(tt.args.slashing.Header_1.Header.Slot), params.BeaconConfig().DomainBeaconProposer, tt.args.beaconState.GenesisValidatorRoot())
d, err := signing.Domain(tt.args.beaconState.Fork(), slots.ToEpoch(tt.args.slashing.Header_1.Header.Slot), params.BeaconConfig().DomainBeaconProposer, tt.args.beaconState.GenesisValidatorsRoot())
require.NoError(t, err)
if tt.args.slashing.Header_1.Signature == nil {
sr, err := signing.ComputeSigningRoot(tt.args.slashing.Header_1.Header, d)

View File

@@ -26,7 +26,7 @@ func TestProcessRandao_IncorrectProposerFailsVerification(t *testing.T) {
epoch := types.Epoch(0)
buf := make([]byte, 32)
binary.LittleEndian.PutUint64(buf, uint64(epoch))
domain, err := signing.Domain(beaconState.Fork(), epoch, params.BeaconConfig().DomainRandao, beaconState.GenesisValidatorRoot())
domain, err := signing.Domain(beaconState.Fork(), epoch, params.BeaconConfig().DomainRandao, beaconState.GenesisValidatorsRoot())
require.NoError(t, err)
root, err := (&ethpb.SigningData{ObjectRoot: buf, Domain: domain}).HashTreeRoot()
require.NoError(t, err)

View File

@@ -68,7 +68,7 @@ func VerifyBlockSignature(beaconState state.ReadOnlyBeaconState,
sig []byte,
rootFunc func() ([32]byte, error)) error {
currentEpoch := slots.ToEpoch(beaconState.Slot())
domain, err := signing.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainBeaconProposer, beaconState.GenesisValidatorRoot())
domain, err := signing.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainBeaconProposer, beaconState.GenesisValidatorsRoot())
if err != nil {
return err
}
@@ -83,7 +83,7 @@ func VerifyBlockSignature(beaconState state.ReadOnlyBeaconState,
// VerifyBlockHeaderSignature verifies the proposer signature of a beacon block header.
func VerifyBlockHeaderSignature(beaconState state.BeaconState, header *ethpb.SignedBeaconBlockHeader) error {
currentEpoch := slots.ToEpoch(beaconState.Slot())
domain, err := signing.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainBeaconProposer, beaconState.GenesisValidatorRoot())
domain, err := signing.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainBeaconProposer, beaconState.GenesisValidatorsRoot())
if err != nil {
return err
}
@@ -104,7 +104,7 @@ func VerifyBlockSignatureUsingCurrentFork(beaconState state.ReadOnlyBeaconState,
if err != nil {
return err
}
domain, err := signing.Domain(fork, currentEpoch, params.BeaconConfig().DomainBeaconProposer, beaconState.GenesisValidatorRoot())
domain, err := signing.Domain(fork, currentEpoch, params.BeaconConfig().DomainBeaconProposer, beaconState.GenesisValidatorsRoot())
if err != nil {
return err
}
@@ -122,7 +122,7 @@ func BlockSignatureBatch(beaconState state.ReadOnlyBeaconState,
sig []byte,
rootFunc func() ([32]byte, error)) (*bls.SignatureBatch, error) {
currentEpoch := slots.ToEpoch(beaconState.Slot())
domain, err := signing.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainBeaconProposer, beaconState.GenesisValidatorRoot())
domain, err := signing.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainBeaconProposer, beaconState.GenesisValidatorsRoot())
if err != nil {
return nil, err
}
@@ -164,7 +164,7 @@ func randaoSigningData(ctx context.Context, beaconState state.ReadOnlyBeaconStat
buf := make([]byte, 32)
binary.LittleEndian.PutUint64(buf, uint64(currentEpoch))
domain, err := signing.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainRandao, beaconState.GenesisValidatorRoot())
domain, err := signing.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainRandao, beaconState.GenesisValidatorsRoot())
if err != nil {
return nil, nil, nil, err
}
@@ -231,7 +231,7 @@ func AttestationSignatureBatch(ctx context.Context, beaconState state.ReadOnlyBe
}
fork := beaconState.Fork()
gvr := beaconState.GenesisValidatorRoot()
gvr := beaconState.GenesisValidatorsRoot()
dt := params.BeaconConfig().DomainBeaconAttester
// Split attestations by fork. Note: the signature domain will differ based on the fork.

View File

@@ -41,7 +41,7 @@ func TestVerifyBlockHeaderSignature(t *testing.T) {
beaconState.Fork(),
0,
params.BeaconConfig().DomainBeaconProposer,
beaconState.GenesisValidatorRoot(),
beaconState.GenesisValidatorsRoot(),
)
require.NoError(t, err)
htr, err := blockHeader.Header.HashTreeRoot()
@@ -77,7 +77,7 @@ func TestVerifyBlockSignatureUsingCurrentFork(t *testing.T) {
CurrentVersion: params.BeaconConfig().AltairForkVersion,
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
}
domain, err := signing.Domain(fData, 100, params.BeaconConfig().DomainBeaconProposer, bState.GenesisValidatorRoot())
domain, err := signing.Domain(fData, 100, params.BeaconConfig().DomainBeaconProposer, bState.GenesisValidatorsRoot())
assert.NoError(t, err)
rt, err := signing.ComputeSigningRoot(altairBlk.Block, domain)
assert.NoError(t, err)

View File

@@ -16,6 +16,7 @@ import (
"github.com/prysmaticlabs/prysm/config/params"
"github.com/prysmaticlabs/prysm/math"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/runtime/version"
"github.com/prysmaticlabs/prysm/testing/assert"
"github.com/prysmaticlabs/prysm/testing/require"
)
@@ -47,8 +48,7 @@ func TestProcessRewardsAndPenaltiesPrecompute(t *testing.T) {
processedState, err := ProcessRewardsAndPenaltiesPrecompute(beaconState, bp, vp, AttestationsDelta, ProposersDelta)
require.NoError(t, err)
beaconState, ok := processedState.(*v1.BeaconState)
require.Equal(t, true, ok)
require.Equal(t, true, processedState.Version() == version.Phase0)
// Indices that voted everything except for head, lost a bit money
wanted := uint64(31999810265)

View File

@@ -38,7 +38,7 @@ func UpgradeToBellatrix(ctx context.Context, state state.BeaconState) (state.Bea
s := &ethpb.BeaconStateBellatrix{
GenesisTime: state.GenesisTime(),
GenesisValidatorsRoot: state.GenesisValidatorRoot(),
GenesisValidatorsRoot: state.GenesisValidatorsRoot(),
Slot: state.Slot(),
Fork: &ethpb.Fork{
PreviousVersion: state.Fork().CurrentVersion,

View File

@@ -19,7 +19,7 @@ func TestUpgradeToBellatrix(t *testing.T) {
require.NoError(t, err)
require.Equal(t, preForkState.GenesisTime(), mSt.GenesisTime())
require.DeepSSZEqual(t, preForkState.GenesisValidatorRoot(), mSt.GenesisValidatorRoot())
require.DeepSSZEqual(t, preForkState.GenesisValidatorsRoot(), mSt.GenesisValidatorsRoot())
require.Equal(t, preForkState.Slot(), mSt.Slot())
require.DeepSSZEqual(t, preForkState.LatestBlockHeader(), mSt.LatestBlockHeader())
require.DeepSSZEqual(t, preForkState.BlockRoots(), mSt.BlockRoots())

View File

@@ -23,7 +23,7 @@ var ErrSigFailedToVerify = errors.New("signature did not verify")
// ComputeDomainAndSign computes the domain and signing root and sign it using the passed in private key.
func ComputeDomainAndSign(st state.ReadOnlyBeaconState, epoch types.Epoch, obj fssz.HashRoot, domain [4]byte, key bls.SecretKey) ([]byte, error) {
d, err := Domain(st.Fork(), epoch, domain, st.GenesisValidatorRoot())
d, err := Domain(st.Fork(), epoch, domain, st.GenesisValidatorsRoot())
if err != nil {
return nil, err
}
@@ -69,7 +69,7 @@ func ComputeDomainVerifySigningRoot(st state.ReadOnlyBeaconState, index types.Va
if err != nil {
return err
}
d, err := Domain(st.Fork(), epoch, domain, st.GenesisValidatorRoot())
d, err := Domain(st.Fork(), epoch, domain, st.GenesisValidatorsRoot())
if err != nil {
return err
}
@@ -219,7 +219,7 @@ func computeForkDataRoot(version, root []byte) ([32]byte, error) {
return r, nil
}
// ComputeForkDigest returns the fork for the current version and genesis validator root
// ComputeForkDigest returns the fork for the current version and genesis validators root
//
// Spec pseudocode definition:
// def compute_fork_digest(current_version: Version, genesis_validators_root: Root) -> ForkDigest:

View File

@@ -10,6 +10,7 @@ import (
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
"github.com/prysmaticlabs/prysm/config/params"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
"github.com/prysmaticlabs/prysm/runtime/version"
"github.com/prysmaticlabs/prysm/testing/assert"
"github.com/prysmaticlabs/prysm/testing/require"
"github.com/prysmaticlabs/prysm/testing/util"
@@ -33,8 +34,7 @@ func TestSkipSlotCache_OK(t *testing.T) {
require.NoError(t, err)
executedState, err := transition.ExecuteStateTransition(context.Background(), originalState, wrapper.WrappedPhase0SignedBeaconBlock(blk))
require.NoError(t, err, "Could not run state transition")
originalState, ok := executedState.(*v1.BeaconState)
require.Equal(t, true, ok)
require.Equal(t, true, executedState.Version() == version.Phase0)
bState, err = transition.ExecuteStateTransition(context.Background(), bState, wrapper.WrappedPhase0SignedBeaconBlock(blk))
require.NoError(t, err, "Could not process state transition")
@@ -59,8 +59,7 @@ func TestSkipSlotCache_ConcurrentMixup(t *testing.T) {
require.NoError(t, err)
executedState, err := transition.ExecuteStateTransition(context.Background(), originalState, wrapper.WrappedPhase0SignedBeaconBlock(blk))
require.NoError(t, err, "Could not run state transition")
originalState, ok := executedState.(*v1.BeaconState)
require.Equal(t, true, ok)
require.Equal(t, true, executedState.Version() == version.Phase0)
// Create two shallow but different forks
var s1, s0 state.BeaconState

View File

@@ -7,6 +7,7 @@ import (
fuzz "github.com/google/gofuzz"
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/testing/require"
)
func TestGenesisBeaconState_1000(t *testing.T) {
@@ -37,7 +38,8 @@ func TestOptimizedGenesisBeaconState_1000(t *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
fuzzer.NilChance(0.1)
var genesisTime uint64
preState := &v1.BeaconState{}
preState, err := v1.InitializeFromProtoUnsafe(&ethpb.BeaconState{})
require.NoError(t, err)
eth1Data := &ethpb.Eth1Data{}
for i := 0; i < 1000; i++ {
fuzzer.Fuzz(&genesisTime)

View File

@@ -10,13 +10,15 @@ import (
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
"github.com/prysmaticlabs/prysm/testing/require"
)
func TestFuzzExecuteStateTransition_1000(t *testing.T) {
SkipSlotCache.Disable()
defer SkipSlotCache.Enable()
ctx := context.Background()
state := &v1.BeaconState{}
state, err := v1.InitializeFromProtoUnsafe(&ethpb.BeaconState{})
require.NoError(t, err)
sb := &ethpb.SignedBeaconBlock{}
fuzzer := fuzz.NewWithSeed(0)
fuzzer.NilChance(0.1)
@@ -34,7 +36,8 @@ func TestFuzzCalculateStateRoot_1000(t *testing.T) {
SkipSlotCache.Disable()
defer SkipSlotCache.Enable()
ctx := context.Background()
state := &v1.BeaconState{}
state, err := v1.InitializeFromProtoUnsafe(&ethpb.BeaconState{})
require.NoError(t, err)
sb := &ethpb.SignedBeaconBlock{}
fuzzer := fuzz.NewWithSeed(0)
fuzzer.NilChance(0.1)
@@ -52,7 +55,8 @@ func TestFuzzProcessSlot_1000(t *testing.T) {
SkipSlotCache.Disable()
defer SkipSlotCache.Enable()
ctx := context.Background()
state := &v1.BeaconState{}
state, err := v1.InitializeFromProtoUnsafe(&ethpb.BeaconState{})
require.NoError(t, err)
fuzzer := fuzz.NewWithSeed(0)
fuzzer.NilChance(0.1)
for i := 0; i < 1000; i++ {
@@ -68,7 +72,8 @@ func TestFuzzProcessSlots_1000(t *testing.T) {
SkipSlotCache.Disable()
defer SkipSlotCache.Enable()
ctx := context.Background()
state := &v1.BeaconState{}
state, err := v1.InitializeFromProtoUnsafe(&ethpb.BeaconState{})
require.NoError(t, err)
slot := types.Slot(0)
fuzzer := fuzz.NewWithSeed(0)
fuzzer.NilChance(0.1)
@@ -86,7 +91,8 @@ func TestFuzzprocessOperationsNoVerify_1000(t *testing.T) {
SkipSlotCache.Disable()
defer SkipSlotCache.Enable()
ctx := context.Background()
state := &v1.BeaconState{}
state, err := v1.InitializeFromProtoUnsafe(&ethpb.BeaconState{})
require.NoError(t, err)
bb := &ethpb.SignedBeaconBlock{}
fuzzer := fuzz.NewWithSeed(0)
fuzzer.NilChance(0.1)
@@ -100,10 +106,11 @@ func TestFuzzprocessOperationsNoVerify_1000(t *testing.T) {
}
}
func TestFuzzverifyOperationLengths_10000(_ *testing.T) {
func TestFuzzverifyOperationLengths_10000(t *testing.T) {
SkipSlotCache.Disable()
defer SkipSlotCache.Enable()
state := &v1.BeaconState{}
state, err := v1.InitializeFromProtoUnsafe(&ethpb.BeaconState{})
require.NoError(t, err)
bb := &ethpb.SignedBeaconBlock{}
fuzzer := fuzz.NewWithSeed(0)
fuzzer.NilChance(0.1)
@@ -115,10 +122,11 @@ func TestFuzzverifyOperationLengths_10000(_ *testing.T) {
}
}
func TestFuzzCanProcessEpoch_10000(_ *testing.T) {
func TestFuzzCanProcessEpoch_10000(t *testing.T) {
SkipSlotCache.Disable()
defer SkipSlotCache.Enable()
state := &v1.BeaconState{}
state, err := v1.InitializeFromProtoUnsafe(&ethpb.BeaconState{})
require.NoError(t, err)
fuzzer := fuzz.NewWithSeed(0)
fuzzer.NilChance(0.1)
for i := 0; i < 10000; i++ {
@@ -131,7 +139,8 @@ func TestFuzzProcessEpochPrecompute_1000(t *testing.T) {
SkipSlotCache.Disable()
defer SkipSlotCache.Enable()
ctx := context.Background()
state := &v1.BeaconState{}
state, err := v1.InitializeFromProtoUnsafe(&ethpb.BeaconState{})
require.NoError(t, err)
fuzzer := fuzz.NewWithSeed(0)
fuzzer.NilChance(0.1)
for i := 0; i < 1000; i++ {
@@ -147,7 +156,8 @@ func TestFuzzProcessBlockForStateRoot_1000(t *testing.T) {
SkipSlotCache.Disable()
defer SkipSlotCache.Enable()
ctx := context.Background()
state := &v1.BeaconState{}
state, err := v1.InitializeFromProtoUnsafe(&ethpb.BeaconState{})
require.NoError(t, err)
sb := &ethpb.SignedBeaconBlock{}
fuzzer := fuzz.NewWithSeed(0)
fuzzer.NilChance(0.1)

View File

@@ -253,7 +253,7 @@ func createFullBlockWithOperations(t *testing.T) (state.BeaconState,
},
AttestingIndices: []uint64{0, 1},
})
domain, err := signing.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorRoot())
domain, err := signing.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorsRoot())
require.NoError(t, err)
hashTreeRoot, err := signing.ComputeSigningRoot(att1.Data, domain)
require.NoError(t, err)
@@ -394,7 +394,9 @@ func TestProcessBlock_OverMaxProposerSlashings(t *testing.T) {
}
want := fmt.Sprintf("number of proposer slashings (%d) in block body exceeds allowed threshold of %d",
len(b.Block.Body.ProposerSlashings), params.BeaconConfig().MaxProposerSlashings)
_, err := transition.VerifyOperationLengths(context.Background(), &v1.BeaconState{}, wrapper.WrappedPhase0SignedBeaconBlock(b))
s, err := v1.InitializeFromProtoUnsafe(&ethpb.BeaconState{})
require.NoError(t, err)
_, err = transition.VerifyOperationLengths(context.Background(), s, wrapper.WrappedPhase0SignedBeaconBlock(b))
assert.ErrorContains(t, want, err)
}
@@ -409,7 +411,9 @@ func TestProcessBlock_OverMaxAttesterSlashings(t *testing.T) {
}
want := fmt.Sprintf("number of attester slashings (%d) in block body exceeds allowed threshold of %d",
len(b.Block.Body.AttesterSlashings), params.BeaconConfig().MaxAttesterSlashings)
_, err := transition.VerifyOperationLengths(context.Background(), &v1.BeaconState{}, wrapper.WrappedPhase0SignedBeaconBlock(b))
s, err := v1.InitializeFromProtoUnsafe(&ethpb.BeaconState{})
require.NoError(t, err)
_, err = transition.VerifyOperationLengths(context.Background(), s, wrapper.WrappedPhase0SignedBeaconBlock(b))
assert.ErrorContains(t, want, err)
}
@@ -423,7 +427,9 @@ func TestProcessBlock_OverMaxAttestations(t *testing.T) {
}
want := fmt.Sprintf("number of attestations (%d) in block body exceeds allowed threshold of %d",
len(b.Block.Body.Attestations), params.BeaconConfig().MaxAttestations)
_, err := transition.VerifyOperationLengths(context.Background(), &v1.BeaconState{}, wrapper.WrappedPhase0SignedBeaconBlock(b))
s, err := v1.InitializeFromProtoUnsafe(&ethpb.BeaconState{})
require.NoError(t, err)
_, err = transition.VerifyOperationLengths(context.Background(), s, wrapper.WrappedPhase0SignedBeaconBlock(b))
assert.ErrorContains(t, want, err)
}
@@ -438,7 +444,9 @@ func TestProcessBlock_OverMaxVoluntaryExits(t *testing.T) {
}
want := fmt.Sprintf("number of voluntary exits (%d) in block body exceeds allowed threshold of %d",
len(b.Block.Body.VoluntaryExits), maxExits)
_, err := transition.VerifyOperationLengths(context.Background(), &v1.BeaconState{}, wrapper.WrappedPhase0SignedBeaconBlock(b))
s, err := v1.InitializeFromProtoUnsafe(&ethpb.BeaconState{})
require.NoError(t, err)
_, err = transition.VerifyOperationLengths(context.Background(), s, wrapper.WrappedPhase0SignedBeaconBlock(b))
assert.ErrorContains(t, want, err)
}

View File

@@ -31,6 +31,7 @@ go_test(
"//beacon-chain/state/v1:go_default_library",
"//config/params:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//runtime/version:go_default_library",
"//testing/assert:go_default_library",
"//testing/require:go_default_library",
"@com_github_prysmaticlabs_eth2_types//:go_default_library",

View File

@@ -10,6 +10,7 @@ import (
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
"github.com/prysmaticlabs/prysm/config/params"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/runtime/version"
"github.com/prysmaticlabs/prysm/testing/assert"
"github.com/prysmaticlabs/prysm/testing/require"
)
@@ -129,8 +130,7 @@ func TestSlashValidator_OK(t *testing.T) {
cfg := params.BeaconConfig()
slashedState, err := SlashValidator(context.Background(), state, slashedIdx, cfg.MinSlashingPenaltyQuotient, cfg.ProposerRewardQuotient)
require.NoError(t, err, "Could not slash validator")
state, ok := slashedState.(*v1.BeaconState)
require.Equal(t, true, ok)
require.Equal(t, true, slashedState.Version() == version.Phase0)
v, err := state.ValidatorAtIndex(slashedIdx)
require.NoError(t, err)

View File

@@ -59,6 +59,7 @@ type NoHeadAccessDatabase interface {
ReadOnlyDatabase
// Block related methods.
DeleteBlock(ctx context.Context, root [32]byte) error
SaveBlock(ctx context.Context, block block.SignedBeaconBlock) error
SaveBlocks(ctx context.Context, blocks []block.SignedBeaconBlock) error
SaveGenesisBlockRoot(ctx context.Context, blockRoot [32]byte) error

View File

@@ -204,6 +204,34 @@ func (s *Store) BlockRootsBySlot(ctx context.Context, slot types.Slot) (bool, []
return len(blockRoots) > 0, blockRoots, nil
}
// DeleteBlock from the db
// This deletes the root entry from all buckets in the blocks DB
// If the block is finalized this function returns an error
func (s *Store) DeleteBlock(ctx context.Context, root [32]byte) error {
ctx, span := trace.StartSpan(ctx, "BeaconDB.DeleteBlock")
defer span.End()
if err := s.DeleteState(ctx, root); err != nil {
return errDeleteFinalized
}
return s.db.Update(func(tx *bolt.Tx) error {
bkt := tx.Bucket(finalizedBlockRootsIndexBucket)
if b := bkt.Get(root[:]); b != nil {
return errDeleteFinalized
}
if err := tx.Bucket(blocksBucket).Delete(root[:]); err != nil {
return err
}
if err := tx.Bucket(blockParentRootIndicesBucket).Delete(root[:]); err != nil {
return err
}
s.blockCache.Del(string(root[:]))
return nil
})
}
// SaveBlock to the db.
func (s *Store) SaveBlock(ctx context.Context, signed block.SignedBeaconBlock) error {
ctx, span := trace.StartSpan(ctx, "BeaconDB.SaveBlock")

View File

@@ -8,6 +8,7 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/db/filters"
"github.com/prysmaticlabs/prysm/config/params"
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
"github.com/prysmaticlabs/prysm/testing/assert"
@@ -163,6 +164,44 @@ func TestStore_BlocksHandleInvalidEndSlot(t *testing.T) {
}
}
func TestStore_DeleteBlock(t *testing.T) {
slotsPerEpoch := uint64(params.BeaconConfig().SlotsPerEpoch)
db := setupDB(t)
ctx := context.Background()
require.NoError(t, db.SaveGenesisBlockRoot(ctx, genesisBlockRoot))
blks := makeBlocks(t, 0, slotsPerEpoch*4, genesisBlockRoot)
require.NoError(t, db.SaveBlocks(ctx, blks))
root, err := blks[slotsPerEpoch].Block().HashTreeRoot()
require.NoError(t, err)
cp := &ethpb.Checkpoint{
Epoch: 1,
Root: root[:],
}
st, err := util.NewBeaconState()
require.NoError(t, err)
require.NoError(t, db.SaveState(ctx, st, root))
require.NoError(t, db.SaveFinalizedCheckpoint(ctx, cp))
root2, err := blks[4*slotsPerEpoch-2].Block().HashTreeRoot()
require.NoError(t, err)
b, err := db.Block(ctx, root2)
require.NoError(t, err)
require.NotNil(t, b)
require.NoError(t, db.DeleteBlock(ctx, root2))
st, err = db.State(ctx, root2)
require.NoError(t, err)
require.Equal(t, st, nil)
b, err = db.Block(ctx, root2)
require.NoError(t, err)
require.Equal(t, b, nil)
require.ErrorIs(t, db.DeleteBlock(ctx, root), errDeleteFinalized)
}
func TestStore_GenesisBlock(t *testing.T) {
db := setupDB(t)
ctx := context.Background()

View File

@@ -2,6 +2,9 @@ package kv
import "errors"
// errDeleteFinalized is raised when we attempt to delete a finalized block/state
var errDeleteFinalized = errors.New("cannot delete finalized block or state")
// ErrNotFound can be used directly, or as a wrapped DBError, whenever a db method needs to
// indicate that a value couldn't be found.
var ErrNotFound = errors.New("not found in db")

View File

@@ -105,6 +105,8 @@ func NewKVStore(ctx context.Context, dirPath string, config *Config) (*Store, er
}
}
datafile := KVStoreDatafilePath(dirPath)
start := time.Now()
log.Infof("Opening Bolt DB at %s", datafile)
boltDB, err := bolt.Open(
datafile,
params.BeaconIoConfig().ReadWritePermissions,
@@ -114,29 +116,40 @@ func NewKVStore(ctx context.Context, dirPath string, config *Config) (*Store, er
},
)
if err != nil {
log.WithField("elapsed", time.Since(start)).Error("Failed to open Bolt DB")
if errors.Is(err, bolt.ErrTimeout) {
return nil, errors.New("cannot obtain database lock, database may be in use by another process")
}
return nil, err
}
log.WithField("elapsed", time.Since(start)).Info("Opened Bolt DB")
boltDB.AllocSize = boltAllocSize
start = time.Now()
log.Infof("Creating block cache...")
blockCache, err := ristretto.NewCache(&ristretto.Config{
NumCounters: 1000, // number of keys to track frequency of (1000).
MaxCost: BlockCacheSize, // maximum cost of cache (1000 Blocks).
BufferItems: 64, // number of keys per Get buffer.
})
if err != nil {
log.WithField("elapsed", time.Since(start)).Error("Failed to create block cache")
return nil, err
}
log.WithField("elapsed", time.Since(start)).Info("Created block cache")
start = time.Now()
log.Infof("Creating validator cache...")
validatorCache, err := ristretto.NewCache(&ristretto.Config{
NumCounters: NumOfValidatorEntries, // number of entries in cache (2 Million).
MaxCost: ValidatorEntryMaxCost, // maximum size of the cache (64Mb)
BufferItems: 64, // number of keys per Get buffer.
})
if err != nil {
log.WithField("elapsed", time.Since(start)).Error("Failed to to create validator cache")
return nil, err
}
log.WithField("elapsed", time.Since(start)).Info("Created validator cache")
kv := &Store{
db: boltDB,
@@ -146,7 +159,8 @@ func NewKVStore(ctx context.Context, dirPath string, config *Config) (*Store, er
stateSummaryCache: newStateSummaryCache(),
ctx: ctx,
}
start = time.Now()
log.Infof("Updating DB and creating buckets...")
if err := kv.db.Update(func(tx *bolt.Tx) error {
return createBuckets(
tx,
@@ -179,8 +193,10 @@ func NewKVStore(ctx context.Context, dirPath string, config *Config) (*Store, er
migrationsBucket,
)
}); err != nil {
log.WithField("elapsed", time.Since(start)).Error("Failed to update db and create buckets")
return nil, err
}
log.WithField("elapsed", time.Since(start)).Info("Updated db and created buckets")
err = prometheus.Register(createBoltCollector(kv.db))

View File

@@ -6,6 +6,7 @@ import (
"testing"
"github.com/golang/snappy"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
v2 "github.com/prysmaticlabs/prysm/beacon-chain/state/v2"
"github.com/prysmaticlabs/prysm/config/features"
@@ -19,12 +20,12 @@ import (
func Test_migrateStateValidators(t *testing.T) {
tests := []struct {
name string
setup func(t *testing.T, dbStore *Store, state *v1.BeaconState, vals []*v1alpha1.Validator)
eval func(t *testing.T, dbStore *Store, state *v1.BeaconState, vals []*v1alpha1.Validator)
setup func(t *testing.T, dbStore *Store, state state.BeaconState, vals []*v1alpha1.Validator)
eval func(t *testing.T, dbStore *Store, state state.BeaconState, vals []*v1alpha1.Validator)
}{
{
name: "only runs once",
setup: func(t *testing.T, dbStore *Store, state *v1.BeaconState, vals []*v1alpha1.Validator) {
setup: func(t *testing.T, dbStore *Store, state state.BeaconState, vals []*v1alpha1.Validator) {
// create some new buckets that should be present for this migration
err := dbStore.db.Update(func(tx *bbolt.Tx) error {
_, err := tx.CreateBucketIfNotExists(stateValidatorsBucket)
@@ -35,7 +36,7 @@ func Test_migrateStateValidators(t *testing.T) {
})
assert.NoError(t, err)
},
eval: func(t *testing.T, dbStore *Store, state *v1.BeaconState, vals []*v1alpha1.Validator) {
eval: func(t *testing.T, dbStore *Store, state state.BeaconState, vals []*v1alpha1.Validator) {
// check if the migration is completed, per migration table.
err := dbStore.db.View(func(tx *bbolt.Tx) error {
migrationCompleteOrNot := tx.Bucket(migrationsBucket).Get(migrationStateValidatorsKey)
@@ -47,7 +48,7 @@ func Test_migrateStateValidators(t *testing.T) {
},
{
name: "once migrated, always enable flag",
setup: func(t *testing.T, dbStore *Store, state *v1.BeaconState, vals []*v1alpha1.Validator) {
setup: func(t *testing.T, dbStore *Store, state state.BeaconState, vals []*v1alpha1.Validator) {
// create some new buckets that should be present for this migration
err := dbStore.db.Update(func(tx *bbolt.Tx) error {
_, err := tx.CreateBucketIfNotExists(stateValidatorsBucket)
@@ -58,7 +59,7 @@ func Test_migrateStateValidators(t *testing.T) {
})
assert.NoError(t, err)
},
eval: func(t *testing.T, dbStore *Store, state *v1.BeaconState, vals []*v1alpha1.Validator) {
eval: func(t *testing.T, dbStore *Store, state state.BeaconState, vals []*v1alpha1.Validator) {
// disable the flag and see if the code mandates that flag.
resetCfg := features.InitWithReset(&features.Flags{
EnableHistoricalSpaceRepresentation: false,
@@ -111,7 +112,7 @@ func Test_migrateStateValidators(t *testing.T) {
},
{
name: "migrates validators and adds them to new buckets",
setup: func(t *testing.T, dbStore *Store, state *v1.BeaconState, vals []*v1alpha1.Validator) {
setup: func(t *testing.T, dbStore *Store, state state.BeaconState, vals []*v1alpha1.Validator) {
// create some new buckets that should be present for this migration
err := dbStore.db.Update(func(tx *bbolt.Tx) error {
_, err := tx.CreateBucketIfNotExists(stateValidatorsBucket)
@@ -122,7 +123,7 @@ func Test_migrateStateValidators(t *testing.T) {
})
assert.NoError(t, err)
},
eval: func(t *testing.T, dbStore *Store, state *v1.BeaconState, vals []*v1alpha1.Validator) {
eval: func(t *testing.T, dbStore *Store, state state.BeaconState, vals []*v1alpha1.Validator) {
// check whether the new buckets are present
err := dbStore.db.View(func(tx *bbolt.Tx) error {
valBkt := tx.Bucket(stateValidatorsBucket)
@@ -209,12 +210,12 @@ func Test_migrateStateValidators(t *testing.T) {
func Test_migrateAltairStateValidators(t *testing.T) {
tests := []struct {
name string
setup func(t *testing.T, dbStore *Store, state *v2.BeaconState, vals []*v1alpha1.Validator)
eval func(t *testing.T, dbStore *Store, state *v2.BeaconState, vals []*v1alpha1.Validator)
setup func(t *testing.T, dbStore *Store, state state.BeaconStateAltair, vals []*v1alpha1.Validator)
eval func(t *testing.T, dbStore *Store, state state.BeaconStateAltair, vals []*v1alpha1.Validator)
}{
{
name: "migrates validators and adds them to new buckets",
setup: func(t *testing.T, dbStore *Store, state *v2.BeaconState, vals []*v1alpha1.Validator) {
setup: func(t *testing.T, dbStore *Store, state state.BeaconStateAltair, vals []*v1alpha1.Validator) {
// create some new buckets that should be present for this migration
err := dbStore.db.Update(func(tx *bbolt.Tx) error {
_, err := tx.CreateBucketIfNotExists(stateValidatorsBucket)
@@ -225,7 +226,7 @@ func Test_migrateAltairStateValidators(t *testing.T) {
})
assert.NoError(t, err)
},
eval: func(t *testing.T, dbStore *Store, state *v2.BeaconState, vals []*v1alpha1.Validator) {
eval: func(t *testing.T, dbStore *Store, state state.BeaconStateAltair, vals []*v1alpha1.Validator) {
// check whether the new buckets are present
err := dbStore.db.View(func(tx *bbolt.Tx) error {
valBkt := tx.Bucket(stateValidatorsBucket)
@@ -300,9 +301,9 @@ func Test_migrateAltairStateValidators(t *testing.T) {
})
defer resetCfg()
tt.setup(t, dbStore, st.(*v2.BeaconState), vals)
tt.setup(t, dbStore, st, vals)
assert.NoError(t, migrateStateValidators(context.Background(), dbStore.db), "migrateArchivedIndex(tx) error")
tt.eval(t, dbStore, st.(*v2.BeaconState), vals)
tt.eval(t, dbStore, st, vals)
})
}
}

View File

@@ -132,7 +132,11 @@ func (_ *Service) ChainStartEth1Data() *ethpb.Eth1Data {
// PreGenesisState returns an empty beacon state.
func (_ *Service) PreGenesisState() state.BeaconState {
return &v1.BeaconState{}
s, err := v1.InitializeFromProto(&ethpb.BeaconState{})
if err != nil {
panic("could not initialize state")
}
return s
}
// ClearPreGenesisData --

View File

@@ -8,7 +8,7 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
)
// ForkChoicer represents the full fork choice interface composed of all of the sub-interfaces.
// ForkChoicer represents the full fork choice interface composed of all the sub-interfaces.
type ForkChoicer interface {
HeadRetriever // to compute head.
BlockProcessor // to track new block for fork choice.
@@ -60,6 +60,7 @@ type Getter interface {
// SyncTipper returns sync tips related information.
type SyncTipper interface {
SyncedTips() map[[32]byte]types.Slot
SetSyncedTips(tips map[[32]byte]types.Slot) error
UpdateSyncedTipsWithValidRoot(ctx context.Context, root [32]byte) error
UpdateSyncedTipsWithInvalidRoot(ctx context.Context, root [32]byte) error
}

View File

@@ -1,7 +1,7 @@
/*
Package protoarray implements proto array fork choice as outlined:
https://github.com/protolambda/lmd-ghost#array-based-stateful-dag-proto_array
This was motivated by the the original implementation by Sigma Prime here:
This was motivated by the original implementation by Sigma Prime here:
https://github.com/sigp/lighthouse/pull/804
*/
package protoarray

View File

@@ -11,3 +11,4 @@ var errInvalidBestDescendantIndex = errors.New("best descendant index is invalid
var errInvalidParentDelta = errors.New("parent delta is invalid")
var errInvalidNodeDelta = errors.New("node delta is invalid")
var errInvalidDeltaLength = errors.New("delta length is invalid")
var errInvalidSyncedTips = errors.New("invalid synced tips")

View File

@@ -24,7 +24,7 @@ func computeDeltas(
oldBalance := uint64(0)
newBalance := uint64(0)
// Skip if validator has never voted for current root and next root (ie. if the
// Skip if validator has never voted for current root and next root (i.e. if the
// votes are zero hash aka genesis block), there's nothing to compute.
if vote.currentRoot == params.BeaconConfig().ZeroHash && vote.nextRoot == params.BeaconConfig().ZeroHash {
continue

View File

@@ -48,4 +48,16 @@ var (
Help: "The number of times pruning happened.",
},
)
lastSyncedTipSlot = promauto.NewGauge(
prometheus.GaugeOpts{
Name: "proto_array_last_synced_tip_slot",
Help: "The slot of the last fully validated block added to the proto array.",
},
)
syncedTipsCount = promauto.NewGauge(
prometheus.GaugeOpts{
Name: "proto_array_synced_tips_count",
Help: "The number of elements in the syncedTips structure.",
},
)
)

View File

@@ -107,7 +107,9 @@ func (s *Store) findSyncedTip(ctx context.Context, node *Node, syncedTips *optim
}
}
// UpdateSyncedTipsWithValidRoot updates the synced_tips map when the block with the given root becomes VALID
// UpdateSyncedTipsWithValidRoot is called with the root of a block that was returned as
// VALID by the EL. This routine recomputes and updates the synced_tips map to
// account for this new tip.
func (f *ForkChoice) UpdateSyncedTipsWithValidRoot(ctx context.Context, root [32]byte) error {
f.store.nodesLock.RLock()
defer f.store.nodesLock.RUnlock()
@@ -132,7 +134,9 @@ func (f *ForkChoice) UpdateSyncedTipsWithValidRoot(ctx context.Context, root [32
}
// Cache root and slot to validated tips
f.syncedTips.validatedTips[root] = node.slot
newTips := make(map[[32]byte]types.Slot)
newValidSlot := node.slot
newTips[root] = newValidSlot
// Compute the full valid path from the given node to its previous synced tip
// This path will now consist of fully validated blocks. Notice that
@@ -140,6 +144,7 @@ func (f *ForkChoice) UpdateSyncedTipsWithValidRoot(ctx context.Context, root [32
// In this case, only one block can be in syncedTips as the whole
// Fork Choice would be a descendant of this block.
validPath := make(map[uint64]bool)
validPath[index] = true
for {
if ctx.Err() != nil {
return ctx.Err()
@@ -168,7 +173,6 @@ func (f *ForkChoice) UpdateSyncedTipsWithValidRoot(ctx context.Context, root [32
}
// For each leaf, recompute the new tip.
newTips := make(map[[32]byte]types.Slot)
for _, i := range leaves {
node = f.store.nodes[i]
j := i
@@ -202,6 +206,8 @@ func (f *ForkChoice) UpdateSyncedTipsWithValidRoot(ctx context.Context, root [32
}
f.syncedTips.validatedTips = newTips
lastSyncedTipSlot.Set(float64(newValidSlot))
syncedTipsCount.Set(float64(len(newTips)))
return nil
}
@@ -311,5 +317,6 @@ func (f *ForkChoice) UpdateSyncedTipsWithInvalidRoot(ctx context.Context, root [
}
}
delete(f.syncedTips.validatedTips, parentRoot)
syncedTipsCount.Set(float64(len(f.syncedTips.validatedTips)))
return nil
}

View File

@@ -235,7 +235,7 @@ func TestUpdateSyncTipsWithValidRoots(t *testing.T) {
tests := []struct {
root [32]byte // the root of the new VALID block
tips map[[32]byte]types.Slot // the old synced tips
newtips map[[32]byte]types.Slot // the updated synced tips
newTips map[[32]byte]types.Slot // the updated synced tips
wantedErr error
}{
{
@@ -327,7 +327,7 @@ func TestUpdateSyncTipsWithValidRoots(t *testing.T) {
} else {
require.NoError(t, err)
f.syncedTips.RLock()
require.DeepEqual(t, f.syncedTips.validatedTips, tc.newtips)
require.DeepEqual(t, f.syncedTips.validatedTips, tc.newTips)
f.syncedTips.RUnlock()
}
}
@@ -345,7 +345,7 @@ func TestUpdateSyncTipsWithValidRoots(t *testing.T) {
// J(1) -- K(1) -- L(0)
//
// And every block in the Fork choice is optimistic. Synced_Tips contains a
// single block that is outside of Fork choice. The numbers in parenthesis are
// single block that is outside of Fork choice. The numbers in parentheses are
// the weights of the nodes before removal
//
func TestUpdateSyncTipsWithInvalidRoot(t *testing.T) {
@@ -535,15 +535,16 @@ func TestFindSyncedTip(t *testing.T) {
}
for _, tc := range tests {
f.store.nodesLock.RLock()
defer f.store.nodesLock.RUnlock()
node := f.store.nodes[f.store.nodesIndices[tc.root]]
syncedTips := &optimisticStore{
validatedTips: tc.tips,
}
syncedTips.RLock()
defer syncedTips.RUnlock()
idx, err := f.store.findSyncedTip(ctx, node, syncedTips)
require.NoError(t, err)
require.Equal(t, tc.wanted, f.store.nodes[idx].root)
f.store.nodesLock.RUnlock()
syncedTips.RUnlock()
}
}

View File

@@ -143,7 +143,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
// Ancestors have the added weights of their children. Genesis is a special exception at 0 weight,
require.Equal(t, f.store.nodes[0].weight, uint64(0))
// Otherwise assuming a block, A, that is not-genesis:
// Otherwise, assuming a block, A, that is not-genesis:
//
// A -> B -> C
//
@@ -160,7 +160,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
// (A: 54) -> (B: 44) -> (C: 24)
// \_->(D: 10)
//
// So B has its own weight, 10, and the sum of of both C and D thats why we see weight 54 in the
// So B has its own weight, 10, and the sum of both C and D. That's why we see weight 54 in the
// middle instead of the normal progression of (44 -> 34 -> 24).
require.Equal(t, f.store.nodes[1].weight, uint64(54))
require.Equal(t, f.store.nodes[2].weight, uint64(44))

View File

@@ -40,6 +40,21 @@ func New(justifiedEpoch, finalizedEpoch types.Epoch, finalizedRoot [32]byte) *Fo
return &ForkChoice{store: s, balances: b, votes: v, syncedTips: st}
}
// SetSyncedTips sets the synced and validated tips from the passed map
func (f *ForkChoice) SetSyncedTips(tips map[[32]byte]types.Slot) error {
if len(tips) == 0 {
return errInvalidSyncedTips
}
newTips := make(map[[32]byte]types.Slot, len(tips))
for k, v := range tips {
newTips[k] = v
}
f.syncedTips.Lock()
defer f.syncedTips.Unlock()
f.syncedTips.validatedTips = newTips
return nil
}
// SyncedTips returns the synced and validated tips from the fork choice store.
func (f *ForkChoice) SyncedTips() map[[32]byte]types.Slot {
f.syncedTips.RLock()
@@ -280,7 +295,7 @@ func (s *Store) head(ctx context.Context, justifiedRoot [32]byte) ([32]byte, err
justifiedNode := s.nodes[justifiedIndex]
bestDescendantIndex := justifiedNode.bestDescendant
// If the justified node doesn't have a best descendent,
// If the justified node doesn't have a best descendant,
// the best node is itself.
if bestDescendantIndex == NonExistentNode {
bestDescendantIndex = justifiedIndex
@@ -363,7 +378,7 @@ func (s *Store) insert(ctx context.Context,
index := uint64(len(s.nodes))
parentIndex, ok := s.nodesIndices[parent]
// Mark genesis block's parent as non existent.
// Mark genesis block's parent as non-existent.
if !ok {
parentIndex = NonExistentNode
}
@@ -383,7 +398,7 @@ func (s *Store) insert(ctx context.Context,
s.nodesIndices[root] = index
s.nodes = append(s.nodes, n)
// Update parent with the best child and descendent only if it's available.
// Update parent with the best child and descendant only if it's available.
if n.parent != NonExistentNode {
if err := s.updateBestChildAndDescendant(parentIndex, index); err != nil {
return err
@@ -399,8 +414,8 @@ func (s *Store) insert(ctx context.Context,
// applyWeightChanges iterates backwards through the nodes in store. It checks all nodes parent
// and its best child. For each node, it updates the weight with input delta and
// back propagate the nodes delta to its parents delta. After scoring changes,
// the best child is then updated along with best descendant.
// back propagate the nodes' delta to its parents' delta. After scoring changes,
// the best child is then updated along with the best descendant.
func (s *Store) applyWeightChanges(
ctx context.Context, justifiedEpoch, finalizedEpoch types.Epoch, newBalances []uint64, delta []int,
) error {
@@ -451,33 +466,25 @@ func (s *Store) applyWeightChanges(
}
s.proposerBoostLock.Unlock()
// A node's weight can not be negative but the delta can be negative.
if nodeDelta < 0 {
// A node's weight can not be negative but the delta can be negative.
if int(n.weight)+nodeDelta < 0 {
d := uint64(-nodeDelta)
if n.weight < d {
n.weight = 0
} else {
// Absolute value of node delta.
d := nodeDelta
if nodeDelta < 0 {
d *= -1
}
// Subtract node's weight.
n.weight -= uint64(d)
n.weight -= d
}
} else {
// Add node's weight.
n.weight += uint64(nodeDelta)
}
s.nodes[i] = n
// Update parent's best child and descendent if the node has a known parent.
// Update parent's best child and descendant if the node has a known parent.
if n.parent != NonExistentNode {
// Protection against node parent index out of bound. This should not happen.
if int(n.parent) >= len(delta) {
return errInvalidParentDelta
}
// Back propagate the nodes delta to its parent.
// Back propagate the nodes' delta to its parent.
delta[n.parent] += nodeDelta
}
}
@@ -503,14 +510,14 @@ func (s *Store) applyWeightChanges(
return nil
}
// updateBestChildAndDescendant updates parent node's best child and descendent.
// updateBestChildAndDescendant updates parent node's best child and descendant.
// It looks at input parent node and input child node and potentially modifies parent's best
// child and best descendent indices.
// child and best descendant indices.
// There are four outcomes:
// 1.) The child is already the best child but it's now invalid due to a FFG change and should be removed.
// 1.) The child is already the best child, but it's now invalid due to a FFG change and should be removed.
// 2.) The child is already the best child and the parent is updated with the new best descendant.
// 3.) The child is not the best child but becomes the best child.
// 4.) The child is not the best child and does not become best child.
// 4.) The child is not the best child and does not become the best child.
func (s *Store) updateBestChildAndDescendant(parentIndex, childIndex uint64) error {
// Protection against parent index out of bound, this should not happen.
@@ -545,12 +552,12 @@ func (s *Store) updateBestChildAndDescendant(parentIndex, childIndex uint64) err
if parent.bestChild != NonExistentNode {
if parent.bestChild == childIndex && !childLeadsToViableHead {
// If the child is already the best child of the parent but it's not viable for head,
// If the child is already the best child of the parent, but it's not viable for head,
// we should remove it. (Outcome 1)
newParentChild = changeToNone
} else if parent.bestChild == childIndex {
// If the child is already the best child of the parent, set it again to ensure best
// descendent of the parent is updated. (Outcome 2)
// If the child is already the best child of the parent, set it again to ensure the best
// descendant of the parent is updated. (Outcome 2)
newParentChild = changeToChild
} else {
// Protection against parent's best child going out of bound.
@@ -565,7 +572,7 @@ func (s *Store) updateBestChildAndDescendant(parentIndex, childIndex uint64) err
}
if childLeadsToViableHead && !bestChildLeadsToViableHead {
// The child leads to a viable head, but the current parent's best child doesnt.
// The child leads to a viable head, but the current parent's best child doesn't.
newParentChild = changeToChild
} else if !childLeadsToViableHead && bestChildLeadsToViableHead {
// The child doesn't lead to a viable head, the current parent's best child does.
@@ -663,7 +670,7 @@ func (s *Store) prune(ctx context.Context, finalizedRoot [32]byte, syncedTips *o
}
s.nodesIndices[finalizedRoot] = uint64(0)
// Recompute best child and descendant for each canonical nodes.
// Recompute the best child and descendant for each canonical nodes.
for _, node := range canonicalNodes {
if node.bestChild != NonExistentNode {
node.bestChild = canonicalNodesMap[node.bestChild]
@@ -675,31 +682,31 @@ func (s *Store) prune(ctx context.Context, finalizedRoot [32]byte, syncedTips *o
s.nodes = canonicalNodes
prunedCount.Inc()
syncedTipsCount.Set(float64(len(syncedTips.validatedTips)))
return nil
}
// leadsToViableHead returns true if the node or the best descendent of the node is viable for head.
// leadsToViableHead returns true if the node or the best descendant of the node is viable for head.
// Any node with diff finalized or justified epoch than the ones in fork choice store
// should not be viable to head.
func (s *Store) leadsToViableHead(node *Node) (bool, error) {
var bestDescendentViable bool
bestDescendentIndex := node.bestDescendant
var bestDescendantViable bool
bestDescendantIndex := node.bestDescendant
// If the best descendant is not part of the leaves.
if bestDescendentIndex != NonExistentNode {
// Protection against out of bound, best descendent index can not be
if bestDescendantIndex != NonExistentNode {
// Protection against out of bound, the best descendant index can not be
// exceeds length of nodes list.
if bestDescendentIndex >= uint64(len(s.nodes)) {
if bestDescendantIndex >= uint64(len(s.nodes)) {
return false, errInvalidBestDescendantIndex
}
bestDescendentNode := s.nodes[bestDescendentIndex]
bestDescendentViable = s.viableForHead(bestDescendentNode)
bestDescendantNode := s.nodes[bestDescendantIndex]
bestDescendantViable = s.viableForHead(bestDescendantNode)
}
// The node is viable as long as the best descendent is viable.
return bestDescendentViable || s.viableForHead(node), nil
// The node is viable as long as the best descendant is viable.
return bestDescendantViable || s.viableForHead(node), nil
}
// viableForHead returns true if the node is viable to head.

View File

@@ -134,7 +134,7 @@ func TestStore_Head_BestDescendant(t *testing.T) {
indices := make(map[[32]byte]uint64)
indices[r] = 0
// Since the justified node's best descendent is at index 1 and it's root is `best`,
// Since the justified node's best descendant is at index 1, and its root is `best`,
// the head should be `best`.
s := &Store{nodesIndices: indices, nodes: []*Node{{root: r, bestDescendant: 1}, {root: best}}, canonicalNodes: make(map[[32]byte]bool)}
h, err := s.head(context.Background(), r)
@@ -265,7 +265,7 @@ func TestStore_UpdateBestChildAndDescendant_UpdateDescendant(t *testing.T) {
func TestStore_UpdateBestChildAndDescendant_ChangeChildByViability(t *testing.T) {
// Make parent's best child not equal to child index, child leads to viable index and
// parents best child doesnt lead to viable index.
// parent's best child doesn't lead to viable index.
s := &Store{
justifiedEpoch: 1,
finalizedEpoch: 1,
@@ -600,6 +600,20 @@ func TestStore_LeadsToViableHead(t *testing.T) {
}
}
func TestStore_SetSyncedTips(t *testing.T) {
f := setup(1, 1)
tips := make(map[[32]byte]types.Slot)
require.ErrorIs(t, errInvalidSyncedTips, f.SetSyncedTips(tips))
tips[bytesutil.ToBytes32([]byte{'a'})] = 1
require.NoError(t, f.SetSyncedTips(tips))
f.syncedTips.RLock()
defer f.syncedTips.RUnlock()
require.Equal(t, 1, len(f.syncedTips.validatedTips))
slot, ok := f.syncedTips.validatedTips[bytesutil.ToBytes32([]byte{'a'})]
require.Equal(t, true, ok)
require.Equal(t, types.Slot(1), slot)
}
func TestStore_ViableForHead(t *testing.T) {
tests := []struct {
n *Node

View File

@@ -119,6 +119,7 @@ func New(cliCtx *cli.Context, opts ...Option) (*BeaconNode, error) {
configureEth1Config(cliCtx)
configureNetwork(cliCtx)
configureInteropConfig(cliCtx)
configureExecutionSetting(cliCtx)
// Initializes any forks here.
params.BeaconConfig().InitializeForkSchedule()
@@ -154,65 +155,80 @@ func New(cliCtx *cli.Context, opts ...Option) (*BeaconNode, error) {
if err != nil {
return nil, err
}
log.Debugln("Starting DB")
if err := beacon.startDB(cliCtx, depositAddress); err != nil {
return nil, err
}
log.Debugln("Starting Slashing DB")
if err := beacon.startSlasherDB(cliCtx); err != nil {
return nil, err
}
log.Debugln("Starting State Gen")
if err := beacon.startStateGen(); err != nil {
return nil, err
}
log.Debugln("Registering P2P Service")
if err := beacon.registerP2P(cliCtx); err != nil {
return nil, err
}
log.Debugln("Registering POW Chain Service")
if err := beacon.registerPOWChainService(); err != nil {
return nil, err
}
log.Debugln("Registering Attestation Pool Service")
if err := beacon.registerAttestationPool(); err != nil {
return nil, err
}
log.Debugln("Registering Determinstic Genesis Service")
if err := beacon.registerDeterminsticGenesisService(); err != nil {
return nil, err
}
log.Debugln("Starting Fork Choice")
beacon.startForkChoice()
log.Debugln("Registering Blockchain Service")
if err := beacon.registerBlockchainService(); err != nil {
return nil, err
}
log.Debugln("Registering Intial Sync Service")
if err := beacon.registerInitialSyncService(); err != nil {
return nil, err
}
log.Debugln("Registering Sync Service")
if err := beacon.registerSyncService(); err != nil {
return nil, err
}
log.Debugln("Registering Slasher Service")
if err := beacon.registerSlasherService(); err != nil {
return nil, err
}
log.Debugln("Registering RPC Service")
if err := beacon.registerRPCService(); err != nil {
return nil, err
}
log.Debugln("Registering GRPC Gateway Service")
if err := beacon.registerGRPCGateway(); err != nil {
return nil, err
}
log.Debugln("Registering Validator Monitoring Service")
if err := beacon.registerValidatorMonitorService(); err != nil {
return nil, err
}
if !cliCtx.Bool(cmd.DisableMonitoringFlag.Name) {
log.Debugln("Registering Prometheus Service")
if err := beacon.registerPrometheusService(cliCtx); err != nil {
return nil, err
}
@@ -539,6 +555,7 @@ func (b *BeaconNode) registerBlockchainService() error {
blockchain.WithDatabase(b.db),
blockchain.WithDepositCache(b.depositCache),
blockchain.WithChainStartFetcher(web3Service),
blockchain.WithExecutionEngineCaller(web3Service.EngineAPIClient()),
blockchain.WithAttestationPool(b.attestationPool),
blockchain.WithExitPool(b.exitPool),
blockchain.WithSlashingPool(b.slashingsPool),
@@ -765,6 +782,7 @@ func (b *BeaconNode) registerRPCService() error {
StateGen: b.stateGen,
EnableDebugRPCEndpoints: enableDebugRPCEndpoints,
MaxMsgSize: maxMsgSize,
ExecutionEngineCaller: web3Service.EngineAPIClient(),
})
return b.services.RegisterService(rpcService)

View File

@@ -98,7 +98,7 @@ func (s *Service) PublishToTopic(ctx context.Context, topic string, data []byte,
// SubscribeToTopic joins (if necessary) and subscribes to PubSub topic.
func (s *Service) SubscribeToTopic(topic string, opts ...pubsub.SubOpt) (*pubsub.Subscription, error) {
s.awaitStateInitialized() // Genesis time and genesis validator root are required to subscribe.
s.awaitStateInitialized() // Genesis time and genesis validators root are required to subscribe.
topicHandle, err := s.JoinTopic(topic)
if err != nil {

View File

@@ -490,7 +490,7 @@ func (s *Service) connectToBootnodes() error {
return nil
}
// Returns true if the service is aware of the genesis time and genesis validator root. This is
// Returns true if the service is aware of the genesis time and genesis validators root. This is
// required for discovery and pubsub validation.
func (s *Service) isInitialized() bool {
return !s.genesisTime.IsZero() && len(s.genesisValidatorsRoot) == 32

View File

@@ -306,7 +306,7 @@ func TestService_JoinLeaveTopic(t *testing.T) {
// digest associated with that genesis event.
func initializeStateWithForkDigest(ctx context.Context, t *testing.T, ef *event.Feed) [4]byte {
gt := prysmTime.Now()
gvr := bytesutil.PadTo([]byte("genesis validator root"), 32)
gvr := bytesutil.PadTo([]byte("genesis validators root"), 32)
for n := 0; n == 0; {
if ctx.Err() != nil {
t.Fatal(ctx.Err())

View File

@@ -27,10 +27,13 @@ go_library(
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/core/transition:go_default_library",
"//beacon-chain/db:go_default_library",
"//beacon-chain/powchain/engine-api-client/v1:go_default_library",
"//beacon-chain/powchain/types:go_default_library",
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/state-native/v1:go_default_library",
"//beacon-chain/state/stategen:go_default_library",
"//beacon-chain/state/v1:go_default_library",
"//config/features:go_default_library",
"//config/params:go_default_library",
"//container/trie:go_default_library",
"//contracts/deposit:go_default_library",

View File

@@ -1,4 +1,4 @@
load("@prysm//tools/go:def.bzl", "go_library")
load("@prysm//tools/go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
@@ -11,6 +11,22 @@ go_library(
visibility = ["//beacon-chain:__subpackages__"],
deps = [
"//proto/engine/v1:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_ethereum_go_ethereum//rpc:go_default_library",
"@com_github_pkg_errors//:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = ["client_test.go"],
embed = [":go_default_library"],
deps = [
"//config/fieldparams:go_default_library",
"//encoding/bytesutil:go_default_library",
"//proto/engine/v1:go_default_library",
"//testing/require:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_ethereum_go_ethereum//rpc:go_default_library",
"@com_github_pkg_errors//:go_default_library",
],

View File

@@ -8,6 +8,7 @@ import (
"net/url"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rpc"
"github.com/pkg/errors"
pb "github.com/prysmaticlabs/prysm/proto/engine/v1"
@@ -20,6 +21,10 @@ const (
ForkchoiceUpdatedMethod = "engine_forkchoiceUpdatedV1"
// GetPayloadMethod v1 request string for JSON-RPC.
GetPayloadMethod = "engine_getPayloadV1"
// ExecutionBlockByHashMethod request string for JSON-RPC.
ExecutionBlockByHashMethod = "eth_getBlockByHash"
// ExecutionBlockByNumberMethod request string for JSON-RPC.
ExecutionBlockByNumberMethod = "eth_getBlockByNumber"
// DefaultTimeout for HTTP.
DefaultTimeout = time.Second * 5
)
@@ -27,8 +32,20 @@ const (
// ForkchoiceUpdatedResponse is the response kind received by the
// engine_forkchoiceUpdatedV1 endpoint.
type ForkchoiceUpdatedResponse struct {
Status *pb.PayloadStatus `json:"status"`
PayloadId [8]byte `json:"payloadId"`
Status *pb.PayloadStatus `json:"payloadStatus"`
PayloadId *pb.PayloadIDBytes `json:"payloadId"`
}
// EngineCaller defines a client that can interact with an Ethereum
// execution node's engine service via JSON-RPC.
type EngineCaller interface {
NewPayload(ctx context.Context, payload *pb.ExecutionPayload) (*pb.PayloadStatus, error)
ForkchoiceUpdated(
ctx context.Context, state *pb.ForkchoiceState, attrs *pb.PayloadAttributes,
) (*ForkchoiceUpdatedResponse, error)
GetPayload(ctx context.Context, payloadId [8]byte) (*pb.ExecutionPayload, error)
LatestExecutionBlock(ctx context.Context) (*pb.ExecutionBlock, error)
ExecutionBlockByHash(ctx context.Context, hash common.Hash) (*pb.ExecutionBlock, error)
}
// Client defines a new engine API client for the Prysm consensus node
@@ -67,19 +84,81 @@ func New(ctx context.Context, endpoint string, opts ...Option) (*Client, error)
return c, nil
}
// NewPayload --
func (*Client) NewPayload(_ context.Context, _ *pb.ExecutionPayload) (*pb.PayloadStatus, error) {
return nil, errors.New("unimplemented")
// NewPayload calls the engine_newPayloadV1 method via JSON-RPC.
func (c *Client) NewPayload(ctx context.Context, payload *pb.ExecutionPayload) (*pb.PayloadStatus, error) {
result := &pb.PayloadStatus{}
err := c.rpc.CallContext(ctx, result, NewPayloadMethod, payload)
return result, handleRPCError(err)
}
// ForkchoiceUpdated --
func (*Client) ForkchoiceUpdated(
_ context.Context, _ *pb.ForkchoiceState, _ *pb.PayloadAttributes,
// ForkchoiceUpdated calls the engine_forkchoiceUpdatedV1 method via JSON-RPC.
func (c *Client) ForkchoiceUpdated(
ctx context.Context, state *pb.ForkchoiceState, attrs *pb.PayloadAttributes,
) (*ForkchoiceUpdatedResponse, error) {
return nil, errors.New("unimplemented")
result := &ForkchoiceUpdatedResponse{}
err := c.rpc.CallContext(ctx, result, ForkchoiceUpdatedMethod, state, attrs)
return result, handleRPCError(err)
}
// GetPayload --
func (*Client) GetPayload(_ context.Context, _ [8]byte) (*pb.ExecutionPayload, error) {
return nil, errors.New("unimplemented")
// GetPayload calls the engine_getPayloadV1 method via JSON-RPC.
func (c *Client) GetPayload(ctx context.Context, payloadId [8]byte) (*pb.ExecutionPayload, error) {
result := &pb.ExecutionPayload{}
err := c.rpc.CallContext(ctx, result, GetPayloadMethod, pb.PayloadIDBytes(payloadId))
return result, handleRPCError(err)
}
// LatestExecutionBlock fetches the latest execution engine block by calling
// eth_blockByNumber via JSON-RPC.
func (c *Client) LatestExecutionBlock(ctx context.Context) (*pb.ExecutionBlock, error) {
result := &pb.ExecutionBlock{}
err := c.rpc.CallContext(
ctx,
result,
ExecutionBlockByNumberMethod,
"latest",
false, /* no full transaction objects */
)
return result, handleRPCError(err)
}
// ExecutionBlockByHash fetches an execution engine block by hash by calling
// eth_blockByHash via JSON-RPC.
func (c *Client) ExecutionBlockByHash(ctx context.Context, hash common.Hash) (*pb.ExecutionBlock, error) {
result := &pb.ExecutionBlock{}
err := c.rpc.CallContext(ctx, result, ExecutionBlockByHashMethod, hash, false /* no full transaction objects */)
return result, handleRPCError(err)
}
// Handles errors received from the RPC server according to the specification.
func handleRPCError(err error) error {
if err == nil {
return nil
}
e, ok := err.(rpc.Error)
if !ok {
return errors.Wrap(err, "got an unexpected error")
}
switch e.ErrorCode() {
case -32700:
return ErrParse
case -32600:
return ErrInvalidRequest
case -32601:
return ErrMethodNotFound
case -32602:
return ErrInvalidParams
case -32603:
return ErrInternal
case -32001:
return ErrUnknownPayload
case -32000:
// Only -32000 status codes are data errors in the RPC specification.
errWithData, ok := err.(rpc.DataError)
if !ok {
return errors.Wrap(err, "got an unexpected error")
}
return errors.Wrapf(ErrServer, "%v", errWithData.ErrorData())
default:
return err
}
}

View File

@@ -0,0 +1,522 @@
package v1
import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"math/big"
"net/http"
"net/http/httptest"
"strings"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rpc"
"github.com/pkg/errors"
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
pb "github.com/prysmaticlabs/prysm/proto/engine/v1"
"github.com/prysmaticlabs/prysm/testing/require"
)
var _ = EngineCaller(&Client{})
func TestClient_IPC(t *testing.T) {
server := newTestIPCServer(t)
defer server.Stop()
rpcClient := rpc.DialInProc(server)
defer rpcClient.Close()
client := &Client{}
client.rpc = rpcClient
ctx := context.Background()
fix := fixtures()
t.Run(GetPayloadMethod, func(t *testing.T) {
want, ok := fix["ExecutionPayload"].(*pb.ExecutionPayload)
require.Equal(t, true, ok)
payloadId := [8]byte{1}
resp, err := client.GetPayload(ctx, payloadId)
require.NoError(t, err)
require.DeepEqual(t, want, resp)
})
t.Run(ForkchoiceUpdatedMethod, func(t *testing.T) {
want, ok := fix["ForkchoiceUpdatedResponse"].(*ForkchoiceUpdatedResponse)
require.Equal(t, true, ok)
resp, err := client.ForkchoiceUpdated(ctx, &pb.ForkchoiceState{}, &pb.PayloadAttributes{})
require.NoError(t, err)
require.DeepEqual(t, want.Status, resp.Status)
require.DeepEqual(t, want.PayloadId, resp.PayloadId)
})
t.Run(NewPayloadMethod, func(t *testing.T) {
want, ok := fix["PayloadStatus"].(*pb.PayloadStatus)
require.Equal(t, true, ok)
req, ok := fix["ExecutionPayload"].(*pb.ExecutionPayload)
require.Equal(t, true, ok)
resp, err := client.NewPayload(ctx, req)
require.NoError(t, err)
require.DeepEqual(t, want, resp)
})
t.Run(ExecutionBlockByNumberMethod, func(t *testing.T) {
want, ok := fix["ExecutionBlock"].(*pb.ExecutionBlock)
require.Equal(t, true, ok)
resp, err := client.LatestExecutionBlock(ctx)
require.NoError(t, err)
require.DeepEqual(t, want, resp)
})
t.Run(ExecutionBlockByHashMethod, func(t *testing.T) {
want, ok := fix["ExecutionBlock"].(*pb.ExecutionBlock)
require.Equal(t, true, ok)
arg := common.BytesToHash([]byte("foo"))
resp, err := client.ExecutionBlockByHash(ctx, arg)
require.NoError(t, err)
require.DeepEqual(t, want, resp)
})
}
func TestClient_HTTP(t *testing.T) {
ctx := context.Background()
fix := fixtures()
t.Run(GetPayloadMethod, func(t *testing.T) {
payloadId := [8]byte{1}
want, ok := fix["ExecutionPayload"].(*pb.ExecutionPayload)
require.Equal(t, true, ok)
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
defer func() {
require.NoError(t, r.Body.Close())
}()
enc, err := ioutil.ReadAll(r.Body)
require.NoError(t, err)
jsonRequestString := string(enc)
reqArg, err := json.Marshal(pb.PayloadIDBytes(payloadId))
require.NoError(t, err)
// We expect the JSON string RPC request contains the right arguments.
require.Equal(t, true, strings.Contains(
jsonRequestString, string(reqArg),
))
resp := map[string]interface{}{
"jsonrpc": "2.0",
"id": 1,
"result": want,
}
err = json.NewEncoder(w).Encode(resp)
require.NoError(t, err)
}))
defer srv.Close()
rpcClient, err := rpc.DialHTTP(srv.URL)
require.NoError(t, err)
defer rpcClient.Close()
client := &Client{}
client.rpc = rpcClient
// We call the RPC method via HTTP and expect a proper result.
resp, err := client.GetPayload(ctx, payloadId)
require.NoError(t, err)
require.DeepEqual(t, want, resp)
})
t.Run(ForkchoiceUpdatedMethod, func(t *testing.T) {
forkChoiceState := &pb.ForkchoiceState{
HeadBlockHash: []byte("head"),
SafeBlockHash: []byte("safe"),
FinalizedBlockHash: []byte("finalized"),
}
payloadAttributes := &pb.PayloadAttributes{
Timestamp: 1,
Random: []byte("random"),
SuggestedFeeRecipient: []byte("suggestedFeeRecipient"),
}
want, ok := fix["ForkchoiceUpdatedResponse"].(*ForkchoiceUpdatedResponse)
require.Equal(t, true, ok)
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
defer func() {
require.NoError(t, r.Body.Close())
}()
enc, err := ioutil.ReadAll(r.Body)
require.NoError(t, err)
jsonRequestString := string(enc)
forkChoiceStateReq, err := json.Marshal(forkChoiceState)
require.NoError(t, err)
payloadAttrsReq, err := json.Marshal(payloadAttributes)
require.NoError(t, err)
// We expect the JSON string RPC request contains the right arguments.
require.Equal(t, true, strings.Contains(
jsonRequestString, string(forkChoiceStateReq),
))
require.Equal(t, true, strings.Contains(
jsonRequestString, string(payloadAttrsReq),
))
resp := map[string]interface{}{
"jsonrpc": "2.0",
"id": 1,
"result": want,
}
err = json.NewEncoder(w).Encode(resp)
require.NoError(t, err)
}))
defer srv.Close()
rpcClient, err := rpc.DialHTTP(srv.URL)
require.NoError(t, err)
defer rpcClient.Close()
client := &Client{}
client.rpc = rpcClient
// We call the RPC method via HTTP and expect a proper result.
resp, err := client.ForkchoiceUpdated(ctx, forkChoiceState, payloadAttributes)
require.NoError(t, err)
require.DeepEqual(t, want.Status, resp.Status)
require.DeepEqual(t, want.PayloadId, resp.PayloadId)
})
t.Run(NewPayloadMethod, func(t *testing.T) {
execPayload, ok := fix["ExecutionPayload"].(*pb.ExecutionPayload)
require.Equal(t, true, ok)
want, ok := fix["PayloadStatus"].(*pb.PayloadStatus)
require.Equal(t, true, ok)
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
defer func() {
require.NoError(t, r.Body.Close())
}()
enc, err := ioutil.ReadAll(r.Body)
require.NoError(t, err)
jsonRequestString := string(enc)
reqArg, err := json.Marshal(execPayload)
require.NoError(t, err)
// We expect the JSON string RPC request contains the right arguments.
require.Equal(t, true, strings.Contains(
jsonRequestString, string(reqArg),
))
resp := map[string]interface{}{
"jsonrpc": "2.0",
"id": 1,
"result": want,
}
err = json.NewEncoder(w).Encode(resp)
require.NoError(t, err)
}))
defer srv.Close()
rpcClient, err := rpc.DialHTTP(srv.URL)
require.NoError(t, err)
defer rpcClient.Close()
client := &Client{}
client.rpc = rpcClient
// We call the RPC method via HTTP and expect a proper result.
resp, err := client.NewPayload(ctx, execPayload)
require.NoError(t, err)
require.DeepEqual(t, want, resp)
})
t.Run(ExecutionBlockByNumberMethod, func(t *testing.T) {
want, ok := fix["ExecutionBlock"].(*pb.ExecutionBlock)
require.Equal(t, true, ok)
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
defer func() {
require.NoError(t, r.Body.Close())
}()
resp := map[string]interface{}{
"jsonrpc": "2.0",
"id": 1,
"result": want,
}
err := json.NewEncoder(w).Encode(resp)
require.NoError(t, err)
}))
defer srv.Close()
rpcClient, err := rpc.DialHTTP(srv.URL)
require.NoError(t, err)
defer rpcClient.Close()
client := &Client{}
client.rpc = rpcClient
// We call the RPC method via HTTP and expect a proper result.
resp, err := client.LatestExecutionBlock(ctx)
require.NoError(t, err)
require.DeepEqual(t, want, resp)
})
t.Run(ExecutionBlockByHashMethod, func(t *testing.T) {
arg := common.BytesToHash([]byte("foo"))
want, ok := fix["ExecutionBlock"].(*pb.ExecutionBlock)
require.Equal(t, true, ok)
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
defer func() {
require.NoError(t, r.Body.Close())
}()
enc, err := ioutil.ReadAll(r.Body)
require.NoError(t, err)
jsonRequestString := string(enc)
// We expect the JSON string RPC request contains the right arguments.
require.Equal(t, true, strings.Contains(
jsonRequestString, fmt.Sprintf("%#x", arg),
))
resp := map[string]interface{}{
"jsonrpc": "2.0",
"id": 1,
"result": want,
}
err = json.NewEncoder(w).Encode(resp)
require.NoError(t, err)
}))
defer srv.Close()
rpcClient, err := rpc.DialHTTP(srv.URL)
require.NoError(t, err)
defer rpcClient.Close()
client := &Client{}
client.rpc = rpcClient
// We call the RPC method via HTTP and expect a proper result.
resp, err := client.ExecutionBlockByHash(ctx, arg)
require.NoError(t, err)
require.DeepEqual(t, want, resp)
})
}
type customError struct {
code int
}
func (c *customError) ErrorCode() int {
return c.code
}
func (*customError) Error() string {
return "something went wrong"
}
type dataError struct {
code int
data interface{}
}
func (c *dataError) ErrorCode() int {
return c.code
}
func (*dataError) Error() string {
return "something went wrong"
}
func (c *dataError) ErrorData() interface{} {
return c.data
}
func Test_handleRPCError(t *testing.T) {
got := handleRPCError(nil)
require.Equal(t, true, got == nil)
var tests = []struct {
name string
expected error
expectedContains string
given error
}{
{
name: "not an rpc error",
expectedContains: "got an unexpected error",
given: errors.New("foo"),
},
{
name: "ErrParse",
expectedContains: ErrParse.Error(),
given: &customError{code: -32700},
},
{
name: "ErrInvalidRequest",
expectedContains: ErrInvalidRequest.Error(),
given: &customError{code: -32600},
},
{
name: "ErrMethodNotFound",
expectedContains: ErrMethodNotFound.Error(),
given: &customError{code: -32601},
},
{
name: "ErrInvalidParams",
expectedContains: ErrInvalidParams.Error(),
given: &customError{code: -32602},
},
{
name: "ErrInternal",
expectedContains: ErrInternal.Error(),
given: &customError{code: -32603},
},
{
name: "ErrUnknownPayload",
expectedContains: ErrUnknownPayload.Error(),
given: &customError{code: -32001},
},
{
name: "ErrServer unexpected no data",
expectedContains: "got an unexpected error",
given: &customError{code: -32000},
},
{
name: "ErrServer with data",
expectedContains: ErrServer.Error(),
given: &dataError{code: -32000, data: 5},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := handleRPCError(tt.given)
require.ErrorContains(t, tt.expectedContains, got)
})
}
}
func newTestIPCServer(t *testing.T) *rpc.Server {
server := rpc.NewServer()
err := server.RegisterName("engine", new(testEngineService))
require.NoError(t, err)
err = server.RegisterName("eth", new(testEngineService))
require.NoError(t, err)
return server
}
func fixtures() map[string]interface{} {
foo := bytesutil.ToBytes32([]byte("foo"))
bar := bytesutil.PadTo([]byte("bar"), 20)
baz := bytesutil.PadTo([]byte("baz"), 256)
baseFeePerGas := big.NewInt(6)
executionPayloadFixture := &pb.ExecutionPayload{
ParentHash: foo[:],
FeeRecipient: bar,
StateRoot: foo[:],
ReceiptsRoot: foo[:],
LogsBloom: baz,
Random: foo[:],
BlockNumber: 1,
GasLimit: 1,
GasUsed: 1,
Timestamp: 1,
ExtraData: foo[:],
BaseFeePerGas: bytesutil.PadTo(baseFeePerGas.Bytes(), fieldparams.RootLength),
BlockHash: foo[:],
Transactions: [][]byte{foo[:]},
}
number := bytesutil.PadTo([]byte("100"), fieldparams.RootLength)
hash := bytesutil.PadTo([]byte("hash"), fieldparams.RootLength)
parent := bytesutil.PadTo([]byte("parentHash"), fieldparams.RootLength)
sha3Uncles := bytesutil.PadTo([]byte("sha3Uncles"), fieldparams.RootLength)
miner := bytesutil.PadTo([]byte("miner"), fieldparams.FeeRecipientLength)
stateRoot := bytesutil.PadTo([]byte("stateRoot"), fieldparams.RootLength)
transactionsRoot := bytesutil.PadTo([]byte("transactionsRoot"), fieldparams.RootLength)
receiptsRoot := bytesutil.PadTo([]byte("receiptsRoot"), fieldparams.RootLength)
logsBloom := bytesutil.PadTo([]byte("logs"), fieldparams.LogsBloomLength)
executionBlock := &pb.ExecutionBlock{
Number: number,
Hash: hash,
ParentHash: parent,
Sha3Uncles: sha3Uncles,
Miner: miner,
StateRoot: stateRoot,
TransactionsRoot: transactionsRoot,
ReceiptsRoot: receiptsRoot,
LogsBloom: logsBloom,
Difficulty: bytesutil.PadTo([]byte("1"), fieldparams.RootLength),
TotalDifficulty: bytesutil.PadTo([]byte("2"), fieldparams.RootLength),
GasLimit: 3,
GasUsed: 4,
Timestamp: 5,
Size: bytesutil.PadTo([]byte("6"), fieldparams.RootLength),
ExtraData: bytesutil.PadTo([]byte("extraData"), fieldparams.RootLength),
BaseFeePerGas: bytesutil.PadTo([]byte("baseFeePerGas"), fieldparams.RootLength),
Transactions: [][]byte{foo[:]},
Uncles: [][]byte{foo[:]},
}
status := &pb.PayloadStatus{
Status: pb.PayloadStatus_ACCEPTED,
LatestValidHash: foo[:],
ValidationError: "",
}
id := pb.PayloadIDBytes([8]byte{1, 0, 0, 0, 0, 0, 0, 0})
forkChoiceResp := &ForkchoiceUpdatedResponse{
Status: status,
PayloadId: &id,
}
return map[string]interface{}{
"ExecutionBlock": executionBlock,
"ExecutionPayload": executionPayloadFixture,
"PayloadStatus": status,
"ForkchoiceUpdatedResponse": forkChoiceResp,
}
}
type testEngineService struct{}
func (*testEngineService) NoArgsRets() {}
func (*testEngineService) GetBlockByHash(
_ context.Context, _ common.Hash, _ bool,
) *pb.ExecutionBlock {
fix := fixtures()
item, ok := fix["ExecutionBlock"].(*pb.ExecutionBlock)
if !ok {
panic("not found")
}
return item
}
func (*testEngineService) GetBlockByNumber(
_ context.Context, _ string, _ bool,
) *pb.ExecutionBlock {
fix := fixtures()
item, ok := fix["ExecutionBlock"].(*pb.ExecutionBlock)
if !ok {
panic("not found")
}
return item
}
func (*testEngineService) GetPayloadV1(
_ context.Context, _ pb.PayloadIDBytes,
) *pb.ExecutionPayload {
fix := fixtures()
item, ok := fix["ExecutionPayload"].(*pb.ExecutionPayload)
if !ok {
panic("not found")
}
return item
}
func (*testEngineService) ForkchoiceUpdatedV1(
_ context.Context, _ *pb.ForkchoiceState, _ *pb.PayloadAttributes,
) *ForkchoiceUpdatedResponse {
fix := fixtures()
item, ok := fix["ForkchoiceUpdatedResponse"].(*ForkchoiceUpdatedResponse)
if !ok {
panic("not found")
}
return item
}
func (*testEngineService) NewPayloadV1(
_ context.Context, _ *pb.ExecutionPayload,
) *pb.PayloadStatus {
fix := fixtures()
item, ok := fix["PayloadStatus"].(*pb.PayloadStatus)
if !ok {
panic("not found")
}
return item
}

View File

@@ -32,6 +32,14 @@ func WithHttpEndpoints(endpointStrings []string) Option {
}
}
// WithExecutionEndpoint for the execution node JSON-RPC endpoint.
func WithExecutionEndpoint(endpoint string) Option {
return func(s *Service) error {
s.cfg.executionEndpoint = endpoint
return nil
}
}
// WithDepositContractAddress for the deposit contract.
func WithDepositContractAddress(addr common.Address) Option {
return func(s *Service) error {

View File

@@ -27,10 +27,13 @@ import (
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
"github.com/prysmaticlabs/prysm/beacon-chain/core/transition"
"github.com/prysmaticlabs/prysm/beacon-chain/db"
engine "github.com/prysmaticlabs/prysm/beacon-chain/powchain/engine-api-client/v1"
"github.com/prysmaticlabs/prysm/beacon-chain/powchain/types"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
nativev1 "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/v1"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
"github.com/prysmaticlabs/prysm/config/features"
"github.com/prysmaticlabs/prysm/config/params"
"github.com/prysmaticlabs/prysm/container/trie"
contracts "github.com/prysmaticlabs/prysm/contracts/deposit"
@@ -133,6 +136,7 @@ type config struct {
eth1HeaderReqLimit uint64
beaconNodeStatsUpdater BeaconNodeStatsUpdater
httpEndpoints []network.Endpoint
executionEndpoint string
currHttpEndpoint network.Endpoint
finalizedStateAtStartup state.BeaconState
}
@@ -153,6 +157,7 @@ type Service struct {
headTicker *time.Ticker
httpLogger bind.ContractFilterer
eth1DataFetcher RPCDataFetcher
engineAPIClient *engine.Client
rpcClient RPCClient
headerCache *headerCache // cache to store block hash/block height.
latestEth1Data *ethpb.LatestETH1Data
@@ -208,6 +213,10 @@ func NewService(ctx context.Context, opts ...Option) (*Service, error) {
}
}
if err := s.initializeEngineAPIClient(ctx); err != nil {
return nil, errors.Wrap(err, "unable to initialize engine API client")
}
if err := s.ensureValidPowchainData(ctx); err != nil {
return nil, errors.Wrap(err, "unable to validate powchain data")
}
@@ -271,7 +280,11 @@ func (s *Service) ChainStartDeposits() []*ethpb.Deposit {
// ClearPreGenesisData clears out the stored chainstart deposits and beacon state.
func (s *Service) ClearPreGenesisData() {
s.chainStartData.ChainstartDeposits = []*ethpb.Deposit{}
s.preGenesisState = &v1.BeaconState{}
if features.Get().EnableNativeState {
s.preGenesisState = &nativev1.BeaconState{}
} else {
s.preGenesisState = &v1.BeaconState{}
}
}
// ChainStartEth1Data returns the eth1 data at chainstart.
@@ -298,6 +311,12 @@ func (s *Service) Status() error {
return nil
}
// EngineAPIClient returns the associated engine API client to interact
// with an execution node via JSON-RPC.
func (s *Service) EngineAPIClient() *engine.Client {
return s.engineAPIClient
}
func (s *Service) updateBeaconNodeStats() {
bs := clientstats.BeaconNodeStats{}
if len(s.cfg.httpEndpoints) > 1 {
@@ -783,12 +802,14 @@ func (s *Service) initPOWService() {
s.latestEth1Data.BlockHeight = header.Number.Uint64()
s.latestEth1Data.BlockHash = header.Hash().Bytes()
s.latestEth1Data.BlockTime = header.Time
if err := s.processPastLogs(ctx); err != nil {
log.Errorf("Unable to process past logs %v", err)
s.retryETH1Node(err)
continue
if !features.Get().KilnTestnet {
if err := s.processPastLogs(ctx); err != nil {
log.Errorf("Unable to process past logs %v", err)
s.retryETH1Node(err)
continue
}
}
// Cache eth1 headers from our voting period.
if err := s.cacheHeadersForEth1DataVote(ctx); err != nil {
log.Errorf("Unable to process past headers %v", err)
@@ -797,14 +818,21 @@ func (s *Service) initPOWService() {
}
// Handle edge case with embedded genesis state by fetching genesis header to determine
// its height.
if s.chainStartData.Chainstarted && s.chainStartData.GenesisBlock == 0 {
genHeader, err := s.eth1DataFetcher.HeaderByHash(ctx, common.BytesToHash(s.chainStartData.Eth1Data.BlockHash))
if err != nil {
log.Errorf("Unable to retrieve genesis ETH1.0 chain header: %v", err)
s.retryETH1Node(err)
continue
if s.chainStartData.Chainstarted && s.chainStartData.GenesisBlock == 0 && !features.Get().KilnTestnet {
genHash := common.BytesToHash(s.chainStartData.Eth1Data.BlockHash)
genBlock := s.chainStartData.GenesisBlock
// In the event our provided chainstart data references a non-existent blockhash
// we assume the genesis block to be 0.
if genHash != [32]byte{} {
genHeader, err := s.eth1DataFetcher.HeaderByHash(ctx, genHash)
if err != nil {
log.Errorf("Unable to retrieve genesis ETH1.0 chain header: %v", err)
s.retryETH1Node(err)
continue
}
genBlock = genHeader.Number.Uint64()
}
s.chainStartData.GenesisBlock = genHeader.Number.Uint64()
s.chainStartData.GenesisBlock = genBlock
if err := s.savePowchainData(ctx); err != nil {
log.Errorf("Unable to save powchain data: %v", err)
}
@@ -1073,6 +1101,19 @@ func (s *Service) ensureValidPowchainData(ctx context.Context) error {
return nil
}
// Initializes a connection to the engine API if an execution provider endpoint is set.
func (s *Service) initializeEngineAPIClient(ctx context.Context) error {
if s.cfg.executionEndpoint == "" {
return nil
}
client, err := engine.New(ctx, s.cfg.executionEndpoint)
if err != nil {
return err
}
s.engineAPIClient = client
return nil
}
func dedupEndpoints(endpoints []string) []string {
selectionMap := make(map[string]bool)
newEndpoints := make([]string, 0, len(endpoints))

View File

@@ -24,5 +24,6 @@ go_library(
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
"@com_github_ethereum_go_ethereum//core/types:go_default_library",
"@com_github_ethereum_go_ethereum//rpc:go_default_library",
"@com_github_pkg_errors//:go_default_library",
],
)

View File

@@ -2,10 +2,10 @@ package testing
import (
"context"
"errors"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/async/event"
"github.com/prysmaticlabs/prysm/beacon-chain/powchain/types"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
@@ -76,7 +76,11 @@ func (_ *FaultyMockPOWChain) ChainStartEth1Data() *ethpb.Eth1Data {
// PreGenesisState --
func (_ *FaultyMockPOWChain) PreGenesisState() state.BeaconState {
return &v1.BeaconState{}
s, err := v1.InitializeFromProtoUnsafe(&ethpb.BeaconState{})
if err != nil {
panic("could not initialize state")
}
return s
}
// ClearPreGenesisData --

View File

@@ -22,6 +22,7 @@ go_library(
"//beacon-chain/operations/voluntaryexits:go_default_library",
"//beacon-chain/p2p:go_default_library",
"//beacon-chain/powchain:go_default_library",
"//beacon-chain/powchain/engine-api-client/v1:go_default_library",
"//beacon-chain/rpc/eth/beacon:go_default_library",
"//beacon-chain/rpc/eth/debug:go_default_library",
"//beacon-chain/rpc/eth/events:go_default_library",

View File

@@ -52,7 +52,6 @@ func TestGetSpec(t *testing.T) {
config.BellatrixForkEpoch = 101
config.ShardingForkVersion = []byte("ShardingForkVersion")
config.ShardingForkEpoch = 102
config.MinAnchorPowBlockDifficulty = 1000
config.BLSWithdrawalPrefixByte = byte('b')
config.GenesisDelay = 24
config.SecondsPerSlot = 25
@@ -100,7 +99,7 @@ func TestGetSpec(t *testing.T) {
config.MinSyncCommitteeParticipants = 71
config.TerminalBlockHash = common.HexToHash("TerminalBlockHash")
config.TerminalBlockHashActivationEpoch = 72
config.TerminalTotalDifficulty = 73
config.TerminalTotalDifficulty = "73"
config.FeeRecipient = common.HexToAddress("FeeRecipient")
var dbp [4]byte
@@ -131,7 +130,7 @@ func TestGetSpec(t *testing.T) {
resp, err := server.GetSpec(context.Background(), &emptypb.Empty{})
require.NoError(t, err)
assert.Equal(t, 100, len(resp.Data))
assert.Equal(t, 98, len(resp.Data))
for k, v := range resp.Data {
switch k {
case "CONFIG_NAME":

View File

@@ -275,7 +275,7 @@ func (bs *Server) SubmitVoluntaryExit(ctx context.Context, req *ethpbv1.SignedVo
return nil, status.Errorf(codes.Internal, "Could not get exiting validator: %v", err)
}
alphaExit := migration.V1ExitToV1Alpha1(req)
err = blocks.VerifyExitAndSignature(validator, headState.Slot(), headState.Fork(), alphaExit, headState.GenesisValidatorRoot())
err = blocks.VerifyExitAndSignature(validator, headState.Slot(), headState.Fork(), alphaExit, headState.GenesisValidatorsRoot())
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "Invalid voluntary exit: %v", err)
}

View File

@@ -34,7 +34,7 @@ func (bs *Server) GetGenesis(ctx context.Context, _ *emptypb.Empty) (*ethpb.Gene
if genesisTime.IsZero() {
return nil, status.Errorf(codes.NotFound, "Chain genesis info is not yet known")
}
validatorRoot := bs.ChainInfoFetcher.GenesisValidatorRoot()
validatorRoot := bs.ChainInfoFetcher.GenesisValidatorsRoot()
if bytes.Equal(validatorRoot[:], params.BeaconConfig().ZeroHash[:]) {
return nil, status.Errorf(codes.NotFound, "Chain genesis info is not yet known")
}

View File

@@ -56,7 +56,7 @@ func TestGetGenesis(t *testing.T) {
assert.ErrorContains(t, "Chain genesis info is not yet known", err)
})
t.Run("No genesis validator root", func(t *testing.T) {
t.Run("No genesis validators root", func(t *testing.T) {
chainService := &chainMock.ChainService{
Genesis: genesis,
ValidatorsRoot: [32]byte{},

View File

@@ -13,8 +13,7 @@ go_library(
"//beacon-chain/db:go_default_library",
"//beacon-chain/rpc/eth/helpers:go_default_library",
"//beacon-chain/rpc/statefetcher:go_default_library",
"//beacon-chain/state/v1:go_default_library",
"//beacon-chain/state/v2:go_default_library",
"//beacon-chain/state:go_default_library",
"//proto/eth/v1:go_default_library",
"//proto/eth/v2:go_default_library",
"//proto/migration:go_default_library",

View File

@@ -4,8 +4,7 @@ import (
"context"
"github.com/prysmaticlabs/prysm/beacon-chain/rpc/eth/helpers"
statev1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
statev2 "github.com/prysmaticlabs/prysm/beacon-chain/state/v2"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
ethpbv1 "github.com/prysmaticlabs/prysm/proto/eth/v1"
ethpbv2 "github.com/prysmaticlabs/prysm/proto/eth/v2"
"github.com/prysmaticlabs/prysm/proto/migration"
@@ -26,11 +25,10 @@ func (ds *Server) GetBeaconState(ctx context.Context, req *ethpbv1.StateRequest)
return nil, helpers.PrepareStateFetchGRPCError(err)
}
st, ok := beaconSt.(*statev1.BeaconState)
if !ok {
return nil, status.Error(codes.Internal, "State type assertion failed")
if beaconSt.Version() != version.Phase0 {
return nil, status.Error(codes.Internal, "State has incorrect type")
}
protoSt, err := migration.BeaconStateToV1(st)
protoSt, err := migration.BeaconStateToV1(beaconSt)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not convert state to proto: %v", err)
}
@@ -69,11 +67,7 @@ func (ds *Server) GetBeaconStateV2(ctx context.Context, req *ethpbv2.StateReques
}
switch beaconSt.Version() {
case version.Phase0:
st, ok := beaconSt.(*statev1.BeaconState)
if !ok {
return nil, status.Error(codes.Internal, "State type assertion failed")
}
protoSt, err := migration.BeaconStateToV1(st)
protoSt, err := migration.BeaconStateToV1(beaconSt)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not convert state to proto: %v", err)
}
@@ -84,7 +78,7 @@ func (ds *Server) GetBeaconStateV2(ctx context.Context, req *ethpbv2.StateReques
},
}, nil
case version.Altair:
altairState, ok := beaconSt.(*statev2.BeaconState)
altairState, ok := beaconSt.(state.BeaconStateAltair)
if !ok {
return nil, status.Error(codes.Internal, "Altair state type assertion failed")
}

View File

@@ -910,7 +910,7 @@ func TestServer_StreamIndexedAttestations_OK(t *testing.T) {
},
},
}
domain, err := signing.Domain(headState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, headState.GenesisValidatorRoot())
domain, err := signing.Domain(headState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, headState.GenesisValidatorsRoot())
require.NoError(t, err)
encoded, err := signing.ComputeSigningRoot(attExample.Data, domain)
require.NoError(t, err)

View File

@@ -68,7 +68,7 @@ func (ns *Server) GetGenesis(ctx context.Context, _ *empty.Empty) (*ethpb.Genesi
gt = timestamppb.New(genesisTime)
}
genValRoot := ns.GenesisFetcher.GenesisValidatorRoot()
genValRoot := ns.GenesisFetcher.GenesisValidatorsRoot()
return &ethpb.Genesis{
GenesisTime: gt,
DepositContractAddress: contractAddr,
@@ -227,7 +227,11 @@ func (ns *Server) GetETH1ConnectionStatus(ctx context.Context, _ *empty.Empty) (
errs := ns.POWChainInfoFetcher.ETH1ConnectionErrors()
// Extract string version of the errors.
for _, err := range errs {
errStrs = append(errStrs, err.Error())
if err == nil {
errStrs = append(errStrs, "")
} else {
errStrs = append(errStrs, err.Error())
}
}
return &ethpb.ETH1ConnectionStatus{
CurrentAddress: ns.POWChainInfoFetcher.CurrentETH1Endpoint(),

View File

@@ -153,8 +153,8 @@ func TestNodeServer_ListPeers(t *testing.T) {
func TestNodeServer_GetETH1ConnectionStatus(t *testing.T) {
server := grpc.NewServer()
eps := []string{"foo", "bar"}
errs := []error{fmt.Errorf("error 1"), fmt.Errorf("error 2")}
errStrs := []string{"error 1", "error 2"}
errs := []error{fmt.Errorf("error 1"), fmt.Errorf("error 2"), nil}
errStrs := []string{"error 1", "error 2", ""}
mockFetcher := &testutil.MockPOWChainInfoFetcher{
CurrEndpoint: eps[0],
CurrError: errs[0],

View File

@@ -12,8 +12,10 @@ go_library(
"proposer.go",
"proposer_altair.go",
"proposer_attestations.go",
"proposer_bellatrix.go",
"proposer_deposits.go",
"proposer_eth1data.go",
"proposer_execution_payload.go",
"proposer_phase0.go",
"proposer_sync_aggregate.go",
"server.go",
@@ -39,12 +41,14 @@ go_library(
"//beacon-chain/core/transition:go_default_library",
"//beacon-chain/core/transition/interop:go_default_library",
"//beacon-chain/core/validators:go_default_library",
"//beacon-chain/db:go_default_library",
"//beacon-chain/operations/attestations:go_default_library",
"//beacon-chain/operations/slashings:go_default_library",
"//beacon-chain/operations/synccommittee:go_default_library",
"//beacon-chain/operations/voluntaryexits:go_default_library",
"//beacon-chain/p2p:go_default_library",
"//beacon-chain/powchain:go_default_library",
"//beacon-chain/powchain/engine-api-client/v1:go_default_library",
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/stategen:go_default_library",
"//beacon-chain/sync:go_default_library",
@@ -59,6 +63,7 @@ go_library(
"//encoding/bytesutil:go_default_library",
"//monitoring/tracing:go_default_library",
"//network/forks:go_default_library",
"//proto/engine/v1:go_default_library",
"//proto/eth/v1:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//proto/prysm/v1alpha1/attestation/aggregation:go_default_library",
@@ -69,7 +74,9 @@ go_library(
"//runtime/version:go_default_library",
"//time:go_default_library",
"//time/slots:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_ferranbt_fastssz//:go_default_library",
"@com_github_holiman_uint256//:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
@@ -134,6 +141,7 @@ go_test(
"//container/trie:go_default_library",
"//crypto/bls:go_default_library",
"//encoding/bytesutil:go_default_library",
"//proto/engine/v1:go_default_library",
"//proto/eth/v1:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//proto/prysm/v1alpha1/attestation:go_default_library",

View File

@@ -30,7 +30,8 @@ import (
func TestSubmitAggregateAndProof_Syncing(t *testing.T) {
ctx := context.Background()
s := &v1.BeaconState{}
s, err := v1.InitializeFromProtoUnsafe(&ethpb.BeaconState{})
require.NoError(t, err)
aggregatorServer := &Server{
HeadFetcher: &mock.ChainService{State: s},
@@ -39,7 +40,7 @@ func TestSubmitAggregateAndProof_Syncing(t *testing.T) {
req := &ethpb.AggregateSelectionRequest{CommitteeIndex: 1}
wanted := "Syncing to latest head, not ready to respond"
_, err := aggregatorServer.SubmitAggregateSelectionProof(ctx, req)
_, err = aggregatorServer.SubmitAggregateSelectionProof(ctx, req)
assert.ErrorContains(t, wanted, err)
}

View File

@@ -34,7 +34,7 @@ func (vs *Server) ProposeExit(ctx context.Context, req *ethpb.SignedVoluntaryExi
return nil, status.Error(codes.InvalidArgument, "validator index exceeds validator set length")
}
if err := blocks.VerifyExitAndSignature(val, s.Slot(), s.Fork(), req, s.GenesisValidatorRoot()); err != nil {
if err := blocks.VerifyExitAndSignature(val, s.Slot(), s.Fork(), req, s.GenesisValidatorsRoot()); err != nil {
return nil, status.Error(codes.InvalidArgument, err.Error())
}

View File

@@ -40,12 +40,20 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (
return nil, status.Errorf(codes.Internal, "Could not fetch phase0 beacon block: %v", err)
}
return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_Phase0{Phase0: blk}}, nil
} else if slots.ToEpoch(req.Slot) < params.BeaconConfig().BellatrixForkEpoch {
blk, err := vs.getAltairBeaconBlock(ctx, req)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not fetch Altair beacon block: %v", err)
}
return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_Altair{Altair: blk}}, nil
}
blk, err := vs.getAltairBeaconBlock(ctx, req)
blk, err := vs.getBellatrixBeaconBlock(ctx, req)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not fetch Altair beacon block: %v", err)
return nil, status.Errorf(codes.Internal, "Could not fetch Bellatrix beacon block: %v", err)
}
return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_Altair{Altair: blk}}, nil
return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_Bellatrix{Bellatrix: blk}}, nil
}
// GetBlock is called by a proposer during its assigned slot to request a block to sign
@@ -75,6 +83,11 @@ func (vs *Server) ProposeBeaconBlock(ctx context.Context, req *ethpb.GenericSign
if err != nil {
return nil, status.Error(codes.Internal, "could not wrap altair beacon block")
}
case *ethpb.GenericSignedBeaconBlock_Bellatrix:
blk, err = wrapper.WrappedBellatrixSignedBeaconBlock(b.Bellatrix)
if err != nil {
return nil, status.Error(codes.Internal, "could not wrap Bellatrix beacon block")
}
default:
return nil, status.Error(codes.Internal, "block version not supported")
}

View File

@@ -15,8 +15,8 @@ import (
"go.opencensus.io/trace"
)
func (vs *Server) getAltairBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (*ethpb.BeaconBlockAltair, error) {
ctx, span := trace.StartSpan(ctx, "ProposerServer.getAltairBeaconBlock")
func (vs *Server) buildAltairBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (*ethpb.BeaconBlockAltair, error) {
ctx, span := trace.StartSpan(ctx, "ProposerServer.buildAltairBeaconBlock")
defer span.End()
blkData, err := vs.buildPhase0BlockData(ctx, req)
if err != nil {
@@ -33,7 +33,7 @@ func (vs *Server) getAltairBeaconBlock(ctx context.Context, req *ethpb.BlockRequ
return nil, err
}
blk := &ethpb.BeaconBlockAltair{
return &ethpb.BeaconBlockAltair{
Slot: req.Slot,
ParentRoot: blkData.ParentRoot,
StateRoot: stateRoot,
@@ -49,6 +49,15 @@ func (vs *Server) getAltairBeaconBlock(ctx context.Context, req *ethpb.BlockRequ
Graffiti: blkData.Graffiti[:],
SyncAggregate: syncAggregate,
},
}, nil
}
func (vs *Server) getAltairBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (*ethpb.BeaconBlockAltair, error) {
ctx, span := trace.StartSpan(ctx, "ProposerServer.getAltairBeaconBlock")
defer span.End()
blk, err := vs.buildAltairBeaconBlock(ctx, req)
if err != nil {
return nil, fmt.Errorf("could not build block data: %v", err)
}
// Compute state root with the newly constructed block.
wsb, err := wrapper.WrappedAltairSignedBeaconBlock(
@@ -57,7 +66,7 @@ func (vs *Server) getAltairBeaconBlock(ctx context.Context, req *ethpb.BlockRequ
if err != nil {
return nil, err
}
stateRoot, err = vs.computeStateRoot(ctx, wsb)
stateRoot, err := vs.computeStateRoot(ctx, wsb)
if err != nil {
interop.WriteBlockToDisk(wsb, true /*failed*/)
return nil, fmt.Errorf("could not compute state root: %v", err)

View File

@@ -89,7 +89,7 @@ func (a proposerAtts) filter(ctx context.Context, st state.BeaconState) (propose
switch st.Version() {
case version.Phase0:
attestationProcessor = blocks.ProcessAttestationNoVerifySignature
case version.Altair:
case version.Altair, version.Bellatrix:
// Use a wrapper here, as go needs strong typing for the function signature.
attestationProcessor = func(ctx context.Context, st state.BeaconState, attestation *ethpb.Attestation) (state.BeaconState, error) {
totalBalance, err := helpers.TotalActiveBalance(st)

View File

@@ -0,0 +1,64 @@
package validator
import (
"context"
"fmt"
"github.com/prysmaticlabs/prysm/beacon-chain/core/transition/interop"
"github.com/prysmaticlabs/prysm/config/params"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
"github.com/sirupsen/logrus"
)
func (vs *Server) getBellatrixBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (*ethpb.BeaconBlockBellatrix, error) {
altairBlk, err := vs.buildAltairBeaconBlock(ctx, req)
if err != nil {
return nil, err
}
payload, err := vs.getExecutionPayload(ctx, req.Slot)
if err != nil {
return nil, err
}
log.WithFields(logrus.Fields{
"hash": fmt.Sprintf("%#x", payload.BlockHash),
"parentHash": fmt.Sprintf("%#x", payload.ParentHash),
"number": payload.BlockNumber,
"txCount": len(payload.Transactions),
}).Info("Received payload")
blk := &ethpb.BeaconBlockBellatrix{
Slot: altairBlk.Slot,
ProposerIndex: altairBlk.ProposerIndex,
ParentRoot: altairBlk.ParentRoot,
StateRoot: params.BeaconConfig().ZeroHash[:],
Body: &ethpb.BeaconBlockBodyBellatrix{
RandaoReveal: altairBlk.Body.RandaoReveal,
Eth1Data: altairBlk.Body.Eth1Data,
Graffiti: altairBlk.Body.Graffiti,
ProposerSlashings: altairBlk.Body.ProposerSlashings,
AttesterSlashings: altairBlk.Body.AttesterSlashings,
Attestations: altairBlk.Body.Attestations,
Deposits: altairBlk.Body.Deposits,
VoluntaryExits: altairBlk.Body.VoluntaryExits,
SyncAggregate: altairBlk.Body.SyncAggregate,
ExecutionPayload: payload,
},
}
// Compute state root with the newly constructed block.
wsb, err := wrapper.WrappedBellatrixSignedBeaconBlock(
&ethpb.SignedBeaconBlockBellatrix{Block: blk, Signature: make([]byte, 96)},
)
if err != nil {
return nil, err
}
stateRoot, err := vs.computeStateRoot(ctx, wsb)
if err != nil {
interop.WriteBlockToDisk(wsb, true /*failed*/)
return nil, fmt.Errorf("could not compute state root: %v", err)
}
blk.StateRoot = stateRoot
return blk, nil
}

View File

@@ -0,0 +1,248 @@
package validator
import (
"context"
"fmt"
"math/big"
"github.com/holiman/uint256"
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/core/time"
"github.com/prysmaticlabs/prysm/beacon-chain/core/transition"
"github.com/prysmaticlabs/prysm/config/params"
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
enginev1 "github.com/prysmaticlabs/prysm/proto/engine/v1"
"github.com/prysmaticlabs/prysm/runtime/version"
"github.com/prysmaticlabs/prysm/time/slots"
"github.com/sirupsen/logrus"
)
// This returns the execution payload of a given slot. The function has full awareness of pre and post merge.
// Payload is computed given the respected time of merge.
//
// Spec code:
// def prepare_execution_payload(state: BeaconState,
// pow_chain: Dict[Hash32, PowBlock],
// finalized_block_hash: Hash32,
// fee_recipient: ExecutionAddress,
// execution_engine: ExecutionEngine) -> Optional[PayloadId]:
// if not is_merge_complete(state):
// is_terminal_block_hash_set = TERMINAL_BLOCK_HASH != Hash32()
// is_activation_epoch_reached = get_current_epoch(state.slot) >= TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH
// if is_terminal_block_hash_set and not is_activation_epoch_reached:
// # Terminal block hash is set but activation epoch is not yet reached, no prepare payload call is needed
// return None
//
// terminal_pow_block = get_terminal_pow_block(pow_chain)
// if terminal_pow_block is None:
// # Pre-merge, no prepare payload call is needed
// return None
// # Signify merge via producing on top of the terminal PoW block
// parent_hash = terminal_pow_block.block_hash
// else:
// # Post-merge, normal payload
// parent_hash = state.latest_execution_payload_header.block_hash
//
// # Set the forkchoice head and initiate the payload build process
// payload_attributes = PayloadAttributes(
// timestamp=compute_timestamp_at_slot(state, state.slot),
// random=get_randao_mix(state, get_current_epoch(state)),
// fee_recipient=fee_recipient,
// )
// return execution_engine.notify_forkchoice_updated(parent_hash, finalized_block_hash, payload_attributes)
func (vs *Server) getExecutionPayload(ctx context.Context, slot types.Slot) (*enginev1.ExecutionPayload, error) {
// TODO_MERGE: Reuse the same head state as in building phase0 block attestation.
st, err := vs.HeadFetcher.HeadState(ctx)
if err != nil {
return nil, err
}
st, err = transition.ProcessSlots(ctx, st, slot)
if err != nil {
return nil, err
}
var parentHash []byte
var hasTerminalBlock bool
complete, err := blocks.MergeTransitionComplete(st)
if err != nil {
return nil, err
}
if !complete {
if bytesutil.ToBytes32(params.BeaconConfig().TerminalBlockHash.Bytes()) != [32]byte{} {
// `TERMINAL_BLOCK_HASH` is used as an override, the activation epoch must be reached.
isActivationEpochReached := params.BeaconConfig().TerminalBlockHashActivationEpoch <= slots.ToEpoch(slot)
if !isActivationEpochReached {
return blocks.EmptyPayload(), nil
}
}
parentHash, hasTerminalBlock, err = vs.getTerminalBlockHash(ctx)
if err != nil {
return nil, err
}
if !hasTerminalBlock {
// No terminal block signals this is pre merge, empty payload is used.
return blocks.EmptyPayload(), nil
}
// Terminal block found signals production on top of terminal PoW block.
} else {
// Post merge, normal payload is used.
header, err := st.LatestExecutionPayloadHeader()
if err != nil {
return nil, err
}
parentHash = header.BlockHash
}
t, err := slots.ToTime(st.GenesisTime(), slot)
if err != nil {
return nil, err
}
random, err := helpers.RandaoMix(st, time.CurrentEpoch(st))
if err != nil {
return nil, err
}
finalizedBlock, err := vs.BeaconDB.Block(ctx, bytesutil.ToBytes32(st.FinalizedCheckpoint().Root))
if err != nil {
return nil, err
}
finalizedBlockHash := params.BeaconConfig().ZeroHash[:]
if finalizedBlock != nil && finalizedBlock.Version() == version.Bellatrix {
finalizedPayload, err := finalizedBlock.Block().Body().ExecutionPayload()
if err != nil {
return nil, err
}
finalizedBlockHash = finalizedPayload.BlockHash
}
f := &enginev1.ForkchoiceState{
HeadBlockHash: parentHash,
SafeBlockHash: parentHash,
FinalizedBlockHash: finalizedBlockHash,
}
p := &enginev1.PayloadAttributes{
Timestamp: uint64(t.Unix()),
Random: random,
SuggestedFeeRecipient: params.BeaconConfig().FeeRecipient.Bytes(),
}
res, err := vs.ExecutionEngineCaller.ForkchoiceUpdated(ctx, f, p)
if err != nil {
return nil, errors.Wrap(err, "could not prepare payload")
}
if res == nil || res.PayloadId == nil {
return nil, errors.New("forkchoice returned nil")
}
log.WithFields(logrus.Fields{
"id": fmt.Sprintf("%#x", res.PayloadId),
"slot": slot,
"hash": fmt.Sprintf("%#x", parentHash),
}).Info("Received payload ID")
var id [8]byte
copy(id[:], res.PayloadId[:])
return vs.ExecutionEngineCaller.GetPayload(ctx, id)
}
// This returns the valid terminal block hash with an existence bool value.
//
// Spec code:
// def get_terminal_pow_block(pow_chain: Dict[Hash32, PowBlock]) -> Optional[PowBlock]:
// if TERMINAL_BLOCK_HASH != Hash32():
// # Terminal block hash override takes precedence over terminal total difficulty
// if TERMINAL_BLOCK_HASH in pow_chain:
// return pow_chain[TERMINAL_BLOCK_HASH]
// else:
// return None
//
// return get_pow_block_at_terminal_total_difficulty(pow_chain)
func (vs *Server) getTerminalBlockHash(ctx context.Context) ([]byte, bool, error) {
terminalBlockHash := params.BeaconConfig().TerminalBlockHash
// Terminal block hash override takes precedence over terminal total difficult.
if params.BeaconConfig().TerminalBlockHash != params.BeaconConfig().ZeroHash {
e, _, err := vs.Eth1BlockFetcher.BlockExists(ctx, terminalBlockHash)
if err != nil {
return nil, false, err
}
if !e {
return nil, false, nil
}
return terminalBlockHash.Bytes(), true, nil
}
return vs.getPowBlockHashAtTerminalTotalDifficulty(ctx)
}
// This returns the valid terminal block hash based on total difficulty.
//
// Spec code:
// def get_pow_block_at_terminal_total_difficulty(pow_chain: Dict[Hash32, PowBlock]) -> Optional[PowBlock]:
// # `pow_chain` abstractly represents all blocks in the PoW chain
// for block in pow_chain:
// parent = pow_chain[block.parent_hash]
// block_reached_ttd = block.total_difficulty >= TERMINAL_TOTAL_DIFFICULTY
// parent_reached_ttd = parent.total_difficulty >= TERMINAL_TOTAL_DIFFICULTY
// if block_reached_ttd and not parent_reached_ttd:
// return block
//
// return None
func (vs *Server) getPowBlockHashAtTerminalTotalDifficulty(ctx context.Context) ([]byte, bool, error) {
ttd := new(big.Int)
ttd.SetString(params.BeaconConfig().TerminalTotalDifficulty, 10)
terminalTotalDifficulty, of := uint256.FromBig(ttd)
if of {
return nil, false, errors.New("could not convert terminal total difficulty to uint256")
}
blk, err := vs.ExecutionEngineCaller.LatestExecutionBlock(ctx)
if err != nil {
return nil, false, errors.Wrap(err, "could not get latest execution block")
}
log.WithFields(logrus.Fields{
"number": blk.Number,
"hash": fmt.Sprintf("%#x", blk.Hash),
"td": blk.TotalDifficulty,
}).Info("Retrieving latest execution block")
for {
currentTotalDifficulty := new(uint256.Int)
currentTotalDifficulty.SetBytes(bytesutil.ReverseByteOrder(blk.TotalDifficulty))
blockReachedTTD := currentTotalDifficulty.Cmp(terminalTotalDifficulty) >= 0
parentHash := bytesutil.ToBytes32(blk.ParentHash)
if len(blk.ParentHash) == 0 || parentHash == params.BeaconConfig().ZeroHash {
return nil, false, nil
}
parentBlk, err := vs.ExecutionEngineCaller.ExecutionBlockByHash(ctx, parentHash)
if err != nil {
return nil, false, errors.Wrap(err, "could not get parent execution block")
}
log.WithFields(logrus.Fields{
"number": parentBlk.Number,
"hash": fmt.Sprintf("%#x", parentBlk.Hash),
"td": parentBlk.TotalDifficulty,
}).Info("Retrieving parent execution block")
if blockReachedTTD {
parentTotalDifficulty := new(uint256.Int)
parentTotalDifficulty.SetBytes(bytesutil.ReverseByteOrder(parentBlk.TotalDifficulty))
parentReachedTTD := parentTotalDifficulty.Cmp(terminalTotalDifficulty) >= 0
if !parentReachedTTD {
log.WithFields(logrus.Fields{
"number": blk.Number,
"hash": fmt.Sprintf("%#x", blk.Hash),
"td": blk.TotalDifficulty,
"parentTd": parentBlk.TotalDifficulty,
"ttd": terminalTotalDifficulty,
}).Info("Retrieved terminal block hash")
return blk.Hash, true, nil
}
}
blk = parentBlk
}
}

View File

@@ -144,7 +144,7 @@ func (vs *Server) buildPhase0BlockData(ctx context.Context, req *ethpb.BlockRequ
log.WithError(err).Warn("Proposer: invalid exit")
continue
}
if err := blocks.VerifyExitAndSignature(val, head.Slot(), head.Fork(), exit, head.GenesisValidatorRoot()); err != nil {
if err := blocks.VerifyExitAndSignature(val, head.Slot(), head.Fork(), exit, head.GenesisValidatorsRoot()); err != nil {
log.WithError(err).Warn("Proposer: invalid exit")
continue
}

View File

@@ -25,10 +25,12 @@ import (
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
mockSync "github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync/testing"
"github.com/prysmaticlabs/prysm/config/features"
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
"github.com/prysmaticlabs/prysm/config/params"
"github.com/prysmaticlabs/prysm/container/trie"
"github.com/prysmaticlabs/prysm/crypto/bls"
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
enginev1 "github.com/prysmaticlabs/prysm/proto/engine/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/attestation"
attaggregation "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/attestation/aggregation/attestations"
@@ -281,6 +283,44 @@ func TestProposer_ProposeBlock_Altair_OK(t *testing.T) {
assert.NoError(t, err, "Could not propose block correctly")
}
func TestProposer_ProposeBlock_Bellatrix_OK(t *testing.T) {
db := dbutil.SetupDB(t)
ctx := context.Background()
params.SetupTestConfigCleanup(t)
params.OverrideBeaconConfig(params.MainnetConfig())
genesis := util.NewBeaconBlock()
require.NoError(t, db.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(genesis)), "Could not save genesis block")
numDeposits := uint64(64)
beaconState, _ := util.DeterministicGenesisStateBellatrix(t, numDeposits)
bsRoot, err := beaconState.HashTreeRoot(ctx)
require.NoError(t, err)
genesisRoot, err := genesis.Block.HashTreeRoot()
require.NoError(t, err)
require.NoError(t, db.SaveState(ctx, beaconState, genesisRoot), "Could not save genesis state")
c := &mock.ChainService{Root: bsRoot[:], State: beaconState}
proposerServer := &Server{
ChainStartFetcher: &mockPOW.POWChain{},
Eth1InfoFetcher: &mockPOW.POWChain{},
Eth1BlockFetcher: &mockPOW.POWChain{},
BlockReceiver: c,
HeadFetcher: c,
BlockNotifier: c.BlockNotifier(),
P2P: mockp2p.NewTestP2P(t),
}
blockToPropose := util.NewBeaconBlockBellatrix()
blockToPropose.Block.Slot = 5
blockToPropose.Block.ParentRoot = bsRoot[:]
blk := &ethpb.GenericSignedBeaconBlock_Bellatrix{Bellatrix: blockToPropose}
wrapped, err := wrapper.WrappedSignedBeaconBlock(blockToPropose)
require.NoError(t, err)
require.NoError(t, db.SaveBlock(ctx, wrapped))
_, err = proposerServer.ProposeBeaconBlock(context.Background(), &ethpb.GenericSignedBeaconBlock{Block: blk})
assert.NoError(t, err, "Could not propose block correctly")
}
func TestProposer_ComputeStateRoot_OK(t *testing.T) {
db := dbutil.SetupDB(t)
ctx := context.Background()
@@ -1790,7 +1830,7 @@ func TestProposer_FilterAttestation(t *testing.T) {
numValidators := uint64(64)
state, privKeys := util.DeterministicGenesisState(t, numValidators)
require.NoError(t, state.SetGenesisValidatorRoot(params.BeaconConfig().ZeroHash[:]))
require.NoError(t, state.SetGenesisValidatorsRoot(params.BeaconConfig().ZeroHash[:]))
assert.NoError(t, state.SetSlot(1))
genesisRoot, err := genesis.Block.HashTreeRoot()
@@ -2222,6 +2262,101 @@ func TestProposer_GetBeaconBlock_PostForkEpoch(t *testing.T) {
assert.DeepEqual(t, attSlashings, altairBlk.Altair.Body.AttesterSlashings)
}
func TestProposer_GetBeaconBlock_BellatrixEpoch(t *testing.T) {
db := dbutil.SetupDB(t)
ctx := context.Background()
params.SetupTestConfigCleanup(t)
cfg := params.MainnetConfig().Copy()
cfg.BellatrixForkEpoch = 2
cfg.AltairForkEpoch = 1
params.OverrideBeaconConfig(cfg)
beaconState, privKeys := util.DeterministicGenesisState(t, 64)
stateRoot, err := beaconState.HashTreeRoot(ctx)
require.NoError(t, err, "Could not hash genesis state")
genesis := b.NewGenesisBlock(stateRoot[:])
wsb := wrapper.WrappedPhase0SignedBeaconBlock(genesis)
require.NoError(t, err)
require.NoError(t, db.SaveBlock(ctx, wsb), "Could not save genesis block")
parentRoot, err := genesis.Block.HashTreeRoot()
require.NoError(t, err, "Could not get signing root")
require.NoError(t, db.SaveState(ctx, beaconState, parentRoot), "Could not save genesis state")
require.NoError(t, db.SaveHeadBlockRoot(ctx, parentRoot), "Could not save genesis state")
bellatrixSlot, err := slots.EpochStart(params.BeaconConfig().BellatrixForkEpoch)
require.NoError(t, err)
blk := &ethpb.SignedBeaconBlockBellatrix{
Block: &ethpb.BeaconBlockBellatrix{
Slot: bellatrixSlot + 1,
ParentRoot: parentRoot[:],
StateRoot: genesis.Block.StateRoot,
Body: &ethpb.BeaconBlockBodyBellatrix{
RandaoReveal: genesis.Block.Body.RandaoReveal,
Graffiti: genesis.Block.Body.Graffiti,
Eth1Data: genesis.Block.Body.Eth1Data,
SyncAggregate: &ethpb.SyncAggregate{SyncCommitteeBits: bitfield.NewBitvector512(), SyncCommitteeSignature: make([]byte, 96)},
ExecutionPayload: &enginev1.ExecutionPayload{
ParentHash: make([]byte, fieldparams.RootLength),
FeeRecipient: make([]byte, fieldparams.FeeRecipientLength),
StateRoot: make([]byte, fieldparams.RootLength),
ReceiptsRoot: make([]byte, fieldparams.RootLength),
LogsBloom: make([]byte, fieldparams.LogsBloomLength),
Random: make([]byte, fieldparams.RootLength),
BaseFeePerGas: make([]byte, fieldparams.RootLength),
BlockHash: make([]byte, fieldparams.RootLength),
},
},
},
Signature: genesis.Signature,
}
blkRoot, err := blk.Block.HashTreeRoot()
require.NoError(t, err)
require.NoError(t, err, "Could not get signing root")
require.NoError(t, db.SaveState(ctx, beaconState, blkRoot), "Could not save genesis state")
require.NoError(t, db.SaveHeadBlockRoot(ctx, blkRoot), "Could not save genesis state")
proposerServer := &Server{
HeadFetcher: &mock.ChainService{State: beaconState, Root: parentRoot[:]},
SyncChecker: &mockSync.Sync{IsSyncing: false},
BlockReceiver: &mock.ChainService{},
ChainStartFetcher: &mockPOW.POWChain{},
Eth1InfoFetcher: &mockPOW.POWChain{},
Eth1BlockFetcher: &mockPOW.POWChain{},
MockEth1Votes: true,
AttPool: attestations.NewPool(),
SlashingsPool: slashings.NewPool(),
ExitPool: voluntaryexits.NewPool(),
StateGen: stategen.New(db),
SyncCommitteePool: synccommittee.NewStore(),
}
randaoReveal, err := util.RandaoReveal(beaconState, 0, privKeys)
require.NoError(t, err)
graffiti := bytesutil.ToBytes32([]byte("eth2"))
require.NoError(t, err)
req := &ethpb.BlockRequest{
Slot: bellatrixSlot + 1,
RandaoReveal: randaoReveal,
Graffiti: graffiti[:],
}
block, err := proposerServer.GetBeaconBlock(ctx, req)
require.NoError(t, err)
bellatrixBlk, ok := block.GetBlock().(*ethpb.GenericBeaconBlock_Bellatrix)
require.Equal(t, true, ok)
assert.Equal(t, req.Slot, bellatrixBlk.Bellatrix.Slot)
assert.DeepEqual(t, parentRoot[:], bellatrixBlk.Bellatrix.ParentRoot, "Expected block to have correct parent root")
assert.DeepEqual(t, randaoReveal, bellatrixBlk.Bellatrix.Body.RandaoReveal, "Expected block to have correct randao reveal")
assert.DeepEqual(t, req.Graffiti, bellatrixBlk.Bellatrix.Body.Graffiti, "Expected block to have correct Graffiti")
}
func TestProposer_GetSyncAggregate_OK(t *testing.T) {
proposerServer := &Server{
SyncChecker: &mockSync.Sync{IsSyncing: false},

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