Compare commits

...

336 Commits

Author SHA1 Message Date
terence tsao
d9affb927b Init map 2023-04-05 14:41:58 -07:00
Kasey Kirkham
b3d509a5a1 fixing several initial-sync blob bugs 2023-04-05 16:13:45 -05:00
Kasey Kirkham
a8d154f75e 🤦 2023-04-05 14:39:01 -05:00
Kasey Kirkham
8bd5a265dd unblinded blocks had serious commitment issues 2023-04-05 14:30:04 -05:00
Kasey Kirkham
8dc84411b2 bug fixes and chatty logs 2023-04-04 16:50:52 -05:00
Kasey Kirkham
0d0147b0cb deneb changes for exec engine api
Unblinding blocks without these changes resulted in mtuating the block
type, transforming deneb blocks into capella blocks.
note debug logs in beacon-chain/sync/rpc_chunked_response.go
2023-04-04 15:45:07 -05:00
Kasey Kirkham
60ab9f22c1 simplify batch block logic 2023-04-03 14:34:56 -05:00
Kasey Kirkham
eede6ec2c4 WIP debugging 2023-04-03 13:38:46 -05:00
Kasey Kirkham
bea41af396 fixes 2023-03-31 09:42:23 -05:00
Kasey Kirkham
8a0ef4a85c janky initial-sync blob downloading 2023-03-30 20:39:53 -05:00
terence tsao
7c9bb47f99 Implement send blob by range request 2023-03-30 13:39:54 -05:00
Radosław Kapka
d5dadc75e4 Block rewards API endpoint (#12020)
Co-authored-by: terencechain <terence@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2023-03-30 13:50:33 +02:00
kasey
12d0a4ceeb Separate EE blob type (#12203)
* BlobSidecar.Blob should be a byte slice

* remove engine Blob type from db

---------

Co-authored-by: Kasey Kirkham <kasey@users.noreply.github.com>
2023-03-28 20:12:44 -05:00
terencechain
18743ec30f Blob by root fixes (#12202) 2023-03-28 16:39:30 -07:00
kasey
dc8ba012e9 MarshalSSZ/UnmarshalSSZ for blob sidecar req (#12200)
* ser/des methods for BlobSidecarsByRootReq

* lint

---------

Co-authored-by: Kasey Kirkham <kasey@users.noreply.github.com>
2023-03-28 14:43:36 +00:00
Kasey Kirkham
8dddf1eaeb simplifying blinded block reconstruction code 2023-03-27 20:20:14 -05:00
kasey
66727a853f separate block bather code from blocks rpc 2023-03-27 16:30:49 -05:00
terence tsao
10fadd0ac3 Merge branch 'develop' of github.com:prysmaticlabs/prysm into eip4844 2023-03-27 13:51:32 -07:00
terence tsao
b9ec6837ab Merge branch 'develop' of github.com:prysmaticlabs/prysm into eip4844 2023-03-27 13:48:54 -07:00
kasey
0254d31810 WIP: BlobDB changes (#12193)
* hide ethpb.BlobSidecars in kv pkg only

* Add variadic indices arg to blob retrieval methods

* raul review

---------

Co-authored-by: kasey <kasey@users.noreply.github.com>
2023-03-27 19:52:00 +00:00
terencechain
25ce2ac4dc Fix eip4844 unit tests (#12190) 2023-03-27 09:20:56 -07:00
kasey
80e9042c6b BlobsByRange RPC (#12092) 2023-03-24 13:06:55 -07:00
terencechain
6b7e8ac00e Use blob getters from DB and fix tests (#12166) 2023-03-24 09:40:47 -07:00
terencechain
ca770f12ee EIP4844: gossip fixes (#12179) 2023-03-23 09:07:31 -07:00
terence tsao
74bebd9244 Set execution when there's a blob 2023-03-22 11:34:13 -07:00
terencechain
447b42044a Fix interop bugs (#12172) 2023-03-21 09:18:45 -07:00
kasey
6ec8d23d4f add missing field to proto copy helper (#12171) 2023-03-21 08:57:00 -07:00
terence tsao
a41d80a03d Add capella fork epoch 2023-03-20 18:52:25 -07:00
terencechain
849c1dd25b Add blob db methods (#12157) 2023-03-19 16:38:37 -07:00
terence tsao
d430266b70 Merge branch 'develop' of github.com:prysmaticlabs/prysm into eip4844 2023-03-18 07:54:49 -07:00
terence tsao
6d52516638 Update v3 to v4 2023-03-17 12:55:16 -07:00
terence tsao
2ff3a82eac Merge branch 'develop' of github.com:prysmaticlabs/prysm into eip4844 2023-03-17 12:35:54 -07:00
terence tsao
d403b68d76 Clean up old code 2023-03-17 12:10:11 -07:00
terence tsao
b0768e39c3 Use copy 2023-03-16 16:53:14 -07:00
terence tsao
cae57ee9f6 Fix spec tests 2023-03-16 13:54:47 -07:00
terence tsao
3104fd217d Merge branch 'develop' of github.com:prysmaticlabs/prysm into eip4844 2023-03-16 13:28:00 -07:00
terencechain
d1b9954566 Use block blobs queue for sync (#12129) 2023-03-16 13:23:56 -07:00
terencechain
033b165c08 Add KZG proof and new gossip condition (#12136) 2023-03-16 12:53:15 -07:00
terencechain
78175ee0fd Update and clean up validators for devnet5 (#12131) 2023-03-15 11:54:57 -07:00
terence tsao
a34cc7f7bf Update geth] 2023-03-15 10:51:52 -07:00
terence tsao
6f22cd7963 Merge branch 'develop' of github.com:prysmaticlabs/prysm into eip4844 2023-03-14 14:34:45 -07:00
terencechain
58967e4516 Rm blobs sidecar usages (#12118) 2023-03-13 11:34:20 -07:00
terence tsao
947c9fbe60 Merge branch 'develop' of github.com:prysmaticlabs/prysm into eip4844 2023-03-13 08:04:23 -07:00
terence tsao
8cc1e67e6c Merge branch 'develop' of github.com:prysmaticlabs/prysm into eip4844 2023-03-10 08:23:09 -08:00
terencechain
2f3deac8b0 Make eip4844 green again (#12093) 2023-03-10 07:32:09 -08:00
terencechain
aa44ba40ab Add blob gossip (#12007) 2023-03-07 20:05:43 -08:00
terencechain
8b268d646c Add block and blobs cache (#12088) 2023-03-07 15:32:36 -08:00
kasey
d6ecadb471 BlobsByRoot RPC (#12011)
* boilerplate for block&block-by-root->blob-by-root

* add db interface to service and use in handler

* rm unused requestBlockAndSidecarByRoot

* add test for base case of sidecar by root

* test blob slot < min req epoch, other fixes

* cleaning up test mess

* rm unused func

* add BroadcastBlob method stubs to fix build

* handler name consistent with path

* initialize blob queue for test

* lint & gaz

* update mock to satisfy interface

* fix wrong sig for mock

* clean up min req epoch, no underflow, + tests

---------

Co-authored-by: kasey <kasey@users.noreply.github.com>
2023-03-07 09:45:01 -06:00
terence tsao
9a8bde448e Sync with develop 2023-03-06 16:16:18 -08:00
terence tsao
ce71b3b6b1 Merge branch 'develop' of github.com:prysmaticlabs/prysm into eip4844 2023-03-06 15:56:29 -08:00
terence tsao
5fa30bf73a Merge branch 'develop' of github.com:prysmaticlabs/prysm into eip4844 2023-02-23 15:45:32 -08:00
terencechain
b93aba6126 Add validator signing decoupled blobs (#12015) 2023-02-23 13:26:45 -08:00
terence tsao
51ed80df69 Fix build 2023-02-23 09:22:38 -08:00
terencechain
a614c4ac8c Add broadcast blob method (#12016) 2023-02-23 07:52:58 -08:00
terencechain
7b777a10a5 EIP4844: update excessive data gas field and pass spec tests (#12032) 2023-02-22 10:19:32 -08:00
terence tsao
bf1ab9951f Merge branch 'develop' of github.com:prysmaticlabs/prysm into eip4844 2023-02-22 06:59:31 -08:00
terencechain
5cea2b3855 Revert block gossip changes to before coupling (#12012) 2023-02-21 17:06:11 -08:00
terencechain
ab63757fe5 Add decoupled blob protobufs (#12002) 2023-02-16 11:10:55 -08:00
terencechain
736ed1e003 Fix spec tests after renamed EIP4844 to Deneb (#12005) 2023-02-16 11:10:37 -08:00
terence tsao
6ee9707fd7 Sync with develop 2023-02-16 08:49:00 -08:00
terence tsao
e40835b1a9 Merge branch 'develop' of github.com:prysmaticlabs/prysm into eip4844 2023-02-16 08:20:20 -08:00
terence tsao
216a420bbc Sync with master 2023-01-28 14:19:50 +01:00
terence tsao
4845abecb8 Merge branch 'develop' of github.com:prysmaticlabs/prysm into eip4844 2023-01-28 13:09:08 +01:00
James He
08a910e44f renaming to proto endpoint 2023-01-27 16:30:24 +01:00
terence tsao
67ba2c4fe3 Add slash 2023-01-27 15:36:10 +01:00
terence tsao
7efa501bdc Fix space 2023-01-27 15:35:57 +01:00
terence tsao
879a694ab3 Another nil check 2023-01-27 10:15:04 +01:00
terence tsao
4e3b1881ed Add check for nil block 2023-01-27 09:44:15 +01:00
Inphi
35d3707de7 sync: Fix BlobsSidecarByRange rate limiting (#11920) 2023-01-26 07:48:39 +01:00
terence tsao
1f468bd3f5 Rm field params 2023-01-25 10:49:06 +01:00
terence tsao
ac32098c86 Merge branch 'init-nil-withdrawals' into eip4844 2023-01-25 10:32:11 +01:00
terence tsao
e0af005c42 Initialize nil withdrawals at marshal / unmarshal 2023-01-25 10:29:44 +01:00
Francis Li
f08af1bdbf Fix eip4844 branch errors (#11901) 2023-01-24 11:52:05 +01:00
terence tsao
6d0420fde5 Merge branch 'eip4844' of github.com:prysmaticlabs/prysm into eip4844 2023-01-24 11:41:40 +01:00
terence tsao
5172e6e362 Rate limiter 2023-01-24 11:41:08 +01:00
Inphi
42df0f70b6 sync: Re-broadcast block and blobs sidecar (#11907) 2023-01-24 11:15:57 +01:00
terence tsao
dace0f6a2d Rename eip4844 to deneb 2023-01-19 17:30:36 -08:00
terence tsao
26a5878181 Write bad block and blob to disk 2023-01-18 14:02:09 -08:00
terence tsao
db6474a3e4 Sync with develop 2023-01-18 12:00:48 -08:00
terence tsao
b84851fd0d Merge branch 'develop' of github.com:prysmaticlabs/prysm into eip4844 2023-01-18 08:38:13 -08:00
terence tsao
673702c100 Fix loop referencing for kzgs 2023-01-12 15:50:46 -08:00
terence tsao
520eb6baca Rm unused checks 2023-01-12 10:36:21 -08:00
terence tsao
e6047dc344 Merge branch 'capella' of github.com:prysmaticlabs/prysm into eip4844 2023-01-11 14:59:00 -08:00
terence tsao
d86a452b15 Merge branch 'develop' of github.com:prysmaticlabs/prysm into capella 2023-01-11 14:52:26 -08:00
terence tsao
67f9d0b9c4 Fix log 2023-01-11 08:08:33 -08:00
terence tsao
21cd055b84 Better logs 2023-01-11 07:40:19 -08:00
Kasey Kirkham
9f3bb623ec add capella to yaml "template" 2023-01-10 16:30:32 -06:00
Kasey Kirkham
b10a95097e capella state version detection bug fix 2023-01-10 15:54:27 -06:00
terence tsao
4561f5cacb Clean ups 2023-01-09 14:33:05 -08:00
terence tsao
50b672a4db Beacon api: get blobs 2023-01-09 11:40:06 -08:00
Potuz
ffbb73a59b Merge remote-tracking branch 'origin/develop' into capella 2023-01-09 12:07:00 -03:00
Potuz
649974f14d removed duplicated case 2023-01-09 09:54:15 -03:00
Potuz
9ec0bc0734 Merge remote-tracking branch 'origin/historical-summaries' into capella 2023-01-09 08:57:24 -03:00
terence tsao
9649e49658 Passing spec tests 2023-01-07 08:50:20 -08:00
terence tsao
49fdcb7347 Add spec tests 2023-01-07 08:33:48 -08:00
terence tsao
cd6ee956ed Merge branch 'historical-summaries' into eip4844 2023-01-07 08:03:15 -08:00
terence tsao
ef95fd33f8 Uncomment withdrawal stubs 2023-01-07 07:52:31 -08:00
terence tsao
1a488241b0 Sync with capella 2023-01-07 07:48:57 -08:00
terence tsao
5fdd3a3d66 Merge branch 'capella' of github.com:prysmaticlabs/prysm into eip4844 2023-01-07 07:19:55 -08:00
terence tsao
b6a32c050f Merge branch 'develop' of github.com:prysmaticlabs/prysm into capella 2023-01-07 07:03:58 -08:00
terence tsao
055e225093 Passing spec tests 2023-01-06 15:18:38 -08:00
terence tsao
144218cb1b Process historical roots test 2023-01-06 11:56:24 -08:00
Potuz
13b575a609 Merge remote-tracking branch 'origin/develop' into capella 2023-01-06 10:59:43 -03:00
terence tsao
b5a414eae9 Rm bad imports 2023-01-04 08:10:27 -08:00
terence tsao
b94b347ace Sync with develop 2023-01-04 07:37:25 -08:00
terence tsao
f5ee225819 Merge branch 'develop' of github.com:prysmaticlabs/prysm into capella 2023-01-04 07:16:00 -08:00
terence tsao
9cb48be14f Add historical summaries to state and processing 2023-01-03 15:58:39 -08:00
terence tsao
85fa9951eb Fix span name 2022-12-24 23:40:30 +08:00
terence tsao
ec72575fc9 Close stream for by root rpc handler 2022-12-24 23:34:02 +08:00
terence tsao
d9d1bb6d3d Skip on empty 2022-12-24 11:37:58 +08:00
Potuz
ffcdc26618 Merge remote-tracking branch 'origin/develop' into capella 2022-12-23 13:03:11 -03:00
Potuz
96981a07b9 check signatures of BLS changes before capella 2022-12-22 16:10:00 -03:00
Potuz
6b2721b239 Check BLS_TO_EXECUTION_CHANGE as if they were from Capella
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.
2022-12-22 11:34:57 -03:00
terence tsao
c79151a574 Fix rate limiter 2022-12-22 22:10:34 +08:00
Inphi
4b20234801 Fix missing context in post-altair /v1 messages (#11807) 2022-12-22 06:46:15 +08:00
terence tsao
911048aa6d Merge branch 'develop' of github.com:prysmaticlabs/prysm into capella 2022-12-21 13:01:40 +08:00
James He
255e9693ee fixing typo on comments 2022-12-20 22:42:31 -06:00
terence tsao
61c1216e3d Better handling for validate sync msg time 2022-12-21 10:08:44 +08:00
terence tsao
17e1eaf0f3 Set stream write deadline 2022-12-21 09:38:00 +08:00
terence tsao
9940943595 Clean up sync 2022-12-21 09:30:11 +08:00
terence tsao
9a0f941870 Change avgSidecarBlobsTransferBytes 2022-12-21 08:32:47 +08:00
terence tsao
5d0f54d332 Blobs rate limiter 2022-12-21 08:17:54 +08:00
rkapka
d602c94b7b fix 2022-12-20 20:28:53 +01:00
rkapka
6a5ecbd68f Implement getPoolBLSToExecutionChanges API endpoint
(cherry picked from commit cd25d922bc)

# Conflicts:
#	beacon-chain/node/node.go
#	beacon-chain/rpc/eth/beacon/pool.go
#	proto/eth/service/beacon_chain_service.pb.go
#	proto/migration/v1alpha1_to_v2.go
2022-12-20 17:31:21 +01:00
Potuz
29dfcab505 Fix BlockValue marshalling 2022-12-19 11:14:35 -03:00
Potuz
16e5c903cc Merge remote-tracking branch 'origin/develop' into capella 2022-12-19 10:28:05 -03:00
terencechain
66682cb4e5 Clean up block initizliation and remove set block (#11791) 2022-12-19 15:41:28 +08:00
terencechain
52faea8b7d Support 4844 container type queries in the beacon API + update spec tests (#11794) 2022-12-19 15:38:23 +08:00
terence tsao
8a78315682 Save blobs during by range sync 2022-12-18 07:44:30 +08:00
Potuz
cab42a4ae3 Take raw arrays for BLS changes 2022-12-16 18:02:35 -03:00
Potuz
a5bdd42bdd Merge remote-tracking branch 'origin/block-value' into capella 2022-12-16 12:47:29 -03:00
Potuz
a26197f919 take lists for bls changes endpoint 2022-12-16 12:47:18 -03:00
terence tsao
8b9cab457e Got block and blobs gossip working 2022-12-16 13:41:59 +08:00
terence tsao
080ce31395 Add block value to get payload v2 2022-12-15 17:17:58 +08:00
terence tsao
7866e8a196 Got blob syncing to work 2022-12-15 17:02:38 +08:00
Potuz
d5d17e00b3 Merge branch 'develop' into capella 2022-12-14 13:04:23 -03:00
rkapka
9c6a1331cf remove redeclared struct 2022-12-14 16:29:14 +01:00
terence tsao
d89c97634c Merge branch 'eip4844' of github.com:prysmaticlabs/prysm into eip4844 2022-12-14 10:26:47 +08:00
terence tsao
7e95ca3705 Add blobs to initial syncing path 2022-12-14 10:26:39 +08:00
Inphi
abd46b01b7 Fix non-empty kzg commitment in proposal (#11766) 2022-12-14 08:06:14 +08:00
Potuz
8629ac8417 only broadcast bls changes post-capella 2022-12-13 09:53:05 -03:00
terence tsao
304925aabf Add todos for 4844 sync 2022-12-13 16:18:09 +08:00
terence tsao
16d93e47a5 Merge branch 'capella' of github.com:prysmaticlabs/prysm into eip4844 2022-12-13 15:12:46 +08:00
rkapka
6dcb2bbf0d Use signed changes in middleware block
(cherry picked from commit e3c9e7bb5c)
2022-12-12 16:21:39 +01:00
Potuz
deb138959a fix validator client 2022-12-12 11:43:48 -03:00
Potuz
45e6f3bd00 fix build 2022-12-12 11:29:57 -03:00
Potuz
55a9e0d51a Merge branch 'develop' into capella 2022-12-12 11:15:39 -03:00
terence tsao
3ddae600fb Merge branch 'capella' of github.com:prysmaticlabs/prysm into capella 2022-12-09 19:35:39 -08:00
terence tsao
861ede8945 Fix subscriptions 2022-12-09 15:29:23 -08:00
terence tsao
93f11f9047 Change target / max blobs to 2 / 4 2022-12-09 10:40:20 -08:00
rkapka
56503110dd Merge branch 'recontruct-capella-blinded' into capella
# Conflicts:
#	testing/spectest/shared/common/forkchoice/service.go
2022-12-09 12:45:23 +01:00
rkapka
f67d35dffd single execution block type 2022-12-09 12:43:35 +01:00
terence tsao
efbca1b5b7 Add v3 engine apis 2022-12-08 16:45:05 -08:00
terence tsao
2de0ebaf8d Merge branch 'roberto-fix-auth' into eip4844 2022-12-08 13:52:11 -08:00
Roberto Bayardo
0815ef94a3 Merge branch 'develop' into roberto-fix-auth 2022-12-08 13:23:29 -08:00
Roberto Bayardo
092ffa99e5 update & fix code around setting auth header for latest geth 2022-12-08 13:14:09 -08:00
rkapka
b05b67b264 reorder checks 2022-12-08 19:48:02 +01:00
rkapka
a5c6518c20 deepsource 2022-12-08 19:48:02 +01:00
Radosław Kapka
da048395ce Merge branch 'develop' into recontruct-capella-blinded 2022-12-08 18:41:12 +01:00
rkapka
f31f7be310 fix engine mock 2022-12-08 18:39:59 +01:00
rkapka
e1a2267f86 Merge remote-tracking branch 'origin/capella' into capella 2022-12-08 18:36:44 +01:00
rkapka
3c9e4ee7f7 Merge branch 'recontruct-capella-blinded' into capella
# Conflicts:
#	beacon-chain/blockchain/pow_block.go
#	beacon-chain/execution/engine_client.go
#	beacon-chain/execution/engine_client_test.go
#	beacon-chain/execution/testing/mock_engine_client.go
#	beacon-chain/rpc/eth/beacon/blocks.go
#	beacon-chain/state/state-native/getters_withdrawal.go
#	consensus-types/blocks/factory.go
#	proto/engine/v1/json_marshal_unmarshal.go
#	proto/engine/v1/json_marshal_unmarshal_test.go
2022-12-08 18:31:25 +01:00
rkapka
9ba32c9acd single ExecutionBlockByHash function 2022-12-08 17:53:02 +01:00
rkapka
d23008452e fix failing tests 2022-12-08 17:29:51 +01:00
terencechain
f397cba1e0 Better proposal RPC (#11721) 2022-12-08 07:40:48 -08:00
terence tsao
3eecbb5b1a Fix enum for cli 2022-12-07 12:12:56 -08:00
rkapka
1583e93b48 bzl 2022-12-07 18:23:43 +01:00
rkapka
849457df81 deepsource
(cherry picked from commit 903cab75ee)

# Conflicts:
#	beacon-chain/execution/testing/mock_engine_client.go
2022-12-07 16:29:34 +01:00
rkapka
903cab75ee deepsource 2022-12-07 16:27:09 +01:00
rkapka
ee108d4aff add doc to interface
(cherry picked from commit a08baf4a14)
2022-12-07 16:22:14 +01:00
rkapka
49bcc58762 rename methods
(cherry picked from commit 8c56dfdd46)
2022-12-07 16:22:09 +01:00
rkapka
a08baf4a14 add doc to interface 2022-12-07 16:20:43 +01:00
rkapka
8c56dfdd46 rename methods 2022-12-07 16:20:31 +01:00
rkapka
dcdd9af9db remove unneeded test 2022-12-07 16:05:44 +01:00
rkapka
a464cf5c60 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
2022-12-07 15:21:58 +01:00
terence tsao
cc55c754dc Fix cli flag 2022-12-06 16:57:50 -08:00
terence tsao
2d483ab09f Merge branch 'develop' of github.com:prysmaticlabs/prysm into capella 2022-12-06 16:48:44 -08:00
terence tsao
d64e10a337 Interop 2022-12-06 16:06:18 -08:00
terence tsao
1e9ee10674 Merge branch 'better-validator-rpcs' of github.com:prysmaticlabs/prysm into eip4844 2022-12-06 15:14:20 -08:00
terence tsao
3ac395b39e Merge branch 'capella' of github.com:prysmaticlabs/prysm into eip4844 2022-12-06 14:42:49 -08:00
Justin Traglia
6e26a6f128 Replace LastWithdrawalValidatorIndex to updated name (#11725) 2022-12-06 14:40:10 -08:00
Justin Traglia
b512b92a8a Update withdrawal error message to reflect new field name (#11724) 2022-12-06 14:39:17 -08:00
terence tsao
5ff601a1b9 Sync with latest go-ethereum changes 2022-12-06 14:38:14 -08:00
terence tsao
5823054519 Merge branch 'develop' of github.com:prysmaticlabs/prysm into eip4844 2022-12-06 14:08:00 -08:00
terence tsao
3d196662bc Merge branch 'capella' of github.com:prysmaticlabs/prysm into eip4844 2022-12-06 14:06:30 -08:00
rkapka
b0601580ef Merge branch 'reconstruct-capella-block' into capella 2022-12-06 22:16:59 +01:00
rkapka
c1f29ea651 remove logs 2022-12-06 22:11:35 +01:00
rkapka
881d1d435a logs 2022-12-06 21:46:41 +01:00
rkapka
d1aae0c941 Merge branch 'capella' into reconstruct-capella-block 2022-12-06 21:26:55 +01:00
terence tsao
468cc23876 Fix interop 2022-12-04 08:40:41 -08:00
terence tsao
d9646a9183 Add builder paths 2022-12-03 07:29:46 -08:00
terence tsao
279cee42f1 Refactor block proposal path 2022-12-02 16:13:01 -08:00
terence tsao
57bdb907cc Merge branch 'develop' of github.com:prysmaticlabs/prysm into capella 2022-12-02 11:10:39 -08:00
rkapka
15d683c78f Merge branch 'capella' into reconstruct-capella-block 2022-12-02 16:43:56 +01:00
rkapka
bf6c8ced7d working 2022-12-02 16:37:24 +01:00
Potuz
78fb685027 Check BLS changes when requesting from the pool 2022-12-02 10:14:39 -03:00
terence tsao
a87536eba0 Fix minimal spec test 2022-12-01 15:26:18 -08:00
terence tsao
3f05395a00 Merge branch 'capella' of github.com:prysmaticlabs/prysm into eip4844 2022-12-01 14:52:49 -08:00
terence tsao
85fc57d41e Merge branch 'develop' of github.com:prysmaticlabs/prysm into eip4844 2022-12-01 14:45:31 -08:00
terence tsao
1e5976d5ce Mainnet spec tests passing 2022-12-01 14:41:34 -08:00
Potuz
98c0b23350 broadcast BLS changes 2022-12-01 11:26:56 -03:00
terence tsao
039a0fffba Merge branch 'develop' of github.com:prysmaticlabs/prysm into capella 2022-11-30 12:09:47 -08:00
Potuz
90ec640e7a Fix capella operations spectests 2022-11-30 15:35:55 -03:00
Potuz
10acd31d25 check on verify instead of sig 2022-11-30 15:20:23 -03:00
terence tsao
4224014fad Add 4844 block and state 2022-11-30 10:14:35 -08:00
Potuz
df1e8b33d8 BLS Change signature verification 2022-11-30 14:52:31 -03:00
rkapka
cdb4ee42cc not working 2022-11-30 18:22:52 +01:00
rkapka
d29baec77e proper error handling in BuildSignedBeaconBlockFromExecutionPayload 2022-11-30 15:32:57 +01:00
terence tsao
53c189da9b Merge branch 'update-eip4844-objs' into eip4844 2022-11-29 21:16:31 -08:00
terence tsao
277fbce61b Update eip4844 objects 2022-11-29 21:15:14 -08:00
terence tsao
0adc54b7ff Refactor get payload 2022-11-29 12:02:47 -08:00
Potuz
1cbd7e9888 withdraw by default 2022-11-29 13:52:34 -03:00
rkapka
0a9e1658dd move stuff to blinded_blocks.go 2022-11-29 17:36:52 +01:00
rkapka
31d4a4cd11 test other functions 2022-11-29 17:36:52 +01:00
rkapka
fbc4e73d31 refactor and test GetSSZBlockV2 2022-11-29 17:36:52 +01:00
rkapka
c1d4eaa79d refactor and test GetBlockV2 2022-11-29 17:36:52 +01:00
rkapka
760af6428e update ssz 2022-11-29 17:36:52 +01:00
terence tsao
dfa0ccf626 Fix attribute pb nil checks 2022-11-29 07:27:33 -08:00
terence tsao
7a142cf324 Merge branch 'capella' of github.com:prysmaticlabs/prysm into eip4844 2022-11-29 07:09:41 -08:00
rkapka
1a51fdbd58 update withdrawals proto 2022-11-29 14:23:11 +01:00
terencechain
368a99ec8d Fix nil attribute for capella branch (#11701) 2022-11-28 17:34:26 -08:00
terence tsao
1c7e734918 Fix some blockchain tests 2022-11-28 13:59:17 -08:00
rkapka
764d1325bf Merge remote-tracking branch 'origin/capella' into capella 2022-11-28 21:07:00 +01:00
rkapka
0cf30e9022 Merge branch '__develop' into capella 2022-11-28 21:06:20 +01:00
Potuz
227b20f368 fix nil block from stream 2022-11-28 16:53:11 -03:00
rkapka
d7d70bc25b support SSZ lol
(cherry picked from commit 52bc2c8d617ac3e1254c493fa053cdce4a1ebd63)
2022-11-28 20:19:24 +01:00
rkapka
82f6ddb693 add Capella version
(cherry picked from commit 5d6fd0bbe663e5dd16df5b2e773f68982bbcd24e)
2022-11-28 20:19:19 +01:00
rkapka
9e4e82d2c5 refactor GetBlindedBlockSSZ
(cherry picked from commit 97483c339f99b0d96bd81846a979383ffd2b0cda)

# Conflicts:
#	beacon-chain/rpc/eth/beacon/blocks.go
2022-11-28 20:19:15 +01:00
rkapka
9838369fe9 fix proto generation 2022-11-28 20:15:05 +01:00
rkapka
6085ad1bfa fix issues 2022-11-28 20:07:37 +01:00
rkapka
d3851b27df Merge branch '__develop' into capella
# Conflicts:
#	beacon-chain/rpc/apimiddleware/structs.go
#	beacon-chain/rpc/eth/beacon/blocks.go
#	proto/eth/v2/BUILD.bazel
#	proto/eth/v2/beacon_block.pb.go
#	proto/eth/v2/beacon_block.proto
#	proto/eth/v2/generated.ssz.go
#	proto/migration/v1alpha1_to_v2.go
#	proto/prysm/v1alpha1/beacon_chain.pb.go
#	proto/prysm/v1alpha1/beacon_chain.proto
2022-11-28 19:31:33 +01:00
Potuz
d6100dfdcb fix spectest 2022-11-28 12:38:14 -03:00
Potuz
c2144dac86 Add BLSToExecutionChangge endpoint 2022-11-27 23:00:16 -03:00
Potuz
a47ff569a8 Add Submit BLSChange endpoint 2022-11-27 20:50:21 -03:00
Potuz
f8be022ef2 Merge branch 'develop' into capella 2022-11-27 20:40:41 -03:00
Potuz
4f39e6b685 Implement REST block API endpoints 2022-11-27 16:20:30 -03:00
Potuz
c67b000633 add test 2022-11-27 13:07:50 -03:00
Potuz
02f7443586 Refactor Sync Committee Rewards 2022-11-27 09:04:03 -03:00
terence tsao
6275e7df4e Clean up execution engine 2022-11-25 17:20:28 -08:00
terencechain
1b6b52fda1 Add PayloadAttribute superset and use it for engine-api (#11691) 2022-11-25 17:12:55 -08:00
Potuz
5fa1fd84b9 Hook the BLSTOExecution Pool to the proposer 2022-11-25 09:33:17 -03:00
nisdas
bd0c9f9e8d fix 2022-11-25 09:06:59 -03:00
Potuz
2532bb370c Merge branch 'develop' into capella 2022-11-25 08:16:32 -03:00
nisdas
12efc6c2c1 make it reject 2022-11-24 22:21:12 +08:00
nisdas
a6cc9ac9c5 add sig validation 2022-11-24 22:19:55 +08:00
nisdas
031f5845a2 add gossip handler for bls change object 2022-11-24 21:22:18 +08:00
nisdas
b88559726c Merge branch 'develop' of https://github.com/prysmaticlabs/geth-sharding into capella 2022-11-24 20:05:41 +08:00
terence tsao
ca6ddf4490 Add and use send blocks and sidecars requests 2022-11-23 16:11:06 -08:00
terence tsao
3ebb2fce94 Merge branch 'capella' of github.com:prysmaticlabs/prysm into eip4844 2022-11-23 14:21:45 -08:00
nisdas
62f6b07cba fix gossip registration 2022-11-23 20:10:44 +08:00
terence tsao
f956f1ed6e Handle capella version for packing atts 2022-11-22 17:21:21 -08:00
terence tsao
1c0fa95053 Fix forkchoice test 2022-11-22 17:09:34 -08:00
terence tsao
04bf4a1060 Clean up 2022-11-22 15:38:24 -08:00
terence tsao
ae276fd371 Add mainnet spec tests 2022-11-22 10:53:47 -08:00
terence tsao
104bdaed12 Merge branch 'capella' of github.com:prysmaticlabs/prysm into eip4844 2022-11-22 09:43:43 -08:00
terence tsao
089a5d6ac2 Migrate from geth's kzg lib to go-kzg/eth (Thanks @roberto-bayardo) 2022-11-22 08:51:45 -08:00
Potuz
16b0820193 Merge branch 'develop' into capella 2022-11-22 13:43:03 -03:00
Potuz
4b02267e96 add more minimal fixes 2022-11-22 13:34:33 -03:00
Potuz
746584c453 fix missing minimal test 2022-11-22 13:34:33 -03:00
Potuz
b56daaaca2 Fix empty withdrawals slice 2022-11-22 10:38:42 -03:00
terence tsao
b7a6fe88ee Update block and sidecar gossip conditions 2022-11-21 14:38:44 -08:00
terence tsao
22d1c37b92 Merge branch 'develop' of github.com:prysmaticlabs/prysm into eip4844 2022-11-20 19:22:30 -08:00
terence tsao
78a393f825 Merge branch 'develop' of github.com:prysmaticlabs/prysm into eip4844 2022-11-18 13:48:40 -08:00
terence tsao
ac8290c1bf Port over shared kzg functions and updated trusted setup 2022-11-18 10:55:35 -08:00
terence tsao
5d0662b415 Merge branch 'develop' of github.com:prysmaticlabs/prysm into eip4844 2022-11-18 10:00:32 -08:00
terence tsao
931e5e10c3 Fix mainnet fork transition tests 2022-11-16 08:49:06 -05:00
Potuz
c172f838b1 Mark capella fields as dirty 2022-11-15 09:58:34 -05:00
Potuz
c07ae29cd9 move MaxWithdrawalsPerPayload to fieldparams 2022-11-14 22:59:31 -05:00
Potuz
214c9bfd8b fix bls_to_execution_changes 2022-11-14 16:41:17 -05:00
Potuz
716140d64d add bls_to_execution_change tests 2022-11-14 16:26:39 -05:00
Potuz
088cb4ef59 fix expected_withdrawals 2022-11-14 14:50:41 -05:00
terence tsao
fa33e93a8e Merge branch 'develop' of github.com:prysmaticlabs/prysm into eip4844 2022-11-14 08:53:15 -05:00
Potuz
d1472fc351 Add withdrawals operations tests 2022-11-13 08:54:59 -03:00
terence tsao
5c8c0c31d8 Merge branch 'capella-withdrawal-minimal' into capella 2022-11-12 22:06:43 -08:00
terence tsao
7f3c00c7a2 Can build 2022-11-12 22:06:22 -08:00
terencechain
c180dab791 Merge branch 'develop' into capella 2022-11-12 18:28:18 -08:00
terence tsao
f24acc21c7 Fix bazel 2022-11-12 17:43:19 -08:00
terence tsao
40b637849d Fix miminal capella tests 2022-11-12 17:26:05 -08:00
terence tsao
e7db1685df Add mainnet capella tests 2022-11-12 17:13:26 -08:00
terence tsao
eccbfd1011 Add shared capella spec tests helpers 2022-11-12 17:13:16 -08:00
terence tsao
90211f6769 Fix prev epoch attested precompute 2022-11-12 17:12:29 -08:00
terence tsao
edc32ac18e Fix slashing quotient 2022-11-12 17:12:04 -08:00
terence tsao
fe68e020e3 Add selector with minimal withdrawal size 2022-11-12 16:18:16 -08:00
terence tsao
81e1e3544d Add mainnet ssz vectors 2022-11-12 15:50:07 -08:00
Potuz
09372d5c35 Revert "added mainnet ssz tests"
This reverts commit 078a89e4ca.
2022-11-12 18:40:28 -03:00
Potuz
078a89e4ca added mainnet ssz tests 2022-11-12 18:39:11 -03:00
Potuz
dbc6ae26a6 Add minimal support for capella spec tests
Fixed many issues about hashing
Added fork typing in the state replayer
2022-11-12 18:18:35 -03:00
Potuz
b6f429867a Merge branch 'develop' into capella 2022-11-12 16:35:20 -03:00
Potuz
09f50660ce Merge branch 'develop' into capella 2022-11-12 11:51:06 -03:00
Potuz
189825b495 fix withdrawal hashing 2022-11-11 23:21:41 -03:00
terence tsao
441cad58d4 Merge commit 'e03de47db7b782bdf7dc8d9b42749eb2a236cdea' into eip4844 2022-11-11 09:18:57 -08:00
terence tsao
1277d08f9e Merge branch 'develop' of github.com:prysmaticlabs/prysm into eip4844 2022-11-11 08:46:39 -08:00
terence tsao
e03de47db7 Ops, wrong branch 2022-11-11 08:45:22 -08:00
Potuz
764b7ff610 Don't build capella payload twice 2022-11-11 10:47:29 -03:00
terence tsao
307be7694e Merge branch 'develop' of github.com:prysmaticlabs/prysm into eip4844 2022-11-09 16:44:34 -08:00
terence tsao
c76ae1ef39 Add beacon_block_and_blobs_sidecar gossip 2022-11-09 16:43:26 -08:00
Potuz
d499db7f0e Merge branch 'develop' into capella 2022-11-09 21:27:18 -03:00
terence tsao
a894b9f29a Merge branch 'develop' of github.com:prysmaticlabs/prysm into eip4844 2022-11-09 14:49:18 -08:00
terence tsao
902e6b3905 Update to use latest kzg library 2022-11-09 10:17:27 -08:00
Potuz
ed2d1c7bf9 Merge branch 'develop' into capella 2022-11-09 09:14:55 -03:00
nisdas
14b73cbd47 register flag 2022-11-09 08:48:36 +08:00
terence tsao
a39c7aa864 Add rpc blobs sidecars by range 2022-11-07 14:53:12 -08:00
terence tsao
170bc9c8ec Network changes 2022-11-07 14:43:46 -08:00
terence tsao
365c01fc29 Add tests 2022-11-07 06:58:24 -08:00
Potuz
3124785a08 Merge branch 'develop' into capella 2022-11-07 10:08:09 -03:00
Potuz
60e6306107 working withrawals initial commits 2022-11-06 16:53:57 -03:00
terence tsao
42ccb7830a Add Capella DB changes 2022-11-06 15:25:34 -03:00
Potuz
0bb03b9292 fix marshalling and engine calls 2022-11-06 15:24:22 -03:00
nisdas
ed6fbf1480 stupid bug 2022-11-07 00:18:01 +08:00
nisdas
477cec6021 wei it 2022-11-07 00:13:12 +08:00
nisdas
924500d111 add unmarshal 2022-11-06 23:57:37 +08:00
Potuz
0677504ef1 Revert "proposer changes"
This reverts commit ca2a7c4d9c.
2022-11-06 12:16:53 -03:00
Potuz
ca2a7c4d9c proposer changes 2022-11-06 12:14:17 -03:00
Potuz
28606629ad marshalling stub 2022-11-06 12:03:25 -03:00
Potuz
c817279464 fix capella payload 2022-11-06 11:14:39 -03:00
Potuz
009d6ed8ed proposer logic 2022-11-06 10:49:32 -03:00
Potuz
5cec1282a9 FCU two versions 2022-11-06 10:22:45 -03:00
Potuz
340170fd29 propose block V2 2022-11-06 09:42:20 -03:00
Potuz
7ed0cc139a marshalling first attempt 2022-11-06 07:47:43 -03:00
Potuz
2c822213eb rpc changes 2022-11-06 00:24:56 -03:00
terence tsao
0894b9591c Add Capella DB changes 2022-11-05 13:27:18 -07:00
terence tsao
f0ca45f9a2 Json marshal and unmarshal blob bundle 2022-11-05 12:45:14 -07:00
terence tsao
afc48c6485 State change and config changes for Capella 2022-11-05 12:45:01 -07:00
terence tsao
93dce8a0cb P2p changes for Capella fork 2022-11-05 12:44:46 -07:00
terence tsao
149ccdaf39 Add engine call for get payload 2022-11-05 11:00:13 -07:00
Potuz
c08bb39ffe add fork versions 2022-11-05 13:38:11 -03:00
Potuz
5083d8ab34 propose capella blocks 2022-11-05 12:38:27 -03:00
Potuz
7552a5dd07 capella fork logic 2022-11-05 07:33:20 -03:00
Potuz
c93d68f853 Capella state transition 2022-11-05 06:06:15 -03:00
terence tsao
2b74db2dce Add blob database methods 2022-11-04 13:46:01 -07:00
terence tsao
cc6c91415d Add validate blobs sidecar 2022-11-04 13:06:15 -07:00
terence tsao
6d7d7e0adc Add excessive blobs to execution payload 2022-11-04 09:48:39 -07:00
terence tsao
2105d777f0 Add blobs kzg to Capella beacon block 2022-11-04 09:33:01 -07:00
terence tsao
14338afbdb Update go.mod 2022-11-04 08:52:16 -07:00
Potuz
3e8aa4023d Fix config test and export method 2022-11-04 11:59:49 -03:00
Potuz
b443875e66 Implement get_expected_withdrawals 2022-11-04 11:45:45 -03:00
343 changed files with 27167 additions and 8445 deletions

View File

@@ -21,7 +21,7 @@ linters:
linters-settings: linters-settings:
gocognit: gocognit:
# TODO: We should target for < 50 # TODO: We should target for < 50
min-complexity: 65 min-complexity: 69
output: output:
print-issued-lines: true print-issued-lines: true

View File

@@ -483,7 +483,7 @@ func (fsr *forkScheduleResponse) OrderedForkSchedule() (forks.OrderedSchedule, e
version := bytesutil.ToBytes4(vSlice) version := bytesutil.ToBytes4(vSlice)
ofs = append(ofs, forks.ForkScheduleEntry{ ofs = append(ofs, forks.ForkScheduleEntry{
Version: version, Version: version,
Epoch: primitives.Epoch(uint64(epoch)), Epoch: primitives.Epoch(epoch),
}) })
} }
sort.Sort(ofs) sort.Sort(ofs)

View File

@@ -70,15 +70,16 @@ type Gateway struct {
func New(ctx context.Context, opts ...Option) (*Gateway, error) { func New(ctx context.Context, opts ...Option) (*Gateway, error) {
g := &Gateway{ g := &Gateway{
ctx: ctx, ctx: ctx,
cfg: &config{ cfg: &config{},
router: mux.NewRouter(),
},
} }
for _, opt := range opts { for _, opt := range opts {
if err := opt(g); err != nil { if err := opt(g); err != nil {
return nil, err return nil, err
} }
} }
if g.cfg.router == nil {
g.cfg.router = mux.NewRouter()
}
return g, nil return g, nil
} }

View File

@@ -10,11 +10,6 @@ import (
type Option func(g *Gateway) error type Option func(g *Gateway) error
func (g *Gateway) SetRouter(r *mux.Router) *Gateway {
g.cfg.router = r
return g
}
func WithPbHandlers(handlers []*PbMux) Option { func WithPbHandlers(handlers []*PbMux) Option {
return func(g *Gateway) error { return func(g *Gateway) error {
g.cfg.pbHandlers = handlers g.cfg.pbHandlers = handlers

View File

@@ -301,7 +301,7 @@ func (s *Service) getPayloadAttribute(ctx context.Context, st state.BeaconState,
var attr payloadattribute.Attributer var attr payloadattribute.Attributer
switch st.Version() { switch st.Version() {
case version.Capella: case version.Capella, version.Deneb:
withdrawals, err := st.ExpectedWithdrawals() withdrawals, err := st.ExpectedWithdrawals()
if err != nil { if err != nil {
log.WithError(err).Error("Could not get expected withdrawals to get payload attribute") log.WithError(err).Error("Could not get expected withdrawals to get payload attribute")

View File

@@ -60,7 +60,13 @@ func logStateTransitionData(b interfaces.ReadOnlyBeaconBlock) error {
log = log.WithField("txCount", len(txs)) log = log.WithField("txCount", len(txs))
txsPerSlotCount.Set(float64(len(txs))) txsPerSlotCount.Set(float64(len(txs)))
} }
}
if b.Version() >= version.Deneb {
k, err := b.Body().BlobKzgCommitments()
if err != nil {
return err
}
log = log.WithField("blobCount", len(k))
} }
log.Info("Finished applying state transition") log.Info("Finished applying state transition")
return nil return nil
@@ -96,6 +102,7 @@ func logBlockSyncStatus(block interfaces.ReadOnlyBeaconBlock, blockRoot [32]byte
"finalizedEpoch": finalized.Epoch, "finalizedEpoch": finalized.Epoch,
"finalizedRoot": fmt.Sprintf("0x%s...", hex.EncodeToString(finalized.Root)[:8]), "finalizedRoot": fmt.Sprintf("0x%s...", hex.EncodeToString(finalized.Root)[:8]),
"epoch": slots.ToEpoch(block.Slot()), "epoch": slots.ToEpoch(block.Slot()),
"version": version.String(block.Version()),
}).Info("Synced new block") }).Info("Synced new block")
} }
return nil return nil

View File

@@ -57,6 +57,11 @@ type mockBroadcaster struct {
broadcastCalled bool broadcastCalled bool
} }
func (mb *mockBroadcaster) BroadcastBlob(ctx context.Context, subnet uint64, blobSidecar *ethpb.SignedBlobSidecar) error {
//TODO implement me
panic("implement me")
}
func (mb *mockBroadcaster) Broadcast(_ context.Context, _ proto.Message) error { func (mb *mockBroadcaster) Broadcast(_ context.Context, _ proto.Message) error {
mb.broadcastCalled = true mb.broadcastCalled = true
return nil return nil

View File

@@ -9,6 +9,110 @@ import (
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1" ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
) )
// UpgradeToDeneb updates inputs a generic state to return the version Deneb state.
func UpgradeToDeneb(state state.BeaconState) (state.BeaconState, error) {
epoch := time.CurrentEpoch(state)
currentSyncCommittee, err := state.CurrentSyncCommittee()
if err != nil {
return nil, err
}
nextSyncCommittee, err := state.NextSyncCommittee()
if err != nil {
return nil, err
}
prevEpochParticipation, err := state.PreviousEpochParticipation()
if err != nil {
return nil, err
}
currentEpochParticipation, err := state.CurrentEpochParticipation()
if err != nil {
return nil, err
}
inactivityScores, err := state.InactivityScores()
if err != nil {
return nil, err
}
payloadHeader, err := state.LatestExecutionPayloadHeader()
if err != nil {
return nil, err
}
txRoot, err := payloadHeader.TransactionsRoot()
if err != nil {
return nil, err
}
wdRoot, err := payloadHeader.WithdrawalsRoot()
if err != nil {
return nil, err
}
wi, err := state.NextWithdrawalIndex()
if err != nil {
return nil, err
}
vi, err := state.NextWithdrawalValidatorIndex()
if err != nil {
return nil, err
}
summarires, err := state.HistoricalSummaries()
if err != nil {
return nil, err
}
s := &ethpb.BeaconStateDeneb{
GenesisTime: state.GenesisTime(),
GenesisValidatorsRoot: state.GenesisValidatorsRoot(),
Slot: state.Slot(),
Fork: &ethpb.Fork{
PreviousVersion: state.Fork().CurrentVersion,
CurrentVersion: params.BeaconConfig().DenebForkVersion,
Epoch: epoch,
},
LatestBlockHeader: state.LatestBlockHeader(),
BlockRoots: state.BlockRoots(),
StateRoots: state.StateRoots(),
HistoricalRoots: [][]byte{},
Eth1Data: state.Eth1Data(),
Eth1DataVotes: state.Eth1DataVotes(),
Eth1DepositIndex: state.Eth1DepositIndex(),
Validators: state.Validators(),
Balances: state.Balances(),
RandaoMixes: state.RandaoMixes(),
Slashings: state.Slashings(),
PreviousEpochParticipation: prevEpochParticipation,
CurrentEpochParticipation: currentEpochParticipation,
JustificationBits: state.JustificationBits(),
PreviousJustifiedCheckpoint: state.PreviousJustifiedCheckpoint(),
CurrentJustifiedCheckpoint: state.CurrentJustifiedCheckpoint(),
FinalizedCheckpoint: state.FinalizedCheckpoint(),
InactivityScores: inactivityScores,
CurrentSyncCommittee: currentSyncCommittee,
NextSyncCommittee: nextSyncCommittee,
LatestExecutionPayloadHeader: &enginev1.ExecutionPayloadHeaderDeneb{
ParentHash: payloadHeader.ParentHash(),
FeeRecipient: payloadHeader.FeeRecipient(),
StateRoot: payloadHeader.StateRoot(),
ReceiptsRoot: payloadHeader.ReceiptsRoot(),
LogsBloom: payloadHeader.LogsBloom(),
PrevRandao: payloadHeader.PrevRandao(),
BlockNumber: payloadHeader.BlockNumber(),
GasLimit: payloadHeader.GasLimit(),
GasUsed: payloadHeader.GasUsed(),
Timestamp: payloadHeader.Timestamp(),
ExtraData: payloadHeader.ExtraData(),
BaseFeePerGas: payloadHeader.BaseFeePerGas(),
BlockHash: payloadHeader.BlockHash(),
ExcessDataGas: make([]byte, 32),
TransactionsRoot: txRoot,
WithdrawalsRoot: wdRoot,
},
NextWithdrawalIndex: wi,
NextWithdrawalValidatorIndex: vi,
HistoricalSummaries: summarires,
}
return state_native.InitializeFromProtoUnsafeDeneb(s)
}
// UpgradeToCapella updates a generic state to return the version Capella state. // UpgradeToCapella updates a generic state to return the version Capella state.
func UpgradeToCapella(state state.BeaconState) (state.BeaconState, error) { func UpgradeToCapella(state state.BeaconState) (state.BeaconState, error) {
epoch := time.CurrentEpoch(state) epoch := time.CurrentEpoch(state)

View File

@@ -353,7 +353,7 @@ func ProcessRandaoMixesReset(state state.BeaconState) (state.BeaconState, error)
} }
// ProcessHistoricalDataUpdate processes the updates to historical data during epoch processing. // 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. // From Capella onward, per spec, state's historical summaries are updated instead of historical roots.
func ProcessHistoricalDataUpdate(state state.BeaconState) (state.BeaconState, error) { func ProcessHistoricalDataUpdate(state state.BeaconState) (state.BeaconState, error) {
currentEpoch := time.CurrentEpoch(state) currentEpoch := time.CurrentEpoch(state)
nextEpoch := currentEpoch + 1 nextEpoch := currentEpoch + 1

View File

@@ -81,6 +81,15 @@ func CanUpgradeToCapella(slot primitives.Slot) bool {
return epochStart && capellaEpoch return epochStart && capellaEpoch
} }
// CanUpgradeToDeneb returns true if the input `slot` can upgrade to Deneb.
// Spec code:
// If state.slot % SLOTS_PER_EPOCH == 0 and compute_epoch_at_slot(state.slot) == DENEB_FORK_EPOCH
func CanUpgradeToDeneb(slot primitives.Slot) bool {
epochStart := slots.IsEpochStart(slot)
DenebEpoch := slots.ToEpoch(slot) == params.BeaconConfig().DenebForkEpoch
return epochStart && DenebEpoch
}
// CanProcessEpoch checks the eligibility to process epoch. // CanProcessEpoch checks the eligibility to process epoch.
// The epoch can be processed at the end of the last slot of every epoch. // The epoch can be processed at the end of the last slot of every epoch.
// //

View File

@@ -23,7 +23,6 @@ go_library(
"//beacon-chain/core/execution:go_default_library", "//beacon-chain/core/execution:go_default_library",
"//beacon-chain/core/helpers:go_default_library", "//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/core/time:go_default_library", "//beacon-chain/core/time:go_default_library",
"//beacon-chain/core/transition/interop:go_default_library",
"//beacon-chain/core/validators:go_default_library", "//beacon-chain/core/validators:go_default_library",
"//beacon-chain/state:go_default_library", "//beacon-chain/state:go_default_library",
"//beacon-chain/state/state-native:go_default_library", "//beacon-chain/state/state-native:go_default_library",
@@ -46,6 +45,7 @@ go_library(
"@com_github_pkg_errors//:go_default_library", "@com_github_pkg_errors//:go_default_library",
"@com_github_prometheus_client_golang//prometheus:go_default_library", "@com_github_prometheus_client_golang//prometheus:go_default_library",
"@com_github_prometheus_client_golang//prometheus/promauto:go_default_library", "@com_github_prometheus_client_golang//prometheus/promauto:go_default_library",
"@com_github_protolambda_go_kzg//eth:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library",
"@io_opencensus_go//trace:go_default_library", "@io_opencensus_go//trace:go_default_library",
], ],

View File

@@ -302,6 +302,14 @@ func ProcessSlots(ctx context.Context, state state.BeaconState, slot primitives.
return nil, err return nil, err
} }
} }
if time.CanUpgradeToDeneb(state.Slot()) {
state, err = capella.UpgradeToDeneb(state)
if err != nil {
tracing.AnnotateError(span, err)
return nil, err
}
}
} }
if highestSlot < state.Slot() { if highestSlot < state.Slot() {

View File

@@ -6,16 +6,18 @@ import (
"fmt" "fmt"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/protolambda/go-kzg/eth"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/altair" "github.com/prysmaticlabs/prysm/v4/beacon-chain/core/altair"
b "github.com/prysmaticlabs/prysm/v4/beacon-chain/core/blocks" b "github.com/prysmaticlabs/prysm/v4/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/transition/interop"
v "github.com/prysmaticlabs/prysm/v4/beacon-chain/core/validators" v "github.com/prysmaticlabs/prysm/v4/beacon-chain/core/validators"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state" "github.com/prysmaticlabs/prysm/v4/beacon-chain/state"
"github.com/prysmaticlabs/prysm/v4/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v4/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v4/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v4/consensus-types/interfaces"
"github.com/prysmaticlabs/prysm/v4/crypto/bls" "github.com/prysmaticlabs/prysm/v4/crypto/bls"
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/v4/monitoring/tracing" "github.com/prysmaticlabs/prysm/v4/monitoring/tracing"
"github.com/prysmaticlabs/prysm/v4/runtime/version" "github.com/prysmaticlabs/prysm/v4/runtime/version"
"go.opencensus.io/trace" "go.opencensus.io/trace"
) )
@@ -57,9 +59,6 @@ func ExecuteStateTransitionNoVerifyAnySig(
defer span.End() defer span.End()
var err error var err error
interop.WriteBlockToDisk(signed, false /* Has the block failed */)
interop.WriteStateToDisk(st)
parentRoot := signed.Block().ParentRoot() parentRoot := signed.Block().ParentRoot()
st, err = ProcessSlotsUsingNextSlotCache(ctx, st, parentRoot[:], signed.Block().Slot()) st, err = ProcessSlotsUsingNextSlotCache(ctx, st, parentRoot[:], signed.Block().Slot())
if err != nil { if err != nil {
@@ -256,7 +255,7 @@ func ProcessOperationsNoVerifyAttsSigs(
if err != nil { if err != nil {
return nil, err return nil, err
} }
case version.Altair, version.Bellatrix, version.Capella: case version.Altair, version.Bellatrix, version.Capella, version.Deneb:
state, err = altairOperations(ctx, state, signedBeaconBlock) state, err = altairOperations(ctx, state, signedBeaconBlock)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -356,9 +355,48 @@ func ProcessBlockForStateRoot(
return nil, errors.Wrap(err, "process_sync_aggregate failed") return nil, errors.Wrap(err, "process_sync_aggregate failed")
} }
if signed.Block().Version() == version.Deneb {
err := ValidateBlobKzgs(ctx, signed.Block().Body())
if err != nil {
return nil, errors.Wrap(err, "could not validate blob kzgs")
}
}
return state, nil return state, nil
} }
// ValidateBlobKzgs validates the blob kzgs in the beacon block.
//
// Spec code:
// def process_blob_kzg_commitments(state: BeaconState, body: BeaconBlockBody):
//
// assert verify_kzg_commitments_against_transactions(body.execution_payload.transactions, body.blob_kzg_commitments)
func ValidateBlobKzgs(ctx context.Context, body interfaces.ReadOnlyBeaconBlockBody) error {
_, span := trace.StartSpan(ctx, "core.state.ValidateBlobKzgs")
defer span.End()
payload, err := body.Execution()
if err != nil {
return errors.Wrap(err, "could not get execution payload from block")
}
blkKzgs, err := body.BlobKzgCommitments()
if err != nil {
return errors.Wrap(err, "could not get blob kzg commitments from block")
}
kzgs := make(eth.KZGCommitmentSequenceImpl, len(blkKzgs))
for i := range blkKzgs {
kzgs[i] = bytesutil.ToBytes48(blkKzgs[i])
}
txs, err := payload.Transactions()
if err != nil {
return errors.Wrap(err, "could not get transactions from payload")
}
if err := eth.VerifyKZGCommitmentsAgainstTransactions(txs, kzgs); err != nil {
return err
}
return nil
}
// This calls altair block operations. // This calls altair block operations.
func altairOperations( func altairOperations(
ctx context.Context, ctx context.Context,

View File

@@ -54,6 +54,11 @@ type ReadOnlyDatabase interface {
// Fee recipients operations. // Fee recipients operations.
FeeRecipientByValidatorID(ctx context.Context, id primitives.ValidatorIndex) (common.Address, error) FeeRecipientByValidatorID(ctx context.Context, id primitives.ValidatorIndex) (common.Address, error)
RegistrationByValidatorID(ctx context.Context, id primitives.ValidatorIndex) (*ethpb.ValidatorRegistrationV1, error) RegistrationByValidatorID(ctx context.Context, id primitives.ValidatorIndex) (*ethpb.ValidatorRegistrationV1, error)
// Blob operations.
BlobSidecarsByRoot(ctx context.Context, beaconBlockRoot [32]byte, indices ...uint64) ([]*ethpb.BlobSidecar, error)
BlobSidecarsBySlot(ctx context.Context, slot primitives.Slot, indices ...uint64) ([]*ethpb.BlobSidecar, error)
// origin checkpoint sync support // origin checkpoint sync support
OriginCheckpointBlockRoot(ctx context.Context) ([32]byte, error) OriginCheckpointBlockRoot(ctx context.Context) ([32]byte, error)
BackfillBlockRoot(ctx context.Context) ([32]byte, error) BackfillBlockRoot(ctx context.Context) ([32]byte, error)
@@ -89,6 +94,10 @@ type NoHeadAccessDatabase interface {
SaveFeeRecipientsByValidatorIDs(ctx context.Context, ids []primitives.ValidatorIndex, addrs []common.Address) error SaveFeeRecipientsByValidatorIDs(ctx context.Context, ids []primitives.ValidatorIndex, addrs []common.Address) error
SaveRegistrationsByValidatorIDs(ctx context.Context, ids []primitives.ValidatorIndex, regs []*ethpb.ValidatorRegistrationV1) error SaveRegistrationsByValidatorIDs(ctx context.Context, ids []primitives.ValidatorIndex, regs []*ethpb.ValidatorRegistrationV1) error
// Blob operations.
SaveBlobSidecar(ctx context.Context, sidecars []*ethpb.BlobSidecar) error
DeleteBlobSidecar(ctx context.Context, beaconBlockRoot [32]byte) error
CleanUpDirtyStates(ctx context.Context, slotsPerArchivedPoint primitives.Slot) error CleanUpDirtyStates(ctx context.Context, slotsPerArchivedPoint primitives.Slot) error
} }

View File

@@ -5,6 +5,7 @@ go_library(
srcs = [ srcs = [
"archived_point.go", "archived_point.go",
"backup.go", "backup.go",
"blob.go",
"blocks.go", "blocks.go",
"checkpoint.go", "checkpoint.go",
"deposit_contract.go", "deposit_contract.go",
@@ -74,6 +75,7 @@ go_test(
srcs = [ srcs = [
"archived_point_test.go", "archived_point_test.go",
"backup_test.go", "backup_test.go",
"blob_test.go",
"blocks_test.go", "blocks_test.go",
"checkpoint_test.go", "checkpoint_test.go",
"deposit_contract_test.go", "deposit_contract_test.go",
@@ -110,6 +112,7 @@ go_test(
"//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1:go_default_library",
"//proto/testing:go_default_library", "//proto/testing:go_default_library",
"//testing/assert:go_default_library", "//testing/assert:go_default_library",
"//testing/assertions:go_default_library",
"//testing/require:go_default_library", "//testing/require:go_default_library",
"//testing/util:go_default_library", "//testing/util:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library", "@com_github_ethereum_go_ethereum//common:go_default_library",

182
beacon-chain/db/kv/blob.go Normal file
View File

@@ -0,0 +1,182 @@
package kv
import (
"bytes"
"context"
"fmt"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v4/config/params"
types "github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
bolt "go.etcd.io/bbolt"
"go.opencensus.io/trace"
)
// SaveBlobSidecar saves the blobs for a given epoch in the sidecar bucket. When we receive a blob:
//
// 1. Convert slot using a modulo operator to [0, maxSlots] where maxSlots = MAX_BLOB_EPOCHS*SLOTS_PER_EPOCH
//
// 2. Compute key for blob as bytes(slot_to_rotating_buffer(blob.slot)) ++ bytes(blob.slot) ++ blob.block_root
//
// 3. Begin the save algorithm: If the incoming blob has a slot bigger than the saved slot at the spot
// in the rotating keys buffer, we overwrite all elements for that slot.
func (s *Store) SaveBlobSidecar(ctx context.Context, scs []*ethpb.BlobSidecar) error {
ctx, span := trace.StartSpan(ctx, "BeaconDB.SaveBlobSidecar")
defer span.End()
if len(scs) == 0 {
return errors.New("nil or empty blob sidecars")
}
slot := scs[0].Slot
return s.db.Update(func(tx *bolt.Tx) error {
encodedBlobSidecar, err := encode(ctx, &ethpb.BlobSidecars{Sidecars: scs})
if err != nil {
return err
}
bkt := tx.Bucket(blobsBucket)
c := bkt.Cursor()
newKey := blobSidecarKey(scs[0])
rotatingBufferPrefix := newKey[0:8]
var replacingKey []byte
for k, _ := c.Seek(rotatingBufferPrefix); bytes.HasPrefix(k, rotatingBufferPrefix); k, _ = c.Next() {
if len(k) != 0 {
replacingKey = k
oldSlotBytes := replacingKey[8:16]
oldSlot := bytesutil.BytesToSlotBigEndian(oldSlotBytes)
if oldSlot >= slot {
return fmt.Errorf("attempted to save blob with slot %d but already have older blob with slot %d", slot, oldSlot)
}
break
}
}
// If there is no element stored at blob.slot % MAX_SLOTS_TO_PERSIST_BLOBS, then we simply
// store the blob by key and exit early.
if len(replacingKey) == 0 {
return bkt.Put(newKey, encodedBlobSidecar)
}
if err := bkt.Delete(replacingKey); err != nil {
log.WithError(err).Warnf("Could not delete blob with key %#x", replacingKey)
}
return bkt.Put(newKey, encodedBlobSidecar)
})
}
// BlobSidecarsByRoot retrieves the blobs for the given beacon block root.
// If the `indices` argument is omitted, all blobs for the root will be returned.
// Otherwise, the result will be filtered to only include the specified indices.
// An error will result if an invalid index is specified.
func (s *Store) BlobSidecarsByRoot(ctx context.Context, root [32]byte, indices ...uint64) ([]*ethpb.BlobSidecar, error) {
ctx, span := trace.StartSpan(ctx, "BeaconDB.BlobSidecarsByRoot")
defer span.End()
var enc []byte
if err := s.db.View(func(tx *bolt.Tx) error {
c := tx.Bucket(blobsBucket).Cursor()
// Bucket size is bounded and bolt cursors are fast. Moreover, a thin caching layer can be added.
for k, v := c.First(); k != nil; k, v = c.Next() {
if bytes.HasSuffix(k, root[:]) {
enc = v
break
}
}
return nil
}); err != nil {
return nil, err
}
if enc == nil {
return nil, ErrNotFound
}
sc := &ethpb.BlobSidecars{}
if err := decode(ctx, enc, sc); err != nil {
return nil, err
}
return filterForIndices(sc, indices...)
}
func filterForIndices(sc *ethpb.BlobSidecars, indices ...uint64) ([]*ethpb.BlobSidecar, error) {
if len(indices) == 0 {
return sc.Sidecars, nil
}
// NB: This loop assumes that the BlobSidecars value stores the complete set of blobs for a block
// in ascending order from eg 0..3, without gaps. This allows us to assume the indices argument
// maps 1:1 with indices in the BlobSidecars storage object.
maxIdx := uint64(len(sc.Sidecars)) - 1
sidecars := make([]*ethpb.BlobSidecar, len(indices))
for i, idx := range indices {
if idx > maxIdx {
return nil, errors.Wrapf(ErrNotFound, "BlobSidecars missing index: index %d", idx)
}
sidecars[i] = sc.Sidecars[idx]
}
return sidecars, nil
}
// BlobSidecarsBySlot retrieves BlobSidecars for the given slot.
// If the `indices` argument is omitted, all blobs for the root will be returned.
// Otherwise, the result will be filtered to only include the specified indices.
// An error will result if an invalid index is specified.
func (s *Store) BlobSidecarsBySlot(ctx context.Context, slot types.Slot, indices ...uint64) ([]*ethpb.BlobSidecar, error) {
ctx, span := trace.StartSpan(ctx, "BeaconDB.BlobSidecarsBySlot")
defer span.End()
var enc []byte
if err := s.db.View(func(tx *bolt.Tx) error {
c := tx.Bucket(blobsBucket).Cursor()
// Bucket size is bounded and bolt cursors are fast. Moreover, a thin caching layer can be added.
for k, v := c.First(); k != nil; k, v = c.Next() {
slotInKey := bytesutil.BytesToSlotBigEndian(k[8:16])
if slotInKey == slot {
enc = v
break
}
}
return nil
}); err != nil {
return nil, err
}
if enc == nil {
return nil, ErrNotFound
}
sc := &ethpb.BlobSidecars{}
if err := decode(ctx, enc, sc); err != nil {
return nil, err
}
return filterForIndices(sc, indices...)
}
// DeleteBlobSidecar returns true if the blobs are in the db.
func (s *Store) DeleteBlobSidecar(ctx context.Context, beaconBlockRoot [32]byte) error {
ctx, span := trace.StartSpan(ctx, "BeaconDB.DeleteBlobSidecar")
defer span.End()
return s.db.Update(func(tx *bolt.Tx) error {
bkt := tx.Bucket(blobsBucket)
c := bkt.Cursor()
for k, _ := c.First(); k != nil; k, _ = c.Next() {
if bytes.HasSuffix(k, beaconBlockRoot[:]) {
if err := bkt.Delete(k); err != nil {
return err
}
}
}
return nil
})
}
// We define a blob sidecar key as: bytes(slot_to_rotating_buffer(blob.slot)) ++ bytes(blob.slot) ++ blob.block_root
// where slot_to_rotating_buffer(slot) = slot % MAX_SLOTS_TO_PERSIST_BLOBS.
func blobSidecarKey(blob *ethpb.BlobSidecar) []byte {
slotsPerEpoch := params.BeaconConfig().SlotsPerEpoch
maxEpochsToPersistBlobs := params.BeaconNetworkConfig().MinEpochsForBlobsSidecarsRequest
maxSlotsToPersistBlobs := types.Slot(maxEpochsToPersistBlobs.Mul(uint64(slotsPerEpoch)))
slotInRotatingBuffer := blob.Slot.ModSlot(maxSlotsToPersistBlobs)
key := bytesutil.SlotToBytesBigEndian(slotInRotatingBuffer)
key = append(key, bytesutil.SlotToBytesBigEndian(blob.Slot)...)
key = append(key, blob.BlockRoot...)
return key
}

View File

@@ -0,0 +1,235 @@
package kv
import (
"context"
"crypto/rand"
"encoding/binary"
"fmt"
"testing"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v4/config/params"
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v4/testing/assertions"
"github.com/prysmaticlabs/prysm/v4/testing/require"
)
func equalBlobSlices(expect []*ethpb.BlobSidecar, got []*ethpb.BlobSidecar) error {
if len(expect) != len(got) {
return fmt.Errorf("mismatched lengths, expect=%d, got=%d", len(expect), len(got))
}
for i := 0; i < len(expect); i++ {
es := expect[i]
gs := got[i]
var e string
assertions.DeepEqual(assertions.SprintfAssertionLoggerFn(&e), es, gs)
if e != "" {
return errors.New(e)
}
}
return nil
}
func TestStore_BlobSidecars(t *testing.T) {
ctx := context.Background()
t.Run("empty", func(t *testing.T) {
db := setupDB(t)
scs := generateBlobSidecars(t, 0)
require.ErrorContains(t, "nil or empty blob sidecars", db.SaveBlobSidecar(ctx, scs))
})
t.Run("empty by root", func(t *testing.T) {
db := setupDB(t)
got, err := db.BlobSidecarsByRoot(ctx, [32]byte{})
require.ErrorIs(t, ErrNotFound, err)
require.Equal(t, 0, len(got))
})
t.Run("empty by slot", func(t *testing.T) {
db := setupDB(t)
got, err := db.BlobSidecarsBySlot(ctx, 1)
require.ErrorIs(t, ErrNotFound, err)
require.Equal(t, 0, len(got))
})
t.Run("save and retrieve by root (one)", func(t *testing.T) {
db := setupDB(t)
scs := generateBlobSidecars(t, 1)
require.NoError(t, db.SaveBlobSidecar(ctx, scs))
require.Equal(t, 1, len(scs))
got, err := db.BlobSidecarsByRoot(ctx, bytesutil.ToBytes32(scs[0].BlockRoot))
require.NoError(t, err)
require.NoError(t, equalBlobSlices(scs, got))
})
t.Run("save and retrieve by root (max)", func(t *testing.T) {
db := setupDB(t)
scs := generateBlobSidecars(t, params.BeaconConfig().MaxBlobsPerBlock)
require.NoError(t, db.SaveBlobSidecar(ctx, scs))
require.Equal(t, int(params.BeaconConfig().MaxBlobsPerBlock), len(scs))
got, err := db.BlobSidecarsByRoot(ctx, bytesutil.ToBytes32(scs[0].BlockRoot))
require.NoError(t, err)
require.NoError(t, equalBlobSlices(scs, got))
})
t.Run("save and retrieve valid subset by root", func(t *testing.T) {
db := setupDB(t)
scs := generateBlobSidecars(t, params.BeaconConfig().MaxBlobsPerBlock)
require.NoError(t, db.SaveBlobSidecar(ctx, scs))
require.Equal(t, int(params.BeaconConfig().MaxBlobsPerBlock), len(scs))
// we'll request indices 0 and 3, so make a slice with those indices for comparison
expect := make([]*ethpb.BlobSidecar, 2)
expect[0] = scs[0]
expect[1] = scs[3]
got, err := db.BlobSidecarsByRoot(ctx, bytesutil.ToBytes32(scs[0].BlockRoot), 0, 3)
require.NoError(t, err)
require.NoError(t, equalBlobSlices(expect, got))
require.Equal(t, uint64(0), got[0].Index)
require.Equal(t, uint64(3), got[1].Index)
})
t.Run("error for invalid index when retrieving by root", func(t *testing.T) {
db := setupDB(t)
scs := generateBlobSidecars(t, params.BeaconConfig().MaxBlobsPerBlock)
require.NoError(t, db.SaveBlobSidecar(ctx, scs))
require.Equal(t, int(params.BeaconConfig().MaxBlobsPerBlock), len(scs))
got, err := db.BlobSidecarsByRoot(ctx, bytesutil.ToBytes32(scs[0].BlockRoot), uint64(len(scs)))
require.ErrorIs(t, err, ErrNotFound)
require.Equal(t, 0, len(got))
})
t.Run("save and retrieve by slot (one)", func(t *testing.T) {
db := setupDB(t)
scs := generateBlobSidecars(t, 1)
require.NoError(t, db.SaveBlobSidecar(ctx, scs))
require.Equal(t, 1, len(scs))
got, err := db.BlobSidecarsBySlot(ctx, scs[0].Slot)
require.NoError(t, err)
require.NoError(t, equalBlobSlices(scs, got))
})
t.Run("save and retrieve by slot (max)", func(t *testing.T) {
db := setupDB(t)
scs := generateBlobSidecars(t, params.BeaconConfig().MaxBlobsPerBlock)
require.NoError(t, db.SaveBlobSidecar(ctx, scs))
require.Equal(t, int(params.BeaconConfig().MaxBlobsPerBlock), len(scs))
got, err := db.BlobSidecarsBySlot(ctx, scs[0].Slot)
require.NoError(t, err)
require.NoError(t, equalBlobSlices(scs, got))
})
t.Run("save and retrieve valid subset by slot", func(t *testing.T) {
db := setupDB(t)
scs := generateBlobSidecars(t, params.BeaconConfig().MaxBlobsPerBlock)
require.NoError(t, db.SaveBlobSidecar(ctx, scs))
require.Equal(t, int(params.BeaconConfig().MaxBlobsPerBlock), len(scs))
// we'll request indices 0 and 3, so make a slice with those indices for comparison
expect := make([]*ethpb.BlobSidecar, 2)
expect[0] = scs[0]
expect[1] = scs[3]
got, err := db.BlobSidecarsBySlot(ctx, scs[0].Slot, 0, 3)
require.NoError(t, err)
require.NoError(t, equalBlobSlices(expect, got))
require.Equal(t, uint64(0), got[0].Index)
require.Equal(t, uint64(3), got[1].Index)
})
t.Run("error for invalid index when retrieving by slot", func(t *testing.T) {
db := setupDB(t)
scs := generateBlobSidecars(t, params.BeaconConfig().MaxBlobsPerBlock)
require.NoError(t, db.SaveBlobSidecar(ctx, scs))
require.Equal(t, int(params.BeaconConfig().MaxBlobsPerBlock), len(scs))
got, err := db.BlobSidecarsBySlot(ctx, scs[0].Slot, uint64(len(scs)))
require.ErrorIs(t, err, ErrNotFound)
require.Equal(t, 0, len(got))
})
t.Run("delete works", func(t *testing.T) {
db := setupDB(t)
scs := generateBlobSidecars(t, params.BeaconConfig().MaxBlobsPerBlock)
require.NoError(t, db.SaveBlobSidecar(ctx, scs))
require.Equal(t, int(params.BeaconConfig().MaxBlobsPerBlock), len(scs))
got, err := db.BlobSidecarsByRoot(ctx, bytesutil.ToBytes32(scs[0].BlockRoot))
require.NoError(t, err)
require.NoError(t, equalBlobSlices(scs, got))
require.NoError(t, db.DeleteBlobSidecar(ctx, bytesutil.ToBytes32(scs[0].BlockRoot)))
got, err = db.BlobSidecarsByRoot(ctx, bytesutil.ToBytes32(scs[0].BlockRoot))
require.ErrorIs(t, ErrNotFound, err)
require.Equal(t, 0, len(got))
})
t.Run("saving a blob with older slot", func(t *testing.T) {
db := setupDB(t)
scs := generateBlobSidecars(t, params.BeaconConfig().MaxBlobsPerBlock)
require.NoError(t, db.SaveBlobSidecar(ctx, scs))
require.Equal(t, int(params.BeaconConfig().MaxBlobsPerBlock), len(scs))
got, err := db.BlobSidecarsByRoot(ctx, bytesutil.ToBytes32(scs[0].BlockRoot))
require.NoError(t, err)
require.NoError(t, equalBlobSlices(scs, got))
require.ErrorContains(t, "but already have older blob with slot", db.SaveBlobSidecar(ctx, scs))
})
t.Run("saving a new blob for rotation", func(t *testing.T) {
db := setupDB(t)
scs := generateBlobSidecars(t, params.BeaconConfig().MaxBlobsPerBlock)
require.NoError(t, db.SaveBlobSidecar(ctx, scs))
require.Equal(t, int(params.BeaconConfig().MaxBlobsPerBlock), len(scs))
oldBlockRoot := scs[0].BlockRoot
got, err := db.BlobSidecarsByRoot(ctx, bytesutil.ToBytes32(oldBlockRoot))
require.NoError(t, err)
require.NoError(t, equalBlobSlices(scs, got))
newScs := generateBlobSidecars(t, params.BeaconConfig().MaxBlobsPerBlock)
newRetentionSlot := primitives.Slot(params.BeaconNetworkConfig().MinEpochsForBlobsSidecarsRequest.Mul(uint64(params.BeaconConfig().SlotsPerEpoch)))
newScs[0].Slot = scs[0].Slot + newRetentionSlot
require.NoError(t, db.SaveBlobSidecar(ctx, newScs))
_, err = db.BlobSidecarsByRoot(ctx, bytesutil.ToBytes32(oldBlockRoot))
require.ErrorIs(t, ErrNotFound, err)
got, err = db.BlobSidecarsByRoot(ctx, bytesutil.ToBytes32(newScs[0].BlockRoot))
require.NoError(t, err)
require.NoError(t, equalBlobSlices(newScs, got))
})
}
func generateBlobSidecars(t *testing.T, n uint64) []*ethpb.BlobSidecar {
blobSidecars := make([]*ethpb.BlobSidecar, n)
for i := uint64(0); i < n; i++ {
blobSidecars[i] = generateBlobSidecar(t, i)
}
return blobSidecars
}
func generateBlobSidecar(t *testing.T, index uint64) *ethpb.BlobSidecar {
blockRoot := make([]byte, 32)
_, err := rand.Read(blockRoot)
require.NoError(t, err)
require.NoError(t, err)
slot := make([]byte, 8)
_, err = rand.Read(slot)
require.NoError(t, err)
blockParentRoot := make([]byte, 32)
_, err = rand.Read(blockParentRoot)
require.NoError(t, err)
proposerIndex := make([]byte, 8)
_, err = rand.Read(proposerIndex)
require.NoError(t, err)
blob := make([]byte, 131072)
_, err = rand.Read(blob)
require.NoError(t, err)
kzgCommitment := make([]byte, 48)
_, err = rand.Read(kzgCommitment)
require.NoError(t, err)
kzgProof := make([]byte, 48)
_, err = rand.Read(kzgProof)
require.NoError(t, err)
return &ethpb.BlobSidecar{
BlockRoot: blockRoot,
Index: index,
Slot: primitives.Slot(binary.LittleEndian.Uint64(slot)),
BlockParentRoot: blockParentRoot,
ProposerIndex: primitives.ValidatorIndex(binary.LittleEndian.Uint64(proposerIndex)),
Blob: blob,
KzgCommitment: kzgCommitment,
KzgProof: kzgProof,
}
}

View File

@@ -818,6 +818,16 @@ func unmarshalBlock(_ context.Context, enc []byte) (interfaces.ReadOnlySignedBea
if err := rawBlock.UnmarshalSSZ(enc[len(capellaBlindKey):]); err != nil { if err := rawBlock.UnmarshalSSZ(enc[len(capellaBlindKey):]); err != nil {
return nil, errors.Wrap(err, "could not unmarshal blinded Capella block") return nil, errors.Wrap(err, "could not unmarshal blinded Capella block")
} }
case hasDenebKey(enc):
rawBlock = &ethpb.SignedBeaconBlockDeneb{}
if err := rawBlock.UnmarshalSSZ(enc[len(denebKey):]); err != nil {
return nil, err
}
case hasDenebBlindKey(enc):
rawBlock = &ethpb.SignedBlindedBeaconBlockDeneb{}
if err := rawBlock.UnmarshalSSZ(enc[len(denebBlindKey):]); err != nil {
return nil, errors.Wrap(err, "could not unmarshal blinded Deneb block")
}
default: default:
// Marshal block bytes to phase 0 beacon block. // Marshal block bytes to phase 0 beacon block.
rawBlock = &ethpb.SignedBeaconBlock{} rawBlock = &ethpb.SignedBeaconBlock{}
@@ -854,6 +864,8 @@ func marshalBlockFull(
return nil, err return nil, err
} }
switch blk.Version() { switch blk.Version() {
case version.Deneb:
return snappy.Encode(nil, append(denebKey, encodedBlock...)), nil
case version.Capella: case version.Capella:
return snappy.Encode(nil, append(capellaKey, encodedBlock...)), nil return snappy.Encode(nil, append(capellaKey, encodedBlock...)), nil
case version.Bellatrix: case version.Bellatrix:
@@ -888,6 +900,8 @@ func marshalBlockBlinded(
return nil, errors.Wrap(err, "could not marshal blinded block") return nil, errors.Wrap(err, "could not marshal blinded block")
} }
switch blk.Version() { switch blk.Version() {
case version.Deneb:
return snappy.Encode(nil, append(denebBlindKey, encodedBlock...)), nil
case version.Capella: case version.Capella:
return snappy.Encode(nil, append(capellaBlindKey, encodedBlock...)), nil return snappy.Encode(nil, append(capellaBlindKey, encodedBlock...)), nil
case version.Bellatrix: case version.Bellatrix:

View File

@@ -37,3 +37,17 @@ func hasCapellaBlindKey(enc []byte) bool {
} }
return bytes.Equal(enc[:len(capellaBlindKey)], capellaBlindKey) return bytes.Equal(enc[:len(capellaBlindKey)], capellaBlindKey)
} }
func hasDenebKey(enc []byte) bool {
if len(denebKey) >= len(enc) {
return false
}
return bytes.Equal(enc[:len(denebKey)], denebKey)
}
func hasDenebBlindKey(enc []byte) bool {
if len(denebBlindKey) >= len(enc) {
return false
}
return bytes.Equal(enc[:len(denebBlindKey)], denebBlindKey)
}

View File

@@ -129,6 +129,8 @@ var Buckets = [][]byte{
feeRecipientBucket, feeRecipientBucket,
registrationBucket, registrationBucket,
blobsBucket,
} }
// NewKVStore initializes a new boltDB key-value store at the directory // NewKVStore initializes a new boltDB key-value store at the directory

View File

@@ -46,6 +46,7 @@ var (
finalizedCheckpointKey = []byte("finalized-checkpoint") finalizedCheckpointKey = []byte("finalized-checkpoint")
powchainDataKey = []byte("powchain-data") powchainDataKey = []byte("powchain-data")
lastValidatedCheckpointKey = []byte("last-validated-checkpoint") lastValidatedCheckpointKey = []byte("last-validated-checkpoint")
blobsBucket = []byte("blobs")
// Below keys are used to identify objects are to be fork compatible. // Below keys are used to identify objects are to be fork compatible.
// Objects that are only compatible with specific forks should be prefixed with such keys. // Objects that are only compatible with specific forks should be prefixed with such keys.
@@ -55,6 +56,9 @@ var (
capellaKey = []byte("capella") capellaKey = []byte("capella")
capellaBlindKey = []byte("blind-capella") capellaBlindKey = []byte("blind-capella")
saveBlindedBeaconBlocksKey = []byte("save-blinded-beacon-blocks") saveBlindedBeaconBlocksKey = []byte("save-blinded-beacon-blocks")
denebKey = []byte("deneb")
denebBlindKey = []byte("blind-deneb")
// block root included in the beacon state used by weak subjectivity initial sync // block root included in the beacon state used by weak subjectivity initial sync
originCheckpointBlockRootKey = []byte("origin-checkpoint-block-root") originCheckpointBlockRootKey = []byte("origin-checkpoint-block-root")
// block root tracking the progress of backfill, or pointing at genesis if backfill has not been initiated // block root tracking the progress of backfill, or pointing at genesis if backfill has not been initiated

View File

@@ -473,6 +473,19 @@ func (s *Store) unmarshalState(_ context.Context, enc []byte, validatorEntries [
} }
switch { switch {
case hasDenebKey(enc):
protoState := &ethpb.BeaconStateDeneb{}
if err := protoState.UnmarshalSSZ(enc[len(denebKey):]); err != nil {
return nil, errors.Wrap(err, "failed to unmarshal encoding for Deneb")
}
ok, err := s.isStateValidatorMigrationOver()
if err != nil {
return nil, err
}
if ok {
protoState.Validators = validatorEntries
}
return statenative.InitializeFromProtoUnsafeDeneb(protoState)
case hasCapellaKey(enc): case hasCapellaKey(enc):
// Marshal state bytes to capella beacon state. // Marshal state bytes to capella beacon state.
protoState := &ethpb.BeaconStateCapella{} protoState := &ethpb.BeaconStateCapella{}
@@ -580,6 +593,19 @@ func marshalState(ctx context.Context, st state.ReadOnlyBeaconState) ([]byte, er
return nil, err return nil, err
} }
return snappy.Encode(nil, append(capellaKey, rawObj...)), nil return snappy.Encode(nil, append(capellaKey, rawObj...)), nil
case *ethpb.BeaconStateDeneb:
rState, ok := st.ToProtoUnsafe().(*ethpb.BeaconStateDeneb)
if !ok {
return nil, errors.New("non valid inner state")
}
if rState == nil {
return nil, errors.New("nil state")
}
rawObj, err := rState.MarshalSSZ()
if err != nil {
return nil, err
}
return snappy.Encode(nil, append(denebKey, rawObj...)), nil
default: default:
return nil, errors.New("invalid inner state") return nil, errors.New("invalid inner state")
} }

View File

@@ -35,6 +35,7 @@ const (
NewPayloadMethod = "engine_newPayloadV1" NewPayloadMethod = "engine_newPayloadV1"
// NewPayloadMethodV2 v2 request string for JSON-RPC. // NewPayloadMethodV2 v2 request string for JSON-RPC.
NewPayloadMethodV2 = "engine_newPayloadV2" NewPayloadMethodV2 = "engine_newPayloadV2"
NewPayloadMethodV3 = "engine_newPayloadV3"
// ForkchoiceUpdatedMethod v1 request string for JSON-RPC. // ForkchoiceUpdatedMethod v1 request string for JSON-RPC.
ForkchoiceUpdatedMethod = "engine_forkchoiceUpdatedV1" ForkchoiceUpdatedMethod = "engine_forkchoiceUpdatedV1"
// ForkchoiceUpdatedMethodV2 v2 request string for JSON-RPC. // ForkchoiceUpdatedMethodV2 v2 request string for JSON-RPC.
@@ -43,6 +44,9 @@ const (
GetPayloadMethod = "engine_getPayloadV1" GetPayloadMethod = "engine_getPayloadV1"
// GetPayloadMethodV2 v2 request string for JSON-RPC. // GetPayloadMethodV2 v2 request string for JSON-RPC.
GetPayloadMethodV2 = "engine_getPayloadV2" GetPayloadMethodV2 = "engine_getPayloadV2"
GetPayloadMethodV3 = "engine_getPayloadV3"
// GetBlobsBundleMethod v1 request string for JSON-RPC.
GetBlobsBundleMethod = "engine_getBlobsBundleV1"
// ExchangeTransitionConfigurationMethod v1 request string for JSON-RPC. // ExchangeTransitionConfigurationMethod v1 request string for JSON-RPC.
ExchangeTransitionConfigurationMethod = "engine_exchangeTransitionConfigurationV1" ExchangeTransitionConfigurationMethod = "engine_exchangeTransitionConfigurationV1"
// ExecutionBlockByHashMethod request string for JSON-RPC. // ExecutionBlockByHashMethod request string for JSON-RPC.
@@ -89,6 +93,7 @@ type EngineCaller interface {
) error ) error
ExecutionBlockByHash(ctx context.Context, hash common.Hash, withTxs bool) (*pb.ExecutionBlock, error) ExecutionBlockByHash(ctx context.Context, hash common.Hash, withTxs bool) (*pb.ExecutionBlock, error)
GetTerminalBlockHash(ctx context.Context, transitionTime uint64) ([]byte, bool, error) GetTerminalBlockHash(ctx context.Context, transitionTime uint64) ([]byte, bool, error)
GetBlobsBundle(ctx context.Context, payloadId [8]byte) (*pb.BlobsBundle, error)
} }
var EmptyBlockHash = errors.New("Block hash is empty 0x0000...") var EmptyBlockHash = errors.New("Block hash is empty 0x0000...")
@@ -126,8 +131,17 @@ func (s *Service) NewPayload(ctx context.Context, payload interfaces.ExecutionDa
if err != nil { if err != nil {
return nil, handleRPCError(err) return nil, handleRPCError(err)
} }
case *pb.ExecutionPayloadDeneb:
payloadPb, ok := payload.Proto().(*pb.ExecutionPayloadDeneb)
if !ok {
return nil, errors.New("execution data must be a Deneb execution payload")
}
err := s.rpcClient.CallContext(ctx, result, NewPayloadMethodV3, payloadPb)
if err != nil {
return nil, handleRPCError(err)
}
default: default:
return nil, errors.New("unknown execution data type") return nil, ErrUnknownExecutionDataType
} }
switch result.Status { switch result.Status {
@@ -173,7 +187,7 @@ func (s *Service) ForkchoiceUpdated(
if err != nil { if err != nil {
return nil, nil, handleRPCError(err) return nil, nil, handleRPCError(err)
} }
case version.Capella: case version.Capella, version.Deneb:
a, err := attrs.PbV2() a, err := attrs.PbV2()
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
@@ -215,6 +229,15 @@ func (s *Service) GetPayload(ctx context.Context, payloadId [8]byte, slot primit
ctx, cancel := context.WithDeadline(ctx, d) ctx, cancel := context.WithDeadline(ctx, d)
defer cancel() defer cancel()
if slots.ToEpoch(slot) >= params.BeaconConfig().DenebForkEpoch {
result := &pb.ExecutionPayloadDenebWithValue{}
err := s.rpcClient.CallContext(ctx, result, GetPayloadMethodV3, pb.PayloadIDBytes(payloadId))
if err != nil {
return nil, handleRPCError(err)
}
return blocks.WrappedExecutionPayloadDeneb(result.Payload, big.NewInt(0).SetBytes(bytesutil.ReverseByteOrder(result.Value)))
}
if slots.ToEpoch(slot) >= params.BeaconConfig().CapellaForkEpoch { if slots.ToEpoch(slot) >= params.BeaconConfig().CapellaForkEpoch {
result := &pb.ExecutionPayloadCapellaWithValue{} result := &pb.ExecutionPayloadCapellaWithValue{}
err := s.rpcClient.CallContext(ctx, result, GetPayloadMethodV2, pb.PayloadIDBytes(payloadId)) err := s.rpcClient.CallContext(ctx, result, GetPayloadMethodV2, pb.PayloadIDBytes(payloadId))
@@ -422,6 +445,19 @@ func (s *Service) ExecutionBlocksByHashes(ctx context.Context, hashes []common.H
return execBlks, nil return execBlks, nil
} }
// GetBlobsBundle calls the engine_getBlobsV1 method via JSON-RPC.
func (s *Service) GetBlobsBundle(ctx context.Context, payloadId [8]byte) (*pb.BlobsBundle, error) {
ctx, span := trace.StartSpan(ctx, "powchain.engine-api-client.GetBlobsBundle")
defer span.End()
d := time.Now().Add(defaultEngineTimeout)
ctx, cancel := context.WithDeadline(ctx, d)
defer cancel()
result := &pb.BlobsBundle{}
err := s.rpcClient.CallContext(ctx, result, GetBlobsBundleMethod, pb.PayloadIDBytes(payloadId))
return result, handleRPCError(err)
}
// HeaderByHash returns the relevant header details for the provided block hash. // HeaderByHash returns the relevant header details for the provided block hash.
func (s *Service) HeaderByHash(ctx context.Context, hash common.Hash) (*types.HeaderInfo, error) { func (s *Service) HeaderByHash(ctx context.Context, hash common.Hash) (*types.HeaderInfo, error) {
var hdr *types.HeaderInfo var hdr *types.HeaderInfo
@@ -637,7 +673,8 @@ func fullPayloadFromExecutionBlock(
txs[i] = txBin txs[i] = txBin
} }
if block.Version == version.Bellatrix { switch block.Version {
case version.Bellatrix:
return blocks.WrappedExecutionPayload(&pb.ExecutionPayload{ return blocks.WrappedExecutionPayload(&pb.ExecutionPayload{
ParentHash: header.ParentHash(), ParentHash: header.ParentHash(),
FeeRecipient: header.FeeRecipient(), FeeRecipient: header.FeeRecipient(),
@@ -654,24 +691,51 @@ func fullPayloadFromExecutionBlock(
BlockHash: blockHash[:], BlockHash: blockHash[:],
Transactions: txs, Transactions: txs,
}) })
case version.Capella:
return blocks.WrappedExecutionPayloadCapella(&pb.ExecutionPayloadCapella{
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,
Withdrawals: block.Withdrawals,
}, big.NewInt(0)) // We can't get the block value and don't care about the block value for this instance
case version.Deneb:
edg, err := header.ExcessDataGas()
if err != nil {
return nil, errors.Wrap(err, "unable to extract ExcessDataGas attribute from excution payload header")
}
return blocks.WrappedExecutionPayloadDeneb(
&pb.ExecutionPayloadDeneb{
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,
Withdrawals: block.Withdrawals,
ExcessDataGas: edg,
}, big.NewInt(0))
default:
return nil, errors.Wrapf(ErrUnknownExecutionDataType, "block.version=%d", block.Version)
} }
return blocks.WrappedExecutionPayloadCapella(&pb.ExecutionPayloadCapella{
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,
Withdrawals: block.Withdrawals,
}, big.NewInt(0)) // We can't get the block value and don't care about the block value for this instance
} }
// Handles errors received from the RPC server according to the specification. // Handles errors received from the RPC server according to the specification.

View File

@@ -36,4 +36,7 @@ var (
ErrNilResponse = errors.New("nil response") ErrNilResponse = errors.New("nil response")
// ErrRequestTooLarge when the request is too large // ErrRequestTooLarge when the request is too large
ErrRequestTooLarge = errors.New("request too large") ErrRequestTooLarge = errors.New("request too large")
// ErrUnknownExecutionDataType is an internal error when an execution payload type is unrecognized,
// making type conversions impossible to do correctly.
ErrUnknownExecutionDataType = errors.New("unknown execution data type")
) )

View File

@@ -405,8 +405,8 @@ func TestProcessETH2GenesisLog_CorrectNumOfDeposits(t *testing.T) {
web3Service.rpcClient = &mockExecution.RPCClient{Backend: testAcc.Backend} web3Service.rpcClient = &mockExecution.RPCClient{Backend: testAcc.Backend}
web3Service.httpLogger = testAcc.Backend web3Service.httpLogger = testAcc.Backend
web3Service.latestEth1Data.LastRequestedBlock = 0 web3Service.latestEth1Data.LastRequestedBlock = 0
web3Service.latestEth1Data.BlockHeight = testAcc.Backend.Blockchain().CurrentBlock().NumberU64() web3Service.latestEth1Data.BlockHeight = testAcc.Backend.Blockchain().CurrentBlock().Number.Uint64()
web3Service.latestEth1Data.BlockTime = testAcc.Backend.Blockchain().CurrentBlock().Time() web3Service.latestEth1Data.BlockTime = testAcc.Backend.Blockchain().CurrentBlock().Time
bConfig := params.MinimalSpecConfig().Copy() bConfig := params.MinimalSpecConfig().Copy()
bConfig.MinGenesisTime = 0 bConfig.MinGenesisTime = 0
bConfig.SecondsPerETH1Block = 10 bConfig.SecondsPerETH1Block = 10
@@ -444,8 +444,8 @@ func TestProcessETH2GenesisLog_CorrectNumOfDeposits(t *testing.T) {
for i := uint64(0); i < params.BeaconConfig().Eth1FollowDistance; i++ { for i := uint64(0); i < params.BeaconConfig().Eth1FollowDistance; i++ {
testAcc.Backend.Commit() testAcc.Backend.Commit()
} }
web3Service.latestEth1Data.BlockHeight = testAcc.Backend.Blockchain().CurrentBlock().NumberU64() web3Service.latestEth1Data.BlockHeight = testAcc.Backend.Blockchain().CurrentBlock().Number.Uint64()
web3Service.latestEth1Data.BlockTime = testAcc.Backend.Blockchain().CurrentBlock().Time() web3Service.latestEth1Data.BlockTime = testAcc.Backend.Blockchain().CurrentBlock().Time
// Set up our subscriber now to listen for the chain started event. // Set up our subscriber now to listen for the chain started event.
stateChannel := make(chan *feed.Event, 1) stateChannel := make(chan *feed.Event, 1)
@@ -502,8 +502,8 @@ func TestProcessETH2GenesisLog_LargePeriodOfNoLogs(t *testing.T) {
web3Service.rpcClient = &mockExecution.RPCClient{Backend: testAcc.Backend} web3Service.rpcClient = &mockExecution.RPCClient{Backend: testAcc.Backend}
web3Service.httpLogger = testAcc.Backend web3Service.httpLogger = testAcc.Backend
web3Service.latestEth1Data.LastRequestedBlock = 0 web3Service.latestEth1Data.LastRequestedBlock = 0
web3Service.latestEth1Data.BlockHeight = testAcc.Backend.Blockchain().CurrentBlock().NumberU64() web3Service.latestEth1Data.BlockHeight = testAcc.Backend.Blockchain().CurrentBlock().Number.Uint64()
web3Service.latestEth1Data.BlockTime = testAcc.Backend.Blockchain().CurrentBlock().Time() web3Service.latestEth1Data.BlockTime = testAcc.Backend.Blockchain().CurrentBlock().Time
bConfig := params.MinimalSpecConfig().Copy() bConfig := params.MinimalSpecConfig().Copy()
bConfig.SecondsPerETH1Block = 10 bConfig.SecondsPerETH1Block = 10
params.OverrideBeaconConfig(bConfig) params.OverrideBeaconConfig(bConfig)
@@ -540,14 +540,14 @@ func TestProcessETH2GenesisLog_LargePeriodOfNoLogs(t *testing.T) {
for i := uint64(0); i < 1500; i++ { for i := uint64(0); i < 1500; i++ {
testAcc.Backend.Commit() testAcc.Backend.Commit()
} }
wantedGenesisTime := testAcc.Backend.Blockchain().CurrentBlock().Time() wantedGenesisTime := testAcc.Backend.Blockchain().CurrentBlock().Time
// Forward the chain to account for the follow distance // Forward the chain to account for the follow distance
for i := uint64(0); i < params.BeaconConfig().Eth1FollowDistance; i++ { for i := uint64(0); i < params.BeaconConfig().Eth1FollowDistance; i++ {
testAcc.Backend.Commit() testAcc.Backend.Commit()
} }
web3Service.latestEth1Data.BlockHeight = testAcc.Backend.Blockchain().CurrentBlock().NumberU64() web3Service.latestEth1Data.BlockHeight = testAcc.Backend.Blockchain().CurrentBlock().Number.Uint64()
web3Service.latestEth1Data.BlockTime = testAcc.Backend.Blockchain().CurrentBlock().Time() web3Service.latestEth1Data.BlockTime = testAcc.Backend.Blockchain().CurrentBlock().Time
// Set the genesis time 500 blocks ahead of the last // Set the genesis time 500 blocks ahead of the last
// deposit log. // deposit log.

View File

@@ -3,6 +3,7 @@ package execution
import ( import (
"context" "context"
"fmt" "fmt"
"net/http"
"net/url" "net/url"
"strings" "strings"
"time" "time"
@@ -14,7 +15,6 @@ import (
contracts "github.com/prysmaticlabs/prysm/v4/contracts/deposit" contracts "github.com/prysmaticlabs/prysm/v4/contracts/deposit"
"github.com/prysmaticlabs/prysm/v4/io/logs" "github.com/prysmaticlabs/prysm/v4/io/logs"
"github.com/prysmaticlabs/prysm/v4/network" "github.com/prysmaticlabs/prysm/v4/network"
"github.com/prysmaticlabs/prysm/v4/network/authorization"
) )
func (s *Service) setupExecutionClientConnections(ctx context.Context, currEndpoint network.Endpoint) error { func (s *Service) setupExecutionClientConnections(ctx context.Context, currEndpoint network.Endpoint) error {
@@ -34,7 +34,7 @@ func (s *Service) setupExecutionClientConnections(ctx context.Context, currEndpo
} }
s.depositContractCaller = depositContractCaller s.depositContractCaller = depositContractCaller
// Ensure we have the correct chain and deposit IDs. //Ensure we have the correct chain and deposit IDs.
if err := ensureCorrectExecutionChain(ctx, fetcher); err != nil { if err := ensureCorrectExecutionChain(ctx, fetcher); err != nil {
client.Close() client.Close()
errStr := err.Error() errStr := err.Error()
@@ -113,9 +113,21 @@ func (s *Service) newRPCClientWithAuth(ctx context.Context, endpoint network.End
if err != nil { if err != nil {
return nil, err return nil, err
} }
headers := http.Header{}
for _, h := range s.cfg.headers {
if h == "" {
continue
}
keyValue := strings.Split(h, "=")
if len(keyValue) < 2 {
log.Warnf("Incorrect HTTP header flag format. Skipping %v", keyValue[0])
continue
}
headers.Set(keyValue[0], strings.Join(keyValue[1:], "="))
}
switch u.Scheme { switch u.Scheme {
case "http", "https": case "http", "https":
client, err = gethRPC.DialOptions(ctx, endpoint.Url, gethRPC.WithHTTPClient(endpoint.HttpClient())) client, err = gethRPC.DialOptions(ctx, endpoint.Url, gethRPC.WithHTTPClient(endpoint.HttpClient()), gethRPC.WithHeaders(headers))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -127,13 +139,6 @@ func (s *Service) newRPCClientWithAuth(ctx context.Context, endpoint network.End
default: default:
return nil, fmt.Errorf("no known transport for URL scheme %q", u.Scheme) return nil, fmt.Errorf("no known transport for URL scheme %q", u.Scheme)
} }
if endpoint.Auth.Method != authorization.None {
header, err := endpoint.Auth.ToHeaderValue()
if err != nil {
return nil, err
}
client.SetHeader("Authorization", header)
}
for _, h := range s.cfg.headers { for _, h := range s.cfg.headers {
if h != "" { if h != "" {
keyValue := strings.Split(h, "=") keyValue := strings.Split(h, "=")

View File

@@ -210,14 +210,14 @@ func TestFollowBlock_OK(t *testing.T) {
web3Service = setDefaultMocks(web3Service) web3Service = setDefaultMocks(web3Service)
web3Service.rpcClient = &mockExecution.RPCClient{Backend: testAcc.Backend} web3Service.rpcClient = &mockExecution.RPCClient{Backend: testAcc.Backend}
baseHeight := testAcc.Backend.Blockchain().CurrentBlock().NumberU64() baseHeight := testAcc.Backend.Blockchain().CurrentBlock().Number.Uint64()
// process follow_distance blocks // process follow_distance blocks
for i := 0; i < int(params.BeaconConfig().Eth1FollowDistance); i++ { for i := 0; i < int(params.BeaconConfig().Eth1FollowDistance); i++ {
testAcc.Backend.Commit() testAcc.Backend.Commit()
} }
// set current height // set current height
web3Service.latestEth1Data.BlockHeight = testAcc.Backend.Blockchain().CurrentBlock().NumberU64() web3Service.latestEth1Data.BlockHeight = testAcc.Backend.Blockchain().CurrentBlock().Number.Uint64()
web3Service.latestEth1Data.BlockTime = testAcc.Backend.Blockchain().CurrentBlock().Time() web3Service.latestEth1Data.BlockTime = testAcc.Backend.Blockchain().CurrentBlock().Time
h, err := web3Service.followedBlockHeight(context.Background()) h, err := web3Service.followedBlockHeight(context.Background())
require.NoError(t, err) require.NoError(t, err)
@@ -229,8 +229,8 @@ func TestFollowBlock_OK(t *testing.T) {
testAcc.Backend.Commit() testAcc.Backend.Commit()
} }
// set current height // set current height
web3Service.latestEth1Data.BlockHeight = testAcc.Backend.Blockchain().CurrentBlock().NumberU64() web3Service.latestEth1Data.BlockHeight = testAcc.Backend.Blockchain().CurrentBlock().Number.Uint64()
web3Service.latestEth1Data.BlockTime = testAcc.Backend.Blockchain().CurrentBlock().Time() web3Service.latestEth1Data.BlockTime = testAcc.Backend.Blockchain().CurrentBlock().Time
h, err = web3Service.followedBlockHeight(context.Background()) h, err = web3Service.followedBlockHeight(context.Background())
require.NoError(t, err) require.NoError(t, err)

View File

@@ -38,6 +38,7 @@ type EngineClient struct {
TerminalBlockHash []byte TerminalBlockHash []byte
TerminalBlockHashExists bool TerminalBlockHashExists bool
OverrideValidHash [32]byte OverrideValidHash [32]byte
BlobsBundle *pb.BlobsBundle
BlockValue *big.Int BlockValue *big.Int
} }
@@ -172,3 +173,8 @@ func (e *EngineClient) GetTerminalBlockHash(ctx context.Context, transitionTime
blk = parentBlk blk = parentBlk
} }
} }
// GetBlobsBundle --
func (e *EngineClient) GetBlobsBundle(ctx context.Context, payloadId [8]byte) (*pb.BlobsBundle, error) {
return e.BlobsBundle, nil
}

View File

@@ -61,6 +61,7 @@ go_library(
"//runtime/prereqs:go_default_library", "//runtime/prereqs:go_default_library",
"//runtime/version:go_default_library", "//runtime/version:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library", "@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_gorilla_mux//:go_default_library",
"@com_github_pkg_errors//:go_default_library", "@com_github_pkg_errors//:go_default_library",
"@com_github_prometheus_client_golang//prometheus:go_default_library", "@com_github_prometheus_client_golang//prometheus:go_default_library",
"@com_github_prysmaticlabs_fastssz//:go_default_library", "@com_github_prysmaticlabs_fastssz//:go_default_library",

View File

@@ -15,6 +15,7 @@ import (
"syscall" "syscall"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/gorilla/mux"
"github.com/pkg/errors" "github.com/pkg/errors"
apigateway "github.com/prysmaticlabs/prysm/v4/api/gateway" apigateway "github.com/prysmaticlabs/prysm/v4/api/gateway"
"github.com/prysmaticlabs/prysm/v4/async/event" "github.com/prysmaticlabs/prysm/v4/async/event"
@@ -253,12 +254,13 @@ func New(cliCtx *cli.Context, opts ...Option) (*BeaconNode, error) {
} }
log.Debugln("Registering RPC Service") log.Debugln("Registering RPC Service")
if err := beacon.registerRPCService(); err != nil { router := mux.NewRouter()
if err := beacon.registerRPCService(router); err != nil {
return nil, err return nil, err
} }
log.Debugln("Registering GRPC Gateway Service") log.Debugln("Registering GRPC Gateway Service")
if err := beacon.registerGRPCGateway(); err != nil { if err := beacon.registerGRPCGateway(router); err != nil {
return nil, err return nil, err
} }
@@ -734,7 +736,7 @@ func (b *BeaconNode) registerSlasherService() error {
return b.services.RegisterService(slasherSrv) return b.services.RegisterService(slasherSrv)
} }
func (b *BeaconNode) registerRPCService() error { func (b *BeaconNode) registerRPCService(router *mux.Router) error {
var chainService *blockchain.Service var chainService *blockchain.Service
if err := b.services.FetchService(&chainService); err != nil { if err := b.services.FetchService(&chainService); err != nil {
return err return err
@@ -830,6 +832,7 @@ func (b *BeaconNode) registerRPCService() error {
MaxMsgSize: maxMsgSize, MaxMsgSize: maxMsgSize,
ProposerIdsCache: b.proposerIdsCache, ProposerIdsCache: b.proposerIdsCache,
BlockBuilder: b.fetchBuilderService(), BlockBuilder: b.fetchBuilderService(),
Router: router,
}) })
return b.services.RegisterService(rpcService) return b.services.RegisterService(rpcService)
@@ -858,7 +861,7 @@ func (b *BeaconNode) registerPrometheusService(_ *cli.Context) error {
return b.services.RegisterService(service) return b.services.RegisterService(service)
} }
func (b *BeaconNode) registerGRPCGateway() error { func (b *BeaconNode) registerGRPCGateway(router *mux.Router) error {
if b.cliCtx.Bool(flags.DisableGRPCGateway.Name) { if b.cliCtx.Bool(flags.DisableGRPCGateway.Name) {
return nil return nil
} }
@@ -884,6 +887,7 @@ func (b *BeaconNode) registerGRPCGateway() error {
} }
opts := []apigateway.Option{ opts := []apigateway.Option{
apigateway.WithRouter(router),
apigateway.WithGatewayAddr(gatewayAddress), apigateway.WithGatewayAddr(gatewayAddress),
apigateway.WithRemoteAddr(selfAddress), apigateway.WithRemoteAddr(selfAddress),
apigateway.WithPbHandlers(muxs), apigateway.WithPbHandlers(muxs),

View File

@@ -141,6 +141,35 @@ func (s *Service) broadcastAttestation(ctx context.Context, subnet uint64, att *
} }
} }
// BroadcastBlob broadcasts a blob to the p2p network, the message is assumed to be
// broadcasted to the current fork and to the input subnet.
func (s *Service) BroadcastBlob(ctx context.Context, subnet uint64, blob *ethpb.SignedBlobSidecar) error {
ctx, span := trace.StartSpan(ctx, "p2p.BroadcastBlob")
defer span.End()
forkDigest, err := s.currentForkDigest()
if err != nil {
err := errors.Wrap(err, "could not retrieve fork digest")
tracing.AnnotateError(span, err)
return err
}
// Non-blocking broadcast, with attempts to discover a subnet peer if none available.
go s.broadcastBlob(ctx, subnet, blob, forkDigest)
return nil
}
func (s *Service) broadcastBlob(ctx context.Context, subnet uint64, blobSidecar *ethpb.SignedBlobSidecar, forkDigest [4]byte) {
ctx, span := trace.StartSpan(ctx, "p2p.broadcastBlob")
defer span.End()
ctx = trace.NewContext(context.Background(), span) // clear parent context / deadline.
if err := s.broadcastObject(ctx, blobSidecar, blobSubnetToTopic(subnet, forkDigest)); err != nil {
log.WithError(err).Error("Failed to broadcast blob sidecar")
tracing.AnnotateError(span, err)
}
}
func (s *Service) broadcastSyncCommittee(ctx context.Context, subnet uint64, sMsg *ethpb.SyncCommitteeMessage, forkDigest [4]byte) { func (s *Service) broadcastSyncCommittee(ctx context.Context, subnet uint64, sMsg *ethpb.SyncCommitteeMessage, forkDigest [4]byte) {
ctx, span := trace.StartSpan(ctx, "p2p.broadcastSyncCommittee") ctx, span := trace.StartSpan(ctx, "p2p.broadcastSyncCommittee")
defer span.End() defer span.End()
@@ -232,3 +261,7 @@ func attestationToTopic(subnet uint64, forkDigest [4]byte) string {
func syncCommitteeToTopic(subnet uint64, forkDigest [4]byte) string { func syncCommitteeToTopic(subnet uint64, forkDigest [4]byte) string {
return fmt.Sprintf(SyncCommitteeSubnetTopicFormat, forkDigest, subnet) return fmt.Sprintf(SyncCommitteeSubnetTopicFormat, forkDigest, subnet)
} }
func blobSubnetToTopic(subnet uint64, forkDigest [4]byte) string {
return fmt.Sprintf(BlobSubnetTopicFormat, forkDigest, subnet)
}

View File

@@ -17,7 +17,8 @@ func (s *Service) forkWatcher() {
currEpoch := slots.ToEpoch(currSlot) currEpoch := slots.ToEpoch(currSlot)
if currEpoch == params.BeaconConfig().AltairForkEpoch || if currEpoch == params.BeaconConfig().AltairForkEpoch ||
currEpoch == params.BeaconConfig().BellatrixForkEpoch || currEpoch == params.BeaconConfig().BellatrixForkEpoch ||
currEpoch == params.BeaconConfig().CapellaForkEpoch { currEpoch == params.BeaconConfig().CapellaForkEpoch ||
currEpoch == params.BeaconConfig().DenebForkEpoch {
// If we are in the fork epoch, we update our enr with // If we are in the fork epoch, we update our enr with
// the updated fork digest. These repeatedly does // the updated fork digest. These repeatedly does
// this over the epoch, which might be slightly wasteful // this over the epoch, which might be slightly wasteful

View File

@@ -119,6 +119,9 @@ func (s *Service) topicScoreParams(topic string) (*pubsub.TopicScoreParams, erro
return defaultProposerSlashingTopicParams(), nil return defaultProposerSlashingTopicParams(), nil
case strings.Contains(topic, GossipAttesterSlashingMessage): case strings.Contains(topic, GossipAttesterSlashingMessage):
return defaultAttesterSlashingTopicParams(), nil return defaultAttesterSlashingTopicParams(), nil
case strings.Contains(topic, GossipBlobSidecarMessage):
// TODO(Deneb): Using the default block scoring. But this should be updated.
return defaultBlockTopicParams(), nil
case strings.Contains(topic, GossipBlsToExecutionChangeMessage): case strings.Contains(topic, GossipBlsToExecutionChangeMessage):
return defaultBlsToExecutionChangeTopicParams(), nil return defaultBlsToExecutionChangeTopicParams(), nil
default: default:

View File

@@ -21,12 +21,16 @@ var gossipTopicMappings = map[string]proto.Message{
SyncContributionAndProofSubnetTopicFormat: &ethpb.SignedContributionAndProof{}, SyncContributionAndProofSubnetTopicFormat: &ethpb.SignedContributionAndProof{},
SyncCommitteeSubnetTopicFormat: &ethpb.SyncCommitteeMessage{}, SyncCommitteeSubnetTopicFormat: &ethpb.SyncCommitteeMessage{},
BlsToExecutionChangeSubnetTopicFormat: &ethpb.SignedBLSToExecutionChange{}, BlsToExecutionChangeSubnetTopicFormat: &ethpb.SignedBLSToExecutionChange{},
BlobSubnetTopicFormat: &ethpb.SignedBlobSidecar{},
} }
// GossipTopicMappings is a function to return the assigned data type // GossipTopicMappings is a function to return the assigned data type
// versioned by epoch. // versioned by epoch.
func GossipTopicMappings(topic string, epoch primitives.Epoch) proto.Message { func GossipTopicMappings(topic string, epoch primitives.Epoch) proto.Message {
if topic == BlockSubnetTopicFormat { if topic == BlockSubnetTopicFormat {
if epoch >= params.BeaconConfig().DenebForkEpoch {
return &ethpb.SignedBeaconBlockDeneb{}
}
if epoch >= params.BeaconConfig().CapellaForkEpoch { if epoch >= params.BeaconConfig().CapellaForkEpoch {
return &ethpb.SignedBeaconBlockCapella{} return &ethpb.SignedBeaconBlockCapella{}
} }
@@ -64,4 +68,6 @@ func init() {
GossipTypeMapping[reflect.TypeOf(&ethpb.SignedBeaconBlockBellatrix{})] = BlockSubnetTopicFormat GossipTypeMapping[reflect.TypeOf(&ethpb.SignedBeaconBlockBellatrix{})] = BlockSubnetTopicFormat
// Specially handle Capella objects // Specially handle Capella objects
GossipTypeMapping[reflect.TypeOf(&ethpb.SignedBeaconBlockCapella{})] = BlockSubnetTopicFormat GossipTypeMapping[reflect.TypeOf(&ethpb.SignedBeaconBlockCapella{})] = BlockSubnetTopicFormat
// Specially handle Deneb objects
GossipTypeMapping[reflect.TypeOf(&ethpb.SignedBeaconBlockDeneb{})] = BlockSubnetTopicFormat
} }

View File

@@ -35,6 +35,7 @@ type Broadcaster interface {
Broadcast(context.Context, proto.Message) error Broadcast(context.Context, proto.Message) error
BroadcastAttestation(ctx context.Context, subnet uint64, att *ethpb.Attestation) error BroadcastAttestation(ctx context.Context, subnet uint64, att *ethpb.Attestation) error
BroadcastSyncCommitteeMessage(ctx context.Context, subnet uint64, sMsg *ethpb.SyncCommitteeMessage) error BroadcastSyncCommitteeMessage(ctx context.Context, subnet uint64, sMsg *ethpb.SyncCommitteeMessage) error
BroadcastBlob(ctx context.Context, subnet uint64, blobSidecar *ethpb.SignedBlobSidecar) error
} }
// SetStreamHandler configures p2p to handle streams of a certain topic ID. // SetStreamHandler configures p2p to handle streams of a certain topic ID.

View File

@@ -57,12 +57,17 @@ func (s *Service) CanSubscribe(topic string) bool {
log.WithError(err).Error("Could not determine Capella fork digest") log.WithError(err).Error("Could not determine Capella fork digest")
return false return false
} }
denebForkDigest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().DenebForkEpoch, s.genesisValidatorsRoot)
if err != nil {
log.WithError(err).Error("Could not determine Capella fork digest")
return false
}
switch parts[2] { switch parts[2] {
case fmt.Sprintf("%x", phase0ForkDigest): case fmt.Sprintf("%x", phase0ForkDigest):
case fmt.Sprintf("%x", altairForkDigest): case fmt.Sprintf("%x", altairForkDigest):
case fmt.Sprintf("%x", bellatrixForkDigest): case fmt.Sprintf("%x", bellatrixForkDigest):
case fmt.Sprintf("%x", capellaForkDigest): case fmt.Sprintf("%x", capellaForkDigest):
case fmt.Sprintf("%x", denebForkDigest):
default: default:
return false return false
} }

View File

@@ -92,7 +92,7 @@ func TestService_CanSubscribe(t *testing.T) {
formatting := []interface{}{digest} formatting := []interface{}{digest}
// Special case for attestation subnets which have a second formatting placeholder. // Special case for attestation subnets which have a second formatting placeholder.
if topic == AttestationSubnetTopicFormat || topic == SyncCommitteeSubnetTopicFormat { if topic == AttestationSubnetTopicFormat || topic == SyncCommitteeSubnetTopicFormat || topic == BlobSubnetTopicFormat {
formatting = append(formatting, 0 /* some subnet ID */) formatting = append(formatting, 0 /* some subnet ID */)
} }

View File

@@ -37,6 +37,9 @@ const PingMessageName = "/ping"
// MetadataMessageName specifies the name for the metadata message topic. // MetadataMessageName specifies the name for the metadata message topic.
const MetadataMessageName = "/metadata" const MetadataMessageName = "/metadata"
const BlobSidecarsByRootName = "/blob_sidecars_by_root"
const BlobSidecarsByRangeName = "/blob_sidecars_by_range"
const ( const (
// V1 RPC Topics // V1 RPC Topics
// RPCStatusTopicV1 defines the v1 topic for the status rpc method. // RPCStatusTopicV1 defines the v1 topic for the status rpc method.
@@ -52,6 +55,15 @@ const (
// RPCMetaDataTopicV1 defines the v1 topic for the metadata rpc method. // RPCMetaDataTopicV1 defines the v1 topic for the metadata rpc method.
RPCMetaDataTopicV1 = protocolPrefix + MetadataMessageName + SchemaVersionV1 RPCMetaDataTopicV1 = protocolPrefix + MetadataMessageName + SchemaVersionV1
// RPCBlobSidecarsByRootTopicV1 is a topic for requesting blob sidecars by their block root. New in deneb.
// /eth2/beacon_chain/req/blob_sidecars_by_root/1/
RPCBlobSidecarsByRootTopicV1 = protocolPrefix + BlobSidecarsByRootName + SchemaVersionV1
// RPCBlobSidecarsByRangeTopicV1 is a topic for requesting blob sidecars
// in the slot range [start_slot, start_slot + count), leading up to the current head block as selected by fork choice.
// Protocol ID: /eth2/beacon_chain/req/blob_sidecars_by_range/1/ - New in deneb.
RPCBlobSidecarsByRangeTopicV1 = protocolPrefix + BlobSidecarsByRangeName + SchemaVersionV1
// V2 RPC Topics // V2 RPC Topics
// RPCBlocksByRangeTopicV2 defines v2 the topic for the blocks by range rpc method. // RPCBlocksByRangeTopicV2 defines v2 the topic for the blocks by range rpc method.
RPCBlocksByRangeTopicV2 = protocolPrefix + BeaconBlocksByRangeMessageName + SchemaVersionV2 RPCBlocksByRangeTopicV2 = protocolPrefix + BeaconBlocksByRangeMessageName + SchemaVersionV2
@@ -83,6 +95,10 @@ var RPCTopicMappings = map[string]interface{}{
// RPC Metadata Message // RPC Metadata Message
RPCMetaDataTopicV1: new(interface{}), RPCMetaDataTopicV1: new(interface{}),
RPCMetaDataTopicV2: new(interface{}), RPCMetaDataTopicV2: new(interface{}),
// BlobSidecarsByRange v1 Message
RPCBlobSidecarsByRangeTopicV1: new(pb.BlobSidecarsByRangeRequest),
// BlobSidecarsByRoot v1 Message
RPCBlobSidecarsByRootTopicV1: new(p2ptypes.BlobSidecarsByRootReq),
} }
// Maps all registered protocol prefixes. // Maps all registered protocol prefixes.
@@ -99,6 +115,8 @@ var messageMapping = map[string]bool{
BeaconBlocksByRootsMessageName: true, BeaconBlocksByRootsMessageName: true,
PingMessageName: true, PingMessageName: true,
MetadataMessageName: true, MetadataMessageName: true,
BlobSidecarsByRangeName: true,
BlobSidecarsByRootName: true,
} }
// Maps all the RPC messages which are to updated in altair. // Maps all the RPC messages which are to updated in altair.
@@ -113,6 +131,15 @@ var versionMapping = map[string]bool{
SchemaVersionV2: true, SchemaVersionV2: true,
} }
var PreAltairV1SchemaMapping = map[string]bool{
StatusMessageName: true,
GoodbyeMessageName: true,
BeaconBlocksByRangeMessageName: true,
BeaconBlocksByRootsMessageName: true,
PingMessageName: true,
MetadataMessageName: true,
}
// VerifyTopicMapping verifies that the topic and its accompanying // VerifyTopicMapping verifies that the topic and its accompanying
// message type is correct. // message type is correct.
func VerifyTopicMapping(topic string, msg interface{}) error { func VerifyTopicMapping(topic string, msg interface{}) error {

View File

@@ -138,6 +138,11 @@ func (_ *FakeP2P) BroadcastAttestation(_ context.Context, _ uint64, _ *ethpb.Att
return nil return nil
} }
// BroadcastBlob -- fake.
func (p *FakeP2P) BroadcastBlob(ctx context.Context, subnet uint64, blobSidecar *ethpb.SignedBlobSidecar) error {
return nil
}
// BroadcastSyncCommitteeMessage -- fake. // BroadcastSyncCommitteeMessage -- fake.
func (_ *FakeP2P) BroadcastSyncCommitteeMessage(_ context.Context, _ uint64, _ *ethpb.SyncCommitteeMessage) error { func (_ *FakeP2P) BroadcastSyncCommitteeMessage(_ context.Context, _ uint64, _ *ethpb.SyncCommitteeMessage) error {
return nil return nil

View File

@@ -33,3 +33,9 @@ func (m *MockBroadcaster) BroadcastSyncCommitteeMessage(_ context.Context, _ uin
m.BroadcastCalled = true m.BroadcastCalled = true
return nil return nil
} }
// BroadcastSyncCommitteeMessage records a broadcast occurred.
func (m *MockBroadcaster) BroadcastBlob(ctx context.Context, subnet uint64, blob *ethpb.SignedBlobSidecar) error {
m.BroadcastCalled = true
return nil
}

View File

@@ -170,6 +170,11 @@ func (p *TestP2P) BroadcastAttestation(_ context.Context, _ uint64, _ *ethpb.Att
return nil return nil
} }
func (p *TestP2P) BroadcastBlob(ctx context.Context, subnet uint64, blobSidecar *ethpb.SignedBlobSidecar) error {
p.BroadcastCalled = true
return nil
}
// BroadcastSyncCommitteeMessage broadcasts a sync committee message. // BroadcastSyncCommitteeMessage broadcasts a sync committee message.
func (p *TestP2P) BroadcastSyncCommitteeMessage(_ context.Context, _ uint64, _ *ethpb.SyncCommitteeMessage) error { func (p *TestP2P) BroadcastSyncCommitteeMessage(_ context.Context, _ uint64, _ *ethpb.SyncCommitteeMessage) error {
p.BroadcastCalled = true p.BroadcastCalled = true

View File

@@ -28,6 +28,8 @@ const (
GossipContributionAndProofMessage = "sync_committee_contribution_and_proof" GossipContributionAndProofMessage = "sync_committee_contribution_and_proof"
// GossipBlsToExecutionChangeMessage is the name for the bls to execution change message type. // GossipBlsToExecutionChangeMessage is the name for the bls to execution change message type.
GossipBlsToExecutionChangeMessage = "bls_to_execution_change" GossipBlsToExecutionChangeMessage = "bls_to_execution_change"
// GossipBlobSidecarMessage is the name for the blob sidecar message type.
GossipBlobSidecarMessage = "blob_sidecar"
// Topic Formats // Topic Formats
// //
@@ -49,4 +51,6 @@ const (
SyncContributionAndProofSubnetTopicFormat = GossipProtocolAndDigest + GossipContributionAndProofMessage SyncContributionAndProofSubnetTopicFormat = GossipProtocolAndDigest + GossipContributionAndProofMessage
// BlsToExecutionChangeSubnetTopicFormat is the topic format for the bls to execution change subnet. // BlsToExecutionChangeSubnetTopicFormat is the topic format for the bls to execution change subnet.
BlsToExecutionChangeSubnetTopicFormat = GossipProtocolAndDigest + GossipBlsToExecutionChangeMessage BlsToExecutionChangeSubnetTopicFormat = GossipProtocolAndDigest + GossipBlsToExecutionChangeMessage
// BlobSubnetTopicFormat is the topic format for the blob subnet.
BlobSubnetTopicFormat = GossipProtocolAndDigest + GossipBlobSidecarMessage + "_%d"
) )

View File

@@ -41,7 +41,9 @@ go_test(
"//config/params:go_default_library", "//config/params:go_default_library",
"//consensus-types/primitives:go_default_library", "//consensus-types/primitives:go_default_library",
"//encoding/bytesutil:go_default_library", "//encoding/bytesutil:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//testing/assert:go_default_library", "//testing/assert:go_default_library",
"//testing/require:go_default_library", "//testing/require:go_default_library",
"@com_github_prysmaticlabs_fastssz//:go_default_library",
], ],
) )

View File

@@ -53,6 +53,11 @@ func InitializeDataMaps() {
&ethpb.SignedBeaconBlockCapella{Block: &ethpb.BeaconBlockCapella{Body: &ethpb.BeaconBlockBodyCapella{}}}, &ethpb.SignedBeaconBlockCapella{Block: &ethpb.BeaconBlockCapella{Body: &ethpb.BeaconBlockBodyCapella{}}},
) )
}, },
bytesutil.ToBytes4(params.BeaconConfig().DenebForkVersion): func() (interfaces.ReadOnlySignedBeaconBlock, error) {
return blocks.NewSignedBeaconBlock(
&ethpb.SignedBeaconBlockDeneb{Block: &ethpb.BeaconBlockDeneb{Body: &ethpb.BeaconBlockBodyDeneb{}}},
)
},
} }
// Reset our metadata map. // Reset our metadata map.
@@ -69,5 +74,8 @@ func InitializeDataMaps() {
bytesutil.ToBytes4(params.BeaconConfig().CapellaForkVersion): func() metadata.Metadata { bytesutil.ToBytes4(params.BeaconConfig().CapellaForkVersion): func() metadata.Metadata {
return wrapper.WrappedMetadataV1(&ethpb.MetaDataV1{}) return wrapper.WrappedMetadataV1(&ethpb.MetaDataV1{})
}, },
bytesutil.ToBytes4(params.BeaconConfig().DenebForkVersion): func() metadata.Metadata {
return wrapper.WrappedMetadataV1(&ethpb.MetaDataV1{})
},
} }
} }

View File

@@ -12,4 +12,5 @@ var (
ErrRateLimited = errors.New("rate limited") ErrRateLimited = errors.New("rate limited")
ErrIODeadline = errors.New("i/o deadline exceeded") ErrIODeadline = errors.New("i/o deadline exceeded")
ErrInvalidRequest = errors.New("invalid range, step or count") ErrInvalidRequest = errors.New("invalid range, step or count")
ErrBlobLTMinRequest = errors.New("blob slot < minimum_request_epoch")
) )

View File

@@ -7,6 +7,7 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
ssz "github.com/prysmaticlabs/fastssz" ssz "github.com/prysmaticlabs/fastssz"
"github.com/prysmaticlabs/prysm/v4/config/params" "github.com/prysmaticlabs/prysm/v4/config/params"
eth "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
) )
const rootLength = 32 const rootLength = 32
@@ -120,3 +121,66 @@ func (m *ErrorMessage) UnmarshalSSZ(buf []byte) error {
*m = errMsg *m = errMsg
return nil return nil
} }
// BlobSidecarsByRootReq is used to specify a list of blob targets (root+index) in a BlobSidecarsByRoot RPC request.
type BlobSidecarsByRootReq []*eth.BlobIdentifier
// BlobIdentifier is a fixed size value, so we can compute its fixed size at start time (see init below)
var blobIdSize int
// SizeSSZ returns the size of the serialized representation.
func (b *BlobSidecarsByRootReq) SizeSSZ() int {
return len(*b) * blobIdSize
}
// MarshalSSZTo marshals the block by roots request with the provided byte slice.
func (b *BlobSidecarsByRootReq) MarshalSSZTo(dst []byte) ([]byte, error) {
// A List without an enclosing container is marshaled exactly like a vector, no length offset required.
marshalledObj, err := b.MarshalSSZ()
if err != nil {
return nil, err
}
return append(dst, marshalledObj...), nil
}
// MarshalSSZ Marshals the block by roots request type into the serialized object.
func (b *BlobSidecarsByRootReq) MarshalSSZ() ([]byte, error) {
buf := make([]byte, len(*b)*blobIdSize)
for i, id := range *b {
by, err := id.MarshalSSZ()
if err != nil {
return nil, err
}
copy(buf[i*blobIdSize:(i+1)*blobIdSize], by)
}
return buf, nil
}
// UnmarshalSSZ unmarshals the provided bytes buffer into the
// block by roots request object.
func (b *BlobSidecarsByRootReq) UnmarshalSSZ(buf []byte) error {
bufLen := len(buf)
maxLength := int(params.BeaconNetworkConfig().MaxRequestBlobsSidecars) * blobIdSize
if bufLen > maxLength {
return errors.Errorf("expected buffer with length of upto %d but received length %d", maxLength, bufLen)
}
if bufLen%blobIdSize != 0 {
return errors.Wrapf(ssz.ErrIncorrectByteSize, "size=%d", bufLen)
}
count := bufLen / blobIdSize
*b = make([]*eth.BlobIdentifier, count)
for i := 0; i < count; i++ {
id := &eth.BlobIdentifier{}
err := id.UnmarshalSSZ(buf[i*blobIdSize : (i+1)*blobIdSize])
if err != nil {
return err
}
(*b)[i] = id
}
return nil
}
func init() {
sizer := &eth.BlobIdentifier{}
blobIdSize = sizer.SizeSSZ()
}

View File

@@ -4,12 +4,82 @@ import (
"encoding/hex" "encoding/hex"
"testing" "testing"
ssz "github.com/prysmaticlabs/fastssz"
"github.com/prysmaticlabs/prysm/v4/config/params" "github.com/prysmaticlabs/prysm/v4/config/params"
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
eth "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v4/testing/assert" "github.com/prysmaticlabs/prysm/v4/testing/assert"
"github.com/prysmaticlabs/prysm/v4/testing/require" "github.com/prysmaticlabs/prysm/v4/testing/require"
) )
func generateBlobIdentifiers(n int) []*eth.BlobIdentifier {
r := make([]*eth.BlobIdentifier, n)
for i := 0; i < n; i++ {
r[i] = &eth.BlobIdentifier{
BlockRoot: bytesutil.PadTo([]byte{byte(i)}, 32),
Index: 0,
}
}
return r
}
func TestBlobSidecarsByRootReq_MarshalSSZ(t *testing.T) {
cases := []struct {
name string
ids []*eth.BlobIdentifier
marshalErr error
unmarshalErr error
unmarshalMod func([]byte) []byte
}{
{
name: "empty list",
},
{
name: "single item list",
ids: generateBlobIdentifiers(1),
},
{
name: "10 item list",
ids: generateBlobIdentifiers(10),
},
{
name: "wonky unmarshal size",
ids: generateBlobIdentifiers(10),
unmarshalMod: func(in []byte) []byte {
in = append(in, byte(0))
return in
},
unmarshalErr: ssz.ErrIncorrectByteSize,
},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
r := BlobSidecarsByRootReq(c.ids)
by, err := r.MarshalSSZ()
if c.marshalErr != nil {
require.ErrorIs(t, err, c.marshalErr)
return
}
require.NoError(t, err)
if c.unmarshalMod != nil {
by = c.unmarshalMod(by)
}
got := &BlobSidecarsByRootReq{}
err = got.UnmarshalSSZ(by)
if c.unmarshalErr != nil {
require.ErrorIs(t, err, c.unmarshalErr)
return
}
require.NoError(t, err)
for i, gid := range *got {
require.DeepEqual(t, c.ids[i], gid)
}
})
}
}
func TestBeaconBlockByRootsReq_Limit(t *testing.T) { func TestBeaconBlockByRootsReq_Limit(t *testing.T) {
fixedRoots := make([][32]byte, 0) fixedRoots := make([][32]byte, 0)
for i := uint64(0); i < params.BeaconNetworkConfig().MaxRequestBlocks+100; i++ { for i := uint64(0); i < params.BeaconNetworkConfig().MaxRequestBlocks+100; i++ {

View File

@@ -28,12 +28,13 @@ go_library(
"//beacon-chain/rpc/eth/debug:go_default_library", "//beacon-chain/rpc/eth/debug:go_default_library",
"//beacon-chain/rpc/eth/events:go_default_library", "//beacon-chain/rpc/eth/events:go_default_library",
"//beacon-chain/rpc/eth/node:go_default_library", "//beacon-chain/rpc/eth/node:go_default_library",
"//beacon-chain/rpc/eth/rewards:go_default_library",
"//beacon-chain/rpc/eth/validator:go_default_library", "//beacon-chain/rpc/eth/validator:go_default_library",
"//beacon-chain/rpc/lookup:go_default_library",
"//beacon-chain/rpc/prysm/v1alpha1/beacon:go_default_library", "//beacon-chain/rpc/prysm/v1alpha1/beacon:go_default_library",
"//beacon-chain/rpc/prysm/v1alpha1/debug:go_default_library", "//beacon-chain/rpc/prysm/v1alpha1/debug:go_default_library",
"//beacon-chain/rpc/prysm/v1alpha1/node:go_default_library", "//beacon-chain/rpc/prysm/v1alpha1/node:go_default_library",
"//beacon-chain/rpc/prysm/v1alpha1/validator:go_default_library", "//beacon-chain/rpc/prysm/v1alpha1/validator:go_default_library",
"//beacon-chain/rpc/statefetcher:go_default_library",
"//beacon-chain/slasher:go_default_library", "//beacon-chain/slasher:go_default_library",
"//beacon-chain/state/stategen:go_default_library", "//beacon-chain/state/stategen:go_default_library",
"//beacon-chain/sync:go_default_library", "//beacon-chain/sync:go_default_library",
@@ -43,6 +44,7 @@ go_library(
"//monitoring/tracing:go_default_library", "//monitoring/tracing:go_default_library",
"//proto/eth/service:go_default_library", "//proto/eth/service:go_default_library",
"//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1:go_default_library",
"@com_github_gorilla_mux//:go_default_library",
"@com_github_grpc_ecosystem_go_grpc_middleware//:go_default_library", "@com_github_grpc_ecosystem_go_grpc_middleware//:go_default_library",
"@com_github_grpc_ecosystem_go_grpc_middleware//recovery:go_default_library", "@com_github_grpc_ecosystem_go_grpc_middleware//recovery:go_default_library",
"@com_github_grpc_ecosystem_go_grpc_middleware//tracing/opentracing:go_default_library", "@com_github_grpc_ecosystem_go_grpc_middleware//tracing/opentracing:go_default_library",
@@ -68,6 +70,7 @@ go_test(
"//beacon-chain/sync/initial-sync/testing:go_default_library", "//beacon-chain/sync/initial-sync/testing:go_default_library",
"//testing/assert:go_default_library", "//testing/assert:go_default_library",
"//testing/require:go_default_library", "//testing/require:go_default_library",
"@com_github_gorilla_mux//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library",
"@com_github_sirupsen_logrus//hooks/test:go_default_library", "@com_github_sirupsen_logrus//hooks/test:go_default_library",
], ],

View File

@@ -503,6 +503,13 @@ type capellaBlockResponseJson struct {
Finalized bool `json:"finalized"` Finalized bool `json:"finalized"`
} }
type denebBlockResponseJson struct {
Version string `json:"version"`
Data *SignedBeaconBlockDenebContainerJson `json:"data"`
ExecutionOptimistic bool `json:"execution_optimistic"`
Finalized bool `json:"finalized"`
}
type bellatrixBlindedBlockResponseJson struct { type bellatrixBlindedBlockResponseJson struct {
Version string `json:"version" enum:"true"` Version string `json:"version" enum:"true"`
Data *SignedBlindedBeaconBlockBellatrixContainerJson `json:"data"` Data *SignedBlindedBeaconBlockBellatrixContainerJson `json:"data"`
@@ -517,6 +524,12 @@ type capellaBlindedBlockResponseJson struct {
Finalized bool `json:"finalized"` Finalized bool `json:"finalized"`
} }
type denebBlindedBlockResponseJson struct {
Version string `json:"version"`
Data *SignedBlindedBeaconBlockDenebContainerJson `json:"data"`
ExecutionOptimistic bool `json:"execution_optimistic"`
}
func serializeV2Block(response interface{}) (apimiddleware.RunDefault, []byte, apimiddleware.ErrorJson) { func serializeV2Block(response interface{}) (apimiddleware.RunDefault, []byte, apimiddleware.ErrorJson) {
respContainer, ok := response.(*BlockV2ResponseJson) respContainer, ok := response.(*BlockV2ResponseJson)
if !ok { if !ok {
@@ -565,6 +578,16 @@ func serializeV2Block(response interface{}) (apimiddleware.RunDefault, []byte, a
ExecutionOptimistic: respContainer.ExecutionOptimistic, ExecutionOptimistic: respContainer.ExecutionOptimistic,
Finalized: respContainer.Finalized, Finalized: respContainer.Finalized,
} }
case strings.EqualFold(respContainer.Version, strings.ToLower(ethpbv2.Version_Deneb.String())):
actualRespContainer = &denebBlockResponseJson{
Version: respContainer.Version,
Data: &SignedBeaconBlockDenebContainerJson{
Message: respContainer.Data.DenebBlock,
Signature: respContainer.Data.Signature,
},
ExecutionOptimistic: respContainer.ExecutionOptimistic,
Finalized: respContainer.Finalized,
}
default: default:
return false, nil, apimiddleware.InternalServerError(fmt.Errorf("unsupported block version '%s'", respContainer.Version)) return false, nil, apimiddleware.InternalServerError(fmt.Errorf("unsupported block version '%s'", respContainer.Version))
} }
@@ -624,6 +647,15 @@ func serializeBlindedBlock(response interface{}) (apimiddleware.RunDefault, []by
ExecutionOptimistic: respContainer.ExecutionOptimistic, ExecutionOptimistic: respContainer.ExecutionOptimistic,
Finalized: respContainer.Finalized, Finalized: respContainer.Finalized,
} }
case strings.EqualFold(respContainer.Version, strings.ToLower(ethpbv2.Version_Deneb.String())):
actualRespContainer = &denebBlindedBlockResponseJson{
Version: respContainer.Version,
Data: &SignedBlindedBeaconBlockDenebContainerJson{
Message: respContainer.Data.DenebBlock,
Signature: respContainer.Data.Signature,
},
ExecutionOptimistic: respContainer.ExecutionOptimistic,
}
default: default:
return false, nil, apimiddleware.InternalServerError(fmt.Errorf("unsupported block version '%s'", respContainer.Version)) return false, nil, apimiddleware.InternalServerError(fmt.Errorf("unsupported block version '%s'", respContainer.Version))
} }
@@ -655,6 +687,11 @@ type capellaStateResponseJson struct {
Data *BeaconStateCapellaJson `json:"data"` Data *BeaconStateCapellaJson `json:"data"`
} }
type denebStateResponseJson struct {
Version string `json:"version"`
Data *BeaconStateDenebJson `json:"data"`
}
func serializeV2State(response interface{}) (apimiddleware.RunDefault, []byte, apimiddleware.ErrorJson) { func serializeV2State(response interface{}) (apimiddleware.RunDefault, []byte, apimiddleware.ErrorJson) {
respContainer, ok := response.(*BeaconStateV2ResponseJson) respContainer, ok := response.(*BeaconStateV2ResponseJson)
if !ok { if !ok {
@@ -683,6 +720,11 @@ func serializeV2State(response interface{}) (apimiddleware.RunDefault, []byte, a
Version: respContainer.Version, Version: respContainer.Version,
Data: respContainer.Data.CapellaState, Data: respContainer.Data.CapellaState,
} }
case strings.EqualFold(respContainer.Version, strings.ToLower(ethpbv2.Version_Deneb.String())):
actualRespContainer = &denebStateResponseJson{
Version: respContainer.Version,
Data: respContainer.Data.DenebState,
}
default: default:
return false, nil, apimiddleware.InternalServerError(fmt.Errorf("unsupported state version '%s'", respContainer.Version)) return false, nil, apimiddleware.InternalServerError(fmt.Errorf("unsupported state version '%s'", respContainer.Version))
} }

View File

@@ -395,6 +395,7 @@ type SignedBeaconBlockContainerV2Json struct {
AltairBlock *BeaconBlockAltairJson `json:"altair_block"` AltairBlock *BeaconBlockAltairJson `json:"altair_block"`
BellatrixBlock *BeaconBlockBellatrixJson `json:"bellatrix_block"` BellatrixBlock *BeaconBlockBellatrixJson `json:"bellatrix_block"`
CapellaBlock *BeaconBlockCapellaJson `json:"capella_block"` CapellaBlock *BeaconBlockCapellaJson `json:"capella_block"`
DenebBlock *BeaconBlockDenebJson `json:"deneb_block"`
Signature string `json:"signature" hex:"true"` Signature string `json:"signature" hex:"true"`
} }
@@ -403,6 +404,7 @@ type SignedBlindedBeaconBlockContainerJson struct {
AltairBlock *BeaconBlockAltairJson `json:"altair_block"` AltairBlock *BeaconBlockAltairJson `json:"altair_block"`
BellatrixBlock *BlindedBeaconBlockBellatrixJson `json:"bellatrix_block"` BellatrixBlock *BlindedBeaconBlockBellatrixJson `json:"bellatrix_block"`
CapellaBlock *BlindedBeaconBlockCapellaJson `json:"capella_block"` CapellaBlock *BlindedBeaconBlockCapellaJson `json:"capella_block"`
DenebBlock *BlindedBeaconBlockDenebJson `json:"deneb_block"`
Signature string `json:"signature" hex:"true"` Signature string `json:"signature" hex:"true"`
} }
@@ -411,6 +413,7 @@ type BeaconBlockContainerV2Json struct {
AltairBlock *BeaconBlockAltairJson `json:"altair_block"` AltairBlock *BeaconBlockAltairJson `json:"altair_block"`
BellatrixBlock *BeaconBlockBellatrixJson `json:"bellatrix_block"` BellatrixBlock *BeaconBlockBellatrixJson `json:"bellatrix_block"`
CapellaBlock *BeaconBlockCapellaJson `json:"capella_block"` CapellaBlock *BeaconBlockCapellaJson `json:"capella_block"`
DenebBlock *BeaconBlockDenebJson `json:"deneb_block"`
} }
type BlindedBeaconBlockContainerJson struct { type BlindedBeaconBlockContainerJson struct {
@@ -418,6 +421,7 @@ type BlindedBeaconBlockContainerJson struct {
AltairBlock *BeaconBlockAltairJson `json:"altair_block"` AltairBlock *BeaconBlockAltairJson `json:"altair_block"`
BellatrixBlock *BlindedBeaconBlockBellatrixJson `json:"bellatrix_block"` BellatrixBlock *BlindedBeaconBlockBellatrixJson `json:"bellatrix_block"`
CapellaBlock *BlindedBeaconBlockCapellaJson `json:"capella_block"` CapellaBlock *BlindedBeaconBlockCapellaJson `json:"capella_block"`
DenebBlock *BlindedBeaconBlockDenebJson `json:"deneb_block"`
} }
type SignedBeaconBlockAltairContainerJson struct { type SignedBeaconBlockAltairContainerJson struct {
@@ -435,6 +439,11 @@ type SignedBeaconBlockCapellaContainerJson struct {
Signature string `json:"signature" hex:"true"` Signature string `json:"signature" hex:"true"`
} }
type SignedBeaconBlockDenebContainerJson struct {
Message *BeaconBlockDenebJson `json:"message"`
Signature string `json:"signature" hex:"true"`
}
type SignedBlindedBeaconBlockBellatrixContainerJson struct { type SignedBlindedBeaconBlockBellatrixContainerJson struct {
Message *BlindedBeaconBlockBellatrixJson `json:"message"` Message *BlindedBeaconBlockBellatrixJson `json:"message"`
Signature string `json:"signature" hex:"true"` Signature string `json:"signature" hex:"true"`
@@ -445,6 +454,11 @@ type SignedBlindedBeaconBlockCapellaContainerJson struct {
Signature string `json:"signature" hex:"true"` Signature string `json:"signature" hex:"true"`
} }
type SignedBlindedBeaconBlockDenebContainerJson struct {
Message *BlindedBeaconBlockDenebJson `json:"message"`
Signature string `json:"signature" hex:"true"`
}
type BeaconBlockAltairJson struct { type BeaconBlockAltairJson struct {
Slot string `json:"slot"` Slot string `json:"slot"`
ProposerIndex string `json:"proposer_index"` ProposerIndex string `json:"proposer_index"`
@@ -469,6 +483,14 @@ type BeaconBlockCapellaJson struct {
Body *BeaconBlockBodyCapellaJson `json:"body"` Body *BeaconBlockBodyCapellaJson `json:"body"`
} }
type BeaconBlockDenebJson struct {
Slot string `json:"slot"`
ProposerIndex string `json:"proposer_index"`
ParentRoot string `json:"parent_root" hex:"true"`
StateRoot string `json:"state_root" hex:"true"`
Body *BeaconBlockBodyDenebJson `json:"body"`
}
type BlindedBeaconBlockBellatrixJson struct { type BlindedBeaconBlockBellatrixJson struct {
Slot string `json:"slot"` Slot string `json:"slot"`
ProposerIndex string `json:"proposer_index"` ProposerIndex string `json:"proposer_index"`
@@ -485,6 +507,14 @@ type BlindedBeaconBlockCapellaJson struct {
Body *BlindedBeaconBlockBodyCapellaJson `json:"body"` Body *BlindedBeaconBlockBodyCapellaJson `json:"body"`
} }
type BlindedBeaconBlockDenebJson struct {
Slot string `json:"slot"`
ProposerIndex string `json:"proposer_index"`
ParentRoot string `json:"parent_root" hex:"true"`
StateRoot string `json:"state_root" hex:"true"`
Body *BlindedBeaconBlockBodyDenebJson `json:"body"`
}
type BeaconBlockBodyAltairJson struct { type BeaconBlockBodyAltairJson struct {
RandaoReveal string `json:"randao_reveal" hex:"true"` RandaoReveal string `json:"randao_reveal" hex:"true"`
Eth1Data *Eth1DataJson `json:"eth1_data"` Eth1Data *Eth1DataJson `json:"eth1_data"`
@@ -524,6 +554,21 @@ type BeaconBlockBodyCapellaJson struct {
BLSToExecutionChanges []*SignedBLSToExecutionChangeJson `json:"bls_to_execution_changes"` BLSToExecutionChanges []*SignedBLSToExecutionChangeJson `json:"bls_to_execution_changes"`
} }
type BeaconBlockBodyDenebJson struct {
RandaoReveal string `json:"randao_reveal" hex:"true"`
Eth1Data *Eth1DataJson `json:"eth1_data"`
Graffiti string `json:"graffiti" hex:"true"`
ProposerSlashings []*ProposerSlashingJson `json:"proposer_slashings"`
AttesterSlashings []*AttesterSlashingJson `json:"attester_slashings"`
Attestations []*AttestationJson `json:"attestations"`
Deposits []*DepositJson `json:"deposits"`
VoluntaryExits []*SignedVoluntaryExitJson `json:"voluntary_exits"`
SyncAggregate *SyncAggregateJson `json:"sync_aggregate"`
ExecutionPayload *ExecutionPayloadDenebJson `json:"execution_payload"`
BLSToExecutionChanges []*SignedBLSToExecutionChangeJson `json:"bls_to_execution_changes"`
BlobKzgCommitments []string `json:"blob_kzg_commitments" hex:"true"`
}
type BlindedBeaconBlockBodyBellatrixJson struct { type BlindedBeaconBlockBodyBellatrixJson struct {
RandaoReveal string `json:"randao_reveal" hex:"true"` RandaoReveal string `json:"randao_reveal" hex:"true"`
Eth1Data *Eth1DataJson `json:"eth1_data"` Eth1Data *Eth1DataJson `json:"eth1_data"`
@@ -551,6 +596,21 @@ type BlindedBeaconBlockBodyCapellaJson struct {
BLSToExecutionChanges []*SignedBLSToExecutionChangeJson `json:"bls_to_execution_changes"` BLSToExecutionChanges []*SignedBLSToExecutionChangeJson `json:"bls_to_execution_changes"`
} }
type BlindedBeaconBlockBodyDenebJson struct {
RandaoReveal string `json:"randao_reveal" hex:"true"`
Eth1Data *Eth1DataJson `json:"eth1_data"`
Graffiti string `json:"graffiti" hex:"true"`
ProposerSlashings []*ProposerSlashingJson `json:"proposer_slashings"`
AttesterSlashings []*AttesterSlashingJson `json:"attester_slashings"`
Attestations []*AttestationJson `json:"attestations"`
Deposits []*DepositJson `json:"deposits"`
VoluntaryExits []*SignedVoluntaryExitJson `json:"voluntary_exits"`
SyncAggregate *SyncAggregateJson `json:"sync_aggregate"`
ExecutionPayloadHeader *ExecutionPayloadHeaderDenebJson `json:"execution_payload_header"`
BLSToExecutionChanges []*SignedBLSToExecutionChangeJson `json:"bls_to_execution_changes"`
BlobKzgCommitments []string `json:"blob_kzg_commitments" hex:"true"`
}
type ExecutionPayloadJson struct { type ExecutionPayloadJson struct {
ParentHash string `json:"parent_hash" hex:"true"` ParentHash string `json:"parent_hash" hex:"true"`
FeeRecipient string `json:"fee_recipient" hex:"true"` FeeRecipient string `json:"fee_recipient" hex:"true"`
@@ -586,6 +646,25 @@ type ExecutionPayloadCapellaJson struct {
Withdrawals []*WithdrawalJson `json:"withdrawals"` Withdrawals []*WithdrawalJson `json:"withdrawals"`
} }
type ExecutionPayloadDenebJson struct {
ParentHash string `json:"parent_hash" hex:"true"`
FeeRecipient string `json:"fee_recipient" hex:"true"`
StateRoot string `json:"state_root" hex:"true"`
ReceiptsRoot string `json:"receipts_root" hex:"true"`
LogsBloom string `json:"logs_bloom" hex:"true"`
PrevRandao string `json:"prev_randao" hex:"true"`
BlockNumber string `json:"block_number"`
GasLimit string `json:"gas_limit"`
GasUsed string `json:"gas_used"`
TimeStamp string `json:"timestamp"`
ExtraData string `json:"extra_data" hex:"true"`
BaseFeePerGas string `json:"base_fee_per_gas" uint256:"true"`
ExcessDataGas string `json:"excess_data_gas" uint256:"true"`
BlockHash string `json:"block_hash" hex:"true"`
Transactions []string `json:"transactions" hex:"true"`
Withdrawals []*WithdrawalJson `json:"withdrawals"`
}
type ExecutionPayloadHeaderJson struct { type ExecutionPayloadHeaderJson struct {
ParentHash string `json:"parent_hash" hex:"true"` ParentHash string `json:"parent_hash" hex:"true"`
FeeRecipient string `json:"fee_recipient" hex:"true"` FeeRecipient string `json:"fee_recipient" hex:"true"`
@@ -621,6 +700,25 @@ type ExecutionPayloadHeaderCapellaJson struct {
WithdrawalsRoot string `json:"withdrawals_root" hex:"true"` WithdrawalsRoot string `json:"withdrawals_root" hex:"true"`
} }
type ExecutionPayloadHeaderDenebJson struct {
ParentHash string `json:"parent_hash" hex:"true"`
FeeRecipient string `json:"fee_recipient" hex:"true"`
StateRoot string `json:"state_root" hex:"true"`
ReceiptsRoot string `json:"receipts_root" hex:"true"`
LogsBloom string `json:"logs_bloom" hex:"true"`
PrevRandao string `json:"prev_randao" hex:"true"`
BlockNumber string `json:"block_number"`
GasLimit string `json:"gas_limit"`
GasUsed string `json:"gas_used"`
TimeStamp string `json:"timestamp"`
ExtraData string `json:"extra_data" hex:"true"`
BaseFeePerGas string `json:"base_fee_per_gas" uint256:"true"`
ExcessDataGas string `json:"excess_data_gas" uint256:"true"`
BlockHash string `json:"block_hash" hex:"true"`
TransactionsRoot string `json:"transactions_root" hex:"true"`
WithdrawalsRoot string `json:"withdrawals_root" hex:"true"`
}
type SyncAggregateJson struct { type SyncAggregateJson struct {
SyncCommitteeBits string `json:"sync_committee_bits" hex:"true"` SyncCommitteeBits string `json:"sync_committee_bits" hex:"true"`
SyncCommitteeSignature string `json:"sync_committee_signature" hex:"true"` SyncCommitteeSignature string `json:"sync_committee_signature" hex:"true"`
@@ -877,11 +975,42 @@ type BeaconStateCapellaJson struct {
HistoricalSummaries []*HistoricalSummaryJson `json:"historical_summaries"` HistoricalSummaries []*HistoricalSummaryJson `json:"historical_summaries"`
} }
type BeaconStateDenebJson struct {
GenesisTime string `json:"genesis_time"`
GenesisValidatorsRoot string `json:"genesis_validators_root" hex:"true"`
Slot string `json:"slot"`
Fork *ForkJson `json:"fork"`
LatestBlockHeader *BeaconBlockHeaderJson `json:"latest_block_header"`
BlockRoots []string `json:"block_roots" hex:"true"`
StateRoots []string `json:"state_roots" hex:"true"`
HistoricalRoots []string `json:"historical_roots" hex:"true"`
Eth1Data *Eth1DataJson `json:"eth1_data"`
Eth1DataVotes []*Eth1DataJson `json:"eth1_data_votes"`
Eth1DepositIndex string `json:"eth1_deposit_index"`
Validators []*ValidatorJson `json:"validators"`
Balances []string `json:"balances"`
RandaoMixes []string `json:"randao_mixes" hex:"true"`
Slashings []string `json:"slashings"`
PreviousEpochParticipation EpochParticipation `json:"previous_epoch_participation"`
CurrentEpochParticipation EpochParticipation `json:"current_epoch_participation"`
JustificationBits string `json:"justification_bits" hex:"true"`
PreviousJustifiedCheckpoint *CheckpointJson `json:"previous_justified_checkpoint"`
CurrentJustifiedCheckpoint *CheckpointJson `json:"current_justified_checkpoint"`
FinalizedCheckpoint *CheckpointJson `json:"finalized_checkpoint"`
InactivityScores []string `json:"inactivity_scores"`
CurrentSyncCommittee *SyncCommitteeJson `json:"current_sync_committee"`
NextSyncCommittee *SyncCommitteeJson `json:"next_sync_committee"`
LatestExecutionPayloadHeader *ExecutionPayloadHeaderDenebJson `json:"latest_execution_payload_header"`
NextWithdrawalIndex string `json:"next_withdrawal_index"`
NextWithdrawalValidatorIndex string `json:"next_withdrawal_validator_index"`
}
type BeaconStateContainerV2Json struct { type BeaconStateContainerV2Json struct {
Phase0State *BeaconStateJson `json:"phase0_state"` Phase0State *BeaconStateJson `json:"phase0_state"`
AltairState *BeaconStateAltairJson `json:"altair_state"` AltairState *BeaconStateAltairJson `json:"altair_state"`
BellatrixState *BeaconStateBellatrixJson `json:"bellatrix_state"` BellatrixState *BeaconStateBellatrixJson `json:"bellatrix_state"`
CapellaState *BeaconStateCapellaJson `json:"capella_state"` CapellaState *BeaconStateCapellaJson `json:"capella_state"`
DenebState *BeaconStateDenebJson `json:"deneb_state"`
} }
type ForkJson struct { type ForkJson struct {

View File

@@ -34,8 +34,8 @@ go_library(
"//beacon-chain/operations/voluntaryexits:go_default_library", "//beacon-chain/operations/voluntaryexits:go_default_library",
"//beacon-chain/p2p:go_default_library", "//beacon-chain/p2p:go_default_library",
"//beacon-chain/rpc/eth/helpers:go_default_library", "//beacon-chain/rpc/eth/helpers:go_default_library",
"//beacon-chain/rpc/lookup:go_default_library",
"//beacon-chain/rpc/prysm/v1alpha1/validator:go_default_library", "//beacon-chain/rpc/prysm/v1alpha1/validator:go_default_library",
"//beacon-chain/rpc/statefetcher:go_default_library",
"//beacon-chain/state:go_default_library", "//beacon-chain/state:go_default_library",
"//beacon-chain/state/state-native:go_default_library", "//beacon-chain/state/state-native:go_default_library",
"//beacon-chain/state/stategen:go_default_library", "//beacon-chain/state/stategen:go_default_library",
@@ -92,7 +92,6 @@ go_test(
"//beacon-chain/core/transition:go_default_library", "//beacon-chain/core/transition:go_default_library",
"//beacon-chain/db:go_default_library", "//beacon-chain/db:go_default_library",
"//beacon-chain/db/testing:go_default_library", "//beacon-chain/db/testing:go_default_library",
"//beacon-chain/execution/testing:go_default_library",
"//beacon-chain/operations/attestations:go_default_library", "//beacon-chain/operations/attestations:go_default_library",
"//beacon-chain/operations/blstoexec:go_default_library", "//beacon-chain/operations/blstoexec:go_default_library",
"//beacon-chain/operations/blstoexec/mock:go_default_library", "//beacon-chain/operations/blstoexec/mock:go_default_library",
@@ -101,12 +100,11 @@ go_test(
"//beacon-chain/operations/voluntaryexits/mock:go_default_library", "//beacon-chain/operations/voluntaryexits/mock:go_default_library",
"//beacon-chain/p2p/testing:go_default_library", "//beacon-chain/p2p/testing:go_default_library",
"//beacon-chain/rpc/eth/helpers:go_default_library", "//beacon-chain/rpc/eth/helpers:go_default_library",
"//beacon-chain/rpc/lookup:go_default_library",
"//beacon-chain/rpc/prysm/v1alpha1/validator:go_default_library", "//beacon-chain/rpc/prysm/v1alpha1/validator:go_default_library",
"//beacon-chain/rpc/statefetcher:go_default_library",
"//beacon-chain/rpc/testutil:go_default_library", "//beacon-chain/rpc/testutil:go_default_library",
"//beacon-chain/state:go_default_library", "//beacon-chain/state:go_default_library",
"//beacon-chain/state/state-native:go_default_library", "//beacon-chain/state/state-native:go_default_library",
"//config/features:go_default_library",
"//config/params:go_default_library", "//config/params:go_default_library",
"//consensus-types/blocks:go_default_library", "//consensus-types/blocks:go_default_library",
"//consensus-types/interfaces:go_default_library", "//consensus-types/interfaces:go_default_library",

View File

@@ -25,7 +25,7 @@ func (bs *Server) GetBlindedBlock(ctx context.Context, req *ethpbv1.BlockRequest
ctx, span := trace.StartSpan(ctx, "beacon.GetBlindedBlock") ctx, span := trace.StartSpan(ctx, "beacon.GetBlindedBlock")
defer span.End() defer span.End()
blk, err := bs.blockFromBlockID(ctx, req.BlockId) blk, err := bs.Blocker.Block(ctx, req.BlockId)
err = handleGetBlockError(blk, err) err = handleGetBlockError(blk, err)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -80,7 +80,7 @@ func (bs *Server) GetBlindedBlockSSZ(ctx context.Context, req *ethpbv1.BlockRequ
ctx, span := trace.StartSpan(ctx, "beacon.GetBlindedBlockSSZ") ctx, span := trace.StartSpan(ctx, "beacon.GetBlindedBlockSSZ")
defer span.End() defer span.End()
blk, err := bs.blockFromBlockID(ctx, req.BlockId) blk, err := bs.Blocker.Block(ctx, req.BlockId)
err = handleGetBlockError(blk, err) err = handleGetBlockError(blk, err)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -2,17 +2,15 @@ package beacon
import ( import (
"context" "context"
"fmt"
"reflect"
"testing" "testing"
mock "github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain/testing" mock "github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain/testing"
builderTest "github.com/prysmaticlabs/prysm/v4/beacon-chain/builder/testing" builderTest "github.com/prysmaticlabs/prysm/v4/beacon-chain/builder/testing"
dbTest "github.com/prysmaticlabs/prysm/v4/beacon-chain/db/testing" dbTest "github.com/prysmaticlabs/prysm/v4/beacon-chain/db/testing"
executionTest "github.com/prysmaticlabs/prysm/v4/beacon-chain/execution/testing"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/operations/synccommittee" "github.com/prysmaticlabs/prysm/v4/beacon-chain/operations/synccommittee"
mockp2p "github.com/prysmaticlabs/prysm/v4/beacon-chain/p2p/testing" mockp2p "github.com/prysmaticlabs/prysm/v4/beacon-chain/p2p/testing"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/prysm/v1alpha1/validator" "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/prysm/v1alpha1/validator"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/testutil"
"github.com/prysmaticlabs/prysm/v4/config/params" "github.com/prysmaticlabs/prysm/v4/config/params"
"github.com/prysmaticlabs/prysm/v4/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v4/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
@@ -21,7 +19,6 @@ import (
ethpbv1 "github.com/prysmaticlabs/prysm/v4/proto/eth/v1" ethpbv1 "github.com/prysmaticlabs/prysm/v4/proto/eth/v1"
ethpbv2 "github.com/prysmaticlabs/prysm/v4/proto/eth/v2" ethpbv2 "github.com/prysmaticlabs/prysm/v4/proto/eth/v2"
"github.com/prysmaticlabs/prysm/v4/proto/migration" "github.com/prysmaticlabs/prysm/v4/proto/migration"
ethpbalpha "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v4/testing/assert" "github.com/prysmaticlabs/prysm/v4/testing/assert"
"github.com/prysmaticlabs/prysm/v4/testing/require" "github.com/prysmaticlabs/prysm/v4/testing/require"
"github.com/prysmaticlabs/prysm/v4/testing/util" "github.com/prysmaticlabs/prysm/v4/testing/util"
@@ -29,774 +26,284 @@ import (
) )
func TestServer_GetBlindedBlock(t *testing.T) { func TestServer_GetBlindedBlock(t *testing.T) {
ctx := context.Background()
t.Run("Phase 0", func(t *testing.T) { t.Run("Phase 0", func(t *testing.T) {
beaconDB := dbTest.SetupDB(t) b := util.NewBeaconBlock()
ctx := context.Background() blk, err := blocks.NewSignedBeaconBlock(b)
genBlk, blkContainers := fillDBTestBlocks(ctx, t, beaconDB)
canonicalRoots := make(map[[32]byte]bool)
for _, bContr := range blkContainers {
canonicalRoots[bytesutil.ToBytes32(bContr.BlockRoot)] = true
}
headBlock := blkContainers[len(blkContainers)-1]
nextSlot := headBlock.GetPhase0Block().Block.Slot + 1
wsb, err := blocks.NewSignedBeaconBlock(headBlock.Block.(*ethpbalpha.BeaconBlockContainer_Phase0Block).Phase0Block)
require.NoError(t, err) require.NoError(t, err)
mockChainService := &mock.ChainService{
DB: beaconDB,
Block: wsb,
Root: headBlock.BlockRoot,
FinalizedCheckPoint: &ethpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
CanonicalRoots: canonicalRoots,
FinalizedRoots: map[[32]byte]bool{},
}
bs := &Server{ bs := &Server{
BeaconDB: beaconDB, FinalizationFetcher: &mock.ChainService{},
ChainInfoFetcher: mockChainService, Blocker: &testutil.MockBlocker{BlockToReturn: blk},
HeadFetcher: mockChainService,
OptimisticModeFetcher: mockChainService,
FinalizationFetcher: mockChainService,
} }
root, err := genBlk.Block.HashTreeRoot() expected, err := migration.V1Alpha1ToV1SignedBlock(b)
require.NoError(t, err) require.NoError(t, err)
resp, err := bs.GetBlindedBlock(ctx, &ethpbv1.BlockRequest{})
tests := []struct { require.NoError(t, err)
name string phase0Block, ok := resp.Data.Message.(*ethpbv2.SignedBlindedBeaconBlockContainer_Phase0Block)
blockID []byte require.Equal(t, true, ok)
want *ethpbalpha.SignedBeaconBlock assert.DeepEqual(t, expected.Block, phase0Block.Phase0Block)
wantErr bool assert.Equal(t, ethpbv2.Version_PHASE0, resp.Version)
}{
{
name: "slot",
blockID: []byte("30"),
want: blkContainers[30].Block.(*ethpbalpha.BeaconBlockContainer_Phase0Block).Phase0Block,
},
{
name: "bad formatting",
blockID: []byte("3bad0"),
wantErr: true,
},
{
name: "canonical",
blockID: []byte("30"),
want: blkContainers[30].Block.(*ethpbalpha.BeaconBlockContainer_Phase0Block).Phase0Block,
},
{
name: "non canonical",
blockID: []byte(fmt.Sprintf("%d", nextSlot)),
wantErr: true,
},
{
name: "head",
blockID: []byte("head"),
want: headBlock.Block.(*ethpbalpha.BeaconBlockContainer_Phase0Block).Phase0Block,
},
{
name: "finalized",
blockID: []byte("finalized"),
want: blkContainers[64].Block.(*ethpbalpha.BeaconBlockContainer_Phase0Block).Phase0Block,
},
{
name: "genesis",
blockID: []byte("genesis"),
want: genBlk,
},
{
name: "genesis root",
blockID: root[:],
want: genBlk,
},
{
name: "root",
blockID: blkContainers[20].BlockRoot,
want: blkContainers[20].Block.(*ethpbalpha.BeaconBlockContainer_Phase0Block).Phase0Block,
},
{
name: "non-existent root",
blockID: bytesutil.PadTo([]byte("hi there"), 32),
wantErr: true,
},
{
name: "no block",
blockID: []byte("105"),
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
blk, err := bs.GetBlindedBlock(ctx, &ethpbv1.BlockRequest{
BlockId: tt.blockID,
})
if tt.wantErr {
require.NotEqual(t, err, nil)
return
}
require.NoError(t, err)
v1Block, err := migration.V1Alpha1ToV1SignedBlock(tt.want)
require.NoError(t, err)
phase0Block, ok := blk.Data.Message.(*ethpbv2.SignedBlindedBeaconBlockContainer_Phase0Block)
require.Equal(t, true, ok)
if !reflect.DeepEqual(phase0Block.Phase0Block, v1Block.Block) {
t.Error("Expected blocks to equal")
}
assert.Equal(t, ethpbv2.Version_PHASE0, blk.Version)
})
}
}) })
t.Run("Altair", func(t *testing.T) { t.Run("Altair", func(t *testing.T) {
beaconDB := dbTest.SetupDB(t) b := util.NewBeaconBlockAltair()
ctx := context.Background() blk, err := blocks.NewSignedBeaconBlock(b)
genBlk, blkContainers := fillDBTestBlocksAltair(ctx, t, beaconDB)
canonicalRoots := make(map[[32]byte]bool)
for _, bContr := range blkContainers {
canonicalRoots[bytesutil.ToBytes32(bContr.BlockRoot)] = true
}
headBlock := blkContainers[len(blkContainers)-1]
nextSlot := headBlock.GetAltairBlock().Block.Slot + 1
chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetAltairBlock())
require.NoError(t, err) require.NoError(t, err)
mockChainService := &mock.ChainService{
DB: beaconDB,
Block: chainBlk,
Root: headBlock.BlockRoot,
FinalizedCheckPoint: &ethpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
CanonicalRoots: canonicalRoots,
FinalizedRoots: map[[32]byte]bool{},
}
bs := &Server{ bs := &Server{
BeaconDB: beaconDB, FinalizationFetcher: &mock.ChainService{},
ChainInfoFetcher: mockChainService, Blocker: &testutil.MockBlocker{BlockToReturn: blk},
HeadFetcher: mockChainService,
OptimisticModeFetcher: mockChainService,
FinalizationFetcher: mockChainService,
} }
root, err := genBlk.Block.HashTreeRoot() expected, err := migration.V1Alpha1BeaconBlockAltairToV2(b.Block)
require.NoError(t, err) require.NoError(t, err)
resp, err := bs.GetBlindedBlock(ctx, &ethpbv1.BlockRequest{})
tests := []struct { require.NoError(t, err)
name string altairBlock, ok := resp.Data.Message.(*ethpbv2.SignedBlindedBeaconBlockContainer_AltairBlock)
blockID []byte require.Equal(t, true, ok)
want *ethpbalpha.SignedBeaconBlockAltair assert.DeepEqual(t, expected, altairBlock.AltairBlock)
wantErr bool assert.Equal(t, ethpbv2.Version_ALTAIR, resp.Version)
}{
{
name: "slot",
blockID: []byte("30"),
want: blkContainers[30].GetAltairBlock(),
},
{
name: "bad formatting",
blockID: []byte("3bad0"),
wantErr: true,
},
{
name: "canonical",
blockID: []byte("30"),
want: blkContainers[30].GetAltairBlock(),
},
{
name: "non canonical",
blockID: []byte(fmt.Sprintf("%d", nextSlot)),
wantErr: true,
},
{
name: "head",
blockID: []byte("head"),
want: headBlock.GetAltairBlock(),
},
{
name: "finalized",
blockID: []byte("finalized"),
want: blkContainers[64].GetAltairBlock(),
},
{
name: "genesis",
blockID: []byte("genesis"),
want: genBlk,
},
{
name: "genesis root",
blockID: root[:],
want: genBlk,
},
{
name: "root",
blockID: blkContainers[20].BlockRoot,
want: blkContainers[20].GetAltairBlock(),
},
{
name: "non-existent root",
blockID: bytesutil.PadTo([]byte("hi there"), 32),
wantErr: true,
},
{
name: "no block",
blockID: []byte("105"),
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
blk, err := bs.GetBlindedBlock(ctx, &ethpbv1.BlockRequest{
BlockId: tt.blockID,
})
if tt.wantErr {
require.NotEqual(t, err, nil)
return
}
require.NoError(t, err)
v2Block, err := migration.V1Alpha1BeaconBlockAltairToV2(tt.want.Block)
require.NoError(t, err)
altairBlock, ok := blk.Data.Message.(*ethpbv2.SignedBlindedBeaconBlockContainer_AltairBlock)
require.Equal(t, true, ok)
if !reflect.DeepEqual(altairBlock.AltairBlock, v2Block) {
t.Error("Expected blocks to equal")
}
assert.Equal(t, ethpbv2.Version_ALTAIR, blk.Version)
})
}
}) })
t.Run("Bellatrix", func(t *testing.T) { t.Run("Bellatrix", func(t *testing.T) {
beaconDB := dbTest.SetupDB(t) b := util.NewBlindedBeaconBlockBellatrix()
ctx := context.Background() blk, err := blocks.NewSignedBeaconBlock(b)
genBlk, blkContainers := fillDBTestBlocksBellatrixBlinded(ctx, t, beaconDB)
canonicalRoots := make(map[[32]byte]bool)
for _, bContr := range blkContainers {
canonicalRoots[bytesutil.ToBytes32(bContr.BlockRoot)] = true
}
headBlock := blkContainers[len(blkContainers)-1]
nextSlot := headBlock.GetBlindedBellatrixBlock().Block.Slot + 1
chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetBlindedBellatrixBlock())
require.NoError(t, err) require.NoError(t, err)
mockChainService := &mock.ChainService{
DB: beaconDB, mockChainService := &mock.ChainService{}
Block: chainBlk,
Root: headBlock.BlockRoot,
FinalizedCheckPoint: &ethpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
CanonicalRoots: canonicalRoots,
FinalizedRoots: map[[32]byte]bool{},
}
bs := &Server{ bs := &Server{
BeaconDB: beaconDB, FinalizationFetcher: mockChainService,
ChainInfoFetcher: mockChainService, Blocker: &testutil.MockBlocker{BlockToReturn: blk},
HeadFetcher: mockChainService,
OptimisticModeFetcher: mockChainService, OptimisticModeFetcher: mockChainService,
ExecutionPayloadReconstructor: &executionTest.EngineClient{
ExecutionPayloadByBlockHash: map[[32]byte]*enginev1.ExecutionPayload{},
},
FinalizationFetcher: mockChainService,
} }
root, err := genBlk.Block.HashTreeRoot() expected, err := migration.V1Alpha1BeaconBlockBlindedBellatrixToV2Blinded(b.Block)
require.NoError(t, err) require.NoError(t, err)
resp, err := bs.GetBlindedBlock(ctx, &ethpbv1.BlockRequest{})
tests := []struct { require.NoError(t, err)
name string bellatrixBlock, ok := resp.Data.Message.(*ethpbv2.SignedBlindedBeaconBlockContainer_BellatrixBlock)
blockID []byte require.Equal(t, true, ok)
want *ethpbalpha.SignedBlindedBeaconBlockBellatrix assert.DeepEqual(t, expected, bellatrixBlock.BellatrixBlock)
wantErr bool assert.Equal(t, ethpbv2.Version_BELLATRIX, resp.Version)
}{
{
name: "slot",
blockID: []byte("30"),
want: blkContainers[30].GetBlindedBellatrixBlock(),
},
{
name: "bad formatting",
blockID: []byte("3bad0"),
wantErr: true,
},
{
name: "canonical",
blockID: []byte("30"),
want: blkContainers[30].GetBlindedBellatrixBlock(),
},
{
name: "non canonical",
blockID: []byte(fmt.Sprintf("%d", nextSlot)),
wantErr: true,
},
{
name: "head",
blockID: []byte("head"),
want: headBlock.GetBlindedBellatrixBlock(),
},
{
name: "finalized",
blockID: []byte("finalized"),
want: blkContainers[64].GetBlindedBellatrixBlock(),
},
{
name: "genesis",
blockID: []byte("genesis"),
want: genBlk,
},
{
name: "genesis root",
blockID: root[:],
want: genBlk,
},
{
name: "root",
blockID: blkContainers[20].BlockRoot,
want: blkContainers[20].GetBlindedBellatrixBlock(),
},
{
name: "non-existent root",
blockID: bytesutil.PadTo([]byte("hi there"), 32),
wantErr: true,
},
{
name: "no block",
blockID: []byte("105"),
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
blk, err := bs.GetBlindedBlock(ctx, &ethpbv1.BlockRequest{
BlockId: tt.blockID,
})
if tt.wantErr {
require.NotEqual(t, err, nil)
return
}
require.NoError(t, err)
v2Block, err := migration.V1Alpha1BeaconBlockBlindedBellatrixToV2Blinded(tt.want.Block)
require.NoError(t, err)
b, ok := blk.Data.Message.(*ethpbv2.SignedBlindedBeaconBlockContainer_BellatrixBlock)
require.Equal(t, true, ok)
if !reflect.DeepEqual(b.BellatrixBlock, v2Block) {
t.Error("Expected blocks to equal")
}
assert.Equal(t, ethpbv2.Version_BELLATRIX, blk.Version)
})
}
}) })
t.Run("Capella", func(t *testing.T) { t.Run("Capella", func(t *testing.T) {
beaconDB := dbTest.SetupDB(t) b := util.NewBlindedBeaconBlockCapella()
ctx := context.Background() blk, err := blocks.NewSignedBeaconBlock(b)
genBlk, blkContainers := fillDBTestBlocksCapellaBlinded(ctx, t, beaconDB)
canonicalRoots := make(map[[32]byte]bool)
for _, bContr := range blkContainers {
canonicalRoots[bytesutil.ToBytes32(bContr.BlockRoot)] = true
}
headBlock := blkContainers[len(blkContainers)-1]
nextSlot := headBlock.GetBlindedCapellaBlock().Block.Slot + 1
chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetBlindedCapellaBlock())
require.NoError(t, err) require.NoError(t, err)
mockChainService := &mock.ChainService{
DB: beaconDB, mockChainService := &mock.ChainService{}
Block: chainBlk,
Root: headBlock.BlockRoot,
FinalizedCheckPoint: &ethpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
CanonicalRoots: canonicalRoots,
FinalizedRoots: map[[32]byte]bool{},
}
bs := &Server{ bs := &Server{
BeaconDB: beaconDB, FinalizationFetcher: mockChainService,
ChainInfoFetcher: mockChainService, Blocker: &testutil.MockBlocker{BlockToReturn: blk},
HeadFetcher: mockChainService,
OptimisticModeFetcher: mockChainService, OptimisticModeFetcher: mockChainService,
ExecutionPayloadReconstructor: &executionTest.EngineClient{
ExecutionPayloadByBlockHash: map[[32]byte]*enginev1.ExecutionPayload{},
},
FinalizationFetcher: mockChainService,
} }
root, err := genBlk.Block.HashTreeRoot() expected, err := migration.V1Alpha1BeaconBlockBlindedCapellaToV2Blinded(b.Block)
require.NoError(t, err) require.NoError(t, err)
resp, err := bs.GetBlindedBlock(ctx, &ethpbv1.BlockRequest{})
tests := []struct { require.NoError(t, err)
name string capellaBlock, ok := resp.Data.Message.(*ethpbv2.SignedBlindedBeaconBlockContainer_CapellaBlock)
blockID []byte require.Equal(t, true, ok)
want *ethpbalpha.SignedBlindedBeaconBlockCapella assert.DeepEqual(t, expected, capellaBlock.CapellaBlock)
wantErr bool assert.Equal(t, ethpbv2.Version_CAPELLA, resp.Version)
}{
{
name: "slot",
blockID: []byte("30"),
want: blkContainers[30].GetBlindedCapellaBlock(),
},
{
name: "bad formatting",
blockID: []byte("3bad0"),
wantErr: true,
},
{
name: "canonical",
blockID: []byte("30"),
want: blkContainers[30].GetBlindedCapellaBlock(),
},
{
name: "non canonical",
blockID: []byte(fmt.Sprintf("%d", nextSlot)),
wantErr: true,
},
{
name: "head",
blockID: []byte("head"),
want: headBlock.GetBlindedCapellaBlock(),
},
{
name: "finalized",
blockID: []byte("finalized"),
want: blkContainers[64].GetBlindedCapellaBlock(),
},
{
name: "genesis",
blockID: []byte("genesis"),
want: genBlk,
},
{
name: "genesis root",
blockID: root[:],
want: genBlk,
},
{
name: "root",
blockID: blkContainers[20].BlockRoot,
want: blkContainers[20].GetBlindedCapellaBlock(),
},
{
name: "non-existent root",
blockID: bytesutil.PadTo([]byte("hi there"), 32),
wantErr: true,
},
{
name: "no block",
blockID: []byte("105"),
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
blk, err := bs.GetBlindedBlock(ctx, &ethpbv1.BlockRequest{
BlockId: tt.blockID,
})
if tt.wantErr {
require.NotEqual(t, err, nil)
return
}
require.NoError(t, err)
v2Block, err := migration.V1Alpha1BeaconBlockBlindedCapellaToV2Blinded(tt.want.Block)
require.NoError(t, err)
b, ok := blk.Data.Message.(*ethpbv2.SignedBlindedBeaconBlockContainer_CapellaBlock)
require.Equal(t, true, ok)
if !reflect.DeepEqual(b.CapellaBlock, v2Block) {
t.Error("Expected blocks to equal")
}
assert.Equal(t, ethpbv2.Version_CAPELLA, blk.Version)
})
}
}) })
t.Run("execution optimistic", func(t *testing.T) { t.Run("execution optimistic", func(t *testing.T) {
beaconDB := dbTest.SetupDB(t) b := util.NewBlindedBeaconBlockBellatrix()
ctx := context.Background() blk, err := blocks.NewSignedBeaconBlock(b)
_, blkContainers := fillDBTestBlocksBellatrix(ctx, t, beaconDB)
headBlock := blkContainers[len(blkContainers)-1]
chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetBellatrixBlock())
require.NoError(t, err) require.NoError(t, err)
r, err := blk.Block().HashTreeRoot()
require.NoError(t, err)
mockChainService := &mock.ChainService{ mockChainService := &mock.ChainService{
DB: beaconDB, OptimisticRoots: map[[32]byte]bool{r: true},
Block: chainBlk,
Root: headBlock.BlockRoot,
FinalizedCheckPoint: &ethpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
FinalizedRoots: map[[32]byte]bool{},
OptimisticRoots: map[[32]byte]bool{
bytesutil.ToBytes32(headBlock.BlockRoot): true,
},
} }
bs := &Server{ bs := &Server{
BeaconDB: beaconDB,
ChainInfoFetcher: mockChainService,
HeadFetcher: mockChainService,
OptimisticModeFetcher: mockChainService,
FinalizationFetcher: mockChainService, FinalizationFetcher: mockChainService,
Blocker: &testutil.MockBlocker{BlockToReturn: blk},
OptimisticModeFetcher: mockChainService,
} }
blk, err := bs.GetBlindedBlock(ctx, &ethpbv1.BlockRequest{ resp, err := bs.GetBlindedBlock(ctx, &ethpbv1.BlockRequest{})
BlockId: []byte("head"),
})
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, true, blk.ExecutionOptimistic) assert.Equal(t, true, resp.ExecutionOptimistic)
}) })
t.Run("finalized", func(t *testing.T) { t.Run("finalized", func(t *testing.T) {
beaconDB := dbTest.SetupDB(t) b := util.NewBeaconBlock()
ctx := context.Background() blk, err := blocks.NewSignedBeaconBlock(b)
_, blkContainers := fillDBTestBlocks(ctx, t, beaconDB)
headBlock := blkContainers[len(blkContainers)-1]
chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetPhase0Block())
require.NoError(t, err) require.NoError(t, err)
root, err := blk.Block().HashTreeRoot()
require.NoError(t, err)
mockChainService := &mock.ChainService{ mockChainService := &mock.ChainService{
DB: beaconDB, FinalizedRoots: map[[32]byte]bool{root: true},
Block: chainBlk,
Root: headBlock.BlockRoot,
FinalizedCheckPoint: &ethpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
Optimistic: true,
FinalizedRoots: map[[32]byte]bool{
bytesutil.ToBytes32(blkContainers[32].BlockRoot): true,
bytesutil.ToBytes32(blkContainers[64].BlockRoot): false,
},
} }
bs := &Server{ bs := &Server{
BeaconDB: beaconDB, FinalizationFetcher: mockChainService,
ChainInfoFetcher: mockChainService, Blocker: &testutil.MockBlocker{BlockToReturn: blk},
HeadFetcher: mockChainService,
OptimisticModeFetcher: mockChainService,
FinalizationFetcher: mockChainService,
} }
t.Run("true", func(t *testing.T) { resp, err := bs.GetBlindedBlock(ctx, &ethpbv1.BlockRequest{BlockId: root[:]})
blk, err := bs.GetBlindedBlock(ctx, &ethpbv1.BlockRequest{ require.NoError(t, err)
BlockId: []byte("32"), assert.Equal(t, true, resp.Finalized)
}) })
require.NoError(t, err) t.Run("not finalized", func(t *testing.T) {
assert.Equal(t, true, blk.Finalized) b := util.NewBeaconBlock()
}) blk, err := blocks.NewSignedBeaconBlock(b)
t.Run("false", func(t *testing.T) { require.NoError(t, err)
blk, err := bs.GetBlindedBlock(ctx, &ethpbv1.BlockRequest{ root, err := blk.Block().HashTreeRoot()
BlockId: []byte("64"), require.NoError(t, err)
})
require.NoError(t, err) mockChainService := &mock.ChainService{
assert.Equal(t, false, blk.Finalized) FinalizedRoots: map[[32]byte]bool{root: false},
}) }
bs := &Server{
FinalizationFetcher: mockChainService,
Blocker: &testutil.MockBlocker{BlockToReturn: blk},
}
resp, err := bs.GetBlindedBlock(ctx, &ethpbv1.BlockRequest{BlockId: root[:]})
require.NoError(t, err)
assert.Equal(t, false, resp.Finalized)
}) })
} }
func TestServer_GetBlindedBlockSSZ(t *testing.T) { func TestServer_GetBlindedBlockSSZ(t *testing.T) {
ctx := context.Background()
t.Run("Phase 0", func(t *testing.T) { t.Run("Phase 0", func(t *testing.T) {
beaconDB := dbTest.SetupDB(t) b := util.NewBeaconBlock()
ctx := context.Background() blk, err := blocks.NewSignedBeaconBlock(b)
_, blkContainers := fillDBTestBlocks(ctx, t, beaconDB)
headBlock := blkContainers[len(blkContainers)-1]
wsb, err := blocks.NewSignedBeaconBlock(headBlock.Block.(*ethpbalpha.BeaconBlockContainer_Phase0Block).Phase0Block)
require.NoError(t, err) require.NoError(t, err)
mockChainService := &mock.ChainService{
DB: beaconDB,
Block: wsb,
Root: headBlock.BlockRoot,
FinalizedCheckPoint: &ethpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
FinalizedRoots: map[[32]byte]bool{},
}
bs := &Server{ bs := &Server{
BeaconDB: beaconDB, FinalizationFetcher: &mock.ChainService{},
ChainInfoFetcher: mockChainService, Blocker: &testutil.MockBlocker{BlockToReturn: blk},
FinalizationFetcher: mockChainService,
} }
blks, err := beaconDB.BlocksBySlot(ctx, 30) expected, err := blk.MarshalSSZ()
require.Equal(t, true, len(blks) > 0)
require.NoError(t, err) require.NoError(t, err)
sszBlock, err := blks[0].MarshalSSZ() resp, err := bs.GetBlindedBlockSSZ(ctx, &ethpbv1.BlockRequest{})
require.NoError(t, err)
resp, err := bs.GetBlindedBlockSSZ(ctx, &ethpbv1.BlockRequest{BlockId: []byte("30")})
require.NoError(t, err) require.NoError(t, err)
assert.NotNil(t, resp) assert.NotNil(t, resp)
assert.DeepEqual(t, sszBlock, resp.Data) assert.DeepEqual(t, expected, resp.Data)
assert.Equal(t, ethpbv2.Version_PHASE0, resp.Version) assert.Equal(t, ethpbv2.Version_PHASE0, resp.Version)
}) })
t.Run("Altair", func(t *testing.T) { t.Run("Altair", func(t *testing.T) {
beaconDB := dbTest.SetupDB(t) b := util.NewBeaconBlockAltair()
ctx := context.Background() blk, err := blocks.NewSignedBeaconBlock(b)
_, blkContainers := fillDBTestBlocksAltair(ctx, t, beaconDB)
headBlock := blkContainers[len(blkContainers)-1]
chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetAltairBlock())
require.NoError(t, err) require.NoError(t, err)
mockChainService := &mock.ChainService{
DB: beaconDB,
Block: chainBlk,
Root: headBlock.BlockRoot,
FinalizedCheckPoint: &ethpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
FinalizedRoots: map[[32]byte]bool{},
}
bs := &Server{ bs := &Server{
BeaconDB: beaconDB, FinalizationFetcher: &mock.ChainService{},
ChainInfoFetcher: mockChainService, Blocker: &testutil.MockBlocker{BlockToReturn: blk},
FinalizationFetcher: mockChainService,
} }
blks, err := beaconDB.BlocksBySlot(ctx, 30) expected, err := blk.MarshalSSZ()
require.Equal(t, true, len(blks) > 0)
require.NoError(t, err) require.NoError(t, err)
sszBlock, err := blks[0].MarshalSSZ() resp, err := bs.GetBlindedBlockSSZ(ctx, &ethpbv1.BlockRequest{})
require.NoError(t, err)
resp, err := bs.GetBlindedBlockSSZ(ctx, &ethpbv1.BlockRequest{BlockId: []byte("30")})
require.NoError(t, err) require.NoError(t, err)
assert.NotNil(t, resp) assert.NotNil(t, resp)
assert.DeepEqual(t, sszBlock, resp.Data) assert.DeepEqual(t, expected, resp.Data)
assert.Equal(t, ethpbv2.Version_ALTAIR, resp.Version) assert.Equal(t, ethpbv2.Version_ALTAIR, resp.Version)
}) })
t.Run("Bellatrix", func(t *testing.T) { t.Run("Bellatrix", func(t *testing.T) {
beaconDB := dbTest.SetupDB(t) b := util.NewBlindedBeaconBlockBellatrix()
ctx := context.Background() blk, err := blocks.NewSignedBeaconBlock(b)
_, blkContainers := fillDBTestBlocksBellatrixBlinded(ctx, t, beaconDB)
headBlock := blkContainers[len(blkContainers)-1]
chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetBlindedBellatrixBlock())
require.NoError(t, err) require.NoError(t, err)
mockChainService := &mock.ChainService{
DB: beaconDB, mockChainService := &mock.ChainService{}
Block: chainBlk,
Root: headBlock.BlockRoot,
FinalizedCheckPoint: &ethpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
FinalizedRoots: map[[32]byte]bool{},
}
bs := &Server{ bs := &Server{
BeaconDB: beaconDB,
ChainInfoFetcher: mockChainService,
OptimisticModeFetcher: mockChainService,
FinalizationFetcher: mockChainService, FinalizationFetcher: mockChainService,
Blocker: &testutil.MockBlocker{BlockToReturn: blk},
OptimisticModeFetcher: mockChainService,
} }
blks, err := beaconDB.BlocksBySlot(ctx, 30) expected, err := blk.MarshalSSZ()
require.Equal(t, true, len(blks) > 0)
require.NoError(t, err) require.NoError(t, err)
sszBlock, err := blks[0].MarshalSSZ() resp, err := bs.GetBlindedBlockSSZ(ctx, &ethpbv1.BlockRequest{})
require.NoError(t, err)
resp, err := bs.GetBlindedBlockSSZ(ctx, &ethpbv1.BlockRequest{BlockId: []byte("30")})
require.NoError(t, err) require.NoError(t, err)
assert.NotNil(t, resp) assert.NotNil(t, resp)
assert.DeepEqual(t, sszBlock, resp.Data) assert.DeepEqual(t, expected, resp.Data)
assert.Equal(t, ethpbv2.Version_BELLATRIX, resp.Version) assert.Equal(t, ethpbv2.Version_BELLATRIX, resp.Version)
}) })
t.Run("Capella", func(t *testing.T) { t.Run("Capella", func(t *testing.T) {
beaconDB := dbTest.SetupDB(t) b := util.NewBlindedBeaconBlockCapella()
ctx := context.Background() blk, err := blocks.NewSignedBeaconBlock(b)
_, blkContainers := fillDBTestBlocksCapellaBlinded(ctx, t, beaconDB)
headBlock := blkContainers[len(blkContainers)-1]
chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetBlindedCapellaBlock())
require.NoError(t, err) require.NoError(t, err)
mockChainService := &mock.ChainService{
DB: beaconDB, mockChainService := &mock.ChainService{}
Block: chainBlk,
Root: headBlock.BlockRoot,
FinalizedCheckPoint: &ethpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
FinalizedRoots: map[[32]byte]bool{},
}
bs := &Server{ bs := &Server{
BeaconDB: beaconDB,
ChainInfoFetcher: mockChainService,
OptimisticModeFetcher: mockChainService,
FinalizationFetcher: mockChainService, FinalizationFetcher: mockChainService,
Blocker: &testutil.MockBlocker{BlockToReturn: blk},
OptimisticModeFetcher: mockChainService,
} }
blks, err := beaconDB.BlocksBySlot(ctx, 30) expected, err := blk.MarshalSSZ()
require.Equal(t, true, len(blks) > 0)
require.NoError(t, err) require.NoError(t, err)
sszBlock, err := blks[0].MarshalSSZ() resp, err := bs.GetBlindedBlockSSZ(ctx, &ethpbv1.BlockRequest{})
require.NoError(t, err)
resp, err := bs.GetBlindedBlockSSZ(ctx, &ethpbv1.BlockRequest{BlockId: []byte("30")})
require.NoError(t, err) require.NoError(t, err)
assert.NotNil(t, resp) assert.NotNil(t, resp)
assert.DeepEqual(t, sszBlock, resp.Data) assert.DeepEqual(t, expected, resp.Data)
assert.Equal(t, ethpbv2.Version_CAPELLA, resp.Version) assert.Equal(t, ethpbv2.Version_CAPELLA, resp.Version)
}) })
t.Run("execution optimistic", func(t *testing.T) { t.Run("execution optimistic", func(t *testing.T) {
beaconDB := dbTest.SetupDB(t) b := util.NewBlindedBeaconBlockBellatrix()
ctx := context.Background() blk, err := blocks.NewSignedBeaconBlock(b)
_, blkContainers := fillDBTestBlocksBellatrix(ctx, t, beaconDB)
headBlock := blkContainers[len(blkContainers)-1]
chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetBellatrixBlock())
require.NoError(t, err) require.NoError(t, err)
r, err := blk.Block().HashTreeRoot()
require.NoError(t, err)
mockChainService := &mock.ChainService{ mockChainService := &mock.ChainService{
DB: beaconDB, OptimisticRoots: map[[32]byte]bool{r: true},
Block: chainBlk,
Root: headBlock.BlockRoot,
FinalizedCheckPoint: &ethpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
FinalizedRoots: map[[32]byte]bool{},
OptimisticRoots: map[[32]byte]bool{
bytesutil.ToBytes32(headBlock.BlockRoot): true,
},
} }
bs := &Server{ bs := &Server{
BeaconDB: beaconDB,
ChainInfoFetcher: mockChainService,
HeadFetcher: mockChainService,
OptimisticModeFetcher: mockChainService,
FinalizationFetcher: mockChainService, FinalizationFetcher: mockChainService,
Blocker: &testutil.MockBlocker{BlockToReturn: blk},
OptimisticModeFetcher: mockChainService,
} }
blk, err := bs.GetBlindedBlockSSZ(ctx, &ethpbv1.BlockRequest{ resp, err := bs.GetBlindedBlockSSZ(ctx, &ethpbv1.BlockRequest{})
BlockId: []byte("head"),
})
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, true, blk.ExecutionOptimistic) assert.Equal(t, true, resp.ExecutionOptimistic)
}) })
t.Run("finalized", func(t *testing.T) { t.Run("finalized", func(t *testing.T) {
beaconDB := dbTest.SetupDB(t) b := util.NewBeaconBlock()
ctx := context.Background() blk, err := blocks.NewSignedBeaconBlock(b)
_, blkContainers := fillDBTestBlocks(ctx, t, beaconDB)
headBlock := blkContainers[len(blkContainers)-1]
chainBlk, err := blocks.NewSignedBeaconBlock(headBlock.GetPhase0Block())
require.NoError(t, err) require.NoError(t, err)
root, err := blk.Block().HashTreeRoot()
require.NoError(t, err)
mockChainService := &mock.ChainService{ mockChainService := &mock.ChainService{
DB: beaconDB, FinalizedRoots: map[[32]byte]bool{root: true},
Block: chainBlk,
Root: headBlock.BlockRoot,
FinalizedCheckPoint: &ethpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
Optimistic: true,
FinalizedRoots: map[[32]byte]bool{
bytesutil.ToBytes32(blkContainers[32].BlockRoot): true,
bytesutil.ToBytes32(blkContainers[64].BlockRoot): false,
},
} }
bs := &Server{ bs := &Server{
BeaconDB: beaconDB, FinalizationFetcher: mockChainService,
ChainInfoFetcher: mockChainService, Blocker: &testutil.MockBlocker{BlockToReturn: blk},
HeadFetcher: mockChainService,
OptimisticModeFetcher: mockChainService,
FinalizationFetcher: mockChainService,
} }
t.Run("true", func(t *testing.T) { resp, err := bs.GetBlindedBlockSSZ(ctx, &ethpbv1.BlockRequest{BlockId: root[:]})
blk, err := bs.GetBlindedBlockSSZ(ctx, &ethpbv1.BlockRequest{ require.NoError(t, err)
BlockId: []byte("32"), assert.Equal(t, true, resp.Finalized)
}) })
require.NoError(t, err) t.Run("not finalized", func(t *testing.T) {
assert.Equal(t, true, blk.Finalized) b := util.NewBeaconBlock()
}) blk, err := blocks.NewSignedBeaconBlock(b)
t.Run("false", func(t *testing.T) { require.NoError(t, err)
blk, err := bs.GetBlindedBlockSSZ(ctx, &ethpbv1.BlockRequest{ root, err := blk.Block().HashTreeRoot()
BlockId: []byte("64"), require.NoError(t, err)
})
require.NoError(t, err) mockChainService := &mock.ChainService{
assert.Equal(t, false, blk.Finalized) FinalizedRoots: map[[32]byte]bool{root: false},
}) }
bs := &Server{
FinalizationFetcher: mockChainService,
Blocker: &testutil.MockBlocker{BlockToReturn: blk},
}
resp, err := bs.GetBlindedBlockSSZ(ctx, &ethpbv1.BlockRequest{BlockId: root[:]})
require.NoError(t, err)
assert.Equal(t, false, resp.Finalized)
}) })
} }

View File

@@ -12,6 +12,7 @@ import (
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v4/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/db/filters" "github.com/prysmaticlabs/prysm/v4/beacon-chain/db/filters"
rpchelpers "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/helpers" rpchelpers "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/helpers"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/lookup"
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams" fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
"github.com/prysmaticlabs/prysm/v4/config/params" "github.com/prysmaticlabs/prysm/v4/config/params"
"github.com/prysmaticlabs/prysm/v4/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v4/consensus-types/blocks"
@@ -37,23 +38,6 @@ var (
errNilBlock = errors.New("nil block") errNilBlock = errors.New("nil block")
) )
// blockIdParseError represents an error scenario where a block ID could not be parsed.
type blockIdParseError struct {
message string
}
// newBlockIdParseError creates a new error instance.
func newBlockIdParseError(reason error) blockIdParseError {
return blockIdParseError{
message: errors.Wrapf(reason, "could not parse block ID").Error(),
}
}
// Error returns the underlying error message.
func (e *blockIdParseError) Error() string {
return e.message
}
// GetWeakSubjectivity computes the starting epoch of the current weak subjectivity period, and then also // GetWeakSubjectivity computes the starting epoch of the current weak subjectivity period, and then also
// determines the best block root and state root to use for a Checkpoint Sync starting from that point. // determines the best block root and state root to use for a Checkpoint Sync starting from that point.
// DEPRECATED: GetWeakSubjectivity endpoint will no longer be supported // DEPRECATED: GetWeakSubjectivity endpoint will no longer be supported
@@ -101,7 +85,7 @@ func (bs *Server) GetBlockHeader(ctx context.Context, req *ethpbv1.BlockRequest)
ctx, span := trace.StartSpan(ctx, "beacon.GetBlockHeader") ctx, span := trace.StartSpan(ctx, "beacon.GetBlockHeader")
defer span.End() defer span.End()
blk, err := bs.blockFromBlockID(ctx, req.BlockId) blk, err := bs.Blocker.Block(ctx, req.BlockId)
err = handleGetBlockError(blk, err) err = handleGetBlockError(blk, err)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -290,7 +274,7 @@ func (bs *Server) GetBlock(ctx context.Context, req *ethpbv1.BlockRequest) (*eth
ctx, span := trace.StartSpan(ctx, "beacon.GetBlock") ctx, span := trace.StartSpan(ctx, "beacon.GetBlock")
defer span.End() defer span.End()
blk, err := bs.blockFromBlockID(ctx, req.BlockId) blk, err := bs.Blocker.Block(ctx, req.BlockId)
err = handleGetBlockError(blk, err) err = handleGetBlockError(blk, err)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -314,7 +298,7 @@ func (bs *Server) GetBlockSSZ(ctx context.Context, req *ethpbv1.BlockRequest) (*
ctx, span := trace.StartSpan(ctx, "beacon.GetBlockSSZ") ctx, span := trace.StartSpan(ctx, "beacon.GetBlockSSZ")
defer span.End() defer span.End()
blk, err := bs.blockFromBlockID(ctx, req.BlockId) blk, err := bs.Blocker.Block(ctx, req.BlockId)
err = handleGetBlockError(blk, err) err = handleGetBlockError(blk, err)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -336,7 +320,7 @@ func (bs *Server) GetBlockV2(ctx context.Context, req *ethpbv2.BlockRequestV2) (
ctx, span := trace.StartSpan(ctx, "beacon.GetBlockV2") ctx, span := trace.StartSpan(ctx, "beacon.GetBlockV2")
defer span.End() defer span.End()
blk, err := bs.blockFromBlockID(ctx, req.BlockId) blk, err := bs.Blocker.Block(ctx, req.BlockId)
err = handleGetBlockError(blk, err) err = handleGetBlockError(blk, err)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -382,6 +366,14 @@ func (bs *Server) GetBlockV2(ctx context.Context, req *ethpbv2.BlockRequestV2) (
if !errors.Is(err, blocks.ErrUnsupportedGetter) { if !errors.Is(err, blocks.ErrUnsupportedGetter) {
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err) return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
} }
result, err = bs.getBlockDeneb(ctx, blk)
if result != nil {
return result, nil
}
// ErrUnsupportedGetter means that we have another block type
if !errors.Is(err, blocks.ErrUnsupportedGetter) {
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
}
return nil, status.Errorf(codes.Internal, "Unknown block type %T", blk) return nil, status.Errorf(codes.Internal, "Unknown block type %T", blk)
} }
@@ -390,7 +382,7 @@ func (bs *Server) GetBlockSSZV2(ctx context.Context, req *ethpbv2.BlockRequestV2
ctx, span := trace.StartSpan(ctx, "beacon.GetBlockSSZV2") ctx, span := trace.StartSpan(ctx, "beacon.GetBlockSSZV2")
defer span.End() defer span.End()
blk, err := bs.blockFromBlockID(ctx, req.BlockId) blk, err := bs.Blocker.Block(ctx, req.BlockId)
err = handleGetBlockError(blk, err) err = handleGetBlockError(blk, err)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -436,6 +428,14 @@ func (bs *Server) GetBlockSSZV2(ctx context.Context, req *ethpbv2.BlockRequestV2
if !errors.Is(err, blocks.ErrUnsupportedGetter) { if !errors.Is(err, blocks.ErrUnsupportedGetter) {
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err) return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
} }
result, err = bs.getSSZBlockDeneb(ctx, blk)
if result != nil {
return result, nil
}
// ErrUnsupportedGetter means that we have another block type
if !errors.Is(err, blocks.ErrUnsupportedGetter) {
return nil, status.Errorf(codes.Internal, "Could not get signed beacon block: %v", err)
}
return nil, status.Errorf(codes.Internal, "Unknown block type %T", blk) return nil, status.Errorf(codes.Internal, "Unknown block type %T", blk)
} }
@@ -532,7 +532,7 @@ func (bs *Server) ListBlockAttestations(ctx context.Context, req *ethpbv1.BlockR
ctx, span := trace.StartSpan(ctx, "beacon.ListBlockAttestations") ctx, span := trace.StartSpan(ctx, "beacon.ListBlockAttestations")
defer span.End() defer span.End()
blk, err := bs.blockFromBlockID(ctx, req.BlockId) blk, err := bs.Blocker.Block(ctx, req.BlockId)
err = handleGetBlockError(blk, err) err = handleGetBlockError(blk, err)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -559,68 +559,8 @@ func (bs *Server) ListBlockAttestations(ctx context.Context, req *ethpbv1.BlockR
}, nil }, nil
} }
func (bs *Server) blockFromBlockID(ctx context.Context, blockId []byte) (interfaces.ReadOnlySignedBeaconBlock, error) {
var err error
var blk interfaces.ReadOnlySignedBeaconBlock
switch string(blockId) {
case "head":
blk, err = bs.ChainInfoFetcher.HeadBlock(ctx)
if err != nil {
return nil, errors.Wrap(err, "could not retrieve head block")
}
case "finalized":
finalized := bs.ChainInfoFetcher.FinalizedCheckpt()
finalizedRoot := bytesutil.ToBytes32(finalized.Root)
blk, err = bs.BeaconDB.Block(ctx, finalizedRoot)
if err != nil {
return nil, errors.New("could not get finalized block from db")
}
case "genesis":
blk, err = bs.BeaconDB.GenesisBlock(ctx)
if err != nil {
return nil, errors.Wrap(err, "could not retrieve blocks for genesis slot")
}
default:
if len(blockId) == 32 {
blk, err = bs.BeaconDB.Block(ctx, bytesutil.ToBytes32(blockId))
if err != nil {
return nil, errors.Wrap(err, "could not retrieve block")
}
} else {
slot, err := strconv.ParseUint(string(blockId), 10, 64)
if err != nil {
e := newBlockIdParseError(err)
return nil, &e
}
blks, err := bs.BeaconDB.BlocksBySlot(ctx, primitives.Slot(slot))
if err != nil {
return nil, errors.Wrapf(err, "could not retrieve blocks for slot %d", slot)
}
_, roots, err := bs.BeaconDB.BlockRootsBySlot(ctx, primitives.Slot(slot))
if err != nil {
return nil, errors.Wrapf(err, "could not retrieve block roots for slot %d", slot)
}
numBlks := len(blks)
if numBlks == 0 {
return nil, nil
}
for i, b := range blks {
canonical, err := bs.ChainInfoFetcher.IsCanonical(ctx, roots[i])
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not determine if block root is canonical: %v", err)
}
if canonical {
blk = b
break
}
}
}
}
return blk, nil
}
func handleGetBlockError(blk interfaces.ReadOnlySignedBeaconBlock, err error) error { func handleGetBlockError(blk interfaces.ReadOnlySignedBeaconBlock, err error) error {
if invalidBlockIdErr, ok := err.(*blockIdParseError); ok { if invalidBlockIdErr, ok := err.(*lookup.BlockIdParseError); ok {
return status.Errorf(codes.InvalidArgument, "Invalid block ID: %v", invalidBlockIdErr) return status.Errorf(codes.InvalidArgument, "Invalid block ID: %v", invalidBlockIdErr)
} }
if err != nil { if err != nil {
@@ -817,6 +757,76 @@ func (bs *Server) getBlockCapella(ctx context.Context, blk interfaces.ReadOnlySi
}, nil }, nil
} }
func (bs *Server) getBlockDeneb(ctx context.Context, blk interfaces.ReadOnlySignedBeaconBlock) (*ethpbv2.BlockResponseV2, error) {
denebBlk, err := blk.PbDenebBlock()
if err != nil {
// ErrUnsupportedGetter means that we have another block type
if errors.Is(err, blocks.ErrUnsupportedGetter) {
if blindedDenebBlk, err := blk.PbBlindedDenebBlock(); err == nil {
if blindedDenebBlk == nil {
return nil, errNilBlock
}
signedFullBlock, err := bs.ExecutionPayloadReconstructor.ReconstructFullBlock(ctx, blk)
if err != nil {
return nil, errors.Wrapf(err, "could not reconstruct full execution payload to create signed beacon block")
}
denebBlk, err = signedFullBlock.PbDenebBlock()
if err != nil {
return nil, errors.Wrapf(err, "could not get signed beacon block")
}
v2Blk, err := migration.V1Alpha1BeaconBlockDenebToV2(denebBlk.Block)
if err != nil {
return nil, errors.Wrapf(err, "could not convert beacon block")
}
root, err := blk.Block().HashTreeRoot()
if err != nil {
return nil, errors.Wrapf(err, "could not get block root")
}
isOptimistic, err := bs.OptimisticModeFetcher.IsOptimisticForRoot(ctx, root)
if err != nil {
return nil, errors.Wrapf(err, "could not check if block is optimistic")
}
sig := blk.Signature()
return &ethpbv2.BlockResponseV2{
Version: ethpbv2.Version_Deneb,
Data: &ethpbv2.SignedBeaconBlockContainer{
Message: &ethpbv2.SignedBeaconBlockContainer_DenebBlock{DenebBlock: v2Blk},
Signature: sig[:],
},
ExecutionOptimistic: isOptimistic,
}, nil
}
return nil, err
}
return nil, err
}
if denebBlk == nil {
return nil, errNilBlock
}
v2Blk, err := migration.V1Alpha1BeaconBlockDenebToV2(denebBlk.Block)
if err != nil {
return nil, errors.Wrapf(err, "could not convert beacon block")
}
root, err := blk.Block().HashTreeRoot()
if err != nil {
return nil, errors.Wrapf(err, "could not get block root")
}
isOptimistic, err := bs.OptimisticModeFetcher.IsOptimisticForRoot(ctx, root)
if err != nil {
return nil, errors.Wrapf(err, "could not check if block is optimistic")
}
sig := blk.Signature()
return &ethpbv2.BlockResponseV2{
Version: ethpbv2.Version_Deneb,
Data: &ethpbv2.SignedBeaconBlockContainer{
Message: &ethpbv2.SignedBeaconBlockContainer_DenebBlock{DenebBlock: v2Blk},
Signature: sig[:],
},
ExecutionOptimistic: isOptimistic,
}, nil
}
func getSSZBlockPhase0(blk interfaces.ReadOnlySignedBeaconBlock) (*ethpbv2.SSZContainer, error) { func getSSZBlockPhase0(blk interfaces.ReadOnlySignedBeaconBlock) (*ethpbv2.SSZContainer, error) {
phase0Blk, err := blk.PbPhase0Block() phase0Blk, err := blk.PbPhase0Block()
if err != nil { if err != nil {
@@ -1012,6 +1022,82 @@ func (bs *Server) getSSZBlockCapella(ctx context.Context, blk interfaces.ReadOnl
return &ethpbv2.SSZContainer{Version: ethpbv2.Version_CAPELLA, ExecutionOptimistic: isOptimistic, Data: sszData}, nil return &ethpbv2.SSZContainer{Version: ethpbv2.Version_CAPELLA, ExecutionOptimistic: isOptimistic, Data: sszData}, nil
} }
func (bs *Server) getSSZBlockDeneb(ctx context.Context, blk interfaces.ReadOnlySignedBeaconBlock) (*ethpbv2.SSZContainer, error) {
denebBlk, err := blk.PbDenebBlock()
if err != nil {
// ErrUnsupportedGetter means that we have another block type
if errors.Is(err, blocks.ErrUnsupportedGetter) {
if blindedDenebBlk, err := blk.PbBlindedDenebBlock(); err == nil {
if blindedDenebBlk == nil {
return nil, errNilBlock
}
signedFullBlock, err := bs.ExecutionPayloadReconstructor.ReconstructFullBlock(ctx, blk)
if err != nil {
return nil, errors.Wrapf(err, "could not reconstruct full execution payload to create signed beacon block")
}
denebBlk, err = signedFullBlock.PbDenebBlock()
if err != nil {
return nil, errors.Wrapf(err, "could not get signed beacon block")
}
v2Blk, err := migration.V1Alpha1BeaconBlockDenebToV2(denebBlk.Block)
if err != nil {
return nil, errors.Wrapf(err, "could not convert signed beacon block")
}
root, err := blk.Block().HashTreeRoot()
if err != nil {
return nil, errors.Wrapf(err, "could not get block root")
}
isOptimistic, err := bs.OptimisticModeFetcher.IsOptimisticForRoot(ctx, root)
if err != nil {
return nil, errors.Wrapf(err, "could not check if block is optimistic")
}
sig := blk.Signature()
data := &ethpbv2.SignedBeaconBlockDeneb{
Message: v2Blk,
Signature: sig[:],
}
sszData, err := data.MarshalSSZ()
if err != nil {
return nil, errors.Wrapf(err, "could not marshal block into SSZ")
}
return &ethpbv2.SSZContainer{
Version: ethpbv2.Version_Deneb,
ExecutionOptimistic: isOptimistic,
Data: sszData,
}, nil
}
return nil, err
}
return nil, err
}
if denebBlk == nil {
return nil, errNilBlock
}
v2Blk, err := migration.V1Alpha1BeaconBlockDenebToV2(denebBlk.Block)
if err != nil {
return nil, errors.Wrapf(err, "could not convert signed beacon block")
}
root, err := blk.Block().HashTreeRoot()
if err != nil {
return nil, errors.Wrapf(err, "could not get block root")
}
isOptimistic, err := bs.OptimisticModeFetcher.IsOptimisticForRoot(ctx, root)
if err != nil {
return nil, errors.Wrapf(err, "could not check if block is optimistic")
}
sig := blk.Signature()
data := &ethpbv2.SignedBeaconBlockDeneb{
Message: v2Blk,
Signature: sig[:],
}
sszData, err := data.MarshalSSZ()
if err != nil {
return nil, errors.Wrapf(err, "could not marshal block into SSZ")
}
return &ethpbv2.SSZContainer{Version: ethpbv2.Version_Deneb, ExecutionOptimistic: isOptimistic, Data: sszData}, nil
}
func (bs *Server) submitPhase0Block(ctx context.Context, phase0Blk *ethpbv1.BeaconBlock, sig []byte) error { func (bs *Server) submitPhase0Block(ctx context.Context, phase0Blk *ethpbv1.BeaconBlock, sig []byte) error {
v1alpha1Blk, err := migration.V1ToV1Alpha1SignedBlock(&ethpbv1.SignedBeaconBlock{Block: phase0Blk, Signature: sig}) v1alpha1Blk, err := migration.V1ToV1Alpha1SignedBlock(&ethpbv1.SignedBeaconBlock{Block: phase0Blk, Signature: sig})
if err != nil { if err != nil {

File diff suppressed because it is too large Load Diff

View File

@@ -104,6 +104,8 @@ func TestGetSpec(t *testing.T) {
config.MaxWithdrawalsPerPayload = 74 config.MaxWithdrawalsPerPayload = 74
config.MaxBlsToExecutionChanges = 75 config.MaxBlsToExecutionChanges = 75
config.MaxValidatorsPerWithdrawalsSweep = 76 config.MaxValidatorsPerWithdrawalsSweep = 76
config.DenebForkEpoch = 77
config.DenebForkVersion = []byte("DenebForkVersion")
var dbp [4]byte var dbp [4]byte
copy(dbp[:], []byte{'0', '0', '0', '1'}) copy(dbp[:], []byte{'0', '0', '0', '1'})
@@ -129,6 +131,9 @@ func TestGetSpec(t *testing.T) {
var dam [4]byte var dam [4]byte
copy(dam[:], []byte{'1', '0', '0', '0'}) copy(dam[:], []byte{'1', '0', '0', '0'})
config.DomainApplicationMask = dam config.DomainApplicationMask = dam
var dbs [4]byte
copy(dbs[:], []byte{'0', '0', '0', '8'})
config.DomainBlobSidecar = dbs
params.OverrideBeaconConfig(config) params.OverrideBeaconConfig(config)
@@ -136,7 +141,7 @@ func TestGetSpec(t *testing.T) {
resp, err := server.GetSpec(context.Background(), &emptypb.Empty{}) resp, err := server.GetSpec(context.Background(), &emptypb.Empty{})
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, 105, len(resp.Data)) assert.Equal(t, 108, len(resp.Data))
for k, v := range resp.Data { for k, v := range resp.Data {
switch k { switch k {
case "CONFIG_NAME": case "CONFIG_NAME":
@@ -362,8 +367,14 @@ func TestGetSpec(t *testing.T) {
case "REORG_WEIGHT_THRESHOLD": case "REORG_WEIGHT_THRESHOLD":
assert.Equal(t, "20", v) assert.Equal(t, "20", v)
case "SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY": case "SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY":
case "DENEB_FORK_EPOCH":
assert.Equal(t, "77", v)
case "DENEB_FORK_VERSION":
assert.Equal(t, "0x"+hex.EncodeToString([]byte("DenebForkVersion")), v)
case "DOMAIN_BLOB_SIDECAR":
assert.Equal(t, "0x30303038", v)
default: default:
t.Errorf("Incorrect key: %s", k) t.Errorf("Unknown key: %s", k)
} }
} }
} }

View File

@@ -14,8 +14,8 @@ import (
"github.com/prysmaticlabs/prysm/v4/beacon-chain/operations/slashings" "github.com/prysmaticlabs/prysm/v4/beacon-chain/operations/slashings"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/operations/voluntaryexits" "github.com/prysmaticlabs/prysm/v4/beacon-chain/operations/voluntaryexits"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/p2p" "github.com/prysmaticlabs/prysm/v4/beacon-chain/p2p"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/lookup"
v1alpha1validator "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/prysm/v1alpha1/validator" v1alpha1validator "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/prysm/v1alpha1/validator"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/statefetcher"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state/stategen" "github.com/prysmaticlabs/prysm/v4/beacon-chain/state/stategen"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/sync" "github.com/prysmaticlabs/prysm/v4/beacon-chain/sync"
) )
@@ -34,7 +34,8 @@ type Server struct {
SlashingsPool slashings.PoolManager SlashingsPool slashings.PoolManager
VoluntaryExitsPool voluntaryexits.PoolManager VoluntaryExitsPool voluntaryexits.PoolManager
StateGenService stategen.StateManager StateGenService stategen.StateManager
StateFetcher statefetcher.Fetcher Stater lookup.Stater
Blocker lookup.Blocker
HeadFetcher blockchain.HeadFetcher HeadFetcher blockchain.HeadFetcher
OptimisticModeFetcher blockchain.OptimisticModeFetcher OptimisticModeFetcher blockchain.OptimisticModeFetcher
V1Alpha1ValidatorServer *v1alpha1validator.Server V1Alpha1ValidatorServer *v1alpha1validator.Server

View File

@@ -6,7 +6,7 @@ import (
"strconv" "strconv"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/helpers" "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/helpers"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/statefetcher" "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/lookup"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state" "github.com/prysmaticlabs/prysm/v4/beacon-chain/state"
"github.com/prysmaticlabs/prysm/v4/config/params" "github.com/prysmaticlabs/prysm/v4/config/params"
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
@@ -58,20 +58,20 @@ func (bs *Server) GetStateRoot(ctx context.Context, req *ethpb.StateRequest) (*e
ctx, span := trace.StartSpan(ctx, "beacon.GetStateRoot") ctx, span := trace.StartSpan(ctx, "beacon.GetStateRoot")
defer span.End() defer span.End()
stateRoot, err := bs.StateFetcher.StateRoot(ctx, req.StateId) stateRoot, err := bs.Stater.StateRoot(ctx, req.StateId)
if err != nil { if err != nil {
if rootNotFoundErr, ok := err.(*statefetcher.StateRootNotFoundError); ok { if rootNotFoundErr, ok := err.(*lookup.StateRootNotFoundError); ok {
return nil, status.Errorf(codes.NotFound, "State root not found: %v", rootNotFoundErr) return nil, status.Errorf(codes.NotFound, "State root not found: %v", rootNotFoundErr)
} else if parseErr, ok := err.(*statefetcher.StateIdParseError); ok { } else if parseErr, ok := err.(*lookup.StateIdParseError); ok {
return nil, status.Errorf(codes.InvalidArgument, "Invalid state ID: %v", parseErr) return nil, status.Errorf(codes.InvalidArgument, "Invalid state ID: %v", parseErr)
} }
return nil, status.Errorf(codes.Internal, "Could not get state root: %v", err) return nil, status.Errorf(codes.Internal, "Could not get state root: %v", err)
} }
st, err := bs.StateFetcher.State(ctx, req.StateId) st, err := bs.Stater.State(ctx, req.StateId)
if err != nil { if err != nil {
return nil, status.Errorf(codes.Internal, "Could not get state: %v", err) return nil, status.Errorf(codes.Internal, "Could not get state: %v", err)
} }
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.StateFetcher, bs.ChainInfoFetcher, bs.BeaconDB) isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.Stater, bs.ChainInfoFetcher, bs.BeaconDB)
if err != nil { if err != nil {
return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err) return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err)
} }
@@ -95,12 +95,12 @@ func (bs *Server) GetStateFork(ctx context.Context, req *ethpb.StateRequest) (*e
ctx, span := trace.StartSpan(ctx, "beacon.GetStateFork") ctx, span := trace.StartSpan(ctx, "beacon.GetStateFork")
defer span.End() defer span.End()
st, err := bs.StateFetcher.State(ctx, req.StateId) st, err := bs.Stater.State(ctx, req.StateId)
if err != nil { if err != nil {
return nil, helpers.PrepareStateFetchGRPCError(err) return nil, helpers.PrepareStateFetchGRPCError(err)
} }
fork := st.Fork() fork := st.Fork()
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.StateFetcher, bs.ChainInfoFetcher, bs.BeaconDB) isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.Stater, bs.ChainInfoFetcher, bs.BeaconDB)
if err != nil { if err != nil {
return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err) return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err)
} }
@@ -127,11 +127,11 @@ func (bs *Server) GetFinalityCheckpoints(ctx context.Context, req *ethpb.StateRe
ctx, span := trace.StartSpan(ctx, "beacon.GetFinalityCheckpoints") ctx, span := trace.StartSpan(ctx, "beacon.GetFinalityCheckpoints")
defer span.End() defer span.End()
st, err := bs.StateFetcher.State(ctx, req.StateId) st, err := bs.Stater.State(ctx, req.StateId)
if err != nil { if err != nil {
return nil, helpers.PrepareStateFetchGRPCError(err) return nil, helpers.PrepareStateFetchGRPCError(err)
} }
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.StateFetcher, bs.ChainInfoFetcher, bs.BeaconDB) isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.Stater, bs.ChainInfoFetcher, bs.BeaconDB)
if err != nil { if err != nil {
return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err) return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err)
} }
@@ -160,7 +160,7 @@ func (bs *Server) GetRandao(ctx context.Context, req *eth2.RandaoRequest) (*eth2
ctx, span := trace.StartSpan(ctx, "beacon.GetRandao") ctx, span := trace.StartSpan(ctx, "beacon.GetRandao")
defer span.End() defer span.End()
st, err := bs.StateFetcher.State(ctx, req.StateId) st, err := bs.Stater.State(ctx, req.StateId)
if err != nil { if err != nil {
return nil, helpers.PrepareStateFetchGRPCError(err) return nil, helpers.PrepareStateFetchGRPCError(err)
} }
@@ -186,7 +186,7 @@ func (bs *Server) GetRandao(ctx context.Context, req *eth2.RandaoRequest) (*eth2
return nil, status.Errorf(codes.Internal, "Could not get randao mix at index %d", idx) return nil, status.Errorf(codes.Internal, "Could not get randao mix at index %d", idx)
} }
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.StateFetcher, bs.ChainInfoFetcher, bs.BeaconDB) isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.Stater, bs.ChainInfoFetcher, bs.BeaconDB)
if err != nil { if err != nil {
return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err) return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err)
} }
@@ -215,14 +215,14 @@ func (bs *Server) stateFromRequest(ctx context.Context, req *stateRequest) (stat
err, err,
) )
} }
st, err := bs.StateFetcher.State(ctx, []byte(strconv.FormatUint(uint64(slot), 10))) st, err := bs.Stater.State(ctx, []byte(strconv.FormatUint(uint64(slot), 10)))
if err != nil { if err != nil {
return nil, helpers.PrepareStateFetchGRPCError(err) return nil, helpers.PrepareStateFetchGRPCError(err)
} }
return st, nil return st, nil
} }
var err error var err error
st, err := bs.StateFetcher.State(ctx, req.stateId) st, err := bs.Stater.State(ctx, req.stateId)
if err != nil { if err != nil {
return nil, helpers.PrepareStateFetchGRPCError(err) return nil, helpers.PrepareStateFetchGRPCError(err)
} }

View File

@@ -83,7 +83,7 @@ func TestGetStateRoot(t *testing.T) {
chainService := &chainMock.ChainService{} chainService := &chainMock.ChainService{}
server := &Server{ server := &Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconStateRoot: stateRoot[:], BeaconStateRoot: stateRoot[:],
BeaconState: fakeState, BeaconState: fakeState,
}, },
@@ -111,7 +111,7 @@ func TestGetStateRoot(t *testing.T) {
chainService := &chainMock.ChainService{Optimistic: true} chainService := &chainMock.ChainService{Optimistic: true}
server := &Server{ server := &Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconStateRoot: stateRoot[:], BeaconStateRoot: stateRoot[:],
BeaconState: fakeState, BeaconState: fakeState,
}, },
@@ -145,7 +145,7 @@ func TestGetStateRoot(t *testing.T) {
}, },
} }
server := &Server{ server := &Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconStateRoot: stateRoot[:], BeaconStateRoot: stateRoot[:],
BeaconState: fakeState, BeaconState: fakeState,
}, },
@@ -179,7 +179,7 @@ func TestGetStateFork(t *testing.T) {
chainService := &chainMock.ChainService{} chainService := &chainMock.ChainService{}
server := &Server{ server := &Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: fakeState, BeaconState: fakeState,
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -209,7 +209,7 @@ func TestGetStateFork(t *testing.T) {
chainService := &chainMock.ChainService{Optimistic: true} chainService := &chainMock.ChainService{Optimistic: true}
server := &Server{ server := &Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: fakeState, BeaconState: fakeState,
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -242,7 +242,7 @@ func TestGetStateFork(t *testing.T) {
}, },
} }
server := &Server{ server := &Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: fakeState, BeaconState: fakeState,
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -282,7 +282,7 @@ func TestGetFinalityCheckpoints(t *testing.T) {
chainService := &chainMock.ChainService{} chainService := &chainMock.ChainService{}
server := &Server{ server := &Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: fakeState, BeaconState: fakeState,
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -314,7 +314,7 @@ func TestGetFinalityCheckpoints(t *testing.T) {
chainService := &chainMock.ChainService{Optimistic: true} chainService := &chainMock.ChainService{Optimistic: true}
server := &Server{ server := &Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: fakeState, BeaconState: fakeState,
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -347,7 +347,7 @@ func TestGetFinalityCheckpoints(t *testing.T) {
}, },
} }
server := &Server{ server := &Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: fakeState, BeaconState: fakeState,
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -388,7 +388,7 @@ func TestGetRandao(t *testing.T) {
db := dbTest.SetupDB(t) db := dbTest.SetupDB(t)
chainService := &chainMock.ChainService{} chainService := &chainMock.ChainService{}
server := &Server{ server := &Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: st, BeaconState: st,
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -413,7 +413,7 @@ func TestGetRandao(t *testing.T) {
assert.DeepEqual(t, mixOld, resp.Data.Randao) assert.DeepEqual(t, mixOld, resp.Data.Randao)
}) })
t.Run("head state below `EpochsPerHistoricalVector`", func(t *testing.T) { t.Run("head state below `EpochsPerHistoricalVector`", func(t *testing.T) {
server.StateFetcher = &testutil.MockFetcher{ server.Stater = &testutil.MockStater{
BeaconState: headSt, BeaconState: headSt,
} }
resp, err := server.GetRandao(ctx, &eth2.RandaoRequest{StateId: []byte("head")}) resp, err := server.GetRandao(ctx, &eth2.RandaoRequest{StateId: []byte("head")})
@@ -441,7 +441,7 @@ func TestGetRandao(t *testing.T) {
chainService := &chainMock.ChainService{Optimistic: true} chainService := &chainMock.ChainService{Optimistic: true}
server := &Server{ server := &Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: st, BeaconState: st,
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -473,7 +473,7 @@ func TestGetRandao(t *testing.T) {
}, },
} }
server := &Server{ server := &Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: st, BeaconState: st,
}, },
HeadFetcher: chainService, HeadFetcher: chainService,

View File

@@ -91,7 +91,7 @@ func (bs *Server) ListSyncCommittees(ctx context.Context, req *ethpbv2.StateSync
return nil, status.Errorf(codes.Internal, "Could not extract sync subcommittees: %v", err) return nil, status.Errorf(codes.Internal, "Could not extract sync subcommittees: %v", err)
} }
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.StateFetcher, bs.ChainInfoFetcher, bs.BeaconDB) isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.Stater, bs.ChainInfoFetcher, bs.BeaconDB)
if err != nil { if err != nil {
return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err) return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err)
} }

View File

@@ -167,7 +167,7 @@ func TestListSyncCommittees(t *testing.T) {
GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{ GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{
Genesis: time.Now(), Genesis: time.Now(),
}, },
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: st, BeaconState: st,
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -213,7 +213,7 @@ func TestListSyncCommittees(t *testing.T) {
GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{ GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{
Genesis: time.Now(), Genesis: time.Now(),
}, },
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: st, BeaconState: st,
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -249,7 +249,7 @@ func TestListSyncCommittees(t *testing.T) {
GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{ GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{
Genesis: time.Now(), Genesis: time.Now(),
}, },
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: st, BeaconState: st,
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -309,7 +309,7 @@ func TestListSyncCommitteesFuture(t *testing.T) {
GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{ GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{
Genesis: time.Now(), Genesis: time.Now(),
}, },
StateFetcher: &futureSyncMockFetcher{ Stater: &futureSyncMockFetcher{
BeaconState: st, BeaconState: st,
}, },
HeadFetcher: chainService, HeadFetcher: chainService,

View File

@@ -42,7 +42,7 @@ func (bs *Server) GetValidator(ctx context.Context, req *ethpb.StateValidatorReq
ctx, span := trace.StartSpan(ctx, "beacon.GetValidator") ctx, span := trace.StartSpan(ctx, "beacon.GetValidator")
defer span.End() defer span.End()
st, err := bs.StateFetcher.State(ctx, req.StateId) st, err := bs.Stater.State(ctx, req.StateId)
if err != nil { if err != nil {
return nil, helpers.PrepareStateFetchGRPCError(err) return nil, helpers.PrepareStateFetchGRPCError(err)
} }
@@ -57,7 +57,7 @@ func (bs *Server) GetValidator(ctx context.Context, req *ethpb.StateValidatorReq
return nil, status.Error(codes.NotFound, "Could not find validator") return nil, status.Error(codes.NotFound, "Could not find validator")
} }
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.StateFetcher, bs.ChainInfoFetcher, bs.BeaconDB) isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.Stater, bs.ChainInfoFetcher, bs.BeaconDB)
if err != nil { if err != nil {
return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err) return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err)
} }
@@ -76,7 +76,7 @@ func (bs *Server) ListValidators(ctx context.Context, req *ethpb.StateValidators
ctx, span := trace.StartSpan(ctx, "beacon.ListValidators") ctx, span := trace.StartSpan(ctx, "beacon.ListValidators")
defer span.End() defer span.End()
st, err := bs.StateFetcher.State(ctx, req.StateId) st, err := bs.Stater.State(ctx, req.StateId)
if err != nil { if err != nil {
return nil, helpers.PrepareStateFetchGRPCError(err) return nil, helpers.PrepareStateFetchGRPCError(err)
} }
@@ -86,7 +86,7 @@ func (bs *Server) ListValidators(ctx context.Context, req *ethpb.StateValidators
return nil, handleValContainerErr(err) return nil, handleValContainerErr(err)
} }
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.StateFetcher, bs.ChainInfoFetcher, bs.BeaconDB) isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.Stater, bs.ChainInfoFetcher, bs.BeaconDB)
if err != nil { if err != nil {
return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err) return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err)
} }
@@ -138,7 +138,7 @@ func (bs *Server) ListValidatorBalances(ctx context.Context, req *ethpb.Validato
ctx, span := trace.StartSpan(ctx, "beacon.ListValidatorBalances") ctx, span := trace.StartSpan(ctx, "beacon.ListValidatorBalances")
defer span.End() defer span.End()
st, err := bs.StateFetcher.State(ctx, req.StateId) st, err := bs.Stater.State(ctx, req.StateId)
if err != nil { if err != nil {
return nil, helpers.PrepareStateFetchGRPCError(err) return nil, helpers.PrepareStateFetchGRPCError(err)
} }
@@ -155,7 +155,7 @@ func (bs *Server) ListValidatorBalances(ctx context.Context, req *ethpb.Validato
} }
} }
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.StateFetcher, bs.ChainInfoFetcher, bs.BeaconDB) isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.Stater, bs.ChainInfoFetcher, bs.BeaconDB)
if err != nil { if err != nil {
return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err) return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err)
} }
@@ -175,7 +175,7 @@ func (bs *Server) ListCommittees(ctx context.Context, req *ethpb.StateCommittees
ctx, span := trace.StartSpan(ctx, "beacon.ListCommittees") ctx, span := trace.StartSpan(ctx, "beacon.ListCommittees")
defer span.End() defer span.End()
st, err := bs.StateFetcher.State(ctx, req.StateId) st, err := bs.Stater.State(ctx, req.StateId)
if err != nil { if err != nil {
return nil, helpers.PrepareStateFetchGRPCError(err) return nil, helpers.PrepareStateFetchGRPCError(err)
} }
@@ -220,7 +220,7 @@ func (bs *Server) ListCommittees(ctx context.Context, req *ethpb.StateCommittees
} }
} }
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.StateFetcher, bs.ChainInfoFetcher, bs.BeaconDB) isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, bs.OptimisticModeFetcher, bs.Stater, bs.ChainInfoFetcher, bs.BeaconDB)
if err != nil { if err != nil {
return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err) return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err)
} }

View File

@@ -9,7 +9,7 @@ import (
chainMock "github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain/testing" chainMock "github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain/testing"
dbTest "github.com/prysmaticlabs/prysm/v4/beacon-chain/db/testing" dbTest "github.com/prysmaticlabs/prysm/v4/beacon-chain/db/testing"
rpchelpers "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/helpers" rpchelpers "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/helpers"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/statefetcher" "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/lookup"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/testutil" "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/testutil"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state" "github.com/prysmaticlabs/prysm/v4/beacon-chain/state"
state_native "github.com/prysmaticlabs/prysm/v4/beacon-chain/state/state-native" state_native "github.com/prysmaticlabs/prysm/v4/beacon-chain/state/state-native"
@@ -34,7 +34,7 @@ func TestGetValidator(t *testing.T) {
t.Run("Head Get Validator by index", func(t *testing.T) { t.Run("Head Get Validator by index", func(t *testing.T) {
chainService := &chainMock.ChainService{} chainService := &chainMock.ChainService{}
s := Server{ s := Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: st, BeaconState: st,
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -54,7 +54,7 @@ func TestGetValidator(t *testing.T) {
t.Run("Head Get Validator by pubkey", func(t *testing.T) { t.Run("Head Get Validator by pubkey", func(t *testing.T) {
chainService := &chainMock.ChainService{} chainService := &chainMock.ChainService{}
s := Server{ s := Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: st, BeaconState: st,
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -75,7 +75,7 @@ func TestGetValidator(t *testing.T) {
t.Run("Validator ID required", func(t *testing.T) { t.Run("Validator ID required", func(t *testing.T) {
s := Server{ s := Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: st, BeaconState: st,
}, },
HeadFetcher: &chainMock.ChainService{}, HeadFetcher: &chainMock.ChainService{},
@@ -98,7 +98,7 @@ func TestGetValidator(t *testing.T) {
chainService := &chainMock.ChainService{Optimistic: true} chainService := &chainMock.ChainService{Optimistic: true}
s := Server{ s := Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: st, BeaconState: st,
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -131,7 +131,7 @@ func TestGetValidator(t *testing.T) {
}, },
} }
s := Server{ s := Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: st, BeaconState: st,
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -157,7 +157,7 @@ func TestListValidators(t *testing.T) {
t.Run("Head List All Validators", func(t *testing.T) { t.Run("Head List All Validators", func(t *testing.T) {
chainService := &chainMock.ChainService{} chainService := &chainMock.ChainService{}
s := Server{ s := Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: st, BeaconState: st,
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -179,7 +179,7 @@ func TestListValidators(t *testing.T) {
t.Run("Head List Validators by index", func(t *testing.T) { t.Run("Head List Validators by index", func(t *testing.T) {
chainService := &chainMock.ChainService{} chainService := &chainMock.ChainService{}
s := Server{ s := Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: st, BeaconState: st,
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -204,7 +204,7 @@ func TestListValidators(t *testing.T) {
t.Run("Head List Validators by pubkey", func(t *testing.T) { t.Run("Head List Validators by pubkey", func(t *testing.T) {
chainService := &chainMock.ChainService{} chainService := &chainMock.ChainService{}
s := Server{ s := Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: st, BeaconState: st,
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -233,7 +233,7 @@ func TestListValidators(t *testing.T) {
t.Run("Head List Validators by both index and pubkey", func(t *testing.T) { t.Run("Head List Validators by both index and pubkey", func(t *testing.T) {
chainService := &chainMock.ChainService{} chainService := &chainMock.ChainService{}
s := Server{ s := Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: st, BeaconState: st,
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -264,7 +264,7 @@ func TestListValidators(t *testing.T) {
t.Run("Unknown public key is ignored", func(t *testing.T) { t.Run("Unknown public key is ignored", func(t *testing.T) {
chainService := &chainMock.ChainService{} chainService := &chainMock.ChainService{}
s := Server{ s := Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: st, BeaconState: st,
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -287,7 +287,7 @@ func TestListValidators(t *testing.T) {
t.Run("Unknown index is ignored", func(t *testing.T) { t.Run("Unknown index is ignored", func(t *testing.T) {
chainService := &chainMock.ChainService{} chainService := &chainMock.ChainService{}
s := Server{ s := Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: st, BeaconState: st,
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -317,7 +317,7 @@ func TestListValidators(t *testing.T) {
chainService := &chainMock.ChainService{Optimistic: true} chainService := &chainMock.ChainService{Optimistic: true}
s := Server{ s := Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: st, BeaconState: st,
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -349,7 +349,7 @@ func TestListValidators(t *testing.T) {
}, },
} }
s := Server{ s := Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: st, BeaconState: st,
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -440,7 +440,7 @@ func TestListValidators_Status(t *testing.T) {
t.Run("Head List All ACTIVE Validators", func(t *testing.T) { t.Run("Head List All ACTIVE Validators", func(t *testing.T) {
chainService := &chainMock.ChainService{} chainService := &chainMock.ChainService{}
s := Server{ s := Server{
StateFetcher: &statefetcher.StateProvider{ Stater: &lookup.BeaconDbStater{
ChainInfoFetcher: &chainMock.ChainService{State: st}, ChainInfoFetcher: &chainMock.ChainService{State: st},
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -478,7 +478,7 @@ func TestListValidators_Status(t *testing.T) {
t.Run("Head List All ACTIVE_ONGOING Validators", func(t *testing.T) { t.Run("Head List All ACTIVE_ONGOING Validators", func(t *testing.T) {
chainService := &chainMock.ChainService{} chainService := &chainMock.ChainService{}
s := Server{ s := Server{
StateFetcher: &statefetcher.StateProvider{ Stater: &lookup.BeaconDbStater{
ChainInfoFetcher: &chainMock.ChainService{State: st}, ChainInfoFetcher: &chainMock.ChainService{State: st},
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -515,7 +515,7 @@ func TestListValidators_Status(t *testing.T) {
t.Run("Head List All EXITED Validators", func(t *testing.T) { t.Run("Head List All EXITED Validators", func(t *testing.T) {
chainService := &chainMock.ChainService{} chainService := &chainMock.ChainService{}
s := Server{ s := Server{
StateFetcher: &statefetcher.StateProvider{ Stater: &lookup.BeaconDbStater{
ChainInfoFetcher: &chainMock.ChainService{State: st}, ChainInfoFetcher: &chainMock.ChainService{State: st},
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -551,7 +551,7 @@ func TestListValidators_Status(t *testing.T) {
t.Run("Head List All PENDING_INITIALIZED and EXITED_UNSLASHED Validators", func(t *testing.T) { t.Run("Head List All PENDING_INITIALIZED and EXITED_UNSLASHED Validators", func(t *testing.T) {
chainService := &chainMock.ChainService{} chainService := &chainMock.ChainService{}
s := Server{ s := Server{
StateFetcher: &statefetcher.StateProvider{ Stater: &lookup.BeaconDbStater{
ChainInfoFetcher: &chainMock.ChainService{State: st}, ChainInfoFetcher: &chainMock.ChainService{State: st},
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -587,7 +587,7 @@ func TestListValidators_Status(t *testing.T) {
t.Run("Head List All PENDING and EXITED Validators", func(t *testing.T) { t.Run("Head List All PENDING and EXITED Validators", func(t *testing.T) {
chainService := &chainMock.ChainService{} chainService := &chainMock.ChainService{}
s := Server{ s := Server{
StateFetcher: &statefetcher.StateProvider{ Stater: &lookup.BeaconDbStater{
ChainInfoFetcher: &chainMock.ChainService{State: st}, ChainInfoFetcher: &chainMock.ChainService{State: st},
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -638,7 +638,7 @@ func TestListValidatorBalances(t *testing.T) {
t.Run("Head List Validators Balance by index", func(t *testing.T) { t.Run("Head List Validators Balance by index", func(t *testing.T) {
chainService := &chainMock.ChainService{} chainService := &chainMock.ChainService{}
s := Server{ s := Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: st, BeaconState: st,
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -663,7 +663,7 @@ func TestListValidatorBalances(t *testing.T) {
t.Run("Head List Validators Balance by pubkey", func(t *testing.T) { t.Run("Head List Validators Balance by pubkey", func(t *testing.T) {
chainService := &chainMock.ChainService{} chainService := &chainMock.ChainService{}
s := Server{ s := Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: st, BeaconState: st,
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -691,7 +691,7 @@ func TestListValidatorBalances(t *testing.T) {
t.Run("Head List Validators Balance by both index and pubkey", func(t *testing.T) { t.Run("Head List Validators Balance by both index and pubkey", func(t *testing.T) {
chainService := &chainMock.ChainService{} chainService := &chainMock.ChainService{}
s := Server{ s := Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: st, BeaconState: st,
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -726,7 +726,7 @@ func TestListValidatorBalances(t *testing.T) {
chainService := &chainMock.ChainService{Optimistic: true} chainService := &chainMock.ChainService{Optimistic: true}
s := Server{ s := Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: st, BeaconState: st,
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -761,7 +761,7 @@ func TestListValidatorBalances(t *testing.T) {
}, },
} }
s := Server{ s := Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: st, BeaconState: st,
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -791,7 +791,7 @@ func TestListCommittees(t *testing.T) {
t.Run("Head All Committees", func(t *testing.T) { t.Run("Head All Committees", func(t *testing.T) {
chainService := &chainMock.ChainService{} chainService := &chainMock.ChainService{}
s := Server{ s := Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: st, BeaconState: st,
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -814,7 +814,7 @@ func TestListCommittees(t *testing.T) {
t.Run("Head All Committees of Epoch 10", func(t *testing.T) { t.Run("Head All Committees of Epoch 10", func(t *testing.T) {
chainService := &chainMock.ChainService{} chainService := &chainMock.ChainService{}
s := Server{ s := Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: st, BeaconState: st,
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -836,7 +836,7 @@ func TestListCommittees(t *testing.T) {
t.Run("Head All Committees of Slot 4", func(t *testing.T) { t.Run("Head All Committees of Slot 4", func(t *testing.T) {
chainService := &chainMock.ChainService{} chainService := &chainMock.ChainService{}
s := Server{ s := Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: st, BeaconState: st,
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -864,7 +864,7 @@ func TestListCommittees(t *testing.T) {
t.Run("Head All Committees of Index 1", func(t *testing.T) { t.Run("Head All Committees of Index 1", func(t *testing.T) {
chainService := &chainMock.ChainService{} chainService := &chainMock.ChainService{}
s := Server{ s := Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: st, BeaconState: st,
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -892,7 +892,7 @@ func TestListCommittees(t *testing.T) {
t.Run("Head All Committees of Slot 2, Index 1", func(t *testing.T) { t.Run("Head All Committees of Slot 2, Index 1", func(t *testing.T) {
chainService := &chainMock.ChainService{} chainService := &chainMock.ChainService{}
s := Server{ s := Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: st, BeaconState: st,
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -928,7 +928,7 @@ func TestListCommittees(t *testing.T) {
chainService := &chainMock.ChainService{Optimistic: true} chainService := &chainMock.ChainService{Optimistic: true}
s := Server{ s := Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: st, BeaconState: st,
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -961,7 +961,7 @@ func TestListCommittees(t *testing.T) {
}, },
} }
s := Server{ s := Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: st, BeaconState: st,
}, },
HeadFetcher: chainService, HeadFetcher: chainService,

View File

@@ -12,7 +12,7 @@ go_library(
"//beacon-chain/blockchain:go_default_library", "//beacon-chain/blockchain:go_default_library",
"//beacon-chain/db:go_default_library", "//beacon-chain/db:go_default_library",
"//beacon-chain/rpc/eth/helpers:go_default_library", "//beacon-chain/rpc/eth/helpers:go_default_library",
"//beacon-chain/rpc/statefetcher:go_default_library", "//beacon-chain/rpc/lookup:go_default_library",
"//proto/eth/v1:go_default_library", "//proto/eth/v1:go_default_library",
"//proto/eth/v2:go_default_library", "//proto/eth/v2:go_default_library",
"//proto/migration:go_default_library", "//proto/migration:go_default_library",

View File

@@ -19,7 +19,7 @@ func (ds *Server) GetBeaconStateSSZ(ctx context.Context, req *ethpbv1.StateReque
ctx, span := trace.StartSpan(ctx, "debug.GetBeaconStateSSZ") ctx, span := trace.StartSpan(ctx, "debug.GetBeaconStateSSZ")
defer span.End() defer span.End()
state, err := ds.StateFetcher.State(ctx, req.StateId) state, err := ds.Stater.State(ctx, req.StateId)
if err != nil { if err != nil {
return nil, helpers.PrepareStateFetchGRPCError(err) return nil, helpers.PrepareStateFetchGRPCError(err)
} }
@@ -37,11 +37,11 @@ func (ds *Server) GetBeaconStateV2(ctx context.Context, req *ethpbv2.BeaconState
ctx, span := trace.StartSpan(ctx, "debug.GetBeaconStateV2") ctx, span := trace.StartSpan(ctx, "debug.GetBeaconStateV2")
defer span.End() defer span.End()
beaconSt, err := ds.StateFetcher.State(ctx, req.StateId) beaconSt, err := ds.Stater.State(ctx, req.StateId)
if err != nil { if err != nil {
return nil, helpers.PrepareStateFetchGRPCError(err) return nil, helpers.PrepareStateFetchGRPCError(err)
} }
isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, ds.OptimisticModeFetcher, ds.StateFetcher, ds.ChainInfoFetcher, ds.BeaconDB) isOptimistic, err := helpers.IsOptimistic(ctx, req.StateId, ds.OptimisticModeFetcher, ds.Stater, ds.ChainInfoFetcher, ds.BeaconDB)
if err != nil { if err != nil {
return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err) return nil, status.Errorf(codes.Internal, "Could not check if slot's block is optimistic: %v", err)
} }
@@ -104,6 +104,19 @@ func (ds *Server) GetBeaconStateV2(ctx context.Context, req *ethpbv2.BeaconState
ExecutionOptimistic: isOptimistic, ExecutionOptimistic: isOptimistic,
Finalized: isFinalized, Finalized: isFinalized,
}, nil }, nil
case version.Deneb:
protoState, err := migration.BeaconStateDenebToProto(beaconSt)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not convert state to proto: %v", err)
}
return &ethpbv2.BeaconStateResponseV2{
Version: ethpbv2.Version_Deneb,
Data: &ethpbv2.BeaconStateContainer{
State: &ethpbv2.BeaconStateContainer_DenebState{DenebState: protoState},
},
ExecutionOptimistic: isOptimistic,
}, nil
default: default:
return nil, status.Error(codes.Internal, "Unsupported state version") return nil, status.Error(codes.Internal, "Unsupported state version")
} }
@@ -114,7 +127,7 @@ func (ds *Server) GetBeaconStateSSZV2(ctx context.Context, req *ethpbv2.BeaconSt
ctx, span := trace.StartSpan(ctx, "debug.GetBeaconStateSSZV2") ctx, span := trace.StartSpan(ctx, "debug.GetBeaconStateSSZV2")
defer span.End() defer span.End()
st, err := ds.StateFetcher.State(ctx, req.StateId) st, err := ds.Stater.State(ctx, req.StateId)
if err != nil { if err != nil {
return nil, helpers.PrepareStateFetchGRPCError(err) return nil, helpers.PrepareStateFetchGRPCError(err)
} }
@@ -133,6 +146,8 @@ func (ds *Server) GetBeaconStateSSZV2(ctx context.Context, req *ethpbv2.BeaconSt
ver = ethpbv2.Version_BELLATRIX ver = ethpbv2.Version_BELLATRIX
case version.Capella: case version.Capella:
ver = ethpbv2.Version_CAPELLA ver = ethpbv2.Version_CAPELLA
case version.Deneb:
ver = ethpbv2.Version_Deneb
default: default:
return nil, status.Error(codes.Internal, "Unsupported state version") return nil, status.Error(codes.Internal, "Unsupported state version")
} }

View File

@@ -28,7 +28,7 @@ func TestGetBeaconStateV2(t *testing.T) {
fakeState, err := util.NewBeaconState() fakeState, err := util.NewBeaconState()
require.NoError(t, err) require.NoError(t, err)
server := &Server{ server := &Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: fakeState, BeaconState: fakeState,
}, },
HeadFetcher: &blockchainmock.ChainService{}, HeadFetcher: &blockchainmock.ChainService{},
@@ -46,7 +46,7 @@ func TestGetBeaconStateV2(t *testing.T) {
t.Run("Altair", func(t *testing.T) { t.Run("Altair", func(t *testing.T) {
fakeState, _ := util.DeterministicGenesisStateAltair(t, 1) fakeState, _ := util.DeterministicGenesisStateAltair(t, 1)
server := &Server{ server := &Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: fakeState, BeaconState: fakeState,
}, },
HeadFetcher: &blockchainmock.ChainService{}, HeadFetcher: &blockchainmock.ChainService{},
@@ -64,7 +64,7 @@ func TestGetBeaconStateV2(t *testing.T) {
t.Run("Bellatrix", func(t *testing.T) { t.Run("Bellatrix", func(t *testing.T) {
fakeState, _ := util.DeterministicGenesisStateBellatrix(t, 1) fakeState, _ := util.DeterministicGenesisStateBellatrix(t, 1)
server := &Server{ server := &Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: fakeState, BeaconState: fakeState,
}, },
HeadFetcher: &blockchainmock.ChainService{}, HeadFetcher: &blockchainmock.ChainService{},
@@ -82,7 +82,7 @@ func TestGetBeaconStateV2(t *testing.T) {
t.Run("Capella", func(t *testing.T) { t.Run("Capella", func(t *testing.T) {
fakeState, _ := util.DeterministicGenesisStateCapella(t, 1) fakeState, _ := util.DeterministicGenesisStateCapella(t, 1)
server := &Server{ server := &Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: fakeState, BeaconState: fakeState,
}, },
HeadFetcher: &blockchainmock.ChainService{}, HeadFetcher: &blockchainmock.ChainService{},
@@ -108,7 +108,7 @@ func TestGetBeaconStateV2(t *testing.T) {
fakeState, _ := util.DeterministicGenesisStateBellatrix(t, 1) fakeState, _ := util.DeterministicGenesisStateBellatrix(t, 1)
server := &Server{ server := &Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: fakeState, BeaconState: fakeState,
}, },
HeadFetcher: &blockchainmock.ChainService{}, HeadFetcher: &blockchainmock.ChainService{},
@@ -141,7 +141,7 @@ func TestGetBeaconStateV2(t *testing.T) {
}, },
} }
server := &Server{ server := &Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: fakeState, BeaconState: fakeState,
}, },
HeadFetcher: chainService, HeadFetcher: chainService,
@@ -165,7 +165,7 @@ func TestGetBeaconStateSSZ(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
server := &Server{ server := &Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: fakeState, BeaconState: fakeState,
}, },
} }
@@ -186,7 +186,7 @@ func TestGetBeaconStateSSZV2(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
server := &Server{ server := &Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: fakeState, BeaconState: fakeState,
}, },
} }
@@ -205,7 +205,7 @@ func TestGetBeaconStateSSZV2(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
server := &Server{ server := &Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: fakeState, BeaconState: fakeState,
}, },
} }
@@ -224,7 +224,7 @@ func TestGetBeaconStateSSZV2(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
server := &Server{ server := &Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: fakeState, BeaconState: fakeState,
}, },
} }
@@ -243,7 +243,7 @@ func TestGetBeaconStateSSZV2(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
server := &Server{ server := &Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
BeaconState: fakeState, BeaconState: fakeState,
}, },
} }

View File

@@ -6,7 +6,7 @@ package debug
import ( import (
"github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain" "github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/db" "github.com/prysmaticlabs/prysm/v4/beacon-chain/db"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/statefetcher" "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/lookup"
) )
// Server defines a server implementation of the gRPC Beacon Chain service, // Server defines a server implementation of the gRPC Beacon Chain service,
@@ -14,7 +14,7 @@ import (
type Server struct { type Server struct {
BeaconDB db.ReadOnlyDatabase BeaconDB db.ReadOnlyDatabase
HeadFetcher blockchain.HeadFetcher HeadFetcher blockchain.HeadFetcher
StateFetcher statefetcher.Fetcher Stater lookup.Stater
OptimisticModeFetcher blockchain.OptimisticModeFetcher OptimisticModeFetcher blockchain.OptimisticModeFetcher
ForkFetcher blockchain.ForkFetcher ForkFetcher blockchain.ForkFetcher
ForkchoiceFetcher blockchain.ForkchoiceFetcher ForkchoiceFetcher blockchain.ForkchoiceFetcher

View File

@@ -13,7 +13,7 @@ go_library(
"//api/grpc:go_default_library", "//api/grpc:go_default_library",
"//beacon-chain/blockchain:go_default_library", "//beacon-chain/blockchain:go_default_library",
"//beacon-chain/db:go_default_library", "//beacon-chain/db:go_default_library",
"//beacon-chain/rpc/statefetcher:go_default_library", "//beacon-chain/rpc/lookup:go_default_library",
"//beacon-chain/state:go_default_library", "//beacon-chain/state:go_default_library",
"//beacon-chain/state/stategen:go_default_library", "//beacon-chain/state/stategen:go_default_library",
"//beacon-chain/sync:go_default_library", "//beacon-chain/sync:go_default_library",

View File

@@ -3,7 +3,7 @@ package helpers
import ( import (
"errors" "errors"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/statefetcher" "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/lookup"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state/stategen" "github.com/prysmaticlabs/prysm/v4/beacon-chain/state/stategen"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
@@ -15,10 +15,10 @@ func PrepareStateFetchGRPCError(err error) error {
if errors.Is(err, stategen.ErrNoDataForSlot) { if errors.Is(err, stategen.ErrNoDataForSlot) {
return status.Errorf(codes.NotFound, "lacking historical data needed to fulfill request") return status.Errorf(codes.NotFound, "lacking historical data needed to fulfill request")
} }
if stateNotFoundErr, ok := err.(*statefetcher.StateNotFoundError); ok { if stateNotFoundErr, ok := err.(*lookup.StateNotFoundError); ok {
return status.Errorf(codes.NotFound, "State not found: %v", stateNotFoundErr) return status.Errorf(codes.NotFound, "State not found: %v", stateNotFoundErr)
} }
if parseErr, ok := err.(*statefetcher.StateIdParseError); ok { if parseErr, ok := err.(*lookup.StateIdParseError); ok {
return status.Errorf(codes.InvalidArgument, "Invalid state ID: %v", parseErr) return status.Errorf(codes.InvalidArgument, "Invalid state ID: %v", parseErr)
} }
return status.Errorf(codes.Internal, "Invalid state ID: %v", err) return status.Errorf(codes.Internal, "Invalid state ID: %v", err)

View File

@@ -9,7 +9,7 @@ import (
"github.com/prysmaticlabs/prysm/v4/api/grpc" "github.com/prysmaticlabs/prysm/v4/api/grpc"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain" "github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/db" "github.com/prysmaticlabs/prysm/v4/beacon-chain/db"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/statefetcher" "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/lookup"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/sync" "github.com/prysmaticlabs/prysm/v4/beacon-chain/sync"
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
@@ -61,7 +61,7 @@ func IsOptimistic(
ctx context.Context, ctx context.Context,
stateId []byte, stateId []byte,
optimisticModeFetcher blockchain.OptimisticModeFetcher, optimisticModeFetcher blockchain.OptimisticModeFetcher,
stateFetcher statefetcher.Fetcher, stateFetcher lookup.Stater,
chainInfo blockchain.ChainInfoFetcher, chainInfo blockchain.ChainInfoFetcher,
database db.ReadOnlyDatabase, database db.ReadOnlyDatabase,
) (bool, error) { ) (bool, error) {
@@ -97,7 +97,7 @@ func IsOptimistic(
slotNumber, parseErr := strconv.ParseUint(stateIdString, 10, 64) slotNumber, parseErr := strconv.ParseUint(stateIdString, 10, 64)
if parseErr != nil { if parseErr != nil {
// ID format does not match any valid options. // ID format does not match any valid options.
e := statefetcher.NewStateIdParseError(parseErr) e := lookup.NewStateIdParseError(parseErr)
return true, &e return true, &e
} }
fcp := chainInfo.FinalizedCheckpt() fcp := chainInfo.FinalizedCheckpt()
@@ -146,7 +146,7 @@ func isStateRootOptimistic(
ctx context.Context, ctx context.Context,
stateId []byte, stateId []byte,
optimisticModeFetcher blockchain.OptimisticModeFetcher, optimisticModeFetcher blockchain.OptimisticModeFetcher,
stateFetcher statefetcher.Fetcher, stateFetcher lookup.Stater,
chainInfo blockchain.ChainInfoFetcher, chainInfo blockchain.ChainInfoFetcher,
database db.ReadOnlyDatabase, database db.ReadOnlyDatabase,
) (bool, error) { ) (bool, error) {

View File

@@ -97,7 +97,7 @@ func TestIsOptimistic(t *testing.T) {
st, err := util.NewBeaconState() st, err := util.NewBeaconState()
require.NoError(t, err) require.NoError(t, err)
cs := &chainmock.ChainService{Optimistic: true, FinalizedCheckPoint: &eth.Checkpoint{}, OptimisticRoots: map[[32]byte]bool{[32]byte{}: true}} cs := &chainmock.ChainService{Optimistic: true, FinalizedCheckPoint: &eth.Checkpoint{}, OptimisticRoots: map[[32]byte]bool{[32]byte{}: true}}
mf := &testutil.MockFetcher{BeaconState: st} mf := &testutil.MockStater{BeaconState: st}
o, err := IsOptimistic(ctx, []byte("finalized"), cs, mf, cs, nil) o, err := IsOptimistic(ctx, []byte("finalized"), cs, mf, cs, nil)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, true, o) assert.Equal(t, true, o)
@@ -106,7 +106,7 @@ func TestIsOptimistic(t *testing.T) {
st, err := util.NewBeaconState() st, err := util.NewBeaconState()
require.NoError(t, err) require.NoError(t, err)
cs := &chainmock.ChainService{Optimistic: true, FinalizedCheckPoint: &eth.Checkpoint{}} cs := &chainmock.ChainService{Optimistic: true, FinalizedCheckPoint: &eth.Checkpoint{}}
mf := &testutil.MockFetcher{BeaconState: st} mf := &testutil.MockStater{BeaconState: st}
o, err := IsOptimistic(ctx, []byte("finalized"), cs, mf, cs, nil) o, err := IsOptimistic(ctx, []byte("finalized"), cs, mf, cs, nil)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, false, o) assert.Equal(t, false, o)
@@ -117,7 +117,7 @@ func TestIsOptimistic(t *testing.T) {
st, err := util.NewBeaconState() st, err := util.NewBeaconState()
require.NoError(t, err) require.NoError(t, err)
cs := &chainmock.ChainService{Optimistic: true, CurrentJustifiedCheckPoint: &eth.Checkpoint{}, OptimisticRoots: map[[32]byte]bool{[32]byte{}: true}} cs := &chainmock.ChainService{Optimistic: true, CurrentJustifiedCheckPoint: &eth.Checkpoint{}, OptimisticRoots: map[[32]byte]bool{[32]byte{}: true}}
mf := &testutil.MockFetcher{BeaconState: st} mf := &testutil.MockStater{BeaconState: st}
o, err := IsOptimistic(ctx, []byte("justified"), cs, mf, cs, nil) o, err := IsOptimistic(ctx, []byte("justified"), cs, mf, cs, nil)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, true, o) assert.Equal(t, true, o)
@@ -126,7 +126,7 @@ func TestIsOptimistic(t *testing.T) {
st, err := util.NewBeaconState() st, err := util.NewBeaconState()
require.NoError(t, err) require.NoError(t, err)
cs := &chainmock.ChainService{Optimistic: true, CurrentJustifiedCheckPoint: &eth.Checkpoint{}} cs := &chainmock.ChainService{Optimistic: true, CurrentJustifiedCheckPoint: &eth.Checkpoint{}}
mf := &testutil.MockFetcher{BeaconState: st} mf := &testutil.MockStater{BeaconState: st}
o, err := IsOptimistic(ctx, []byte("justified"), cs, mf, cs, nil) o, err := IsOptimistic(ctx, []byte("justified"), cs, mf, cs, nil)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, false, o) assert.Equal(t, false, o)
@@ -137,7 +137,7 @@ func TestIsOptimistic(t *testing.T) {
st, err := util.NewBeaconState() st, err := util.NewBeaconState()
require.NoError(t, err) require.NoError(t, err)
cs := &chainmock.ChainService{Optimistic: true} cs := &chainmock.ChainService{Optimistic: true}
mf := &testutil.MockFetcher{BeaconState: st} mf := &testutil.MockStater{BeaconState: st}
o, err := IsOptimistic(ctx, bytesutil.PadTo([]byte("root"), 32), cs, mf, cs, nil) o, err := IsOptimistic(ctx, bytesutil.PadTo([]byte("root"), 32), cs, mf, cs, nil)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, true, o) assert.Equal(t, true, o)
@@ -146,7 +146,7 @@ func TestIsOptimistic(t *testing.T) {
st, err := util.NewBeaconState() st, err := util.NewBeaconState()
require.NoError(t, err) require.NoError(t, err)
cs := &chainmock.ChainService{Optimistic: false} cs := &chainmock.ChainService{Optimistic: false}
mf := &testutil.MockFetcher{BeaconState: st} mf := &testutil.MockStater{BeaconState: st}
o, err := IsOptimistic(ctx, bytesutil.PadTo([]byte("root"), 32), cs, mf, cs, nil) o, err := IsOptimistic(ctx, bytesutil.PadTo([]byte("root"), 32), cs, mf, cs, nil)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, false, o) assert.Equal(t, false, o)
@@ -165,7 +165,7 @@ func TestIsOptimistic(t *testing.T) {
bRoot, err := b.Block().HashTreeRoot() bRoot, err := b.Block().HashTreeRoot()
require.NoError(t, err) require.NoError(t, err)
cs := &chainmock.ChainService{State: chainSt, OptimisticRoots: map[[32]byte]bool{bRoot: true}} cs := &chainmock.ChainService{State: chainSt, OptimisticRoots: map[[32]byte]bool{bRoot: true}}
mf := &testutil.MockFetcher{BeaconState: fetcherSt} mf := &testutil.MockStater{BeaconState: fetcherSt}
o, err := IsOptimistic(ctx, bytesutil.PadTo([]byte("root"), 32), cs, mf, cs, db) o, err := IsOptimistic(ctx, bytesutil.PadTo([]byte("root"), 32), cs, mf, cs, db)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, true, o) assert.Equal(t, true, o)
@@ -182,7 +182,7 @@ func TestIsOptimistic(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, chainSt.SetSlot(fieldparams.SlotsPerEpoch)) require.NoError(t, chainSt.SetSlot(fieldparams.SlotsPerEpoch))
cs := &chainmock.ChainService{State: chainSt} cs := &chainmock.ChainService{State: chainSt}
mf := &testutil.MockFetcher{BeaconState: fetcherSt} mf := &testutil.MockStater{BeaconState: fetcherSt}
o, err := IsOptimistic(ctx, bytesutil.PadTo([]byte("root"), 32), cs, mf, cs, db) o, err := IsOptimistic(ctx, bytesutil.PadTo([]byte("root"), 32), cs, mf, cs, db)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, false, o) assert.Equal(t, false, o)
@@ -198,7 +198,7 @@ func TestIsOptimistic(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, chainSt.SetSlot(fieldparams.SlotsPerEpoch)) require.NoError(t, chainSt.SetSlot(fieldparams.SlotsPerEpoch))
cs := &chainmock.ChainService{Optimistic: false, State: chainSt, CanonicalRoots: map[[32]byte]bool{}} cs := &chainmock.ChainService{Optimistic: false, State: chainSt, CanonicalRoots: map[[32]byte]bool{}}
mf := &testutil.MockFetcher{BeaconState: fetcherSt} mf := &testutil.MockStater{BeaconState: fetcherSt}
o, err := IsOptimistic(ctx, bytesutil.PadTo([]byte("root"), 32), nil, mf, cs, db) o, err := IsOptimistic(ctx, bytesutil.PadTo([]byte("root"), 32), nil, mf, cs, db)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, true, o) assert.Equal(t, true, o)
@@ -248,7 +248,7 @@ func TestIsOptimistic(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, chainSt.SetSlot(fieldparams.SlotsPerEpoch*2)) require.NoError(t, chainSt.SetSlot(fieldparams.SlotsPerEpoch*2))
cs := &chainmock.ChainService{Optimistic: true, State: chainSt, FinalizedCheckPoint: &eth.Checkpoint{Epoch: 0}} cs := &chainmock.ChainService{Optimistic: true, State: chainSt, FinalizedCheckPoint: &eth.Checkpoint{Epoch: 0}}
mf := &testutil.MockFetcher{BeaconState: fetcherSt} mf := &testutil.MockStater{BeaconState: fetcherSt}
o, err := IsOptimistic(ctx, []byte(strconv.Itoa(fieldparams.SlotsPerEpoch*2)), cs, mf, cs, db) o, err := IsOptimistic(ctx, []byte(strconv.Itoa(fieldparams.SlotsPerEpoch*2)), cs, mf, cs, db)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, true, o) assert.Equal(t, true, o)
@@ -268,7 +268,7 @@ func TestIsOptimistic(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, fcs.InsertNode(ctx, st, root)) require.NoError(t, fcs.InsertNode(ctx, st, root))
cs := &chainmock.ChainService{Root: headRoot[:], Optimistic: true, ForkChoiceStore: fcs, OptimisticRoots: map[[32]byte]bool{r: true}, FinalizedCheckPoint: finalizedCheckpt} cs := &chainmock.ChainService{Root: headRoot[:], Optimistic: true, ForkChoiceStore: fcs, OptimisticRoots: map[[32]byte]bool{r: true}, FinalizedCheckPoint: finalizedCheckpt}
mf := &testutil.MockFetcher{BeaconState: st} mf := &testutil.MockStater{BeaconState: st}
o, err := IsOptimistic(ctx, []byte(strconv.Itoa(fieldparams.SlotsPerEpoch*2)), cs, mf, cs, db) o, err := IsOptimistic(ctx, []byte(strconv.Itoa(fieldparams.SlotsPerEpoch*2)), cs, mf, cs, db)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, true, o) assert.Equal(t, true, o)
@@ -288,7 +288,7 @@ func TestIsOptimistic(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, fcs.InsertNode(ctx, st, root)) require.NoError(t, fcs.InsertNode(ctx, st, root))
cs := &chainmock.ChainService{Root: headRoot[:], Optimistic: true, ForkChoiceStore: fcs, OptimisticRoots: map[[32]byte]bool{r: false}, FinalizedCheckPoint: finalizedCheckpt} cs := &chainmock.ChainService{Root: headRoot[:], Optimistic: true, ForkChoiceStore: fcs, OptimisticRoots: map[[32]byte]bool{r: false}, FinalizedCheckPoint: finalizedCheckpt}
mf := &testutil.MockFetcher{BeaconState: st} mf := &testutil.MockStater{BeaconState: st}
o, err := IsOptimistic(ctx, []byte(strconv.Itoa(fieldparams.SlotsPerEpoch*2)), cs, mf, cs, db) o, err := IsOptimistic(ctx, []byte(strconv.Itoa(fieldparams.SlotsPerEpoch*2)), cs, mf, cs, db)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, false, o) assert.Equal(t, false, o)

View File

@@ -0,0 +1,52 @@
load("@prysm//tools/go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"handlers.go",
"server.go",
"structs.go",
],
importpath = "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/rewards",
visibility = ["//visibility:public"],
deps = [
"//beacon-chain/blockchain:go_default_library",
"//beacon-chain/core/altair:go_default_library",
"//beacon-chain/core/blocks:go_default_library",
"//beacon-chain/core/validators:go_default_library",
"//beacon-chain/rpc/lookup:go_default_library",
"//beacon-chain/state/stategen:go_default_library",
"//consensus-types/blocks:go_default_library",
"//consensus-types/interfaces:go_default_library",
"//network:go_default_library",
"//runtime/version:go_default_library",
"@com_github_pkg_errors//:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = ["handlers_test.go"],
embed = [":go_default_library"],
deps = [
"//beacon-chain/blockchain/testing:go_default_library",
"//beacon-chain/core/altair:go_default_library",
"//beacon-chain/core/signing:go_default_library",
"//beacon-chain/rpc/testutil:go_default_library",
"//beacon-chain/state/stategen/mock: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",
"//crypto/bls:go_default_library",
"//crypto/bls/blst:go_default_library",
"//encoding/bytesutil:go_default_library",
"//network:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//testing/assert:go_default_library",
"//testing/require:go_default_library",
"//testing/util:go_default_library",
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
],
)

View File

@@ -0,0 +1,189 @@
package rewards
import (
"net/http"
"strconv"
"strings"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/altair"
coreblocks "github.com/prysmaticlabs/prysm/v4/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/validators"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/lookup"
"github.com/prysmaticlabs/prysm/v4/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v4/consensus-types/interfaces"
"github.com/prysmaticlabs/prysm/v4/network"
"github.com/prysmaticlabs/prysm/v4/runtime/version"
)
// BlockRewards is an HTTP handler for Beacon API getBlockRewards.
func (s *Server) BlockRewards(w http.ResponseWriter, r *http.Request) {
segments := strings.Split(r.URL.Path, "/")
blockId := segments[len(segments)-1]
blk, err := s.Blocker.Block(r.Context(), []byte(blockId))
if errJson := handleGetBlockError(blk, err); errJson != nil {
network.WriteError(w, errJson)
return
}
if blk.Version() == version.Phase0 {
errJson := &network.DefaultErrorJson{
Message: "block rewards are not supported for Phase 0 blocks",
Code: http.StatusBadRequest,
}
network.WriteError(w, errJson)
return
}
// We want to run several block processing functions that update the proposer's balance.
// This will allow us to calculate proposer rewards for each operation (atts, slashings etc).
// To do this, we replay the state up to the block's slot, but before processing the block.
st, err := s.ReplayerBuilder.ReplayerForSlot(blk.Block().Slot()-1).ReplayToSlot(r.Context(), blk.Block().Slot())
if err != nil {
errJson := &network.DefaultErrorJson{
Message: errors.Wrapf(err, "could not get state").Error(),
Code: http.StatusInternalServerError,
}
network.WriteError(w, errJson)
return
}
proposerIndex := blk.Block().ProposerIndex()
initBalance, err := st.BalanceAtIndex(proposerIndex)
if err != nil {
errJson := &network.DefaultErrorJson{
Message: errors.Wrapf(err, "could not get proposer's balance").Error(),
Code: http.StatusInternalServerError,
}
network.WriteError(w, errJson)
return
}
st, err = altair.ProcessAttestationsNoVerifySignature(r.Context(), st, blk)
if err != nil {
errJson := &network.DefaultErrorJson{
Message: errors.Wrapf(err, "could not get attestation rewards").Error(),
Code: http.StatusInternalServerError,
}
network.WriteError(w, errJson)
return
}
attBalance, err := st.BalanceAtIndex(proposerIndex)
if err != nil {
errJson := &network.DefaultErrorJson{
Message: errors.Wrapf(err, "could not get proposer's balance").Error(),
Code: http.StatusInternalServerError,
}
network.WriteError(w, errJson)
return
}
st, err = coreblocks.ProcessAttesterSlashings(r.Context(), st, blk.Block().Body().AttesterSlashings(), validators.SlashValidator)
if err != nil {
errJson := &network.DefaultErrorJson{
Message: errors.Wrapf(err, "could not get attester slashing rewards").Error(),
Code: http.StatusInternalServerError,
}
network.WriteError(w, errJson)
return
}
attSlashingsBalance, err := st.BalanceAtIndex(proposerIndex)
if err != nil {
errJson := &network.DefaultErrorJson{
Message: errors.Wrapf(err, "could not get proposer's balance").Error(),
Code: http.StatusInternalServerError,
}
network.WriteError(w, errJson)
return
}
st, err = coreblocks.ProcessProposerSlashings(r.Context(), st, blk.Block().Body().ProposerSlashings(), validators.SlashValidator)
if err != nil {
errJson := &network.DefaultErrorJson{
Message: errors.Wrapf(err, "could not get proposer slashing rewards").Error(),
Code: http.StatusInternalServerError,
}
network.WriteError(w, errJson)
return
}
proposerSlashingsBalance, err := st.BalanceAtIndex(proposerIndex)
if err != nil {
errJson := &network.DefaultErrorJson{
Message: errors.Wrapf(err, "could not get proposer's balance").Error(),
Code: http.StatusInternalServerError,
}
network.WriteError(w, errJson)
return
}
sa, err := blk.Block().Body().SyncAggregate()
if err != nil {
errJson := &network.DefaultErrorJson{
Message: errors.Wrapf(err, "could not get sync aggregate").Error(),
Code: http.StatusInternalServerError,
}
network.WriteError(w, errJson)
return
}
var syncCommitteeReward uint64
_, syncCommitteeReward, err = altair.ProcessSyncAggregate(r.Context(), st, sa)
if err != nil {
errJson := &network.DefaultErrorJson{
Message: errors.Wrapf(err, "could not get sync aggregate rewards").Error(),
Code: http.StatusInternalServerError,
}
network.WriteError(w, errJson)
return
}
optimistic, err := s.OptimisticModeFetcher.IsOptimistic(r.Context())
if err != nil {
errJson := &network.DefaultErrorJson{
Message: errors.Wrapf(err, "could not get optimistic mode info").Error(),
Code: http.StatusInternalServerError,
}
network.WriteError(w, errJson)
return
}
blkRoot, err := blk.Block().HashTreeRoot()
if err != nil {
errJson := &network.DefaultErrorJson{
Message: errors.Wrapf(err, "could not get block root").Error(),
Code: http.StatusInternalServerError,
}
network.WriteError(w, errJson)
return
}
response := &BlockRewardsResponse{
Data: &BlockRewards{
ProposerIndex: strconv.FormatUint(uint64(proposerIndex), 10),
Total: strconv.FormatUint(proposerSlashingsBalance-initBalance+syncCommitteeReward, 10),
Attestations: strconv.FormatUint(attBalance-initBalance, 10),
SyncAggregate: strconv.FormatUint(syncCommitteeReward, 10),
ProposerSlashings: strconv.FormatUint(proposerSlashingsBalance-attSlashingsBalance, 10),
AttesterSlashings: strconv.FormatUint(attSlashingsBalance-attBalance, 10),
},
ExecutionOptimistic: optimistic,
Finalized: s.FinalizationFetcher.IsFinalized(r.Context(), blkRoot),
}
network.WriteJson(w, response)
}
func handleGetBlockError(blk interfaces.ReadOnlySignedBeaconBlock, err error) *network.DefaultErrorJson {
if errors.Is(err, lookup.BlockIdParseError{}) {
return &network.DefaultErrorJson{
Message: errors.Wrapf(err, "invalid block ID").Error(),
Code: http.StatusBadRequest,
}
}
if err != nil {
return &network.DefaultErrorJson{
Message: errors.Wrapf(err, "could not get block from block ID").Error(),
Code: http.StatusInternalServerError,
}
}
if err := blocks.BeaconBlockIsNil(blk); err != nil {
return &network.DefaultErrorJson{
Message: errors.Wrapf(err, "could not find requested block").Error(),
Code: http.StatusNotFound,
}
}
return nil
}

View File

@@ -0,0 +1,198 @@
package rewards
import (
"bytes"
"context"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"github.com/prysmaticlabs/go-bitfield"
mock "github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain/testing"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/altair"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/signing"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/testutil"
mockstategen "github.com/prysmaticlabs/prysm/v4/beacon-chain/state/stategen/mock"
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
"github.com/prysmaticlabs/prysm/v4/config/params"
"github.com/prysmaticlabs/prysm/v4/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v4/consensus-types/interfaces"
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v4/crypto/bls"
"github.com/prysmaticlabs/prysm/v4/crypto/bls/blst"
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/v4/network"
eth "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v4/testing/assert"
"github.com/prysmaticlabs/prysm/v4/testing/require"
"github.com/prysmaticlabs/prysm/v4/testing/util"
)
func TestBlockRewards(t *testing.T) {
valCount := 64
st, err := util.NewBeaconStateAltair()
require.NoError(t, st.SetSlot(1))
require.NoError(t, err)
validators := make([]*eth.Validator, 0, valCount)
balances := make([]uint64, 0, valCount)
secretKeys := make([]bls.SecretKey, 0, valCount)
for i := 0; i < valCount; i++ {
blsKey, err := bls.RandKey()
require.NoError(t, err)
secretKeys = append(secretKeys, blsKey)
validators = append(validators, &eth.Validator{
PublicKey: blsKey.PublicKey().Marshal(),
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
WithdrawableEpoch: params.BeaconConfig().FarFutureEpoch,
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
})
balances = append(balances, params.BeaconConfig().MaxEffectiveBalance)
}
require.NoError(t, st.SetValidators(validators))
require.NoError(t, st.SetBalances(balances))
require.NoError(t, st.SetCurrentParticipationBits(make([]byte, valCount)))
syncCommittee, err := altair.NextSyncCommittee(context.Background(), st)
require.NoError(t, err)
require.NoError(t, st.SetCurrentSyncCommittee(syncCommittee))
slot0bRoot := bytesutil.PadTo([]byte("slot0root"), 32)
bRoots := make([][]byte, fieldparams.BlockRootsLength)
bRoots[0] = slot0bRoot
require.NoError(t, st.SetBlockRoots(bRoots))
b := util.HydrateSignedBeaconBlockAltair(util.NewBeaconBlockAltair())
b.Block.Slot = 2
// we have to set the proposer index to the value that will be randomly chosen (fortunately it's deterministic)
b.Block.ProposerIndex = 12
b.Block.Body.Attestations = []*eth.Attestation{
{
AggregationBits: bitfield.Bitlist{0b00000111},
Data: util.HydrateAttestationData(&eth.AttestationData{}),
Signature: make([]byte, fieldparams.BLSSignatureLength),
},
{
AggregationBits: bitfield.Bitlist{0b00000111},
Data: util.HydrateAttestationData(&eth.AttestationData{}),
Signature: make([]byte, fieldparams.BLSSignatureLength),
},
}
attData1 := util.HydrateAttestationData(&eth.AttestationData{BeaconBlockRoot: bytesutil.PadTo([]byte("root1"), 32)})
attData2 := util.HydrateAttestationData(&eth.AttestationData{BeaconBlockRoot: bytesutil.PadTo([]byte("root2"), 32)})
domain, err := signing.Domain(st.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, st.GenesisValidatorsRoot())
require.NoError(t, err)
sigRoot1, err := signing.ComputeSigningRoot(attData1, domain)
require.NoError(t, err)
sigRoot2, err := signing.ComputeSigningRoot(attData2, domain)
require.NoError(t, err)
b.Block.Body.AttesterSlashings = []*eth.AttesterSlashing{
{
Attestation_1: &eth.IndexedAttestation{
AttestingIndices: []uint64{0},
Data: attData1,
Signature: secretKeys[0].Sign(sigRoot1[:]).Marshal(),
},
Attestation_2: &eth.IndexedAttestation{
AttestingIndices: []uint64{0},
Data: attData2,
Signature: secretKeys[0].Sign(sigRoot2[:]).Marshal(),
},
},
}
header1 := &eth.BeaconBlockHeader{
Slot: 0,
ProposerIndex: 1,
ParentRoot: bytesutil.PadTo([]byte("root1"), 32),
StateRoot: bytesutil.PadTo([]byte("root1"), 32),
BodyRoot: bytesutil.PadTo([]byte("root1"), 32),
}
header2 := &eth.BeaconBlockHeader{
Slot: 0,
ProposerIndex: 1,
ParentRoot: bytesutil.PadTo([]byte("root2"), 32),
StateRoot: bytesutil.PadTo([]byte("root2"), 32),
BodyRoot: bytesutil.PadTo([]byte("root2"), 32),
}
domain, err = signing.Domain(st.Fork(), 0, params.BeaconConfig().DomainBeaconProposer, st.GenesisValidatorsRoot())
require.NoError(t, err)
sigRoot1, err = signing.ComputeSigningRoot(header1, domain)
require.NoError(t, err)
sigRoot2, err = signing.ComputeSigningRoot(header2, domain)
require.NoError(t, err)
b.Block.Body.ProposerSlashings = []*eth.ProposerSlashing{
{
Header_1: &eth.SignedBeaconBlockHeader{
Header: header1,
Signature: secretKeys[1].Sign(sigRoot1[:]).Marshal(),
},
Header_2: &eth.SignedBeaconBlockHeader{
Header: header2,
Signature: secretKeys[1].Sign(sigRoot2[:]).Marshal(),
},
},
}
scBits := bitfield.NewBitvector512()
scBits.SetBitAt(10, true)
scBits.SetBitAt(100, true)
domain, err = signing.Domain(st.Fork(), 0, params.BeaconConfig().DomainSyncCommittee, st.GenesisValidatorsRoot())
require.NoError(t, err)
sszBytes := primitives.SSZBytes(slot0bRoot)
r, err := signing.ComputeSigningRoot(&sszBytes, domain)
require.NoError(t, err)
// Bits set in sync committee bits determine which validators will be treated as participating in sync committee.
// These validators have to sign the message.
sig1, err := blst.SignatureFromBytes(secretKeys[47].Sign(r[:]).Marshal())
require.NoError(t, err)
sig2, err := blst.SignatureFromBytes(secretKeys[19].Sign(r[:]).Marshal())
require.NoError(t, err)
aggSig := bls.AggregateSignatures([]bls.Signature{sig1, sig2}).Marshal()
b.Block.Body.SyncAggregate = &eth.SyncAggregate{SyncCommitteeBits: scBits, SyncCommitteeSignature: aggSig}
sbb, err := blocks.NewSignedBeaconBlock(b)
require.NoError(t, err)
phase0block, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlock())
require.NoError(t, err)
mockChainService := &mock.ChainService{Optimistic: true}
s := &Server{
Blocker: &testutil.MockBlocker{SlotBlockMap: map[primitives.Slot]interfaces.ReadOnlySignedBeaconBlock{
0: phase0block,
2: sbb,
}},
OptimisticModeFetcher: mockChainService,
FinalizationFetcher: mockChainService,
ReplayerBuilder: mockstategen.NewMockReplayerBuilder(mockstategen.WithMockState(st)),
}
t.Run("ok", func(t *testing.T) {
url := "http://only.the.slot.number.at.the.end.is.important/2"
request := httptest.NewRequest("GET", url, nil)
writer := httptest.NewRecorder()
writer.Body = &bytes.Buffer{}
s.BlockRewards(writer, request)
assert.Equal(t, http.StatusOK, writer.Code)
resp := &BlockRewardsResponse{}
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
assert.Equal(t, "12", resp.Data.ProposerIndex)
assert.Equal(t, "125089490", resp.Data.Total)
assert.Equal(t, "89442", resp.Data.Attestations)
assert.Equal(t, "48", resp.Data.SyncAggregate)
assert.Equal(t, "62500000", resp.Data.AttesterSlashings)
assert.Equal(t, "62500000", resp.Data.ProposerSlashings)
assert.Equal(t, true, resp.ExecutionOptimistic)
assert.Equal(t, false, resp.Finalized)
})
t.Run("phase 0", func(t *testing.T) {
url := "http://only.the.slot.number.at.the.end.is.important/0"
request := httptest.NewRequest("GET", url, nil)
writer := httptest.NewRecorder()
writer.Body = &bytes.Buffer{}
s.BlockRewards(writer, request)
assert.Equal(t, http.StatusBadRequest, writer.Code)
e := &network.DefaultErrorJson{}
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e))
assert.Equal(t, http.StatusBadRequest, e.Code)
assert.Equal(t, "block rewards are not supported for Phase 0 blocks", e.Message)
})
}

View File

@@ -0,0 +1,14 @@
package rewards
import (
"github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/lookup"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state/stategen"
)
type Server struct {
Blocker lookup.Blocker
OptimisticModeFetcher blockchain.OptimisticModeFetcher
FinalizationFetcher blockchain.FinalizationFetcher
ReplayerBuilder stategen.ReplayerBuilder
}

View File

@@ -0,0 +1,16 @@
package rewards
type BlockRewardsResponse struct {
Data *BlockRewards `json:"data"`
ExecutionOptimistic bool `json:"execution_optimistic"`
Finalized bool `json:"finalized"`
}
type BlockRewards struct {
ProposerIndex string `json:"proposer_index"`
Total string `json:"total"`
Attestations string `json:"attestations"`
SyncAggregate string `json:"sync_aggregate"`
ProposerSlashings string `json:"proposer_slashings"`
AttesterSlashings string `json:"attester_slashings"`
}

View File

@@ -16,11 +16,12 @@ go_library(
"//beacon-chain/db:go_default_library", "//beacon-chain/db:go_default_library",
"//beacon-chain/db/kv:go_default_library", "//beacon-chain/db/kv:go_default_library",
"//beacon-chain/operations/attestations:go_default_library", "//beacon-chain/operations/attestations:go_default_library",
"//beacon-chain/operations/blstoexec:go_default_library",
"//beacon-chain/operations/synccommittee:go_default_library", "//beacon-chain/operations/synccommittee:go_default_library",
"//beacon-chain/p2p:go_default_library", "//beacon-chain/p2p:go_default_library",
"//beacon-chain/rpc/eth/helpers:go_default_library", "//beacon-chain/rpc/eth/helpers:go_default_library",
"//beacon-chain/rpc/lookup:go_default_library",
"//beacon-chain/rpc/prysm/v1alpha1/validator:go_default_library", "//beacon-chain/rpc/prysm/v1alpha1/validator:go_default_library",
"//beacon-chain/rpc/statefetcher:go_default_library",
"//beacon-chain/state:go_default_library", "//beacon-chain/state:go_default_library",
"//beacon-chain/state/state-native:go_default_library", "//beacon-chain/state/state-native:go_default_library",
"//beacon-chain/sync:go_default_library", "//beacon-chain/sync:go_default_library",

View File

@@ -5,10 +5,11 @@ import (
"github.com/prysmaticlabs/prysm/v4/beacon-chain/cache" "github.com/prysmaticlabs/prysm/v4/beacon-chain/cache"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/db" "github.com/prysmaticlabs/prysm/v4/beacon-chain/db"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/operations/attestations" "github.com/prysmaticlabs/prysm/v4/beacon-chain/operations/attestations"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/operations/blstoexec"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/operations/synccommittee" "github.com/prysmaticlabs/prysm/v4/beacon-chain/operations/synccommittee"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/p2p" "github.com/prysmaticlabs/prysm/v4/beacon-chain/p2p"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/lookup"
v1alpha1validator "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/prysm/v1alpha1/validator" v1alpha1validator "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/prysm/v1alpha1/validator"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/statefetcher"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/sync" "github.com/prysmaticlabs/prysm/v4/beacon-chain/sync"
) )
@@ -21,9 +22,10 @@ type Server struct {
AttestationsPool attestations.Pool AttestationsPool attestations.Pool
PeerManager p2p.PeerManager PeerManager p2p.PeerManager
Broadcaster p2p.Broadcaster Broadcaster p2p.Broadcaster
StateFetcher statefetcher.Fetcher Stater lookup.Stater
OptimisticModeFetcher blockchain.OptimisticModeFetcher OptimisticModeFetcher blockchain.OptimisticModeFetcher
SyncCommitteePool synccommittee.Pool SyncCommitteePool synccommittee.Pool
BLSChangesPool blstoexec.PoolManager
V1Alpha1Server *v1alpha1validator.Server V1Alpha1Server *v1alpha1validator.Server
ProposerSlotIndexCache *cache.ProposerPayloadIDsCache ProposerSlotIndexCache *cache.ProposerPayloadIDsCache
ChainInfoFetcher blockchain.ChainInfoFetcher ChainInfoFetcher blockchain.ChainInfoFetcher

View File

@@ -70,7 +70,7 @@ func (vs *Server) GetAttesterDuties(ctx context.Context, req *ethpbv1.AttesterDu
return nil, status.Errorf(codes.Internal, "Could not get start slot from epoch %d: %v", req.Epoch, err) return nil, status.Errorf(codes.Internal, "Could not get start slot from epoch %d: %v", req.Epoch, err)
} }
s, err := vs.StateFetcher.StateBySlot(ctx, startSlot) s, err := vs.Stater.StateBySlot(ctx, startSlot)
if err != nil { if err != nil {
return nil, status.Errorf(codes.Internal, "Could not get state: %v", err) return nil, status.Errorf(codes.Internal, "Could not get state: %v", err)
} }
@@ -159,7 +159,7 @@ func (vs *Server) GetProposerDuties(ctx context.Context, req *ethpbv1.ProposerDu
if err != nil { if err != nil {
return nil, status.Errorf(codes.Internal, "Could not get start slot from epoch %d: %v", req.Epoch, err) return nil, status.Errorf(codes.Internal, "Could not get start slot from epoch %d: %v", req.Epoch, err)
} }
s, err := vs.StateFetcher.StateBySlot(ctx, startSlot) s, err := vs.Stater.StateBySlot(ctx, startSlot)
if err != nil { if err != nil {
return nil, status.Errorf(codes.Internal, "Could not get state: %v", err) return nil, status.Errorf(codes.Internal, "Could not get state: %v", err)
} }
@@ -243,7 +243,7 @@ func (vs *Server) GetSyncCommitteeDuties(ctx context.Context, req *ethpbv2.SyncC
if err != nil { if err != nil {
return nil, status.Errorf(codes.Internal, "Could not get sync committee slot: %v", err) return nil, status.Errorf(codes.Internal, "Could not get sync committee slot: %v", err)
} }
st, err := vs.StateFetcher.State(ctx, []byte(strconv.FormatUint(uint64(slot), 10))) st, err := vs.Stater.State(ctx, []byte(strconv.FormatUint(uint64(slot), 10)))
if err != nil { if err != nil {
return nil, status.Errorf(codes.Internal, "Could not get sync committee state: %v", err) return nil, status.Errorf(codes.Internal, "Could not get sync committee state: %v", err)
} }
@@ -282,7 +282,7 @@ func (vs *Server) GetSyncCommitteeDuties(ctx context.Context, req *ethpbv2.SyncC
ctx, ctx,
[]byte(strconv.FormatUint(uint64(slot), 10)), []byte(strconv.FormatUint(uint64(slot), 10)),
vs.OptimisticModeFetcher, vs.OptimisticModeFetcher,
vs.StateFetcher, vs.Stater,
vs.ChainInfoFetcher, vs.ChainInfoFetcher,
vs.BeaconDB, vs.BeaconDB,
) )
@@ -1081,7 +1081,7 @@ func (vs *Server) GetLiveness(ctx context.Context, req *ethpbv2.GetLivenessReque
if err != nil { if err != nil {
return nil, status.Error(codes.Internal, "Could not get requested epoch's end slot") return nil, status.Error(codes.Internal, "Could not get requested epoch's end slot")
} }
st, err = vs.StateFetcher.StateBySlot(ctx, epochEnd) st, err = vs.Stater.StateBySlot(ctx, epochEnd)
if err != nil { if err != nil {
return nil, status.Error(codes.Internal, "Could not get slot for requested epoch") return nil, status.Error(codes.Internal, "Could not get slot for requested epoch")
} }

View File

@@ -93,7 +93,7 @@ func TestGetAttesterDuties(t *testing.T) {
State: bs, Root: genesisRoot[:], Slot: &chainSlot, State: bs, Root: genesisRoot[:], Slot: &chainSlot,
} }
vs := &Server{ vs := &Server{
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
StatesBySlot: map[primitives.Slot]state.BeaconState{ StatesBySlot: map[primitives.Slot]state.BeaconState{
0: bs, 0: bs,
params.BeaconConfig().SlotsPerEpoch: nextEpochState, params.BeaconConfig().SlotsPerEpoch: nextEpochState,
@@ -198,7 +198,7 @@ func TestGetAttesterDuties(t *testing.T) {
State: bs, Root: genesisRoot[:], Slot: &chainSlot, Optimistic: true, State: bs, Root: genesisRoot[:], Slot: &chainSlot, Optimistic: true,
} }
vs := &Server{ vs := &Server{
StateFetcher: &testutil.MockFetcher{StatesBySlot: map[primitives.Slot]state.BeaconState{0: bs}}, Stater: &testutil.MockStater{StatesBySlot: map[primitives.Slot]state.BeaconState{0: bs}},
TimeFetcher: chain, TimeFetcher: chain,
OptimisticModeFetcher: chain, OptimisticModeFetcher: chain,
SyncChecker: &mockSync.Sync{IsSyncing: false}, SyncChecker: &mockSync.Sync{IsSyncing: false},
@@ -258,7 +258,7 @@ func TestGetProposerDuties(t *testing.T) {
State: bs, Root: genesisRoot[:], Slot: &chainSlot, State: bs, Root: genesisRoot[:], Slot: &chainSlot,
} }
vs := &Server{ vs := &Server{
StateFetcher: &testutil.MockFetcher{StatesBySlot: map[primitives.Slot]state.BeaconState{0: bs}}, Stater: &testutil.MockStater{StatesBySlot: map[primitives.Slot]state.BeaconState{0: bs}},
HeadFetcher: chain, HeadFetcher: chain,
TimeFetcher: chain, TimeFetcher: chain,
OptimisticModeFetcher: chain, OptimisticModeFetcher: chain,
@@ -297,7 +297,7 @@ func TestGetProposerDuties(t *testing.T) {
State: bs, Root: genesisRoot[:], Slot: &chainSlot, State: bs, Root: genesisRoot[:], Slot: &chainSlot,
} }
vs := &Server{ vs := &Server{
StateFetcher: &testutil.MockFetcher{StatesBySlot: map[primitives.Slot]state.BeaconState{0: bs}}, Stater: &testutil.MockStater{StatesBySlot: map[primitives.Slot]state.BeaconState{0: bs}},
HeadFetcher: chain, HeadFetcher: chain,
TimeFetcher: chain, TimeFetcher: chain,
OptimisticModeFetcher: chain, OptimisticModeFetcher: chain,
@@ -337,7 +337,7 @@ func TestGetProposerDuties(t *testing.T) {
State: bs, Root: genesisRoot[:], Slot: &chainSlot, State: bs, Root: genesisRoot[:], Slot: &chainSlot,
} }
vs := &Server{ vs := &Server{
StateFetcher: &testutil.MockFetcher{StatesBySlot: map[primitives.Slot]state.BeaconState{params.BeaconConfig().SlotsPerEpoch: bs}}, Stater: &testutil.MockStater{StatesBySlot: map[primitives.Slot]state.BeaconState{params.BeaconConfig().SlotsPerEpoch: bs}},
HeadFetcher: chain, HeadFetcher: chain,
TimeFetcher: chain, TimeFetcher: chain,
OptimisticModeFetcher: chain, OptimisticModeFetcher: chain,
@@ -377,7 +377,7 @@ func TestGetProposerDuties(t *testing.T) {
State: bs, Root: genesisRoot[:], Slot: &chainSlot, State: bs, Root: genesisRoot[:], Slot: &chainSlot,
} }
vs := &Server{ vs := &Server{
StateFetcher: &testutil.MockFetcher{StatesBySlot: map[primitives.Slot]state.BeaconState{0: bs}}, Stater: &testutil.MockStater{StatesBySlot: map[primitives.Slot]state.BeaconState{0: bs}},
HeadFetcher: chain, HeadFetcher: chain,
TimeFetcher: chain, TimeFetcher: chain,
OptimisticModeFetcher: chain, OptimisticModeFetcher: chain,
@@ -414,7 +414,7 @@ func TestGetProposerDuties(t *testing.T) {
State: bs, Root: genesisRoot[:], Slot: &chainSlot, Optimistic: true, State: bs, Root: genesisRoot[:], Slot: &chainSlot, Optimistic: true,
} }
vs := &Server{ vs := &Server{
StateFetcher: &testutil.MockFetcher{StatesBySlot: map[primitives.Slot]state.BeaconState{0: bs}}, Stater: &testutil.MockStater{StatesBySlot: map[primitives.Slot]state.BeaconState{0: bs}},
HeadFetcher: chain, HeadFetcher: chain,
TimeFetcher: chain, TimeFetcher: chain,
OptimisticModeFetcher: chain, OptimisticModeFetcher: chain,
@@ -469,7 +469,7 @@ func TestGetSyncCommitteeDuties(t *testing.T) {
mockChainService := &mockChain.ChainService{Genesis: genesisTime} mockChainService := &mockChain.ChainService{Genesis: genesisTime}
vs := &Server{ vs := &Server{
StateFetcher: &testutil.MockFetcher{BeaconState: st}, Stater: &testutil.MockStater{BeaconState: st},
SyncChecker: &mockSync.Sync{IsSyncing: false}, SyncChecker: &mockSync.Sync{IsSyncing: false},
TimeFetcher: mockChainService, TimeFetcher: mockChainService,
HeadFetcher: mockChainService, HeadFetcher: mockChainService,
@@ -611,7 +611,7 @@ func TestGetSyncCommitteeDuties(t *testing.T) {
} }
mockChainService := &mockChain.ChainService{Genesis: genesisTime, Slot: &newSyncPeriodStartSlot} mockChainService := &mockChain.ChainService{Genesis: genesisTime, Slot: &newSyncPeriodStartSlot}
vs := &Server{ vs := &Server{
StateFetcher: &testutil.MockFetcher{BeaconState: stateFetchFn(newSyncPeriodStartSlot)}, Stater: &testutil.MockStater{BeaconState: stateFetchFn(newSyncPeriodStartSlot)},
SyncChecker: &mockSync.Sync{IsSyncing: false}, SyncChecker: &mockSync.Sync{IsSyncing: false},
TimeFetcher: mockChainService, TimeFetcher: mockChainService,
HeadFetcher: mockChainService, HeadFetcher: mockChainService,
@@ -665,7 +665,7 @@ func TestGetSyncCommitteeDuties(t *testing.T) {
State: state, State: state,
} }
vs := &Server{ vs := &Server{
StateFetcher: &testutil.MockFetcher{BeaconState: st}, Stater: &testutil.MockStater{BeaconState: st},
SyncChecker: &mockSync.Sync{IsSyncing: false}, SyncChecker: &mockSync.Sync{IsSyncing: false},
TimeFetcher: mockChainService, TimeFetcher: mockChainService,
HeadFetcher: mockChainService, HeadFetcher: mockChainService,
@@ -5021,7 +5021,7 @@ func TestGetLiveness(t *testing.T) {
server := &Server{ server := &Server{
HeadFetcher: &mockChain.ChainService{State: headSt}, HeadFetcher: &mockChain.ChainService{State: headSt},
StateFetcher: &testutil.MockFetcher{ Stater: &testutil.MockStater{
// We configure states for last slots of an epoch // We configure states for last slots of an epoch
StatesBySlot: map[primitives.Slot]state.BeaconState{ StatesBySlot: map[primitives.Slot]state.BeaconState{
params.BeaconConfig().SlotsPerEpoch - 1: oldSt, params.BeaconConfig().SlotsPerEpoch - 1: oldSt,

View File

@@ -2,9 +2,12 @@ load("@prysm//tools/go:def.bzl", "go_library", "go_test")
go_library( go_library(
name = "go_default_library", name = "go_default_library",
srcs = ["fetcher.go"], srcs = [
importpath = "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/statefetcher", "blocker.go",
visibility = ["//beacon-chain:__subpackages__"], "stater.go",
],
importpath = "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/lookup",
visibility = ["//visibility:public"],
deps = [ deps = [
"//beacon-chain/blockchain:go_default_library", "//beacon-chain/blockchain:go_default_library",
"//beacon-chain/db:go_default_library", "//beacon-chain/db:go_default_library",
@@ -12,6 +15,7 @@ go_library(
"//beacon-chain/state/stategen:go_default_library", "//beacon-chain/state/stategen:go_default_library",
"//config/params:go_default_library", "//config/params:go_default_library",
"//consensus-types/blocks:go_default_library", "//consensus-types/blocks:go_default_library",
"//consensus-types/interfaces:go_default_library",
"//consensus-types/primitives:go_default_library", "//consensus-types/primitives:go_default_library",
"//encoding/bytesutil:go_default_library", "//encoding/bytesutil:go_default_library",
"//time/slots:go_default_library", "//time/slots:go_default_library",
@@ -22,11 +26,15 @@ go_library(
go_test( go_test(
name = "go_default_test", name = "go_default_test",
srcs = ["fetcher_test.go"], srcs = [
"blocker_test.go",
"stater_test.go",
],
embed = [":go_default_library"], embed = [":go_default_library"],
deps = [ deps = [
"//beacon-chain/blockchain/testing:go_default_library", "//beacon-chain/blockchain/testing:go_default_library",
"//beacon-chain/db/testing:go_default_library", "//beacon-chain/db/testing:go_default_library",
"//beacon-chain/rpc/testutil:go_default_library",
"//beacon-chain/state/state-native:go_default_library", "//beacon-chain/state/state-native:go_default_library",
"//beacon-chain/state/stategen:go_default_library", "//beacon-chain/state/stategen:go_default_library",
"//beacon-chain/state/stategen/mock:go_default_library", "//beacon-chain/state/stategen/mock:go_default_library",

View File

@@ -0,0 +1,108 @@
package lookup
import (
"context"
"strconv"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/db"
"github.com/prysmaticlabs/prysm/v4/consensus-types/interfaces"
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
)
// BlockIdParseError represents an error scenario where a block ID could not be parsed.
type BlockIdParseError struct {
message string
}
// NewBlockIdParseError creates a new error instance.
func NewBlockIdParseError(reason error) BlockIdParseError {
return BlockIdParseError{
message: errors.Wrapf(reason, "could not parse block ID").Error(),
}
}
// Error returns the underlying error message.
func (e BlockIdParseError) Error() string {
return e.message
}
// Blocker is responsible for retrieving blocks.
type Blocker interface {
Block(ctx context.Context, id []byte) (interfaces.ReadOnlySignedBeaconBlock, error)
}
// BeaconDbBlocker is an implementation of Blocker. It retrieves blocks from the beacon chain database.
type BeaconDbBlocker struct {
BeaconDB db.ReadOnlyDatabase
ChainInfoFetcher blockchain.ChainInfoFetcher
}
// Block returns the beacon block for a given identifier. The identifier can be one of:
// - "head" (canonical head in node's view)
// - "genesis"
// - "finalized"
// - "justified"
// - <slot>
// - <hex encoded block root with '0x' prefix>
func (p *BeaconDbBlocker) Block(ctx context.Context, id []byte) (interfaces.ReadOnlySignedBeaconBlock, error) {
var err error
var blk interfaces.ReadOnlySignedBeaconBlock
switch string(id) {
case "head":
blk, err = p.ChainInfoFetcher.HeadBlock(ctx)
if err != nil {
return nil, errors.Wrap(err, "could not retrieve head block")
}
case "finalized":
finalized := p.ChainInfoFetcher.FinalizedCheckpt()
finalizedRoot := bytesutil.ToBytes32(finalized.Root)
blk, err = p.BeaconDB.Block(ctx, finalizedRoot)
if err != nil {
return nil, errors.New("could not get finalized block from db")
}
case "genesis":
blk, err = p.BeaconDB.GenesisBlock(ctx)
if err != nil {
return nil, errors.Wrap(err, "could not retrieve genesis block")
}
default:
if len(id) == 32 {
blk, err = p.BeaconDB.Block(ctx, bytesutil.ToBytes32(id))
if err != nil {
return nil, errors.Wrap(err, "could not retrieve block")
}
} else {
slot, err := strconv.ParseUint(string(id), 10, 64)
if err != nil {
e := NewBlockIdParseError(err)
return nil, &e
}
blks, err := p.BeaconDB.BlocksBySlot(ctx, primitives.Slot(slot))
if err != nil {
return nil, errors.Wrapf(err, "could not retrieve blocks for slot %d", slot)
}
_, roots, err := p.BeaconDB.BlockRootsBySlot(ctx, primitives.Slot(slot))
if err != nil {
return nil, errors.Wrapf(err, "could not retrieve block roots for slot %d", slot)
}
numBlks := len(blks)
if numBlks == 0 {
return nil, nil
}
for i, b := range blks {
canonical, err := p.ChainInfoFetcher.IsCanonical(ctx, roots[i])
if err != nil {
return nil, errors.Wrapf(err, "could not determine if block root is canonical")
}
if canonical {
blk = b
break
}
}
}
}
return blk, nil
}

View File

@@ -0,0 +1,144 @@
package lookup
import (
"context"
"fmt"
"reflect"
"testing"
mock "github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain/testing"
dbtesting "github.com/prysmaticlabs/prysm/v4/beacon-chain/db/testing"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/testutil"
"github.com/prysmaticlabs/prysm/v4/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
ethpbalpha "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v4/testing/assert"
"github.com/prysmaticlabs/prysm/v4/testing/require"
"github.com/prysmaticlabs/prysm/v4/testing/util"
)
func TestGetBlock(t *testing.T) {
beaconDB := dbtesting.SetupDB(t)
ctx := context.Background()
genBlk, blkContainers := testutil.FillDBWithBlocks(ctx, t, beaconDB)
canonicalRoots := make(map[[32]byte]bool)
for _, bContr := range blkContainers {
canonicalRoots[bytesutil.ToBytes32(bContr.BlockRoot)] = true
}
headBlock := blkContainers[len(blkContainers)-1]
nextSlot := headBlock.GetPhase0Block().Block.Slot + 1
b2 := util.NewBeaconBlock()
b2.Block.Slot = 30
b2.Block.ParentRoot = bytesutil.PadTo([]byte{1}, 32)
util.SaveBlock(t, ctx, beaconDB, b2)
b3 := util.NewBeaconBlock()
b3.Block.Slot = 30
b3.Block.ParentRoot = bytesutil.PadTo([]byte{4}, 32)
util.SaveBlock(t, ctx, beaconDB, b3)
b4 := util.NewBeaconBlock()
b4.Block.Slot = nextSlot
b4.Block.ParentRoot = bytesutil.PadTo([]byte{8}, 32)
util.SaveBlock(t, ctx, beaconDB, b4)
wsb, err := blocks.NewSignedBeaconBlock(headBlock.Block.(*ethpbalpha.BeaconBlockContainer_Phase0Block).Phase0Block)
require.NoError(t, err)
fetcher := &BeaconDbBlocker{
BeaconDB: beaconDB,
ChainInfoFetcher: &mock.ChainService{
DB: beaconDB,
Block: wsb,
Root: headBlock.BlockRoot,
FinalizedCheckPoint: &ethpbalpha.Checkpoint{Root: blkContainers[64].BlockRoot},
CanonicalRoots: canonicalRoots,
},
}
root, err := genBlk.Block.HashTreeRoot()
require.NoError(t, err)
tests := []struct {
name string
blockID []byte
want *ethpbalpha.SignedBeaconBlock
wantErr bool
}{
{
name: "slot",
blockID: []byte("30"),
want: blkContainers[30].Block.(*ethpbalpha.BeaconBlockContainer_Phase0Block).Phase0Block,
},
{
name: "bad formatting",
blockID: []byte("3bad0"),
wantErr: true,
},
{
name: "canonical",
blockID: []byte("30"),
want: blkContainers[30].Block.(*ethpbalpha.BeaconBlockContainer_Phase0Block).Phase0Block,
},
{
name: "non canonical",
blockID: []byte(fmt.Sprintf("%d", nextSlot)),
want: nil,
},
{
name: "head",
blockID: []byte("head"),
want: headBlock.Block.(*ethpbalpha.BeaconBlockContainer_Phase0Block).Phase0Block,
},
{
name: "finalized",
blockID: []byte("finalized"),
want: blkContainers[64].Block.(*ethpbalpha.BeaconBlockContainer_Phase0Block).Phase0Block,
},
{
name: "genesis",
blockID: []byte("genesis"),
want: genBlk,
},
{
name: "genesis root",
blockID: root[:],
want: genBlk,
},
{
name: "root",
blockID: blkContainers[20].BlockRoot,
want: blkContainers[20].Block.(*ethpbalpha.BeaconBlockContainer_Phase0Block).Phase0Block,
},
{
name: "non-existent root",
blockID: bytesutil.PadTo([]byte("hi there"), 32),
want: nil,
},
{
name: "no block",
blockID: []byte("105"),
want: nil,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := fetcher.Block(ctx, tt.blockID)
if tt.wantErr {
assert.NotEqual(t, err, nil, "no error has been returned")
return
}
if tt.want == nil {
assert.Equal(t, nil, result)
return
}
require.NoError(t, err)
pbBlock, err := result.PbPhase0Block()
require.NoError(t, err)
if !reflect.DeepEqual(pbBlock, tt.want) {
t.Error("Expected blocks to equal")
}
})
}
}

View File

@@ -1,4 +1,4 @@
package statefetcher package lookup
import ( import (
"bytes" "bytes"
@@ -71,15 +71,15 @@ func (e *StateRootNotFoundError) Error() string {
return e.message return e.message
} }
// Fetcher is responsible for retrieving info related with the beacon chain. // Stater is responsible for retrieving states.
type Fetcher interface { type Stater interface {
State(ctx context.Context, stateId []byte) (state.BeaconState, error) State(ctx context.Context, id []byte) (state.BeaconState, error)
StateRoot(ctx context.Context, stateId []byte) ([]byte, error) StateRoot(ctx context.Context, id []byte) ([]byte, error)
StateBySlot(ctx context.Context, slot primitives.Slot) (state.BeaconState, error) StateBySlot(ctx context.Context, slot primitives.Slot) (state.BeaconState, error)
} }
// StateProvider is a real implementation of Fetcher. // BeaconDbStater is an implementation of Stater. It retrieves states from the beacon chain database.
type StateProvider struct { type BeaconDbStater struct {
BeaconDB db.ReadOnlyDatabase BeaconDB db.ReadOnlyDatabase
ChainInfoFetcher blockchain.ChainInfoFetcher ChainInfoFetcher blockchain.ChainInfoFetcher
GenesisTimeFetcher blockchain.TimeFetcher GenesisTimeFetcher blockchain.TimeFetcher
@@ -94,7 +94,7 @@ type StateProvider struct {
// - "justified" // - "justified"
// - <slot> // - <slot>
// - <hex encoded state root with '0x' prefix> // - <hex encoded state root with '0x' prefix>
func (p *StateProvider) State(ctx context.Context, stateId []byte) (state.BeaconState, error) { func (p *BeaconDbStater) State(ctx context.Context, stateId []byte) (state.BeaconState, error) {
var ( var (
s state.BeaconState s state.BeaconState
err error err error
@@ -164,7 +164,7 @@ func (p *StateProvider) State(ctx context.Context, stateId []byte) (state.Beacon
// - "justified" // - "justified"
// - <slot> // - <slot>
// - <hex encoded state root with '0x' prefix> // - <hex encoded state root with '0x' prefix>
func (p *StateProvider) StateRoot(ctx context.Context, stateId []byte) (root []byte, err error) { func (p *BeaconDbStater) StateRoot(ctx context.Context, stateId []byte) (root []byte, err error) {
stateIdString := strings.ToLower(string(stateId)) stateIdString := strings.ToLower(string(stateId))
switch stateIdString { switch stateIdString {
case "head": case "head":
@@ -192,7 +192,7 @@ func (p *StateProvider) StateRoot(ctx context.Context, stateId []byte) (root []b
return root, err return root, err
} }
func (p *StateProvider) stateByRoot(ctx context.Context, stateRoot []byte) (state.BeaconState, error) { func (p *BeaconDbStater) stateByRoot(ctx context.Context, stateRoot []byte) (state.BeaconState, error) {
headState, err := p.ChainInfoFetcher.HeadStateReadOnly(ctx) headState, err := p.ChainInfoFetcher.HeadStateReadOnly(ctx)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not get head state") return nil, errors.Wrap(err, "could not get head state")
@@ -213,7 +213,7 @@ func (p *StateProvider) stateByRoot(ctx context.Context, stateRoot []byte) (stat
// between the found state's slot and the target slot. // between the found state's slot and the target slot.
// process_blocks is applied for all canonical blocks, and process_slots is called for any skipped // process_blocks is applied for all canonical blocks, and process_slots is called for any skipped
// slots, or slots following the most recent canonical block up to and including the target slot. // slots, or slots following the most recent canonical block up to and including the target slot.
func (p *StateProvider) StateBySlot(ctx context.Context, target primitives.Slot) (state.BeaconState, error) { func (p *BeaconDbStater) StateBySlot(ctx context.Context, target primitives.Slot) (state.BeaconState, error) {
ctx, span := trace.StartSpan(ctx, "statefetcher.StateBySlot") ctx, span := trace.StartSpan(ctx, "statefetcher.StateBySlot")
defer span.End() defer span.End()
@@ -229,7 +229,7 @@ func (p *StateProvider) StateBySlot(ctx context.Context, target primitives.Slot)
return st, nil return st, nil
} }
func (p *StateProvider) headStateRoot(ctx context.Context) ([]byte, error) { func (p *BeaconDbStater) headStateRoot(ctx context.Context) ([]byte, error) {
b, err := p.ChainInfoFetcher.HeadBlock(ctx) b, err := p.ChainInfoFetcher.HeadBlock(ctx)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not get head block") return nil, errors.Wrap(err, "could not get head block")
@@ -241,7 +241,7 @@ func (p *StateProvider) headStateRoot(ctx context.Context) ([]byte, error) {
return stateRoot[:], nil return stateRoot[:], nil
} }
func (p *StateProvider) genesisStateRoot(ctx context.Context) ([]byte, error) { func (p *BeaconDbStater) genesisStateRoot(ctx context.Context) ([]byte, error) {
b, err := p.BeaconDB.GenesisBlock(ctx) b, err := p.BeaconDB.GenesisBlock(ctx)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not get genesis block") return nil, errors.Wrap(err, "could not get genesis block")
@@ -253,7 +253,7 @@ func (p *StateProvider) genesisStateRoot(ctx context.Context) ([]byte, error) {
return stateRoot[:], nil return stateRoot[:], nil
} }
func (p *StateProvider) finalizedStateRoot(ctx context.Context) ([]byte, error) { func (p *BeaconDbStater) finalizedStateRoot(ctx context.Context) ([]byte, error) {
cp, err := p.BeaconDB.FinalizedCheckpoint(ctx) cp, err := p.BeaconDB.FinalizedCheckpoint(ctx)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not get finalized checkpoint") return nil, errors.Wrap(err, "could not get finalized checkpoint")
@@ -269,7 +269,7 @@ func (p *StateProvider) finalizedStateRoot(ctx context.Context) ([]byte, error)
return stateRoot[:], nil return stateRoot[:], nil
} }
func (p *StateProvider) justifiedStateRoot(ctx context.Context) ([]byte, error) { func (p *BeaconDbStater) justifiedStateRoot(ctx context.Context) ([]byte, error) {
cp, err := p.BeaconDB.JustifiedCheckpoint(ctx) cp, err := p.BeaconDB.JustifiedCheckpoint(ctx)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not get justified checkpoint") return nil, errors.Wrap(err, "could not get justified checkpoint")
@@ -285,7 +285,7 @@ func (p *StateProvider) justifiedStateRoot(ctx context.Context) ([]byte, error)
return stateRoot[:], nil return stateRoot[:], nil
} }
func (p *StateProvider) stateRootByRoot(ctx context.Context, stateRoot []byte) ([]byte, error) { func (p *BeaconDbStater) stateRootByRoot(ctx context.Context, stateRoot []byte) ([]byte, error) {
var r [32]byte var r [32]byte
copy(r[:], stateRoot) copy(r[:], stateRoot)
headState, err := p.ChainInfoFetcher.HeadStateReadOnly(ctx) headState, err := p.ChainInfoFetcher.HeadStateReadOnly(ctx)
@@ -302,7 +302,7 @@ func (p *StateProvider) stateRootByRoot(ctx context.Context, stateRoot []byte) (
return nil, &rootNotFoundErr return nil, &rootNotFoundErr
} }
func (p *StateProvider) stateRootBySlot(ctx context.Context, slot primitives.Slot) ([]byte, error) { func (p *BeaconDbStater) stateRootBySlot(ctx context.Context, slot primitives.Slot) ([]byte, error) {
currentSlot := p.GenesisTimeFetcher.CurrentSlot() currentSlot := p.GenesisTimeFetcher.CurrentSlot()
if slot > currentSlot { if slot > currentSlot {
return nil, errors.New("slot cannot be in the future") return nil, errors.New("slot cannot be in the future")

View File

@@ -1,4 +1,4 @@
package statefetcher package lookup
import ( import (
"context" "context"
@@ -38,7 +38,7 @@ func TestGetState(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
t.Run("head", func(t *testing.T) { t.Run("head", func(t *testing.T) {
p := StateProvider{ p := BeaconDbStater{
ChainInfoFetcher: &chainMock.ChainService{State: newBeaconState}, ChainInfoFetcher: &chainMock.ChainService{State: newBeaconState},
} }
@@ -78,7 +78,7 @@ func TestGetState(t *testing.T) {
cs := &mockstategen.MockCurrentSlotter{Slot: bs.Slot() + 1} cs := &mockstategen.MockCurrentSlotter{Slot: bs.Slot() + 1}
ch := stategen.NewCanonicalHistory(db, cc, cs) ch := stategen.NewCanonicalHistory(db, cc, cs)
currentSlot := primitives.Slot(0) currentSlot := primitives.Slot(0)
p := StateProvider{ p := BeaconDbStater{
BeaconDB: db, BeaconDB: db,
ReplayerBuilder: ch, ReplayerBuilder: ch,
GenesisTimeFetcher: &chainMock.ChainService{Slot: &currentSlot}, GenesisTimeFetcher: &chainMock.ChainService{Slot: &currentSlot},
@@ -98,7 +98,7 @@ func TestGetState(t *testing.T) {
replayer.SetMockStateForSlot(newBeaconState, params.BeaconConfig().SlotsPerEpoch*10) replayer.SetMockStateForSlot(newBeaconState, params.BeaconConfig().SlotsPerEpoch*10)
stateGen.StatesByRoot[stateRoot] = newBeaconState stateGen.StatesByRoot[stateRoot] = newBeaconState
p := StateProvider{ p := BeaconDbStater{
ChainInfoFetcher: &chainMock.ChainService{ ChainInfoFetcher: &chainMock.ChainService{
FinalizedCheckPoint: &ethpb.Checkpoint{ FinalizedCheckPoint: &ethpb.Checkpoint{
Root: stateRoot[:], Root: stateRoot[:],
@@ -122,7 +122,7 @@ func TestGetState(t *testing.T) {
replayer.SetMockStateForSlot(newBeaconState, params.BeaconConfig().SlotsPerEpoch*10) replayer.SetMockStateForSlot(newBeaconState, params.BeaconConfig().SlotsPerEpoch*10)
stateGen.StatesByRoot[stateRoot] = newBeaconState stateGen.StatesByRoot[stateRoot] = newBeaconState
p := StateProvider{ p := BeaconDbStater{
ChainInfoFetcher: &chainMock.ChainService{ ChainInfoFetcher: &chainMock.ChainService{
CurrentJustifiedCheckPoint: &ethpb.Checkpoint{ CurrentJustifiedCheckPoint: &ethpb.Checkpoint{
Root: stateRoot[:], Root: stateRoot[:],
@@ -146,7 +146,7 @@ func TestGetState(t *testing.T) {
stateGen := mockstategen.NewMockService() stateGen := mockstategen.NewMockService()
stateGen.StatesByRoot[bytesutil.ToBytes32(stateId)] = newBeaconState stateGen.StatesByRoot[bytesutil.ToBytes32(stateId)] = newBeaconState
p := StateProvider{ p := BeaconDbStater{
ChainInfoFetcher: &chainMock.ChainService{State: newBeaconState}, ChainInfoFetcher: &chainMock.ChainService{State: newBeaconState},
StateGenService: stateGen, StateGenService: stateGen,
} }
@@ -159,7 +159,7 @@ func TestGetState(t *testing.T) {
}) })
t.Run("hex_root_not_found", func(t *testing.T) { t.Run("hex_root_not_found", func(t *testing.T) {
p := StateProvider{ p := BeaconDbStater{
ChainInfoFetcher: &chainMock.ChainService{State: newBeaconState}, ChainInfoFetcher: &chainMock.ChainService{State: newBeaconState},
} }
stateId, err := hexutil.Decode("0x" + strings.Repeat("f", 64)) stateId, err := hexutil.Decode("0x" + strings.Repeat("f", 64))
@@ -169,7 +169,7 @@ func TestGetState(t *testing.T) {
}) })
t.Run("slot", func(t *testing.T) { t.Run("slot", func(t *testing.T) {
p := StateProvider{ p := BeaconDbStater{
GenesisTimeFetcher: &chainMock.ChainService{Slot: &headSlot}, GenesisTimeFetcher: &chainMock.ChainService{Slot: &headSlot},
ChainInfoFetcher: &chainMock.ChainService{ ChainInfoFetcher: &chainMock.ChainService{
CanonicalRoots: map[[32]byte]bool{ CanonicalRoots: map[[32]byte]bool{
@@ -188,7 +188,7 @@ func TestGetState(t *testing.T) {
}) })
t.Run("invalid_state", func(t *testing.T) { t.Run("invalid_state", func(t *testing.T) {
p := StateProvider{} p := BeaconDbStater{}
_, err := p.State(ctx, []byte("foo")) _, err := p.State(ctx, []byte("foo"))
require.ErrorContains(t, "could not parse state ID", err) require.ErrorContains(t, "could not parse state ID", err)
}) })
@@ -212,7 +212,7 @@ func TestGetStateRoot(t *testing.T) {
b.Block.StateRoot = stateRoot[:] b.Block.StateRoot = stateRoot[:]
wsb, err := blocks.NewSignedBeaconBlock(b) wsb, err := blocks.NewSignedBeaconBlock(b)
require.NoError(t, err) require.NoError(t, err)
p := StateProvider{ p := BeaconDbStater{
ChainInfoFetcher: &chainMock.ChainService{ ChainInfoFetcher: &chainMock.ChainService{
State: newBeaconState, State: newBeaconState,
Block: wsb, Block: wsb,
@@ -241,7 +241,7 @@ func TestGetStateRoot(t *testing.T) {
require.NoError(t, db.SaveGenesisBlockRoot(ctx, r)) require.NoError(t, db.SaveGenesisBlockRoot(ctx, r))
require.NoError(t, db.SaveState(ctx, bs, r)) require.NoError(t, db.SaveState(ctx, bs, r))
p := StateProvider{ p := BeaconDbStater{
BeaconDB: db, BeaconDB: db,
} }
@@ -275,7 +275,7 @@ func TestGetStateRoot(t *testing.T) {
require.NoError(t, db.SaveState(ctx, st, root)) require.NoError(t, db.SaveState(ctx, st, root))
require.NoError(t, db.SaveFinalizedCheckpoint(ctx, cp)) require.NoError(t, db.SaveFinalizedCheckpoint(ctx, cp))
p := StateProvider{ p := BeaconDbStater{
BeaconDB: db, BeaconDB: db,
} }
@@ -306,7 +306,7 @@ func TestGetStateRoot(t *testing.T) {
require.NoError(t, db.SaveState(ctx, st, root)) require.NoError(t, db.SaveState(ctx, st, root))
require.NoError(t, db.SaveJustifiedCheckpoint(ctx, cp)) require.NoError(t, db.SaveJustifiedCheckpoint(ctx, cp))
p := StateProvider{ p := BeaconDbStater{
BeaconDB: db, BeaconDB: db,
} }
@@ -319,7 +319,7 @@ func TestGetStateRoot(t *testing.T) {
stateId, err := hexutil.Decode("0x" + strings.Repeat("0", 63) + "1") stateId, err := hexutil.Decode("0x" + strings.Repeat("0", 63) + "1")
require.NoError(t, err) require.NoError(t, err)
p := StateProvider{ p := BeaconDbStater{
ChainInfoFetcher: &chainMock.ChainService{State: newBeaconState}, ChainInfoFetcher: &chainMock.ChainService{State: newBeaconState},
} }
@@ -329,7 +329,7 @@ func TestGetStateRoot(t *testing.T) {
}) })
t.Run("hex_root_not_found", func(t *testing.T) { t.Run("hex_root_not_found", func(t *testing.T) {
p := StateProvider{ p := BeaconDbStater{
ChainInfoFetcher: &chainMock.ChainService{State: newBeaconState}, ChainInfoFetcher: &chainMock.ChainService{State: newBeaconState},
} }
stateId, err := hexutil.Decode("0x" + strings.Repeat("f", 64)) stateId, err := hexutil.Decode("0x" + strings.Repeat("f", 64))
@@ -355,7 +355,7 @@ func TestGetStateRoot(t *testing.T) {
require.NoError(t, db.SaveState(ctx, st, root)) require.NoError(t, db.SaveState(ctx, st, root))
slot := primitives.Slot(40) slot := primitives.Slot(40)
p := StateProvider{ p := BeaconDbStater{
GenesisTimeFetcher: &chainMock.ChainService{Slot: &slot}, GenesisTimeFetcher: &chainMock.ChainService{Slot: &slot},
BeaconDB: db, BeaconDB: db,
} }
@@ -366,7 +366,7 @@ func TestGetStateRoot(t *testing.T) {
}) })
t.Run("slot_too_big", func(t *testing.T) { t.Run("slot_too_big", func(t *testing.T) {
p := StateProvider{ p := BeaconDbStater{
GenesisTimeFetcher: &chainMock.ChainService{ GenesisTimeFetcher: &chainMock.ChainService{
Genesis: time.Now(), Genesis: time.Now(),
}, },
@@ -376,7 +376,7 @@ func TestGetStateRoot(t *testing.T) {
}) })
t.Run("invalid_state", func(t *testing.T) { t.Run("invalid_state", func(t *testing.T) {
p := StateProvider{} p := BeaconDbStater{}
_, err := p.StateRoot(ctx, []byte("foo")) _, err := p.StateRoot(ctx, []byte("foo"))
require.ErrorContains(t, "could not parse state ID", err) require.ErrorContains(t, "could not parse state ID", err)
}) })
@@ -389,7 +389,7 @@ func TestNewStateNotFoundError(t *testing.T) {
func TestStateBySlot_FutureSlot(t *testing.T) { func TestStateBySlot_FutureSlot(t *testing.T) {
slot := primitives.Slot(100) slot := primitives.Slot(100)
p := StateProvider{GenesisTimeFetcher: &chainMock.ChainService{Slot: &slot}} p := BeaconDbStater{GenesisTimeFetcher: &chainMock.ChainService{Slot: &slot}}
_, err := p.StateBySlot(context.Background(), 101) _, err := p.StateBySlot(context.Background(), 101)
assert.ErrorContains(t, "requested slot is in the future", err) assert.ErrorContains(t, "requested slot is in the future", err)
} }
@@ -403,7 +403,7 @@ func TestStateBySlot_AfterHeadSlot(t *testing.T) {
mock := &chainMock.ChainService{State: headSt, Slot: &currentSlot} mock := &chainMock.ChainService{State: headSt, Slot: &currentSlot}
mockReplayer := mockstategen.NewMockReplayerBuilder() mockReplayer := mockstategen.NewMockReplayerBuilder()
mockReplayer.SetMockStateForSlot(slotSt, 101) mockReplayer.SetMockStateForSlot(slotSt, 101)
p := StateProvider{ChainInfoFetcher: mock, GenesisTimeFetcher: mock, ReplayerBuilder: mockReplayer} p := BeaconDbStater{ChainInfoFetcher: mock, GenesisTimeFetcher: mock, ReplayerBuilder: mockReplayer}
st, err := p.StateBySlot(context.Background(), 101) st, err := p.StateBySlot(context.Background(), 101)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, primitives.Slot(101), st.Slot()) assert.Equal(t, primitives.Slot(101), st.Slot())

View File

@@ -122,7 +122,7 @@ func convertToBlockContainer(blk interfaces.ReadOnlySignedBeaconBlock, root [32]
} }
ctr.Block = &ethpb.BeaconBlockContainer_BellatrixBlock{BellatrixBlock: rBlk} ctr.Block = &ethpb.BeaconBlockContainer_BellatrixBlock{BellatrixBlock: rBlk}
} }
case version.Capella: case version.Capella, version.Deneb:
if blk.IsBlinded() { if blk.IsBlinded() {
rBlk, err := blk.PbBlindedCapellaBlock() rBlk, err := blk.PbBlindedCapellaBlock()
if err != nil { if err != nil {

View File

@@ -45,6 +45,7 @@ go_library(
"//beacon-chain/core/signing:go_default_library", "//beacon-chain/core/signing:go_default_library",
"//beacon-chain/core/time:go_default_library", "//beacon-chain/core/time:go_default_library",
"//beacon-chain/core/transition:go_default_library", "//beacon-chain/core/transition:go_default_library",
"//beacon-chain/core/transition/interop:go_default_library",
"//beacon-chain/core/validators:go_default_library", "//beacon-chain/core/validators:go_default_library",
"//beacon-chain/db:go_default_library", "//beacon-chain/db:go_default_library",
"//beacon-chain/db/kv:go_default_library", "//beacon-chain/db/kv:go_default_library",
@@ -85,6 +86,7 @@ go_library(
"//time/slots:go_default_library", "//time/slots:go_default_library",
"@com_github_ethereum_go_ethereum//common: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//common/hexutil:go_default_library",
"@com_github_ethereum_go_ethereum//core/types:go_default_library",
"@com_github_pkg_errors//:go_default_library", "@com_github_pkg_errors//:go_default_library",
"@com_github_prometheus_client_golang//prometheus:go_default_library", "@com_github_prometheus_client_golang//prometheus:go_default_library",
"@com_github_prometheus_client_golang//prometheus/promauto:go_default_library", "@com_github_prometheus_client_golang//prometheus/promauto:go_default_library",

View File

@@ -100,6 +100,17 @@ func sendVerifiedBlocks(stream ethpb.BeaconNodeValidator_StreamBlocksAltairServe
return nil return nil
} }
b.Block = &ethpb.StreamBlocksResponse_CapellaBlock{CapellaBlock: phBlk} b.Block = &ethpb.StreamBlocksResponse_CapellaBlock{CapellaBlock: phBlk}
case version.Deneb:
pb, err := data.SignedBlock.Proto()
if err != nil {
return errors.Wrap(err, "could not get protobuf block")
}
phBlk, ok := pb.(*ethpb.SignedBeaconBlockDeneb)
if !ok {
log.Warn("Mismatch between version and block type, was expecting SignedBeaconBlockDeneb")
return nil
}
b.Block = &ethpb.StreamBlocksResponse_DenebBlock{DenebBlock: phBlk}
} }
if err := stream.Send(b); err != nil { if err := stream.Send(b); err != nil {
@@ -149,6 +160,8 @@ func (vs *Server) sendBlocks(stream ethpb.BeaconNodeValidator_StreamBlocksAltair
b.Block = &ethpb.StreamBlocksResponse_BellatrixBlock{BellatrixBlock: p} b.Block = &ethpb.StreamBlocksResponse_BellatrixBlock{BellatrixBlock: p}
case *ethpb.SignedBeaconBlockCapella: case *ethpb.SignedBeaconBlockCapella:
b.Block = &ethpb.StreamBlocksResponse_CapellaBlock{CapellaBlock: p} b.Block = &ethpb.StreamBlocksResponse_CapellaBlock{CapellaBlock: p}
case *ethpb.SignedBeaconBlockDeneb:
b.Block = &ethpb.StreamBlocksResponse_DenebBlock{DenebBlock: p}
default: default:
log.Errorf("Unknown block type %T", p) log.Errorf("Unknown block type %T", p)
} }

View File

@@ -9,6 +9,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
emptypb "github.com/golang/protobuf/ptypes/empty" emptypb "github.com/golang/protobuf/ptypes/empty"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain" "github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain"
@@ -17,6 +18,7 @@ import (
blockfeed "github.com/prysmaticlabs/prysm/v4/beacon-chain/core/feed/block" blockfeed "github.com/prysmaticlabs/prysm/v4/beacon-chain/core/feed/block"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v4/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/transition" "github.com/prysmaticlabs/prysm/v4/beacon-chain/core/transition"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/transition/interop"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/db/kv" "github.com/prysmaticlabs/prysm/v4/beacon-chain/db/kv"
"github.com/prysmaticlabs/prysm/v4/config/params" "github.com/prysmaticlabs/prysm/v4/config/params"
"github.com/prysmaticlabs/prysm/v4/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v4/consensus-types/blocks"
@@ -24,6 +26,7 @@ import (
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1" ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v4/runtime/version"
"github.com/prysmaticlabs/prysm/v4/time/slots" "github.com/prysmaticlabs/prysm/v4/time/slots"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"go.opencensus.io/trace" "go.opencensus.io/trace"
@@ -120,7 +123,8 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (
vs.setSyncAggregate(ctx, sBlk) vs.setSyncAggregate(ctx, sBlk)
// Set execution data. New in Bellatrix. // Set execution data. New in Bellatrix.
if err := vs.setExecutionData(ctx, sBlk, head); err != nil { blobs, err := vs.setExecutionData(ctx, sBlk, head)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not set execution data: %v", err) return nil, status.Errorf(codes.Internal, "Could not set execution data: %v", err)
} }
@@ -129,6 +133,7 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (
sr, err := vs.computeStateRoot(ctx, sBlk) sr, err := vs.computeStateRoot(ctx, sBlk)
if err != nil { if err != nil {
interop.WriteBlockToDisk(sBlk, true /*failed*/)
return nil, status.Errorf(codes.Internal, "Could not compute state root: %v", err) return nil, status.Errorf(codes.Internal, "Could not compute state root: %v", err)
} }
sBlk.SetStateRoot(sr) sBlk.SetStateRoot(sr)
@@ -137,6 +142,46 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (
if err != nil { if err != nil {
return nil, status.Errorf(codes.Internal, "Could not convert block to proto: %v", err) return nil, status.Errorf(codes.Internal, "Could not convert block to proto: %v", err)
} }
if slots.ToEpoch(req.Slot) >= params.BeaconConfig().DenebForkEpoch {
blk, ok := pb.(*ethpb.BeaconBlockDeneb)
if !ok {
return nil, status.Errorf(codes.Internal, "Could not cast block to BeaconBlockDeneb")
}
br, err := blk.HashTreeRoot()
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not get block root: %v", err)
}
// TODO: Better error handling. If something is wrong with the blob, we don't want to fail block production. Also should check if the kzg commitment matches.
validatorBlobs := make([]*ethpb.BlobSidecar, len(blk.Body.BlobKzgCommitments))
var gethBlobs types.Blobs
for _, b := range blobs {
var gethBlob types.Blob
copy(gethBlob[:], b.Data)
gethBlobs = append(gethBlobs, gethBlob)
}
commitments, _, proofs, err := gethBlobs.ComputeCommitmentsAndProofs()
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not compute commitments and proofs: %v", err)
}
for i, b := range blobs {
validatorBlobs[i] = &ethpb.BlobSidecar{
BlockRoot: br[:],
Index: uint64(i),
Slot: blk.Slot,
BlockParentRoot: blk.ParentRoot,
ProposerIndex: blk.ProposerIndex,
Blob: b.Data,
KzgCommitment: commitments[i][:],
KzgProof: proofs[i][:],
}
}
blkAndBlobs := &ethpb.BeaconBlockDenebAndBlobs{
Block: blk,
Blobs: validatorBlobs,
}
return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_Deneb{Deneb: blkAndBlobs}}, nil
}
if slots.ToEpoch(req.Slot) >= params.BeaconConfig().CapellaForkEpoch { if slots.ToEpoch(req.Slot) >= params.BeaconConfig().CapellaForkEpoch {
if sBlk.IsBlinded() { if sBlk.IsBlinded() {
return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_BlindedCapella{BlindedCapella: pb.(*ethpb.BlindedBeaconBlockCapella)}}, nil return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_BlindedCapella{BlindedCapella: pb.(*ethpb.BlindedBeaconBlockCapella)}}, nil
@@ -160,11 +205,7 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (
func (vs *Server) ProposeBeaconBlock(ctx context.Context, req *ethpb.GenericSignedBeaconBlock) (*ethpb.ProposeResponse, error) { func (vs *Server) ProposeBeaconBlock(ctx context.Context, req *ethpb.GenericSignedBeaconBlock) (*ethpb.ProposeResponse, error) {
ctx, span := trace.StartSpan(ctx, "ProposerServer.ProposeBeaconBlock") ctx, span := trace.StartSpan(ctx, "ProposerServer.ProposeBeaconBlock")
defer span.End() defer span.End()
blk, err := blocks.NewSignedBeaconBlock(req.Block) return vs.proposeGenericBeaconBlock(ctx, req)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "Could not decode block: %v", err)
}
return vs.proposeGenericBeaconBlock(ctx, blk)
} }
// PrepareBeaconProposer caches and updates the fee recipient for the given proposer. // PrepareBeaconProposer caches and updates the fee recipient for the given proposer.
@@ -247,9 +288,15 @@ func (vs *Server) GetFeeRecipientByPubKey(ctx context.Context, request *ethpb.Fe
}, nil }, nil
} }
func (vs *Server) proposeGenericBeaconBlock(ctx context.Context, blk interfaces.ReadOnlySignedBeaconBlock) (*ethpb.ProposeResponse, error) { func (vs *Server) proposeGenericBeaconBlock(ctx context.Context, req *ethpb.GenericSignedBeaconBlock) (*ethpb.ProposeResponse, error) {
ctx, span := trace.StartSpan(ctx, "ProposerServer.proposeGenericBeaconBlock") ctx, span := trace.StartSpan(ctx, "ProposerServer.proposeGenericBeaconBlock")
defer span.End() defer span.End()
blk, err := blocks.NewSignedBeaconBlock(req.Block)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "Could not decode block: %v", err)
}
root, err := blk.Block().HashTreeRoot() root, err := blk.Block().HashTreeRoot()
if err != nil { if err != nil {
return nil, fmt.Errorf("could not tree hash block: %v", err) return nil, fmt.Errorf("could not tree hash block: %v", err)
@@ -267,16 +314,6 @@ func (vs *Server) proposeGenericBeaconBlock(ctx context.Context, blk interfaces.
} }
} }
// Do not block proposal critical path with debug logging or block feed updates.
defer func() {
log.WithField("blockRoot", fmt.Sprintf("%#x", bytesutil.Trunc(root[:]))).Debugf(
"Block proposal received via RPC")
vs.BlockNotifier.BlockFeed().Send(&feed.Event{
Type: blockfeed.ReceivedBlock,
Data: &blockfeed.ReceivedBlockData{SignedBlock: blk},
})
}()
// Broadcast the new block to the network. // Broadcast the new block to the network.
blkPb, err := blk.Proto() blkPb, err := blk.Proto()
if err != nil { if err != nil {
@@ -293,6 +330,35 @@ func (vs *Server) proposeGenericBeaconBlock(ctx context.Context, blk interfaces.
return nil, fmt.Errorf("could not process beacon block: %v", err) return nil, fmt.Errorf("could not process beacon block: %v", err)
} }
if blk.Version() >= version.Deneb {
b, ok := req.GetBlock().(*ethpb.GenericSignedBeaconBlock_Deneb)
if !ok {
return nil, status.Error(codes.Internal, "Could not cast block to Deneb")
}
scs := make([]*ethpb.BlobSidecar, len(b.Deneb.Blobs))
for i, sidecar := range b.Deneb.Blobs {
scs[i] = sidecar.Message
if err := vs.P2P.BroadcastBlob(ctx, sidecar.Message.Index, sidecar); err != nil {
return nil, errors.Wrap(err, "could not broadcast blob sidecar")
}
}
if len(scs) > 0 {
if err := vs.BeaconDB.SaveBlobSidecar(ctx, scs); err != nil {
return nil, errors.Wrap(err, "could not save blob sidecar")
}
}
}
// Do not block proposal critical path with debug logging or block feed updates.
defer func() {
log.WithField("blockRoot", fmt.Sprintf("%#x", bytesutil.Trunc(root[:]))).Debugf(
"Block proposal received via RPC")
vs.BlockNotifier.BlockFeed().Send(&feed.Event{
Type: blockfeed.ReceivedBlock,
Data: &blockfeed.ReceivedBlockData{SignedBlock: blk},
})
}()
return &ethpb.ProposeResponse{ return &ethpb.ProposeResponse{
BlockRoot: root[:], BlockRoot: root[:],
}, nil }, nil

View File

@@ -80,7 +80,7 @@ func (vs *Server) packAttestations(ctx context.Context, latestState state.Beacon
// filter separates attestation list into two groups: valid and invalid attestations. // filter separates attestation list into two groups: valid and invalid attestations.
// The first group passes the all the required checks for attestation to be considered for proposing. // The first group passes the all the required checks for attestation to be considered for proposing.
// And attestations from the second group should be deleted. // And attestations from the second group should be deleted.
func (a proposerAtts) filter(ctx context.Context, st state.BeaconState) (proposerAtts, proposerAtts) { func (a proposerAtts) filter(ctx context.Context, st state.BeaconState) (proposerAtts, proposerAtts, error) {
validAtts := make([]*ethpb.Attestation, 0, len(a)) validAtts := make([]*ethpb.Attestation, 0, len(a))
invalidAtts := make([]*ethpb.Attestation, 0, len(a)) invalidAtts := make([]*ethpb.Attestation, 0, len(a))
var attestationProcessor func(context.Context, state.BeaconState, *ethpb.Attestation) (state.BeaconState, error) var attestationProcessor func(context.Context, state.BeaconState, *ethpb.Attestation) (state.BeaconState, error)
@@ -98,7 +98,7 @@ func (a proposerAtts) filter(ctx context.Context, st state.BeaconState) (propose
} }
} else { } else {
// Exit early if there is an unknown state type. // Exit early if there is an unknown state type.
return validAtts, invalidAtts return validAtts, invalidAtts, errors.Errorf("unknown state type: %v", st.Version())
} }
for _, att := range a { for _, att := range a {
@@ -108,7 +108,7 @@ func (a proposerAtts) filter(ctx context.Context, st state.BeaconState) (propose
} }
invalidAtts = append(invalidAtts, att) invalidAtts = append(invalidAtts, att)
} }
return validAtts, invalidAtts return validAtts, invalidAtts, nil
} }
// sortByProfitability orders attestations by highest slot and by highest aggregation bit count. // sortByProfitability orders attestations by highest slot and by highest aggregation bit count.
@@ -247,7 +247,10 @@ func (vs *Server) validateAndDeleteAttsInPool(ctx context.Context, st state.Beac
ctx, span := trace.StartSpan(ctx, "ProposerServer.validateAndDeleteAttsInPool") ctx, span := trace.StartSpan(ctx, "ProposerServer.validateAndDeleteAttsInPool")
defer span.End() defer span.End()
validAtts, invalidAtts := proposerAtts(atts).filter(ctx, st) validAtts, invalidAtts, err := proposerAtts(atts).filter(ctx, st)
if err != nil {
return nil, err
}
if err := vs.deleteAttsInPool(ctx, invalidAtts); err != nil { if err := vs.deleteAttsInPool(ctx, invalidAtts); err != nil {
return nil, err return nil, err
} }

View File

@@ -37,11 +37,11 @@ var builderGetPayloadMissCount = promauto.NewCounter(prometheus.CounterOpts{
const blockBuilderTimeout = 1 * time.Second const blockBuilderTimeout = 1 * time.Second
// Sets the execution data for the block. Execution data can come from local EL client or remote builder depends on validator registration and circuit breaker conditions. // Sets the execution data for the block. Execution data can come from local EL client or remote builder depends on validator registration and circuit breaker conditions.
func (vs *Server) setExecutionData(ctx context.Context, blk interfaces.SignedBeaconBlock, headState state.BeaconState) error { func (vs *Server) setExecutionData(ctx context.Context, blk interfaces.SignedBeaconBlock, headState state.BeaconState) ([]*enginev1.Blob, error) {
idx := blk.Block().ProposerIndex() idx := blk.Block().ProposerIndex()
slot := blk.Block().Slot() slot := blk.Block().Slot()
if slots.ToEpoch(slot) < params.BeaconConfig().BellatrixForkEpoch { if slots.ToEpoch(slot) < params.BeaconConfig().BellatrixForkEpoch {
return nil return nil, nil
} }
canUseBuilder, err := vs.canUseBuilder(ctx, slot, idx) canUseBuilder, err := vs.canUseBuilder(ctx, slot, idx)
@@ -55,14 +55,14 @@ func (vs *Server) setExecutionData(ctx context.Context, blk interfaces.SignedBea
} else { } else {
switch { switch {
case blk.Version() >= version.Capella: case blk.Version() >= version.Capella:
localPayload, err := vs.getExecutionPayload(ctx, slot, idx, blk.Block().ParentRoot(), headState) localPayload, _, err := vs.getExecutionPayload(ctx, slot, idx, blk.Block().ParentRoot(), headState)
if err != nil { if err != nil {
return errors.Wrap(err, "failed to get execution payload") return nil, errors.Wrap(err, "failed to get execution payload")
} }
// Compare payload values between local and builder. Default to the local value if it is higher. // Compare payload values between local and builder. Default to the local value if it is higher.
localValue, err := localPayload.Value() localValue, err := localPayload.Value()
if err != nil { if err != nil {
return errors.Wrap(err, "failed to get local payload value") return nil, errors.Wrap(err, "failed to get local payload value")
} }
builderValue, err := builderPayload.Value() builderValue, err := builderPayload.Value()
if err != nil { if err != nil {
@@ -71,7 +71,7 @@ func (vs *Server) setExecutionData(ctx context.Context, blk interfaces.SignedBea
withdrawalsMatched, err := matchingWithdrawalsRoot(localPayload, builderPayload) withdrawalsMatched, err := matchingWithdrawalsRoot(localPayload, builderPayload)
if err != nil { if err != nil {
return errors.Wrap(err, "failed to match withdrawals root") return nil, errors.Wrap(err, "failed to match withdrawals root")
} }
// If we can't get the builder value, just use local block. // If we can't get the builder value, just use local block.
if builderValue.Cmp(localValue) > 0 && withdrawalsMatched { // Builder value is higher and withdrawals match. if builderValue.Cmp(localValue) > 0 && withdrawalsMatched { // Builder value is higher and withdrawals match.
@@ -79,31 +79,38 @@ func (vs *Server) setExecutionData(ctx context.Context, blk interfaces.SignedBea
if err := blk.SetExecution(builderPayload); err != nil { if err := blk.SetExecution(builderPayload); err != nil {
log.WithError(err).Warn("Proposer: failed to set builder payload") log.WithError(err).Warn("Proposer: failed to set builder payload")
} else { } else {
return nil return nil, nil
} }
} }
log.WithFields(logrus.Fields{ log.WithFields(logrus.Fields{
"localValue": localValue, "localValue": localValue,
"builderValue": builderValue, "builderValue": builderValue,
}).Warn("Proposer: using local execution payload because higher value") }).Warn("Proposer: using local execution payload because higher value")
return blk.SetExecution(localPayload) return nil, blk.SetExecution(localPayload)
default: // Bellatrix case. default: // Bellatrix case.
blk.SetBlinded(true) blk.SetBlinded(true)
if err := blk.SetExecution(builderPayload); err != nil { if err := blk.SetExecution(builderPayload); err != nil {
log.WithError(err).Warn("Proposer: failed to set builder payload") log.WithError(err).Warn("Proposer: failed to set builder payload")
} else { } else {
return nil return nil, nil
} }
} }
} }
} }
executionData, err := vs.getExecutionPayload(ctx, slot, idx, blk.Block().ParentRoot(), headState) executionData, blobsBundle, err := vs.getExecutionPayload(ctx, slot, idx, blk.Block().ParentRoot(), headState)
if err != nil { if err != nil {
return errors.Wrap(err, "failed to get execution payload") return nil, errors.Wrap(err, "failed to get execution payload")
} }
return blk.SetExecution(executionData) if slots.ToEpoch(slot) >= params.BeaconConfig().DenebForkEpoch && len(blobsBundle.KzgCommitments) > 0 {
// TODO: check block hash matches blob bundle hash
if err := blk.SetBlobKzgCommitments(blobsBundle.KzgCommitments); err != nil {
return nil, errors.Wrap(err, "could not set blob kzg commitments")
}
return blobsBundle.Blobs, blk.SetExecution(executionData)
}
return nil, blk.SetExecution(executionData)
} }
// This function retrieves the payload header given the slot number and the validator index. // This function retrieves the payload header given the slot number and the validator index.
@@ -187,17 +194,17 @@ func (vs *Server) getPayloadHeaderFromBuilder(ctx context.Context, slot primitiv
"builderPubKey": fmt.Sprintf("%#x", bid.Pubkey()), "builderPubKey": fmt.Sprintf("%#x", bid.Pubkey()),
"blockHash": fmt.Sprintf("%#x", header.BlockHash()), "blockHash": fmt.Sprintf("%#x", header.BlockHash()),
}).Info("Received header with bid") }).Info("Received header with bid")
return header, nil return header, nil
} }
// This function retrieves the full payload block using the input blind block. This input must be versioned as // This function retrieves the full payload block using the input blind block. This input must be versioned as
// bellatrix blind block. The output block will contain the full payload. The original header block // bellatrix blind block. The output block will contain the full payload. The original header block
// will be returned the block builder is not configured. // will be returned the block builder is not configured.
func (vs *Server) unblindBuilderBlock(ctx context.Context, b interfaces.ReadOnlySignedBeaconBlock) (interfaces.ReadOnlySignedBeaconBlock, error) { func (vs *Server) unblindBuilderBlock(ctx context.Context, b interfaces.SignedBeaconBlock) (interfaces.SignedBeaconBlock, error) {
if err := consensusblocks.BeaconBlockIsNil(b); err != nil { if err := consensusblocks.BeaconBlockIsNil(b); err != nil {
return nil, err return nil, err
} }
// No-op if the input block is not version blind and bellatrix. // No-op if the input block is not version blind and bellatrix.
if b.Version() != version.Bellatrix || !b.IsBlinded() { if b.Version() != version.Bellatrix || !b.IsBlinded() {
return b, nil return b, nil

View File

@@ -70,7 +70,8 @@ func TestServer_setExecutionData(t *testing.T) {
t.Run("No builder configured. Use local block", func(t *testing.T) { t.Run("No builder configured. Use local block", func(t *testing.T) {
blk, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlockCapella()) blk, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlockCapella())
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, vs.setExecutionData(context.Background(), blk, capellaTransitionState)) _, err = vs.setExecutionData(context.Background(), blk, capellaTransitionState)
require.NoError(t, err)
e, err := blk.Block().Body().Execution() e, err := blk.Block().Body().Execution()
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, uint64(1), e.BlockNumber()) // Local block require.Equal(t, uint64(1), e.BlockNumber()) // Local block
@@ -121,7 +122,8 @@ func TestServer_setExecutionData(t *testing.T) {
vs.ForkchoiceFetcher.SetForkChoiceGenesisTime(uint64(time.Now().Unix())) vs.ForkchoiceFetcher.SetForkChoiceGenesisTime(uint64(time.Now().Unix()))
vs.TimeFetcher = chain vs.TimeFetcher = chain
vs.HeadFetcher = chain vs.HeadFetcher = chain
require.NoError(t, vs.setExecutionData(context.Background(), blk, capellaTransitionState)) _, err = vs.setExecutionData(context.Background(), blk, capellaTransitionState)
require.NoError(t, err)
e, err := blk.Block().Body().Execution() e, err := blk.Block().Body().Execution()
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, uint64(1), e.BlockNumber()) // Local block because incorrect withdrawals require.Equal(t, uint64(1), e.BlockNumber()) // Local block because incorrect withdrawals
@@ -174,7 +176,8 @@ func TestServer_setExecutionData(t *testing.T) {
vs.ForkchoiceFetcher.SetForkChoiceGenesisTime(uint64(time.Now().Unix())) vs.ForkchoiceFetcher.SetForkChoiceGenesisTime(uint64(time.Now().Unix()))
vs.TimeFetcher = chain vs.TimeFetcher = chain
vs.HeadFetcher = chain vs.HeadFetcher = chain
require.NoError(t, vs.setExecutionData(context.Background(), blk, capellaTransitionState)) _, err = vs.setExecutionData(context.Background(), blk, capellaTransitionState)
require.NoError(t, err)
e, err := blk.Block().Body().Execution() e, err := blk.Block().Body().Execution()
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, uint64(2), e.BlockNumber()) // Builder block require.Equal(t, uint64(2), e.BlockNumber()) // Builder block
@@ -183,7 +186,8 @@ func TestServer_setExecutionData(t *testing.T) {
blk, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlockCapella()) blk, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlockCapella())
require.NoError(t, err) require.NoError(t, err)
vs.ExecutionEngineCaller = &powtesting.EngineClient{PayloadIDBytes: id, ExecutionPayloadCapella: &v1.ExecutionPayloadCapella{BlockNumber: 3}, BlockValue: big.NewInt(3)} vs.ExecutionEngineCaller = &powtesting.EngineClient{PayloadIDBytes: id, ExecutionPayloadCapella: &v1.ExecutionPayloadCapella{BlockNumber: 3}, BlockValue: big.NewInt(3)}
require.NoError(t, vs.setExecutionData(context.Background(), blk, capellaTransitionState)) _, err = vs.setExecutionData(context.Background(), blk, capellaTransitionState)
require.NoError(t, err)
e, err := blk.Block().Body().Execution() e, err := blk.Block().Body().Execution()
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, uint64(3), e.BlockNumber()) // Local block require.Equal(t, uint64(3), e.BlockNumber()) // Local block
@@ -195,7 +199,8 @@ func TestServer_setExecutionData(t *testing.T) {
ErrGetHeader: errors.New("fault"), ErrGetHeader: errors.New("fault"),
} }
vs.ExecutionEngineCaller = &powtesting.EngineClient{PayloadIDBytes: id, ExecutionPayloadCapella: &v1.ExecutionPayloadCapella{BlockNumber: 4}, BlockValue: big.NewInt(0)} vs.ExecutionEngineCaller = &powtesting.EngineClient{PayloadIDBytes: id, ExecutionPayloadCapella: &v1.ExecutionPayloadCapella{BlockNumber: 4}, BlockValue: big.NewInt(0)}
require.NoError(t, vs.setExecutionData(context.Background(), blk, capellaTransitionState)) _, err = vs.setExecutionData(context.Background(), blk, capellaTransitionState)
require.NoError(t, err)
e, err := blk.Block().Body().Execution() e, err := blk.Block().Body().Execution()
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, uint64(4), e.BlockNumber()) // Local block require.Equal(t, uint64(4), e.BlockNumber()) // Local block
@@ -366,10 +371,10 @@ func TestServer_getBuilderBlock(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
blk interfaces.ReadOnlySignedBeaconBlock blk interfaces.SignedBeaconBlock
mock *builderTest.MockBuilderService mock *builderTest.MockBuilderService
err string err string
returnedBlk interfaces.ReadOnlySignedBeaconBlock returnedBlk interfaces.SignedBeaconBlock
}{ }{
{ {
name: "nil block", name: "nil block",
@@ -378,12 +383,12 @@ func TestServer_getBuilderBlock(t *testing.T) {
}, },
{ {
name: "old block version", name: "old block version",
blk: func() interfaces.ReadOnlySignedBeaconBlock { blk: func() interfaces.SignedBeaconBlock {
wb, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlock()) wb, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlock())
require.NoError(t, err) require.NoError(t, err)
return wb return wb
}(), }(),
returnedBlk: func() interfaces.ReadOnlySignedBeaconBlock { returnedBlk: func() interfaces.SignedBeaconBlock {
wb, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlock()) wb, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlock())
require.NoError(t, err) require.NoError(t, err)
return wb return wb
@@ -391,7 +396,7 @@ func TestServer_getBuilderBlock(t *testing.T) {
}, },
{ {
name: "not configured", name: "not configured",
blk: func() interfaces.ReadOnlySignedBeaconBlock { blk: func() interfaces.SignedBeaconBlock {
wb, err := blocks.NewSignedBeaconBlock(util.NewBlindedBeaconBlockBellatrix()) wb, err := blocks.NewSignedBeaconBlock(util.NewBlindedBeaconBlockBellatrix())
require.NoError(t, err) require.NoError(t, err)
return wb return wb
@@ -399,7 +404,7 @@ func TestServer_getBuilderBlock(t *testing.T) {
mock: &builderTest.MockBuilderService{ mock: &builderTest.MockBuilderService{
HasConfigured: false, HasConfigured: false,
}, },
returnedBlk: func() interfaces.ReadOnlySignedBeaconBlock { returnedBlk: func() interfaces.SignedBeaconBlock {
wb, err := blocks.NewSignedBeaconBlock(util.NewBlindedBeaconBlockBellatrix()) wb, err := blocks.NewSignedBeaconBlock(util.NewBlindedBeaconBlockBellatrix())
require.NoError(t, err) require.NoError(t, err)
return wb return wb
@@ -407,7 +412,7 @@ func TestServer_getBuilderBlock(t *testing.T) {
}, },
{ {
name: "submit blind block error", name: "submit blind block error",
blk: func() interfaces.ReadOnlySignedBeaconBlock { blk: func() interfaces.SignedBeaconBlock {
b := util.NewBlindedBeaconBlockBellatrix() b := util.NewBlindedBeaconBlockBellatrix()
b.Block.Slot = 1 b.Block.Slot = 1
b.Block.ProposerIndex = 2 b.Block.ProposerIndex = 2
@@ -424,7 +429,7 @@ func TestServer_getBuilderBlock(t *testing.T) {
}, },
{ {
name: "head and payload root mismatch", name: "head and payload root mismatch",
blk: func() interfaces.ReadOnlySignedBeaconBlock { blk: func() interfaces.SignedBeaconBlock {
b := util.NewBlindedBeaconBlockBellatrix() b := util.NewBlindedBeaconBlockBellatrix()
b.Block.Slot = 1 b.Block.Slot = 1
b.Block.ProposerIndex = 2 b.Block.ProposerIndex = 2
@@ -436,7 +441,7 @@ func TestServer_getBuilderBlock(t *testing.T) {
HasConfigured: true, HasConfigured: true,
Payload: p, Payload: p,
}, },
returnedBlk: func() interfaces.ReadOnlySignedBeaconBlock { returnedBlk: func() interfaces.SignedBeaconBlock {
b := util.NewBeaconBlockBellatrix() b := util.NewBeaconBlockBellatrix()
b.Block.Slot = 1 b.Block.Slot = 1
b.Block.ProposerIndex = 2 b.Block.ProposerIndex = 2
@@ -449,7 +454,7 @@ func TestServer_getBuilderBlock(t *testing.T) {
}, },
{ {
name: "can get payload", name: "can get payload",
blk: func() interfaces.ReadOnlySignedBeaconBlock { blk: func() interfaces.SignedBeaconBlock {
b := util.NewBlindedBeaconBlockBellatrix() b := util.NewBlindedBeaconBlockBellatrix()
b.Block.Slot = 1 b.Block.Slot = 1
b.Block.ProposerIndex = 2 b.Block.ProposerIndex = 2
@@ -475,7 +480,7 @@ func TestServer_getBuilderBlock(t *testing.T) {
HasConfigured: true, HasConfigured: true,
Payload: p, Payload: p,
}, },
returnedBlk: func() interfaces.ReadOnlySignedBeaconBlock { returnedBlk: func() interfaces.SignedBeaconBlock {
b := util.NewBeaconBlockBellatrix() b := util.NewBeaconBlockBellatrix()
b.Block.Slot = 1 b.Block.Slot = 1
b.Block.ProposerIndex = 2 b.Block.ProposerIndex = 2

View File

@@ -35,7 +35,7 @@ func (vs *Server) setBlsToExecData(blk interfaces.SignedBeaconBlock, headState s
} }
} }
func (vs *Server) unblindBuilderBlockCapella(ctx context.Context, b interfaces.ReadOnlySignedBeaconBlock) (interfaces.ReadOnlySignedBeaconBlock, error) { func (vs *Server) unblindBuilderBlockCapella(ctx context.Context, b interfaces.SignedBeaconBlock) (interfaces.SignedBeaconBlock, error) {
if err := consensusblocks.BeaconBlockIsNil(b); err != nil { if err := consensusblocks.BeaconBlockIsNil(b); err != nil {
return nil, errors.Wrap(err, "block is nil") return nil, errors.Wrap(err, "block is nil")
} }

View File

@@ -21,10 +21,10 @@ func TestServer_unblindBuilderCapellaBlock(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
blk interfaces.ReadOnlySignedBeaconBlock blk interfaces.SignedBeaconBlock
mock *builderTest.MockBuilderService mock *builderTest.MockBuilderService
err string err string
returnedBlk interfaces.ReadOnlySignedBeaconBlock returnedBlk interfaces.SignedBeaconBlock
}{ }{
{ {
name: "nil block", name: "nil block",
@@ -33,12 +33,12 @@ func TestServer_unblindBuilderCapellaBlock(t *testing.T) {
}, },
{ {
name: "old block version", name: "old block version",
blk: func() interfaces.ReadOnlySignedBeaconBlock { blk: func() interfaces.SignedBeaconBlock {
wb, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlock()) wb, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlock())
require.NoError(t, err) require.NoError(t, err)
return wb return wb
}(), }(),
returnedBlk: func() interfaces.ReadOnlySignedBeaconBlock { returnedBlk: func() interfaces.SignedBeaconBlock {
wb, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlock()) wb, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlock())
require.NoError(t, err) require.NoError(t, err)
return wb return wb
@@ -46,7 +46,7 @@ func TestServer_unblindBuilderCapellaBlock(t *testing.T) {
}, },
{ {
name: "not configured", name: "not configured",
blk: func() interfaces.ReadOnlySignedBeaconBlock { blk: func() interfaces.SignedBeaconBlock {
wb, err := blocks.NewSignedBeaconBlock(util.NewBlindedBeaconBlockBellatrix()) wb, err := blocks.NewSignedBeaconBlock(util.NewBlindedBeaconBlockBellatrix())
require.NoError(t, err) require.NoError(t, err)
return wb return wb
@@ -54,7 +54,7 @@ func TestServer_unblindBuilderCapellaBlock(t *testing.T) {
mock: &builderTest.MockBuilderService{ mock: &builderTest.MockBuilderService{
HasConfigured: false, HasConfigured: false,
}, },
returnedBlk: func() interfaces.ReadOnlySignedBeaconBlock { returnedBlk: func() interfaces.SignedBeaconBlock {
wb, err := blocks.NewSignedBeaconBlock(util.NewBlindedBeaconBlockBellatrix()) wb, err := blocks.NewSignedBeaconBlock(util.NewBlindedBeaconBlockBellatrix())
require.NoError(t, err) require.NoError(t, err)
return wb return wb
@@ -62,7 +62,7 @@ func TestServer_unblindBuilderCapellaBlock(t *testing.T) {
}, },
{ {
name: "submit blind block error", name: "submit blind block error",
blk: func() interfaces.ReadOnlySignedBeaconBlock { blk: func() interfaces.SignedBeaconBlock {
b := util.NewBlindedBeaconBlockCapella() b := util.NewBlindedBeaconBlockCapella()
b.Block.Slot = 1 b.Block.Slot = 1
b.Block.ProposerIndex = 2 b.Block.ProposerIndex = 2
@@ -79,7 +79,7 @@ func TestServer_unblindBuilderCapellaBlock(t *testing.T) {
}, },
{ {
name: "can get payload", name: "can get payload",
blk: func() interfaces.ReadOnlySignedBeaconBlock { blk: func() interfaces.SignedBeaconBlock {
b := util.NewBlindedBeaconBlockCapella() b := util.NewBlindedBeaconBlockCapella()
b.Block.Slot = 1 b.Block.Slot = 1
b.Block.ProposerIndex = 2 b.Block.ProposerIndex = 2
@@ -108,7 +108,7 @@ func TestServer_unblindBuilderCapellaBlock(t *testing.T) {
HasConfigured: true, HasConfigured: true,
PayloadCapella: p, PayloadCapella: p,
}, },
returnedBlk: func() interfaces.ReadOnlySignedBeaconBlock { returnedBlk: func() interfaces.SignedBeaconBlock {
b := util.NewBeaconBlockCapella() b := util.NewBeaconBlockCapella()
b.Block.Slot = 1 b.Block.Slot = 1
b.Block.ProposerIndex = 2 b.Block.ProposerIndex = 2

View File

@@ -30,11 +30,16 @@ func getEmptyBlock(slot primitives.Slot) (interfaces.SignedBeaconBlock, error) {
if err != nil { if err != nil {
return nil, status.Errorf(codes.Internal, "Could not initialize block for proposal: %v", err) return nil, status.Errorf(codes.Internal, "Could not initialize block for proposal: %v", err)
} }
default: case slots.ToEpoch(slot) < params.BeaconConfig().DenebForkEpoch:
sBlk, err = blocks.NewSignedBeaconBlock(&ethpb.SignedBeaconBlockCapella{Block: &ethpb.BeaconBlockCapella{Body: &ethpb.BeaconBlockBodyCapella{}}}) sBlk, err = blocks.NewSignedBeaconBlock(&ethpb.SignedBeaconBlockCapella{Block: &ethpb.BeaconBlockCapella{Body: &ethpb.BeaconBlockBodyCapella{}}})
if err != nil { if err != nil {
return nil, status.Errorf(codes.Internal, "Could not initialize block for proposal: %v", err) return nil, status.Errorf(codes.Internal, "Could not initialize block for proposal: %v", err)
} }
default:
sBlk, err = blocks.NewSignedBeaconBlock(&ethpb.SignedBeaconBlockDeneb{Block: &ethpb.BeaconBlockDeneb{Body: &ethpb.BeaconBlockBodyDeneb{}}})
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not initialize block for proposal: %v", err)
}
} }
return sBlk, err return sBlk, err
} }

View File

@@ -40,9 +40,10 @@ var (
}) })
) )
// This returns the execution payload of a given slot. The function has full awareness of pre and post merge. // This returns the execution payload of a given slot.
// The function has full awareness of pre and post merge.
// The payload is computed given the respected time of merge. // The payload is computed given the respected time of merge.
func (vs *Server) getExecutionPayload(ctx context.Context, slot primitives.Slot, vIdx primitives.ValidatorIndex, headRoot [32]byte, st state.BeaconState) (interfaces.ExecutionData, error) { func (vs *Server) getExecutionPayload(ctx context.Context, slot primitives.Slot, vIdx primitives.ValidatorIndex, headRoot [32]byte, st state.BeaconState) (interfaces.ExecutionData, *enginev1.BlobsBundle, error) {
proposerID, payloadId, ok := vs.ProposerSlotIndexCache.GetProposerPayloadIDs(slot, headRoot) proposerID, payloadId, ok := vs.ProposerSlotIndexCache.GetProposerPayloadIDs(slot, headRoot)
feeRecipient := params.BeaconConfig().DefaultFeeRecipient feeRecipient := params.BeaconConfig().DefaultFeeRecipient
recipient, err := vs.BeaconDB.FeeRecipientByValidatorID(ctx, vIdx) recipient, err := vs.BeaconDB.FeeRecipientByValidatorID(ctx, vIdx)
@@ -62,7 +63,7 @@ func (vs *Server) getExecutionPayload(ctx context.Context, slot primitives.Slot,
"Please refer to our documentation for instructions") "Please refer to our documentation for instructions")
} }
default: default:
return nil, errors.Wrap(err, "could not get fee recipient in db") return nil, nil, errors.Wrap(err, "could not get fee recipient in db")
} }
if ok && proposerID == vIdx && payloadId != [8]byte{} { // Payload ID is cache hit. Return the cached payload ID. if ok && proposerID == vIdx && payloadId != [8]byte{} { // Payload ID is cache hit. Return the cached payload ID.
@@ -73,10 +74,17 @@ func (vs *Server) getExecutionPayload(ctx context.Context, slot primitives.Slot,
switch { switch {
case err == nil: case err == nil:
warnIfFeeRecipientDiffers(payload, feeRecipient) warnIfFeeRecipientDiffers(payload, feeRecipient)
return payload, nil if slots.ToEpoch(slot) >= params.BeaconConfig().DenebForkEpoch {
sc, err := vs.ExecutionEngineCaller.GetBlobsBundle(ctx, pid)
if err != nil {
return nil, nil, errors.Wrap(err, "could not get blobs bundle from execution client")
}
return payload, sc, nil
}
return payload, nil, nil
case errors.Is(err, context.DeadlineExceeded): case errors.Is(err, context.DeadlineExceeded):
default: default:
return nil, errors.Wrap(err, "could not get cached payload from execution client") return nil, nil, errors.Wrap(err, "could not get cached payload from execution client")
} }
} }
@@ -84,53 +92,61 @@ func (vs *Server) getExecutionPayload(ctx context.Context, slot primitives.Slot,
var hasTerminalBlock bool var hasTerminalBlock bool
mergeComplete, err := blocks.IsMergeTransitionComplete(st) mergeComplete, err := blocks.IsMergeTransitionComplete(st)
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
t, err := slots.ToTime(st.GenesisTime(), slot) t, err := slots.ToTime(st.GenesisTime(), slot)
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
if mergeComplete { if mergeComplete {
header, err := st.LatestExecutionPayloadHeader() header, err := st.LatestExecutionPayloadHeader()
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
parentHash = header.BlockHash() parentHash = header.BlockHash()
} else { } else {
if activationEpochNotReached(slot) { if activationEpochNotReached(slot) {
return consensusblocks.WrappedExecutionPayload(emptyPayload()) p, err := consensusblocks.WrappedExecutionPayload(emptyPayload())
if err != nil {
return nil, nil, err
}
return p, nil, nil
} }
parentHash, hasTerminalBlock, err = vs.getTerminalBlockHashIfExists(ctx, uint64(t.Unix())) parentHash, hasTerminalBlock, err = vs.getTerminalBlockHashIfExists(ctx, uint64(t.Unix()))
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
if !hasTerminalBlock { if !hasTerminalBlock {
return consensusblocks.WrappedExecutionPayload(emptyPayload()) p, err := consensusblocks.WrappedExecutionPayload(emptyPayload())
if err != nil {
return nil, nil, err
}
return p, nil, nil
} }
} }
payloadIDCacheMiss.Inc() payloadIDCacheMiss.Inc()
random, err := helpers.RandaoMix(st, time.CurrentEpoch(st)) random, err := helpers.RandaoMix(st, time.CurrentEpoch(st))
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
finalizedBlockHash := params.BeaconConfig().ZeroHash[:] finalizedBlockHash := params.BeaconConfig().ZeroHash[:]
finalizedRoot := bytesutil.ToBytes32(st.FinalizedCheckpoint().Root) finalizedRoot := bytesutil.ToBytes32(st.FinalizedCheckpoint().Root)
if finalizedRoot != [32]byte{} { // finalized root could be zeros before the first finalized block. if finalizedRoot != [32]byte{} { // finalized root could be zeros before the first finalized block.
finalizedBlock, err := vs.BeaconDB.Block(ctx, bytesutil.ToBytes32(st.FinalizedCheckpoint().Root)) finalizedBlock, err := vs.BeaconDB.Block(ctx, bytesutil.ToBytes32(st.FinalizedCheckpoint().Root))
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
if err := consensusblocks.BeaconBlockIsNil(finalizedBlock); err != nil { if err := consensusblocks.BeaconBlockIsNil(finalizedBlock); err != nil {
return nil, err return nil, nil, err
} }
switch finalizedBlock.Version() { switch finalizedBlock.Version() {
case version.Phase0, version.Altair: // Blocks before Bellatrix don't have execution payloads. Use zeros as the hash. case version.Phase0, version.Altair: // Blocks before Bellatrix don't have execution payloads. Use zeros as the hash.
default: default:
finalizedPayload, err := finalizedBlock.Block().Body().Execution() finalizedPayload, err := finalizedBlock.Block().Body().Execution()
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
finalizedBlockHash = finalizedPayload.BlockHash() finalizedBlockHash = finalizedPayload.BlockHash()
} }
@@ -143,10 +159,10 @@ func (vs *Server) getExecutionPayload(ctx context.Context, slot primitives.Slot,
} }
var attr payloadattribute.Attributer var attr payloadattribute.Attributer
switch st.Version() { switch st.Version() {
case version.Capella: case version.Capella, version.Deneb:
withdrawals, err := st.ExpectedWithdrawals() withdrawals, err := st.ExpectedWithdrawals()
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
attr, err = payloadattribute.New(&enginev1.PayloadAttributesV2{ attr, err = payloadattribute.New(&enginev1.PayloadAttributesV2{
Timestamp: uint64(t.Unix()), Timestamp: uint64(t.Unix()),
@@ -155,7 +171,7 @@ func (vs *Server) getExecutionPayload(ctx context.Context, slot primitives.Slot,
Withdrawals: withdrawals, Withdrawals: withdrawals,
}) })
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
case version.Bellatrix: case version.Bellatrix:
attr, err = payloadattribute.New(&enginev1.PayloadAttributes{ attr, err = payloadattribute.New(&enginev1.PayloadAttributes{
@@ -164,25 +180,32 @@ func (vs *Server) getExecutionPayload(ctx context.Context, slot primitives.Slot,
SuggestedFeeRecipient: feeRecipient.Bytes(), SuggestedFeeRecipient: feeRecipient.Bytes(),
}) })
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
default: default:
return nil, errors.New("unknown beacon state version") return nil, nil, errors.New("unknown beacon state version")
} }
payloadID, _, err := vs.ExecutionEngineCaller.ForkchoiceUpdated(ctx, f, attr) payloadID, _, err := vs.ExecutionEngineCaller.ForkchoiceUpdated(ctx, f, attr)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not prepare payload") return nil, nil, errors.Wrap(err, "could not prepare payload")
} }
if payloadID == nil { if payloadID == nil {
return nil, fmt.Errorf("nil payload with block hash: %#x", parentHash) return nil, nil, fmt.Errorf("nil payload with block hash: %#x", parentHash)
} }
payload, err := vs.ExecutionEngineCaller.GetPayload(ctx, *payloadID, slot) payload, err := vs.ExecutionEngineCaller.GetPayload(ctx, *payloadID, slot)
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
warnIfFeeRecipientDiffers(payload, feeRecipient) warnIfFeeRecipientDiffers(payload, feeRecipient)
return payload, nil if slots.ToEpoch(slot) >= params.BeaconConfig().DenebForkEpoch {
sc, err := vs.ExecutionEngineCaller.GetBlobsBundle(ctx, *payloadID)
if err != nil {
return nil, nil, errors.Wrap(err, "could not get blobs bundle from execution client")
}
return payload, sc, nil
}
return payload, nil, nil
} }
// warnIfFeeRecipientDiffers logs a warning if the fee recipient in the included payload does not // warnIfFeeRecipientDiffers logs a warning if the fee recipient in the included payload does not

View File

@@ -143,7 +143,7 @@ func TestServer_getExecutionPayload(t *testing.T) {
ProposerSlotIndexCache: cache.NewProposerPayloadIDsCache(), ProposerSlotIndexCache: cache.NewProposerPayloadIDsCache(),
} }
vs.ProposerSlotIndexCache.SetProposerAndPayloadIDs(tt.st.Slot(), 100, [8]byte{100}, [32]byte{'a'}) vs.ProposerSlotIndexCache.SetProposerAndPayloadIDs(tt.st.Slot(), 100, [8]byte{100}, [32]byte{'a'})
_, err := vs.getExecutionPayload(context.Background(), tt.st.Slot(), tt.validatorIndx, [32]byte{'a'}, tt.st) _, _, err := vs.getExecutionPayload(context.Background(), tt.st.Slot(), tt.validatorIndx, [32]byte{'a'}, tt.st)
if tt.errString != "" { if tt.errString != "" {
require.ErrorContains(t, tt.errString, err) require.ErrorContains(t, tt.errString, err)
} else { } else {
@@ -179,7 +179,7 @@ func TestServer_getExecutionPayloadContextTimeout(t *testing.T) {
} }
vs.ProposerSlotIndexCache.SetProposerAndPayloadIDs(nonTransitionSt.Slot(), 100, [8]byte{100}, [32]byte{'a'}) vs.ProposerSlotIndexCache.SetProposerAndPayloadIDs(nonTransitionSt.Slot(), 100, [8]byte{100}, [32]byte{'a'})
_, err = vs.getExecutionPayload(context.Background(), nonTransitionSt.Slot(), 100, [32]byte{'a'}, nonTransitionSt) _, _, err = vs.getExecutionPayload(context.Background(), nonTransitionSt.Slot(), 100, [32]byte{'a'}, nonTransitionSt)
require.NoError(t, err) require.NoError(t, err)
} }
@@ -224,7 +224,7 @@ func TestServer_getExecutionPayload_UnexpectedFeeRecipient(t *testing.T) {
BeaconDB: beaconDB, BeaconDB: beaconDB,
ProposerSlotIndexCache: cache.NewProposerPayloadIDsCache(), ProposerSlotIndexCache: cache.NewProposerPayloadIDsCache(),
} }
gotPayload, err := vs.getExecutionPayload(context.Background(), transitionSt.Slot(), 0, [32]byte{}, transitionSt) gotPayload, _, err := vs.getExecutionPayload(context.Background(), transitionSt.Slot(), 0, [32]byte{}, transitionSt)
require.NoError(t, err) require.NoError(t, err)
require.NotNil(t, gotPayload) require.NotNil(t, gotPayload)
@@ -236,7 +236,7 @@ func TestServer_getExecutionPayload_UnexpectedFeeRecipient(t *testing.T) {
payload.FeeRecipient = evilRecipientAddress[:] payload.FeeRecipient = evilRecipientAddress[:]
vs.ProposerSlotIndexCache = cache.NewProposerPayloadIDsCache() vs.ProposerSlotIndexCache = cache.NewProposerPayloadIDsCache()
gotPayload, err = vs.getExecutionPayload(context.Background(), transitionSt.Slot(), 0, [32]byte{}, transitionSt) gotPayload, _, err = vs.getExecutionPayload(context.Background(), transitionSt.Slot(), 0, [32]byte{}, transitionSt)
require.NoError(t, err) require.NoError(t, err)
require.NotNil(t, gotPayload) require.NotNil(t, gotPayload)

View File

@@ -8,6 +8,7 @@ import (
"net" "net"
"sync" "sync"
"github.com/gorilla/mux"
middleware "github.com/grpc-ecosystem/go-grpc-middleware" middleware "github.com/grpc-ecosystem/go-grpc-middleware"
recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery" recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery"
grpcopentracing "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing" grpcopentracing "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing"
@@ -32,12 +33,13 @@ import (
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/debug" "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/debug"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/events" "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/events"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/node" "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/node"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/rewards"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/validator" "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/validator"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/lookup"
beaconv1alpha1 "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/prysm/v1alpha1/beacon" beaconv1alpha1 "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/prysm/v1alpha1/beacon"
debugv1alpha1 "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/prysm/v1alpha1/debug" debugv1alpha1 "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/prysm/v1alpha1/debug"
nodev1alpha1 "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/prysm/v1alpha1/node" nodev1alpha1 "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/prysm/v1alpha1/node"
validatorv1alpha1 "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/prysm/v1alpha1/validator" validatorv1alpha1 "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/prysm/v1alpha1/validator"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/statefetcher"
slasherservice "github.com/prysmaticlabs/prysm/v4/beacon-chain/slasher" slasherservice "github.com/prysmaticlabs/prysm/v4/beacon-chain/slasher"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state/stategen" "github.com/prysmaticlabs/prysm/v4/beacon-chain/state/stategen"
chainSync "github.com/prysmaticlabs/prysm/v4/beacon-chain/sync" chainSync "github.com/prysmaticlabs/prysm/v4/beacon-chain/sync"
@@ -117,6 +119,7 @@ type Config struct {
ProposerIdsCache *cache.ProposerPayloadIDsCache ProposerIdsCache *cache.ProposerPayloadIDsCache
OptimisticModeFetcher blockchain.OptimisticModeFetcher OptimisticModeFetcher blockchain.OptimisticModeFetcher
BlockBuilder builder.BlockBuilder BlockBuilder builder.BlockBuilder
Router *mux.Router
} }
// NewService instantiates a new RPC service instance that will // NewService instantiates a new RPC service instance that will
@@ -189,6 +192,25 @@ func (s *Service) Start() {
} }
withCache := stategen.WithCache(stateCache) withCache := stategen.WithCache(stateCache)
ch := stategen.NewCanonicalHistory(s.cfg.BeaconDB, s.cfg.ChainInfoFetcher, s.cfg.ChainInfoFetcher, withCache) ch := stategen.NewCanonicalHistory(s.cfg.BeaconDB, s.cfg.ChainInfoFetcher, s.cfg.ChainInfoFetcher, withCache)
stater := &lookup.BeaconDbStater{
BeaconDB: s.cfg.BeaconDB,
ChainInfoFetcher: s.cfg.ChainInfoFetcher,
GenesisTimeFetcher: s.cfg.GenesisTimeFetcher,
StateGenService: s.cfg.StateGen,
ReplayerBuilder: ch,
}
blocker := &lookup.BeaconDbBlocker{
BeaconDB: s.cfg.BeaconDB,
ChainInfoFetcher: s.cfg.ChainInfoFetcher,
}
rewardsServer := &rewards.Server{
Blocker: blocker,
OptimisticModeFetcher: s.cfg.OptimisticModeFetcher,
FinalizationFetcher: s.cfg.FinalizationFetcher,
ReplayerBuilder: ch,
}
s.cfg.Router.HandleFunc("/eth/v1/beacon/rewards/blocks/{block_id}", rewardsServer.BlockRewards)
validatorServer := &validatorv1alpha1.Server{ validatorServer := &validatorv1alpha1.Server{
Ctx: s.ctx, Ctx: s.ctx,
@@ -226,21 +248,15 @@ func (s *Service) Start() {
BLSChangesPool: s.cfg.BLSChangesPool, BLSChangesPool: s.cfg.BLSChangesPool,
} }
validatorServerV1 := &validator.Server{ validatorServerV1 := &validator.Server{
HeadFetcher: s.cfg.HeadFetcher, HeadFetcher: s.cfg.HeadFetcher,
TimeFetcher: s.cfg.GenesisTimeFetcher, TimeFetcher: s.cfg.GenesisTimeFetcher,
SyncChecker: s.cfg.SyncService, SyncChecker: s.cfg.SyncService,
OptimisticModeFetcher: s.cfg.OptimisticModeFetcher, OptimisticModeFetcher: s.cfg.OptimisticModeFetcher,
AttestationsPool: s.cfg.AttestationsPool, AttestationsPool: s.cfg.AttestationsPool,
PeerManager: s.cfg.PeerManager, PeerManager: s.cfg.PeerManager,
Broadcaster: s.cfg.Broadcaster, Broadcaster: s.cfg.Broadcaster,
V1Alpha1Server: validatorServer, V1Alpha1Server: validatorServer,
StateFetcher: &statefetcher.StateProvider{ Stater: stater,
BeaconDB: s.cfg.BeaconDB,
ChainInfoFetcher: s.cfg.ChainInfoFetcher,
GenesisTimeFetcher: s.cfg.GenesisTimeFetcher,
StateGenService: s.cfg.StateGen,
ReplayerBuilder: ch,
},
SyncCommitteePool: s.cfg.SyncCommitteeObjectPool, SyncCommitteePool: s.cfg.SyncCommitteeObjectPool,
ProposerSlotIndexCache: s.cfg.ProposerIdsCache, ProposerSlotIndexCache: s.cfg.ProposerIdsCache,
ChainInfoFetcher: s.cfg.ChainInfoFetcher, ChainInfoFetcher: s.cfg.ChainInfoFetcher,
@@ -298,24 +314,19 @@ func (s *Service) Start() {
ReplayerBuilder: ch, ReplayerBuilder: ch,
} }
beaconChainServerV1 := &beacon.Server{ beaconChainServerV1 := &beacon.Server{
CanonicalHistory: ch, CanonicalHistory: ch,
BeaconDB: s.cfg.BeaconDB, BeaconDB: s.cfg.BeaconDB,
AttestationsPool: s.cfg.AttestationsPool, AttestationsPool: s.cfg.AttestationsPool,
SlashingsPool: s.cfg.SlashingsPool, SlashingsPool: s.cfg.SlashingsPool,
ChainInfoFetcher: s.cfg.ChainInfoFetcher, ChainInfoFetcher: s.cfg.ChainInfoFetcher,
GenesisTimeFetcher: s.cfg.GenesisTimeFetcher, GenesisTimeFetcher: s.cfg.GenesisTimeFetcher,
BlockNotifier: s.cfg.BlockNotifier, BlockNotifier: s.cfg.BlockNotifier,
OperationNotifier: s.cfg.OperationNotifier, OperationNotifier: s.cfg.OperationNotifier,
Broadcaster: s.cfg.Broadcaster, Broadcaster: s.cfg.Broadcaster,
BlockReceiver: s.cfg.BlockReceiver, BlockReceiver: s.cfg.BlockReceiver,
StateGenService: s.cfg.StateGen, StateGenService: s.cfg.StateGen,
StateFetcher: &statefetcher.StateProvider{ Stater: stater,
BeaconDB: s.cfg.BeaconDB, Blocker: blocker,
ChainInfoFetcher: s.cfg.ChainInfoFetcher,
GenesisTimeFetcher: s.cfg.GenesisTimeFetcher,
StateGenService: s.cfg.StateGen,
ReplayerBuilder: ch,
},
OptimisticModeFetcher: s.cfg.OptimisticModeFetcher, OptimisticModeFetcher: s.cfg.OptimisticModeFetcher,
HeadFetcher: s.cfg.HeadFetcher, HeadFetcher: s.cfg.HeadFetcher,
VoluntaryExitsPool: s.cfg.ExitPool, VoluntaryExitsPool: s.cfg.ExitPool,
@@ -350,15 +361,9 @@ func (s *Service) Start() {
ReplayerBuilder: ch, ReplayerBuilder: ch,
} }
debugServerV1 := &debug.Server{ debugServerV1 := &debug.Server{
BeaconDB: s.cfg.BeaconDB, BeaconDB: s.cfg.BeaconDB,
HeadFetcher: s.cfg.HeadFetcher, HeadFetcher: s.cfg.HeadFetcher,
StateFetcher: &statefetcher.StateProvider{ Stater: stater,
BeaconDB: s.cfg.BeaconDB,
ChainInfoFetcher: s.cfg.ChainInfoFetcher,
GenesisTimeFetcher: s.cfg.GenesisTimeFetcher,
StateGenService: s.cfg.StateGen,
ReplayerBuilder: ch,
},
OptimisticModeFetcher: s.cfg.OptimisticModeFetcher, OptimisticModeFetcher: s.cfg.OptimisticModeFetcher,
ForkFetcher: s.cfg.ForkFetcher, ForkFetcher: s.cfg.ForkFetcher,
ForkchoiceFetcher: s.cfg.ForkchoiceFetcher, ForkchoiceFetcher: s.cfg.ForkchoiceFetcher,

View File

@@ -7,6 +7,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/gorilla/mux"
mock "github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain/testing" mock "github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain/testing"
mockExecution "github.com/prysmaticlabs/prysm/v4/beacon-chain/execution/testing" mockExecution "github.com/prysmaticlabs/prysm/v4/beacon-chain/execution/testing"
mockSync "github.com/prysmaticlabs/prysm/v4/beacon-chain/sync/initial-sync/testing" mockSync "github.com/prysmaticlabs/prysm/v4/beacon-chain/sync/initial-sync/testing"
@@ -35,6 +36,7 @@ func TestLifecycle_OK(t *testing.T) {
GenesisTimeFetcher: chainService, GenesisTimeFetcher: chainService,
ExecutionChainService: &mockExecution.Chain{}, ExecutionChainService: &mockExecution.Chain{},
StateNotifier: chainService.StateNotifier(), StateNotifier: chainService.StateNotifier(),
Router: mux.NewRouter(),
}) })
rpcService.Start() rpcService.Start()
@@ -75,6 +77,7 @@ func TestRPC_InsecureEndpoint(t *testing.T) {
HeadFetcher: chainService, HeadFetcher: chainService,
ExecutionChainService: &mockExecution.Chain{}, ExecutionChainService: &mockExecution.Chain{},
StateNotifier: chainService.StateNotifier(), StateNotifier: chainService.StateNotifier(),
Router: mux.NewRouter(),
}) })
rpcService.Start() rpcService.Start()

View File

@@ -4,15 +4,24 @@ go_library(
name = "go_default_library", name = "go_default_library",
testonly = True, testonly = True,
srcs = [ srcs = [
"db.go",
"mock_blocker.go",
"mock_exec_chain_info_fetcher.go", "mock_exec_chain_info_fetcher.go",
"mock_genesis_timefetcher.go", "mock_genesis_timefetcher.go",
"mock_state_fetcher.go", "mock_stater.go",
], ],
importpath = "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/testutil", importpath = "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/testutil",
visibility = ["//beacon-chain:__subpackages__"], visibility = ["//beacon-chain:__subpackages__"],
deps = [ deps = [
"//beacon-chain/db:go_default_library",
"//beacon-chain/state:go_default_library", "//beacon-chain/state:go_default_library",
"//config/params: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", "//consensus-types/primitives:go_default_library",
"//encoding/bytesutil:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//testing/require:go_default_library",
"//testing/util:go_default_library",
], ],
) )

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