Compare commits

...

110 Commits

Author SHA1 Message Date
nisdas
61e57cac49 Merge branch 'capella-marshal-unmarshal' of https://github.com/prysmaticlabs/geth-sharding into devnet-3 2023-01-17 19:42:34 +08:00
nisdas
2d9c1bf6ee add flag to develop 2023-01-17 19:34:09 +08:00
prylabs-bulldozer[bot]
5388286d25 Merge refs/heads/develop into capella-marshal-unmarshal 2023-01-17 10:59:58 +00:00
Potuz
75d98cf9af Do not log an overflow computing Capella's slot start (#11884)
* Do not log an overflow computing Capella's slot start

* nishant's review

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

Co-authored-by: Nishant Das <nishdas93@gmail.com>
2023-01-17 10:59:51 +00:00
prylabs-bulldozer[bot]
1aba7d6b78 Merge refs/heads/develop into capella-marshal-unmarshal 2023-01-17 09:45:27 +00:00
Radosław Kapka
96401e734e Implement bls_to_execution_change API event (#11865)
* Implement `bls_to_execution_change` API event

(cherry picked from commit 1c8a2c580b3664e1238380138dc65c30e238cb11)
(cherry picked from commit aabcaac619)

* missing event code

(cherry picked from commit daa4fd2b72)

* Update beacon-chain/core/feed/operation/events.go

Co-authored-by: Nishant Das <nishdas93@gmail.com>
2023-01-17 09:45:20 +00:00
Potuz
94379741cf skip test 2023-01-16 23:40:35 -03:00
Potuz
372de81eeb Merge branch 'develop' into capella-marshal-unmarshal 2023-01-16 19:14:17 -03:00
terencechain
5480d607ac Change withdrawal amount unmarshal to uint64 (gwei) (#11866)
* Change withdrawal amount unmarshal to uint64 (gwei)

* Init server

Co-authored-by: Nishant Das <nishdas93@gmail.com>
Co-authored-by: Potuz <potuz@prysmaticlabs.com>
2023-01-16 21:25:16 +00:00
terence tsao
97355690ce Add capella's marshal and unmarshal 2023-01-16 09:56:08 -08:00
terencechain
38f0a81526 Clarify circuit breaker logs (#11876)
* Clarify circuit breaker logs

* Revert bad changes

* Fix test
2023-01-16 17:49:23 +00:00
Potuz
ad680d3417 Move broadcast of BLS changes to the forkwatcher (#11878)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2023-01-16 15:00:11 +00:00
Potuz
047cae5e8b Sign BLS_TO_EXECUTION_CHANGES with GENESIS_FORK_VERSION (#11870)
* Sign BLS_TO_EXECUTION_CHANGES with GENESIS_FORK_VERSION

* update spectests

* extra blank line

* fix consensus_specs_sha

* get rid of LightClients tests

* fix unit tests

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2023-01-16 14:29:33 +00:00
terencechain
179252faea Address historical summaries feedback (#11864)
* Address historical summaries feedback

* Fix build

* Fix test

* Move historicalSummaries

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2023-01-16 12:44:40 +00:00
Potuz
f93b82ee89 broadcast bls changes at the fork (#11872) 2023-01-16 11:51:03 +00:00
int88
508e1ad005 optimize and fix bug of attestations related code (#11869)
Co-authored-by: Nishant Das <nishdas93@gmail.com>
2023-01-16 02:19:46 +00:00
terencechain
1b2d917389 New prysm get block RPC (#11834) 2023-01-13 15:45:17 -08:00
kasey
eb6b811071 Remove ShardingForkVersion/Epoch from config (#11868)
* remove ShardingForkVersion/Epoch from config

* update magic value counting config params

* skip the sharding params, which we disavow

we wanted to remove these upstream and may well do some day but right
now it's too big of a mess to untangle.

Co-authored-by: Kasey Kirkham <kasey@users.noreply.github.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2023-01-13 17:11:33 +00:00
kasey
cf71dbdf97 "Fail" in logs makes FAIL in e2e hard to find (#11867)
Co-authored-by: Kasey Kirkham <kasey@users.noreply.github.com>
2023-01-13 13:03:30 +01:00
kasey
9328e9af1f Capella State Detection (#11862)
* capella state version detection bug fix

* add capella to yaml "template"

* changes for capella state detection

* lint

* don't set capella fork version == altair!!!

* less brittle test for fork schedule rpc

* fix assertions that use wrong field name

* don't test capella/sharding fv against upstream

* hat tip Terence for sanity check

* Update config/params/loader_test.go

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

Co-authored-by: Kasey Kirkham <kasey@users.noreply.github.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
Co-authored-by: terencechain <terence@prysmaticlabs.com>
2023-01-13 04:04:37 +00:00
terencechain
4762fd71de Add historical summaries to beacon api state (#11863)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2023-01-12 17:06:23 +00:00
Nishant Das
769daffb73 Fix State Fetcher (#11820)
* fix fetcher

* kasey's review

Co-authored-by: terencechain <terence@prysmaticlabs.com>
2023-01-12 10:00:12 +00:00
Radosław Kapka
16e6e0de6c Replace FutureForkStub with specific interfaces (#11861)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2023-01-12 00:42:35 +00:00
Nishant Das
396fc3dc7e Fix Waiting For Bandwidth Issue While Syncing (#11853)
* fix bugs

* fix up

* comment

* raul's review

* comment

* finally fix it
2023-01-12 00:07:09 +00:00
terencechain
7fa3ebfaa8 Add historical summaries to state and processing (#11842)
* Add historical summaries to state and processing

* Process historical roots test

* Passing spec tests

* Fix shas and tests

* Fix mainnet spectest sha

* Fix tests

* Update beacon-chain/core/epoch/epoch_processing.go

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

* Update beacon-chain/core/epoch/epoch_processing_test.go

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

* Update proto/prysm/v1alpha1/beacon_state.proto

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

* Update beacon-chain/state/state-native/hasher.go

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

* Radek's feedback

* Getters error

* Dont return

* Fix else

* Fix tests

* Fix test

* Rm white space

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
2023-01-11 22:20:15 +00:00
Patrice Vignola
81b9eceb50 Add Capella support for Validator's REST API ProposeBeaconBlock and GetBeaconBlock endpoints (#11848)
* Add Capella support for Validator's REST API ProposeBeaconBlock and GetBeaconBlock endpoints

* Fix

* Fix

* Add context to capella tests

* Update validator/client/beacon-api/beacon_block_proto_helpers.go

* Update validator/client/beacon-api/beacon_block_proto_helpers.go

* Update validator/client/beacon-api/beacon_block_proto_helpers_test.go

* Update validator/client/beacon-api/beacon_block_proto_helpers_test.go

Co-authored-by: james-prysm <90280386+james-prysm@users.noreply.github.com>
Co-authored-by: Radosław Kapka <radek@prysmaticlabs.com>
Co-authored-by: Radosław Kapka <rkapka@wp.pl>
2023-01-11 16:55:09 +00:00
Radosław Kapka
505ff6ea3d Replay state to current slot in StateBySlot (#11858) 2023-01-11 14:53:06 +01:00
Nishant Das
2b5125c7bc Check If Validator Is In Sync Committee (#11860) 2023-01-11 10:19:31 +00:00
Preston Van Loon
1e3a55c6a6 Refactor bytesutil, add support for go1.20 slice to array conversions (#11838)
* Refactor bytes.go and bytes_test.go to smaller files, introduce go1.17 and go1.20 style of array copy

* rename bytes_go17.go to reflect that it works on any version 1.19 and below

* fix PadTo when len is exactly the size

* Add go1.20 style conversions

* Forgot another int method

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2023-01-10 16:41:01 +00:00
Dhruv Bodani
116f3ac265 Add REST implementation for validator's ProposeAttestation (#11800)
* Add REST implementation for validator's ProposeAttestation

* handle nil attestation

* update propose attestation with context

* fix lint

* add remaining nil testcases

* Update validator/client/beacon-api/propose_attestation_test.go

Co-authored-by: Radosław Kapka <radek@prysmaticlabs.com>

* fix BUILD.bazel

Co-authored-by: Radosław Kapka <radek@prysmaticlabs.com>
Co-authored-by: james-prysm <90280386+james-prysm@users.noreply.github.com>
2023-01-10 16:21:29 +00:00
Jacob Shufro
bbe003720c add custom headers to DomainData requests (#11767)
Co-authored-by: Nishant Das <nishdas93@gmail.com>
2023-01-10 00:20:45 +00:00
Patrice Vignola
e957edcb12 Add REST implementation for Validator's SubmitSignedContributionAndProof (#11812)
* Add REST implementation for Validator's SubscribeCommitteeSubnets

* Add context

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
2023-01-09 22:54:52 +00:00
Dhruv Bodani
684022fa69 Add REST implementation for validator's SubmitSignedAggregateSelectionProof (#11826)
* add REST endpoint for SubmitSignedAggregateSelectionProof

* fix linter action

* update with context

* fix context import

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
2023-01-09 21:18:42 +00:00
Dhruv Bodani
a7a64632b1 fix TestEndToEnd_MinimalConfig_ValidatorRESTApi test (#11856)
Co-authored-by: Radosław Kapka <rkapka@wp.pl>
2023-01-09 21:45:37 +01:00
Dhruv Bodani
c89ab764e3 Add REST implementation for validator's GetSyncMessageBlockRoot (#11824)
* add REST implementation for GetSyncMessageBlockRoot

* improve sync_message_block_root_test.go to handle errors

* include context

* fix unit tests
2023-01-09 19:35:33 +00:00
Manu NALEPA
375a76d6c9 Add REST implementation for SubmitSyncMessage (#11827)
* Add REST implementation for `SubmitSyncMessage`

* Use context

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
2023-01-09 17:05:18 +00:00
terencechain
bad7c6a94e Better reconstruct error msg while EL client is syncing (#11851)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2023-01-09 15:09:45 +00:00
Potuz
bdc3a6ef11 Capella coverage and json structs (#11854)
* Capella coverage and json structs

* use SetupTestConfig
2023-01-09 14:47:40 +00:00
Manu NALEPA
4c9a0bf772 Add REST implementation for SubmitValidatorRegistrations (#11816)
* Add REST implementation for `SubmitValidatorRegistrations`

* Remove unused context

* Use context

Co-authored-by: james-prysm <90280386+james-prysm@users.noreply.github.com>
2023-01-06 19:46:09 +00:00
kasey
1c27b21b5a Prevent pollution between scenario tests (#11850)
Co-authored-by: Kasey Kirkham <kasey@users.noreply.github.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2023-01-06 07:49:42 +00:00
Potuz
c1f00923c1 Implement bls_to_execution_changes beacon endpoint (#11845)
* Initial implementation

* fix withrawal unit tests

* add custom hooks api middleware test

* unit tests for endpoint

* update screwed proto file

* double import

* Raul review

Co-authored-by: james-prysm <90280386+james-prysm@users.noreply.github.com>
2023-01-06 05:17:33 +00:00
Dhruv Bodani
700f5fee8c Add context to beacon API REST implementation (#11847)
* add context to beacon APIs

* add TODO to merge GET and POST methods

* fix linter action

Co-authored-by: kasey <489222+kasey@users.noreply.github.com>
Co-authored-by: james-prysm <90280386+james-prysm@users.noreply.github.com>
2023-01-06 03:32:13 +00:00
Potuz
66b6177ed3 Log forkchoice weights on reorgs (#11849) 2023-01-05 20:06:40 -03:00
Raul Jordan
0b0373f2fd Remove Lock from Checkpoint Cache as LRU is Already Thread-Safe (#11846)
* lru cache in prysm is already thread safe

* rem import
2023-01-05 16:00:11 +00:00
Nishant Das
b481c91453 Shift Multiclient E2E to Post-Submit (#11811)
Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2023-01-05 02:39:28 +00:00
Manu NALEPA
e1408deb40 Add REST implementation for MultipleValidatorStatus (#11786)
* Add REST implementation for `MultipleValidatorStatus`

* Fix PR comments

* Address PR comments

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
Co-authored-by: james-prysm <90280386+james-prysm@users.noreply.github.com>
2023-01-04 23:15:23 +00:00
Potuz
51601716dc Rename proposer_exists (#11844) 2023-01-04 14:09:40 +00:00
terencechain
0e77a89208 Better version checks for future proof (#11825)
* Better version checks for future proof

* Revert changes for blob

* Use if else

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2023-01-04 03:47:20 +00:00
terencechain
6715f10ffc Add canUseBuilder helper method (#11829)
* Add canUseBuilder helper method

* Fix build

* Go fmt

* Check circuit breaker first
2023-01-03 12:46:08 +08:00
terencechain
2906196786 Add test utility helper to generate valid bls-to-exec (#11836)
* Add test util helper to generate bls-to-exec

* Gazelle
2023-01-03 00:34:15 +00:00
Potuz
ff82d9ee8c Add back BLS changes from orphaned blocks (#11822)
* Add back BLS changes from orphaned blocks

* Add full test

* add missing file

* remove duplicate imports

* Update beacon-chain/blockchain/head.go

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
Co-authored-by: terencechain <terence@prysmaticlabs.com>
2023-01-01 18:22:01 +00:00
int88
42450fb24e fix trace name of function ExecuteStateTransitionNoVerifyAnySig (#11828)
Co-authored-by: Radosław Kapka <rkapka@wp.pl>
2022-12-31 12:14:26 +00:00
terencechain
b6060d5a49 Track head slot through head block (#11833)
* Track head slot through head block

* Update beacon-chain/blockchain/head.go

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

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
2022-12-29 22:23:56 +00:00
terencechain
cf6617933d Fix BUILD.bazel for v1alpha1 rpcs (#11830)
* Fix build.bazel for v1alpha1 rpcs

* Revert common_deps
2022-12-28 21:38:28 +00:00
terencechain
4e28192541 Proposer RPC: helpers to get exits and slashings (#11808)
* Proposer RPC: helpers to get exits and slashings

* add test

Co-authored-by: Nishant Das <nishdas93@gmail.com>
2022-12-23 05:50:14 +00:00
Nishant Das
4aa075abac Use Single Log File in E2E (#11810)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2022-12-23 03:43:00 +00:00
kasey
c1563e40bd attempt to fix WaitForTextInFile log corruption (#11819)
* attempt to fix WaitForTextInFile log corruption

* restore Seek, just in case!

* lint

* handle file close error in all cases with a log

Co-authored-by: Kasey Kirkham <kasey@users.noreply.github.com>
2022-12-23 01:08:32 +00:00
terencechain
dac555a57c Allow proposer duties one epoch in advance part 2 (#11818)
Co-authored-by: rkapka <rkapka@wp.pl>
2022-12-22 23:00:36 +01:00
Potuz
4d549f572c Check BLS_TO_EXECUTION_CHANGE as if they were from Capella (#11762)
In the event we receive a BLS_TO_EXECUTION_CHANGE and our head state is
before Capella, verify it's signature with the Capella fork version.

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2022-12-22 14:09:24 -03:00
Patrice Vignola
83f48350b2 Fix a bunch of deepsource warnings (#11814) 2022-12-22 09:20:10 +00:00
kasey
77a9dca9eb Cleaner genesis state population (#11809)
* e2e using dynamic configs; runtime bellatrix setup

* starts from phase0 but fee recipient eval fails

* lower TTD to cross before bellatrix epoch in e2e

* fix debug printf

* fix it

* dynamic ttd and more robust fee_recipient eval

* let multiplication set ttd=0 if bellatrix epoch=0

* refactoring fee recipient test after cognit errors

* lint

* appease deepsource

* deep sourcin

* gazelle

* missed a usage of this when refactoring

* refactoring premine genesis to work for all forks

previous set of functions was a copypasta mess

* gaz post-merge

* gaz

* resolve merge artifact and pr feedback

* back out some unneeded changes

* appease deepsource

* move premine-state next to similar utils

Co-authored-by: Kasey Kirkham <kasey@users.noreply.github.com>
Co-authored-by: nisdas <nishdas93@gmail.com>
2022-12-22 05:38:51 +00:00
Nishant Das
9f1c6b2d18 Fix Multiclient E2E (#11803)
* fix multiclient e2e

* parallelize keystore generation

* fix config startup

* fix GetAggregateAttestation

* regression test

* kasey's review

* fix test

* gaz

* fix tests

* deep source
2022-12-22 02:48:46 +00:00
Radosław Kapka
0c997ede0f Query duties - epoch changes (#11806)
* Allow fetching next epoch attester duties

* better formatting

* fix tests

* use param
2022-12-21 16:28:16 +00:00
Radosław Kapka
2dc56878cd Implement getPoolBLSToExecutionChanges API endpoint (#11801)
* Implement `getPoolBLSToExecutionChanges` API endpoint

* fix

(cherry picked from commit d602c94b7b)

* unify with Capella

* newline
2022-12-21 13:01:04 +00:00
kasey
d916827fb9 E2E from Phase0 or Bellatrix (#11802)
* e2e using dynamic configs; runtime bellatrix setup

* starts from phase0 but fee recipient eval fails

* lower TTD to cross before bellatrix epoch in e2e

* fix debug printf

* fix it

* dynamic ttd and more robust fee_recipient eval

* let multiplication set ttd=0 if bellatrix epoch=0

* refactoring fee recipient test after cognit errors

* lint

* appease deepsource

* deep sourcin

* gazelle

* missed a usage of this when refactoring

Co-authored-by: Kasey Kirkham <kasey@users.noreply.github.com>
Co-authored-by: nisdas <nishdas93@gmail.com>
2022-12-21 04:43:29 +00:00
Ye Ding
e43152102e Identify invalid signature within batch verification (#11582) (#11741)
* Identify invalid signature within batch verification (#11582)

* Fix issues found by linter

* Make deepsource happy

* Add signature description enums

* Make descriptions a mandatory field

* More readable error message of invalid signatures

* Add 'enable-verbose-sig-verification' option

* Fix format

* Move descriptions to package signing

* Add more validation and test cases

* Fix build failure

Co-authored-by: Nishant Das <nishdas93@gmail.com>
2022-12-20 18:41:47 +08:00
Nishant Das
90d5f6097c lock state (#11796) 2022-12-20 15:39:35 +08:00
james-prysm
ce125b763c Improve validator set change event readability and error handling (#11797) 2022-12-19 22:12:09 +01:00
Patrice Vignola
3ff5895548 Add REST implementation for Validator's ProposeExit (#11785)
* Add REST implementation for Validator's GetBeaconBlock

* Move endpoint into constant

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
2022-12-19 12:58:52 +00:00
Patrice Vignola
4eb4cd9756 Add REST implementation for Validator's PrepareBeaconProposer (#11784)
* Add REST implementation for Validator's PrepareBeaconProposer

* Change fee recipients

* Handle error in a better way

* Move endpoint into constant

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
2022-12-19 12:23:54 +00:00
terencechain
81b049ea02 Remove copy for block setters (#11795) 2022-12-19 10:54:25 +00:00
Radosław Kapka
a2fc57cb03 Improve tests for ProduceBlockV2 (#11789)
* Improve tests for `ProduceBlockV2`

* Revert "Auxiliary commit to revert individual files from 31c606198bdc91bac798b7a446d04d5cce86dad7"

This reverts commit d8b264457168f8f5e03d0473288a56606e38ab39.
2022-12-16 20:54:38 +00:00
Radosław Kapka
b63f649d89 Add finalized metadata field to API block fetching (#11788) 2022-12-16 18:21:08 +01:00
Ye Ding
e627d3c6a4 Fix command to fetch latest stable version (#11782) (#11787) 2022-12-16 16:13:54 +00:00
Potuz
856102cba8 Implement bound on expected withdrawals (#11760)
* Implement bound on expected withdrawals

This PR implements https://github.com/ethereum/consensus-specs/pull/3095

* Terence's suggestion

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

* Update spectests

* fix minimal preset

* Clear committee cache during header tests to ensure active validators ain't leaking

* Rm debug log

* Rm bad init

* Update consensus spec sha

* Fix bad tests and remove redundant casting

* Fix build

* MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP typo

Co-authored-by: terencechain <terence@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2022-12-16 06:45:26 +00:00
terencechain
8ff6f7768f Sync committee head state cache for Capella (#11773)
* Handle capella

* Handle capella

* Error

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2022-12-16 00:42:43 +00:00
terencechain
295cc5e4f0 Engine API: new/get_payload for Capella (#11775)
* Engine API: new/get_payload for Capella

* Fix build

* Use switch for payload type check

* Fix bad tests

* Rm redundant arg

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2022-12-16 00:25:22 +00:00
Radosław Kapka
8a2c7e4269 Add finalized metadata field to API responses (#11783)
* in progress

* grpc working

* middleware

* fix tests

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2022-12-16 00:04:40 +00:00
Radosław Kapka
cb02a6897d Update block Beacon APIs to Capella (#11706)
* proto+ssz

* refactor GetBlindedBlockSSZ

(cherry picked from commit 97483c339f99b0d96bd81846a979383ffd2b0cda)

# Conflicts:
#	beacon-chain/rpc/eth/beacon/blocks.go
(cherry picked from commit 9e4e82d2c5)

# Conflicts:
#	beacon-chain/rpc/eth/beacon/blocks.go

* add Capella version

(cherry picked from commit 5d6fd0bbe663e5dd16df5b2e773f68982bbcd24e)
(cherry picked from commit 82f6ddb693)

* support SSZ lol

(cherry picked from commit 52bc2c8d617ac3e1254c493fa053cdce4a1ebd63)
(cherry picked from commit d7d70bc25b)

* update withdrawals proto

* refactor and test GetBlockV2

(cherry picked from commit c1d4eaa79d)

# Conflicts:
#	beacon-chain/rpc/eth/beacon/blocks.go

* refactor and test GetSSZBlockV2

(cherry picked from commit fbc4e73d31)

# Conflicts:
#	beacon-chain/rpc/eth/beacon/blocks.go

* test other functions

(cherry picked from commit 31d4a4cd11)

* move stuff to blinded_blocks.go

(cherry picked from commit 0a9e1658dd)

# Conflicts:
#	beacon-chain/rpc/eth/beacon/blocks.go

* fix migration code

* add Capella to SubmitBlock

* custom hooks

* missing structs

* fix tests

* fix tests

* review

* fix build issues

* replace ioutil with io

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2022-12-15 23:42:07 +00:00
Patrice Vignola
e843cafe7d Add REST implementation for Validator's GetBeaconBlock (#11772)
* WIP

* WIP

* WIP

* Remove unused parameter

* Address PR comments

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
2022-12-15 22:34:05 +00:00
Radosław Kapka
1c5b0596c7 More user-friendly message in ErrUndefinedExecutionEngineError (#11777)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2022-12-15 07:46:17 +00:00
David Theodore
159228b34f SparseMerkleTrie depth fix & regression tests (#11778) 2022-12-15 06:50:12 +00:00
Radosław Kapka
1fbb3f3e51 Reconstruct full Capella block (#11732)
* Merge branch 'reconstruct-capella-block' into capella

(cherry picked from commit b0601580ef)

# Conflicts:
#	beacon-chain/rpc/eth/beacon/blocks.go
#	proto/engine/v1/json_marshal_unmarshal.go

* remove unneeded test

* rename methods

* add doc to interface

* deepsource

(cherry picked from commit 903cab75ee)

# Conflicts:
#	beacon-chain/execution/testing/mock_engine_client.go

* bzl

* fix failing tests

* single ExecutionBlockByHash function

* fix engine mock

* deepsource

* reorder checks

* single execution block type

* update tests

* update doc

* bytes test

* remove toWithdrawalJSON

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2022-12-14 13:42:48 +00:00
Manu NALEPA
9c21809c50 Add REST implementation for ValidatorStatus (#11757)
* Add REST implementation for `ValidatorStatus`

* Fix review comments
2022-12-14 12:58:36 +00:00
terencechain
62ffed7861 Add capella cases for RPC calls (#11759)
* Add capella cases for rpc calls

* Use if else

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2022-12-14 05:08:54 +00:00
Victor
bdf063819c Fixed comments of the template (#11652)
The comments of the template were not inside the braces and appeared when creating a new Issue.

Thanks

Co-authored-by: terencechain <terence@prysmaticlabs.com>
2022-12-14 02:49:19 +00:00
Radosław Kapka
9efc89f993 Correct duties calculation for old slots (#11723)
* initial code

* update proposalDependentRoot

* convert method to function

* decouple tests

Co-authored-by: terencechain <terence@prysmaticlabs.com>
2022-12-14 00:33:30 +00:00
Preston Van Loon
5ed52b1e44 Validator: Add trace span information for AttestationRecord save requests (#11742)
* Add additional span information when saving attestation records

* Remove keymanager.sign span. It's very noisy and not a helpful data point.

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2022-12-14 00:06:32 +00:00
kasey
2e49fdb3d2 Start chain from bellatrix state (#11746)
* WIP trying to start from bellatrix state

* env var to control log path with unique paths

due to flaky test re-run behavior, logs from a failed test run are
overwritten by subsequent retries. This makes it difficult to retrieve
logs after the first failed run. It also takes some squinting through
output to find the location of the log file in the first place. This
flag enables logs to be placed in an arbitrary path. Note that bazel
sandboxing generally will force this path to be in the /tmp tree.

* WIP - grabbing changes from rm-pre-genesis branch

* combine bellatrix state w/ rm-pre-genesis branch

* WIP

* use encoding/detect for genesis state bytes

* WIP more fixes towards start from bellatrix

* remove debug wrapping

* WIP

* multiple bugfixes

* fix fork ordering bug and bellatrix genesis blocks

* send deposits, spam tx to advance, fix miner alloc

* WIP

* WIP mess

* WIP

* Print process ID information for purposes of attaching a debugger

* bugs: genesis body_root and deposit index mismatch

* fix voting period start, skip altair check

* add changes

* make it better

* rm startup FCU, rm logs

* cleanup import grouping&ordering

* restore FCU log, get rid of tmp var

* rm newline

* restore newline

* restore wrapped error

* rm newline

* removing boot node version override

this doesn't seem to matter?

* add issue number to todo comment

* rm commented code

* rm vmdebug geth flag

* unexport values only used with genesis test pkg

and add comments where missing from exported values.

* adding comments to special cases for testnets

* migrate comments from PR to actual code :)

* rm unused test param

* mark e2e spawns exempt from gosec warning

* Fix DeepSource errors in `proposer_bellatrix.go` (#11739)

* Fix DeepSource errors in

* Omit receiver name

* Address PR comments

* Remove unused variable

* Fix more DeepSource errors

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

* Remove `Test_IsExecutionEnabledCapella` (#11752)

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

* Add REST implementation for Validator's `ProposeBeaconBlock` (#11731)

* WIP

* WIP

* WIP

* Add tests

* WIP

* Add more tests

* Address DeepSource errors

* Remove unused param

* Add more tests

* Address PR comments

* Address PR comments

* Fix formatting

* Remove unused parameter

* Fix TestLittleEndianBytesToBigInt

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

* fix validator client (#11755)

* fix validator client

(cherry picked from commit deb138959a)

* Use signed changes in middleware block

Co-authored-by: Potuz <potuz@prysmaticlabs.com>

* API `finalized` metadata field - update protos (#11749)

* API `finalized` metadata field - update protos

* change nums

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

* log breaks unit tests that don't do full arg setup

easiest to just remove it for now

* restore prior behavior of phase0 block for altair

* update unit tests to account for special case

* loosen condition for fork version to match config

we don't know which fork version genesis will start from, so we
shouldn't force it to be a phase0 genesis.

* skip until we can mod configs at runtime

* NewGenesisBlockForState computes state root itself

* rm noisy log

* this log would be noisy in mainnet

* fix format specifier, []byte -> string

* core.Genesis UnmarshalJson has a value receiver :)

* no longer needs to be exported

Co-authored-by: Kasey Kirkham <kasey@users.noreply.github.com>
Co-authored-by: prestonvanloon <preston@prysmaticlabs.com>
Co-authored-by: nisdas <nishdas93@gmail.com>
Co-authored-by: Patrice Vignola <vignola.patrice@gmail.com>
Co-authored-by: Radosław Kapka <rkapka@wp.pl>
Co-authored-by: terencechain <terence@prysmaticlabs.com>
Co-authored-by: Potuz <potuz@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2022-12-14 07:13:49 +08:00
Preston Van Loon
a01d08b857 Add --stamp to release builds (#11768) 2022-12-13 21:33:51 +00:00
Preston Van Loon
fbe0672fc4 state: Improve replay state logs metadata (#11763)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2022-12-13 18:46:51 +00:00
Potuz
a15ec49844 Do not remove attestations twice (#11764) 2022-12-13 14:43:42 -03:00
int88
a268255ab1 fix mismatch of code and comment (#11761) 2022-12-13 15:57:52 +00:00
james-prysm
043079dafe Adding exit codes to cli commands (#11735)
* adding exit codes to cmd

* adding in fatal logs to other cli actions

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
2022-12-13 12:13:33 +00:00
terencechain
3fcdd58872 Add block setters for consensus type (#11751)
* Add block getters

* Rm changes

* Rm changes

* Revert "Rm changes"

This reverts commit 1ae5db79da.

* Fix tests

* Set graffiti right place

* Potuz feedback

* Update consensus-types/blocks/setters.go

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

* Radek feedback

* Fix comments

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
2022-12-13 00:03:36 +00:00
Radosław Kapka
0798092ca8 API finalized metadata field - update protos (#11749)
* API `finalized` metadata field - update protos

* change nums

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2022-12-12 16:59:27 +00:00
Radosław Kapka
fb981d29e8 fix validator client (#11755)
* fix validator client

(cherry picked from commit deb138959a)

* Use signed changes in middleware block

Co-authored-by: Potuz <potuz@prysmaticlabs.com>
2022-12-12 15:49:02 +00:00
Patrice Vignola
fa01ee5eba Add REST implementation for Validator's ProposeBeaconBlock (#11731)
* WIP

* WIP

* WIP

* Add tests

* WIP

* Add more tests

* Address DeepSource errors

* Remove unused param

* Add more tests

* Address PR comments

* Address PR comments

* Fix formatting

* Remove unused parameter

* Fix TestLittleEndianBytesToBigInt

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
2022-12-12 10:39:51 +00:00
terencechain
09619c388f Remove Test_IsExecutionEnabledCapella (#11752)
Co-authored-by: Radosław Kapka <rkapka@wp.pl>
2022-12-11 22:59:12 +00:00
Patrice Vignola
1531313603 Fix DeepSource errors in proposer_bellatrix.go (#11739)
* Fix DeepSource errors in

* Omit receiver name

* Address PR comments

* Remove unused variable

* Fix more DeepSource errors

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
2022-12-10 10:27:07 +00:00
Potuz
babfc66c5b Check BLS changes when requesting from pool (#11718)
* Check BLS changes when requesting from pool

* Terence's suggestions

* Radek's suggestion

Co-authored-by: terencechain <terence@prysmaticlabs.com>
Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2022-12-09 14:41:45 +00:00
terencechain
cb9b5e8f6e Use payload attribute type for engine-API (#11719)
* Add payload attribute type

* Gazelle

* Fix test

* Use new payload attribute type

* Fix test

* Fix test

* Update beacon-chain/execution/engine_client.go

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

* Feedbacks

* Fix suggestion

* Update argument, fix test

* Return emptyAttri instead of nil

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
Co-authored-by: Radosław Kapka <rkapka@wp.pl>
2022-12-08 21:39:45 +00:00
james-prysm
145eb5a8e4 add m1 chip info (#11736) 2022-12-08 15:20:32 -06:00
Preston Van Loon
7510f584cb beacondb: Remove cache look up and lock request from boltdb transaction for state summaries (#11745)
* Remove cache look up from bolt transaction

* remove bogus line, oops

* Remove independent cache lookup entirely and just use HasStateSummary

* Rm newline
2022-12-08 19:32:04 +00:00
Patrice Vignola
dbeb3ee886 Onboard validator's Beacon REST API usage to e2e tests (#11704)
* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* Onboard validator's Beacon REST API usage to e2e tests

* Remove unused variables

* Remove use_beacon_api tags

* Fix DeepSource errors

* Revert unneeded changes

* Revert evaluator changes

* Revert import reordering

* Address PR comments

* Remove all REST API e2e tests except minimal one

* Fix validator pointing to inexisting beacon node port

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
2022-12-08 14:38:56 +00:00
Preston Van Loon
ca2618110f e2e: Print process IDs for debugging. (#11734)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2022-12-08 04:48:16 +00:00
Nishant Das
642c399b9d Add Back Cross Client Option (#11738)
* add changes

* remove env var

* fix
2022-12-07 22:20:35 -06:00
Manu NALEPA
6eee539425 Add REST implementation for Validator's WaitForActivation (Ethereum Protocol Fellowship) (#11671)
* Implement REST `WaitForActivation`

* Activation: Factorize tests

* Fix PR comments

* `missingPubKeys`: Replace map by slice (no need to have a map here)

* Fix typo

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
2022-12-07 19:20:11 +00:00
james-prysm
bd82eb873c Fix to Post Submit E2E (#11733) 2022-12-07 18:19:44 +01:00
Nishant Das
62455b7bcb Fix Lint and Minor Bugs in E2E (#11730) 2022-12-07 05:31:53 +00:00
503 changed files with 26680 additions and 7691 deletions

View File

@@ -37,6 +37,7 @@ build:minimal --@io_bazel_rules_go//go/config:tags=minimal
# Release flags
build:release --compilation_mode=opt
build:release --stamp
# LLVM compiler for building C/C++ dependencies.
build:llvm --define compiler=llvm
@@ -230,9 +231,3 @@ build --modify_execution_info='GoStdlib.*=+no-remote-cache'
# Set bazel gotag
build --define gotags=bazel
# Build the binary with Beacon API calls for the validator
build --flag_alias=use_beacon_api=//validator/client/validator-client-factory:use_beacon_api
build:beacon_api --use_beacon_api
build:beacon_api --define=gotags=use_beacon_api

View File

@@ -16,12 +16,12 @@ Existing issues often contain information about workarounds, resolution, or prog
### Description
<!-- ✍️--> A clear and concise description of the problem or missing capability...
<!-- ✍️ A clear and concise description of the problem or missing capability... -->
### Describe the solution you'd like
<!-- ✍️--> If you have a solution in mind, please describe it.
<!-- ✍️ If you have a solution in mind, please describe it. -->
### Describe alternatives you've considered
<!-- ✍️--> Have you considered any alternative solutions or workarounds?
<!-- ✍️ Have you considered any alternative solutions or workarounds? -->

View File

@@ -188,7 +188,7 @@ filegroup(
url = "https://github.com/eth-clients/slashing-protection-interchange-tests/archive/b8413ca42dc92308019d0d4db52c87e9e125c4e9.tar.gz",
)
consensus_spec_version = "v1.3.0-alpha.1"
consensus_spec_version = "v1.3.0-rc.1"
bls_test_version = "v0.1.1"
@@ -204,7 +204,7 @@ filegroup(
visibility = ["//visibility:public"],
)
""",
sha256 = "b5a65eb5ecef1c4fca82ff29739936fee019e8a529ef392ea5e46aa39f40a0b2",
sha256 = "3d6fadb64674eb64a84fae6c2efa9949231ea91e7cb74ada9214097323e86569",
url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/general.tar.gz" % consensus_spec_version,
)
@@ -220,7 +220,7 @@ filegroup(
visibility = ["//visibility:public"],
)
""",
sha256 = "b381bb0184e69cb17d05fbbe75f48c6aec7726957d073e3a65c26671d5d27d37",
sha256 = "54ffbcab1e77316a280e6f5a64c6ed62351e8f5678e6fa49340e49b9b5575e8e",
url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/minimal.tar.gz" % consensus_spec_version,
)
@@ -236,7 +236,7 @@ filegroup(
visibility = ["//visibility:public"],
)
""",
sha256 = "9466f2a5a2dea039a2deb953f0b5dce5399400028bf3f218ffef03f8ef9c446c",
sha256 = "bb06d30ca533dc97d45f2367916ba9ff1b5af52f08a9d8c33bb7b1a61254094e",
url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/mainnet.tar.gz" % consensus_spec_version,
)
@@ -251,7 +251,7 @@ filegroup(
visibility = ["//visibility:public"],
)
""",
sha256 = "3cc3141651a320a1f5767d15826e85aaa96eb4459d9e1a1d3f5a0cdbc79b8f56",
sha256 = "9d22246c00ec3907ef8dc3ddccdfe6f7153ce46df73deee0a0176fe7e4aa1126",
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

@@ -110,8 +110,7 @@ func stringToUint256(s string) (Uint256, error) {
// sszBytesToUint256 creates a Uint256 from a ssz-style (little-endian byte slice) representation.
func sszBytesToUint256(b []byte) (Uint256, error) {
bi := new(big.Int)
bi.SetBytes(bytesutil.ReverseByteOrder(b))
bi := bytesutil.LittleEndianBytesToBigInt(b)
if !isValidUint256(bi) {
return Uint256{}, errors.Wrapf(errDecodeUint256, "value=%s", b)
}

View File

@@ -64,6 +64,7 @@ go_library(
"//config/params:go_default_library",
"//consensus-types/blocks:go_default_library",
"//consensus-types/interfaces:go_default_library",
"//consensus-types/payload-attribute:go_default_library",
"//consensus-types/primitives:go_default_library",
"//crypto/bls:go_default_library",
"//encoding/bytesutil:go_default_library",

View File

@@ -328,6 +328,11 @@ func (s *Service) IsFinalized(ctx context.Context, root [32]byte) bool {
if s.ForkChoicer().FinalizedCheckpoint().Root == root {
return true
}
// If node exists in our store, then it is not
// finalized.
if s.ForkChoicer().HasNode(root) {
return false
}
return s.cfg.BeaconDB.IsFinalizedBlock(ctx, root)
}

View File

@@ -125,7 +125,10 @@ func TestHeadSlot_CanRetrieve(t *testing.T) {
c := &Service{}
s, err := state_native.InitializeFromProtoPhase0(&ethpb.BeaconState{})
require.NoError(t, err)
c.head = &head{slot: 100, state: s}
b, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlock())
require.NoError(t, err)
b.Block().SetSlot(100)
c.head = &head{block: b, state: s}
assert.Equal(t, types.Slot(100), c.HeadSlot())
}
@@ -328,7 +331,7 @@ func TestService_ChainHeads(t *testing.T) {
st, blkRoot, err = prepareForkchoiceState(ctx, 102, [32]byte{'c'}, [32]byte{'b'}, params.BeaconConfig().ZeroHash, ojc, ofc)
require.NoError(t, err)
require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, st, blkRoot))
st, blkRoot, err = prepareForkchoiceState(ctx, 103, [32]byte{'d'}, [32]byte{}, params.BeaconConfig().ZeroHash, ojc, ofc)
st, blkRoot, err = prepareForkchoiceState(ctx, 103, [32]byte{'d'}, [32]byte{'a'}, params.BeaconConfig().ZeroHash, ojc, ofc)
require.NoError(t, err)
require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, st, blkRoot))
st, blkRoot, err = prepareForkchoiceState(ctx, 104, [32]byte{'e'}, [32]byte{'b'}, params.BeaconConfig().ZeroHash, ojc, ofc)
@@ -412,7 +415,7 @@ func TestService_IsOptimistic(t *testing.T) {
ctx := context.Background()
ojc := &ethpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]}
ofc := &ethpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]}
c := &Service{cfg: &config{ForkChoiceStore: doublylinkedtree.New()}, head: &head{slot: 101, root: [32]byte{'b'}}}
c := &Service{cfg: &config{ForkChoiceStore: doublylinkedtree.New()}, head: &head{root: [32]byte{'b'}}}
st, blkRoot, err := prepareForkchoiceState(ctx, 100, [32]byte{'a'}, [32]byte{}, params.BeaconConfig().ZeroHash, ojc, ofc)
require.NoError(t, err)
require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, st, blkRoot))
@@ -435,7 +438,7 @@ func TestService_IsOptimisticBeforeBellatrix(t *testing.T) {
func TestService_IsOptimisticForRoot(t *testing.T) {
ctx := context.Background()
c := &Service{cfg: &config{ForkChoiceStore: doublylinkedtree.New()}, head: &head{slot: 101, root: [32]byte{'b'}}}
c := &Service{cfg: &config{ForkChoiceStore: doublylinkedtree.New()}, head: &head{root: [32]byte{'b'}}}
ojc := &ethpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]}
ofc := &ethpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]}
st, blkRoot, err := prepareForkchoiceState(ctx, 100, [32]byte{'a'}, [32]byte{}, params.BeaconConfig().ZeroHash, ojc, ofc)
@@ -453,7 +456,7 @@ func TestService_IsOptimisticForRoot(t *testing.T) {
func TestService_IsOptimisticForRoot_DB(t *testing.T) {
beaconDB := testDB.SetupDB(t)
ctx := context.Background()
c := &Service{cfg: &config{BeaconDB: beaconDB, ForkChoiceStore: doublylinkedtree.New()}, head: &head{slot: 101, root: [32]byte{'b'}}}
c := &Service{cfg: &config{BeaconDB: beaconDB, ForkChoiceStore: doublylinkedtree.New()}, head: &head{root: [32]byte{'b'}}}
c.head = &head{root: params.BeaconConfig().ZeroHash}
b := util.NewBeaconBlock()
b.Block.Slot = 10
@@ -511,7 +514,7 @@ func TestService_IsOptimisticForRoot_DB(t *testing.T) {
func TestService_IsOptimisticForRoot_DB_non_canonical(t *testing.T) {
beaconDB := testDB.SetupDB(t)
ctx := context.Background()
c := &Service{cfg: &config{BeaconDB: beaconDB, ForkChoiceStore: doublylinkedtree.New()}, head: &head{slot: 101, root: [32]byte{'b'}}}
c := &Service{cfg: &config{BeaconDB: beaconDB, ForkChoiceStore: doublylinkedtree.New()}, head: &head{root: [32]byte{'b'}}}
c.head = &head{root: params.BeaconConfig().ZeroHash}
b := util.NewBeaconBlock()
b.Block.Slot = 10

View File

@@ -8,7 +8,7 @@ var (
// ErrInvalidBlockHashPayloadStatus is returned when the payload has invalid block hash.
ErrInvalidBlockHashPayloadStatus = invalidBlock{error: errors.New("received an INVALID_BLOCK_HASH payload from execution engine")}
// ErrUndefinedExecutionEngineError is returned when the execution engine returns an error that is not defined
ErrUndefinedExecutionEngineError = errors.New("received an undefined ee error")
ErrUndefinedExecutionEngineError = errors.New("received an undefined execution engine error")
// errNilFinalizedInStore is returned when a nil finalized checkpt is returned from store.
errNilFinalizedInStore = errors.New("nil finalized checkpoint returned from store")
// errNilFinalizedCheckpoint is returned when a nil finalized checkpt is returned from a state.
@@ -19,8 +19,6 @@ var (
errInvalidNilSummary = errors.New("nil summary returned from the DB")
// errWrongBlockCount is returned when the wrong number of blocks or block roots is used
errWrongBlockCount = errors.New("wrong number of blocks or block roots")
// block is not a valid optimistic candidate block
errNotOptimisticCandidate = errors.New("block is not suitable for optimistic sync")
// errBlockNotFoundInCacheOrDB is returned when a block is not found in the cache or DB.
errBlockNotFoundInCacheOrDB = errors.New("block not found in cache or db")
// errNilStateFromStategen is returned when a nil state is returned from the state generator.

View File

@@ -15,9 +15,11 @@ import (
"github.com/prysmaticlabs/prysm/v3/config/params"
consensusblocks "github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces"
payloadattribute "github.com/prysmaticlabs/prysm/v3/consensus-types/payload-attribute"
types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
"github.com/prysmaticlabs/prysm/v3/runtime/version"
"github.com/prysmaticlabs/prysm/v3/time/slots"
"github.com/sirupsen/logrus"
"go.opencensus.io/trace"
@@ -67,10 +69,7 @@ func (s *Service) notifyForkchoiceUpdate(ctx context.Context, arg *notifyForkcho
}
nextSlot := s.CurrentSlot() + 1 // Cache payload ID for next slot proposer.
hasAttr, attr, proposerId, err := s.getPayloadAttribute(ctx, arg.headState, nextSlot)
if err != nil {
log.WithError(err).Error("Could not get head payload attribute")
}
hasAttr, attr, proposerId := s.getPayloadAttribute(ctx, arg.headState, nextSlot)
payloadID, lastValidHash, err := s.cfg.ExecutionEngineCaller.ForkchoiceUpdated(ctx, fcs, attr)
if err != nil {
@@ -149,7 +148,8 @@ func (s *Service) notifyForkchoiceUpdate(ctx context.Context, arg *notifyForkcho
log.WithError(err).Error("Could not set head root to valid")
return nil, nil
}
if hasAttr && payloadID != nil { // If the forkchoice update call has an attribute, update the proposer payload ID cache.
// If the forkchoice update call has an attribute, update the proposer payload ID cache.
if hasAttr && payloadID != nil {
var pId [8]byte
copy(pId[:], payloadID[:])
s.cfg.ProposerSlotIndexCache.SetProposerAndPayloadIDs(nextSlot, proposerId, pId, arg.headRoot)
@@ -250,22 +250,25 @@ func (s *Service) notifyNewPayload(ctx context.Context, postStateVersion int,
// getPayloadAttributes returns the payload attributes for the given state and slot.
// The attribute is required to initiate a payload build process in the context of an `engine_forkchoiceUpdated` call.
func (s *Service) getPayloadAttribute(ctx context.Context, st state.BeaconState, slot types.Slot) (bool, *enginev1.PayloadAttributes, types.ValidatorIndex, error) {
func (s *Service) getPayloadAttribute(ctx context.Context, st state.BeaconState, slot types.Slot) (bool, payloadattribute.Attributer, types.ValidatorIndex) {
emptyAttri := payloadattribute.EmptyWithVersion(st.Version())
// Root is `[32]byte{}` since we are retrieving proposer ID of a given slot. During insertion at assignment the root was not known.
proposerID, _, ok := s.cfg.ProposerSlotIndexCache.GetProposerPayloadIDs(slot, [32]byte{} /* root */)
if !ok { // There's no need to build attribute if there is no proposer for slot.
return false, nil, 0, nil
return false, emptyAttri, 0
}
// Get previous randao.
st = st.Copy()
st, err := transition.ProcessSlotsIfPossible(ctx, st, slot)
if err != nil {
return false, nil, 0, err
log.WithError(err).Error("Could not process slots to get payload attribute")
return false, emptyAttri, 0
}
prevRando, err := helpers.RandaoMix(st, time.CurrentEpoch(st))
if err != nil {
return false, nil, 0, nil
log.WithError(err).Error("Could not get randao mix to get payload attribute")
return false, emptyAttri, 0
}
// Get fee recipient.
@@ -283,7 +286,8 @@ func (s *Service) getPayloadAttribute(ctx context.Context, st state.BeaconState,
"Please refer to our documentation for instructions")
}
case err != nil:
return false, nil, 0, errors.Wrap(err, "could not get fee recipient in db")
log.WithError(err).Error("Could not get fee recipient to get payload attribute")
return false, emptyAttri, 0
default:
feeRecipient = recipient
}
@@ -291,14 +295,44 @@ func (s *Service) getPayloadAttribute(ctx context.Context, st state.BeaconState,
// Get timestamp.
t, err := slots.ToTime(uint64(s.genesisTime.Unix()), slot)
if err != nil {
return false, nil, 0, err
log.WithError(err).Error("Could not get timestamp to get payload attribute")
return false, emptyAttri, 0
}
attr := &enginev1.PayloadAttributes{
Timestamp: uint64(t.Unix()),
PrevRandao: prevRando,
SuggestedFeeRecipient: feeRecipient.Bytes(),
var attr payloadattribute.Attributer
switch st.Version() {
case version.Capella:
withdrawals, err := st.ExpectedWithdrawals()
if err != nil {
log.WithError(err).Error("Could not get expected withdrawals to get payload attribute")
return false, emptyAttri, 0
}
attr, err = payloadattribute.New(&enginev1.PayloadAttributesV2{
Timestamp: uint64(t.Unix()),
PrevRandao: prevRando,
SuggestedFeeRecipient: feeRecipient.Bytes(),
Withdrawals: withdrawals,
})
if err != nil {
log.WithError(err).Error("Could not get payload attribute")
return false, emptyAttri, 0
}
case version.Bellatrix:
attr, err = payloadattribute.New(&enginev1.PayloadAttributes{
Timestamp: uint64(t.Unix()),
PrevRandao: prevRando,
SuggestedFeeRecipient: feeRecipient.Bytes(),
})
if err != nil {
log.WithError(err).Error("Could not get payload attribute")
return false, emptyAttri, 0
}
default:
log.WithField("version", st.Version()).Error("Could not get payload attribute due to unknown state version")
return false, emptyAttri, 0
}
return true, attr, proposerID, nil
return true, attr, proposerID
}
// removeInvalidBlockAndState removes the invalid block and its corresponding state from the cache and DB.

View File

@@ -792,8 +792,8 @@ func Test_GetPayloadAttribute(t *testing.T) {
// Cache miss
service, err := NewService(ctx, opts...)
require.NoError(t, err)
hasPayload, _, vId, err := service.getPayloadAttribute(ctx, nil, 0)
require.NoError(t, err)
st, _ := util.DeterministicGenesisStateBellatrix(t, 1)
hasPayload, _, vId := service.getPayloadAttribute(ctx, st, 0)
require.Equal(t, false, hasPayload)
require.Equal(t, types.ValidatorIndex(0), vId)
@@ -801,24 +801,65 @@ func Test_GetPayloadAttribute(t *testing.T) {
suggestedVid := types.ValidatorIndex(1)
slot := types.Slot(1)
service.cfg.ProposerSlotIndexCache.SetProposerAndPayloadIDs(slot, suggestedVid, [8]byte{}, [32]byte{})
st, _ := util.DeterministicGenesisState(t, 1)
hook := logTest.NewGlobal()
hasPayload, attr, vId, err := service.getPayloadAttribute(ctx, st, slot)
require.NoError(t, err)
hasPayload, attr, vId := service.getPayloadAttribute(ctx, st, slot)
require.Equal(t, true, hasPayload)
require.Equal(t, suggestedVid, vId)
require.Equal(t, params.BeaconConfig().EthBurnAddressHex, common.BytesToAddress(attr.SuggestedFeeRecipient).String())
require.Equal(t, params.BeaconConfig().EthBurnAddressHex, common.BytesToAddress(attr.SuggestedFeeRecipient()).String())
require.LogsContain(t, hook, "Fee recipient is currently using the burn address")
// Cache hit, advance state, has fee recipient
suggestedAddr := common.HexToAddress("123")
require.NoError(t, service.cfg.BeaconDB.SaveFeeRecipientsByValidatorIDs(ctx, []types.ValidatorIndex{suggestedVid}, []common.Address{suggestedAddr}))
service.cfg.ProposerSlotIndexCache.SetProposerAndPayloadIDs(slot, suggestedVid, [8]byte{}, [32]byte{})
hasPayload, attr, vId, err = service.getPayloadAttribute(ctx, st, slot)
require.NoError(t, err)
hasPayload, attr, vId = service.getPayloadAttribute(ctx, st, slot)
require.Equal(t, true, hasPayload)
require.Equal(t, suggestedVid, vId)
require.Equal(t, suggestedAddr, common.BytesToAddress(attr.SuggestedFeeRecipient))
require.Equal(t, suggestedAddr, common.BytesToAddress(attr.SuggestedFeeRecipient()))
}
func Test_GetPayloadAttributeV2(t *testing.T) {
ctx := context.Background()
beaconDB := testDB.SetupDB(t)
opts := []Option{
WithDatabase(beaconDB),
WithStateGen(stategen.New(beaconDB, doublylinkedtree.New())),
WithProposerIdsCache(cache.NewProposerPayloadIDsCache()),
}
// Cache miss
service, err := NewService(ctx, opts...)
require.NoError(t, err)
st, _ := util.DeterministicGenesisStateCapella(t, 1)
hasPayload, _, vId := service.getPayloadAttribute(ctx, st, 0)
require.Equal(t, false, hasPayload)
require.Equal(t, types.ValidatorIndex(0), vId)
// Cache hit, advance state, no fee recipient
suggestedVid := types.ValidatorIndex(1)
slot := types.Slot(1)
service.cfg.ProposerSlotIndexCache.SetProposerAndPayloadIDs(slot, suggestedVid, [8]byte{}, [32]byte{})
hook := logTest.NewGlobal()
hasPayload, attr, vId := service.getPayloadAttribute(ctx, st, slot)
require.Equal(t, true, hasPayload)
require.Equal(t, suggestedVid, vId)
require.Equal(t, params.BeaconConfig().EthBurnAddressHex, common.BytesToAddress(attr.SuggestedFeeRecipient()).String())
require.LogsContain(t, hook, "Fee recipient is currently using the burn address")
a, err := attr.Withdrawals()
require.NoError(t, err)
require.Equal(t, 0, len(a))
// Cache hit, advance state, has fee recipient
suggestedAddr := common.HexToAddress("123")
require.NoError(t, service.cfg.BeaconDB.SaveFeeRecipientsByValidatorIDs(ctx, []types.ValidatorIndex{suggestedVid}, []common.Address{suggestedAddr}))
service.cfg.ProposerSlotIndexCache.SetProposerAndPayloadIDs(slot, suggestedVid, [8]byte{}, [32]byte{})
hasPayload, attr, vId = service.getPayloadAttribute(ctx, st, slot)
require.Equal(t, true, hasPayload)
require.Equal(t, suggestedVid, vId)
require.Equal(t, suggestedAddr, common.BytesToAddress(attr.SuggestedFeeRecipient()))
a, err = attr.Withdrawals()
require.NoError(t, err)
require.Equal(t, 0, len(a))
}
func Test_UpdateLastValidatedCheckpoint(t *testing.T) {
@@ -836,7 +877,7 @@ func Test_UpdateLastValidatedCheckpoint(t *testing.T) {
}
service, err := NewService(ctx, opts...)
require.NoError(t, err)
genesisStateRoot := [32]byte{}
var genesisStateRoot [32]byte
genesisBlk := blocks.NewGenesisBlock(genesisStateRoot[:])
util.SaveBlock(t, ctx, beaconDB, genesisBlk)
genesisRoot, err := genesisBlk.Block.HashTreeRoot()

View File

@@ -19,6 +19,7 @@ import (
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/v3/math"
ethpbv1 "github.com/prysmaticlabs/prysm/v3/proto/eth/v1"
"github.com/prysmaticlabs/prysm/v3/runtime/version"
"github.com/prysmaticlabs/prysm/v3/time/slots"
"github.com/sirupsen/logrus"
"go.opencensus.io/trace"
@@ -51,7 +52,6 @@ func (s *Service) UpdateAndSaveHeadWithBalances(ctx context.Context) error {
// This defines the current chain service's view of head.
type head struct {
slot types.Slot // current head slot.
root [32]byte // current head root.
block interfaces.SignedBeaconBlock // current head block.
state state.BeaconState // current head state.
@@ -109,11 +109,21 @@ func (s *Service) saveHead(ctx context.Context, newHeadRoot [32]byte, headBlock
}
dis := headSlot + newHeadSlot - 2*forkSlot
dep := math.Max(uint64(headSlot-forkSlot), uint64(newHeadSlot-forkSlot))
oldWeight, err := s.ForkChoicer().Weight(oldHeadRoot)
if err != nil {
log.WithField("root", fmt.Sprintf("%#x", oldHeadRoot)).Warn("could not determine node weight")
}
newWeight, err := s.ForkChoicer().Weight(newHeadRoot)
if err != nil {
log.WithField("root", fmt.Sprintf("%#x", newHeadRoot)).Warn("could not determine node weight")
}
log.WithFields(logrus.Fields{
"newSlot": fmt.Sprintf("%d", newHeadSlot),
"newRoot": fmt.Sprintf("%#x", newHeadRoot),
"newWeight": newWeight,
"oldSlot": fmt.Sprintf("%d", headSlot),
"oldRoot": fmt.Sprintf("%#x", oldHeadRoot),
"oldWeight": oldWeight,
"commonAncestorRoot": fmt.Sprintf("%#x", commonRoot),
"distance": dis,
"depth": dep,
@@ -139,7 +149,7 @@ func (s *Service) saveHead(ctx context.Context, newHeadRoot [32]byte, headBlock
},
})
if err := s.saveOrphanedAtts(ctx, oldHeadRoot, newHeadRoot); err != nil {
if err := s.saveOrphanedOperations(ctx, oldHeadRoot, newHeadRoot); err != nil {
return err
}
reorgCount.Inc()
@@ -202,7 +212,6 @@ func (s *Service) setHead(root [32]byte, block interfaces.SignedBeaconBlock, sta
return err
}
s.head = &head{
slot: block.Block().Slot(),
root: root,
block: bCp,
state: state.Copy(),
@@ -223,7 +232,6 @@ func (s *Service) setHeadInitialSync(root [32]byte, block interfaces.SignedBeaco
return err
}
s.head = &head{
slot: block.Block().Slot(),
root: root,
block: bCp,
state: state,
@@ -234,7 +242,10 @@ func (s *Service) setHeadInitialSync(root [32]byte, block interfaces.SignedBeaco
// This returns the head slot.
// This is a lock free version.
func (s *Service) headSlot() types.Slot {
return s.head.slot
if s.head == nil || s.head.block == nil || s.head.block.Block() == nil {
return 0
}
return s.head.block.Block().Slot()
}
// This returns the head root.
@@ -347,9 +358,9 @@ func (s *Service) notifyNewHeadEvent(
return nil
}
// This saves the attestations between `orphanedRoot` and the common ancestor root that is derived using `newHeadRoot`.
// This saves the Attestations and BLSToExecChanges between `orphanedRoot` and the common ancestor root that is derived using `newHeadRoot`.
// It also filters out the attestations that is one epoch older as a defense so invalid attestations don't flow into the attestation pool.
func (s *Service) saveOrphanedAtts(ctx context.Context, orphanedRoot [32]byte, newHeadRoot [32]byte) error {
func (s *Service) saveOrphanedOperations(ctx context.Context, orphanedRoot [32]byte, newHeadRoot [32]byte) error {
commonAncestorRoot, _, err := s.ForkChoicer().CommonAncestor(ctx, newHeadRoot, orphanedRoot)
switch {
// Exit early if there's no common ancestor and root doesn't exist, there would be nothing to save.
@@ -388,6 +399,15 @@ func (s *Service) saveOrphanedAtts(ctx context.Context, orphanedRoot [32]byte, n
}
saveOrphanedAttCount.Inc()
}
if orphanedBlk.Version() >= version.Capella {
changes, err := orphanedBlk.Block().Body().BLSToExecutionChanges()
if err != nil {
return errors.Wrap(err, "could not get BLSToExecutionChanges")
}
for _, c := range changes {
s.cfg.BLSToExecPool.InsertBLSToExecChange(c)
}
}
parentRoot := orphanedBlk.Block().ParentRoot()
orphanedRoot = bytesutil.ToBytes32(parentRoot[:])
}

View File

@@ -10,6 +10,7 @@ import (
mock "github.com/prysmaticlabs/prysm/v3/beacon-chain/blockchain/testing"
testDB "github.com/prysmaticlabs/prysm/v3/beacon-chain/db/testing"
doublylinkedtree "github.com/prysmaticlabs/prysm/v3/beacon-chain/forkchoice/doubly-linked-tree"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/blstoexec"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state/stategen"
"github.com/prysmaticlabs/prysm/v3/config/features"
"github.com/prysmaticlabs/prysm/v3/config/params"
@@ -30,7 +31,7 @@ func TestSaveHead_Same(t *testing.T) {
service := setupBeaconChain(t, beaconDB)
r := [32]byte{'A'}
service.head = &head{slot: 0, root: r}
service.head = &head{root: r}
b, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlock())
require.NoError(t, err)
st, _ := util.DeterministicGenesisState(t, 1)
@@ -53,7 +54,6 @@ func TestSaveHead_Different(t *testing.T) {
require.NoError(t, err)
require.NoError(t, service.cfg.ForkChoiceStore.InsertNode(ctx, state, blkRoot))
service.head = &head{
slot: 0,
root: oldRoot,
block: oldBlock,
}
@@ -107,7 +107,6 @@ func TestSaveHead_Different_Reorg(t *testing.T) {
require.NoError(t, err)
require.NoError(t, service.cfg.ForkChoiceStore.InsertNode(ctx, state, blkRoot))
service.head = &head{
slot: 0,
root: oldRoot,
block: oldBlock,
}
@@ -285,7 +284,7 @@ func TestSaveOrphanedAtts(t *testing.T) {
util.SaveBlock(t, ctx, beaconDB, blk)
}
require.NoError(t, service.saveOrphanedAtts(ctx, r3, r4))
require.NoError(t, service.saveOrphanedOperations(ctx, r3, r4))
require.Equal(t, 3, service.cfg.AttPool.AggregatedAttestationCount())
wantAtts := []*ethpb.Attestation{
blk3.Block.Body.Attestations[0],
@@ -303,31 +302,37 @@ func TestSaveOrphanedAtts_CanFilter(t *testing.T) {
ctx := context.Background()
beaconDB := testDB.SetupDB(t)
service := setupBeaconChain(t, beaconDB)
service.cfg.BLSToExecPool = blstoexec.NewPool()
service.genesisTime = time.Now().Add(time.Duration(-1*int64(params.BeaconConfig().SlotsPerEpoch+2)*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second)
// Chain setup
// 0 -- 1 -- 2
// \-4
st, keys := util.DeterministicGenesisState(t, 64)
blkG, err := util.GenerateFullBlock(st, keys, util.DefaultBlockGenConfig(), 0)
st, keys := util.DeterministicGenesisStateCapella(t, 64)
blkConfig := util.DefaultBlockGenConfig()
blkConfig.NumBLSChanges = 5
blkG, err := util.GenerateFullBlockCapella(st, keys, blkConfig, 1)
assert.NoError(t, err)
util.SaveBlock(t, ctx, service.cfg.BeaconDB, blkG)
rG, err := blkG.Block.HashTreeRoot()
require.NoError(t, err)
blk1, err := util.GenerateFullBlock(st, keys, util.DefaultBlockGenConfig(), 1)
blkConfig.NumBLSChanges = 10
blk1, err := util.GenerateFullBlockCapella(st, keys, blkConfig, 2)
assert.NoError(t, err)
blk1.Block.ParentRoot = rG[:]
r1, err := blk1.Block.HashTreeRoot()
require.NoError(t, err)
blk2, err := util.GenerateFullBlock(st, keys, util.DefaultBlockGenConfig(), 2)
blkConfig.NumBLSChanges = 15
blk2, err := util.GenerateFullBlockCapella(st, keys, blkConfig, 3)
assert.NoError(t, err)
blk2.Block.ParentRoot = r1[:]
r2, err := blk2.Block.HashTreeRoot()
require.NoError(t, err)
blk4 := util.NewBeaconBlock()
blk4 := util.NewBeaconBlockCapella()
blkConfig.NumBLSChanges = 0
blk4.Block.Slot = 4
blk4.Block.ParentRoot = rG[:]
r4, err := blk4.Block.HashTreeRoot()
@@ -335,7 +340,7 @@ func TestSaveOrphanedAtts_CanFilter(t *testing.T) {
ojc := &ethpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]}
ofc := &ethpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]}
for _, blk := range []*ethpb.SignedBeaconBlock{blkG, blk1, blk2, blk4} {
for _, blk := range []*ethpb.SignedBeaconBlockCapella{blkG, blk1, blk2, blk4} {
r, err := blk.Block.HashTreeRoot()
require.NoError(t, err)
state, blkRoot, err := prepareForkchoiceState(ctx, blk.Block.Slot, r, bytesutil.ToBytes32(blk.Block.ParentRoot), [32]byte{}, ojc, ofc)
@@ -344,8 +349,11 @@ func TestSaveOrphanedAtts_CanFilter(t *testing.T) {
util.SaveBlock(t, ctx, beaconDB, blk)
}
require.NoError(t, service.saveOrphanedAtts(ctx, r2, r4))
require.Equal(t, 0, service.cfg.AttPool.AggregatedAttestationCount())
require.NoError(t, service.saveOrphanedOperations(ctx, r2, r4))
require.Equal(t, 1, service.cfg.AttPool.AggregatedAttestationCount())
pending, err := service.cfg.BLSToExecPool.PendingBLSToExecChanges()
require.NoError(t, err)
require.Equal(t, 15, len(pending))
}
func TestSaveOrphanedAtts_DoublyLinkedTrie(t *testing.T) {
@@ -404,7 +412,7 @@ func TestSaveOrphanedAtts_DoublyLinkedTrie(t *testing.T) {
util.SaveBlock(t, ctx, beaconDB, blk)
}
require.NoError(t, service.saveOrphanedAtts(ctx, r3, r4))
require.NoError(t, service.saveOrphanedOperations(ctx, r3, r4))
require.Equal(t, 3, service.cfg.AttPool.AggregatedAttestationCount())
wantAtts := []*ethpb.Attestation{
blk3.Block.Body.Attestations[0],
@@ -468,7 +476,7 @@ func TestSaveOrphanedAtts_CanFilter_DoublyLinkedTrie(t *testing.T) {
util.SaveBlock(t, ctx, beaconDB, blk)
}
require.NoError(t, service.saveOrphanedAtts(ctx, r2, r4))
require.NoError(t, service.saveOrphanedOperations(ctx, r2, r4))
require.Equal(t, 0, service.cfg.AttPool.AggregatedAttestationCount())
}

View File

@@ -38,14 +38,14 @@ func logStateTransitionData(b interfaces.BeaconBlock) error {
if len(b.Body().VoluntaryExits()) > 0 {
log = log.WithField("voluntaryExits", len(b.Body().VoluntaryExits()))
}
if b.Version() == version.Altair || b.Version() == version.Bellatrix {
if b.Version() >= version.Altair {
agg, err := b.Body().SyncAggregate()
if err != nil {
return err
}
log = log.WithField("syncBitsCount", agg.SyncCommitteeBits.Count())
}
if b.Version() == version.Bellatrix {
if b.Version() >= version.Bellatrix {
p, err := b.Body().Execution()
if err != nil {
return err
@@ -87,6 +87,7 @@ func logBlockSyncStatus(block interfaces.BeaconBlock, blockRoot [32]byte, justif
"version": version.String(block.Version()),
"sinceSlotStartTime": prysmTime.Now().Sub(startTime),
"chainServiceProcessedTime": prysmTime.Now().Sub(receivedTime),
"deposits": len(block.Body().Deposits()),
}).Debug("Synced new block")
} else {
log.WithFields(logrus.Fields{

View File

@@ -317,9 +317,8 @@ func reportEpochMetrics(ctx context.Context, postState, headState state.BeaconSt
var b *precompute.Balance
var v []*precompute.Validator
var err error
switch headState.Version() {
case version.Phase0:
// Validator participation should be viewed on the canonical chain.
if headState.Version() == version.Phase0 {
v, b, err = precompute.New(ctx, headState)
if err != nil {
return err
@@ -328,7 +327,7 @@ func reportEpochMetrics(ctx context.Context, postState, headState state.BeaconSt
if err != nil {
return err
}
case version.Altair, version.Bellatrix, version.Capella:
} else if headState.Version() >= version.Altair {
v, b, err = altair.InitializePrecomputeValidators(ctx, headState)
if err != nil {
return err
@@ -337,9 +336,10 @@ func reportEpochMetrics(ctx context.Context, postState, headState state.BeaconSt
if err != nil {
return err
}
default:
} else {
return errors.Errorf("invalid state type provided: %T", headState.ToProtoUnsafe())
}
prevEpochActiveBalances.Set(float64(b.ActivePrevEpoch))
prevEpochSourceBalances.Set(float64(b.PrevEpochAttested))
prevEpochTargetBalances.Set(float64(b.PrevEpochTargetAttested))

View File

@@ -15,6 +15,7 @@ import (
"github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces"
types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/v3/runtime/version"
"github.com/prysmaticlabs/prysm/v3/time/slots"
"github.com/sirupsen/logrus"
)
@@ -92,6 +93,7 @@ func (s *Service) getBlkParentHashAndTD(ctx context.Context, blkHash []byte) ([]
if blk == nil {
return nil, nil, errors.New("pow block is nil")
}
blk.Version = version.Bellatrix
blkTDBig, err := hexutil.DecodeBig(blk.TotalDifficulty)
if err != nil {
return nil, nil, errors.Wrap(err, "could not decode merge block total difficulty")

View File

@@ -337,11 +337,7 @@ func (s *Service) onBlockBatch(ctx context.Context, blks []interfaces.SignedBeac
jCheckpoints := make([]*ethpb.Checkpoint, len(blks))
fCheckpoints := make([]*ethpb.Checkpoint, len(blks))
sigSet := &bls.SignatureBatch{
Signatures: [][]byte{},
PublicKeys: []bls.PublicKey{},
Messages: [][32]byte{},
}
sigSet := bls.NewSet()
type versionAndHeader struct {
version int
header interfaces.ExecutionData
@@ -381,7 +377,13 @@ func (s *Service) onBlockBatch(ctx context.Context, blks []interfaces.SignedBeac
}
sigSet.Join(set)
}
verify, err := sigSet.Verify()
var verify bool
if features.Get().EnableVerboseSigVerification {
verify, err = sigSet.VerifyVerbosely()
} else {
verify, err = sigSet.Verify()
}
if err != nil {
return invalidBlock{error: err}
}
@@ -529,11 +531,7 @@ func (s *Service) insertBlockToForkchoiceStore(ctx context.Context, blk interfac
}
}
if err := s.cfg.ForkChoiceStore.InsertNode(ctx, st, root); err != nil {
return err
}
return nil
return s.cfg.ForkChoiceStore.InsertNode(ctx, st, root)
}
// This feeds in the attestations included in the block to fork choice store. It's allows fork choice store

View File

@@ -6,7 +6,6 @@ import (
"fmt"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/helpers"
doublylinkedtree "github.com/prysmaticlabs/prysm/v3/beacon-chain/forkchoice/doubly-linked-tree"
forkchoicetypes "github.com/prysmaticlabs/prysm/v3/beacon-chain/forkchoice/types"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state"
@@ -317,23 +316,6 @@ func (s *Service) insertFinalizedDeposits(ctx context.Context, fRoot [32]byte) e
return nil
}
// The deletes input attestations from the attestation pool, so proposers don't include them in a block for the future.
func (s *Service) deletePoolAtts(atts []*ethpb.Attestation) error {
for _, att := range atts {
if helpers.IsAggregated(att) {
if err := s.cfg.AttPool.DeleteAggregatedAttestation(att); err != nil {
return err
}
} else {
if err := s.cfg.AttPool.DeleteUnaggregatedAttestation(att); err != nil {
return err
}
}
}
return nil
}
// This ensures that the input root defaults to using genesis root instead of zero hashes. This is needed for handling
// fork choice justification routine.
func (s *Service) ensureRootNotZeros(root [32]byte) [32]byte {

View File

@@ -59,7 +59,7 @@ func TestStore_OnBlock(t *testing.T) {
service, err := NewService(ctx, opts...)
require.NoError(t, err)
genesisStateRoot := [32]byte{}
var genesisStateRoot [32]byte
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
util.SaveBlock(t, ctx, beaconDB, genesis)
validGenesisRoot, err := genesis.Block.HashTreeRoot()
@@ -362,7 +362,7 @@ func TestFillForkChoiceMissingBlocks_FilterFinalized(t *testing.T) {
require.NoError(t, err)
service.cfg.ForkChoiceStore = doublylinkedtree.New()
genesisStateRoot := [32]byte{}
var genesisStateRoot [32]byte
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
util.SaveBlock(t, ctx, beaconDB, genesis)
validGenesisRoot, err := genesis.Block.HashTreeRoot()
@@ -421,7 +421,7 @@ func TestFillForkChoiceMissingBlocks_FinalizedSibling(t *testing.T) {
require.NoError(t, err)
service.cfg.ForkChoiceStore = doublylinkedtree.New()
genesisStateRoot := [32]byte{}
var genesisStateRoot [32]byte
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
util.SaveBlock(t, ctx, beaconDB, genesis)
validGenesisRoot, err := genesis.Block.HashTreeRoot()
@@ -1004,7 +1004,7 @@ func TestInsertFinalizedDeposits(t *testing.T) {
assert.NoError(t, gs.SetEth1Data(&ethpb.Eth1Data{DepositCount: 10}))
assert.NoError(t, gs.SetEth1DepositIndex(8))
assert.NoError(t, service.cfg.StateGen.SaveState(ctx, [32]byte{'m', 'o', 'c', 'k'}, gs))
zeroSig := [96]byte{}
var zeroSig [96]byte
for i := uint64(0); i < uint64(4*params.BeaconConfig().SlotsPerEpoch); i++ {
root := []byte(strconv.Itoa(int(i)))
assert.NoError(t, depositCache.InsertDeposit(ctx, &ethpb.Deposit{Data: &ethpb.Deposit_Data{
@@ -1042,7 +1042,7 @@ func TestInsertFinalizedDeposits_MultipleFinalizedRoutines(t *testing.T) {
assert.NoError(t, gs2.SetEth1Data(&ethpb.Eth1Data{DepositCount: 15}))
assert.NoError(t, gs2.SetEth1DepositIndex(13))
assert.NoError(t, service.cfg.StateGen.SaveState(ctx, [32]byte{'m', 'o', 'c', 'k', '2'}, gs2))
zeroSig := [96]byte{}
var zeroSig [96]byte
for i := uint64(0); i < uint64(4*params.BeaconConfig().SlotsPerEpoch); i++ {
root := []byte(strconv.Itoa(int(i)))
assert.NoError(t, depositCache.InsertDeposit(ctx, &ethpb.Deposit{Data: &ethpb.Deposit_Data{

View File

@@ -159,7 +159,6 @@ func TestNotifyEngineIfChangedHead(t *testing.T) {
require.NoError(t, service.saveInitSyncBlock(ctx, r1, wsb))
st, _ := util.DeterministicGenesisState(t, 1)
service.head = &head{
slot: 1,
root: r1,
block: wsb,
state: st,
@@ -177,7 +176,6 @@ func TestNotifyEngineIfChangedHead(t *testing.T) {
require.NoError(t, err)
st, _ = util.DeterministicGenesisState(t, 1)
service.head = &head{
slot: 1,
root: r1,
block: wsb,
state: st,

View File

@@ -145,11 +145,6 @@ func (s *Service) ReceiveAttesterSlashing(ctx context.Context, slashing *ethpb.A
}
func (s *Service) handlePostBlockOperations(b interfaces.BeaconBlock) error {
// Delete the processed block attestations from attestation pool.
if err := s.deletePoolAtts(b.Body().Attestations()); err != nil {
return err
}
// Mark block exits as seen so we don't include same ones in future blocks.
for _, e := range b.Body().VoluntaryExits() {
s.cfg.ExitPool.MarkIncluded(e)

View File

@@ -33,7 +33,7 @@ func TestService_ReceiveBlock(t *testing.T) {
assert.NoError(t, err)
return blk
}
params.SetupTestConfigCleanupWithLock(t)
//params.SetupTestConfigCleanupWithLock(t)
bc := params.BeaconConfig().Copy()
bc.ShardCommitteePeriod = 0 // Required for voluntary exits test in reasonable time.
params.OverrideBeaconConfig(bc)

View File

@@ -1,8 +1,6 @@
package cache
import (
"sync"
lru "github.com/hashicorp/golang-lru"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
@@ -32,7 +30,6 @@ var (
// CheckpointStateCache is a struct with 1 queue for looking up state by checkpoint.
type CheckpointStateCache struct {
cache *lru.Cache
lock sync.RWMutex
}
// NewCheckpointStateCache creates a new checkpoint state cache for storing/accessing processed state.
@@ -45,8 +42,6 @@ func NewCheckpointStateCache() *CheckpointStateCache {
// StateByCheckpoint fetches state by checkpoint. Returns true with a
// reference to the CheckpointState info, if exists. Otherwise returns false, nil.
func (c *CheckpointStateCache) StateByCheckpoint(cp *ethpb.Checkpoint) (state.BeaconState, error) {
c.lock.RLock()
defer c.lock.RUnlock()
h, err := hash.HashProto(cp)
if err != nil {
return nil, err
@@ -67,8 +62,6 @@ func (c *CheckpointStateCache) StateByCheckpoint(cp *ethpb.Checkpoint) (state.Be
// AddCheckpointState adds CheckpointState object to the cache. This method also trims the least
// recently added CheckpointState object if the cache size has ready the max cache size limit.
func (c *CheckpointStateCache) AddCheckpointState(cp *ethpb.Checkpoint, s state.ReadOnlyBeaconState) error {
c.lock.Lock()
defer c.lock.Unlock()
h, err := hash.HashProto(cp)
if err != nil {
return err

View File

@@ -57,7 +57,7 @@ func (f *ProposerPayloadIDsCache) SetProposerAndPayloadIDs(slot types.Slot, vId
ids, ok := f.slotToProposerAndPayloadIDs[k]
// Ok to overwrite if the slot is already set but the cached payload ID is not set.
// This combats the re-org case where payload assignment could change at the start of the epoch.
byte8 := [vIdLength]byte{}
var byte8 [vIdLength]byte
if !ok || (ok && bytes.Equal(ids[vIdLength:], byte8[:])) {
f.slotToProposerAndPayloadIDs[k] = bs
}

View File

@@ -9,7 +9,7 @@ import (
func TestValidatorPayloadIDsCache_GetAndSaveValidatorPayloadIDs(t *testing.T) {
cache := NewProposerPayloadIDsCache()
r := [32]byte{}
var r [32]byte
i, p, ok := cache.GetProposerPayloadIDs(0, r)
require.Equal(t, false, ok)
require.Equal(t, types.ValidatorIndex(0), i)

View File

@@ -52,9 +52,8 @@ func (c *SyncCommitteeHeadStateCache) Get(slot types.Slot) (state.BeaconState, e
if !ok {
return nil, ErrIncorrectType
}
switch st.Version() {
case version.Altair, version.Bellatrix:
default:
// Sync committee is not supported in phase 0.
if st.Version() == version.Phase0 {
return nil, ErrIncorrectType
}
return st, nil

View File

@@ -33,6 +33,13 @@ func TestSyncCommitteeHeadState(t *testing.T) {
},
})
require.NoError(t, err)
capellaState, err := state_native.InitializeFromProtoCapella(&ethpb.BeaconStateCapella{
Fork: &ethpb.Fork{
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
},
})
require.NoError(t, err)
type put struct {
slot types.Slot
state state.BeaconState
@@ -106,6 +113,15 @@ func TestSyncCommitteeHeadState(t *testing.T) {
},
want: bellatrixState,
},
{
name: "found with key (capella state)",
key: types.Slot(200),
put: &put{
slot: types.Slot(200),
state: capellaState,
},
want: capellaState,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {

View File

@@ -14,14 +14,7 @@ go_library(
"upgrade.go",
],
importpath = "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/altair",
visibility = [
"//beacon-chain:__subpackages__",
"//cmd/prysmctl/testnet:__pkg__",
"//testing/endtoend/evaluators:__subpackages__",
"//testing/spectest:__subpackages__",
"//testing/util:__pkg__",
"//validator/client:__pkg__",
],
visibility = ["//visibility:public"],
deps = [
"//beacon-chain/core/blocks:go_default_library",
"//beacon-chain/core/epoch:go_default_library",

View File

@@ -256,7 +256,7 @@ func TestProcessAttestationNoVerify_SourceTargetHead(t *testing.T) {
},
AggregationBits: aggBits,
}
zeroSig := [96]byte{}
var zeroSig [96]byte
att.Signature = zeroSig[:]
ckp := beaconState.CurrentJustifiedCheckpoint()

View File

@@ -93,7 +93,7 @@ func ProcessEpoch(ctx context.Context, state state.BeaconState) (state.BeaconSta
if err != nil {
return nil, err
}
state, err = e.ProcessHistoricalRootsUpdate(state)
state, err = e.ProcessHistoricalDataUpdate(state)
if err != nil {
return nil, err
}

View File

@@ -67,6 +67,10 @@ func UpgradeToAltair(ctx context.Context, state state.BeaconState) (state.Beacon
epoch := time.CurrentEpoch(state)
numValidators := state.NumValidators()
hrs, err := state.HistoricalRoots()
if err != nil {
return nil, err
}
s := &ethpb.BeaconStateAltair{
GenesisTime: state.GenesisTime(),
GenesisValidatorsRoot: state.GenesisValidatorsRoot(),
@@ -79,7 +83,7 @@ func UpgradeToAltair(ctx context.Context, state state.BeaconState) (state.Beacon
LatestBlockHeader: state.LatestBlockHeader(),
BlockRoots: state.BlockRoots(),
StateRoots: state.StateRoots(),
HistoricalRoots: state.HistoricalRoots(),
HistoricalRoots: hrs,
Eth1Data: state.Eth1Data(),
Eth1DataVotes: state.Eth1DataVotes(),
Eth1DepositIndex: state.Eth1DepositIndex(),

View File

@@ -82,7 +82,11 @@ func TestUpgradeToAltair(t *testing.T) {
require.DeepSSZEqual(t, preForkState.LatestBlockHeader(), aState.LatestBlockHeader())
require.DeepSSZEqual(t, preForkState.BlockRoots(), aState.BlockRoots())
require.DeepSSZEqual(t, preForkState.StateRoots(), aState.StateRoots())
require.DeepSSZEqual(t, preForkState.HistoricalRoots(), aState.HistoricalRoots())
r1, err := preForkState.HistoricalRoots()
require.NoError(t, err)
r2, err := aState.HistoricalRoots()
require.NoError(t, err)
require.DeepSSZEqual(t, r1, r2)
require.DeepSSZEqual(t, preForkState.Eth1Data(), aState.Eth1Data())
require.DeepSSZEqual(t, preForkState.Eth1DataVotes(), aState.Eth1DataVotes())
require.DeepSSZEqual(t, preForkState.Eth1DepositIndex(), aState.Eth1DepositIndex())

View File

@@ -19,12 +19,7 @@ go_library(
"withdrawals.go",
],
importpath = "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/blocks",
visibility = [
"//beacon-chain:__subpackages__",
"//testing/spectest:__subpackages__",
"//testing/util:__pkg__",
"//validator:__subpackages__",
],
visibility = ["//visibility:public"],
deps = [
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/core/signing:go_default_library",
@@ -46,6 +41,7 @@ go_library(
"//math:go_default_library",
"//network/forks:go_default_library",
"//proto/engine/v1:go_default_library",
"//proto/eth/v2:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//proto/prysm/v1alpha1/attestation:go_default_library",
"//proto/prysm/v1alpha1/slashings:go_default_library",
@@ -103,6 +99,7 @@ go_test(
"//encoding/bytesutil:go_default_library",
"//encoding/ssz:go_default_library",
"//proto/engine/v1:go_default_library",
"//proto/migration:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//proto/prysm/v1alpha1/attestation:go_default_library",
"//proto/prysm/v1alpha1/attestation/aggregation:go_default_library",

View File

@@ -64,7 +64,7 @@ func TestVerifyAttestationNoVerifySignature_IncorrectSourceEpoch(t *testing.T) {
AggregationBits: aggBits,
}
zeroSig := [96]byte{}
var zeroSig [96]byte
att.Signature = zeroSig[:]
err := beaconState.SetSlot(beaconState.Slot() + params.BeaconConfig().MinAttestationInclusionDelay)

View File

@@ -113,7 +113,7 @@ func TestProcessAttestationsNoVerify_OK(t *testing.T) {
AggregationBits: aggBits,
}
zeroSig := [fieldparams.BLSSignatureLength]byte{}
var zeroSig [fieldparams.BLSSignatureLength]byte
att.Signature = zeroSig[:]
err := beaconState.SetSlot(beaconState.Slot() + params.BeaconConfig().MinAttestationInclusionDelay)
@@ -144,7 +144,7 @@ func TestVerifyAttestationNoVerifySignature_OK(t *testing.T) {
AggregationBits: aggBits,
}
zeroSig := [fieldparams.BLSSignatureLength]byte{}
var zeroSig [fieldparams.BLSSignatureLength]byte
att.Signature = zeroSig[:]
err := beaconState.SetSlot(beaconState.Slot() + params.BeaconConfig().MinAttestationInclusionDelay)
@@ -172,7 +172,7 @@ func TestVerifyAttestationNoVerifySignature_BadAttIdx(t *testing.T) {
},
AggregationBits: aggBits,
}
zeroSig := [fieldparams.BLSSignatureLength]byte{}
var zeroSig [fieldparams.BLSSignatureLength]byte
att.Signature = zeroSig[:]
require.NoError(t, beaconState.SetSlot(beaconState.Slot()+params.BeaconConfig().MinAttestationInclusionDelay))
ckp := beaconState.CurrentJustifiedCheckpoint()

View File

@@ -84,7 +84,7 @@ func ProcessAttesterSlashing(
slashingQuotient = cfg.MinSlashingPenaltyQuotient
case beaconState.Version() == version.Altair:
slashingQuotient = cfg.MinSlashingPenaltyQuotientAltair
case beaconState.Version() == version.Bellatrix, beaconState.Version() == version.Capella:
case beaconState.Version() >= version.Bellatrix:
slashingQuotient = cfg.MinSlashingPenaltyQuotientBellatrix
default:
return nil, errors.New("unknown state version")

View File

@@ -55,9 +55,9 @@ func TestFuzzProcessBlockHeader_10000(t *testing.T) {
func TestFuzzverifyDepositDataSigningRoot_10000(_ *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
var ba []byte
pubkey := [fieldparams.BLSPubkeyLength]byte{}
sig := [96]byte{}
domain := [4]byte{}
var pubkey [fieldparams.BLSPubkeyLength]byte
var sig [96]byte
var domain [4]byte
var p []byte
var s []byte
var d []byte

View File

@@ -3,9 +3,16 @@
package blocks
import (
"context"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state"
fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams"
"github.com/prysmaticlabs/prysm/v3/config/params"
"github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces"
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
)
@@ -29,3 +36,116 @@ func NewGenesisBlock(stateRoot []byte) *ethpb.SignedBeaconBlock {
}
return block
}
var ErrUnrecognizedState = errors.New("unknown underlying type for state.BeaconState value")
func NewGenesisBlockForState(ctx context.Context, st state.BeaconState) (interfaces.SignedBeaconBlock, error) {
root, err := st.HashTreeRoot(ctx)
if err != nil {
return nil, err
}
ps := st.ToProto()
switch ps.(type) {
case *ethpb.BeaconState:
return blocks.NewSignedBeaconBlock(&ethpb.SignedBeaconBlock{
Block: &ethpb.BeaconBlock{
ParentRoot: params.BeaconConfig().ZeroHash[:],
StateRoot: root[:],
Body: &ethpb.BeaconBlockBody{
RandaoReveal: make([]byte, fieldparams.BLSSignatureLength),
Eth1Data: &ethpb.Eth1Data{
DepositRoot: make([]byte, 32),
BlockHash: make([]byte, 32),
},
Graffiti: make([]byte, 32),
},
},
Signature: params.BeaconConfig().EmptySignature[:],
})
case *ethpb.BeaconStateAltair:
return blocks.NewSignedBeaconBlock(&ethpb.SignedBeaconBlockAltair{
Block: &ethpb.BeaconBlockAltair{
ParentRoot: params.BeaconConfig().ZeroHash[:],
StateRoot: root[:],
Body: &ethpb.BeaconBlockBodyAltair{
RandaoReveal: make([]byte, fieldparams.BLSSignatureLength),
Eth1Data: &ethpb.Eth1Data{
DepositRoot: make([]byte, 32),
BlockHash: make([]byte, 32),
},
Graffiti: make([]byte, 32),
SyncAggregate: &ethpb.SyncAggregate{
SyncCommitteeBits: make([]byte, fieldparams.SyncCommitteeLength/8),
SyncCommitteeSignature: make([]byte, fieldparams.BLSSignatureLength),
},
},
},
Signature: params.BeaconConfig().EmptySignature[:],
})
case *ethpb.BeaconStateBellatrix:
return blocks.NewSignedBeaconBlock(&ethpb.SignedBeaconBlockBellatrix{
Block: &ethpb.BeaconBlockBellatrix{
ParentRoot: params.BeaconConfig().ZeroHash[:],
StateRoot: root[:],
Body: &ethpb.BeaconBlockBodyBellatrix{
RandaoReveal: make([]byte, 96),
Eth1Data: &ethpb.Eth1Data{
DepositRoot: make([]byte, 32),
BlockHash: make([]byte, 32),
},
Graffiti: make([]byte, 32),
SyncAggregate: &ethpb.SyncAggregate{
SyncCommitteeBits: make([]byte, fieldparams.SyncCommitteeLength/8),
SyncCommitteeSignature: make([]byte, fieldparams.BLSSignatureLength),
},
ExecutionPayload: &enginev1.ExecutionPayload{
ParentHash: make([]byte, 32),
FeeRecipient: make([]byte, 20),
StateRoot: make([]byte, 32),
ReceiptsRoot: make([]byte, 32),
LogsBloom: make([]byte, 256),
PrevRandao: make([]byte, 32),
BaseFeePerGas: make([]byte, 32),
BlockHash: make([]byte, 32),
Transactions: make([][]byte, 0),
},
},
},
Signature: params.BeaconConfig().EmptySignature[:],
})
case *ethpb.BeaconStateCapella:
return blocks.NewSignedBeaconBlock(&ethpb.SignedBeaconBlockCapella{
Block: &ethpb.BeaconBlockCapella{
ParentRoot: params.BeaconConfig().ZeroHash[:],
StateRoot: root[:],
Body: &ethpb.BeaconBlockBodyCapella{
RandaoReveal: make([]byte, 96),
Eth1Data: &ethpb.Eth1Data{
DepositRoot: make([]byte, 32),
BlockHash: make([]byte, 32),
},
Graffiti: make([]byte, 32),
SyncAggregate: &ethpb.SyncAggregate{
SyncCommitteeBits: make([]byte, fieldparams.SyncCommitteeLength/8),
SyncCommitteeSignature: make([]byte, fieldparams.BLSSignatureLength),
},
ExecutionPayload: &enginev1.ExecutionPayloadCapella{
ParentHash: make([]byte, 32),
FeeRecipient: make([]byte, 20),
StateRoot: make([]byte, 32),
ReceiptsRoot: make([]byte, 32),
LogsBloom: make([]byte, 256),
PrevRandao: make([]byte, 32),
BaseFeePerGas: make([]byte, 32),
BlockHash: make([]byte, 32),
Transactions: make([][]byte, 0),
Withdrawals: make([]*enginev1.Withdrawal, 0),
},
},
},
Signature: params.BeaconConfig().EmptySignature[:],
})
default:
return nil, ErrUnrecognizedState
}
}

View File

@@ -281,7 +281,7 @@ func ProcessPayloadHeader(st state.BeaconState, header interfaces.ExecutionData)
// GetBlockPayloadHash returns the hash of the execution payload of the block
func GetBlockPayloadHash(blk interfaces.BeaconBlock) ([32]byte, error) {
payloadHash := [32]byte{}
var payloadHash [32]byte
if IsPreBellatrixVersion(blk.Version()) {
return payloadHash, nil
}

View File

@@ -7,14 +7,12 @@ import (
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/time"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state"
state_native "github.com/prysmaticlabs/prysm/v3/beacon-chain/state/state-native"
fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams"
consensusblocks "github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces"
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/v3/encoding/ssz"
enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v3/testing/require"
"github.com/prysmaticlabs/prysm/v3/testing/util"
"github.com/prysmaticlabs/prysm/v3/time/slots"
@@ -350,16 +348,6 @@ func Test_IsExecutionEnabled(t *testing.T) {
}
}
func Test_IsExecutionEnabledCapella(t *testing.T) {
st, _ := util.DeterministicGenesisStateCapella(t, 1)
blk := util.NewBeaconBlockCapella()
body, err := consensusblocks.NewBeaconBlockBody(blk.Block.Body)
require.NoError(t, err)
got, err := blocks.IsExecutionEnabled(st, body)
require.NoError(t, err)
require.Equal(t, false, got)
}
func Test_IsExecutionEnabledUsingHeader(t *testing.T) {
tests := []struct {
name string
@@ -613,13 +601,14 @@ func Test_ProcessPayload(t *testing.T) {
}
func Test_ProcessPayloadCapella(t *testing.T) {
spb := &ethpb.BeaconStateCapella{}
st, err := state_native.InitializeFromProtoCapella(spb)
require.NoError(t, err)
st, _ := util.DeterministicGenesisStateCapella(t, 1)
header, err := emptyPayloadHeaderCapella()
require.NoError(t, err)
require.NoError(t, st.SetLatestExecutionPayloadHeader(header))
payload := emptyPayloadCapella()
random, err := helpers.RandaoMix(st, time.CurrentEpoch(st))
require.NoError(t, err)
payload.PrevRandao = random
wrapped, err := consensusblocks.WrappedExecutionPayloadCapella(payload)
require.NoError(t, err)
_, err = blocks.ProcessPayload(st, wrapped)

View File

@@ -82,7 +82,7 @@ func ProcessProposerSlashing(
slashingQuotient = cfg.MinSlashingPenaltyQuotient
case beaconState.Version() == version.Altair:
slashingQuotient = cfg.MinSlashingPenaltyQuotientAltair
case beaconState.Version() == version.Bellatrix, beaconState.Version() == version.Capella:
case beaconState.Version() >= version.Bellatrix:
slashingQuotient = cfg.MinSlashingPenaltyQuotientBellatrix
default:
return nil, errors.New("unknown state version")

View File

@@ -19,7 +19,7 @@ import (
)
// retrieves the signature batch from the raw data, public key,signature and domain provided.
func signatureBatch(signedData, pub, signature, domain []byte) (*bls.SignatureBatch, error) {
func signatureBatch(signedData, pub, signature, domain []byte, desc string) (*bls.SignatureBatch, error) {
publicKey, err := bls.PublicKeyFromBytes(pub)
if err != nil {
return nil, errors.Wrap(err, "could not convert bytes to public key")
@@ -33,15 +33,16 @@ func signatureBatch(signedData, pub, signature, domain []byte) (*bls.SignatureBa
return nil, errors.Wrap(err, "could not hash container")
}
return &bls.SignatureBatch{
Signatures: [][]byte{signature},
PublicKeys: []bls.PublicKey{publicKey},
Messages: [][32]byte{root},
Signatures: [][]byte{signature},
PublicKeys: []bls.PublicKey{publicKey},
Messages: [][32]byte{root},
Descriptions: []string{desc},
}, nil
}
// verifies the signature from the raw data, public key and domain provided.
func verifySignature(signedData, pub, signature, domain []byte) error {
set, err := signatureBatch(signedData, pub, signature, domain)
set, err := signatureBatch(signedData, pub, signature, domain, signing.UnknownSignature)
if err != nil {
return err
}
@@ -146,7 +147,7 @@ func RandaoSignatureBatch(
if err != nil {
return nil, err
}
set, err := signatureBatch(buf, proposerPub, reveal, domain)
set, err := signatureBatch(buf, proposerPub, reveal, domain, signing.RandaoSignature)
if err != nil {
return nil, err
}
@@ -186,6 +187,7 @@ func createAttestationSignatureBatch(
sigs := make([][]byte, len(atts))
pks := make([]bls.PublicKey, len(atts))
msgs := make([][32]byte, len(atts))
descs := make([]string, len(atts))
for i, a := range atts {
sigs[i] = a.Signature
c, err := helpers.BeaconCommitteeFromState(ctx, beaconState, a.Data.Slot, a.Data.CommitteeIndex)
@@ -216,11 +218,14 @@ func createAttestationSignatureBatch(
return nil, errors.Wrap(err, "could not get signing root of object")
}
msgs[i] = root
descs[i] = signing.AttestationSignature
}
return &bls.SignatureBatch{
Signatures: sigs,
PublicKeys: pks,
Messages: msgs,
Signatures: sigs,
PublicKeys: pks,
Messages: msgs,
Descriptions: descs,
}, nil
}

View File

@@ -2,7 +2,6 @@ package blocks
import (
"bytes"
"context"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/helpers"
@@ -15,9 +14,9 @@ import (
"github.com/prysmaticlabs/prysm/v3/crypto/hash"
"github.com/prysmaticlabs/prysm/v3/encoding/ssz"
enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
ethpbv2 "github.com/prysmaticlabs/prysm/v3/proto/eth/v2"
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v3/runtime/version"
"github.com/prysmaticlabs/prysm/v3/time/slots"
)
const executionToBLSPadding = 12
@@ -120,13 +119,13 @@ func ProcessWithdrawals(st state.BeaconState, withdrawals []*enginev1.Withdrawal
return nil, errInvalidWithdrawalNumber
}
for i, withdrawal := range withdrawals {
if withdrawal.WithdrawalIndex != expected[i].WithdrawalIndex {
if withdrawal.Index != expected[i].Index {
return nil, errInvalidWithdrawalIndex
}
if withdrawal.ValidatorIndex != expected[i].ValidatorIndex {
return nil, errInvalidValidatorIndex
}
if !bytes.Equal(withdrawal.ExecutionAddress, expected[i].ExecutionAddress) {
if !bytes.Equal(withdrawal.Address, expected[i].Address) {
return nil, errInvalidExecutionAddress
}
if withdrawal.Amount != expected[i].Amount {
@@ -138,22 +137,31 @@ func ProcessWithdrawals(st state.BeaconState, withdrawals []*enginev1.Withdrawal
}
}
if len(withdrawals) > 0 {
if err := st.SetNextWithdrawalIndex(withdrawals[len(withdrawals)-1].WithdrawalIndex + 1); err != nil {
if err := st.SetNextWithdrawalIndex(withdrawals[len(withdrawals)-1].Index + 1); err != nil {
return nil, errors.Wrap(err, "could not set next withdrawal index")
}
nextValidatorIndex := withdrawals[len(withdrawals)-1].ValidatorIndex + 1
}
var nextValidatorIndex types.ValidatorIndex
if uint64(len(withdrawals)) < params.BeaconConfig().MaxWithdrawalsPerPayload {
nextValidatorIndex, err = st.NextWithdrawalValidatorIndex()
if err != nil {
return nil, errors.Wrap(err, "could not get next withdrawal validator index")
}
nextValidatorIndex += types.ValidatorIndex(params.BeaconConfig().MaxValidatorsPerWithdrawalsSweep)
nextValidatorIndex = nextValidatorIndex % types.ValidatorIndex(st.NumValidators())
} else {
nextValidatorIndex = withdrawals[len(withdrawals)-1].ValidatorIndex + 1
if nextValidatorIndex == types.ValidatorIndex(st.NumValidators()) {
nextValidatorIndex = 0
}
if err := st.SetNextWithdrawalValidatorIndex(nextValidatorIndex); err != nil {
return nil, errors.Wrap(err, "could not set latest withdrawal validator index")
}
}
if err := st.SetNextWithdrawalValidatorIndex(nextValidatorIndex); err != nil {
return nil, errors.Wrap(err, "could not set next withdrawal validator index")
}
return st, nil
}
func BLSChangesSignatureBatch(
ctx context.Context,
st state.ReadOnlyBeaconState,
changes []*ethpb.SignedBLSToExecutionChange,
) (*bls.SignatureBatch, error) {
@@ -162,19 +170,17 @@ func BLSChangesSignatureBatch(
return bls.NewSet(), nil
}
batch := &bls.SignatureBatch{
Signatures: make([][]byte, len(changes)),
PublicKeys: make([]bls.PublicKey, len(changes)),
Messages: make([][32]byte, len(changes)),
Signatures: make([][]byte, len(changes)),
PublicKeys: make([]bls.PublicKey, len(changes)),
Messages: make([][32]byte, len(changes)),
Descriptions: make([]string, len(changes)),
}
epoch := slots.ToEpoch(st.Slot())
domain, err := signing.Domain(st.Fork(), epoch, params.BeaconConfig().DomainBLSToExecutionChange, st.GenesisValidatorsRoot())
c := params.BeaconConfig()
domain, err := signing.ComputeDomain(c.DomainBLSToExecutionChange, c.GenesisForkVersion, st.GenesisValidatorsRoot())
if err != nil {
return nil, err
return nil, errors.Wrap(err, "could not compute signing domain")
}
for i, change := range changes {
if ctx.Err() != nil {
return nil, ctx.Err()
}
batch.Signatures[i] = change.Signature
publicKey, err := bls.PublicKeyFromBytes(change.Message.FromBlsPubkey)
if err != nil {
@@ -186,6 +192,23 @@ func BLSChangesSignatureBatch(
return nil, errors.Wrap(err, "could not compute BLSToExecutionChange signing data")
}
batch.Messages[i] = htr
batch.Descriptions[i] = signing.BlsChangeSignature
}
return batch, nil
}
// VerifyBLSChangeSignature checks the signature in the SignedBLSToExecutionChange message.
// It validates the signature with the Capella fork version if the passed state
// is from a previous fork.
func VerifyBLSChangeSignature(
st state.BeaconState,
change *ethpbv2.SignedBLSToExecutionChange,
) error {
c := params.BeaconConfig()
domain, err := signing.ComputeDomain(c.DomainBLSToExecutionChange, c.GenesisForkVersion, st.GenesisValidatorsRoot())
if err != nil {
return errors.Wrap(err, "could not compute signing domain")
}
publicKey := change.Message.FromBlsPubkey
return signing.VerifySigningRoot(change.Message, publicKey, change.Signature, domain)
}

View File

@@ -1,7 +1,6 @@
package blocks_test
import (
"context"
"math/rand"
"testing"
@@ -18,6 +17,7 @@ import (
"github.com/prysmaticlabs/prysm/v3/crypto/hash"
"github.com/prysmaticlabs/prysm/v3/encoding/ssz"
enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
"github.com/prysmaticlabs/prysm/v3/proto/migration"
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v3/testing/require"
"github.com/prysmaticlabs/prysm/v3/time/slots"
@@ -245,6 +245,7 @@ func TestProcessWithdrawals(t *testing.T) {
numValidators = 128
notWithdrawableIndex = 127
notPartiallyWithdrawable = 126
maxSweep = uint64(80)
)
maxEffectiveBalance := params.BeaconConfig().MaxEffectiveBalance
@@ -276,18 +277,18 @@ func TestProcessWithdrawals(t *testing.T) {
}
fullWithdrawal := func(i types.ValidatorIndex, idx uint64) *enginev1.Withdrawal {
return &enginev1.Withdrawal{
WithdrawalIndex: idx,
ValidatorIndex: i,
ExecutionAddress: executionAddress(i),
Amount: withdrawalAmount(i),
Index: idx,
ValidatorIndex: i,
Address: executionAddress(i),
Amount: withdrawalAmount(i),
}
}
partialWithdrawal := func(i types.ValidatorIndex, idx uint64) *enginev1.Withdrawal {
return &enginev1.Withdrawal{
WithdrawalIndex: idx,
ValidatorIndex: i,
ExecutionAddress: executionAddress(i),
Amount: withdrawalAmount(i) - maxEffectiveBalance,
Index: idx,
ValidatorIndex: i,
Address: executionAddress(i),
Amount: withdrawalAmount(i) - maxEffectiveBalance,
}
}
tests := []Test{
@@ -298,7 +299,7 @@ func TestProcessWithdrawals(t *testing.T) {
NextWithdrawalIndex: 3,
},
Control: control{
NextWithdrawalValidatorIndex: 10,
NextWithdrawalValidatorIndex: 90,
NextWithdrawalIndex: 3,
},
},
@@ -307,29 +308,29 @@ func TestProcessWithdrawals(t *testing.T) {
Name: "success one full withdrawal",
NextWithdrawalIndex: 3,
NextWithdrawalValidatorIndex: 5,
FullWithdrawalIndices: []types.ValidatorIndex{1},
FullWithdrawalIndices: []types.ValidatorIndex{70},
Withdrawals: []*enginev1.Withdrawal{
fullWithdrawal(1, 3),
fullWithdrawal(70, 3),
},
},
Control: control{
NextWithdrawalValidatorIndex: 2,
NextWithdrawalValidatorIndex: 85,
NextWithdrawalIndex: 4,
Balances: map[uint64]uint64{1: 0},
Balances: map[uint64]uint64{70: 0},
},
},
{
Args: args{
Name: "success one partial withdrawal",
NextWithdrawalIndex: 21,
NextWithdrawalValidatorIndex: 37,
NextWithdrawalValidatorIndex: 120,
PartialWithdrawalIndices: []types.ValidatorIndex{7},
Withdrawals: []*enginev1.Withdrawal{
partialWithdrawal(7, 21),
},
},
Control: control{
NextWithdrawalValidatorIndex: 8,
NextWithdrawalValidatorIndex: 72,
NextWithdrawalIndex: 22,
Balances: map[uint64]uint64{7: maxEffectiveBalance},
},
@@ -342,13 +343,45 @@ func TestProcessWithdrawals(t *testing.T) {
FullWithdrawalIndices: []types.ValidatorIndex{7, 19, 28, 1},
Withdrawals: []*enginev1.Withdrawal{
fullWithdrawal(7, 22), fullWithdrawal(19, 23), fullWithdrawal(28, 24),
fullWithdrawal(1, 25),
},
},
Control: control{
NextWithdrawalValidatorIndex: 2,
NextWithdrawalValidatorIndex: 84,
NextWithdrawalIndex: 25,
Balances: map[uint64]uint64{7: 0, 19: 0, 28: 0},
},
},
{
Args: args{
Name: "Less than max sweep at end",
NextWithdrawalIndex: 22,
NextWithdrawalValidatorIndex: 4,
FullWithdrawalIndices: []types.ValidatorIndex{80, 81, 82, 83},
Withdrawals: []*enginev1.Withdrawal{
fullWithdrawal(80, 22), fullWithdrawal(81, 23), fullWithdrawal(82, 24),
fullWithdrawal(83, 25),
},
},
Control: control{
NextWithdrawalValidatorIndex: 84,
NextWithdrawalIndex: 26,
Balances: map[uint64]uint64{7: 0, 19: 0, 28: 0, 1: 0},
Balances: map[uint64]uint64{80: 0, 81: 0, 82: 0, 83: 0},
},
},
{
Args: args{
Name: "Less than max sweep and beginning",
NextWithdrawalIndex: 22,
NextWithdrawalValidatorIndex: 4,
FullWithdrawalIndices: []types.ValidatorIndex{4, 5, 6},
Withdrawals: []*enginev1.Withdrawal{
fullWithdrawal(4, 22), fullWithdrawal(5, 23), fullWithdrawal(6, 24),
},
},
Control: control{
NextWithdrawalValidatorIndex: 84,
NextWithdrawalIndex: 25,
Balances: map[uint64]uint64{4: 0, 5: 0, 6: 0},
},
},
{
@@ -356,20 +389,18 @@ func TestProcessWithdrawals(t *testing.T) {
Name: "success many partial withdrawals",
NextWithdrawalIndex: 22,
NextWithdrawalValidatorIndex: 4,
PartialWithdrawalIndices: []types.ValidatorIndex{7, 19, 28, 1},
PartialWithdrawalIndices: []types.ValidatorIndex{7, 19, 28},
Withdrawals: []*enginev1.Withdrawal{
partialWithdrawal(7, 22), partialWithdrawal(19, 23), partialWithdrawal(28, 24),
partialWithdrawal(1, 25),
},
},
Control: control{
NextWithdrawalValidatorIndex: 2,
NextWithdrawalIndex: 26,
NextWithdrawalValidatorIndex: 84,
NextWithdrawalIndex: 25,
Balances: map[uint64]uint64{
7: maxEffectiveBalance,
19: maxEffectiveBalance,
28: maxEffectiveBalance,
1: maxEffectiveBalance,
},
},
},
@@ -377,17 +408,17 @@ func TestProcessWithdrawals(t *testing.T) {
Args: args{
Name: "success many withdrawals",
NextWithdrawalIndex: 22,
NextWithdrawalValidatorIndex: 12,
NextWithdrawalValidatorIndex: 88,
FullWithdrawalIndices: []types.ValidatorIndex{7, 19, 28},
PartialWithdrawalIndices: []types.ValidatorIndex{2, 1, 89, 15},
Withdrawals: []*enginev1.Withdrawal{
partialWithdrawal(15, 22), fullWithdrawal(19, 23), fullWithdrawal(28, 24),
partialWithdrawal(89, 25), partialWithdrawal(1, 26), partialWithdrawal(2, 27),
fullWithdrawal(7, 28),
partialWithdrawal(89, 22), partialWithdrawal(1, 23), partialWithdrawal(2, 24),
fullWithdrawal(7, 25), partialWithdrawal(15, 26), fullWithdrawal(19, 27),
fullWithdrawal(28, 28),
},
},
Control: control{
NextWithdrawalValidatorIndex: 8,
NextWithdrawalValidatorIndex: 40,
NextWithdrawalIndex: 29,
Balances: map[uint64]uint64{
7: 0, 19: 0, 28: 0,
@@ -590,6 +621,8 @@ func TestProcessWithdrawals(t *testing.T) {
for _, test := range tests {
t.Run(test.Args.Name, func(t *testing.T) {
saved := params.BeaconConfig().MaxValidatorsPerWithdrawalsSweep
params.BeaconConfig().MaxValidatorsPerWithdrawalsSweep = maxSweep
if test.Args.Withdrawals == nil {
test.Args.Withdrawals = make([]*enginev1.Withdrawal, 0)
}
@@ -615,6 +648,7 @@ func TestProcessWithdrawals(t *testing.T) {
require.NoError(t, err)
checkPostState(t, test.Control, post)
}
params.BeaconConfig().MaxValidatorsPerWithdrawalsSweep = saved
})
}
}
@@ -746,9 +780,167 @@ func TestBLSChangesSignatureBatch(t *testing.T) {
}
signedChanges[i] = signed
}
batch, err := blocks.BLSChangesSignatureBatch(context.Background(), st, signedChanges)
batch, err := blocks.BLSChangesSignatureBatch(st, signedChanges)
require.NoError(t, err)
verify, err := batch.Verify()
require.NoError(t, err)
require.Equal(t, true, verify)
// Verify a single change
change := migration.V1Alpha1SignedBLSToExecChangeToV2(signedChanges[0])
require.NoError(t, blocks.VerifyBLSChangeSignature(st, change))
}
func TestBLSChangesSignatureBatchWrongFork(t *testing.T) {
spb := &ethpb.BeaconStateCapella{
Fork: &ethpb.Fork{
CurrentVersion: params.BeaconConfig().CapellaForkVersion,
PreviousVersion: params.BeaconConfig().BellatrixForkVersion,
Epoch: params.BeaconConfig().CapellaForkEpoch,
},
}
numValidators := 10
validators := make([]*ethpb.Validator, numValidators)
blsChanges := make([]*ethpb.BLSToExecutionChange, numValidators)
spb.Balances = make([]uint64, numValidators)
privKeys := make([]common.SecretKey, numValidators)
maxEffectiveBalance := params.BeaconConfig().MaxEffectiveBalance
executionAddress := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13}
for i := range validators {
v := &ethpb.Validator{}
v.EffectiveBalance = maxEffectiveBalance
v.WithdrawableEpoch = params.BeaconConfig().FarFutureEpoch
v.WithdrawalCredentials = make([]byte, 32)
priv, err := bls.RandKey()
require.NoError(t, err)
privKeys[i] = priv
pubkey := priv.PublicKey().Marshal()
message := &ethpb.BLSToExecutionChange{
ToExecutionAddress: executionAddress,
ValidatorIndex: types.ValidatorIndex(i),
FromBlsPubkey: pubkey,
}
hashFn := ssz.NewHasherFunc(hash.CustomSHA256Hasher())
digest := hashFn.Hash(pubkey)
digest[0] = params.BeaconConfig().BLSWithdrawalPrefixByte
copy(v.WithdrawalCredentials, digest[:])
validators[i] = v
blsChanges[i] = message
}
spb.Validators = validators
st, err := state_native.InitializeFromProtoCapella(spb)
require.NoError(t, err)
signedChanges := make([]*ethpb.SignedBLSToExecutionChange, numValidators)
for i, message := range blsChanges {
signature, err := signing.ComputeDomainAndSign(st, time.CurrentEpoch(st), message, params.BeaconConfig().DomainBLSToExecutionChange, privKeys[i])
require.NoError(t, err)
signed := &ethpb.SignedBLSToExecutionChange{
Message: message,
Signature: signature,
}
signedChanges[i] = signed
}
batch, err := blocks.BLSChangesSignatureBatch(st, signedChanges)
require.NoError(t, err)
verify, err := batch.Verify()
require.NoError(t, err)
require.Equal(t, false, verify)
// Verify a single change
change := migration.V1Alpha1SignedBLSToExecChangeToV2(signedChanges[0])
require.ErrorIs(t, signing.ErrSigFailedToVerify, blocks.VerifyBLSChangeSignature(st, change))
}
func TestBLSChangesSignatureBatchFromBellatrix(t *testing.T) {
cfg := params.BeaconConfig()
savedConfig := cfg.Copy()
cfg.CapellaForkEpoch = cfg.BellatrixForkEpoch.AddEpoch(2)
params.OverrideBeaconConfig(cfg)
spb := &ethpb.BeaconStateBellatrix{
Fork: &ethpb.Fork{
CurrentVersion: params.BeaconConfig().BellatrixForkVersion,
PreviousVersion: params.BeaconConfig().AltairForkVersion,
Epoch: params.BeaconConfig().BellatrixForkEpoch,
},
}
numValidators := 10
validators := make([]*ethpb.Validator, numValidators)
blsChanges := make([]*ethpb.BLSToExecutionChange, numValidators)
spb.Balances = make([]uint64, numValidators)
slot, err := slots.EpochStart(params.BeaconConfig().BellatrixForkEpoch)
require.NoError(t, err)
spb.Slot = slot
privKeys := make([]common.SecretKey, numValidators)
maxEffectiveBalance := params.BeaconConfig().MaxEffectiveBalance
executionAddress := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13}
for i := range validators {
v := &ethpb.Validator{}
v.EffectiveBalance = maxEffectiveBalance
v.WithdrawableEpoch = params.BeaconConfig().FarFutureEpoch
v.WithdrawalCredentials = make([]byte, 32)
priv, err := bls.RandKey()
require.NoError(t, err)
privKeys[i] = priv
pubkey := priv.PublicKey().Marshal()
message := &ethpb.BLSToExecutionChange{
ToExecutionAddress: executionAddress,
ValidatorIndex: types.ValidatorIndex(i),
FromBlsPubkey: pubkey,
}
hashFn := ssz.NewHasherFunc(hash.CustomSHA256Hasher())
digest := hashFn.Hash(pubkey)
digest[0] = params.BeaconConfig().BLSWithdrawalPrefixByte
copy(v.WithdrawalCredentials, digest[:])
validators[i] = v
blsChanges[i] = message
}
spb.Validators = validators
st, err := state_native.InitializeFromProtoBellatrix(spb)
require.NoError(t, err)
signedChanges := make([]*ethpb.SignedBLSToExecutionChange, numValidators)
spc := &ethpb.BeaconStateCapella{
Fork: &ethpb.Fork{
CurrentVersion: params.BeaconConfig().CapellaForkVersion,
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
Epoch: params.BeaconConfig().CapellaForkEpoch,
},
}
slot, err = slots.EpochStart(params.BeaconConfig().CapellaForkEpoch)
require.NoError(t, err)
spc.Slot = slot
stc, err := state_native.InitializeFromProtoCapella(spc)
require.NoError(t, err)
for i, message := range blsChanges {
signature, err := signing.ComputeDomainAndSign(stc, 0, message, params.BeaconConfig().DomainBLSToExecutionChange, privKeys[i])
require.NoError(t, err)
signed := &ethpb.SignedBLSToExecutionChange{
Message: message,
Signature: signature,
}
signedChanges[i] = signed
}
batch, err := blocks.BLSChangesSignatureBatch(st, signedChanges)
require.NoError(t, err)
verify, err := batch.Verify()
require.NoError(t, err)
require.Equal(t, true, verify)
// Verify a single change
change := migration.V1Alpha1SignedBLSToExecChangeToV2(signedChanges[0])
require.NoError(t, blocks.VerifyBLSChangeSignature(st, change))
params.OverrideBeaconConfig(savedConfig)
}

View File

@@ -42,6 +42,10 @@ func UpgradeToCapella(state state.BeaconState) (state.BeaconState, error) {
return nil, err
}
hrs, err := state.HistoricalRoots()
if err != nil {
return nil, err
}
s := &ethpb.BeaconStateCapella{
GenesisTime: state.GenesisTime(),
GenesisValidatorsRoot: state.GenesisValidatorsRoot(),
@@ -54,7 +58,7 @@ func UpgradeToCapella(state state.BeaconState) (state.BeaconState, error) {
LatestBlockHeader: state.LatestBlockHeader(),
BlockRoots: state.BlockRoots(),
StateRoots: state.StateRoots(),
HistoricalRoots: state.HistoricalRoots(),
HistoricalRoots: hrs,
Eth1Data: state.Eth1Data(),
Eth1DataVotes: state.Eth1DataVotes(),
Eth1DepositIndex: state.Eth1DepositIndex(),
@@ -90,6 +94,7 @@ func UpgradeToCapella(state state.BeaconState) (state.BeaconState, error) {
},
NextWithdrawalIndex: 0,
NextWithdrawalValidatorIndex: 0,
HistoricalSummaries: make([]*ethpb.HistoricalSummary, 0),
}
return state_native.InitializeFromProtoUnsafeCapella(s)

View File

@@ -25,7 +25,6 @@ func TestUpgradeToCapella(t *testing.T) {
require.DeepSSZEqual(t, preForkState.LatestBlockHeader(), mSt.LatestBlockHeader())
require.DeepSSZEqual(t, preForkState.BlockRoots(), mSt.BlockRoots())
require.DeepSSZEqual(t, preForkState.StateRoots(), mSt.StateRoots())
require.DeepSSZEqual(t, preForkState.HistoricalRoots(), mSt.HistoricalRoots())
require.DeepSSZEqual(t, preForkState.Eth1Data(), mSt.Eth1Data())
require.DeepSSZEqual(t, preForkState.Eth1DataVotes(), mSt.Eth1DataVotes())
require.DeepSSZEqual(t, preForkState.Eth1DepositIndex(), mSt.Eth1DepositIndex())
@@ -98,4 +97,8 @@ func TestUpgradeToCapella(t *testing.T) {
lwvi, err := mSt.NextWithdrawalValidatorIndex()
require.NoError(t, err)
require.Equal(t, types.ValidatorIndex(0), lwvi)
summaries, err := mSt.HistoricalSummaries()
require.NoError(t, err)
require.Equal(t, 0, len(summaries))
}

View File

@@ -13,11 +13,14 @@ go_library(
"//beacon-chain/core/time:go_default_library",
"//beacon-chain/core/validators:go_default_library",
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/stateutil:go_default_library",
"//config/fieldparams:go_default_library",
"//config/params:go_default_library",
"//consensus-types/primitives:go_default_library",
"//math:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//proto/prysm/v1alpha1/attestation:go_default_library",
"//runtime/version:go_default_library",
"@com_github_pkg_errors//:go_default_library",
],
)
@@ -33,8 +36,10 @@ go_test(
deps = [
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/core/time:go_default_library",
"//beacon-chain/core/transition:go_default_library",
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/state-native:go_default_library",
"//beacon-chain/state/stateutil:go_default_library",
"//config/fieldparams:go_default_library",
"//config/params:go_default_library",
"//consensus-types/primitives:go_default_library",

View File

@@ -14,11 +14,14 @@ import (
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/time"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/validators"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state/stateutil"
fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams"
"github.com/prysmaticlabs/prysm/v3/config/params"
types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v3/math"
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1/attestation"
"github.com/prysmaticlabs/prysm/v3/runtime/version"
)
// sortableIndices implements the Sort interface to sort newly activated validator indices
@@ -349,33 +352,39 @@ func ProcessRandaoMixesReset(state state.BeaconState) (state.BeaconState, error)
return state, nil
}
// ProcessHistoricalRootsUpdate processes the updates to historical root accumulator during epoch processing.
//
// Spec pseudocode definition:
//
// def process_historical_roots_update(state: BeaconState) -> None:
// # Set historical root accumulator
// next_epoch = Epoch(get_current_epoch(state) + 1)
// if next_epoch % (SLOTS_PER_HISTORICAL_ROOT // SLOTS_PER_EPOCH) == 0:
// historical_batch = HistoricalBatch(block_roots=state.block_roots, state_roots=state.state_roots)
// state.historical_roots.append(hash_tree_root(historical_batch))
func ProcessHistoricalRootsUpdate(state state.BeaconState) (state.BeaconState, error) {
// ProcessHistoricalDataUpdate processes the updates to historical data during epoch processing.
// From Capella onward, per spec,state's historical summaries are updated instead of historical roots.
func ProcessHistoricalDataUpdate(state state.BeaconState) (state.BeaconState, error) {
currentEpoch := time.CurrentEpoch(state)
nextEpoch := currentEpoch + 1
// Set historical root accumulator.
epochsPerHistoricalRoot := params.BeaconConfig().SlotsPerHistoricalRoot.DivSlot(params.BeaconConfig().SlotsPerEpoch)
if nextEpoch.Mod(uint64(epochsPerHistoricalRoot)) == 0 {
historicalBatch := &ethpb.HistoricalBatch{
BlockRoots: state.BlockRoots(),
StateRoots: state.StateRoots(),
}
batchRoot, err := historicalBatch.HashTreeRoot()
if err != nil {
return nil, errors.Wrap(err, "could not hash historical batch")
}
if err := state.AppendHistoricalRoots(batchRoot); err != nil {
return nil, err
if state.Version() >= version.Capella {
br, err := stateutil.ArraysRoot(state.BlockRoots(), fieldparams.BlockRootsLength)
if err != nil {
return nil, err
}
sr, err := stateutil.ArraysRoot(state.StateRoots(), fieldparams.StateRootsLength)
if err != nil {
return nil, err
}
if err := state.AppendHistoricalSummaries(&ethpb.HistoricalSummary{BlockSummaryRoot: br[:], StateSummaryRoot: sr[:]}); err != nil {
return nil, err
}
} else {
historicalBatch := &ethpb.HistoricalBatch{
BlockRoots: state.BlockRoots(),
StateRoots: state.StateRoots(),
}
batchRoot, err := historicalBatch.HashTreeRoot()
if err != nil {
return nil, errors.Wrap(err, "could not hash historical batch")
}
if err := state.AppendHistoricalRoots(batchRoot); err != nil {
return nil, err
}
}
}
@@ -426,7 +435,7 @@ func ProcessFinalUpdates(state state.BeaconState) (state.BeaconState, error) {
}
// Set historical root accumulator.
state, err = ProcessHistoricalRootsUpdate(state)
state, err = ProcessHistoricalDataUpdate(state)
if err != nil {
return nil, err
}

View File

@@ -10,8 +10,10 @@ import (
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/epoch"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/time"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/transition"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state"
state_native "github.com/prysmaticlabs/prysm/v3/beacon-chain/state/state-native"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state/stateutil"
fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams"
"github.com/prysmaticlabs/prysm/v3/config/params"
types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
@@ -274,7 +276,9 @@ func TestProcessFinalUpdates_CanProcess(t *testing.T) {
assert.DeepNotEqual(t, params.BeaconConfig().ZeroHash[:], mix, "latest RANDAO still zero hashes")
// Verify historical root accumulator was appended.
assert.Equal(t, 1, len(newS.HistoricalRoots()), "Unexpected slashed balance")
roots, err := newS.HistoricalRoots()
require.NoError(t, err)
assert.Equal(t, 1, len(roots), "Unexpected slashed balance")
currAtt, err := newS.CurrentEpochAttestations()
require.NoError(t, err)
assert.NotNil(t, currAtt, "Nil value stored in current epoch attestations instead of empty slice")
@@ -455,3 +459,83 @@ func TestProcessSlashings_BadValue(t *testing.T) {
_, err = epoch.ProcessSlashings(s, params.BeaconConfig().ProportionalSlashingMultiplier)
require.ErrorContains(t, "addition overflows", err)
}
func TestProcessHistoricalDataUpdate(t *testing.T) {
tests := []struct {
name string
st func() state.BeaconState
verifier func(state.BeaconState)
}{
{
name: "no change",
st: func() state.BeaconState {
st, _ := util.DeterministicGenesisState(t, 1)
return st
},
verifier: func(st state.BeaconState) {
roots, err := st.HistoricalRoots()
require.NoError(t, err)
require.Equal(t, 0, len(roots))
},
},
{
name: "before capella can process and get historical root",
st: func() state.BeaconState {
st, _ := util.DeterministicGenesisState(t, 1)
st, err := transition.ProcessSlots(context.Background(), st, params.BeaconConfig().SlotsPerHistoricalRoot-1)
require.NoError(t, err)
return st
},
verifier: func(st state.BeaconState) {
roots, err := st.HistoricalRoots()
require.NoError(t, err)
require.Equal(t, 1, len(roots))
b := &ethpb.HistoricalBatch{
BlockRoots: st.BlockRoots(),
StateRoots: st.StateRoots(),
}
r, err := b.HashTreeRoot()
require.NoError(t, err)
require.DeepEqual(t, r[:], roots[0])
_, err = st.HistoricalSummaries()
require.ErrorContains(t, "HistoricalSummaries is not supported for phase0", err)
},
},
{
name: "after capella can process and get historical summary",
st: func() state.BeaconState {
st, _ := util.DeterministicGenesisStateCapella(t, 1)
st, err := transition.ProcessSlots(context.Background(), st, params.BeaconConfig().SlotsPerHistoricalRoot-1)
require.NoError(t, err)
return st
},
verifier: func(st state.BeaconState) {
summaries, err := st.HistoricalSummaries()
require.NoError(t, err)
require.Equal(t, 1, len(summaries))
br, err := stateutil.ArraysRoot(st.BlockRoots(), fieldparams.BlockRootsLength)
require.NoError(t, err)
sr, err := stateutil.ArraysRoot(st.StateRoots(), fieldparams.StateRootsLength)
require.NoError(t, err)
b := &ethpb.HistoricalSummary{
BlockSummaryRoot: br[:],
StateSummaryRoot: sr[:],
}
require.DeepEqual(t, b, summaries[0])
hrs, err := st.HistoricalRoots()
require.NoError(t, err)
require.DeepEqual(t, hrs, [][]byte{})
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := epoch.ProcessHistoricalDataUpdate(tt.st())
require.NoError(t, err)
tt.verifier(got)
})
}
}

View File

@@ -35,6 +35,10 @@ func UpgradeToBellatrix(state state.BeaconState) (state.BeaconState, error) {
return nil, err
}
hrs, err := state.HistoricalRoots()
if err != nil {
return nil, err
}
s := &ethpb.BeaconStateBellatrix{
GenesisTime: state.GenesisTime(),
GenesisValidatorsRoot: state.GenesisValidatorsRoot(),
@@ -47,7 +51,7 @@ func UpgradeToBellatrix(state state.BeaconState) (state.BeaconState, error) {
LatestBlockHeader: state.LatestBlockHeader(),
BlockRoots: state.BlockRoots(),
StateRoots: state.StateRoots(),
HistoricalRoots: state.HistoricalRoots(),
HistoricalRoots: hrs,
Eth1Data: state.Eth1Data(),
Eth1DataVotes: state.Eth1DataVotes(),
Eth1DepositIndex: state.Eth1DepositIndex(),

View File

@@ -24,7 +24,11 @@ func TestUpgradeToBellatrix(t *testing.T) {
require.DeepSSZEqual(t, preForkState.LatestBlockHeader(), mSt.LatestBlockHeader())
require.DeepSSZEqual(t, preForkState.BlockRoots(), mSt.BlockRoots())
require.DeepSSZEqual(t, preForkState.StateRoots(), mSt.StateRoots())
require.DeepSSZEqual(t, preForkState.HistoricalRoots(), mSt.HistoricalRoots())
r1, err := preForkState.HistoricalRoots()
require.NoError(t, err)
r2, err := mSt.HistoricalRoots()
require.NoError(t, err)
require.DeepSSZEqual(t, r1, r2)
require.DeepSSZEqual(t, preForkState.Eth1Data(), mSt.Eth1Data())
require.DeepSSZEqual(t, preForkState.Eth1DataVotes(), mSt.Eth1DataVotes())
require.DeepSSZEqual(t, preForkState.Eth1DepositIndex(), mSt.Eth1DepositIndex())

View File

@@ -19,6 +19,9 @@ const (
// SyncCommitteeContributionReceived is sent after a sync committee contribution object has been received.
SyncCommitteeContributionReceived
// BLSToExecutionChangeReceived is sent after a BLS to execution change object has been received from gossip or rpc.
BLSToExecutionChangeReceived
)
// UnAggregatedAttReceivedData is the data sent with UnaggregatedAttReceived events.
@@ -44,3 +47,8 @@ type SyncCommitteeContributionReceivedData struct {
// Contribution is the sync committee contribution object.
Contribution *ethpb.SignedContributionAndProof
}
// BLSToExecutionChangeReceivedData is the data sent with BLSToExecutionChangeReceived events.
type BLSToExecutionChangeReceivedData struct {
Change *ethpb.SignedBLSToExecutionChange
}

View File

@@ -21,6 +21,32 @@ const DomainByteLength = 4
// failed to verify.
var ErrSigFailedToVerify = errors.New("signature did not verify")
// List of descriptions for different kinds of signatures
const (
// UnknownSignature represents all signatures other than below types
UnknownSignature string = "unknown signature"
// BlockSignature represents the block signature from block proposer
BlockSignature = "block signature"
// RandaoSignature represents randao specific signature
RandaoSignature = "randao signature"
// SelectionProof represents selection proof
SelectionProof = "selection proof"
// AggregatorSignature represents aggregator's signature
AggregatorSignature = "aggregator signature"
// AttestationSignature represents aggregated attestation signature
AttestationSignature = "attestation signature"
// BlsChangeSignature represents signature to BLSToExecutionChange
BlsChangeSignature = "blschange signature"
// SyncCommitteeSignature represents sync committee signature
SyncCommitteeSignature = "sync committee signature"
// SyncSelectionProof represents sync committee selection proof
SyncSelectionProof = "sync selection proof"
// ContributionSignature represents sync committee contributor's signature
ContributionSignature = "sync committee contribution signature"
// SyncAggregateSignature represents sync committee aggregator's signature
SyncAggregateSignature = "sync committee aggregator signature"
)
// 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.GenesisValidatorsRoot())
@@ -150,10 +176,12 @@ func BlockSignatureBatch(pub, signature, domain []byte, rootFunc func() ([32]byt
if err != nil {
return nil, errors.Wrap(err, "could not compute signing root")
}
desc := BlockSignature
return &bls.SignatureBatch{
Signatures: [][]byte{signature},
PublicKeys: []bls.PublicKey{publicKey},
Messages: [][32]byte{root},
Signatures: [][]byte{signature},
PublicKeys: []bls.PublicKey{publicKey},
Messages: [][32]byte{root},
Descriptions: []string{desc},
}, nil
}
@@ -178,7 +206,7 @@ func ComputeDomain(domainType [DomainByteLength]byte, forkVersion, genesisValida
if genesisValidatorsRoot == nil {
genesisValidatorsRoot = params.BeaconConfig().ZeroHash[:]
}
forkBytes := [ForkVersionByteLength]byte{}
var forkBytes [ForkVersionByteLength]byte
copy(forkBytes[:], forkVersion)
forkDataRoot, err := computeForkDataRoot(forkBytes[:], genesisValidatorsRoot)

View File

@@ -114,9 +114,9 @@ func TestSigningRoot_ComputeForkDigest(t *testing.T) {
func TestFuzzverifySigningRoot_10000(_ *testing.T) {
fuzzer := fuzz.NewWithSeed(0)
st := &ethpb.BeaconState{}
pubkey := [fieldparams.BLSPubkeyLength]byte{}
sig := [96]byte{}
domain := [4]byte{}
var pubkey [fieldparams.BLSPubkeyLength]byte
var sig [96]byte
var domain [4]byte
var p []byte
var s []byte
var d []byte

View File

@@ -6,21 +6,13 @@ go_library(
"log.go",
"skip_slot_cache.go",
"state.go",
"state-bellatrix.go",
"trailing_slot_state_cache.go",
"transition.go",
"transition_no_verify_sig.go",
],
importpath = "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/transition",
visibility = [
"//beacon-chain:__subpackages__",
"//runtime/interop:__pkg__",
"//testing/endtoend:__pkg__",
"//testing/spectest:__subpackages__",
"//testing/util:__pkg__",
"//tools/benchmark-files-gen:__pkg__",
"//tools/genesis-state-gen:__pkg__",
"//tools/pcli:__pkg__",
],
visibility = ["//visibility:public"],
deps = [
"//beacon-chain/cache:go_default_library",
"//beacon-chain/core/altair:go_default_library",
@@ -36,15 +28,19 @@ go_library(
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/state-native:go_default_library",
"//beacon-chain/state/stateutil:go_default_library",
"//config/features:go_default_library",
"//config/fieldparams:go_default_library",
"//config/params:go_default_library",
"//consensus-types/blocks:go_default_library",
"//consensus-types/interfaces:go_default_library",
"//consensus-types/primitives:go_default_library",
"//container/trie:go_default_library",
"//crypto/bls:go_default_library",
"//crypto/hash:go_default_library",
"//encoding/bytesutil:go_default_library",
"//math:go_default_library",
"//monitoring/tracing:go_default_library",
"//proto/engine/v1:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//runtime/version:go_default_library",
"@com_github_pkg_errors//:go_default_library",

View File

@@ -0,0 +1,279 @@
package transition
import (
"context"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/altair"
b "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state"
state_native "github.com/prysmaticlabs/prysm/v3/beacon-chain/state/state-native"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state/stateutil"
fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams"
"github.com/prysmaticlabs/prysm/v3/config/params"
"github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
)
// GenesisBeaconStateBellatrix gets called when MinGenesisActiveValidatorCount count of
// full deposits were made to the deposit contract and the ChainStart log gets emitted.
//
// Spec pseudocode definition:
//
// def initialize_beacon_state_from_eth1(eth1_block_hash: Bytes32,
// eth1_timestamp: uint64,
// deposits: Sequence[Deposit]) -> BeaconState:
// fork = Fork(
// previous_version=GENESIS_FORK_VERSION,
// current_version=GENESIS_FORK_VERSION,
// epoch=GENESIS_EPOCH,
// )
// state = BeaconState(
// genesis_time=eth1_timestamp + GENESIS_DELAY,
// fork=fork,
// eth1_data=Eth1Data(block_hash=eth1_block_hash, deposit_count=uint64(len(deposits))),
// latest_block_header=BeaconBlockHeader(body_root=hash_tree_root(BeaconBlockBody())),
// randao_mixes=[eth1_block_hash] * EPOCHS_PER_HISTORICAL_VECTOR, # Seed RANDAO with Eth1 entropy
// )
//
// # Process deposits
// leaves = list(map(lambda deposit: deposit.data, deposits))
// for index, deposit in enumerate(deposits):
// deposit_data_list = List[DepositData, 2**DEPOSIT_CONTRACT_TREE_DEPTH](*leaves[:index + 1])
// state.eth1_data.deposit_root = hash_tree_root(deposit_data_list)
// process_deposit(state, deposit)
//
// # Process activations
// for index, validator in enumerate(state.validators):
// balance = state.balances[index]
// validator.effective_balance = min(balance - balance % EFFECTIVE_BALANCE_INCREMENT, MAX_EFFECTIVE_BALANCE)
// if validator.effective_balance == MAX_EFFECTIVE_BALANCE:
// validator.activation_eligibility_epoch = GENESIS_EPOCH
// validator.activation_epoch = GENESIS_EPOCH
//
// # Set genesis validators root for domain separation and chain versioning
// state.genesis_validators_root = hash_tree_root(state.validators)
//
// return state
//
// This method differs from the spec so as to process deposits beforehand instead of the end of the function.
func GenesisBeaconStateBellatrix(ctx context.Context, deposits []*ethpb.Deposit, genesisTime uint64, eth1Data *ethpb.Eth1Data, ep *enginev1.ExecutionPayload) (state.BeaconState, error) {
st, err := EmptyGenesisStateBellatrix()
if err != nil {
return nil, err
}
// Process initial deposits.
st, err = helpers.UpdateGenesisEth1Data(st, deposits, eth1Data)
if err != nil {
return nil, err
}
st, err = b.ProcessPreGenesisDeposits(ctx, st, deposits)
if err != nil {
return nil, errors.Wrap(err, "could not process validator deposits")
}
// After deposits have been processed, overwrite eth1data to what is passed in. This allows us to "pre-mine" validators
// without the deposit root and count mismatching the real deposit contract.
if err := st.SetEth1Data(eth1Data); err != nil {
return nil, err
}
if err := st.SetEth1DepositIndex(eth1Data.DepositCount); err != nil {
return nil, err
}
return OptimizedGenesisBeaconStateBellatrix(genesisTime, st, st.Eth1Data(), ep)
}
// OptimizedGenesisBeaconState is used to create a state that has already processed deposits. This is to efficiently
// create a mainnet state at chainstart.
func OptimizedGenesisBeaconStateBellatrix(genesisTime uint64, preState state.BeaconState, eth1Data *ethpb.Eth1Data, ep *enginev1.ExecutionPayload) (state.BeaconState, error) {
if eth1Data == nil {
return nil, errors.New("no eth1data provided for genesis state")
}
randaoMixes := make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector)
for i := 0; i < len(randaoMixes); i++ {
h := make([]byte, 32)
copy(h, eth1Data.BlockHash)
randaoMixes[i] = h
}
zeroHash := params.BeaconConfig().ZeroHash[:]
activeIndexRoots := make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector)
for i := 0; i < len(activeIndexRoots); i++ {
activeIndexRoots[i] = zeroHash
}
blockRoots := make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot)
for i := 0; i < len(blockRoots); i++ {
blockRoots[i] = zeroHash
}
stateRoots := make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot)
for i := 0; i < len(stateRoots); i++ {
stateRoots[i] = zeroHash
}
slashings := make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector)
genesisValidatorsRoot, err := stateutil.ValidatorRegistryRoot(preState.Validators())
if err != nil {
return nil, errors.Wrapf(err, "could not hash tree root genesis validators %v", err)
}
scores, err := preState.InactivityScores()
if err != nil {
return nil, err
}
scoresMissing := len(preState.Validators()) - len(scores)
if scoresMissing > 0 {
for i := 0; i < scoresMissing; i++ {
scores = append(scores, 0)
}
}
wep, err := blocks.WrappedExecutionPayload(ep)
if err != nil {
return nil, err
}
eph, err := blocks.PayloadToHeader(wep)
if err != nil {
return nil, err
}
st := &ethpb.BeaconStateBellatrix{
// Misc fields.
Slot: 0,
GenesisTime: genesisTime,
GenesisValidatorsRoot: genesisValidatorsRoot[:],
Fork: &ethpb.Fork{
PreviousVersion: params.BeaconConfig().AltairForkVersion,
CurrentVersion: params.BeaconConfig().BellatrixForkVersion,
Epoch: 0,
},
// Validator registry fields.
Validators: preState.Validators(),
Balances: preState.Balances(),
// Randomness and committees.
RandaoMixes: randaoMixes,
// Finality.
PreviousJustifiedCheckpoint: &ethpb.Checkpoint{
Epoch: 0,
Root: params.BeaconConfig().ZeroHash[:],
},
CurrentJustifiedCheckpoint: &ethpb.Checkpoint{
Epoch: 0,
Root: params.BeaconConfig().ZeroHash[:],
},
JustificationBits: []byte{0},
FinalizedCheckpoint: &ethpb.Checkpoint{
Epoch: 0,
Root: params.BeaconConfig().ZeroHash[:],
},
HistoricalRoots: [][]byte{},
BlockRoots: blockRoots,
StateRoots: stateRoots,
Slashings: slashings,
// Eth1 data.
Eth1Data: eth1Data,
Eth1DataVotes: []*ethpb.Eth1Data{},
Eth1DepositIndex: preState.Eth1DepositIndex(),
LatestExecutionPayloadHeader: eph,
InactivityScores: scores,
}
bodyRoot, err := (&ethpb.BeaconBlockBodyBellatrix{
RandaoReveal: make([]byte, 96),
Eth1Data: &ethpb.Eth1Data{
DepositRoot: make([]byte, 32),
BlockHash: make([]byte, 32),
},
Graffiti: make([]byte, 32),
SyncAggregate: &ethpb.SyncAggregate{
SyncCommitteeBits: make([]byte, fieldparams.SyncCommitteeLength/8),
SyncCommitteeSignature: make([]byte, fieldparams.BLSSignatureLength),
},
ExecutionPayload: &enginev1.ExecutionPayload{
ParentHash: make([]byte, 32),
FeeRecipient: make([]byte, 20),
StateRoot: make([]byte, 32),
ReceiptsRoot: make([]byte, 32),
LogsBloom: make([]byte, 256),
PrevRandao: make([]byte, 32),
BaseFeePerGas: make([]byte, 32),
BlockHash: make([]byte, 32),
Transactions: make([][]byte, 0),
},
}).HashTreeRoot()
if err != nil {
return nil, errors.Wrap(err, "could not hash tree root empty block body")
}
st.LatestBlockHeader = &ethpb.BeaconBlockHeader{
ParentRoot: zeroHash,
StateRoot: zeroHash,
BodyRoot: bodyRoot[:],
}
ist, err := state_native.InitializeFromProtoBellatrix(st)
if err != nil {
return nil, err
}
sc, err := altair.NextSyncCommittee(context.Background(), ist)
if err != nil {
return nil, err
}
if err := ist.SetNextSyncCommittee(sc); err != nil {
return nil, err
}
if err := ist.SetCurrentSyncCommittee(sc); err != nil {
return nil, err
}
return ist, nil
}
// EmptyGenesisState returns an empty beacon state object.
func EmptyGenesisStateBellatrix() (state.BeaconState, error) {
st := &ethpb.BeaconStateBellatrix{
// Misc fields.
Slot: 0,
Fork: &ethpb.Fork{
PreviousVersion: params.BeaconConfig().AltairForkVersion,
CurrentVersion: params.BeaconConfig().BellatrixForkVersion,
Epoch: 0,
},
// Validator registry fields.
Validators: []*ethpb.Validator{},
Balances: []uint64{},
JustificationBits: []byte{0},
HistoricalRoots: [][]byte{},
// Eth1 data.
Eth1Data: &ethpb.Eth1Data{},
Eth1DataVotes: []*ethpb.Eth1Data{},
Eth1DepositIndex: 0,
LatestExecutionPayloadHeader: &enginev1.ExecutionPayloadHeader{
ParentHash: make([]byte, 32),
FeeRecipient: make([]byte, 20),
StateRoot: make([]byte, 32),
ReceiptsRoot: make([]byte, 32),
LogsBloom: make([]byte, 256),
PrevRandao: make([]byte, 32),
BaseFeePerGas: make([]byte, 32),
BlockHash: make([]byte, 32),
TransactionsRoot: make([]byte, 32),
},
}
return state_native.InitializeFromProtoBellatrix(st)
}

View File

@@ -10,6 +10,7 @@ import (
state_native "github.com/prysmaticlabs/prysm/v3/beacon-chain/state/state-native"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state/stateutil"
"github.com/prysmaticlabs/prysm/v3/config/params"
"github.com/prysmaticlabs/prysm/v3/container/trie"
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
)
@@ -75,6 +76,43 @@ func GenesisBeaconState(ctx context.Context, deposits []*ethpb.Deposit, genesisT
return OptimizedGenesisBeaconState(genesisTime, st, st.Eth1Data())
}
// PreminedGenesisBeaconState works almost exactly like GenesisBeaconState, except that it assumes that genesis deposits
// are not represented in the deposit contract and are only found in the genesis state validator registry. In order
// to ensure the deposit root and count match the empty deposit contract deployed in a testnet genesis block, the root
// of an empty deposit trie is computed and used as Eth1Data.deposit_root, and the deposit count is set to 0.
func PreminedGenesisBeaconState(ctx context.Context, deposits []*ethpb.Deposit, genesisTime uint64, eth1Data *ethpb.Eth1Data) (state.BeaconState, error) {
st, err := EmptyGenesisState()
if err != nil {
return nil, err
}
// Process initial deposits.
st, err = helpers.UpdateGenesisEth1Data(st, deposits, eth1Data)
if err != nil {
return nil, err
}
st, err = b.ProcessPreGenesisDeposits(ctx, st, deposits)
if err != nil {
return nil, errors.Wrap(err, "could not process validator deposits")
}
t, err := trie.NewTrie(params.BeaconConfig().DepositContractTreeDepth)
if err != nil {
return nil, err
}
dr, err := t.HashTreeRoot()
if err != nil {
return nil, err
}
if err := st.SetEth1Data(&ethpb.Eth1Data{DepositRoot: dr[:], BlockHash: eth1Data.BlockHash}); err != nil {
return nil, err
}
if err := st.SetEth1DepositIndex(0); err != nil {
return nil, err
}
return OptimizedGenesisBeaconState(genesisTime, st, st.Eth1Data())
}
// OptimizedGenesisBeaconState is used to create a state that has already processed deposits. This is to efficiently
// create a mainnet state at chainstart.
func OptimizedGenesisBeaconState(genesisTime uint64, preState state.BeaconState, eth1Data *ethpb.Eth1Data) (state.BeaconState, error) {

View File

@@ -17,6 +17,7 @@ import (
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/execution"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/time"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state"
"github.com/prysmaticlabs/prysm/v3/config/features"
"github.com/prysmaticlabs/prysm/v3/config/params"
"github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces"
@@ -66,7 +67,13 @@ func ExecuteStateTransition(
if err != nil {
return nil, errors.Wrap(err, "could not execute state transition")
}
valid, err := set.Verify()
var valid bool
if features.Get().EnableVerboseSigVerification {
valid, err = set.VerifyVerbosely()
} else {
valid, err = set.Verify()
}
if err != nil {
return nil, errors.Wrap(err, "could not batch verify signature")
}
@@ -251,20 +258,19 @@ func ProcessSlots(ctx context.Context, state state.BeaconState, slot types.Slot)
return nil, errors.Wrap(err, "could not process slot")
}
if time.CanProcessEpoch(state) {
switch state.Version() {
case version.Phase0:
if state.Version() == version.Phase0 {
state, err = ProcessEpochPrecompute(ctx, state)
if err != nil {
tracing.AnnotateError(span, err)
return nil, errors.Wrap(err, "could not process epoch with optimizations")
}
case version.Altair, version.Bellatrix, version.Capella:
} else if state.Version() >= version.Altair {
state, err = altair.ProcessEpoch(ctx, state)
if err != nil {
tracing.AnnotateError(span, err)
return nil, errors.Wrap(err, "could not process epoch")
}
default:
} else {
return nil, errors.New("beacon state should have a version")
}
}

View File

@@ -53,7 +53,7 @@ func ExecuteStateTransitionNoVerifyAnySig(
return nil, nil, errors.New("nil block")
}
ctx, span := trace.StartSpan(ctx, "core.state.ExecuteStateTransitionNoVerifyAttSigs")
ctx, span := trace.StartSpan(ctx, "core.state.ExecuteStateTransitionNoVerifyAnySig")
defer span.End()
var err error
@@ -205,7 +205,7 @@ func ProcessBlockNoVerifyAnySig(
if err != nil {
return nil, nil, errors.Wrap(err, "could not get BLSToExecutionChanges")
}
cSet, err := b.BLSChangesSignatureBatch(ctx, st, changes)
cSet, err := b.BLSChangesSignatureBatch(st, changes)
if err != nil {
return nil, nil, errors.Wrap(err, "could not get BLSToExecutionChanges signatures")
}

View File

@@ -151,6 +151,18 @@ func TestProcessBlockNoVerifyAnySigAltair_OK(t *testing.T) {
require.Equal(t, true, verified, "Could not verify signature set")
}
func TestProcessBlockNoVerify_SigSetContainsDescriptions(t *testing.T) {
beaconState, block, _, _, _ := createFullBlockWithOperations(t)
wsb, err := blocks.NewSignedBeaconBlock(block)
require.NoError(t, err)
set, _, err := transition.ProcessBlockNoVerifyAnySig(context.Background(), beaconState, wsb)
require.NoError(t, err)
assert.Equal(t, len(set.Signatures), len(set.Descriptions), "Signatures and descriptions do not match up")
assert.Equal(t, "block signature", set.Descriptions[0])
assert.Equal(t, "randao signature", set.Descriptions[1])
assert.Equal(t, "attestation signature", set.Descriptions[2])
}
func TestProcessOperationsNoVerifyAttsSigs_OK(t *testing.T) {
beaconState, block := createFullAltairBlockWithOperations(t)
wsb, err := blocks.NewSignedBeaconBlock(block)

View File

@@ -212,7 +212,7 @@ func createFullBlockWithOperations(t *testing.T) (state.BeaconState,
err = beaconState.SetSlashings(make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector))
require.NoError(t, err)
cp := beaconState.CurrentJustifiedCheckpoint()
mockRoot := [32]byte{}
var mockRoot [32]byte
copy(mockRoot[:], "hello-world")
cp.Root = mockRoot[:]
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(cp))

View File

@@ -328,8 +328,8 @@ func (s *Store) SaveBlocks(ctx context.Context, blks []interfaces.SignedBeaconBl
func (s *Store) SaveHeadBlockRoot(ctx context.Context, blockRoot [32]byte) error {
ctx, span := trace.StartSpan(ctx, "BeaconDB.SaveHeadBlockRoot")
defer span.End()
hasStateSummary := s.HasStateSummary(ctx, blockRoot)
return s.db.Update(func(tx *bolt.Tx) error {
hasStateSummary := s.hasStateSummaryBytes(tx, blockRoot)
hasStateInDB := tx.Bucket(stateBucket).Get(blockRoot[:]) != nil
if !(hasStateInDB || hasStateSummary) {
return errors.New("no state or state summary found with head block root")

View File

@@ -98,7 +98,7 @@ func TestStore_SaveBackfillBlockRoot(t *testing.T) {
_, err := db.BackfillBlockRoot(ctx)
require.ErrorIs(t, err, ErrNotFoundBackfillBlockRoot)
expected := [32]byte{}
var expected [32]byte
copy(expected[:], []byte{0x23})
err = db.SaveBackfillBlockRoot(ctx, expected)
require.NoError(t, err)

View File

@@ -59,9 +59,9 @@ func (s *Store) SaveJustifiedCheckpoint(ctx context.Context, checkpoint *ethpb.C
if err != nil {
return err
}
hasStateSummary := s.HasStateSummary(ctx, bytesutil.ToBytes32(checkpoint.Root))
return s.db.Update(func(tx *bolt.Tx) error {
bucket := tx.Bucket(checkpointBucket)
hasStateSummary := s.hasStateSummaryBytes(tx, bytesutil.ToBytes32(checkpoint.Root))
hasStateInDB := tx.Bucket(stateBucket).Get(checkpoint.Root) != nil
if !(hasStateInDB || hasStateSummary) {
log.Warnf("Recovering state summary for justified root: %#x", bytesutil.Trunc(checkpoint.Root))
@@ -82,9 +82,9 @@ func (s *Store) SaveFinalizedCheckpoint(ctx context.Context, checkpoint *ethpb.C
if err != nil {
return err
}
hasStateSummary := s.HasStateSummary(ctx, bytesutil.ToBytes32(checkpoint.Root))
return s.db.Update(func(tx *bolt.Tx) error {
bucket := tx.Bucket(checkpointBucket)
hasStateSummary := s.hasStateSummaryBytes(tx, bytesutil.ToBytes32(checkpoint.Root))
hasStateInDB := tx.Bucket(stateBucket).Get(checkpoint.Root) != nil
if !(hasStateInDB || hasStateSummary) {
log.Warnf("Recovering state summary for finalized root: %#x", bytesutil.Trunc(checkpoint.Root))

View File

@@ -1,34 +1,25 @@
package kv
import (
"bytes"
"context"
"fmt"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/blocks"
dbIface "github.com/prysmaticlabs/prysm/v3/beacon-chain/db/iface"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state"
state_native "github.com/prysmaticlabs/prysm/v3/beacon-chain/state/state-native"
"github.com/prysmaticlabs/prysm/v3/config/params"
consensusblocks "github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v3/encoding/ssz/detect"
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
)
// SaveGenesisData bootstraps the beaconDB with a given genesis state.
func (s *Store) SaveGenesisData(ctx context.Context, genesisState state.BeaconState) error {
stateRoot, err := genesisState.HashTreeRoot(ctx)
if err != nil {
return err
}
genesisBlk := blocks.NewGenesisBlock(stateRoot[:])
genesisBlkRoot, err := genesisBlk.Block.HashTreeRoot()
wsb, err := blocks.NewGenesisBlockForState(ctx, genesisState)
if err != nil {
return errors.Wrap(err, "could not get genesis block root")
}
wsb, err := consensusblocks.NewSignedBeaconBlock(genesisBlk)
genesisBlkRoot, err := wsb.Block().HashTreeRoot()
if err != nil {
return errors.Wrap(err, "could not wrap genesis block")
return errors.Wrap(err, "could not get genesis block root")
}
if err := s.SaveBlock(ctx, wsb); err != nil {
return errors.Wrap(err, "could not save genesis block")
@@ -54,11 +45,11 @@ func (s *Store) SaveGenesisData(ctx context.Context, genesisState state.BeaconSt
// LoadGenesis loads a genesis state from a ssz-serialized byte slice, if no genesis exists already.
func (s *Store) LoadGenesis(ctx context.Context, sb []byte) error {
st := &ethpb.BeaconState{}
if err := st.UnmarshalSSZ(sb); err != nil {
vu, err := detect.FromState(sb)
if err != nil {
return err
}
gs, err := state_native.InitializeFromProtoUnsafePhase0(st)
gs, err := vu.UnmarshalBeaconState(sb)
if err != nil {
return err
}
@@ -83,10 +74,6 @@ func (s *Store) LoadGenesis(ctx context.Context, sb []byte) error {
return dbIface.ErrExistingGenesisState
}
if !bytes.Equal(gs.Fork().CurrentVersion, params.BeaconConfig().GenesisForkVersion) {
return fmt.Errorf("loaded genesis fork version (%#x) does not match config genesis "+
"fork version (%#x)", gs.Fork().CurrentVersion, params.BeaconConfig().GenesisForkVersion)
}
return s.SaveGenesisData(ctx, gs)
}

View File

@@ -2,12 +2,14 @@ package kv
import (
"context"
"encoding/hex"
"os"
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/db/iface"
"github.com/prysmaticlabs/prysm/v3/config/params"
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/v3/testing/assert"
"github.com/prysmaticlabs/prysm/v3/testing/require"
"github.com/prysmaticlabs/prysm/v3/testing/util"
@@ -48,6 +50,37 @@ func testGenesisDataSaved(t *testing.T, db iface.Database) {
require.Equal(t, gbHTR, headHTR, "head block does not match genesis block")
}
func TestLoadCapellaFromFile(t *testing.T) {
cfg, err := params.ByName(params.MainnetName)
require.NoError(t, err)
// This state fixture is from a hive testnet, `0a` is the suffix they are using in their fork versions.
suffix, err := hex.DecodeString("0a")
require.NoError(t, err)
require.Equal(t, 1, len(suffix))
reversioned := cfg.Copy()
params.FillTestVersions(reversioned, suffix[0])
reversioned.CapellaForkEpoch = 0
require.Equal(t, [4]byte{3, 0, 0, 10}, bytesutil.ToBytes4(reversioned.CapellaForkVersion))
reversioned.ConfigName = "capella-genesis-test"
undo, err := params.SetActiveWithUndo(reversioned)
require.NoError(t, err)
defer func() {
require.NoError(t, undo())
}()
fp := "testdata/capella_genesis.ssz"
rfp, err := bazel.Runfile(fp)
if err == nil {
fp = rfp
}
sb, err := os.ReadFile(fp)
require.NoError(t, err)
db := setupDB(t)
require.NoError(t, db.LoadGenesis(context.Background(), sb))
testGenesisDataSaved(t, db)
}
func TestLoadGenesisFromFile(t *testing.T) {
// for this test to work, we need the active config to have these properties:
// - fork version schedule that matches mainnnet.genesis.ssz
@@ -57,7 +90,7 @@ func TestLoadGenesisFromFile(t *testing.T) {
// uses the mainnet fork schedule. construct the differently named mainnet config and set it active.
// finally, revert all this at the end of the test.
// first get the real mainnet out of the way by overwriting it schedule.
// first get the real mainnet out of the way by overwriting its schedule.
cfg, err := params.ByName(params.MainnetName)
require.NoError(t, err)
cfg = cfg.Copy()
@@ -106,7 +139,7 @@ func TestLoadGenesisFromFile_mismatchedForkVersion(t *testing.T) {
// Loading a genesis with the wrong fork version as beacon config should throw an error.
db := setupDB(t)
assert.ErrorContains(t, "does not match config genesis fork version", db.LoadGenesis(context.Background(), sb))
assert.ErrorContains(t, "not found in any known fork choice schedule", db.LoadGenesis(context.Background(), sb))
}
func TestEnsureEmbeddedGenesis(t *testing.T) {

View File

@@ -67,9 +67,14 @@ func (s *Store) HasStateSummary(ctx context.Context, blockRoot [32]byte) bool {
ctx, span := trace.StartSpan(ctx, "BeaconDB.HasStateSummary")
defer span.End()
if s.stateSummaryCache.has(blockRoot) {
return true
}
var hasSummary bool
if err := s.db.View(func(tx *bolt.Tx) error {
hasSummary = s.hasStateSummaryBytes(tx, blockRoot)
enc := tx.Bucket(stateSummaryBucket).Get(blockRoot[:])
hasSummary = len(enc) > 0
return nil
}); err != nil {
return false
@@ -77,14 +82,6 @@ func (s *Store) HasStateSummary(ctx context.Context, blockRoot [32]byte) bool {
return hasSummary
}
func (s *Store) hasStateSummaryBytes(tx *bolt.Tx, blockRoot [32]byte) bool {
if s.stateSummaryCache.has(blockRoot) {
return true
}
enc := tx.Bucket(stateSummaryBucket).Get(blockRoot[:])
return len(enc) > 0
}
// This saves all cached state summary objects to DB, and clears up the cache.
func (s *Store) saveCachedStateSummariesDB(ctx context.Context) error {
summaries := s.stateSummaryCache.getAll()

Binary file not shown.

View File

@@ -38,9 +38,9 @@ func (s *Store) SaveLastValidatedCheckpoint(ctx context.Context, checkpoint *eth
if err != nil {
return err
}
hasStateSummary := s.HasStateSummary(ctx, bytesutil.ToBytes32(checkpoint.Root))
return s.db.Update(func(tx *bolt.Tx) error {
bucket := tx.Bucket(checkpointBucket)
hasStateSummary := s.hasStateSummaryBytes(tx, bytesutil.ToBytes32(checkpoint.Root))
hasStateInDB := tx.Bucket(stateBucket).Get(checkpoint.Root) != nil
if !(hasStateInDB || hasStateSummary) {
log.Warnf("Recovering state summary for last validated root: %#x", bytesutil.Trunc(checkpoint.Root))

View File

@@ -51,6 +51,26 @@ func TestStore_LastValidatedCheckpoint_Recover(t *testing.T) {
assert.Equal(t, true, proto.Equal(cp, retrieved), "Wanted %v, received %v", cp, retrieved)
}
func BenchmarkStore_SaveLastValidatedCheckpoint(b *testing.B) {
db := setupDB(b)
ctx := context.Background()
root := bytesutil.ToBytes32([]byte{'A'})
cp := &ethpb.Checkpoint{
Epoch: 10,
Root: root[:],
}
st, err := util.NewBeaconState()
require.NoError(b, err)
require.NoError(b, st.SetSlot(1))
require.NoError(b, db.SaveState(ctx, st, root))
db.stateSummaryCache.clear()
b.ResetTimer()
for i := 0; i < b.N; i++ {
require.NoError(b, db.SaveLastValidatedCheckpoint(ctx, cp))
}
}
func TestStore_LastValidatedCheckpoint_DefaultIsFinalized(t *testing.T) {
db := setupDB(t)
ctx := context.Background()

View File

@@ -41,6 +41,8 @@ go_library(
"//config/params:go_default_library",
"//consensus-types/blocks:go_default_library",
"//consensus-types/interfaces:go_default_library",
"//consensus-types/payload-attribute:go_default_library",
"//consensus-types/primitives:go_default_library",
"//container/trie:go_default_library",
"//contracts/deposit:go_default_library",
"//crypto/hash:go_default_library",
@@ -52,6 +54,7 @@ go_library(
"//network/authorization:go_default_library",
"//proto/engine/v1:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//runtime/version:go_default_library",
"//time:go_default_library",
"//time/slots:go_default_library",
"@com_github_ethereum_go_ethereum//:go_default_library",
@@ -108,6 +111,7 @@ go_test(
"//config/params:go_default_library",
"//consensus-types/blocks:go_default_library",
"//consensus-types/interfaces:go_default_library",
"//consensus-types/payload-attribute:go_default_library",
"//consensus-types/primitives:go_default_library",
"//container/trie:go_default_library",
"//contracts/deposit:go_default_library",
@@ -118,6 +122,7 @@ go_test(
"//network/authorization:go_default_library",
"//proto/engine/v1:go_default_library",
"//proto/prysm/v1alpha1: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

@@ -19,8 +19,12 @@ import (
"github.com/prysmaticlabs/prysm/v3/config/params"
"github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces"
payloadattribute "github.com/prysmaticlabs/prysm/v3/consensus-types/payload-attribute"
prysmType "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
pb "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
"github.com/prysmaticlabs/prysm/v3/runtime/version"
"github.com/prysmaticlabs/prysm/v3/time/slots"
"github.com/sirupsen/logrus"
"go.opencensus.io/trace"
)
@@ -28,10 +32,16 @@ import (
const (
// NewPayloadMethod v1 request string for JSON-RPC.
NewPayloadMethod = "engine_newPayloadV1"
// NewPayloadMethodV2 v2 request string for JSON-RPC.
NewPayloadMethodV2 = "engine_newPayloadV2"
// ForkchoiceUpdatedMethod v1 request string for JSON-RPC.
ForkchoiceUpdatedMethod = "engine_forkchoiceUpdatedV1"
// ForkchoiceUpdatedMethodV2 v2 request string for JSON-RPC.
ForkchoiceUpdatedMethodV2 = "engine_forkchoiceUpdatedV2"
// GetPayloadMethod v1 request string for JSON-RPC.
GetPayloadMethod = "engine_getPayloadV1"
// GetPayloadMethodV2 v2 request string for JSON-RPC.
GetPayloadMethodV2 = "engine_getPayloadV2"
// ExchangeTransitionConfigurationMethod v1 request string for JSON-RPC.
ExchangeTransitionConfigurationMethod = "engine_exchangeTransitionConfigurationV1"
// ExecutionBlockByHashMethod request string for JSON-RPC.
@@ -53,7 +63,7 @@ type ForkchoiceUpdatedResponse struct {
// block with an execution payload from a signed beacon block and a connection
// to an execution client's engine API.
type ExecutionPayloadReconstructor interface {
ReconstructFullBellatrixBlock(
ReconstructFullBlock(
ctx context.Context, blindedBlock interfaces.SignedBeaconBlock,
) (interfaces.SignedBeaconBlock, error)
ReconstructFullBellatrixBlockBatch(
@@ -66,9 +76,9 @@ type ExecutionPayloadReconstructor interface {
type EngineCaller interface {
NewPayload(ctx context.Context, payload interfaces.ExecutionData) ([]byte, error)
ForkchoiceUpdated(
ctx context.Context, state *pb.ForkchoiceState, attrs *pb.PayloadAttributes,
ctx context.Context, state *pb.ForkchoiceState, attrs payloadattribute.Attributer,
) (*pb.PayloadIDBytes, []byte, error)
GetPayload(ctx context.Context, payloadId [8]byte) (*pb.ExecutionPayload, error)
GetPayload(ctx context.Context, payloadId [8]byte, slot prysmType.Slot) (interfaces.ExecutionData, error)
ExchangeTransitionConfiguration(
ctx context.Context, cfg *pb.TransitionConfiguration,
) error
@@ -76,7 +86,9 @@ type EngineCaller interface {
GetTerminalBlockHash(ctx context.Context, transitionTime uint64) ([]byte, bool, error)
}
// NewPayload calls the engine_newPayloadV1 method via JSON-RPC.
var EmptyBlockHash = errors.New("Block hash is empty 0x0000...")
// NewPayload calls the engine_newPayloadVX method via JSON-RPC.
func (s *Service) NewPayload(ctx context.Context, payload interfaces.ExecutionData) ([]byte, error) {
ctx, span := trace.StartSpan(ctx, "powchain.engine-api-client.NewPayload")
defer span.End()
@@ -89,13 +101,28 @@ func (s *Service) NewPayload(ctx context.Context, payload interfaces.ExecutionDa
ctx, cancel := context.WithDeadline(ctx, d)
defer cancel()
result := &pb.PayloadStatus{}
payloadPb, ok := payload.Proto().(*pb.ExecutionPayload)
if !ok {
return nil, errors.New("execution data must be an execution payload")
}
err := s.rpcClient.CallContext(ctx, result, NewPayloadMethod, payloadPb)
if err != nil {
return nil, handleRPCError(err)
switch payload.Proto().(type) {
case *pb.ExecutionPayload:
payloadPb, ok := payload.Proto().(*pb.ExecutionPayload)
if !ok {
return nil, errors.New("execution data must be a Bellatrix or Capella execution payload")
}
err := s.rpcClient.CallContext(ctx, result, NewPayloadMethod, payloadPb)
if err != nil {
return nil, handleRPCError(err)
}
case *pb.ExecutionPayloadCapella:
payloadPb, ok := payload.Proto().(*pb.ExecutionPayloadCapella)
if !ok {
return nil, errors.New("execution data must be a Capella execution payload")
}
err := s.rpcClient.CallContext(ctx, result, NewPayloadMethodV2, payloadPb)
if err != nil {
return nil, handleRPCError(err)
}
default:
return nil, errors.New("unknown execution data type")
}
switch result.Status {
@@ -114,7 +141,7 @@ func (s *Service) NewPayload(ctx context.Context, payload interfaces.ExecutionDa
// ForkchoiceUpdated calls the engine_forkchoiceUpdatedV1 method via JSON-RPC.
func (s *Service) ForkchoiceUpdated(
ctx context.Context, state *pb.ForkchoiceState, attrs *pb.PayloadAttributes,
ctx context.Context, state *pb.ForkchoiceState, attrs payloadattribute.Attributer,
) (*pb.PayloadIDBytes, []byte, error) {
ctx, span := trace.StartSpan(ctx, "powchain.engine-api-client.ForkchoiceUpdated")
defer span.End()
@@ -127,9 +154,31 @@ func (s *Service) ForkchoiceUpdated(
ctx, cancel := context.WithDeadline(ctx, d)
defer cancel()
result := &ForkchoiceUpdatedResponse{}
err := s.rpcClient.CallContext(ctx, result, ForkchoiceUpdatedMethod, state, attrs)
if err != nil {
return nil, nil, handleRPCError(err)
if attrs == nil {
return nil, nil, errors.New("nil payload attributer")
}
switch attrs.Version() {
case version.Bellatrix:
a, err := attrs.PbV1()
if err != nil {
return nil, nil, err
}
err = s.rpcClient.CallContext(ctx, result, ForkchoiceUpdatedMethod, state, a)
if err != nil {
return nil, nil, handleRPCError(err)
}
case version.Capella:
a, err := attrs.PbV2()
if err != nil {
return nil, nil, err
}
err = s.rpcClient.CallContext(ctx, result, ForkchoiceUpdatedMethodV2, state, a)
if err != nil {
return nil, nil, handleRPCError(err)
}
default:
return nil, nil, fmt.Errorf("unknown payload attribute version: %v", attrs.Version())
}
if result.Status == nil {
@@ -148,8 +197,8 @@ func (s *Service) ForkchoiceUpdated(
}
}
// GetPayload calls the engine_getPayloadV1 method via JSON-RPC.
func (s *Service) GetPayload(ctx context.Context, payloadId [8]byte) (*pb.ExecutionPayload, error) {
// GetPayload calls the engine_getPayloadVX method via JSON-RPC.
func (s *Service) GetPayload(ctx context.Context, payloadId [8]byte, slot prysmType.Slot) (interfaces.ExecutionData, error) {
ctx, span := trace.StartSpan(ctx, "powchain.engine-api-client.GetPayload")
defer span.End()
start := time.Now()
@@ -160,9 +209,22 @@ func (s *Service) GetPayload(ctx context.Context, payloadId [8]byte) (*pb.Execut
d := time.Now().Add(defaultEngineTimeout)
ctx, cancel := context.WithDeadline(ctx, d)
defer cancel()
if slots.ToEpoch(slot) >= params.BeaconConfig().CapellaForkEpoch {
result := &pb.ExecutionPayloadCapella{}
err := s.rpcClient.CallContext(ctx, result, GetPayloadMethodV2, pb.PayloadIDBytes(payloadId))
if err != nil {
return nil, handleRPCError(err)
}
return blocks.WrappedExecutionPayloadCapella(result)
}
result := &pb.ExecutionPayload{}
err := s.rpcClient.CallContext(ctx, result, GetPayloadMethod, pb.PayloadIDBytes(payloadId))
return result, handleRPCError(err)
if err != nil {
return nil, handleRPCError(err)
}
return blocks.WrappedExecutionPayload(result)
}
// ExchangeTransitionConfiguration calls the engine_exchangeTransitionConfigurationV1 method via JSON-RPC.
@@ -377,9 +439,9 @@ func (s *Service) HeaderByNumber(ctx context.Context, number *big.Int) (*types.H
return hdr, err
}
// ReconstructFullBellatrixBlock takes in a blinded beacon block and reconstructs
// ReconstructFullBlock takes in a blinded beacon block and reconstructs
// a beacon block with a full execution payload via the engine API.
func (s *Service) ReconstructFullBellatrixBlock(
func (s *Service) ReconstructFullBlock(
ctx context.Context, blindedBlock interfaces.SignedBeaconBlock,
) (interfaces.SignedBeaconBlock, error) {
if err := blocks.BeaconBlockIsNil(blindedBlock); err != nil {
@@ -411,11 +473,16 @@ func (s *Service) ReconstructFullBellatrixBlock(
if executionBlock == nil {
return nil, fmt.Errorf("received nil execution block for request by hash %#x", executionBlockHash)
}
if bytes.Equal(executionBlock.Hash.Bytes(), []byte{}) {
return nil, EmptyBlockHash
}
executionBlock.Version = blindedBlock.Version()
payload, err := fullPayloadFromExecutionBlock(header, executionBlock)
if err != nil {
return nil, err
}
fullBlock, err := blocks.BuildSignedBeaconBlockFromExecutionPayload(blindedBlock, payload)
fullBlock, err := blocks.BuildSignedBeaconBlockFromExecutionPayload(blindedBlock, payload.Proto())
if err != nil {
return nil, err
}
@@ -478,7 +545,7 @@ func (s *Service) ReconstructFullBellatrixBlockBatch(
if err != nil {
return nil, err
}
fullBlock, err := blocks.BuildSignedBeaconBlockFromExecutionPayload(blindedBlocks[realIdx], payload)
fullBlock, err := blocks.BuildSignedBeaconBlockFromExecutionPayload(blindedBlocks[realIdx], payload.Proto())
if err != nil {
return nil, err
}
@@ -500,26 +567,47 @@ func (s *Service) ReconstructFullBellatrixBlockBatch(
func fullPayloadFromExecutionBlock(
header interfaces.ExecutionData, block *pb.ExecutionBlock,
) (*pb.ExecutionPayload, error) {
) (interfaces.ExecutionData, error) {
if header.IsNil() || block == nil {
return nil, errors.New("execution block and header cannot be nil")
}
if !bytes.Equal(header.BlockHash(), block.Hash[:]) {
blockHash := block.Hash
if !bytes.Equal(header.BlockHash(), blockHash[:]) {
return nil, fmt.Errorf(
"block hash field in execution header %#x does not match execution block hash %#x",
header.BlockHash(),
block.Hash,
blockHash,
)
}
txs := make([][]byte, len(block.Transactions))
for i, tx := range block.Transactions {
blockTransactions := block.Transactions
txs := make([][]byte, len(blockTransactions))
for i, tx := range blockTransactions {
txBin, err := tx.MarshalBinary()
if err != nil {
return nil, err
}
txs[i] = txBin
}
return &pb.ExecutionPayload{
if block.Version == version.Bellatrix {
return blocks.WrappedExecutionPayload(&pb.ExecutionPayload{
ParentHash: header.ParentHash(),
FeeRecipient: header.FeeRecipient(),
StateRoot: header.StateRoot(),
ReceiptsRoot: header.ReceiptsRoot(),
LogsBloom: header.LogsBloom(),
PrevRandao: header.PrevRandao(),
BlockNumber: header.BlockNumber(),
GasLimit: header.GasLimit(),
GasUsed: header.GasUsed(),
Timestamp: header.Timestamp(),
ExtraData: header.ExtraData(),
BaseFeePerGas: header.BaseFeePerGas(),
BlockHash: blockHash[:],
Transactions: txs,
})
}
return blocks.WrappedExecutionPayloadCapella(&pb.ExecutionPayloadCapella{
ParentHash: header.ParentHash(),
FeeRecipient: header.FeeRecipient(),
StateRoot: header.StateRoot(),
@@ -532,9 +620,10 @@ func fullPayloadFromExecutionBlock(
Timestamp: header.Timestamp(),
ExtraData: header.ExtraData(),
BaseFeePerGas: header.BaseFeePerGas(),
BlockHash: block.Hash[:],
BlockHash: blockHash[:],
Transactions: txs,
}, nil
Withdrawals: block.Withdrawals,
})
}
// Handles errors received from the RPC server according to the specification.

View File

@@ -24,8 +24,10 @@ import (
"github.com/prysmaticlabs/prysm/v3/config/params"
"github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces"
payloadattribute "github.com/prysmaticlabs/prysm/v3/consensus-types/payload-attribute"
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
pb "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
"github.com/prysmaticlabs/prysm/v3/runtime/version"
"github.com/prysmaticlabs/prysm/v3/testing/assert"
"github.com/prysmaticlabs/prysm/v3/testing/require"
"github.com/prysmaticlabs/prysm/v3/testing/util"
@@ -52,6 +54,7 @@ func (RPCClientBad) CallContext(context.Context, interface{}, string, ...interfa
}
func TestClient_IPC(t *testing.T) {
t.Skip("Skipping IPC test to support Capella devnet-3")
server := newTestIPCServer(t)
defer server.Stop()
rpcClient := rpc.DialInProc(server)
@@ -61,18 +64,47 @@ func TestClient_IPC(t *testing.T) {
ctx := context.Background()
fix := fixtures()
params.SetupTestConfigCleanup(t)
cfg := params.BeaconConfig().Copy()
cfg.CapellaForkEpoch = 1
params.OverrideBeaconConfig(cfg)
t.Run(GetPayloadMethod, func(t *testing.T) {
want, ok := fix["ExecutionPayload"].(*pb.ExecutionPayload)
require.Equal(t, true, ok)
payloadId := [8]byte{1}
resp, err := srv.GetPayload(ctx, payloadId)
resp, err := srv.GetPayload(ctx, payloadId, 1)
require.NoError(t, err)
require.DeepEqual(t, want, resp)
resPb, err := resp.PbBellatrix()
require.NoError(t, err)
require.DeepEqual(t, want, resPb)
})
t.Run(GetPayloadMethodV2, func(t *testing.T) {
want, ok := fix["ExecutionPayloadCapella"].(*pb.ExecutionPayloadCapella)
require.Equal(t, true, ok)
payloadId := [8]byte{1}
resp, err := srv.GetPayload(ctx, payloadId, params.BeaconConfig().SlotsPerEpoch)
require.NoError(t, err)
resPb, err := resp.PbCapella()
require.NoError(t, err)
require.DeepEqual(t, want, resPb)
})
t.Run(ForkchoiceUpdatedMethod, func(t *testing.T) {
want, ok := fix["ForkchoiceUpdatedResponse"].(*ForkchoiceUpdatedResponse)
require.Equal(t, true, ok)
payloadID, validHash, err := srv.ForkchoiceUpdated(ctx, &pb.ForkchoiceState{}, &pb.PayloadAttributes{})
p, err := payloadattribute.New(&pb.PayloadAttributes{})
require.NoError(t, err)
payloadID, validHash, err := srv.ForkchoiceUpdated(ctx, &pb.ForkchoiceState{}, p)
require.NoError(t, err)
require.DeepEqual(t, want.Status.LatestValidHash, validHash)
require.DeepEqual(t, want.PayloadId, payloadID)
})
t.Run(ForkchoiceUpdatedMethodV2, func(t *testing.T) {
want, ok := fix["ForkchoiceUpdatedResponse"].(*ForkchoiceUpdatedResponse)
require.Equal(t, true, ok)
p, err := payloadattribute.New(&pb.PayloadAttributesV2{})
require.NoError(t, err)
payloadID, validHash, err := srv.ForkchoiceUpdated(ctx, &pb.ForkchoiceState{}, p)
require.NoError(t, err)
require.DeepEqual(t, want.Status.LatestValidHash, validHash)
require.DeepEqual(t, want.PayloadId, payloadID)
@@ -88,6 +120,17 @@ func TestClient_IPC(t *testing.T) {
require.NoError(t, err)
require.DeepEqual(t, bytesutil.ToBytes32(want.LatestValidHash), bytesutil.ToBytes32(latestValidHash))
})
t.Run(NewPayloadMethodV2, func(t *testing.T) {
want, ok := fix["ValidPayloadStatus"].(*pb.PayloadStatus)
require.Equal(t, true, ok)
req, ok := fix["ExecutionPayloadCapella"].(*pb.ExecutionPayloadCapella)
require.Equal(t, true, ok)
wrappedPayload, err := blocks.WrappedExecutionPayloadCapella(req)
require.NoError(t, err)
latestValidHash, err := srv.NewPayload(ctx, wrappedPayload)
require.NoError(t, err)
require.DeepEqual(t, bytesutil.ToBytes32(want.LatestValidHash), bytesutil.ToBytes32(latestValidHash))
})
t.Run(ExchangeTransitionConfigurationMethod, func(t *testing.T) {
want, ok := fix["TransitionConfiguration"].(*pb.TransitionConfiguration)
require.Equal(t, true, ok)
@@ -115,6 +158,11 @@ func TestClient_HTTP(t *testing.T) {
ctx := context.Background()
fix := fixtures()
params.SetupTestConfigCleanup(t)
cfg := params.BeaconConfig().Copy()
cfg.CapellaForkEpoch = 1
params.OverrideBeaconConfig(cfg)
t.Run(GetPayloadMethod, func(t *testing.T) {
payloadId := [8]byte{1}
want, ok := fix["ExecutionPayload"].(*pb.ExecutionPayload)
@@ -153,9 +201,55 @@ func TestClient_HTTP(t *testing.T) {
client.rpcClient = rpcClient
// We call the RPC method via HTTP and expect a proper result.
resp, err := client.GetPayload(ctx, payloadId)
resp, err := client.GetPayload(ctx, payloadId, 1)
require.NoError(t, err)
require.DeepEqual(t, want, resp)
pb, err := resp.PbBellatrix()
require.NoError(t, err)
require.DeepEqual(t, want, pb)
})
t.Run(GetPayloadMethodV2, func(t *testing.T) {
payloadId := [8]byte{1}
want, ok := fix["ExecutionPayloadCapella"].(*pb.ExecutionPayloadCapella)
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 := io.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 := &Service{}
client.rpcClient = rpcClient
// We call the RPC method via HTTP and expect a proper result.
resp, err := client.GetPayload(ctx, payloadId, params.BeaconConfig().SlotsPerEpoch)
require.NoError(t, err)
pb, err := resp.PbCapella()
require.NoError(t, err)
require.DeepEqual(t, want, pb)
})
t.Run(ForkchoiceUpdatedMethod+" VALID status", func(t *testing.T) {
forkChoiceState := &pb.ForkchoiceState{
@@ -168,12 +262,38 @@ func TestClient_HTTP(t *testing.T) {
PrevRandao: []byte("random"),
SuggestedFeeRecipient: []byte("suggestedFeeRecipient"),
}
p, err := payloadattribute.New(payloadAttributes)
require.NoError(t, err)
want, ok := fix["ForkchoiceUpdatedResponse"].(*ForkchoiceUpdatedResponse)
require.Equal(t, true, ok)
srv := forkchoiceUpdateSetup(t, forkChoiceState, payloadAttributes, want)
// We call the RPC method via HTTP and expect a proper result.
payloadID, validHash, err := srv.ForkchoiceUpdated(ctx, forkChoiceState, payloadAttributes)
payloadID, validHash, err := srv.ForkchoiceUpdated(ctx, forkChoiceState, p)
require.NoError(t, err)
require.DeepEqual(t, want.Status.LatestValidHash, validHash)
require.DeepEqual(t, want.PayloadId, payloadID)
})
t.Run(ForkchoiceUpdatedMethodV2+" VALID status", func(t *testing.T) {
forkChoiceState := &pb.ForkchoiceState{
HeadBlockHash: []byte("head"),
SafeBlockHash: []byte("safe"),
FinalizedBlockHash: []byte("finalized"),
}
payloadAttributes := &pb.PayloadAttributesV2{
Timestamp: 1,
PrevRandao: []byte("random"),
SuggestedFeeRecipient: []byte("suggestedFeeRecipient"),
Withdrawals: []*pb.Withdrawal{{ValidatorIndex: 1, Amount: 1}},
}
p, err := payloadattribute.New(payloadAttributes)
require.NoError(t, err)
want, ok := fix["ForkchoiceUpdatedResponse"].(*ForkchoiceUpdatedResponse)
require.Equal(t, true, ok)
srv := forkchoiceUpdateSetupV2(t, forkChoiceState, payloadAttributes, want)
// We call the RPC method via HTTP and expect a proper result.
payloadID, validHash, err := srv.ForkchoiceUpdated(ctx, forkChoiceState, p)
require.NoError(t, err)
require.DeepEqual(t, want.Status.LatestValidHash, validHash)
require.DeepEqual(t, want.PayloadId, payloadID)
@@ -189,12 +309,38 @@ func TestClient_HTTP(t *testing.T) {
PrevRandao: []byte("random"),
SuggestedFeeRecipient: []byte("suggestedFeeRecipient"),
}
p, err := payloadattribute.New(payloadAttributes)
require.NoError(t, err)
want, ok := fix["ForkchoiceUpdatedSyncingResponse"].(*ForkchoiceUpdatedResponse)
require.Equal(t, true, ok)
client := forkchoiceUpdateSetup(t, forkChoiceState, payloadAttributes, want)
// We call the RPC method via HTTP and expect a proper result.
payloadID, validHash, err := client.ForkchoiceUpdated(ctx, forkChoiceState, payloadAttributes)
payloadID, validHash, err := client.ForkchoiceUpdated(ctx, forkChoiceState, p)
require.ErrorIs(t, err, ErrAcceptedSyncingPayloadStatus)
require.DeepEqual(t, (*pb.PayloadIDBytes)(nil), payloadID)
require.DeepEqual(t, []byte(nil), validHash)
})
t.Run(ForkchoiceUpdatedMethodV2+" SYNCING status", func(t *testing.T) {
forkChoiceState := &pb.ForkchoiceState{
HeadBlockHash: []byte("head"),
SafeBlockHash: []byte("safe"),
FinalizedBlockHash: []byte("finalized"),
}
payloadAttributes := &pb.PayloadAttributesV2{
Timestamp: 1,
PrevRandao: []byte("random"),
SuggestedFeeRecipient: []byte("suggestedFeeRecipient"),
Withdrawals: []*pb.Withdrawal{{ValidatorIndex: 1, Amount: 1}},
}
p, err := payloadattribute.New(payloadAttributes)
require.NoError(t, err)
want, ok := fix["ForkchoiceUpdatedSyncingResponse"].(*ForkchoiceUpdatedResponse)
require.Equal(t, true, ok)
srv := forkchoiceUpdateSetupV2(t, forkChoiceState, payloadAttributes, want)
// We call the RPC method via HTTP and expect a proper result.
payloadID, validHash, err := srv.ForkchoiceUpdated(ctx, forkChoiceState, p)
require.ErrorIs(t, err, ErrAcceptedSyncingPayloadStatus)
require.DeepEqual(t, (*pb.PayloadIDBytes)(nil), payloadID)
require.DeepEqual(t, []byte(nil), validHash)
@@ -210,12 +356,14 @@ func TestClient_HTTP(t *testing.T) {
PrevRandao: []byte("random"),
SuggestedFeeRecipient: []byte("suggestedFeeRecipient"),
}
p, err := payloadattribute.New(payloadAttributes)
require.NoError(t, err)
want, ok := fix["ForkchoiceUpdatedInvalidResponse"].(*ForkchoiceUpdatedResponse)
require.Equal(t, true, ok)
client := forkchoiceUpdateSetup(t, forkChoiceState, payloadAttributes, want)
// We call the RPC method via HTTP and expect a proper result.
payloadID, validHash, err := client.ForkchoiceUpdated(ctx, forkChoiceState, payloadAttributes)
payloadID, validHash, err := client.ForkchoiceUpdated(ctx, forkChoiceState, p)
require.ErrorIs(t, err, ErrInvalidPayloadStatus)
require.DeepEqual(t, (*pb.PayloadIDBytes)(nil), payloadID)
require.DeepEqual(t, want.Status.LatestValidHash, validHash)
@@ -231,12 +379,14 @@ func TestClient_HTTP(t *testing.T) {
PrevRandao: []byte("random"),
SuggestedFeeRecipient: []byte("suggestedFeeRecipient"),
}
p, err := payloadattribute.New(payloadAttributes)
require.NoError(t, err)
want, ok := fix["ForkchoiceUpdatedAcceptedResponse"].(*ForkchoiceUpdatedResponse)
require.Equal(t, true, ok)
client := forkchoiceUpdateSetup(t, forkChoiceState, payloadAttributes, want)
// We call the RPC method via HTTP and expect a proper result.
payloadID, validHash, err := client.ForkchoiceUpdated(ctx, forkChoiceState, payloadAttributes)
payloadID, validHash, err := client.ForkchoiceUpdated(ctx, forkChoiceState, p)
require.ErrorIs(t, err, ErrUnknownPayloadStatus)
require.DeepEqual(t, (*pb.PayloadIDBytes)(nil), payloadID)
require.DeepEqual(t, []byte(nil), validHash)
@@ -255,6 +405,20 @@ func TestClient_HTTP(t *testing.T) {
require.NoError(t, err)
require.DeepEqual(t, want.LatestValidHash, resp)
})
t.Run(NewPayloadMethodV2+" VALID status", func(t *testing.T) {
execPayload, ok := fix["ExecutionPayloadCapella"].(*pb.ExecutionPayloadCapella)
require.Equal(t, true, ok)
want, ok := fix["ValidPayloadStatus"].(*pb.PayloadStatus)
require.Equal(t, true, ok)
client := newPayloadV2Setup(t, want, execPayload)
// We call the RPC method via HTTP and expect a proper result.
wrappedPayload, err := blocks.WrappedExecutionPayloadCapella(execPayload)
require.NoError(t, err)
resp, err := client.NewPayload(ctx, wrappedPayload)
require.NoError(t, err)
require.DeepEqual(t, want.LatestValidHash, resp)
})
t.Run(NewPayloadMethod+" SYNCING status", func(t *testing.T) {
execPayload, ok := fix["ExecutionPayload"].(*pb.ExecutionPayload)
require.Equal(t, true, ok)
@@ -269,6 +433,20 @@ func TestClient_HTTP(t *testing.T) {
require.ErrorIs(t, ErrAcceptedSyncingPayloadStatus, err)
require.DeepEqual(t, []uint8(nil), resp)
})
t.Run(NewPayloadMethodV2+" SYNCING status", func(t *testing.T) {
execPayload, ok := fix["ExecutionPayloadCapella"].(*pb.ExecutionPayloadCapella)
require.Equal(t, true, ok)
want, ok := fix["SyncingStatus"].(*pb.PayloadStatus)
require.Equal(t, true, ok)
client := newPayloadV2Setup(t, want, execPayload)
// We call the RPC method via HTTP and expect a proper result.
wrappedPayload, err := blocks.WrappedExecutionPayloadCapella(execPayload)
require.NoError(t, err)
resp, err := client.NewPayload(ctx, wrappedPayload)
require.ErrorIs(t, ErrAcceptedSyncingPayloadStatus, err)
require.DeepEqual(t, []uint8(nil), resp)
})
t.Run(NewPayloadMethod+" INVALID_BLOCK_HASH status", func(t *testing.T) {
execPayload, ok := fix["ExecutionPayload"].(*pb.ExecutionPayload)
require.Equal(t, true, ok)
@@ -283,6 +461,20 @@ func TestClient_HTTP(t *testing.T) {
require.ErrorIs(t, ErrInvalidBlockHashPayloadStatus, err)
require.DeepEqual(t, []uint8(nil), resp)
})
t.Run(NewPayloadMethodV2+" INVALID_BLOCK_HASH status", func(t *testing.T) {
execPayload, ok := fix["ExecutionPayloadCapella"].(*pb.ExecutionPayloadCapella)
require.Equal(t, true, ok)
want, ok := fix["InvalidBlockHashStatus"].(*pb.PayloadStatus)
require.Equal(t, true, ok)
client := newPayloadV2Setup(t, want, execPayload)
// We call the RPC method via HTTP and expect a proper result.
wrappedPayload, err := blocks.WrappedExecutionPayloadCapella(execPayload)
require.NoError(t, err)
resp, err := client.NewPayload(ctx, wrappedPayload)
require.ErrorIs(t, ErrInvalidBlockHashPayloadStatus, err)
require.DeepEqual(t, []uint8(nil), resp)
})
t.Run(NewPayloadMethod+" INVALID status", func(t *testing.T) {
execPayload, ok := fix["ExecutionPayload"].(*pb.ExecutionPayload)
require.Equal(t, true, ok)
@@ -297,6 +489,20 @@ func TestClient_HTTP(t *testing.T) {
require.ErrorIs(t, ErrInvalidPayloadStatus, err)
require.DeepEqual(t, want.LatestValidHash, resp)
})
t.Run(NewPayloadMethodV2+" INVALID status", func(t *testing.T) {
execPayload, ok := fix["ExecutionPayloadCapella"].(*pb.ExecutionPayloadCapella)
require.Equal(t, true, ok)
want, ok := fix["InvalidStatus"].(*pb.PayloadStatus)
require.Equal(t, true, ok)
client := newPayloadV2Setup(t, want, execPayload)
// We call the RPC method via HTTP and expect a proper result.
wrappedPayload, err := blocks.WrappedExecutionPayloadCapella(execPayload)
require.NoError(t, err)
resp, err := client.NewPayload(ctx, wrappedPayload)
require.ErrorIs(t, ErrInvalidPayloadStatus, err)
require.DeepEqual(t, want.LatestValidHash, resp)
})
t.Run(NewPayloadMethod+" UNKNOWN status", func(t *testing.T) {
execPayload, ok := fix["ExecutionPayload"].(*pb.ExecutionPayload)
require.Equal(t, true, ok)
@@ -424,7 +630,7 @@ func TestReconstructFullBellatrixBlock(t *testing.T) {
t.Run("nil block", func(t *testing.T) {
service := &Service{}
_, err := service.ReconstructFullBellatrixBlock(ctx, nil)
_, err := service.ReconstructFullBlock(ctx, nil)
require.ErrorContains(t, "nil data", err)
})
t.Run("only blinded block", func(t *testing.T) {
@@ -433,7 +639,7 @@ func TestReconstructFullBellatrixBlock(t *testing.T) {
bellatrixBlock := util.NewBeaconBlockBellatrix()
wrapped, err := blocks.NewSignedBeaconBlock(bellatrixBlock)
require.NoError(t, err)
_, err = service.ReconstructFullBellatrixBlock(ctx, wrapped)
_, err = service.ReconstructFullBlock(ctx, wrapped)
require.ErrorContains(t, want, err)
})
t.Run("pre-merge execution payload", func(t *testing.T) {
@@ -448,7 +654,7 @@ func TestReconstructFullBellatrixBlock(t *testing.T) {
require.NoError(t, err)
wantedWrapped, err := blocks.NewSignedBeaconBlock(wanted)
require.NoError(t, err)
reconstructed, err := service.ReconstructFullBellatrixBlock(ctx, wrapped)
reconstructed, err := service.ReconstructFullBlock(ctx, wrapped)
require.NoError(t, err)
require.DeepEqual(t, wantedWrapped, reconstructed)
})
@@ -521,7 +727,7 @@ func TestReconstructFullBellatrixBlock(t *testing.T) {
blindedBlock.Block.Body.ExecutionPayloadHeader = header
wrapped, err := blocks.NewSignedBeaconBlock(blindedBlock)
require.NoError(t, err)
reconstructed, err := service.ReconstructFullBellatrixBlock(ctx, wrapped)
reconstructed, err := service.ReconstructFullBlock(ctx, wrapped)
require.NoError(t, err)
got, err := reconstructed.Block().Body().Execution()
@@ -1072,6 +1278,23 @@ func fixtures() map[string]interface{} {
BlockHash: foo[:],
Transactions: [][]byte{foo[:]},
}
executionPayloadFixtureCapella := &pb.ExecutionPayloadCapella{
ParentHash: foo[:],
FeeRecipient: bar,
StateRoot: foo[:],
ReceiptsRoot: foo[:],
LogsBloom: baz,
PrevRandao: foo[:],
BlockNumber: 1,
GasLimit: 1,
GasUsed: 1,
Timestamp: 1,
ExtraData: foo[:],
BaseFeePerGas: bytesutil.PadTo(baseFeePerGas.Bytes(), fieldparams.RootLength),
BlockHash: foo[:],
Transactions: [][]byte{foo[:]},
Withdrawals: []*pb.Withdrawal{},
}
parent := bytesutil.PadTo([]byte("parentHash"), fieldparams.RootLength)
sha3Uncles := bytesutil.PadTo([]byte("sha3Uncles"), fieldparams.RootLength)
miner := bytesutil.PadTo([]byte("miner"), fieldparams.FeeRecipientLength)
@@ -1080,6 +1303,7 @@ func fixtures() map[string]interface{} {
receiptsRoot := bytesutil.PadTo([]byte("receiptsRoot"), fieldparams.RootLength)
logsBloom := bytesutil.PadTo([]byte("logs"), fieldparams.LogsBloomLength)
executionBlock := &pb.ExecutionBlock{
Version: version.Bellatrix,
Header: gethtypes.Header{
ParentHash: common.BytesToHash(parent),
UncleHash: common.BytesToHash(sha3Uncles),
@@ -1165,6 +1389,7 @@ func fixtures() map[string]interface{} {
return map[string]interface{}{
"ExecutionBlock": executionBlock,
"ExecutionPayload": executionPayloadFixture,
"ExecutionPayloadCapella": executionPayloadFixtureCapella,
"ValidPayloadStatus": validStatus,
"InvalidBlockHashStatus": inValidBlockHashStatus,
"AcceptedStatus": acceptedStatus,
@@ -1188,7 +1413,7 @@ func Test_fullPayloadFromExecutionBlock(t *testing.T) {
tests := []struct {
name string
args args
want *pb.ExecutionPayload
want func() interfaces.ExecutionData
err string
}{
{
@@ -1198,7 +1423,8 @@ func Test_fullPayloadFromExecutionBlock(t *testing.T) {
BlockHash: []byte("foo"),
},
block: &pb.ExecutionBlock{
Hash: common.BytesToHash([]byte("bar")),
Version: version.Bellatrix,
Hash: common.BytesToHash([]byte("bar")),
},
},
err: "does not match execution block hash",
@@ -1210,22 +1436,30 @@ func Test_fullPayloadFromExecutionBlock(t *testing.T) {
BlockHash: wantedHash[:],
},
block: &pb.ExecutionBlock{
Hash: wantedHash,
Version: version.Bellatrix,
Hash: wantedHash,
},
},
want: &pb.ExecutionPayload{
BlockHash: wantedHash[:],
want: func() interfaces.ExecutionData {
p, err := blocks.WrappedExecutionPayload(&pb.ExecutionPayload{
BlockHash: wantedHash[:],
Transactions: [][]byte{},
})
require.NoError(t, err)
return p
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
wrapped, err := blocks.WrappedExecutionPayloadHeader(tt.args.header)
require.NoError(t, err)
got, err := fullPayloadFromExecutionBlock(wrapped, tt.args.block)
if (err != nil) && !strings.Contains(err.Error(), tt.err) {
t.Fatalf("Wanted err %s got %v", tt.err, err)
if err != nil {
assert.ErrorContains(t, tt.err, err)
} else {
assert.DeepEqual(t, tt.want(), got)
}
require.DeepEqual(t, tt.want, got)
})
}
}
@@ -1339,6 +1573,17 @@ func (*testEngineService) GetPayloadV1(
return item
}
func (*testEngineService) GetPayloadV2(
_ context.Context, _ pb.PayloadIDBytes,
) *pb.ExecutionPayloadCapella {
fix := fixtures()
item, ok := fix["ExecutionPayloadCapella"].(*pb.ExecutionPayloadCapella)
if !ok {
panic("not found")
}
return item
}
func (*testEngineService) ExchangeTransitionConfigurationV1(
_ context.Context, _ *pb.TransitionConfiguration,
) *pb.TransitionConfiguration {
@@ -1362,6 +1607,18 @@ func (*testEngineService) ForkchoiceUpdatedV1(
return item
}
func (*testEngineService) ForkchoiceUpdatedV2(
_ context.Context, _ *pb.ForkchoiceState, _ *pb.PayloadAttributes,
) *ForkchoiceUpdatedResponse {
fix := fixtures()
item, ok := fix["ForkchoiceUpdatedResponse"].(*ForkchoiceUpdatedResponse)
if !ok {
panic("not found")
}
item.Status.Status = pb.PayloadStatus_VALID
return item
}
func (*testEngineService) NewPayloadV1(
_ context.Context, _ *pb.ExecutionPayload,
) *pb.PayloadStatus {
@@ -1373,6 +1630,17 @@ func (*testEngineService) NewPayloadV1(
return item
}
func (*testEngineService) NewPayloadV2(
_ context.Context, _ *pb.ExecutionPayloadCapella,
) *pb.PayloadStatus {
fix := fixtures()
item, ok := fix["ValidPayloadStatus"].(*pb.PayloadStatus)
if !ok {
panic("not found")
}
return item
}
func forkchoiceUpdateSetup(t *testing.T, fcs *pb.ForkchoiceState, att *pb.PayloadAttributes, res *ForkchoiceUpdatedResponse) *Service {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
@@ -1412,6 +1680,45 @@ func forkchoiceUpdateSetup(t *testing.T, fcs *pb.ForkchoiceState, att *pb.Payloa
return service
}
func forkchoiceUpdateSetupV2(t *testing.T, fcs *pb.ForkchoiceState, att *pb.PayloadAttributesV2, res *ForkchoiceUpdatedResponse) *Service {
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 := io.ReadAll(r.Body)
require.NoError(t, err)
jsonRequestString := string(enc)
forkChoiceStateReq, err := json.Marshal(fcs)
require.NoError(t, err)
payloadAttrsReq, err := json.Marshal(att)
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": res,
}
err = json.NewEncoder(w).Encode(resp)
require.NoError(t, err)
}))
rpcClient, err := rpc.DialHTTP(srv.URL)
require.NoError(t, err)
service := &Service{}
service.rpcClient = rpcClient
return service
}
func newPayloadSetup(t *testing.T, status *pb.PayloadStatus, payload *pb.ExecutionPayload) *Service {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
@@ -1445,3 +1752,37 @@ func newPayloadSetup(t *testing.T, status *pb.PayloadStatus, payload *pb.Executi
service.rpcClient = rpcClient
return service
}
func newPayloadV2Setup(t *testing.T, status *pb.PayloadStatus, payload *pb.ExecutionPayloadCapella) *Service {
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 := io.ReadAll(r.Body)
require.NoError(t, err)
jsonRequestString := string(enc)
reqArg, err := json.Marshal(payload)
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": status,
}
err = json.NewEncoder(w).Encode(resp)
require.NoError(t, err)
}))
rpcClient, err := rpc.DialHTTP(srv.URL)
require.NoError(t, err)
service := &Service{}
service.rpcClient = rpcClient
return service
}

View File

@@ -88,13 +88,13 @@ func (s *Service) pollConnectionStatus(ctx context.Context) {
// Forces to retry an execution client connection.
func (s *Service) retryExecutionClientConnection(ctx context.Context, err error) {
s.runError = err
s.runError = errors.Wrap(err, "retryExecutionClientConnection")
s.updateConnectedETH1(false)
// Back off for a while before redialing.
time.Sleep(backOffPeriod)
currClient := s.rpcClient
if err := s.setupExecutionClientConnections(ctx, s.cfg.currHttpEndpoint); err != nil {
s.runError = err
s.runError = errors.Wrap(err, "setupExecutionClientConnections")
return
}
// Close previous client, if connection was successful.

View File

@@ -319,10 +319,15 @@ func (s *Service) followedBlockHeight(ctx context.Context) (uint64, error) {
latestBlockTime := uint64(0)
if s.latestEth1Data.BlockTime > followTime {
latestBlockTime = s.latestEth1Data.BlockTime - followTime
// This should only come into play in testnets - when the chain hasn't advanced past the follow distance,
// we don't want to consider any block before the genesis block.
if s.latestEth1Data.BlockHeight < params.BeaconConfig().Eth1FollowDistance {
latestBlockTime = s.latestEth1Data.BlockTime
}
}
blk, err := s.BlockByTimestamp(ctx, latestBlockTime)
if err != nil {
return 0, err
return 0, errors.Wrapf(err, "BlockByTimestamp=%d", latestBlockTime)
}
return blk.Number.Uint64(), nil
}
@@ -467,11 +472,12 @@ func (s *Service) handleETH1FollowDistance() {
}
if !s.chainStartData.Chainstarted {
if err := s.processChainStartFromBlockNum(ctx, big.NewInt(int64(s.latestEth1Data.LastRequestedBlock))); err != nil {
s.runError = err
s.runError = errors.Wrap(err, "processChainStartFromBlockNum")
log.Error(err)
return
}
}
// If the last requested block has not changed,
// we do not request batched logs as this means there are no new
// logs for the powchain service to process. Also it is a potential
@@ -481,7 +487,7 @@ func (s *Service) handleETH1FollowDistance() {
return
}
if err := s.requestBatchedHeadersAndLogs(ctx); err != nil {
s.runError = err
s.runError = errors.Wrap(err, "requestBatchedHeadersAndLogs")
log.Error(err)
return
}
@@ -511,6 +517,7 @@ func (s *Service) initPOWService() {
ctx := s.ctx
header, err := s.HeaderByNumber(ctx, nil)
if err != nil {
err = errors.Wrap(err, "HeaderByNumber")
s.retryExecutionClientConnection(ctx, err)
errorLogger(err, "Unable to retrieve latest execution client header")
continue
@@ -523,6 +530,7 @@ func (s *Service) initPOWService() {
s.latestEth1DataLock.Unlock()
if err := s.processPastLogs(ctx); err != nil {
err = errors.Wrap(err, "processPastLogs")
s.retryExecutionClientConnection(ctx, err)
errorLogger(
err,
@@ -532,6 +540,7 @@ func (s *Service) initPOWService() {
}
// Cache eth1 headers from our voting period.
if err := s.cacheHeadersForEth1DataVote(ctx); err != nil {
err = errors.Wrap(err, "cacheHeadersForEth1DataVote")
s.retryExecutionClientConnection(ctx, err)
if errors.Is(err, errBlockTimeTooLate) {
log.WithError(err).Debug("Unable to cache headers for execution client votes")
@@ -550,6 +559,7 @@ func (s *Service) initPOWService() {
if genHash != [32]byte{} {
genHeader, err := s.HeaderByHash(ctx, genHash)
if err != nil {
err = errors.Wrapf(err, "HeaderByHash, hash=%#x", genHash)
s.retryExecutionClientConnection(ctx, err)
errorLogger(err, "Unable to retrieve proof-of-stake genesis block data")
continue
@@ -558,6 +568,7 @@ func (s *Service) initPOWService() {
}
s.chainStartData.GenesisBlock = genBlock
if err := s.savePowchainData(ctx); err != nil {
err = errors.Wrap(err, "savePowchainData")
s.retryExecutionClientConnection(ctx, err)
errorLogger(err, "Unable to save execution client data")
continue
@@ -641,11 +652,11 @@ func (s *Service) cacheHeadersForEth1DataVote(ctx context.Context) error {
// Find the end block to request from.
end, err := s.followedBlockHeight(ctx)
if err != nil {
return err
return errors.Wrap(err, "followedBlockHeight")
}
start, err := s.determineEarliestVotingBlock(ctx, end)
if err != nil {
return err
return errors.Wrapf(err, "determineEarliestVotingBlock=%d", end)
}
return s.cacheBlockHeaders(start, end)
}
@@ -677,7 +688,7 @@ func (s *Service) cacheBlockHeaders(start, end uint64) error {
}
continue
}
return err
return errors.Wrapf(err, "cacheBlockHeaders, start=%d, end=%d", startReq, endReq)
}
}
return nil
@@ -696,12 +707,20 @@ func (s *Service) determineEarliestVotingBlock(ctx context.Context, followBlock
}
return earliestBlk, nil
}
// This should only come into play in testnets - when the chain hasn't advanced past the follow distance,
// we don't want to consider any block before the genesis block.
if s.latestEth1Data.BlockHeight < params.BeaconConfig().Eth1FollowDistance {
return 0, nil
}
votingTime := slots.VotingPeriodStartTime(genesisTime, currSlot)
followBackDist := 2 * params.BeaconConfig().SecondsPerETH1Block * params.BeaconConfig().Eth1FollowDistance
if followBackDist > votingTime {
return 0, errors.Errorf("invalid genesis time provided. %d > %d", followBackDist, votingTime)
}
earliestValidTime := votingTime - followBackDist
if earliestValidTime < genesisTime {
return 0, nil
}
hdr, err := s.BlockByTimestamp(ctx, earliestValidTime)
if err != nil {
return 0, err

View File

@@ -4,13 +4,14 @@ go_library(
name = "go_default_library",
testonly = True,
srcs = [
"genesis.go",
"mock_engine_client.go",
"mock_execution_chain.go",
"mock_faulty_powchain.go",
],
importpath = "github.com/prysmaticlabs/prysm/v3/beacon-chain/execution/testing",
visibility = [
"//beacon-chain:__subpackages__",
"//visibility:public",
],
deps = [
"//async/event:go_default_library",
@@ -20,13 +21,18 @@ go_library(
"//config/params:go_default_library",
"//consensus-types/blocks:go_default_library",
"//consensus-types/interfaces:go_default_library",
"//consensus-types/payload-attribute:go_default_library",
"//consensus-types/primitives:go_default_library",
"//encoding/bytesutil:go_default_library",
"//proto/engine/v1:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//time/slots:go_default_library",
"@com_github_ethereum_go_ethereum//accounts/abi/bind/backends:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
"@com_github_ethereum_go_ethereum//core:go_default_library",
"@com_github_ethereum_go_ethereum//core/types:go_default_library",
"@com_github_ethereum_go_ethereum//params:go_default_library",
"@com_github_ethereum_go_ethereum//rpc:go_default_library",
"@com_github_holiman_uint256//:go_default_library",
"@com_github_pkg_errors//:go_default_library",

File diff suppressed because one or more lines are too long

View File

@@ -11,8 +11,11 @@ import (
"github.com/prysmaticlabs/prysm/v3/config/params"
"github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces"
payloadattribute "github.com/prysmaticlabs/prysm/v3/consensus-types/payload-attribute"
types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
pb "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
"github.com/prysmaticlabs/prysm/v3/time/slots"
)
// EngineClient --
@@ -21,6 +24,7 @@ type EngineClient struct {
PayloadIDBytes *pb.PayloadIDBytes
ForkChoiceUpdatedResp []byte
ExecutionPayload *pb.ExecutionPayload
ExecutionPayloadCapella *pb.ExecutionPayloadCapella
ExecutionBlock *pb.ExecutionBlock
Err error
ErrLatestExecBlock error
@@ -43,7 +47,7 @@ func (e *EngineClient) NewPayload(_ context.Context, _ interfaces.ExecutionData)
// ForkchoiceUpdated --
func (e *EngineClient) ForkchoiceUpdated(
_ context.Context, fcs *pb.ForkchoiceState, _ *pb.PayloadAttributes,
_ context.Context, fcs *pb.ForkchoiceState, _ payloadattribute.Attributer,
) (*pb.PayloadIDBytes, []byte, error) {
if e.OverrideValidHash != [32]byte{} && bytesutil.ToBytes32(fcs.HeadBlockHash) == e.OverrideValidHash {
return e.PayloadIDBytes, e.ForkChoiceUpdatedResp, nil
@@ -52,8 +56,15 @@ func (e *EngineClient) ForkchoiceUpdated(
}
// GetPayload --
func (e *EngineClient) GetPayload(_ context.Context, _ [8]byte) (*pb.ExecutionPayload, error) {
return e.ExecutionPayload, e.ErrGetPayload
func (e *EngineClient) GetPayload(_ context.Context, _ [8]byte, s types.Slot) (interfaces.ExecutionData, error) {
if slots.ToEpoch(s) >= params.BeaconConfig().CapellaForkEpoch {
return blocks.WrappedExecutionPayloadCapella(e.ExecutionPayloadCapella)
}
p, err := blocks.WrappedExecutionPayload(e.ExecutionPayload)
if err != nil {
return nil, err
}
return p, e.ErrGetPayload
}
// ExchangeTransitionConfiguration --
@@ -75,7 +86,8 @@ func (e *EngineClient) ExecutionBlockByHash(_ context.Context, h common.Hash, _
return b, e.ErrExecBlockByHash
}
func (e *EngineClient) ReconstructFullBellatrixBlock(
// ReconstructFullBlock --
func (e *EngineClient) ReconstructFullBlock(
_ context.Context, blindedBlock interfaces.SignedBeaconBlock,
) (interfaces.SignedBeaconBlock, error) {
if !blindedBlock.Block().IsBlinded() {
@@ -93,12 +105,13 @@ func (e *EngineClient) ReconstructFullBellatrixBlock(
return blocks.BuildSignedBeaconBlockFromExecutionPayload(blindedBlock, payload)
}
// ReconstructFullBellatrixBlockBatch --
func (e *EngineClient) ReconstructFullBellatrixBlockBatch(
ctx context.Context, blindedBlocks []interfaces.SignedBeaconBlock,
) ([]interfaces.SignedBeaconBlock, error) {
fullBlocks := make([]interfaces.SignedBeaconBlock, 0, len(blindedBlocks))
for _, b := range blindedBlocks {
newBlock, err := e.ReconstructFullBellatrixBlock(ctx, b)
newBlock, err := e.ReconstructFullBlock(ctx, b)
if err != nil {
return nil, err
}

View File

@@ -129,7 +129,7 @@ func (f *ForkChoice) InsertNode(ctx context.Context, state state.BeaconState, ro
return errNilBlockHeader
}
parentRoot := bytesutil.ToBytes32(bh.ParentRoot)
payloadHash := [32]byte{}
var payloadHash [32]byte
if state.Version() >= version.Bellatrix {
ph, err := state.LatestExecutionPayloadHeader()
if err != nil {
@@ -669,3 +669,14 @@ func (f *ForkChoice) ForkChoiceDump(ctx context.Context) (*v1.ForkChoiceDump, er
func (f *ForkChoice) SetBalancesByRooter(handler forkchoice.BalancesByRooter) {
f.balancesByRoot = handler
}
// Weight returns the weight of the given root if found on the store
func (f *ForkChoice) Weight(root [32]byte) (uint64, error) {
f.store.nodesLock.RLock()
defer f.store.nodesLock.RUnlock()
n, ok := f.store.nodeByRoot[root]
if !ok || n == nil {
return 0, ErrNilNode
}
return n.weight, nil
}

View File

@@ -578,7 +578,7 @@ func TestStore_InsertOptimisticChain(t *testing.T) {
blks := make([]*forkchoicetypes.BlockAndCheckpoints, 0)
blk := util.NewBeaconBlock()
blk.Block.Slot = 1
pr := [32]byte{}
var pr [32]byte
blk.Block.ParentRoot = pr[:]
root, err := blk.Block.HashTreeRoot()
require.NoError(t, err)
@@ -757,3 +757,24 @@ func TestForkChoice_UpdateCheckpoints(t *testing.T) {
})
}
}
func TestWeight(t *testing.T) {
ctx := context.Background()
f := setup(0, 0)
root := [32]byte{'a'}
st, blkRoot, err := prepareForkchoiceState(ctx, 0, root, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 1, 1)
require.NoError(t, err)
require.NoError(t, f.InsertNode(ctx, st, blkRoot))
n, ok := f.store.nodeByRoot[root]
require.Equal(t, true, ok)
n.weight = 10
w, err := f.Weight(root)
require.NoError(t, err)
require.Equal(t, uint64(10), w)
w, err = f.Weight([32]byte{'b'})
require.ErrorIs(t, err, ErrNilNode)
require.Equal(t, uint64(0), w)
}

View File

@@ -414,7 +414,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
func TestForkChoice_BoostProposerRoot(t *testing.T) {
ctx := context.Background()
root := [32]byte{'A'}
zeroHash := [32]byte{}
var zeroHash [32]byte
t.Run("does not boost block from different slot", func(t *testing.T) {
f := setup(0, 0)

View File

@@ -360,7 +360,7 @@ func TestForkChoice_HighestReceivedBlockSlotRoot(t *testing.T) {
func TestForkChoice_ReceivedBlocksLastEpoch(t *testing.T) {
f := setup(1, 1)
s := f.store
b := [32]byte{}
var b [32]byte
// Make sure it doesn't underflow
s.genesisTime = uint64(time.Now().Add(time.Duration(-1*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second).Unix())

View File

@@ -69,6 +69,7 @@ type Getter interface {
HighestReceivedBlockRoot() [32]byte
ReceivedBlocksLastEpoch() (uint64, error)
ForkChoiceDump(context.Context) (*v1.ForkChoiceDump, error)
Weight(root [32]byte) (uint64, error)
VotedFraction(root [32]byte) (uint64, error)
}

View File

@@ -103,7 +103,7 @@ func TestProcessUnaggregatedAttestationStateCached(t *testing.T) {
participation := []byte{0xff, 0xff, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
require.NoError(t, state.SetCurrentParticipationBits(participation))
root := [32]byte{}
var root [32]byte
copy(root[:], "hello-world")
att := &ethpb.Attestation{
@@ -175,7 +175,7 @@ func TestProcessAggregatedAttestationStateCached(t *testing.T) {
participation := []byte{0xff, 0xff, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
require.NoError(t, state.SetCurrentParticipationBits(participation))
root := [32]byte{}
var root [32]byte
copy(root[:], "hello-world")
att := &ethpb.AggregateAttestationAndProof{

View File

@@ -170,7 +170,7 @@ func TestProcessProposedBlock(t *testing.T) {
hook := logTest.NewGlobal()
s := setupService(t)
beaconState, _ := util.DeterministicGenesisState(t, 256)
root := [32]byte{}
var root [32]byte
copy(root[:], "hello-world")
wb, err := blocks.NewBeaconBlock(tt.block)
require.NoError(t, err)

View File

@@ -815,6 +815,7 @@ func (b *BeaconNode) registerRPCService() error {
AttestationsPool: b.attestationPool,
ExitPool: b.exitPool,
SlashingsPool: b.slashingsPool,
BLSChangesPool: b.blsToExecPool,
SlashingChecker: slasherService,
SyncCommitteeObjectPool: b.syncCommitteePool,
ExecutionChainService: web3Service,

View File

@@ -95,8 +95,8 @@ func TestNodeStart_Ok_registerDeterministicGenesisService(t *testing.T) {
genesisState, _, err := interop.GenerateGenesisState(context.Background(), 0, numValidators)
require.NoError(t, err, "Could not generate genesis beacon state")
for i := uint64(1); i < 2; i++ {
someRoot := [32]byte{}
someKey := [fieldparams.BLSPubkeyLength]byte{}
var someRoot [32]byte
var someKey [fieldparams.BLSPubkeyLength]byte
copy(someRoot[:], strconv.Itoa(int(i)))
copy(someKey[:], strconv.Itoa(int(i)))
genesisState.Validators = append(genesisState.Validators, &ethpb.Validator{

View File

@@ -52,8 +52,8 @@ func (c *AttCaches) SaveUnaggregatedAttestations(atts []*ethpb.Attestation) erro
// UnaggregatedAttestations returns all the unaggregated attestations in cache.
func (c *AttCaches) UnaggregatedAttestations() ([]*ethpb.Attestation, error) {
c.unAggregateAttLock.Lock()
defer c.unAggregateAttLock.Unlock()
c.unAggregateAttLock.RLock()
defer c.unAggregateAttLock.RUnlock()
unAggregatedAtts := c.unAggregatedAtt
atts := make([]*ethpb.Attestation, 0, len(unAggregatedAtts))
for _, att := range unAggregatedAtts {

View File

@@ -120,7 +120,7 @@ func TestBatchAttestations_Single(t *testing.T) {
priv, err := bls.RandKey()
require.NoError(t, err)
sig := priv.Sign([]byte("dummy_test_data"))
mockRoot := [32]byte{}
var mockRoot [32]byte
d := &ethpb.AttestationData{
BeaconBlockRoot: mockRoot[:],
Source: &ethpb.Checkpoint{Root: mockRoot[:]},
@@ -162,7 +162,7 @@ func TestAggregateAndSaveForkChoiceAtts_Single(t *testing.T) {
priv, err := bls.RandKey()
require.NoError(t, err)
sig := priv.Sign([]byte("dummy_test_data"))
mockRoot := [32]byte{}
var mockRoot [32]byte
d := &ethpb.AttestationData{
BeaconBlockRoot: mockRoot[:],
Source: &ethpb.Checkpoint{Root: mockRoot[:]},
@@ -186,7 +186,7 @@ func TestAggregateAndSaveForkChoiceAtts_Multiple(t *testing.T) {
priv, err := bls.RandKey()
require.NoError(t, err)
sig := priv.Sign([]byte("dummy_test_data"))
mockRoot := [32]byte{}
var mockRoot [32]byte
d := &ethpb.AttestationData{
BeaconBlockRoot: mockRoot[:],
Source: &ethpb.Checkpoint{Root: mockRoot[:]},

View File

@@ -59,8 +59,8 @@ func (s *Service) pruneExpiredAtts() {
if err := s.cfg.Pool.DeleteBlockAttestation(att); err != nil {
log.WithError(err).Error("Could not delete expired block attestation")
}
expiredBlockAtts.Inc()
}
expiredBlockAtts.Inc()
}
}

View File

@@ -11,10 +11,15 @@ go_library(
"//beacon-chain:__subpackages__",
],
deps = [
"//beacon-chain/core/blocks:go_default_library",
"//beacon-chain/state:go_default_library",
"//config/params:go_default_library",
"//consensus-types/primitives:go_default_library",
"//container/doubly-linked-list:go_default_library",
"//crypto/bls/blst:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
],
)
@@ -24,8 +29,15 @@ go_test(
srcs = ["pool_test.go"],
embed = [":go_default_library"],
deps = [
"//beacon-chain/core/signing:go_default_library",
"//beacon-chain/core/time:go_default_library",
"//beacon-chain/state/state-native:go_default_library",
"//config/params:go_default_library",
"//consensus-types/primitives:go_default_library",
"//crypto/bls:go_default_library",
"//crypto/bls/common:go_default_library",
"//crypto/hash:go_default_library",
"//encoding/ssz:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//testing/assert:go_default_library",
"//testing/require:go_default_library",

View File

@@ -0,0 +1,14 @@
load("@prysm//tools/go:def.bzl", "go_library")
go_library(
name = "go_default_library",
testonly = True,
srcs = ["mock.go"],
importpath = "github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/blstoexec/mock",
visibility = ["//visibility:public"],
deps = [
"//beacon-chain/state:go_default_library",
"//consensus-types/primitives:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
],
)

View File

@@ -0,0 +1,37 @@
package mock
import (
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state"
types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
eth "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
)
// PoolMock is a fake implementation of PoolManager.
type PoolMock struct {
Changes []*eth.SignedBLSToExecutionChange
}
// PendingBLSToExecChanges --
func (m *PoolMock) PendingBLSToExecChanges() ([]*eth.SignedBLSToExecutionChange, error) {
return m.Changes, nil
}
// BLSToExecChangesForInclusion --
func (m *PoolMock) BLSToExecChangesForInclusion(_ state.BeaconState) ([]*eth.SignedBLSToExecutionChange, error) {
return m.Changes, nil
}
// InsertBLSToExecChange --
func (m *PoolMock) InsertBLSToExecChange(change *eth.SignedBLSToExecutionChange) {
m.Changes = append(m.Changes, change)
}
// MarkIncluded --
func (*PoolMock) MarkIncluded(_ *eth.SignedBLSToExecutionChange) error {
panic("implement me")
}
// ValidatorExists --
func (*PoolMock) ValidatorExists(_ types.ValidatorIndex) bool {
panic("implement me")
}

View File

@@ -4,17 +4,22 @@ import (
"math"
"sync"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state"
"github.com/prysmaticlabs/prysm/v3/config/params"
types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
doublylinkedlist "github.com/prysmaticlabs/prysm/v3/container/doubly-linked-list"
"github.com/prysmaticlabs/prysm/v3/crypto/bls/blst"
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
"github.com/sirupsen/logrus"
)
// PoolManager maintains pending and seen BLS-to-execution-change objects.
// This pool is used by proposers to insert BLS-to-execution-change objects into new blocks.
type PoolManager interface {
PendingBLSToExecChanges() ([]*ethpb.SignedBLSToExecutionChange, error)
BLSToExecChangesForInclusion() ([]*ethpb.SignedBLSToExecutionChange, error)
BLSToExecChangesForInclusion(state.BeaconState) ([]*ethpb.SignedBLSToExecutionChange, error)
InsertBLSToExecChange(change *ethpb.SignedBLSToExecutionChange)
MarkIncluded(change *ethpb.SignedBLSToExecutionChange) error
ValidatorExists(idx types.ValidatorIndex) bool
@@ -58,25 +63,69 @@ func (p *Pool) PendingBLSToExecChanges() ([]*ethpb.SignedBLSToExecutionChange, e
// BLSToExecChangesForInclusion returns objects that are ready for inclusion at the given slot.
// This method will not return more than the block enforced MaxBlsToExecutionChanges.
func (p *Pool) BLSToExecChangesForInclusion() ([]*ethpb.SignedBLSToExecutionChange, error) {
func (p *Pool) BLSToExecChangesForInclusion(st state.BeaconState) ([]*ethpb.SignedBLSToExecutionChange, error) {
p.lock.RLock()
defer p.lock.RUnlock()
length := int(math.Min(float64(params.BeaconConfig().MaxBlsToExecutionChanges), float64(p.pending.Len())))
result := make([]*ethpb.SignedBLSToExecutionChange, length)
result := make([]*ethpb.SignedBLSToExecutionChange, 0, length)
node := p.pending.First()
var err error
for i := 0; node != nil && i < length; i++ {
result[i], err = node.Value()
for node != nil && len(result) < length {
change, err := node.Value()
if err != nil {
p.lock.RUnlock()
return nil, err
}
_, err = blocks.ValidateBLSToExecutionChange(st, change)
if err != nil {
logrus.WithError(err).Warning("removing invalid BLSToExecutionChange from pool")
// MarkIncluded removes the invalid change from the pool
p.lock.RUnlock()
if err := p.MarkIncluded(change); err != nil {
return nil, errors.Wrap(err, "could not mark BLSToExecutionChange as included")
}
p.lock.RLock()
} else {
result = append(result, change)
}
node, err = node.Next()
if err != nil {
p.lock.RUnlock()
return nil, err
}
}
return result, nil
p.lock.RUnlock()
if len(result) == 0 {
return result, nil
}
// We now verify the signatures in batches
cSet, err := blocks.BLSChangesSignatureBatch(st, result)
if err != nil {
logrus.WithError(err).Warning("could not get BLSToExecutionChanges signatures")
} else {
ok, err := cSet.Verify()
if err != nil {
logrus.WithError(err).Warning("could not batch verify BLSToExecutionChanges signatures")
} else if ok {
return result, nil
}
}
// Batch signature failed, check signatures individually
verified := make([]*ethpb.SignedBLSToExecutionChange, 0, length)
for i, sig := range cSet.Signatures {
signature, err := blst.SignatureFromBytes(sig)
if err != nil {
logrus.WithError(err).Warning("could not get signature from bytes")
continue
}
if !signature.Verify(cSet.PublicKeys[i], cSet.Messages[i][:]) {
logrus.Warning("removing BLSToExecutionChange with invalid signature from pool")
if err := p.MarkIncluded(result[i]); err != nil {
return nil, errors.Wrap(err, "could not mark BLSToExecutionChange as included")
}
} else {
verified = append(verified, result[i])
}
}
return verified, nil
}
// InsertBLSToExecChange inserts an object into the pool.

View File

@@ -3,8 +3,15 @@ package blstoexec
import (
"testing"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/signing"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/time"
state_native "github.com/prysmaticlabs/prysm/v3/beacon-chain/state/state-native"
"github.com/prysmaticlabs/prysm/v3/config/params"
types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v3/crypto/bls"
"github.com/prysmaticlabs/prysm/v3/crypto/bls/common"
"github.com/prysmaticlabs/prysm/v3/crypto/hash"
"github.com/prysmaticlabs/prysm/v3/encoding/ssz"
eth "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v3/testing/assert"
"github.com/prysmaticlabs/prysm/v3/testing/require"
@@ -36,42 +43,89 @@ func TestPendingBLSToExecChanges(t *testing.T) {
}
func TestBLSToExecChangesForInclusion(t *testing.T) {
spb := &eth.BeaconStateCapella{
Fork: &eth.Fork{
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
},
}
numValidators := 2 * params.BeaconConfig().MaxBlsToExecutionChanges
validators := make([]*eth.Validator, numValidators)
blsChanges := make([]*eth.BLSToExecutionChange, numValidators)
spb.Balances = make([]uint64, numValidators)
privKeys := make([]common.SecretKey, numValidators)
maxEffectiveBalance := params.BeaconConfig().MaxEffectiveBalance
executionAddress := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13}
for i := range validators {
v := &eth.Validator{}
v.EffectiveBalance = maxEffectiveBalance
v.WithdrawableEpoch = params.BeaconConfig().FarFutureEpoch
v.WithdrawalCredentials = make([]byte, 32)
priv, err := bls.RandKey()
require.NoError(t, err)
privKeys[i] = priv
pubkey := priv.PublicKey().Marshal()
message := &eth.BLSToExecutionChange{
ToExecutionAddress: executionAddress,
ValidatorIndex: types.ValidatorIndex(i),
FromBlsPubkey: pubkey,
}
hashFn := ssz.NewHasherFunc(hash.CustomSHA256Hasher())
digest := hashFn.Hash(pubkey)
digest[0] = params.BeaconConfig().BLSWithdrawalPrefixByte
copy(v.WithdrawalCredentials, digest[:])
validators[i] = v
blsChanges[i] = message
}
spb.Validators = validators
st, err := state_native.InitializeFromProtoCapella(spb)
require.NoError(t, err)
signedChanges := make([]*eth.SignedBLSToExecutionChange, numValidators)
for i, message := range blsChanges {
signature, err := signing.ComputeDomainAndSign(st, time.CurrentEpoch(st), message, params.BeaconConfig().DomainBLSToExecutionChange, privKeys[i])
require.NoError(t, err)
signed := &eth.SignedBLSToExecutionChange{
Message: message,
Signature: signature,
}
signedChanges[i] = signed
}
t.Run("empty pool", func(t *testing.T) {
pool := NewPool()
for i := uint64(0); i < params.BeaconConfig().MaxBlsToExecutionChanges-1; i++ {
pool.InsertBLSToExecChange(&eth.SignedBLSToExecutionChange{
Message: &eth.BLSToExecutionChange{
ValidatorIndex: types.ValidatorIndex(i),
},
})
}
changes, err := pool.BLSToExecChangesForInclusion()
changes, err := pool.BLSToExecChangesForInclusion(st)
require.NoError(t, err)
assert.Equal(t, int(params.BeaconConfig().MaxBlsToExecutionChanges-1), len(changes))
assert.Equal(t, 0, len(changes))
})
t.Run("Less than MaxBlsToExecutionChanges in pool", func(t *testing.T) {
pool := NewPool()
for i := uint64(0); i < params.BeaconConfig().MaxBlsToExecutionChanges-1; i++ {
pool.InsertBLSToExecChange(signedChanges[i])
}
changes, err := pool.BLSToExecChangesForInclusion(st)
require.NoError(t, err)
assert.Equal(t, int(params.BeaconConfig().MaxBlsToExecutionChanges)-1, len(changes))
})
t.Run("MaxBlsToExecutionChanges in pool", func(t *testing.T) {
pool := NewPool()
for i := uint64(0); i < params.BeaconConfig().MaxBlsToExecutionChanges; i++ {
pool.InsertBLSToExecChange(&eth.SignedBLSToExecutionChange{
Message: &eth.BLSToExecutionChange{
ValidatorIndex: types.ValidatorIndex(i),
},
})
pool.InsertBLSToExecChange(signedChanges[i])
}
changes, err := pool.BLSToExecChangesForInclusion()
changes, err := pool.BLSToExecChangesForInclusion(st)
require.NoError(t, err)
assert.Equal(t, int(params.BeaconConfig().MaxBlsToExecutionChanges), len(changes))
})
t.Run("more than MaxBlsToExecutionChanges in pool", func(t *testing.T) {
pool := NewPool()
for i := uint64(0); i < params.BeaconConfig().MaxBlsToExecutionChanges+1; i++ {
pool.InsertBLSToExecChange(&eth.SignedBLSToExecutionChange{
Message: &eth.BLSToExecutionChange{
ValidatorIndex: types.ValidatorIndex(i),
},
})
for i := uint64(0); i < numValidators; i++ {
pool.InsertBLSToExecChange(signedChanges[i])
}
changes, err := pool.BLSToExecChangesForInclusion()
changes, err := pool.BLSToExecChangesForInclusion(st)
require.NoError(t, err)
// We want FIFO semantics, which means validator with index 16 shouldn't be returned
assert.Equal(t, int(params.BeaconConfig().MaxBlsToExecutionChanges), len(changes))
@@ -79,6 +133,30 @@ func TestBLSToExecChangesForInclusion(t *testing.T) {
assert.NotEqual(t, types.ValidatorIndex(16), ch.Message.ValidatorIndex)
}
})
t.Run("One Bad change", func(t *testing.T) {
pool := NewPool()
saveByte := signedChanges[1].Message.FromBlsPubkey[5]
signedChanges[1].Message.FromBlsPubkey[5] = 0xff
for i := uint64(0); i < numValidators; i++ {
pool.InsertBLSToExecChange(signedChanges[i])
}
changes, err := pool.BLSToExecChangesForInclusion(st)
require.NoError(t, err)
assert.Equal(t, int(params.BeaconConfig().MaxBlsToExecutionChanges), len(changes))
assert.Equal(t, types.ValidatorIndex(2), changes[1].Message.ValidatorIndex)
signedChanges[1].Message.FromBlsPubkey[5] = saveByte
})
t.Run("One Bad Signature", func(t *testing.T) {
pool := NewPool()
copy(signedChanges[1].Signature, signedChanges[2].Signature)
for i := uint64(0); i < numValidators; i++ {
pool.InsertBLSToExecChange(signedChanges[i])
}
changes, err := pool.BLSToExecChangesForInclusion(st)
require.NoError(t, err)
assert.Equal(t, int(params.BeaconConfig().MaxBlsToExecutionChanges)-1, len(changes))
assert.Equal(t, types.ValidatorIndex(2), changes[1].Message.ValidatorIndex)
})
}
func TestInsertBLSToExecChange(t *testing.T) {

View File

@@ -603,10 +603,10 @@ func TestTrimmedOrderedPeers(t *testing.T) {
expectedTarget := types.Epoch(2)
maxPeers := 3
mockroot2 := [32]byte{}
mockroot3 := [32]byte{}
mockroot4 := [32]byte{}
mockroot5 := [32]byte{}
var mockroot2 [32]byte
var mockroot3 [32]byte
var mockroot4 [32]byte
var mockroot5 [32]byte
copy(mockroot2[:], "two")
copy(mockroot3[:], "three")
copy(mockroot4[:], "four")

View File

@@ -26,7 +26,7 @@ func TestService_CanSubscribe(t *testing.T) {
currentFork := [4]byte{0x01, 0x02, 0x03, 0x04}
validProtocolSuffix := "/" + encoder.ProtocolSuffixSSZSnappy
genesisTime := time.Now()
valRoot := [32]byte{}
var valRoot [32]byte
digest, err := forks.CreateForkDigest(genesisTime, valRoot[:])
assert.NoError(t, err)
type test struct {
@@ -216,7 +216,7 @@ func TestService_FilterIncomingSubscriptions(t *testing.T) {
params.SetupTestConfigCleanup(t)
validProtocolSuffix := "/" + encoder.ProtocolSuffixSSZSnappy
genesisTime := time.Now()
valRoot := [32]byte{}
var valRoot [32]byte
digest, err := forks.CreateForkDigest(genesisTime, valRoot[:])
assert.NoError(t, err)
type args struct {

View File

@@ -19,6 +19,7 @@ go_library(
"//beacon-chain/db:go_default_library",
"//beacon-chain/execution:go_default_library",
"//beacon-chain/operations/attestations:go_default_library",
"//beacon-chain/operations/blstoexec:go_default_library",
"//beacon-chain/operations/slashings:go_default_library",
"//beacon-chain/operations/synccommittee:go_default_library",
"//beacon-chain/operations/voluntaryexits:go_default_library",

View File

@@ -64,6 +64,19 @@ func handleGetBeaconBlockSSZV2(m *apimiddleware.ApiProxyMiddleware, endpoint api
return handleGetSSZ(m, endpoint, w, req, config)
}
func handleGetBlindedBeaconBlockSSZ(
m *apimiddleware.ApiProxyMiddleware,
endpoint apimiddleware.Endpoint,
w http.ResponseWriter,
req *http.Request,
) (handled bool) {
config := sszConfig{
fileName: "beacon_block.ssz",
responseJson: &VersionedSSZResponseJson{},
}
return handleGetSSZ(m, endpoint, w, req, config)
}
func handleSubmitBlockSSZ(m *apimiddleware.ApiProxyMiddleware, endpoint apimiddleware.Endpoint, w http.ResponseWriter, req *http.Request) (handled bool) {
return handlePostSSZ(m, endpoint, w, req)
}
@@ -403,6 +416,8 @@ func receiveEvents(eventChan <-chan *sse.Event, w http.ResponseWriter, req *http
data = &EventChainReorgJson{}
case events.SyncCommitteeContributionTopic:
data = &SignedContributionAndProofJson{}
case events.BLSToExecutionChangeTopic:
data = &SignedBLSToExecutionChangeJson{}
case "error":
data = &EventErrorJson{}
default:

View File

@@ -22,6 +22,7 @@ import (
type testSSZResponseJson struct {
Version string `json:"version"`
ExecutionOptimistic bool `json:"execution_optimistic"`
Finalized bool `json:"finalized"`
Data string `json:"data"`
}
@@ -37,6 +38,10 @@ func (t testSSZResponseJson) SSZData() string {
return t.Data
}
func (t testSSZResponseJson) SSZFinalized() bool {
return t.Finalized
}
func TestSSZRequested(t *testing.T) {
t.Run("ssz_requested", func(t *testing.T) {
request := httptest.NewRequest("GET", "http://foo.example", nil)

View File

@@ -5,7 +5,6 @@ import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"strconv"
"strings"
@@ -18,6 +17,29 @@ import (
"github.com/prysmaticlabs/prysm/v3/time/slots"
)
// https://ethereum.github.io/beacon-APIs/?urls.primaryName=dev#/Beacon/submitPoolBLSToExecutionChange
// expects posting a top-level array. We make it more proto-friendly by wrapping it in a struct.
func wrapBLSChangesArray(
endpoint *apimiddleware.Endpoint,
_ http.ResponseWriter,
req *http.Request,
) (apimiddleware.RunDefault, apimiddleware.ErrorJson) {
if _, ok := endpoint.PostRequest.(*SubmitBLSToExecutionChangesRequest); !ok {
return true, nil
}
changes := make([]*SignedBLSToExecutionChangeJson, 0)
if err := json.NewDecoder(req.Body).Decode(&changes); err != nil {
return false, apimiddleware.InternalServerErrorWithMessage(err, "could not decode body")
}
j := &SubmitBLSToExecutionChangesRequest{Changes: changes}
b, err := json.Marshal(j)
if err != nil {
return false, apimiddleware.InternalServerErrorWithMessage(err, "could not marshal wrapped body")
}
req.Body = io.NopCloser(bytes.NewReader(b))
return true, nil
}
// https://ethereum.github.io/beacon-apis/#/Validator/prepareBeaconProposer expects posting a top-level array.
// We make it more proto-friendly by wrapping it in a struct.
func wrapFeeRecipientsArray(
@@ -233,11 +255,21 @@ type bellatrixPublishBlockRequestJson struct {
Signature string `json:"signature" hex:"true"`
}
type capellaPublishBlockRequestJson struct {
CapellaBlock *BeaconBlockCapellaJson `json:"capella_block"`
Signature string `json:"signature" hex:"true"`
}
type bellatrixPublishBlindedBlockRequestJson struct {
BellatrixBlock *BlindedBeaconBlockBellatrixJson `json:"bellatrix_block"`
Signature string `json:"signature" hex:"true"`
}
type capellaPublishBlindedBlockRequestJson struct {
CapellaBlock *BlindedBeaconBlockCapellaJson `json:"capella_block"`
Signature string `json:"signature" hex:"true"`
}
// setInitialPublishBlockPostRequest is triggered before we deserialize the request JSON into a struct.
// We don't know which version of the block got posted, but we can determine it from the slot.
// We know that blocks of all versions have a Message field with a Slot field,
@@ -269,8 +301,10 @@ func setInitialPublishBlockPostRequest(endpoint *apimiddleware.Endpoint,
endpoint.PostRequest = &SignedBeaconBlockContainerJson{}
} else if currentEpoch < params.BeaconConfig().BellatrixForkEpoch {
endpoint.PostRequest = &SignedBeaconBlockAltairContainerJson{}
} else {
} else if currentEpoch < params.BeaconConfig().CapellaForkEpoch {
endpoint.PostRequest = &SignedBeaconBlockBellatrixContainerJson{}
} else {
endpoint.PostRequest = &SignedBeaconBlockCapellaContainerJson{}
}
req.Body = io.NopCloser(bytes.NewBuffer(buf))
return true, nil
@@ -308,6 +342,15 @@ func preparePublishedBlock(endpoint *apimiddleware.Endpoint, _ http.ResponseWrit
endpoint.PostRequest = actualPostReq
return nil
}
if block, ok := endpoint.PostRequest.(*SignedBeaconBlockCapellaContainerJson); ok {
// Prepare post request that can be properly decoded on gRPC side.
actualPostReq := &capellaPublishBlockRequestJson{
CapellaBlock: block.Message,
Signature: block.Signature,
}
endpoint.PostRequest = actualPostReq
return nil
}
return apimiddleware.InternalServerError(errors.New("unsupported block type"))
}
@@ -326,7 +369,7 @@ func setInitialPublishBlindedBlockPostRequest(endpoint *apimiddleware.Endpoint,
}
}{}
buf, err := ioutil.ReadAll(req.Body)
buf, err := io.ReadAll(req.Body)
if err != nil {
return false, apimiddleware.InternalServerErrorWithMessage(err, "could not read body")
}
@@ -342,10 +385,12 @@ func setInitialPublishBlindedBlockPostRequest(endpoint *apimiddleware.Endpoint,
endpoint.PostRequest = &SignedBeaconBlockContainerJson{}
} else if currentEpoch < params.BeaconConfig().BellatrixForkEpoch {
endpoint.PostRequest = &SignedBeaconBlockAltairContainerJson{}
} else {
} else if currentEpoch < params.BeaconConfig().CapellaForkEpoch {
endpoint.PostRequest = &SignedBlindedBeaconBlockBellatrixContainerJson{}
} else {
endpoint.PostRequest = &SignedBlindedBeaconBlockCapellaContainerJson{}
}
req.Body = ioutil.NopCloser(bytes.NewBuffer(buf))
req.Body = io.NopCloser(bytes.NewBuffer(buf))
return true, nil
}
@@ -381,6 +426,15 @@ func preparePublishedBlindedBlock(endpoint *apimiddleware.Endpoint, _ http.Respo
endpoint.PostRequest = actualPostReq
return nil
}
if block, ok := endpoint.PostRequest.(*SignedBlindedBeaconBlockCapellaContainerJson); ok {
// Prepare post request that can be properly decoded on gRPC side.
actualPostReq := &capellaPublishBlindedBlockRequestJson{
CapellaBlock: block.Message,
Signature: block.Signature,
}
endpoint.PostRequest = actualPostReq
return nil
}
return apimiddleware.InternalServerError(errors.New("unsupported block type"))
}
@@ -422,33 +476,45 @@ func prepareValidatorAggregates(body []byte, responseContainer interface{}) (api
}
type phase0BlockResponseJson struct {
Version string `json:"version"`
Version string `json:"version" enum:"true"`
Data *SignedBeaconBlockContainerJson `json:"data"`
ExecutionOptimistic bool `json:"execution_optimistic"`
Finalized bool `json:"finalized"`
}
type altairBlockResponseJson struct {
Version string `json:"version"`
Version string `json:"version" enum:"true"`
Data *SignedBeaconBlockAltairContainerJson `json:"data"`
ExecutionOptimistic bool `json:"execution_optimistic"`
Finalized bool `json:"finalized"`
}
type bellatrixBlockResponseJson struct {
Version string `json:"version"`
Version string `json:"version" enum:"true"`
Data *SignedBeaconBlockBellatrixContainerJson `json:"data"`
ExecutionOptimistic bool `json:"execution_optimistic"`
Finalized bool `json:"finalized"`
}
type capellaBlockResponseJson struct {
Version string `json:"version"`
Data *SignedBeaconBlockCapellaContainerJson `json:"data"`
ExecutionOptimistic bool `json:"execution_optimistic"`
Finalized bool `json:"finalized"`
}
type bellatrixBlindedBlockResponseJson struct {
Version string `json:"version"`
Version string `json:"version" enum:"true"`
Data *SignedBlindedBeaconBlockBellatrixContainerJson `json:"data"`
ExecutionOptimistic bool `json:"execution_optimistic"`
Finalized bool `json:"finalized"`
}
type capellaBlindedBlockResponseJson struct {
Version string `json:"version"`
Version string `json:"version" enum:"true"`
Data *SignedBlindedBeaconBlockCapellaContainerJson `json:"data"`
ExecutionOptimistic bool `json:"execution_optimistic"`
Finalized bool `json:"finalized"`
}
func serializeV2Block(response interface{}) (apimiddleware.RunDefault, []byte, apimiddleware.ErrorJson) {
@@ -467,6 +533,7 @@ func serializeV2Block(response interface{}) (apimiddleware.RunDefault, []byte, a
Signature: respContainer.Data.Signature,
},
ExecutionOptimistic: respContainer.ExecutionOptimistic,
Finalized: respContainer.Finalized,
}
case strings.EqualFold(respContainer.Version, strings.ToLower(ethpbv2.Version_ALTAIR.String())):
actualRespContainer = &altairBlockResponseJson{
@@ -476,6 +543,7 @@ func serializeV2Block(response interface{}) (apimiddleware.RunDefault, []byte, a
Signature: respContainer.Data.Signature,
},
ExecutionOptimistic: respContainer.ExecutionOptimistic,
Finalized: respContainer.Finalized,
}
case strings.EqualFold(respContainer.Version, strings.ToLower(ethpbv2.Version_BELLATRIX.String())):
actualRespContainer = &bellatrixBlockResponseJson{
@@ -485,6 +553,17 @@ func serializeV2Block(response interface{}) (apimiddleware.RunDefault, []byte, a
Signature: respContainer.Data.Signature,
},
ExecutionOptimistic: respContainer.ExecutionOptimistic,
Finalized: respContainer.Finalized,
}
case strings.EqualFold(respContainer.Version, strings.ToLower(ethpbv2.Version_CAPELLA.String())):
actualRespContainer = &capellaBlockResponseJson{
Version: respContainer.Version,
Data: &SignedBeaconBlockCapellaContainerJson{
Message: respContainer.Data.CapellaBlock,
Signature: respContainer.Data.Signature,
},
ExecutionOptimistic: respContainer.ExecutionOptimistic,
Finalized: respContainer.Finalized,
}
default:
return false, nil, apimiddleware.InternalServerError(fmt.Errorf("unsupported block version '%s'", respContainer.Version))
@@ -513,6 +592,7 @@ func serializeBlindedBlock(response interface{}) (apimiddleware.RunDefault, []by
Signature: respContainer.Data.Signature,
},
ExecutionOptimistic: respContainer.ExecutionOptimistic,
Finalized: respContainer.Finalized,
}
case strings.EqualFold(respContainer.Version, strings.ToLower(ethpbv2.Version_ALTAIR.String())):
actualRespContainer = &altairBlockResponseJson{
@@ -522,6 +602,7 @@ func serializeBlindedBlock(response interface{}) (apimiddleware.RunDefault, []by
Signature: respContainer.Data.Signature,
},
ExecutionOptimistic: respContainer.ExecutionOptimistic,
Finalized: respContainer.Finalized,
}
case strings.EqualFold(respContainer.Version, strings.ToLower(ethpbv2.Version_BELLATRIX.String())):
actualRespContainer = &bellatrixBlindedBlockResponseJson{
@@ -531,6 +612,7 @@ func serializeBlindedBlock(response interface{}) (apimiddleware.RunDefault, []by
Signature: respContainer.Data.Signature,
},
ExecutionOptimistic: respContainer.ExecutionOptimistic,
Finalized: respContainer.Finalized,
}
case strings.EqualFold(respContainer.Version, strings.ToLower(ethpbv2.Version_CAPELLA.String())):
actualRespContainer = &capellaBlindedBlockResponseJson{
@@ -540,6 +622,7 @@ func serializeBlindedBlock(response interface{}) (apimiddleware.RunDefault, []by
Signature: respContainer.Data.Signature,
},
ExecutionOptimistic: respContainer.ExecutionOptimistic,
Finalized: respContainer.Finalized,
}
default:
return false, nil, apimiddleware.InternalServerError(fmt.Errorf("unsupported block version '%s'", respContainer.Version))
@@ -553,22 +636,22 @@ func serializeBlindedBlock(response interface{}) (apimiddleware.RunDefault, []by
}
type phase0StateResponseJson struct {
Version string `json:"version"`
Version string `json:"version" enum:"true"`
Data *BeaconStateJson `json:"data"`
}
type altairStateResponseJson struct {
Version string `json:"version"`
Version string `json:"version" enum:"true"`
Data *BeaconStateAltairJson `json:"data"`
}
type bellatrixStateResponseJson struct {
Version string `json:"version"`
Version string `json:"version" enum:"true"`
Data *BeaconStateBellatrixJson `json:"data"`
}
type capellaStateResponseJson struct {
Version string `json:"version"`
Version string `json:"version" enum:"true"`
Data *BeaconStateCapellaJson `json:"data"`
}
@@ -612,25 +695,35 @@ func serializeV2State(response interface{}) (apimiddleware.RunDefault, []byte, a
}
type phase0ProduceBlockResponseJson struct {
Version string `json:"version"`
Version string `json:"version" enum:"true"`
Data *BeaconBlockJson `json:"data"`
}
type altairProduceBlockResponseJson struct {
Version string `json:"version"`
Version string `json:"version" enum:"true"`
Data *BeaconBlockAltairJson `json:"data"`
}
type bellatrixProduceBlockResponseJson struct {
Version string `json:"version"`
Version string `json:"version" enum:"true"`
Data *BeaconBlockBellatrixJson `json:"data"`
}
type capellaProduceBlockResponseJson struct {
Version string `json:"version" enum:"true"`
Data *BeaconBlockCapellaJson `json:"data"`
}
type bellatrixProduceBlindedBlockResponseJson struct {
Version string `json:"version"`
Version string `json:"version" enum:"true"`
Data *BlindedBeaconBlockBellatrixJson `json:"data"`
}
type capellaProduceBlindedBlockResponseJson struct {
Version string `json:"version" enum:"true"`
Data *BlindedBeaconBlockCapellaJson `json:"data"`
}
func serializeProducedV2Block(response interface{}) (apimiddleware.RunDefault, []byte, apimiddleware.ErrorJson) {
respContainer, ok := response.(*ProduceBlockResponseV2Json)
if !ok {
@@ -654,6 +747,11 @@ func serializeProducedV2Block(response interface{}) (apimiddleware.RunDefault, [
Version: respContainer.Version,
Data: respContainer.Data.BellatrixBlock,
}
case strings.EqualFold(respContainer.Version, strings.ToLower(ethpbv2.Version_CAPELLA.String())):
actualRespContainer = &capellaProduceBlockResponseJson{
Version: respContainer.Version,
Data: respContainer.Data.CapellaBlock,
}
default:
return false, nil, apimiddleware.InternalServerError(fmt.Errorf("unsupported block version '%s'", respContainer.Version))
}
@@ -688,6 +786,11 @@ func serializeProducedBlindedBlock(response interface{}) (apimiddleware.RunDefau
Version: respContainer.Version,
Data: respContainer.Data.BellatrixBlock,
}
case strings.EqualFold(respContainer.Version, strings.ToLower(ethpbv2.Version_CAPELLA.String())):
actualRespContainer = &capellaProduceBlindedBlockResponseJson{
Version: respContainer.Version,
Data: respContainer.Data.CapellaBlock,
}
default:
return false, nil, apimiddleware.InternalServerError(fmt.Errorf("unsupported block version '%s'", respContainer.Version))
}

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