mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-10 05:47:59 -05:00
Compare commits
675 Commits
release-v5
...
migrate-rp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1f3056ac84 | ||
|
|
4ab86838b8 | ||
|
|
203ac12216 | ||
|
|
2e0d4ac184 | ||
|
|
9c598ea9aa | ||
|
|
2cfc204e9a | ||
|
|
e859fc4e09 | ||
|
|
c0021f91c2 | ||
|
|
877d9ee948 | ||
|
|
785fefa3f1 | ||
|
|
0c22d91a55 | ||
|
|
fb60456116 | ||
|
|
be56711892 | ||
|
|
370ae9a12c | ||
|
|
96f1ebf706 | ||
|
|
fb755c7f3b | ||
|
|
bdb12c7d2f | ||
|
|
83cf0f8658 | ||
|
|
762594a368 | ||
|
|
c1fc812a38 | ||
|
|
340935af9c | ||
|
|
17d0082c5c | ||
|
|
e998b5ec97 | ||
|
|
5d0eb3168c | ||
|
|
e0c2aa71d4 | ||
|
|
6eff474042 | ||
|
|
70c31949ba | ||
|
|
e38fdb09a4 | ||
|
|
a50e981c74 | ||
|
|
8be205cf3d | ||
|
|
1b65e00096 | ||
|
|
e3fb4e86ec | ||
|
|
70aaad1904 | ||
|
|
e42611ec72 | ||
|
|
a3e61275a3 | ||
|
|
e82f9ccca3 | ||
|
|
38a6a7a4ea | ||
|
|
1295c987e8 | ||
|
|
6a27c41aad | ||
|
|
98b13ea144 | ||
|
|
c735ed2e32 | ||
|
|
bd17779231 | ||
|
|
e08ed0d823 | ||
|
|
2b4d8a09ff | ||
|
|
21e1f7883b | ||
|
|
bfa24606c3 | ||
|
|
d7628bab37 | ||
|
|
8e2c9313e9 | ||
|
|
fea441d889 | ||
|
|
2351064e8d | ||
|
|
d2699761ed | ||
|
|
c73473b59d | ||
|
|
2aa52fb56a | ||
|
|
16d5abd21b | ||
|
|
08bfaca42d | ||
|
|
179cedd4a0 | ||
|
|
0f39857653 | ||
|
|
645328bb9e | ||
|
|
9d2273c514 | ||
|
|
34429368fe | ||
|
|
629568c796 | ||
|
|
5c24978702 | ||
|
|
4e44999207 | ||
|
|
15ae71c0da | ||
|
|
1caea86152 | ||
|
|
7cef3b0491 | ||
|
|
15462844f9 | ||
|
|
863eee7b40 | ||
|
|
6d89373583 | ||
|
|
9a421a2feb | ||
|
|
4e41d5c610 | ||
|
|
0b6bea43a8 | ||
|
|
f89afb0fbd | ||
|
|
3cd2973c92 | ||
|
|
d3e5710a63 | ||
|
|
f40b4f16c2 | ||
|
|
7fd4f746d6 | ||
|
|
2362d9f3c2 | ||
|
|
6b84f8c6b1 | ||
|
|
997a9112d1 | ||
|
|
d46ca97680 | ||
|
|
417bbf8a9e | ||
|
|
a7b016c954 | ||
|
|
6015493de9 | ||
|
|
c718bdbe2b | ||
|
|
0a8f947169 | ||
|
|
d7efccf6a5 | ||
|
|
334920bc9e | ||
|
|
6e00db433c | ||
|
|
c6344e7c3e | ||
|
|
2131254722 | ||
|
|
b6d1866deb | ||
|
|
e56f489d06 | ||
|
|
bf62afb27c | ||
|
|
8369056027 | ||
|
|
09499a732f | ||
|
|
2ee015452c | ||
|
|
ffc1bf8bbe | ||
|
|
014dbd5c3a | ||
|
|
9bceaa59d2 | ||
|
|
832ebb3f39 | ||
|
|
8345c271cc | ||
|
|
56208aa84d | ||
|
|
b866a2c744 | ||
|
|
a77234e637 | ||
|
|
e0e7354708 | ||
|
|
0f86a16915 | ||
|
|
972c22b02f | ||
|
|
93c27340e4 | ||
|
|
c3edb32558 | ||
|
|
3baaa732df | ||
|
|
8ceb7e76ea | ||
|
|
4d5dddd302 | ||
|
|
55efccb07f | ||
|
|
961d8e1481 | ||
|
|
d396a9931e | ||
|
|
e3f8f121f4 | ||
|
|
80f29e9eda | ||
|
|
8995d8133a | ||
|
|
31044206b8 | ||
|
|
3a1702e56f | ||
|
|
501ec74a48 | ||
|
|
c248fe0bb3 | ||
|
|
215fbcb2e4 | ||
|
|
e39f44b529 | ||
|
|
9eff6ae476 | ||
|
|
3eec5a5cb6 | ||
|
|
66878deb2c | ||
|
|
0b6e1711e4 | ||
|
|
15025837bb | ||
|
|
0229a2055e | ||
|
|
eb9af15c7a | ||
|
|
0584746815 | ||
|
|
8c4ea850ba | ||
|
|
4b43f13e65 | ||
|
|
26d35474e9 | ||
|
|
9fbe3564df | ||
|
|
bed5547890 | ||
|
|
47922fe7d8 | ||
|
|
dcd25d1d97 | ||
|
|
81a2a17c5f | ||
|
|
6b3f1de19d | ||
|
|
7c17af2a41 | ||
|
|
ecf5a368d7 | ||
|
|
557c5be433 | ||
|
|
49405c3afd | ||
|
|
3439122629 | ||
|
|
f6e5da6723 | ||
|
|
842f241cb9 | ||
|
|
41daac1b04 | ||
|
|
2a7fc84044 | ||
|
|
44ff0b1a14 | ||
|
|
91cdd318a8 | ||
|
|
3dc00816fb | ||
|
|
e331d5b371 | ||
|
|
8d5090ce54 | ||
|
|
25244d906d | ||
|
|
aa445713ac | ||
|
|
177769a1ce | ||
|
|
967e9255a2 | ||
|
|
910609a75f | ||
|
|
f9c202190a | ||
|
|
4a63a194b1 | ||
|
|
d887536eb7 | ||
|
|
1069da1cd2 | ||
|
|
4a487ba3bc | ||
|
|
bf81cd4449 | ||
|
|
00337fe005 | ||
|
|
bb3fba4d8e | ||
|
|
89967fe209 | ||
|
|
56712b5e49 | ||
|
|
0be9391e62 | ||
|
|
4a9c60f75f | ||
|
|
9cf6b93356 | ||
|
|
b4220e35c4 | ||
|
|
536cded4cc | ||
|
|
86fc64c917 | ||
|
|
5d6a406829 | ||
|
|
2c78e501b3 | ||
|
|
c8cb0f37b2 | ||
|
|
78722239da | ||
|
|
3ffef024c7 | ||
|
|
a1eef44492 | ||
|
|
2845ab9365 | ||
|
|
4f43c15ebb | ||
|
|
e473d7cc4d | ||
|
|
794a05af26 | ||
|
|
15df13c7e6 | ||
|
|
b76f7fed2f | ||
|
|
e263687ea5 | ||
|
|
0b16c79c35 | ||
|
|
dc002c2806 | ||
|
|
e7e48dcaf9 | ||
|
|
8f43f6cc84 | ||
|
|
e07341e1d5 | ||
|
|
ef293e52f8 | ||
|
|
72cc63a6a3 | ||
|
|
34ff4c3ea9 | ||
|
|
e8c968326a | ||
|
|
2000ef457b | ||
|
|
e36564c4d3 | ||
|
|
e5784d09f0 | ||
|
|
e577bb0dcf | ||
|
|
153d1872ae | ||
|
|
80aa811ab9 | ||
|
|
39cf2c8f06 | ||
|
|
e99df5e489 | ||
|
|
393e63e8e5 | ||
|
|
c48d40907c | ||
|
|
a21f544219 | ||
|
|
705a9e8dcd | ||
|
|
2dcb015470 | ||
|
|
211e1a4b7c | ||
|
|
1efca9c28d | ||
|
|
97d7ca828b | ||
|
|
31df250496 | ||
|
|
8a439a6f5d | ||
|
|
8cff9356f1 | ||
|
|
afeb05c9a1 | ||
|
|
fa16232924 | ||
|
|
1f720bdbf4 | ||
|
|
79ea77ff57 | ||
|
|
d35cd0788e | ||
|
|
093e3df80a | ||
|
|
699a3b07a7 | ||
|
|
937d441e2e | ||
|
|
ead08d56d0 | ||
|
|
f55e62287a | ||
|
|
c7b2838873 | ||
|
|
9e7c1d6af6 | ||
|
|
6ce6b869e5 | ||
|
|
dbd53bd70d | ||
|
|
d04b361cc3 | ||
|
|
96b31a9f64 | ||
|
|
a7c3004115 | ||
|
|
30d5749ef6 | ||
|
|
bc69ab8a44 | ||
|
|
ed7b511949 | ||
|
|
0b7c005d7d | ||
|
|
65e8c37b48 | ||
|
|
689015ff01 | ||
|
|
08c14f02f6 | ||
|
|
4bb0b44f16 | ||
|
|
29237cb0bc | ||
|
|
2b25ede641 | ||
|
|
b7de64a340 | ||
|
|
11aa51e033 | ||
|
|
fa0dc09ce0 | ||
|
|
d93a1b671c | ||
|
|
1d8ffadd4f | ||
|
|
ac1717f1e4 | ||
|
|
6e6012b12f | ||
|
|
008f157e17 | ||
|
|
7afb8c3c86 | ||
|
|
e925d35d55 | ||
|
|
1f2d8cfae9 | ||
|
|
63bc965ddc | ||
|
|
a0791d77eb | ||
|
|
0d810a1fd6 | ||
|
|
92bbf6344c | ||
|
|
df81fa3e9a | ||
|
|
30a136f1fb | ||
|
|
b23c562b67 | ||
|
|
ae36630ccd | ||
|
|
ac72fe2e0e | ||
|
|
d09885b7ce | ||
|
|
dc643c9f32 | ||
|
|
9fa49e7bc9 | ||
|
|
1139c90ab2 | ||
|
|
79d05a87bb | ||
|
|
1707cf3ec7 | ||
|
|
bdbb850250 | ||
|
|
b28b1ed6ce | ||
|
|
74bb0821a8 | ||
|
|
8025a483e2 | ||
|
|
0475631543 | ||
|
|
f27092fa91 | ||
|
|
67cef41cbf | ||
|
|
258908d50e | ||
|
|
415a42a4aa | ||
|
|
25eae3acda | ||
|
|
956d9d108c | ||
|
|
c285715f9f | ||
|
|
9382ae736d | ||
|
|
f16ff45a6b | ||
|
|
8d6577be84 | ||
|
|
9de75b5376 | ||
|
|
a7ba11df37 | ||
|
|
00aeea3656 | ||
|
|
9dbf979e77 | ||
|
|
be60504512 | ||
|
|
1857496159 | ||
|
|
ccf61e1700 | ||
|
|
4edbd2f9ef | ||
|
|
5179af1438 | ||
|
|
c0f9689e30 | ||
|
|
ff8240a04f | ||
|
|
847498c648 | ||
|
|
2633684339 | ||
|
|
ab3f1963e2 | ||
|
|
b87d02eeb3 | ||
|
|
bcb4155523 | ||
|
|
77f10b9e0e | ||
|
|
928b707ef1 | ||
|
|
91c15247e5 | ||
|
|
5ef5b65ffe | ||
|
|
9ae97786c5 | ||
|
|
66d1bb54f6 | ||
|
|
4d98049054 | ||
|
|
d5ff25b59d | ||
|
|
a265cf08fa | ||
|
|
f2ade3caff | ||
|
|
e6ffc0701e | ||
|
|
61c296e075 | ||
|
|
f264680739 | ||
|
|
8fe024f6a1 | ||
|
|
6b7dd833a3 | ||
|
|
060527032b | ||
|
|
a29ecb6bbe | ||
|
|
54656e172f | ||
|
|
97c8adb003 | ||
|
|
2fe8614115 | ||
|
|
09accc7132 | ||
|
|
53f1f11c6d | ||
|
|
48fe9d9c4d | ||
|
|
4386c244e1 | ||
|
|
7ac522d8ff | ||
|
|
52cf3a155d | ||
|
|
83ed320826 | ||
|
|
616cdc1e8b | ||
|
|
361712e886 | ||
|
|
9ec8c6c4b5 | ||
|
|
073cf19b69 | ||
|
|
6ac8090599 | ||
|
|
4aa54107e4 | ||
|
|
ffc443b5f2 | ||
|
|
d6c5692dc0 | ||
|
|
1086bdf2b3 | ||
|
|
2afa63b442 | ||
|
|
5a5193c59d | ||
|
|
c8d3ed02cb | ||
|
|
30fcf5366a | ||
|
|
f776b968ad | ||
|
|
de094b0078 | ||
|
|
0a4ed8279b | ||
|
|
f307a369a5 | ||
|
|
dc91c963b9 | ||
|
|
7238848d81 | ||
|
|
80cafaa6df | ||
|
|
8a0545c3d7 | ||
|
|
9c61117b71 | ||
|
|
6c22edeecc | ||
|
|
57cc4950c0 | ||
|
|
2c981d5564 | ||
|
|
492c8af83f | ||
|
|
e40d2cbd2c | ||
|
|
3fa6d3bd9d | ||
|
|
56f0eb1437 | ||
|
|
7fc5c714a1 | ||
|
|
cfbfccb203 | ||
|
|
884b663455 | ||
|
|
0f1d16c599 | ||
|
|
c11e3392d4 | ||
|
|
f498463843 | ||
|
|
cf4ffc97e2 | ||
|
|
3824e8a463 | ||
|
|
21ca4e008f | ||
|
|
6af44a1466 | ||
|
|
2e29164582 | ||
|
|
6d499bc9fc | ||
|
|
7786cb5684 | ||
|
|
003b70c34b | ||
|
|
71edf96c7d | ||
|
|
ddafedc268 | ||
|
|
7e5738bfcd | ||
|
|
315c05b351 | ||
|
|
3662cf6009 | ||
|
|
98d8b50b0e | ||
|
|
1a1cc25bd1 | ||
|
|
bc9c7193a9 | ||
|
|
7ac3c01b5b | ||
|
|
ed6f69e868 | ||
|
|
222b360c66 | ||
|
|
170a864239 | ||
|
|
b5cfd0d35d | ||
|
|
28181710b0 | ||
|
|
2f756b7ec4 | ||
|
|
df4ca54a76 | ||
|
|
875e3e5e7d | ||
|
|
a5317f8117 | ||
|
|
38b92c0171 | ||
|
|
a03b34af77 | ||
|
|
4c14bd8be2 | ||
|
|
62b8e63a0a | ||
|
|
eec3b0b7fe | ||
|
|
2bffb83a00 | ||
|
|
45fd3eb1bf | ||
|
|
963a1b4cb7 | ||
|
|
77c845043d | ||
|
|
342bb0fcef | ||
|
|
93e6bd7929 | ||
|
|
3015eea4e3 | ||
|
|
2f42f7e313 | ||
|
|
a7c86a6d1b | ||
|
|
2399451869 | ||
|
|
19d9a1915d | ||
|
|
261921ae4c | ||
|
|
6ad8a104dd | ||
|
|
50e53265a1 | ||
|
|
3392fdb21d | ||
|
|
dd3c9652c3 | ||
|
|
022a53f8f2 | ||
|
|
2fa3547644 | ||
|
|
7c213ce161 | ||
|
|
ed3d7d49ec | ||
|
|
068139a78a | ||
|
|
8dd7361b6a | ||
|
|
41ea1d230a | ||
|
|
9e25026519 | ||
|
|
9e9559df60 | ||
|
|
7a5a6c7e54 | ||
|
|
be317c439d | ||
|
|
f43383a3fb | ||
|
|
22f6f787e1 | ||
|
|
44b3986025 | ||
|
|
6cb845660a | ||
|
|
de2c866707 | ||
|
|
74ddb84e0a | ||
|
|
0c6a068fd5 | ||
|
|
fad92472d8 | ||
|
|
2a44e8e6ec | ||
|
|
e3d27f29c7 | ||
|
|
e011f05403 | ||
|
|
b8cd77945d | ||
|
|
9a7f521f8a | ||
|
|
102f94f914 | ||
|
|
0c0a497651 | ||
|
|
e0785a8939 | ||
|
|
af098e737e | ||
|
|
1e4ede5585 | ||
|
|
fb2620364a | ||
|
|
68b38b6666 | ||
|
|
ff3e0856a1 | ||
|
|
85f334b663 | ||
|
|
10f520accb | ||
|
|
836608537e | ||
|
|
13e09c58f6 | ||
|
|
600ca08aa8 | ||
|
|
0ed74b3c4a | ||
|
|
7c69a9aa1c | ||
|
|
c50cfb044a | ||
|
|
38d4e179ba | ||
|
|
be80728320 | ||
|
|
09028033c0 | ||
|
|
52c036c3ab | ||
|
|
2fc7cdeba7 | ||
|
|
6f7976766d | ||
|
|
5c369361b0 | ||
|
|
7d48b45152 | ||
|
|
345aabe996 | ||
|
|
5d04b36680 | ||
|
|
cd8907f76c | ||
|
|
b108d5bf54 | ||
|
|
4d823acf45 | ||
|
|
aa868e5e8c | ||
|
|
b1be6cd20b | ||
|
|
fd9321f6ba | ||
|
|
8364226b68 | ||
|
|
49055acf81 | ||
|
|
57ffc12f17 | ||
|
|
d066480a51 | ||
|
|
0e8f98b2a4 | ||
|
|
3a734f51e0 | ||
|
|
c7e2d709cf | ||
|
|
8b4b3a269b | ||
|
|
2f76ba542f | ||
|
|
637cbc88e8 | ||
|
|
fadff022a0 | ||
|
|
05784a6c28 | ||
|
|
5a48e002dd | ||
|
|
d6f86269a4 | ||
|
|
422438f515 | ||
|
|
e5b25071f9 | ||
|
|
498ee635e1 | ||
|
|
c238c00630 | ||
|
|
3eacc37831 | ||
|
|
5267b4b4d4 | ||
|
|
ec84a1b49c | ||
|
|
afb7383225 | ||
|
|
a00b40fa81 | ||
|
|
365c6252ba | ||
|
|
7c81c7da90 | ||
|
|
f8950c8c40 | ||
|
|
18be899aef | ||
|
|
9dc3b645c4 | ||
|
|
318561999d | ||
|
|
ae5b0b4391 | ||
|
|
74b5f6ecf2 | ||
|
|
aea2a469cc | ||
|
|
7a394062e1 | ||
|
|
8070fc8ece | ||
|
|
d6aeaf77b3 | ||
|
|
40434ac209 | ||
|
|
0aab919d7c | ||
|
|
a8ecf5d118 | ||
|
|
8c0d6b27d0 | ||
|
|
2e6f1de29a | ||
|
|
657750b803 | ||
|
|
af5eb82217 | ||
|
|
84e7f33fd9 | ||
|
|
ca83d29eef | ||
|
|
0d49f6c142 | ||
|
|
041e81aad2 | ||
|
|
028504ae9a | ||
|
|
91c55c6880 | ||
|
|
78cf75a0ed | ||
|
|
fa370724f1 | ||
|
|
5edc64d88c | ||
|
|
7898e65d4e | ||
|
|
6d63dbe1af | ||
|
|
eab9daf5f5 | ||
|
|
4becd7b375 | ||
|
|
f230a6af58 | ||
|
|
539b981ac3 | ||
|
|
aad29ff9fc | ||
|
|
4722446caf | ||
|
|
b8aad84285 | ||
|
|
5f0d6074d6 | ||
|
|
9d6a2f5390 | ||
|
|
490ddbf782 | ||
|
|
adc875b20d | ||
|
|
8cd249c1c8 | ||
|
|
305d5850e7 | ||
|
|
df3a9f218d | ||
|
|
ae451a3a02 | ||
|
|
17561a6576 | ||
|
|
b842b7ea01 | ||
|
|
9bbe12e28c | ||
|
|
0674cf64cc | ||
|
|
3413d05b34 | ||
|
|
070a765d24 | ||
|
|
8ac1647436 | ||
|
|
dfe31c9242 | ||
|
|
b7866be3a9 | ||
|
|
8413660d5f | ||
|
|
e037491756 | ||
|
|
ea2624b5ab | ||
|
|
1b40f941cf | ||
|
|
57830435d7 | ||
|
|
44d850de51 | ||
|
|
b08e691127 | ||
|
|
968e82b02d | ||
|
|
de04ce8329 | ||
|
|
5efecff631 | ||
|
|
3ab759e163 | ||
|
|
836d369c6c | ||
|
|
568273453b | ||
|
|
7a4ecb6060 | ||
|
|
82f0ea5b11 | ||
|
|
6fddd13cb2 | ||
|
|
43c7659d18 | ||
|
|
2d15e53dab | ||
|
|
2f2152e039 | ||
|
|
2542189efc | ||
|
|
8e6d39a44b | ||
|
|
c35889d4c6 | ||
|
|
10dedd5ced | ||
|
|
d2966a4c5b | ||
|
|
62b5c43d87 | ||
|
|
b04baa93cd | ||
|
|
2e84208169 | ||
|
|
2265af58ae | ||
|
|
4d190c41cc | ||
|
|
0fbb27d8e3 | ||
|
|
3df3e84270 | ||
|
|
30cc23c5de | ||
|
|
9befb6bd06 | ||
|
|
8a12b78684 | ||
|
|
46168607e8 | ||
|
|
1272b9e186 | ||
|
|
fcbe19445a | ||
|
|
2b4dffa87d | ||
|
|
49a6d02e12 | ||
|
|
2b06dfd4a3 | ||
|
|
6e81b4e84b | ||
|
|
0de1282e1c | ||
|
|
e3db52ca1f | ||
|
|
c5a36d4c70 | ||
|
|
e28b6695ba | ||
|
|
de177f74fb | ||
|
|
e4310aef73 | ||
|
|
d71079e1d8 | ||
|
|
c08d2f36b0 | ||
|
|
839a80e339 | ||
|
|
a35535043e | ||
|
|
323dd7b22d | ||
|
|
102128ca2e | ||
|
|
f3dd75a2c4 | ||
|
|
0869814a0e | ||
|
|
41edee9fe9 | ||
|
|
2fa3694746 | ||
|
|
e9606b3635 | ||
|
|
ed7c4bb6a7 | ||
|
|
c93fea4ec4 | ||
|
|
aa847991e0 | ||
|
|
5f1b903bdf | ||
|
|
49f3531aed | ||
|
|
9b2934f1f6 | ||
|
|
26355768a0 | ||
|
|
80bff0dc2d | ||
|
|
c312a88aa3 | ||
|
|
625818d556 | ||
|
|
2c5a2e8ec7 | ||
|
|
ae16d5f52c | ||
|
|
d69be8a766 | ||
|
|
8df62a537b | ||
|
|
bf5e667351 | ||
|
|
0e5c2bd18e | ||
|
|
3233e64ace | ||
|
|
751117a308 | ||
|
|
8d9024f01f | ||
|
|
a9862f32f3 | ||
|
|
c8d6f47749 | ||
|
|
a6f134e48e | ||
|
|
fdbb5136d9 | ||
|
|
2c66918594 | ||
|
|
a0dac292ff | ||
|
|
75857e7177 | ||
|
|
0369f70b0b | ||
|
|
276b97530f | ||
|
|
d5daf49a9a | ||
|
|
feb16ae4aa | ||
|
|
219301339c | ||
|
|
aec349f75a | ||
|
|
5f909caedf | ||
|
|
ba6dff3adb | ||
|
|
8cd05f098b | ||
|
|
425f5387fa | ||
|
|
f2ce115ade | ||
|
|
090a3e1ded | ||
|
|
c0acb7d352 | ||
|
|
0d6070e6fc | ||
|
|
bd00f851f0 | ||
|
|
1a0c07deec | ||
|
|
04f231a400 | ||
|
|
be1bfcce63 | ||
|
|
8cf5d79852 | ||
|
|
f7912e7c20 | ||
|
|
caa8be5dd1 | ||
|
|
0c15a30a34 | ||
|
|
7bce1c0714 | ||
|
|
d1084cbe48 | ||
|
|
2cc3f69a3f | ||
|
|
a861489a83 | ||
|
|
0e1c585f7d | ||
|
|
9df20e616c | ||
|
|
53fdd2d062 | ||
|
|
2b4bb5d890 | ||
|
|
38f208d70d | ||
|
|
65b90abdda | ||
|
|
f3b49d4eaf | ||
|
|
5b1da7353c | ||
|
|
9f17e65860 | ||
|
|
9b2d53b0d1 | ||
|
|
d6f9196707 | ||
|
|
1b0e09369e | ||
|
|
12482eeb40 | ||
|
|
acc307b959 | ||
|
|
c1d75c295a | ||
|
|
fad118cb04 | ||
|
|
cdd1d819df | ||
|
|
97edffaff5 | ||
|
|
6de7df6b9d | ||
|
|
14d7416c16 | ||
|
|
6782df917a |
@@ -1 +1 @@
|
||||
7.1.0
|
||||
7.4.1
|
||||
|
||||
@@ -12,8 +12,7 @@
|
||||
build:remote-cache --remote_download_minimal
|
||||
build:remote-cache --remote_build_event_upload=minimal
|
||||
build:remote-cache --remote_cache=grpc://bazel-remote-cache:9092
|
||||
# Does not work with rules_oci. See https://github.com/bazel-contrib/rules_oci/issues/292
|
||||
#build:remote-cache --experimental_remote_downloader=grpc://bazel-remote-cache:9092
|
||||
build:remote-cache --experimental_remote_downloader=grpc://bazel-remote-cache:9092
|
||||
build:remote-cache --remote_local_fallback
|
||||
build:remote-cache --experimental_remote_cache_async
|
||||
build:remote-cache --experimental_remote_merkle_tree_cache
|
||||
|
||||
7
.github/PULL_REQUEST_TEMPLATE.md
vendored
7
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -10,6 +10,7 @@
|
||||
in review.
|
||||
4. Note that PRs updating dependencies and new Go versions are not accepted.
|
||||
Please file an issue instead.
|
||||
5. A changelog entry is required for user facing issues.
|
||||
-->
|
||||
|
||||
**What type of PR is this?**
|
||||
@@ -28,3 +29,9 @@
|
||||
Fixes #
|
||||
|
||||
**Other notes for review**
|
||||
|
||||
**Acknowledgements**
|
||||
|
||||
- [ ] I have read [CONTRIBUTING.md](https://github.com/prysmaticlabs/prysm/blob/develop/CONTRIBUTING.md).
|
||||
- [ ] I have included a uniquely named [changelog fragment file](https://github.com/prysmaticlabs/prysm/blob/develop/CONTRIBUTING.md#maintaining-changelogmd).
|
||||
- [ ] I have added a description to this PR with sufficient context for reviewers to understand this PR.
|
||||
|
||||
2
.github/actions/gomodtidy/Dockerfile
vendored
2
.github/actions/gomodtidy/Dockerfile
vendored
@@ -1,4 +1,4 @@
|
||||
FROM golang:1.21-alpine
|
||||
FROM golang:1.24-alpine
|
||||
|
||||
COPY entrypoint.sh /entrypoint.sh
|
||||
|
||||
|
||||
34
.github/workflows/changelog.yml
vendored
Normal file
34
.github/workflows/changelog.yml
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
# This workflow will build a golang project
|
||||
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go
|
||||
|
||||
name: changelog
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ "develop" ]
|
||||
|
||||
jobs:
|
||||
run-changelog-check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
|
||||
|
||||
- name: Download unclog binary
|
||||
uses: dsaltares/fetch-gh-release-asset@aa2ab1243d6e0d5b405b973c89fa4d06a2d0fff7 # 1.1.2
|
||||
with:
|
||||
repo: OffchainLabs/unclog
|
||||
version: "tags/v0.1.3"
|
||||
file: "unclog"
|
||||
|
||||
- name: Get new changelog files
|
||||
id: new-changelog-files
|
||||
uses: OffchainLabs/gh-action-changed-files@9200e69727eb73eb060652b19946b8a2fdfb654b # v4.0.8
|
||||
with:
|
||||
files: |
|
||||
changelog/**.md
|
||||
|
||||
- name: Run lint command
|
||||
env:
|
||||
ALL_ADDED_MARKDOWN: ${{ steps.new-changelog-files.outputs.added_files }}
|
||||
run: chmod +x unclog && ./unclog check -fragment-env=ALL_ADDED_MARKDOWN
|
||||
21
.github/workflows/clang-format.yml
vendored
Normal file
21
.github/workflows/clang-format.yml
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
name: Protobuf Format
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ '*' ]
|
||||
pull_request:
|
||||
branches: [ '*' ]
|
||||
merge_group:
|
||||
types: [checks_requested]
|
||||
|
||||
jobs:
|
||||
clang-format-checking:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
# Is this step failing for you?
|
||||
# Run: clang-format -i proto/**/*.proto
|
||||
# See: https://clang.llvm.org/docs/ClangFormat.html
|
||||
- uses: RafikFarhad/clang-format-github-action@v3
|
||||
with:
|
||||
sources: "proto/**/*.proto"
|
||||
4
.github/workflows/fuzz.yml
vendored
4
.github/workflows/fuzz.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.21.5'
|
||||
go-version: '1.23.5'
|
||||
- id: list
|
||||
uses: shogo82148/actions-go-fuzz/list@v0
|
||||
with:
|
||||
@@ -36,7 +36,7 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.21.5'
|
||||
go-version: '1.23.5'
|
||||
- uses: shogo82148/actions-go-fuzz/run@v0
|
||||
with:
|
||||
packages: ${{ matrix.package }}
|
||||
|
||||
32
.github/workflows/go.yml
vendored
32
.github/workflows/go.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Go mod tidy checker
|
||||
id: gomodtidy
|
||||
@@ -27,34 +27,34 @@ jobs:
|
||||
GO111MODULE: on
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Set up Go 1.21
|
||||
uses: actions/setup-go@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Set up Go 1.24
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.21.5'
|
||||
go-version: '1.24.0'
|
||||
- name: Run Gosec Security Scanner
|
||||
run: | # https://github.com/securego/gosec/issues/469
|
||||
export PATH=$PATH:$(go env GOPATH)/bin
|
||||
go install github.com/securego/gosec/v2/cmd/gosec@v2.15.0
|
||||
gosec -exclude-generated -exclude=G307 -exclude-dir=crypto/bls/herumi ./...
|
||||
go install github.com/securego/gosec/v2/cmd/gosec@v2.22.1
|
||||
gosec -exclude-generated -exclude=G307,G115 -exclude-dir=crypto/bls/herumi ./...
|
||||
|
||||
lint:
|
||||
name: Lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Go 1.21
|
||||
uses: actions/setup-go@v3
|
||||
- name: Set up Go 1.24
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.21.5'
|
||||
go-version: '1.24.0'
|
||||
id: go
|
||||
|
||||
- name: Golangci-lint
|
||||
uses: golangci/golangci-lint-action@v3
|
||||
uses: golangci/golangci-lint-action@v5
|
||||
with:
|
||||
version: v1.55.2
|
||||
version: v1.64.5
|
||||
args: --config=.golangci.yml --out-${NO_FUTURE}format colored-line-number
|
||||
|
||||
build:
|
||||
@@ -62,13 +62,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set up Go 1.x
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.21.5'
|
||||
go-version: '1.24.0'
|
||||
id: go
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Get dependencies
|
||||
run: |
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -41,3 +41,6 @@ jwt.hex
|
||||
|
||||
# manual testing
|
||||
tmp
|
||||
|
||||
# spectest coverage reports
|
||||
report.txt
|
||||
|
||||
@@ -1,28 +1,20 @@
|
||||
run:
|
||||
skip-files:
|
||||
timeout: 10m
|
||||
go: '1.23.5'
|
||||
|
||||
issues:
|
||||
exclude-files:
|
||||
- validator/web/site_data.go
|
||||
- .*_test.go
|
||||
skip-dirs:
|
||||
exclude-dirs:
|
||||
- proto
|
||||
- tools/analyzers
|
||||
timeout: 10m
|
||||
go: '1.21.5'
|
||||
|
||||
linters:
|
||||
enable-all: true
|
||||
disable:
|
||||
# Deprecated linters:
|
||||
- deadcode
|
||||
- exhaustivestruct
|
||||
- golint
|
||||
- govet
|
||||
- ifshort
|
||||
- interfacer
|
||||
- maligned
|
||||
- nosnakecase
|
||||
- scopelint
|
||||
- structcheck
|
||||
- varcheck
|
||||
|
||||
# Disabled for now:
|
||||
- asasalint
|
||||
@@ -34,7 +26,8 @@ linters:
|
||||
- dogsled
|
||||
- dupl
|
||||
- durationcheck
|
||||
- errorlint
|
||||
- errname
|
||||
- err113
|
||||
- exhaustive
|
||||
- exhaustruct
|
||||
- forbidigo
|
||||
@@ -48,16 +41,17 @@ linters:
|
||||
- gocyclo
|
||||
- godot
|
||||
- godox
|
||||
- goerr113
|
||||
- gofumpt
|
||||
- gomnd
|
||||
- gomoddirectives
|
||||
- gosec
|
||||
- inamedparam
|
||||
- interfacebloat
|
||||
- intrange
|
||||
- ireturn
|
||||
- lll
|
||||
- maintidx
|
||||
- makezero
|
||||
- mnd
|
||||
- musttag
|
||||
- nakedret
|
||||
- nestif
|
||||
@@ -72,13 +66,16 @@ linters:
|
||||
- predeclared
|
||||
- promlinter
|
||||
- protogetter
|
||||
- recvcheck
|
||||
- revive
|
||||
- spancheck
|
||||
- staticcheck
|
||||
- stylecheck
|
||||
- tagalign
|
||||
- tagliatelle
|
||||
- thelper
|
||||
- unparam
|
||||
- usetesting
|
||||
- varnamelen
|
||||
- wrapcheck
|
||||
- wsl
|
||||
|
||||
@@ -26,7 +26,6 @@ approval_rules:
|
||||
only_changed_files:
|
||||
paths:
|
||||
- "*pb.go"
|
||||
- "*pb.gw.go"
|
||||
- "*.bazel"
|
||||
options:
|
||||
ignore_commits_by:
|
||||
@@ -69,7 +68,6 @@ approval_rules:
|
||||
changed_files:
|
||||
ignore:
|
||||
- "*pb.go"
|
||||
- "*pb.gw.go"
|
||||
- "*.bazel"
|
||||
options:
|
||||
ignore_commits_by:
|
||||
|
||||
11
BUILD.bazel
11
BUILD.bazel
@@ -55,13 +55,6 @@ alias(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
# Protobuf gRPC gateway compiler
|
||||
alias(
|
||||
name = "grpc_gateway_proto_compiler",
|
||||
actual = "@com_github_grpc_ecosystem_grpc_gateway_v2//protoc-gen-grpc-gateway:go_gen_grpc_gateway",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
gometalinter(
|
||||
name = "gometalinter",
|
||||
config = "//:.gometalinter.json",
|
||||
@@ -172,7 +165,7 @@ STATICCHECK_ANALYZERS = [
|
||||
"sa6006",
|
||||
"sa9001",
|
||||
"sa9002",
|
||||
#"sa9003", # Doesn't build. See https://github.com/dominikh/go-tools/pull/1483
|
||||
"sa9003",
|
||||
"sa9004",
|
||||
"sa9005",
|
||||
"sa9006",
|
||||
@@ -204,6 +197,7 @@ nogo(
|
||||
"//tools/analyzers/logruswitherror:go_default_library",
|
||||
"//tools/analyzers/maligned:go_default_library",
|
||||
"//tools/analyzers/nop:go_default_library",
|
||||
"//tools/analyzers/nopanic:go_default_library",
|
||||
"//tools/analyzers/properpermissions:go_default_library",
|
||||
"//tools/analyzers/recursivelock:go_default_library",
|
||||
"//tools/analyzers/shadowpredecl:go_default_library",
|
||||
@@ -224,6 +218,7 @@ nogo(
|
||||
"@org_golang_x_tools//go/analysis/passes/deepequalerrors:go_default_library",
|
||||
"@org_golang_x_tools//go/analysis/passes/defers:go_default_library",
|
||||
"@org_golang_x_tools//go/analysis/passes/directive:go_default_library",
|
||||
"@org_golang_x_tools//go/analysis/passes/errorsas:go_default_library",
|
||||
# fieldalignment disabled
|
||||
#"@org_golang_x_tools//go/analysis/passes/fieldalignment:go_default_library",
|
||||
"@org_golang_x_tools//go/analysis/passes/findcall:go_default_library",
|
||||
|
||||
3258
CHANGELOG.md
Normal file
3258
CHANGELOG.md
Normal file
File diff suppressed because it is too large
Load Diff
@@ -6,6 +6,9 @@ Excited by our work and want to get involved in building out our sharding releas
|
||||
|
||||
You can explore our [Open Issues](https://github.com/prysmaticlabs/prysm/issues) in-the works for our different releases. Feel free to fork our repo and start creating PR’s after assigning yourself to an issue of interest. We are always chatting on [Discord](https://discord.gg/CTYGPUJ) drop us a line there if you want to get more involved or have any questions on our implementation!
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Please, **do not send pull requests for trivial changes**, such as typos, these will be rejected. These types of pull requests incur a cost to reviewers and do not provide much value to the project. If you are unsure, please open an issue first to discuss the change.
|
||||
|
||||
## Contribution Steps
|
||||
|
||||
**1. Set up Prysm following the instructions in README.md.**
|
||||
@@ -120,15 +123,19 @@ $ git push myrepo feature-in-progress-branch
|
||||
|
||||
Navigate to your fork of the repo on GitHub. On the upper left where the current branch is listed, change the branch to your feature-in-progress-branch. Open the files that you have worked on and check to make sure they include your changes.
|
||||
|
||||
**16. Create a pull request.**
|
||||
**16. Add an entry to CHANGELOG.md.**
|
||||
|
||||
Navigate your browser to https://github.com/prysmaticlabs/prysm and click on the new pull request button. In the “base” box on the left, leave the default selection “base master”, the branch that you want your changes to be applied to. In the “compare” box on the right, select feature-in-progress-branch, the branch containing the changes you want to apply. You will then be asked to answer a few questions about your pull request. After you complete the questionnaire, the pull request will appear in the list of pull requests at https://github.com/prysmaticlabs/prysm/pulls.
|
||||
All PRs must must include a changelog fragment file in the `changelog` directory. If your change is not user-facing or should not be mentioned in the changelog for some other reason, you may use the `Ignored` changelog section in your fragment's header to satisfy this requirement without altering the final release changelog. See the [Maintaining CHANGELOG.md](#maintaining-changelogmd) section for more information.
|
||||
|
||||
**17. Respond to comments by Core Contributors.**
|
||||
**17. Create a pull request.**
|
||||
|
||||
Navigate your browser to https://github.com/prysmaticlabs/prysm and click on the new pull request button. In the “base” box on the left, leave the default selection “base develop”, the branch that you want your changes to be applied to. In the “compare” box on the right, select feature-in-progress-branch, the branch containing the changes you want to apply. You will then be asked to answer a few questions about your pull request. After you complete the questionnaire, the pull request will appear in the list of pull requests at https://github.com/prysmaticlabs/prysm/pulls. Ensure that you have added an entry to CHANGELOG.md if your PR is a user-facing change. See the [Maintaining CHANGELOG.md](#maintaining-changelogmd) section for more information.
|
||||
|
||||
**18. Respond to comments by Core Contributors.**
|
||||
|
||||
Core Contributors may ask questions and request that you make edits. If you set notifications at the top of the page to “not watching,” you will still be notified by email whenever someone comments on the page of a pull request you have created. If you are asked to modify your pull request, repeat steps 8 through 15, then leave a comment to notify the Core Contributors that the pull request is ready for further review.
|
||||
|
||||
**18. If the number of commits becomes excessive, you may be asked to squash your commits.**
|
||||
**19. If the number of commits becomes excessive, you may be asked to squash your commits.**
|
||||
|
||||
You can do this with an interactive rebase. Start by running the following command to determine the commit that is the base of your branch...
|
||||
|
||||
@@ -136,7 +143,7 @@ Core Contributors may ask questions and request that you make edits. If you set
|
||||
$ git merge-base feature-in-progress-branch prysm/master
|
||||
```
|
||||
|
||||
**19. The previous command will return a commit-hash that you should use in the following command.**
|
||||
**20. The previous command will return a commit-hash that you should use in the following command.**
|
||||
|
||||
```
|
||||
$ git rebase -i commit-hash
|
||||
@@ -160,13 +167,24 @@ squash hash add a feature
|
||||
|
||||
Save and close the file, then a commit command will appear in the terminal that squashes the smaller commits into one. Check to be sure the commit message accurately reflects your changes and then hit enter to execute it.
|
||||
|
||||
**20. Update your pull request with the following command.**
|
||||
**21. Update your pull request with the following command.**
|
||||
|
||||
```
|
||||
$ git push myrepo feature-in-progress-branch -f
|
||||
```
|
||||
|
||||
**21. Finally, again leave a comment to the Core Contributors on the pull request to let them know that the pull request has been updated.**
|
||||
**22. Finally, again leave a comment to the Core Contributors on the pull request to let them know that the pull request has been updated.**
|
||||
|
||||
## Maintaining CHANGELOG.md
|
||||
|
||||
This project follows the changelog guidelines from [keepachangelog.com](https://keepachangelog.com/en/1.1.0/). In order to minimize conflicts and workflow headaches, we chose to implement a changelog management
|
||||
strategy that uses changelog "fragment" files, managed by our changelog management tool called `unclog`. Each PR must include a new changelog fragment file in the `changelog` directory, as specified by unclog's
|
||||
[README.md](https://github.com/OffchainLabs/unclog?tab=readme-ov-file#what-is-a-changelog-fragment). As the `unclog` README suggests in the [Best Practices](https://github.com/OffchainLabs/unclog?tab=readme-ov-file#best-practices) section,
|
||||
the standard naming convention for your PR's fragment file, to avoid conflicting with another fragment file, is `changelog/<github user name>_<PR branch name>.md`.
|
||||
|
||||
### Releasing
|
||||
|
||||
When a new release is made, the "Unreleased" section should be moved to a new section with the release version and the current date. Then a new "Unreleased" section is made at the top of the file with the categories listed above.
|
||||
|
||||
## Contributor Responsibilities
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ bazel build //beacon-chain --config=release
|
||||
## Adding / updating dependencies
|
||||
|
||||
1. Add your dependency as you would with go modules. I.e. `go get ...`
|
||||
1. Run `bazel run //:gazelle -- update-repos -from_file=go.mod` to update the bazel managed dependencies.
|
||||
1. Run `bazel run //:gazelle -- update-repos -from_file=go.mod -to_macro=deps.bzl%prysm_deps -prune=true` to update the bazel managed dependencies.
|
||||
|
||||
Example:
|
||||
|
||||
|
||||
110
INTEROP.md
110
INTEROP.md
@@ -2,18 +2,21 @@
|
||||
|
||||
This README details how to setup Prysm for interop testing for usage with other Ethereum consensus clients.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> This guide is likely to be outdated. The Prysm team does not have capacity to troubleshoot
|
||||
> outdated interop guides or instructions. If you experience issues with this guide, please file an
|
||||
> issue for visibility and propose fixes, if possible.
|
||||
|
||||
## Installation & Setup
|
||||
|
||||
1. Install [Bazel](https://docs.bazel.build/versions/master/install.html) **(Recommended)**
|
||||
2. `git clone https://github.com/prysmaticlabs/prysm && cd prysm`
|
||||
3. `bazel build //...`
|
||||
3. `bazel build //cmd/...`
|
||||
|
||||
## Starting from Genesis
|
||||
|
||||
Prysm supports a few ways to quickly launch a beacon node from basic configurations:
|
||||
|
||||
- `NumValidators + GenesisTime`: Launches a beacon node by deterministically generating a state from a num-validators flag along with a genesis time **(Recommended)**
|
||||
- `SSZ Genesis`: Launches a beacon node from a .ssz file containing a SSZ-encoded, genesis beacon state
|
||||
Prysm can be started from a built-in mainnet genesis state, or started with a provided genesis state by
|
||||
using the `--genesis-state` flag and providing a path to the genesis.ssz file.
|
||||
|
||||
## Generating a Genesis State
|
||||
|
||||
@@ -21,21 +24,34 @@ To setup the necessary files for these quick starts, Prysm provides a tool to ge
|
||||
a deterministically generated set of validator private keys following the official interop YAML format
|
||||
[here](https://github.com/ethereum/eth2.0-pm/blob/master/interop/mocked_start).
|
||||
|
||||
You can use `bazel run //tools/genesis-state-gen` to create a deterministic genesis state for interop.
|
||||
You can use `prysmctl` to create a deterministic genesis state for interop.
|
||||
|
||||
### Usage
|
||||
|
||||
- **--genesis-time** uint: Unix timestamp used as the genesis time in the generated genesis state (defaults to now)
|
||||
- **--num-validators** int: Number of validators to deterministically include in the generated genesis state
|
||||
- **--output-ssz** string: Output filename of the SSZ marshaling of the generated genesis state
|
||||
- **--config-name=interop** string: name of the beacon chain config to use when generating the state. ex mainnet|minimal|interop
|
||||
|
||||
The example below creates 64 validator keys, instantiates a genesis state with those 64 validators and with genesis unix timestamp 1567542540,
|
||||
and finally writes a ssz encoded output to ~/Desktop/genesis.ssz. This file can be used to kickstart the beacon chain in the next section. When using the `--interop-*` flags, the beacon node will assume the `interop` config should be used, unless a different config is specified on the command line.
|
||||
```sh
|
||||
# Download (or create) a chain config file.
|
||||
curl https://raw.githubusercontent.com/ethereum/consensus-specs/refs/heads/dev/configs/minimal.yaml -o /tmp/minimal.yaml
|
||||
|
||||
# Run prysmctl to generate genesis with a 2 minute genesis delay and 256 validators.
|
||||
bazel run //cmd/prysmctl --config=minimal -- \
|
||||
testnet generate-genesis \
|
||||
--genesis-time-delay=120 \
|
||||
--num-validators=256 \
|
||||
--output-ssz=/tmp/genesis.ssz \
|
||||
--chain-config-file=/tmp/minimal.yaml
|
||||
```
|
||||
bazel run //tools/genesis-state-gen -- --config-name interop --output-ssz ~/Desktop/genesis.ssz --num-validators 64 --genesis-time 1567542540
|
||||
```
|
||||
|
||||
The flags are explained below:
|
||||
- `bazel run //cmd/prysmctl` is the bazel command to compile and run prysmctl.
|
||||
- `--config=minimal` is a bazel build time configuration flag to compile Prysm with minimal state constants.
|
||||
- `--` is an argument divider to tell bazel that everything after this divider should be passed as arguments to prysmctl. Without this divider, it isn't clear to bazel if the arguments are meant to be build time arguments or runtime arguments so the operation complains and fails to build without this divider.
|
||||
- `testnet` is the primary command argument for prysmctl.
|
||||
- `generate-genesis` is the subcommand to `testnet` in prysmctl.
|
||||
- `--genesis-time-delay` uint: The number of seconds in the future to define genesis. Example: a value of 60 will set the genesis time to 1 minute in the future. This should be sufficiently large enough to allow for you to start the beacon node before the genesis time.
|
||||
- `--num-validators` int: Number of validators to deterministically include in the generated genesis state
|
||||
- `--output-ssz` string: Output filename of the SSZ marshaling of the generated genesis state
|
||||
- `--chain-config-file` string: Filepath to a chain config yaml file.
|
||||
|
||||
Note: This guide saves items to the `/tmp/` directory which will not persist if your machine is
|
||||
restarted. Consider tweaking the arguments if persistence is needed.
|
||||
|
||||
## Launching a Beacon Node + Validator Client
|
||||
|
||||
@@ -44,45 +60,33 @@ bazel run //tools/genesis-state-gen -- --config-name interop --output-ssz ~/Desk
|
||||
Open up two terminal windows, run:
|
||||
|
||||
```
|
||||
bazel run //beacon-chain -- \
|
||||
--bootstrap-node= \
|
||||
--deposit-contract 0x8A04d14125D0FDCDc742F4A05C051De07232EDa4 \
|
||||
--datadir=/tmp/beacon-chain-interop \
|
||||
--force-clear-db \
|
||||
--min-sync-peers=0 \
|
||||
--interop-num-validators 64 \
|
||||
--interop-eth1data-votes
|
||||
bazel run //cmd/beacon-chain --config=minimal -- \
|
||||
--minimal-config \
|
||||
--bootstrap-node= \
|
||||
--deposit-contract 0x8A04d14125D0FDCDc742F4A05C051De07232EDa4 \
|
||||
--datadir=/tmp/beacon-chain-minimal-devnet \
|
||||
--force-clear-db \
|
||||
--min-sync-peers=0 \
|
||||
--genesis-state=/tmp/genesis.ssz \
|
||||
--chain-config-file=/tmp/minimal.yaml
|
||||
```
|
||||
|
||||
This will deterministically generate a beacon genesis state and start
|
||||
the system with 64 validators and the genesis time set to the current unix timestamp.
|
||||
Wait a bit until your beacon chain starts, and in the other window:
|
||||
This will start the system with 256 validators. The flags used can be explained as such:
|
||||
|
||||
- `bazel run //cmd/beacon-chain --config=minimal` builds and runs the beacon node in minimal build configuration.
|
||||
- `--` is a flag divider to distinguish between bazel flags and flags that should be passed to the application. All flags and arguments after this divider are passed to the beacon chain.
|
||||
- `--minimal-config` tells the beacon node to use minimal network configuration. This is different from the compile time state configuration flag `--config=minimal` and both are required.
|
||||
- `--bootstrap-node=` disables the default bootstrap nodes. This prevents the client from attempting to peer with mainnet nodes.
|
||||
- `--datadir=/tmp/beacon-chain-minimal-devnet` sets the data directory in a temporary location. Change this to your preferred destination.
|
||||
- `--force-clear-db` will delete the beaconchain.db file without confirming with the user. This is helpful for iteratively running local devnets without changing the datadir, but less helpful for one off runs where there was no database in the data directory.
|
||||
- `--min-sync-peers=0` allows the beacon node to skip initial sync without peers. This is essential because Prysm expects at least a few peers to start the blockchain.
|
||||
- `--genesis-state=/tmp/genesis.ssz` defines the path to the generated genesis ssz file. The beacon node will use this as the initial genesis state.
|
||||
- `--chain-config-file=/tmp/minimal.yaml` defines the path to the yaml file with the chain configuration.
|
||||
|
||||
As soon as the beacon node has started, start the validator in the other terminal window.
|
||||
|
||||
```
|
||||
bazel run //validator -- --keymanager=interop --keymanageropts='{"keys":64}'
|
||||
bazel run //cmd/validator --config=minimal -- --datadir=/tmp/validator --interop-num-validators=256 --minimal-config --suggested-fee-recipient=0x8A04d14125D0FDCDc742F4A05C051De07232EDa4
|
||||
```
|
||||
|
||||
This will launch and kickstart the system with your 64 validators performing their duties accordingly.
|
||||
|
||||
### Launching from `genesis.ssz`
|
||||
|
||||
Assuming you generated a `genesis.ssz` file with 64 validators, open up two terminal windows, run:
|
||||
|
||||
```
|
||||
bazel run //beacon-chain -- \
|
||||
--bootstrap-node= \
|
||||
--deposit-contract 0x8A04d14125D0FDCDc742F4A05C051De07232EDa4 \
|
||||
--datadir=/tmp/beacon-chain-interop \
|
||||
--force-clear-db \
|
||||
--min-sync-peers=0 \
|
||||
--interop-genesis-state /path/to/genesis.ssz \
|
||||
--interop-eth1data-votes
|
||||
```
|
||||
|
||||
Wait a bit until your beacon chain starts, and in the other window:
|
||||
|
||||
```
|
||||
bazel run //validator -- --keymanager=interop --keymanageropts='{"keys":64}'
|
||||
```
|
||||
|
||||
This will launch and kickstart the system with your 64 validators performing their duties accordingly.
|
||||
This will launch and kickstart the system with your 256 validators performing their duties accordingly.
|
||||
|
||||
1668
MODULE.bazel.lock
generated
1668
MODULE.bazel.lock
generated
File diff suppressed because it is too large
Load Diff
63
README.md
63
README.md
@@ -1,5 +1,7 @@
|
||||
# Prysm: An Ethereum Consensus Implementation Written in Go
|
||||
<h1 align="left">Prysm: An Ethereum Consensus Implementation Written in Go</h1>
|
||||
|
||||
<div align="left">
|
||||
|
||||
[](https://buildkite.com/prysmatic-labs/prysm)
|
||||
[](https://goreportcard.com/report/github.com/prysmaticlabs/prysm)
|
||||
[](https://github.com/ethereum/consensus-specs/tree/v1.4.0)
|
||||
@@ -7,31 +9,60 @@
|
||||
[](https://discord.gg/prysmaticlabs)
|
||||
[](https://www.gitpoap.io/gh/prysmaticlabs/prysm)
|
||||
|
||||
This is the core repository for Prysm, a [Golang](https://golang.org/) implementation of the [Ethereum Consensus](https://ethereum.org/en/developers/docs/consensus-mechanisms/#proof-of-stake) [specification](https://github.com/ethereum/consensus-specs), developed by [Offchain Labs](https://www.offchainlabs.com). See the [Changelog](https://github.com/prysmaticlabs/prysm/releases) for details of the latest releases and upcoming breaking changes.
|
||||
</div>
|
||||
|
||||
### Getting Started
|
||||
---
|
||||
|
||||
A detailed set of installation and usage instructions as well as breakdowns of each individual component are available in the [official documentation portal](https://docs.prylabs.network). If you still have questions, feel free to stop by our [Discord](https://discord.gg/prysmaticlabs).
|
||||
## 📖 Overview
|
||||
|
||||
### Staking on Mainnet
|
||||
This is the core repository for Prysm, a [Golang](https://golang.org/) implementation of the [Ethereum Consensus](https://ethereum.org/en/developers/docs/consensus-mechanisms/#proof-of-stake) [specification](https://github.com/ethereum/consensus-specs), developed by [Offchain Labs](https://www.offchainlabs.com).
|
||||
|
||||
To participate in staking, you can join the [official eth2 launchpad](https://launchpad.ethereum.org). The launchpad is the only recommended way to become a validator on mainnet. You can explore validator rewards/penalties via Bitfly's block explorer: [beaconcha.in](https://beaconcha.in), and follow the latest blocks added to the chain on [beaconscan](https://beaconscan.com).
|
||||
See the [Changelog](https://github.com/prysmaticlabs/prysm/releases) for details of the latest releases and upcoming breaking changes.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Getting Started
|
||||
|
||||
A detailed set of installation and usage instructions as well as breakdowns of each individual component are available in the **[official documentation portal](https://docs.prylabs.network)**.
|
||||
|
||||
💬 **Need help?** Join our **[Discord Community](https://discord.gg/prysmaticlabs)** for support.
|
||||
|
||||
---
|
||||
|
||||
## 🏆 Staking on Mainnet
|
||||
|
||||
To participate in staking, you can join the **[official Ethereum launchpad](https://launchpad.ethereum.org)**. The launchpad is the **only recommended** way to become a validator on mainnet.
|
||||
|
||||
🔍 Explore validator rewards/penalties:
|
||||
|
||||
- **[beaconcha.in](https://beaconcha.in)**
|
||||
- **[beaconscan](https://beaconscan.com)**
|
||||
|
||||
---
|
||||
|
||||
## 🤝 Contributing
|
||||
|
||||
### 🔥 Branches
|
||||
|
||||
## Contributing
|
||||
### Branches
|
||||
Prysm maintains two permanent branches:
|
||||
|
||||
* [master](https://github.com/prysmaticlabs/prysm/tree/master): This points to the latest stable release. It is ideal for most users.
|
||||
* [develop](https://github.com/prysmaticlabs/prysm/tree/develop): This is used for development, it contains the latest PRs. Developers should base their PRs on this branch.
|
||||
- **[`master`](https://github.com/prysmaticlabs/prysm/tree/master)** - This points to the latest stable release. It is ideal for most users.
|
||||
- **[`develop`](https://github.com/prysmaticlabs/prysm/tree/develop)** - This is used for development and contains the latest PRs. Developers should base their PRs on this branch.
|
||||
|
||||
### Guide
|
||||
Want to get involved? Check out our [Contribution Guide](https://docs.prylabs.network/docs/contribute/contribution-guidelines/) to learn more!
|
||||
### 🛠 Contribution Guide
|
||||
|
||||
## License
|
||||
Want to get involved? Check out our **[Contribution Guide](https://docs.prylabs.network/docs/contribute/contribution-guidelines/)** to learn more!
|
||||
|
||||
[GNU General Public License v3.0](https://www.gnu.org/licenses/gpl-3.0.en.html)
|
||||
---
|
||||
|
||||
## Legal Disclaimer
|
||||
## 📜 License
|
||||
|
||||
[Terms of Use](/TERMS_OF_SERVICE.md)
|
||||
[](https://www.gnu.org/licenses/gpl-3.0.en.html)
|
||||
|
||||
This project is licensed under the **GNU General Public License v3.0**.
|
||||
|
||||
---
|
||||
|
||||
## ⚖️ Legal Disclaimer
|
||||
|
||||
📜 [Terms of Use](/TERMS_OF_SERVICE.md)
|
||||
|
||||
130
WORKSPACE
130
WORKSPACE
@@ -16,6 +16,34 @@ load("@rules_pkg//:deps.bzl", "rules_pkg_dependencies")
|
||||
|
||||
rules_pkg_dependencies()
|
||||
|
||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
|
||||
http_archive(
|
||||
name = "toolchains_protoc",
|
||||
sha256 = "abb1540f8a9e045422730670ebb2f25b41fa56ca5a7cf795175a110a0a68f4ad",
|
||||
strip_prefix = "toolchains_protoc-0.3.6",
|
||||
url = "https://github.com/aspect-build/toolchains_protoc/releases/download/v0.3.6/toolchains_protoc-v0.3.6.tar.gz",
|
||||
)
|
||||
|
||||
load("@toolchains_protoc//protoc:repositories.bzl", "rules_protoc_dependencies")
|
||||
|
||||
rules_protoc_dependencies()
|
||||
|
||||
load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies")
|
||||
|
||||
rules_proto_dependencies()
|
||||
|
||||
load("@bazel_features//:deps.bzl", "bazel_features_deps")
|
||||
|
||||
bazel_features_deps()
|
||||
|
||||
load("@toolchains_protoc//protoc:toolchain.bzl", "protoc_toolchains")
|
||||
|
||||
protoc_toolchains(
|
||||
name = "protoc_toolchains",
|
||||
version = "v25.3",
|
||||
)
|
||||
|
||||
HERMETIC_CC_TOOLCHAIN_VERSION = "v3.0.1"
|
||||
|
||||
http_archive(
|
||||
@@ -29,23 +57,7 @@ http_archive(
|
||||
|
||||
load("@hermetic_cc_toolchain//toolchain:defs.bzl", zig_toolchains = "toolchains")
|
||||
|
||||
# Temporarily use a nightly build until 0.12.0 is released.
|
||||
# See: https://github.com/prysmaticlabs/prysm/issues/13130
|
||||
zig_toolchains(
|
||||
host_platform_sha256 = {
|
||||
"linux-aarch64": "45afb8e32adde825165f4f293fcea9ecea503f7f9ec0e9bf4435afe70e67fb70",
|
||||
"linux-x86_64": "f136c6a8a0f6adcb057d73615fbcd6f88281b3593f7008d5f7ed514ff925c02e",
|
||||
"macos-aarch64": "05d995853c05243151deff47b60bdc2674f1e794a939eaeca0f42312da031cee",
|
||||
"macos-x86_64": "721754ba5a50f31e8a1f0e1a74cace26f8246576878ac4a8591b0ee7b6db1fc1",
|
||||
"windows-x86_64": "93f5248b2ea8c5ee8175e15b1384e133edc1cd49870b3ea259062a2e04164343",
|
||||
},
|
||||
url_formats = [
|
||||
"https://ziglang.org/builds/zig-{host_platform}-{version}.{_ext}",
|
||||
"https://mirror.bazel.build/ziglang.org/builds/zig-{host_platform}-{version}.{_ext}",
|
||||
"https://prysmaticlabs.com/mirror/ziglang.org/builds/zig-{host_platform}-{version}.{_ext}",
|
||||
],
|
||||
version = "0.12.0-dev.1349+fa022d1ec",
|
||||
)
|
||||
zig_toolchains()
|
||||
|
||||
# Register zig sdk toolchains with support for Ubuntu 20.04 (Focal Fossa) which has an EOL date of April, 2025.
|
||||
# For ubuntu glibc support, see https://launchpad.net/ubuntu/+source/glibc
|
||||
@@ -117,9 +129,9 @@ http_archive(
|
||||
|
||||
http_archive(
|
||||
name = "aspect_bazel_lib",
|
||||
sha256 = "f5ea76682b209cc0bd90d0f5a3b26d2f7a6a2885f0c5f615e72913f4805dbb0d",
|
||||
strip_prefix = "bazel-lib-2.5.0",
|
||||
url = "https://github.com/aspect-build/bazel-lib/releases/download/v2.5.0/bazel-lib-v2.5.0.tar.gz",
|
||||
sha256 = "a272d79bb0ac6b6965aa199b1f84333413452e87f043b53eca7f347a23a478e8",
|
||||
strip_prefix = "bazel-lib-2.9.3",
|
||||
url = "https://github.com/bazel-contrib/bazel-lib/releases/download/v2.9.3/bazel-lib-v2.9.3.tar.gz",
|
||||
)
|
||||
|
||||
load("@aspect_bazel_lib//lib:repositories.bzl", "aspect_bazel_lib_dependencies", "aspect_bazel_lib_register_toolchains")
|
||||
@@ -148,15 +160,15 @@ oci_register_toolchains(
|
||||
|
||||
http_archive(
|
||||
name = "io_bazel_rules_go",
|
||||
integrity = "sha256-JD8o94crTb2DFiJJR8nMAGdBAW95zIENB4cbI+JnrI4=",
|
||||
patch_args = ["-p1"],
|
||||
patches = [
|
||||
# Expose internals of go_test for custom build transitions.
|
||||
"//third_party:io_bazel_rules_go_test.patch",
|
||||
],
|
||||
sha256 = "80a98277ad1311dacd837f9b16db62887702e9f1d1c4c9f796d0121a46c8e184",
|
||||
strip_prefix = "rules_go-cf3c3af34bd869b864f5f2b98e2f41c2b220d6c9",
|
||||
urls = [
|
||||
"https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.46.0/rules_go-v0.46.0.zip",
|
||||
"https://github.com/bazelbuild/rules_go/releases/download/v0.46.0/rules_go-v0.46.0.zip",
|
||||
"https://github.com/bazel-contrib/rules_go/archive/cf3c3af34bd869b864f5f2b98e2f41c2b220d6c9.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -181,7 +193,7 @@ load("@rules_oci//oci:pull.bzl", "oci_pull")
|
||||
oci_pull(
|
||||
name = "linux_debian11_multiarch_base", # Debian bullseye
|
||||
digest = "sha256:b82f113425c5b5c714151aaacd8039bc141821cdcd3c65202d42bdf9c43ae60b", # 2023-12-12
|
||||
image = "gcr.io/distroless/cc-debian11",
|
||||
image = "gcr.io/prysmaticlabs/distroless/cc-debian11",
|
||||
platforms = [
|
||||
"linux/amd64",
|
||||
"linux/arm64/v8",
|
||||
@@ -198,7 +210,7 @@ load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_depe
|
||||
go_rules_dependencies()
|
||||
|
||||
go_register_toolchains(
|
||||
go_version = "1.21.8",
|
||||
go_version = "1.24.0",
|
||||
nogo = "@//:nogo",
|
||||
)
|
||||
|
||||
@@ -243,7 +255,7 @@ filegroup(
|
||||
url = "https://github.com/ethereum/EIPs/archive/5480440fe51742ed23342b68cf106cefd427e39d.tar.gz",
|
||||
)
|
||||
|
||||
consensus_spec_version = "v1.4.0"
|
||||
consensus_spec_version = "v1.5.0-beta.4"
|
||||
|
||||
bls_test_version = "v0.1.1"
|
||||
|
||||
@@ -259,7 +271,7 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "c282c0f86f23f3d2e0f71f5975769a4077e62a7e3c7382a16bd26a7e589811a0",
|
||||
integrity = "sha256-QG0NUqaCvP5lKaKKwF/fmeICZVjONMlb7EE+MtYl0C0=",
|
||||
url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/general.tar.gz" % consensus_spec_version,
|
||||
)
|
||||
|
||||
@@ -275,7 +287,7 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "4649c35aa3b8eb0cfdc81bee7c05649f90ef36bede5b0513e1f2e8baf37d6033",
|
||||
integrity = "sha256-8NQngTSSqzW/j3tOUi3r5h+94ChRbLNWTt7BOGqr4+E=",
|
||||
url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/minimal.tar.gz" % consensus_spec_version,
|
||||
)
|
||||
|
||||
@@ -291,7 +303,7 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "c5a03f724f757456ffaabd2a899992a71d2baf45ee4db65ca3518f2b7ee928c8",
|
||||
integrity = "sha256-gFqxbaBnJ7dtdoj0zFbVrtlHv/bLNuWjrTHkyCAjFjI=",
|
||||
url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/mainnet.tar.gz" % consensus_spec_version,
|
||||
)
|
||||
|
||||
@@ -306,7 +318,7 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "cd1c9d97baccbdde1d2454a7dceb8c6c61192a3b581eee12ffc94969f2db8453",
|
||||
integrity = "sha256-9paalF0POULpP2ga+4ouHSETKYrWNCUCZoJHPuFw06E=",
|
||||
strip_prefix = "consensus-specs-" + consensus_spec_version[1:],
|
||||
url = "https://github.com/ethereum/consensus-specs/archive/refs/tags/%s.tar.gz" % consensus_spec_version,
|
||||
)
|
||||
@@ -342,36 +354,52 @@ filegroup(
|
||||
url = "https://github.com/eth-clients/eth2-networks/archive/934c948e69205dcf2deb87e4ae6cc140c335f94d.tar.gz",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "goerli_testnet",
|
||||
build_file_content = """
|
||||
filegroup(
|
||||
name = "configs",
|
||||
srcs = [
|
||||
"prater/config.yaml",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "43fc0f55ddff7b511713e2de07aa22846a67432df997296fb4fc09cd8ed1dcdb",
|
||||
strip_prefix = "goerli-6522ac6684693740cd4ddcc2a0662e03702aa4a1",
|
||||
url = "https://github.com/eth-clients/goerli/archive/6522ac6684693740cd4ddcc2a0662e03702aa4a1.tar.gz",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "holesky_testnet",
|
||||
build_file_content = """
|
||||
filegroup(
|
||||
name = "configs",
|
||||
srcs = [
|
||||
"custom_config_data/config.yaml",
|
||||
"metadata/config.yaml",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "5f4be6fd088683ea9db45c863b9c5a1884422449e5b59fd2d561d3ba0f73ffd9",
|
||||
strip_prefix = "holesky-9d9aabf2d4de51334ee5fed6c79a4d55097d1a43",
|
||||
url = "https://github.com/eth-clients/holesky/archive/9d9aabf2d4de51334ee5fed6c79a4d55097d1a43.tar.gz", # 2024-01-22
|
||||
integrity = "sha256-YVFFrCmjoGZ3fXMWpsCpSsYbANy1grnqYwOLKIg2SsA=",
|
||||
strip_prefix = "holesky-32a72e21c6e53c262f27d50dd540cb654517d03a",
|
||||
url = "https://github.com/eth-clients/holesky/archive/32a72e21c6e53c262f27d50dd540cb654517d03a.tar.gz", # 2025-03-17
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "sepolia_testnet",
|
||||
build_file_content = """
|
||||
filegroup(
|
||||
name = "configs",
|
||||
srcs = [
|
||||
"metadata/config.yaml",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
integrity = "sha256-b5F7Wg9LLMqGRIpP2uqb/YsSFVn2ynzlV7g/Nb1EFLk=",
|
||||
strip_prefix = "sepolia-562d9938f08675e9ba490a1dfba21fb05843f39f",
|
||||
url = "https://github.com/eth-clients/sepolia/archive/562d9938f08675e9ba490a1dfba21fb05843f39f.tar.gz", # 2025-03-17
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "hoodi_testnet",
|
||||
build_file_content = """
|
||||
filegroup(
|
||||
name = "configs",
|
||||
srcs = [
|
||||
"metadata/config.yaml",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
integrity = "sha256-dPiEWUd8QvbYGwGtIm0QtCekitVLOLsW5rpQIGzz8PU=",
|
||||
strip_prefix = "hoodi-828c2c940e1141092bd4bb979cef547ea926d272",
|
||||
url = "https://github.com/eth-clients/hoodi/archive/828c2c940e1141092bd4bb979cef547ea926d272.tar.gz",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
@@ -419,7 +447,7 @@ gometalinter_dependencies()
|
||||
|
||||
load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies")
|
||||
|
||||
gazelle_dependencies()
|
||||
gazelle_dependencies(go_sdk = "go_sdk")
|
||||
|
||||
load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps")
|
||||
|
||||
|
||||
@@ -1,11 +1,24 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_library")
|
||||
load("@prysm//tools/go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"constants.go",
|
||||
"headers.go",
|
||||
"jwt.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/api",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//crypto/rand:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["jwt_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = ["//testing/require:go_default_library"],
|
||||
)
|
||||
|
||||
9
api/apiutil/BUILD.bazel
Normal file
9
api/apiutil/BUILD.bazel
Normal file
@@ -0,0 +1,9 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["common.go"],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/api/client/apiutil",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = ["//consensus-types/primitives:go_default_library"],
|
||||
)
|
||||
30
api/apiutil/common.go
Normal file
30
api/apiutil/common.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package apiutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
neturl "net/url"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
)
|
||||
|
||||
func ValidRoot(root string) bool {
|
||||
matchesRegex, err := regexp.MatchString("^0x[a-fA-F0-9]{64}$", root)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return matchesRegex
|
||||
}
|
||||
|
||||
func Uint64ToString[T uint64 | primitives.Slot | primitives.ValidatorIndex | primitives.CommitteeIndex | primitives.Epoch](val T) string {
|
||||
return strconv.FormatUint(uint64(val), 10)
|
||||
}
|
||||
|
||||
func BuildURL(path string, queryParams ...neturl.Values) string {
|
||||
if len(queryParams) == 0 {
|
||||
return path
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s?%s", path, queryParams[0].Encode())
|
||||
}
|
||||
@@ -5,16 +5,31 @@ go_library(
|
||||
srcs = [
|
||||
"client.go",
|
||||
"errors.go",
|
||||
"json_rest_handler.go",
|
||||
"options.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/api/client",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = ["@com_github_pkg_errors//:go_default_library"],
|
||||
deps = [
|
||||
"//api:go_default_library",
|
||||
"//network/httputil:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["client_test.go"],
|
||||
srcs = [
|
||||
"client_test.go",
|
||||
"json_rest_handler_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = ["//testing/require:go_default_library"],
|
||||
deps = [
|
||||
"//api:go_default_library",
|
||||
"//api/server/structs:go_default_library",
|
||||
"//network/httputil:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -3,61 +3,34 @@ load("@prysm//tools/go:def.bzl", "go_library", "go_test")
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"checkpoint.go",
|
||||
"client.go",
|
||||
"doc.go",
|
||||
"health.go",
|
||||
"log.go",
|
||||
"structs.go",
|
||||
"template.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/api/client/beacon",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//api/client:go_default_library",
|
||||
"//api/client/beacon/iface:go_default_library",
|
||||
"//api/server:go_default_library",
|
||||
"//api/server/structs:go_default_library",
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//consensus-types/interfaces:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//encoding/ssz/detect:go_default_library",
|
||||
"//io/file:go_default_library",
|
||||
"//network/forks:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//runtime/version:go_default_library",
|
||||
"//time/slots:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@org_golang_x_mod//semver:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"checkpoint_test.go",
|
||||
"client_test.go",
|
||||
"health_test.go",
|
||||
],
|
||||
srcs = ["client_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//api/client:go_default_library",
|
||||
"//api/client/beacon/testing:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/blocks:go_default_library",
|
||||
"//consensus-types/blocks/testing:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//encoding/ssz/detect:go_default_library",
|
||||
"//network/forks:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//runtime/version:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"//testing/util:go_default_library",
|
||||
"//time/slots:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@org_uber_go_mock//gomock:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
45
api/client/beacon/chain/BUILD.bazel
Normal file
45
api/client/beacon/chain/BUILD.bazel
Normal file
@@ -0,0 +1,45 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"client.go",
|
||||
"grpc_client.go",
|
||||
"interfaces.go",
|
||||
"rest_client.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/api/client/beacon/chain",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//api/client:go_default_library",
|
||||
"//api/client/beacon/shared_providers:go_default_library",
|
||||
"//api/server/structs:go_default_library",
|
||||
"//config/features:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//time/slots:go_default_library",
|
||||
"//validator/helpers:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
"@com_github_golang_protobuf//ptypes/empty",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@org_golang_google_grpc//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["rest_client_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//api/client/beacon/mock:go_default_library",
|
||||
"//api/server/structs:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"//time/slots:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
"@org_golang_google_protobuf//types/known/emptypb:go_default_library",
|
||||
"@org_uber_go_mock//gomock:go_default_library",
|
||||
],
|
||||
)
|
||||
31
api/client/beacon/chain/client.go
Normal file
31
api/client/beacon/chain/client.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package chain
|
||||
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/shared_providers"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/features"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
validatorHelpers "github.com/prysmaticlabs/prysm/v5/validator/helpers"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
func NewClient(validatorConn validatorHelpers.NodeConnection, jsonRestHandler client.JsonRestHandler) Client {
|
||||
grpcClient := NewGrpcChainClient(validatorConn.GetGrpcClientConn())
|
||||
if features.Get().EnableBeaconRESTApi {
|
||||
return NewBeaconApiChainClientWithFallback(jsonRestHandler, grpcClient)
|
||||
} else {
|
||||
return grpcClient
|
||||
}
|
||||
}
|
||||
|
||||
func NewGrpcChainClient(cc grpc.ClientConnInterface) Client {
|
||||
return &grpcChainClient{ethpb.NewBeaconChainClient(cc)}
|
||||
}
|
||||
|
||||
func NewBeaconApiChainClientWithFallback(jsonRestHandler client.JsonRestHandler, fallbackClient Client) Client {
|
||||
return &beaconApiChainClient{
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
fallbackClient: fallbackClient,
|
||||
stateValidatorsProvider: shared_providers.NewStateValidators(jsonRestHandler),
|
||||
}
|
||||
}
|
||||
36
api/client/beacon/chain/grpc_client.go
Normal file
36
api/client/beacon/chain/grpc_client.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package chain
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
type grpcChainClient struct {
|
||||
beaconChainClient ethpb.BeaconChainClient
|
||||
}
|
||||
|
||||
func (c *grpcChainClient) ChainHead(ctx context.Context, in *empty.Empty) (*ethpb.ChainHead, error) {
|
||||
return c.beaconChainClient.GetChainHead(ctx, in)
|
||||
}
|
||||
|
||||
func (c *grpcChainClient) ValidatorBalances(ctx context.Context, in *ethpb.ListValidatorBalancesRequest) (*ethpb.ValidatorBalances, error) {
|
||||
return c.beaconChainClient.ListValidatorBalances(ctx, in)
|
||||
}
|
||||
|
||||
func (c *grpcChainClient) Validators(ctx context.Context, in *ethpb.ListValidatorsRequest) (*ethpb.Validators, error) {
|
||||
return c.beaconChainClient.ListValidators(ctx, in)
|
||||
}
|
||||
|
||||
func (c *grpcChainClient) ValidatorQueue(ctx context.Context, in *empty.Empty) (*ethpb.ValidatorQueue, error) {
|
||||
return c.beaconChainClient.GetValidatorQueue(ctx, in)
|
||||
}
|
||||
|
||||
func (c *grpcChainClient) ValidatorPerformance(ctx context.Context, in *ethpb.ValidatorPerformanceRequest) (*ethpb.ValidatorPerformanceResponse, error) {
|
||||
return c.beaconChainClient.GetValidatorPerformance(ctx, in)
|
||||
}
|
||||
|
||||
func (c *grpcChainClient) ValidatorParticipation(ctx context.Context, in *ethpb.GetValidatorParticipationRequest) (*ethpb.ValidatorParticipationResponse, error) {
|
||||
return c.beaconChainClient.GetValidatorParticipation(ctx, in)
|
||||
}
|
||||
17
api/client/beacon/chain/interfaces.go
Normal file
17
api/client/beacon/chain/interfaces.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package chain
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
type Client interface {
|
||||
ChainHead(ctx context.Context, in *empty.Empty) (*ethpb.ChainHead, error)
|
||||
ValidatorBalances(ctx context.Context, in *ethpb.ListValidatorBalancesRequest) (*ethpb.ValidatorBalances, error)
|
||||
Validators(ctx context.Context, in *ethpb.ListValidatorsRequest) (*ethpb.Validators, error)
|
||||
ValidatorQueue(ctx context.Context, in *empty.Empty) (*ethpb.ValidatorQueue, error)
|
||||
ValidatorParticipation(ctx context.Context, in *ethpb.GetValidatorParticipationRequest) (*ethpb.ValidatorParticipationResponse, error)
|
||||
ValidatorPerformance(context.Context, *ethpb.ValidatorPerformanceRequest) (*ethpb.ValidatorPerformanceResponse, error)
|
||||
}
|
||||
@@ -1,31 +1,28 @@
|
||||
package beacon_api
|
||||
package chain
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/shared_providers"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/time/slots"
|
||||
"github.com/prysmaticlabs/prysm/v5/validator/client/iface"
|
||||
)
|
||||
|
||||
type beaconApiBeaconChainClient struct {
|
||||
fallbackClient iface.BeaconChainClient
|
||||
jsonRestHandler JsonRestHandler
|
||||
stateValidatorsProvider StateValidatorsProvider
|
||||
type beaconApiChainClient struct {
|
||||
fallbackClient Client
|
||||
jsonRestHandler client.JsonRestHandler
|
||||
stateValidatorsProvider shared_providers.StateValidators
|
||||
}
|
||||
|
||||
const getValidatorPerformanceEndpoint = "/prysm/validators/performance"
|
||||
|
||||
func (c beaconApiBeaconChainClient) getHeadBlockHeaders(ctx context.Context) (*structs.GetBlockHeaderResponse, error) {
|
||||
func (c beaconApiChainClient) headBlockHeaders(ctx context.Context) (*structs.GetBlockHeaderResponse, error) {
|
||||
blockHeader := structs.GetBlockHeaderResponse{}
|
||||
err := c.jsonRestHandler.Get(ctx, "/eth/v1/beacon/headers/head", &blockHeader)
|
||||
if err != nil {
|
||||
@@ -43,7 +40,7 @@ func (c beaconApiBeaconChainClient) getHeadBlockHeaders(ctx context.Context) (*s
|
||||
return &blockHeader, nil
|
||||
}
|
||||
|
||||
func (c beaconApiBeaconChainClient) GetChainHead(ctx context.Context, _ *empty.Empty) (*ethpb.ChainHead, error) {
|
||||
func (c beaconApiChainClient) ChainHead(ctx context.Context, _ *empty.Empty) (*ethpb.ChainHead, error) {
|
||||
const endpoint = "/eth/v1/beacon/states/head/finality_checkpoints"
|
||||
|
||||
finalityCheckpoints := structs.GetFinalityCheckpointsResponse{}
|
||||
@@ -112,7 +109,7 @@ func (c beaconApiBeaconChainClient) GetChainHead(ctx context.Context, _ *empty.E
|
||||
return nil, errors.Wrapf(err, "failed to decode previous justified checkpoint root `%s`", finalityCheckpoints.Data.PreviousJustified.Root)
|
||||
}
|
||||
|
||||
blockHeader, err := c.getHeadBlockHeaders(ctx)
|
||||
blockHeader, err := c.headBlockHeaders(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get head block headers")
|
||||
}
|
||||
@@ -146,16 +143,16 @@ func (c beaconApiBeaconChainClient) GetChainHead(ctx context.Context, _ *empty.E
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c beaconApiBeaconChainClient) ListValidatorBalances(ctx context.Context, in *ethpb.ListValidatorBalancesRequest) (*ethpb.ValidatorBalances, error) {
|
||||
func (c beaconApiChainClient) ValidatorBalances(ctx context.Context, in *ethpb.ListValidatorBalancesRequest) (*ethpb.ValidatorBalances, error) {
|
||||
if c.fallbackClient != nil {
|
||||
return c.fallbackClient.ListValidatorBalances(ctx, in)
|
||||
return c.fallbackClient.ValidatorBalances(ctx, in)
|
||||
}
|
||||
|
||||
// TODO: Implement me
|
||||
panic("beaconApiBeaconChainClient.ListValidatorBalances is not implemented. To use a fallback client, pass a fallback client as the last argument of NewBeaconApiBeaconChainClientWithFallback.")
|
||||
return nil, errors.New("beaconApiChainClient.ValidatorBalances is not implemented. To use a fallback client, pass a fallback client as the last argument of NewBeaconApiChainClientWithFallback.")
|
||||
}
|
||||
|
||||
func (c beaconApiBeaconChainClient) ListValidators(ctx context.Context, in *ethpb.ListValidatorsRequest) (*ethpb.Validators, error) {
|
||||
func (c beaconApiChainClient) Validators(ctx context.Context, in *ethpb.ListValidatorsRequest) (*ethpb.Validators, error) {
|
||||
pageSize := in.PageSize
|
||||
|
||||
// We follow the gRPC behavior here, which returns a maximum of 250 results when pageSize == 0
|
||||
@@ -191,21 +188,21 @@ func (c beaconApiBeaconChainClient) ListValidators(ctx context.Context, in *ethp
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to get first slot for epoch `%d`", queryFilter.Epoch)
|
||||
}
|
||||
if stateValidators, err = c.stateValidatorsProvider.GetStateValidatorsForSlot(ctx, slot, pubkeys, in.Indices, statuses); err != nil {
|
||||
if stateValidators, err = c.stateValidatorsProvider.StateValidatorsForSlot(ctx, slot, pubkeys, in.Indices, statuses); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to get state validators for slot `%d`", slot)
|
||||
}
|
||||
epoch = slots.ToEpoch(slot)
|
||||
case *ethpb.ListValidatorsRequest_Genesis:
|
||||
if stateValidators, err = c.stateValidatorsProvider.GetStateValidatorsForSlot(ctx, 0, pubkeys, in.Indices, statuses); err != nil {
|
||||
if stateValidators, err = c.stateValidatorsProvider.StateValidatorsForSlot(ctx, 0, pubkeys, in.Indices, statuses); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to get genesis state validators")
|
||||
}
|
||||
epoch = 0
|
||||
case nil:
|
||||
if stateValidators, err = c.stateValidatorsProvider.GetStateValidatorsForHead(ctx, pubkeys, in.Indices, statuses); err != nil {
|
||||
if stateValidators, err = c.stateValidatorsProvider.StateValidatorsForHead(ctx, pubkeys, in.Indices, statuses); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get head state validators")
|
||||
}
|
||||
|
||||
blockHeader, err := c.getHeadBlockHeaders(ctx)
|
||||
blockHeader, err := c.headBlockHeaders(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get head block headers")
|
||||
}
|
||||
@@ -310,54 +307,29 @@ func (c beaconApiBeaconChainClient) ListValidators(ctx context.Context, in *ethp
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c beaconApiBeaconChainClient) GetValidatorQueue(ctx context.Context, in *empty.Empty) (*ethpb.ValidatorQueue, error) {
|
||||
func (c beaconApiChainClient) ValidatorQueue(ctx context.Context, in *empty.Empty) (*ethpb.ValidatorQueue, error) {
|
||||
if c.fallbackClient != nil {
|
||||
return c.fallbackClient.GetValidatorQueue(ctx, in)
|
||||
return c.fallbackClient.ValidatorQueue(ctx, in)
|
||||
}
|
||||
|
||||
// TODO: Implement me
|
||||
panic("beaconApiBeaconChainClient.GetValidatorQueue is not implemented. To use a fallback client, pass a fallback client as the last argument of NewBeaconApiBeaconChainClientWithFallback.")
|
||||
return nil, errors.New("beaconApiChainClient.ValidatorQueue is not implemented. To use a fallback client, pass a fallback client as the last argument of NewBeaconApiChainClientWithFallback.")
|
||||
}
|
||||
|
||||
func (c beaconApiBeaconChainClient) GetValidatorPerformance(ctx context.Context, in *ethpb.ValidatorPerformanceRequest) (*ethpb.ValidatorPerformanceResponse, error) {
|
||||
request, err := json.Marshal(structs.GetValidatorPerformanceRequest{
|
||||
PublicKeys: in.PublicKeys,
|
||||
Indices: in.Indices,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to marshal request")
|
||||
}
|
||||
resp := &structs.GetValidatorPerformanceResponse{}
|
||||
if err = c.jsonRestHandler.Post(ctx, getValidatorPerformanceEndpoint, nil, bytes.NewBuffer(request), resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ðpb.ValidatorPerformanceResponse{
|
||||
CurrentEffectiveBalances: resp.CurrentEffectiveBalances,
|
||||
CorrectlyVotedSource: resp.CorrectlyVotedSource,
|
||||
CorrectlyVotedTarget: resp.CorrectlyVotedTarget,
|
||||
CorrectlyVotedHead: resp.CorrectlyVotedHead,
|
||||
BalancesBeforeEpochTransition: resp.BalancesBeforeEpochTransition,
|
||||
BalancesAfterEpochTransition: resp.BalancesAfterEpochTransition,
|
||||
MissingValidators: resp.MissingValidators,
|
||||
PublicKeys: resp.PublicKeys,
|
||||
InactivityScores: resp.InactivityScores,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c beaconApiBeaconChainClient) GetValidatorParticipation(ctx context.Context, in *ethpb.GetValidatorParticipationRequest) (*ethpb.ValidatorParticipationResponse, error) {
|
||||
func (c beaconApiChainClient) ValidatorPerformance(ctx context.Context, in *ethpb.ValidatorPerformanceRequest) (*ethpb.ValidatorPerformanceResponse, error) {
|
||||
if c.fallbackClient != nil {
|
||||
return c.fallbackClient.GetValidatorParticipation(ctx, in)
|
||||
return c.fallbackClient.ValidatorPerformance(ctx, in)
|
||||
}
|
||||
|
||||
// TODO: Implement me
|
||||
panic("beaconApiBeaconChainClient.GetValidatorParticipation is not implemented. To use a fallback client, pass a fallback client as the last argument of NewBeaconApiBeaconChainClientWithFallback.")
|
||||
return nil, errors.New("beaconApiChainClient.ValidatorPerformance is not implemented. To use a fallback client, pass a fallback client as the last argument of NewBeaconApiChainClientWithFallback.")
|
||||
}
|
||||
|
||||
func NewBeaconApiBeaconChainClientWithFallback(jsonRestHandler JsonRestHandler, fallbackClient iface.BeaconChainClient) iface.BeaconChainClient {
|
||||
return &beaconApiBeaconChainClient{
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
fallbackClient: fallbackClient,
|
||||
stateValidatorsProvider: beaconApiStateValidatorsProvider{jsonRestHandler: jsonRestHandler},
|
||||
func (c beaconApiChainClient) ValidatorParticipation(ctx context.Context, in *ethpb.GetValidatorParticipationRequest) (*ethpb.ValidatorParticipationResponse, error) {
|
||||
if c.fallbackClient != nil {
|
||||
return c.fallbackClient.ValidatorParticipation(ctx, in)
|
||||
}
|
||||
|
||||
// TODO: Implement me
|
||||
return nil, errors.New("beaconApiChainClient.ValidatorParticipation is not implemented. To use a fallback client, pass a fallback client as the last argument of NewBeaconApiChainClientWithFallback.")
|
||||
}
|
||||
@@ -1,9 +1,7 @@
|
||||
package beacon_api
|
||||
package chain
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
@@ -11,14 +9,13 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/mock"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v5/time/slots"
|
||||
"github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api/mock"
|
||||
"go.uber.org/mock/gomock"
|
||||
"google.golang.org/protobuf/types/known/emptypb"
|
||||
)
|
||||
@@ -31,8 +28,8 @@ func TestListValidators(t *testing.T) {
|
||||
defer ctrl.Finish()
|
||||
ctx := context.Background()
|
||||
|
||||
beaconChainClient := beaconApiBeaconChainClient{}
|
||||
_, err := beaconChainClient.ListValidators(ctx, ðpb.ListValidatorsRequest{
|
||||
beaconChainClient := beaconApiChainClient{}
|
||||
_, err := beaconChainClient.Validators(ctx, ðpb.ListValidatorsRequest{
|
||||
PageToken: "foo",
|
||||
})
|
||||
assert.ErrorContains(t, "failed to parse page token `foo`", err)
|
||||
@@ -43,8 +40,8 @@ func TestListValidators(t *testing.T) {
|
||||
defer ctrl.Finish()
|
||||
ctx := context.Background()
|
||||
|
||||
beaconChainClient := beaconApiBeaconChainClient{}
|
||||
_, err := beaconChainClient.ListValidators(ctx, ðpb.ListValidatorsRequest{
|
||||
beaconChainClient := beaconApiChainClient{}
|
||||
_, err := beaconChainClient.Validators(ctx, ðpb.ListValidatorsRequest{
|
||||
QueryFilter: ðpb.ListValidatorsRequest_Epoch{
|
||||
Epoch: math.MaxUint64,
|
||||
},
|
||||
@@ -58,13 +55,13 @@ func TestListValidators(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
stateValidatorsProvider := mock.NewMockStateValidatorsProvider(ctrl)
|
||||
stateValidatorsProvider.EXPECT().GetStateValidatorsForSlot(ctx, gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(
|
||||
stateValidatorsProvider.EXPECT().StateValidatorsForSlot(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(
|
||||
nil,
|
||||
errors.New("foo error"),
|
||||
)
|
||||
|
||||
beaconChainClient := beaconApiBeaconChainClient{stateValidatorsProvider: stateValidatorsProvider}
|
||||
_, err := beaconChainClient.ListValidators(ctx, ðpb.ListValidatorsRequest{
|
||||
beaconChainClient := beaconApiChainClient{stateValidatorsProvider: stateValidatorsProvider}
|
||||
_, err := beaconChainClient.Validators(ctx, ðpb.ListValidatorsRequest{
|
||||
QueryFilter: ðpb.ListValidatorsRequest_Epoch{
|
||||
Epoch: 0,
|
||||
},
|
||||
@@ -78,13 +75,13 @@ func TestListValidators(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
stateValidatorsProvider := mock.NewMockStateValidatorsProvider(ctrl)
|
||||
stateValidatorsProvider.EXPECT().GetStateValidatorsForSlot(ctx, gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(
|
||||
stateValidatorsProvider.EXPECT().StateValidatorsForSlot(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(
|
||||
nil,
|
||||
errors.New("bar error"),
|
||||
)
|
||||
|
||||
beaconChainClient := beaconApiBeaconChainClient{stateValidatorsProvider: stateValidatorsProvider}
|
||||
_, err := beaconChainClient.ListValidators(ctx, ðpb.ListValidatorsRequest{
|
||||
beaconChainClient := beaconApiChainClient{stateValidatorsProvider: stateValidatorsProvider}
|
||||
_, err := beaconChainClient.Validators(ctx, ðpb.ListValidatorsRequest{
|
||||
QueryFilter: ðpb.ListValidatorsRequest_Genesis{},
|
||||
})
|
||||
assert.ErrorContains(t, "failed to get genesis state validators: bar error", err)
|
||||
@@ -96,13 +93,13 @@ func TestListValidators(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
stateValidatorsProvider := mock.NewMockStateValidatorsProvider(ctrl)
|
||||
stateValidatorsProvider.EXPECT().GetStateValidatorsForHead(ctx, gomock.Any(), gomock.Any(), gomock.Any()).Return(
|
||||
stateValidatorsProvider.EXPECT().StateValidatorsForHead(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(
|
||||
nil,
|
||||
errors.New("foo error"),
|
||||
)
|
||||
|
||||
beaconChainClient := beaconApiBeaconChainClient{stateValidatorsProvider: stateValidatorsProvider}
|
||||
_, err := beaconChainClient.ListValidators(ctx, ðpb.ListValidatorsRequest{
|
||||
beaconChainClient := beaconApiChainClient{stateValidatorsProvider: stateValidatorsProvider}
|
||||
_, err := beaconChainClient.Validators(ctx, ðpb.ListValidatorsRequest{
|
||||
QueryFilter: nil,
|
||||
})
|
||||
assert.ErrorContains(t, "failed to get head state validators: foo error", err)
|
||||
@@ -114,19 +111,19 @@ func TestListValidators(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
stateValidatorsProvider := mock.NewMockStateValidatorsProvider(ctrl)
|
||||
stateValidatorsProvider.EXPECT().GetStateValidatorsForHead(ctx, gomock.Any(), gomock.Any(), gomock.Any()).Return(
|
||||
stateValidatorsProvider.EXPECT().StateValidatorsForHead(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(ctx, blockHeaderEndpoint, gomock.Any()).Return(errors.New("bar error"))
|
||||
jsonRestHandler.EXPECT().Get(gomock.Any(), blockHeaderEndpoint, gomock.Any()).Return(errors.New("bar error"))
|
||||
|
||||
beaconChainClient := beaconApiBeaconChainClient{
|
||||
beaconChainClient := beaconApiChainClient{
|
||||
stateValidatorsProvider: stateValidatorsProvider,
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
}
|
||||
_, err := beaconChainClient.ListValidators(ctx, ðpb.ListValidatorsRequest{
|
||||
_, err := beaconChainClient.Validators(ctx, ðpb.ListValidatorsRequest{
|
||||
QueryFilter: nil,
|
||||
})
|
||||
assert.ErrorContains(t, "bar error", err)
|
||||
@@ -187,24 +184,24 @@ func TestListValidators(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
stateValidatorsProvider := mock.NewMockStateValidatorsProvider(ctrl)
|
||||
stateValidatorsProvider.EXPECT().GetStateValidatorsForHead(ctx, gomock.Any(), gomock.Any(), gomock.Any()).Return(
|
||||
stateValidatorsProvider.EXPECT().StateValidatorsForHead(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(ctx, blockHeaderEndpoint, gomock.Any()).Return(
|
||||
jsonRestHandler.EXPECT().Get(gomock.Any(), blockHeaderEndpoint, gomock.Any()).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
2,
|
||||
testCase.blockHeaderResponse,
|
||||
)
|
||||
|
||||
beaconChainClient := beaconApiBeaconChainClient{
|
||||
beaconChainClient := beaconApiChainClient{
|
||||
stateValidatorsProvider: stateValidatorsProvider,
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
}
|
||||
_, err := beaconChainClient.ListValidators(ctx, ðpb.ListValidatorsRequest{
|
||||
_, err := beaconChainClient.Validators(ctx, ðpb.ListValidatorsRequest{
|
||||
QueryFilter: nil,
|
||||
})
|
||||
assert.ErrorContains(t, testCase.expectedError, err)
|
||||
@@ -328,13 +325,13 @@ func TestListValidators(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
stateValidatorsProvider := mock.NewMockStateValidatorsProvider(ctrl)
|
||||
stateValidatorsProvider.EXPECT().GetStateValidatorsForSlot(ctx, gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(
|
||||
stateValidatorsProvider.EXPECT().StateValidatorsForSlot(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(
|
||||
testCase.generateStateValidatorsResponse(),
|
||||
nil,
|
||||
)
|
||||
|
||||
beaconChainClient := beaconApiBeaconChainClient{stateValidatorsProvider: stateValidatorsProvider}
|
||||
_, err := beaconChainClient.ListValidators(ctx, ðpb.ListValidatorsRequest{
|
||||
beaconChainClient := beaconApiChainClient{stateValidatorsProvider: stateValidatorsProvider}
|
||||
_, err := beaconChainClient.Validators(ctx, ðpb.ListValidatorsRequest{
|
||||
QueryFilter: ðpb.ListValidatorsRequest_Genesis{},
|
||||
})
|
||||
assert.ErrorContains(t, testCase.expectedError, err)
|
||||
@@ -556,13 +553,13 @@ func TestListValidators(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
stateValidatorsProvider := mock.NewMockStateValidatorsProvider(ctrl)
|
||||
stateValidatorsProvider.EXPECT().GetStateValidatorsForSlot(ctx, primitives.Slot(0), make([]string, 0), []primitives.ValidatorIndex{}, nil).Return(
|
||||
stateValidatorsProvider.EXPECT().StateValidatorsForSlot(gomock.Any(), primitives.Slot(0), make([]string, 0), []primitives.ValidatorIndex{}, nil).Return(
|
||||
testCase.generateJsonStateValidatorsResponse(),
|
||||
nil,
|
||||
)
|
||||
|
||||
beaconChainClient := beaconApiBeaconChainClient{stateValidatorsProvider: stateValidatorsProvider}
|
||||
validators, err := beaconChainClient.ListValidators(ctx, ðpb.ListValidatorsRequest{
|
||||
beaconChainClient := beaconApiChainClient{stateValidatorsProvider: stateValidatorsProvider}
|
||||
validators, err := beaconChainClient.Validators(ctx, ðpb.ListValidatorsRequest{
|
||||
QueryFilter: ðpb.ListValidatorsRequest_Genesis{},
|
||||
PublicKeys: [][]byte{},
|
||||
Indices: []primitives.ValidatorIndex{},
|
||||
@@ -745,15 +742,15 @@ func TestGetChainHead(t *testing.T) {
|
||||
|
||||
finalityCheckpointsResponse := structs.GetFinalityCheckpointsResponse{}
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(ctx, finalityCheckpointsEndpoint, &finalityCheckpointsResponse).Return(
|
||||
jsonRestHandler.EXPECT().Get(gomock.Any(), finalityCheckpointsEndpoint, &finalityCheckpointsResponse).Return(
|
||||
testCase.finalityCheckpointsError,
|
||||
).SetArg(
|
||||
2,
|
||||
testCase.generateFinalityCheckpointsResponse(),
|
||||
)
|
||||
|
||||
beaconChainClient := beaconApiBeaconChainClient{jsonRestHandler: jsonRestHandler}
|
||||
_, err := beaconChainClient.GetChainHead(ctx, &emptypb.Empty{})
|
||||
beaconChainClient := beaconApiChainClient{jsonRestHandler: jsonRestHandler}
|
||||
_, err := beaconChainClient.ChainHead(ctx, &emptypb.Empty{})
|
||||
assert.ErrorContains(t, testCase.expectedError, err)
|
||||
})
|
||||
}
|
||||
@@ -844,7 +841,7 @@ func TestGetChainHead(t *testing.T) {
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
|
||||
finalityCheckpointsResponse := structs.GetFinalityCheckpointsResponse{}
|
||||
jsonRestHandler.EXPECT().Get(ctx, finalityCheckpointsEndpoint, &finalityCheckpointsResponse).Return(
|
||||
jsonRestHandler.EXPECT().Get(gomock.Any(), finalityCheckpointsEndpoint, &finalityCheckpointsResponse).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
2,
|
||||
@@ -852,15 +849,15 @@ func TestGetChainHead(t *testing.T) {
|
||||
)
|
||||
|
||||
headBlockHeadersResponse := structs.GetBlockHeaderResponse{}
|
||||
jsonRestHandler.EXPECT().Get(ctx, headBlockHeadersEndpoint, &headBlockHeadersResponse).Return(
|
||||
jsonRestHandler.EXPECT().Get(gomock.Any(), headBlockHeadersEndpoint, &headBlockHeadersResponse).Return(
|
||||
testCase.headBlockHeadersError,
|
||||
).SetArg(
|
||||
2,
|
||||
testCase.generateHeadBlockHeadersResponse(),
|
||||
)
|
||||
|
||||
beaconChainClient := beaconApiBeaconChainClient{jsonRestHandler: jsonRestHandler}
|
||||
_, err := beaconChainClient.GetChainHead(ctx, &emptypb.Empty{})
|
||||
beaconChainClient := beaconApiChainClient{jsonRestHandler: jsonRestHandler}
|
||||
_, err := beaconChainClient.ChainHead(ctx, &emptypb.Empty{})
|
||||
assert.ErrorContains(t, testCase.expectedError, err)
|
||||
})
|
||||
}
|
||||
@@ -874,7 +871,7 @@ func TestGetChainHead(t *testing.T) {
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
|
||||
finalityCheckpointsResponse := structs.GetFinalityCheckpointsResponse{}
|
||||
jsonRestHandler.EXPECT().Get(ctx, finalityCheckpointsEndpoint, &finalityCheckpointsResponse).Return(
|
||||
jsonRestHandler.EXPECT().Get(gomock.Any(), finalityCheckpointsEndpoint, &finalityCheckpointsResponse).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
2,
|
||||
@@ -882,7 +879,7 @@ func TestGetChainHead(t *testing.T) {
|
||||
)
|
||||
|
||||
headBlockHeadersResponse := structs.GetBlockHeaderResponse{}
|
||||
jsonRestHandler.EXPECT().Get(ctx, headBlockHeadersEndpoint, &headBlockHeadersResponse).Return(
|
||||
jsonRestHandler.EXPECT().Get(gomock.Any(), headBlockHeadersEndpoint, &headBlockHeadersResponse).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
2,
|
||||
@@ -913,49 +910,9 @@ func TestGetChainHead(t *testing.T) {
|
||||
HeadEpoch: slots.ToEpoch(8),
|
||||
}
|
||||
|
||||
beaconChainClient := beaconApiBeaconChainClient{jsonRestHandler: jsonRestHandler}
|
||||
chainHead, err := beaconChainClient.GetChainHead(ctx, &emptypb.Empty{})
|
||||
beaconChainClient := beaconApiChainClient{jsonRestHandler: jsonRestHandler}
|
||||
chainHead, err := beaconChainClient.ChainHead(ctx, &emptypb.Empty{})
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, expectedChainHead, chainHead)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_beaconApiBeaconChainClient_GetValidatorPerformance(t *testing.T) {
|
||||
publicKeys := [][48]byte{
|
||||
bytesutil.ToBytes48([]byte{1}),
|
||||
bytesutil.ToBytes48([]byte{2}),
|
||||
bytesutil.ToBytes48([]byte{3}),
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
request, err := json.Marshal(structs.GetValidatorPerformanceRequest{
|
||||
PublicKeys: [][]byte{publicKeys[0][:], publicKeys[2][:], publicKeys[1][:]},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
wantResponse := &structs.GetValidatorPerformanceResponse{}
|
||||
want := ðpb.ValidatorPerformanceResponse{}
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
ctx,
|
||||
getValidatorPerformanceEndpoint,
|
||||
nil,
|
||||
bytes.NewBuffer(request),
|
||||
wantResponse,
|
||||
).Return(
|
||||
nil,
|
||||
)
|
||||
|
||||
c := beaconApiBeaconChainClient{
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
}
|
||||
|
||||
got, err := c.GetValidatorPerformance(ctx, ðpb.ValidatorPerformanceRequest{
|
||||
PublicKeys: [][]byte{publicKeys[0][:], publicKeys[2][:], publicKeys[1][:]},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, want.PublicKeys, got.PublicKeys)
|
||||
}
|
||||
@@ -1,276 +0,0 @@
|
||||
package beacon
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/pkg/errors"
|
||||
base "github.com/prysmaticlabs/prysm/v5/api/client"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/ssz/detect"
|
||||
"github.com/prysmaticlabs/prysm/v5/io/file"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/v5/time/slots"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/mod/semver"
|
||||
)
|
||||
|
||||
var errCheckpointBlockMismatch = errors.New("mismatch between checkpoint sync state and block")
|
||||
|
||||
// OriginData represents the BeaconState and ReadOnlySignedBeaconBlock necessary to start an empty Beacon Node
|
||||
// using Checkpoint Sync.
|
||||
type OriginData struct {
|
||||
sb []byte
|
||||
bb []byte
|
||||
st state.BeaconState
|
||||
b interfaces.ReadOnlySignedBeaconBlock
|
||||
vu *detect.VersionedUnmarshaler
|
||||
br [32]byte
|
||||
sr [32]byte
|
||||
}
|
||||
|
||||
// SaveBlock saves the downloaded block to a unique file in the given path.
|
||||
// For readability and collision avoidance, the file name includes: type, config name, slot and root
|
||||
func (o *OriginData) SaveBlock(dir string) (string, error) {
|
||||
blockPath := path.Join(dir, fname("block", o.vu, o.b.Block().Slot(), o.br))
|
||||
return blockPath, file.WriteFile(blockPath, o.BlockBytes())
|
||||
}
|
||||
|
||||
// SaveState saves the downloaded state to a unique file in the given path.
|
||||
// For readability and collision avoidance, the file name includes: type, config name, slot and root
|
||||
func (o *OriginData) SaveState(dir string) (string, error) {
|
||||
statePath := path.Join(dir, fname("state", o.vu, o.st.Slot(), o.sr))
|
||||
return statePath, file.WriteFile(statePath, o.StateBytes())
|
||||
}
|
||||
|
||||
// StateBytes returns the ssz-encoded bytes of the downloaded BeaconState value.
|
||||
func (o *OriginData) StateBytes() []byte {
|
||||
return o.sb
|
||||
}
|
||||
|
||||
// BlockBytes returns the ssz-encoded bytes of the downloaded ReadOnlySignedBeaconBlock value.
|
||||
func (o *OriginData) BlockBytes() []byte {
|
||||
return o.bb
|
||||
}
|
||||
|
||||
func fname(prefix string, vu *detect.VersionedUnmarshaler, slot primitives.Slot, root [32]byte) string {
|
||||
return fmt.Sprintf("%s_%s_%s_%d-%#x.ssz", prefix, vu.Config.ConfigName, version.String(vu.Fork), slot, root)
|
||||
}
|
||||
|
||||
// DownloadFinalizedData downloads the most recently finalized state, and the block most recently applied to that state.
|
||||
// This pair can be used to initialize a new beacon node via checkpoint sync.
|
||||
func DownloadFinalizedData(ctx context.Context, client *Client) (*OriginData, error) {
|
||||
sb, err := client.GetState(ctx, IdFinalized)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
vu, err := detect.FromState(sb)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error detecting chain config for finalized state")
|
||||
}
|
||||
|
||||
log.WithFields(logrus.Fields{
|
||||
"name": vu.Config.ConfigName,
|
||||
"fork": version.String(vu.Fork),
|
||||
}).Info("Detected supported config in remote finalized state")
|
||||
|
||||
s, err := vu.UnmarshalBeaconState(sb)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error unmarshaling finalized state to correct version")
|
||||
}
|
||||
|
||||
slot := s.LatestBlockHeader().Slot
|
||||
bb, err := client.GetBlock(ctx, IdFromSlot(slot))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error requesting block by slot = %d", slot)
|
||||
}
|
||||
b, err := vu.UnmarshalBeaconBlock(bb)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to unmarshal block to a supported type using the detected fork schedule")
|
||||
}
|
||||
br, err := b.Block().HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error computing hash_tree_root of retrieved block")
|
||||
}
|
||||
bodyRoot, err := b.Block().Body().HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error computing hash_tree_root of retrieved block body")
|
||||
}
|
||||
|
||||
sbr := bytesutil.ToBytes32(s.LatestBlockHeader().BodyRoot)
|
||||
if sbr != bodyRoot {
|
||||
return nil, errors.Wrapf(errCheckpointBlockMismatch, "state body root = %#x, block body root = %#x", sbr, bodyRoot)
|
||||
}
|
||||
sr, err := s.HashTreeRoot(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to compute htr for finalized state at slot=%d", s.Slot())
|
||||
}
|
||||
|
||||
log.
|
||||
WithField("blockSlot", b.Block().Slot()).
|
||||
WithField("stateSlot", s.Slot()).
|
||||
WithField("stateRoot", hexutil.Encode(sr[:])).
|
||||
WithField("blockRoot", hexutil.Encode(br[:])).
|
||||
Info("Downloaded checkpoint sync state and block.")
|
||||
return &OriginData{
|
||||
st: s,
|
||||
b: b,
|
||||
sb: sb,
|
||||
bb: bb,
|
||||
vu: vu,
|
||||
br: br,
|
||||
sr: sr,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// WeakSubjectivityData represents the state root, block root and epoch of the BeaconState + ReadOnlySignedBeaconBlock
|
||||
// that falls at the beginning of the current weak subjectivity period. These values can be used to construct
|
||||
// a weak subjectivity checkpoint beacon node flag to be used for validation.
|
||||
type WeakSubjectivityData struct {
|
||||
BlockRoot [32]byte
|
||||
StateRoot [32]byte
|
||||
Epoch primitives.Epoch
|
||||
}
|
||||
|
||||
// CheckpointString returns the standard string representation of a Checkpoint.
|
||||
// The format is a hex-encoded block root, followed by the epoch of the block, separated by a colon. For example:
|
||||
// "0x1c35540cac127315fabb6bf29181f2ae0de1a3fc909d2e76ba771e61312cc49a:74888"
|
||||
func (wsd *WeakSubjectivityData) CheckpointString() string {
|
||||
return fmt.Sprintf("%#x:%d", wsd.BlockRoot, wsd.Epoch)
|
||||
}
|
||||
|
||||
// ComputeWeakSubjectivityCheckpoint attempts to use the prysm weak_subjectivity api
|
||||
// to obtain the current weak_subjectivity checkpoint.
|
||||
// For non-prysm nodes, the same computation will be performed with extra steps,
|
||||
// using the head state downloaded from the beacon node api.
|
||||
func ComputeWeakSubjectivityCheckpoint(ctx context.Context, client *Client) (*WeakSubjectivityData, error) {
|
||||
ws, err := client.GetWeakSubjectivity(ctx)
|
||||
if err != nil {
|
||||
// a 404/405 is expected if querying an endpoint that doesn't support the weak subjectivity checkpoint api
|
||||
if !errors.Is(err, base.ErrNotOK) {
|
||||
return nil, errors.Wrap(err, "unexpected API response for prysm-only weak subjectivity checkpoint API")
|
||||
}
|
||||
// fall back to vanilla Beacon Node API method
|
||||
return computeBackwardsCompatible(ctx, client)
|
||||
}
|
||||
log.Printf("server weak subjectivity checkpoint response - epoch=%d, block_root=%#x, state_root=%#x", ws.Epoch, ws.BlockRoot, ws.StateRoot)
|
||||
return ws, nil
|
||||
}
|
||||
|
||||
const (
|
||||
prysmMinimumVersion = "v2.0.7"
|
||||
prysmImplementationName = "Prysm"
|
||||
)
|
||||
|
||||
// errUnsupportedPrysmCheckpointVersion indicates remote beacon node can't be used for checkpoint retrieval.
|
||||
var errUnsupportedPrysmCheckpointVersion = errors.New("node does not meet minimum version requirements for checkpoint retrieval")
|
||||
|
||||
// for older endpoints or clients that do not support the weak_subjectivity api method
|
||||
// we gather the necessary data for a checkpoint sync by:
|
||||
// - inspecting the remote server's head state and computing the weak subjectivity epoch locally
|
||||
// - requesting the state at the first slot of the epoch
|
||||
// - using hash_tree_root(state.latest_block_header) to compute the block the state integrates
|
||||
// - requesting that block by its root
|
||||
func computeBackwardsCompatible(ctx context.Context, client *Client) (*WeakSubjectivityData, error) {
|
||||
log.Print("falling back to generic checkpoint derivation, weak_subjectivity API not supported by server")
|
||||
nv, err := client.GetNodeVersion(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to proceed with fallback method without confirming node version")
|
||||
}
|
||||
if nv.implementation == prysmImplementationName && semver.Compare(nv.semver, prysmMinimumVersion) < 0 {
|
||||
return nil, errors.Wrapf(errUnsupportedPrysmCheckpointVersion, "%s < minimum (%s)", nv.semver, prysmMinimumVersion)
|
||||
}
|
||||
epoch, err := getWeakSubjectivityEpochFromHead(ctx, client)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error computing weak subjectivity epoch via head state inspection")
|
||||
}
|
||||
|
||||
// use first slot of the epoch for the state slot
|
||||
slot, err := slots.EpochStart(epoch)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error computing first slot of epoch=%d", epoch)
|
||||
}
|
||||
|
||||
log.Printf("requesting checkpoint state at slot %d", slot)
|
||||
// get the state at the first slot of the epoch
|
||||
sb, err := client.GetState(ctx, IdFromSlot(slot))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to request state by slot from api, slot=%d", slot)
|
||||
}
|
||||
|
||||
// ConfigFork is used to unmarshal the BeaconState so we can read the block root in latest_block_header
|
||||
vu, err := detect.FromState(sb)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error detecting chain config for beacon state")
|
||||
}
|
||||
log.Printf("detected supported config in checkpoint state, name=%s, fork=%s", vu.Config.ConfigName, version.String(vu.Fork))
|
||||
|
||||
s, err := vu.UnmarshalBeaconState(sb)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error using detected config fork to unmarshal state bytes")
|
||||
}
|
||||
|
||||
// compute state and block roots
|
||||
sr, err := s.HashTreeRoot(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error computing hash_tree_root of state")
|
||||
}
|
||||
|
||||
h := s.LatestBlockHeader()
|
||||
h.StateRoot = sr[:]
|
||||
br, err := h.HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error while computing block root using state data")
|
||||
}
|
||||
|
||||
bb, err := client.GetBlock(ctx, IdFromRoot(br))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error requesting block by root = %d", br)
|
||||
}
|
||||
b, err := vu.UnmarshalBeaconBlock(bb)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to unmarshal block to a supported type using the detected fork schedule")
|
||||
}
|
||||
br, err = b.Block().HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error computing hash_tree_root for block obtained via root")
|
||||
}
|
||||
|
||||
return &WeakSubjectivityData{
|
||||
Epoch: epoch,
|
||||
BlockRoot: br,
|
||||
StateRoot: sr,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// this method downloads the head state, which can be used to find the correct chain config
|
||||
// and use prysm's helper methods to compute the latest weak subjectivity epoch.
|
||||
func getWeakSubjectivityEpochFromHead(ctx context.Context, client *Client) (primitives.Epoch, error) {
|
||||
headBytes, err := client.GetState(ctx, IdHead)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
vu, err := detect.FromState(headBytes)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "error detecting chain config for beacon state")
|
||||
}
|
||||
log.Printf("detected supported config in remote head state, name=%s, fork=%s", vu.Config.ConfigName, version.String(vu.Fork))
|
||||
headState, err := vu.UnmarshalBeaconState(headBytes)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "error unmarshaling state to correct version")
|
||||
}
|
||||
|
||||
epoch, err := helpers.LatestWeakSubjectivityEpoch(ctx, headState, vu.Config)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "error computing the weak subjectivity epoch from head state")
|
||||
}
|
||||
|
||||
log.Printf("(computed client-side) weak subjectivity epoch = %d", epoch)
|
||||
return epoch, nil
|
||||
}
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"text/template"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/pkg/errors"
|
||||
@@ -29,12 +28,13 @@ const (
|
||||
getSignedBlockPath = "/eth/v2/beacon/blocks"
|
||||
getBlockRootPath = "/eth/v1/beacon/blocks/{{.Id}}/root"
|
||||
getForkForStatePath = "/eth/v1/beacon/states/{{.Id}}/fork"
|
||||
getWeakSubjectivityPath = "/prysm/v1/beacon/weak_subjectivity"
|
||||
getForkSchedulePath = "/eth/v1/config/fork_schedule"
|
||||
getConfigSpecPath = "/eth/v1/config/spec"
|
||||
getStatePath = "/eth/v2/debug/beacon/states"
|
||||
getNodeVersionPath = "/eth/v1/node/version"
|
||||
changeBLStoExecutionPath = "/eth/v1/beacon/pool/bls_to_execution_changes"
|
||||
|
||||
GetNodeVersionPath = "/eth/v1/node/version"
|
||||
GetWeakSubjectivityPath = "/prysm/v1/beacon/weak_subjectivity"
|
||||
)
|
||||
|
||||
// StateOrBlockId represents the block_id / state_id parameters that several of the Eth Beacon API methods accept.
|
||||
@@ -63,24 +63,8 @@ func IdFromSlot(s primitives.Slot) StateOrBlockId {
|
||||
return StateOrBlockId(strconv.FormatUint(uint64(s), 10))
|
||||
}
|
||||
|
||||
// idTemplate is used to create template functions that can interpolate StateOrBlockId values.
|
||||
func idTemplate(ts string) func(StateOrBlockId) string {
|
||||
t := template.Must(template.New("").Parse(ts))
|
||||
f := func(id StateOrBlockId) string {
|
||||
b := bytes.NewBuffer(nil)
|
||||
err := t.Execute(b, struct{ Id string }{Id: string(id)})
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("invalid idTemplate: %s", ts))
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
// run the template to ensure that it is valid
|
||||
// this should happen load time (using package scoped vars) to ensure runtime errors aren't possible
|
||||
_ = f(IdGenesis)
|
||||
return f
|
||||
}
|
||||
|
||||
func renderGetBlockPath(id StateOrBlockId) string {
|
||||
// RenderGetBlockPath formats a block id into a path for the GetBlock API endpoint.
|
||||
func RenderGetBlockPath(id StateOrBlockId) string {
|
||||
return path.Join(getSignedBlockPath, string(id))
|
||||
}
|
||||
|
||||
@@ -104,7 +88,7 @@ func NewClient(host string, opts ...client.ClientOpt) (*Client, error) {
|
||||
// for the named identifiers.
|
||||
// The return value contains the ssz-encoded bytes.
|
||||
func (c *Client) GetBlock(ctx context.Context, blockId StateOrBlockId) ([]byte, error) {
|
||||
blockPath := renderGetBlockPath(blockId)
|
||||
blockPath := RenderGetBlockPath(blockId)
|
||||
b, err := c.Get(ctx, blockPath, client.WithSSZEncoding())
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error requesting state by id = %s", blockId)
|
||||
@@ -112,8 +96,6 @@ func (c *Client) GetBlock(ctx context.Context, blockId StateOrBlockId) ([]byte,
|
||||
return b, nil
|
||||
}
|
||||
|
||||
var getBlockRootTpl = idTemplate(getBlockRootPath)
|
||||
|
||||
// GetBlockRoot retrieves the hash_tree_root of the BeaconBlock for the given block id.
|
||||
// Block identifier can be one of: "head" (canonical head in node's view), "genesis", "finalized",
|
||||
// <slot>, <hex encoded blockRoot with 0x prefix>. Variables of type StateOrBlockId are exported by this package
|
||||
@@ -136,8 +118,6 @@ func (c *Client) GetBlockRoot(ctx context.Context, blockId StateOrBlockId) ([32]
|
||||
return bytesutil.ToBytes32(rs), nil
|
||||
}
|
||||
|
||||
var getForkTpl = idTemplate(getForkForStatePath)
|
||||
|
||||
// GetFork queries the Beacon Node API for the Fork from the state identified by stateId.
|
||||
// Block identifier can be one of: "head" (canonical head in node's view), "genesis", "finalized",
|
||||
// <slot>, <hex encoded blockRoot with 0x prefix>. Variables of type StateOrBlockId are exported by this package
|
||||
@@ -195,6 +175,10 @@ type NodeVersion struct {
|
||||
systemInfo string
|
||||
}
|
||||
|
||||
func (nv *NodeVersion) SetImplementation(impl string) {
|
||||
nv.implementation = impl
|
||||
}
|
||||
|
||||
var versionRE = regexp.MustCompile(`^(\w+)/(v\d+\.\d+\.\d+[-a-zA-Z0-9]*)\s*/?(.*)$`)
|
||||
|
||||
func parseNodeVersion(v string) (*NodeVersion, error) {
|
||||
@@ -212,7 +196,7 @@ func parseNodeVersion(v string) (*NodeVersion, error) {
|
||||
// GetNodeVersion requests that the beacon node identify information about its implementation in a format
|
||||
// similar to a HTTP User-Agent field. ex: Lighthouse/v0.1.5 (Linux x86_64)
|
||||
func (c *Client) GetNodeVersion(ctx context.Context) (*NodeVersion, error) {
|
||||
b, err := c.Get(ctx, getNodeVersionPath)
|
||||
b, err := c.Get(ctx, GetNodeVersionPath)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error requesting node version")
|
||||
}
|
||||
@@ -228,7 +212,8 @@ func (c *Client) GetNodeVersion(ctx context.Context) (*NodeVersion, error) {
|
||||
return parseNodeVersion(d.Data.Version)
|
||||
}
|
||||
|
||||
func renderGetStatePath(id StateOrBlockId) string {
|
||||
// RenderGetStatePath formats a state id into a path for the GetState API endpoint.
|
||||
func RenderGetStatePath(id StateOrBlockId) string {
|
||||
return path.Join(getStatePath, string(id))
|
||||
}
|
||||
|
||||
@@ -246,13 +231,29 @@ func (c *Client) GetState(ctx context.Context, stateId StateOrBlockId) ([]byte,
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// WeakSubjectivityData represents the state root, block root and epoch of the BeaconState + ReadOnlySignedBeaconBlock
|
||||
// that falls at the beginning of the current weak subjectivity period. These values can be used to construct
|
||||
// a weak subjectivity checkpoint beacon node flag to be used for validation.
|
||||
type WeakSubjectivityData struct {
|
||||
BlockRoot [32]byte
|
||||
StateRoot [32]byte
|
||||
Epoch primitives.Epoch
|
||||
}
|
||||
|
||||
// CheckpointString returns the standard string representation of a Checkpoint.
|
||||
// The format is a hex-encoded block root, followed by the epoch of the block, separated by a colon. For example:
|
||||
// "0x1c35540cac127315fabb6bf29181f2ae0de1a3fc909d2e76ba771e61312cc49a:74888"
|
||||
func (wsd *WeakSubjectivityData) CheckpointString() string {
|
||||
return fmt.Sprintf("%#x:%d", wsd.BlockRoot, wsd.Epoch)
|
||||
}
|
||||
|
||||
// GetWeakSubjectivity calls a proposed API endpoint that is unique to prysm
|
||||
// This api method does the following:
|
||||
// - computes weak subjectivity epoch
|
||||
// - finds the highest non-skipped block preceding the epoch
|
||||
// - returns the htr of the found block and returns this + the value of state_root from the block
|
||||
func (c *Client) GetWeakSubjectivity(ctx context.Context) (*WeakSubjectivityData, error) {
|
||||
body, err := c.Get(ctx, getWeakSubjectivityPath)
|
||||
body, err := c.Get(ctx, GetWeakSubjectivityPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -97,31 +97,31 @@ func TestValidHostname(t *testing.T) {
|
||||
{
|
||||
name: "hostname with port",
|
||||
hostArg: "mydomain.org:3500",
|
||||
path: getNodeVersionPath,
|
||||
path: GetNodeVersionPath,
|
||||
joined: "http://mydomain.org:3500/eth/v1/node/version",
|
||||
},
|
||||
{
|
||||
name: "https scheme, hostname with port",
|
||||
hostArg: "https://mydomain.org:3500",
|
||||
path: getNodeVersionPath,
|
||||
path: GetNodeVersionPath,
|
||||
joined: "https://mydomain.org:3500/eth/v1/node/version",
|
||||
},
|
||||
{
|
||||
name: "http scheme, hostname without port",
|
||||
hostArg: "http://mydomain.org",
|
||||
path: getNodeVersionPath,
|
||||
path: GetNodeVersionPath,
|
||||
joined: "http://mydomain.org/eth/v1/node/version",
|
||||
},
|
||||
{
|
||||
name: "http scheme, trailing slash, hostname without port",
|
||||
hostArg: "http://mydomain.org/",
|
||||
path: getNodeVersionPath,
|
||||
path: GetNodeVersionPath,
|
||||
joined: "http://mydomain.org/eth/v1/node/version",
|
||||
},
|
||||
{
|
||||
name: "http scheme, hostname with basic auth creds and no port",
|
||||
hostArg: "http://username:pass@mydomain.org/",
|
||||
path: getNodeVersionPath,
|
||||
path: GetNodeVersionPath,
|
||||
joined: "http://username:pass@mydomain.org/eth/v1/node/version",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
package beacon
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/iface"
|
||||
)
|
||||
|
||||
type NodeHealthTracker struct {
|
||||
isHealthy *bool
|
||||
healthChan chan bool
|
||||
node iface.HealthNode
|
||||
sync.RWMutex
|
||||
}
|
||||
|
||||
func NewNodeHealthTracker(node iface.HealthNode) *NodeHealthTracker {
|
||||
return &NodeHealthTracker{
|
||||
node: node,
|
||||
healthChan: make(chan bool, 1),
|
||||
}
|
||||
}
|
||||
|
||||
// HealthUpdates provides a read-only channel for health updates.
|
||||
func (n *NodeHealthTracker) HealthUpdates() <-chan bool {
|
||||
return n.healthChan
|
||||
}
|
||||
|
||||
func (n *NodeHealthTracker) IsHealthy() bool {
|
||||
n.RLock()
|
||||
defer n.RUnlock()
|
||||
if n.isHealthy == nil {
|
||||
return false
|
||||
}
|
||||
return *n.isHealthy
|
||||
}
|
||||
|
||||
func (n *NodeHealthTracker) CheckHealth(ctx context.Context) bool {
|
||||
n.RLock()
|
||||
newStatus := n.node.IsHealthy(ctx)
|
||||
if n.isHealthy == nil {
|
||||
n.isHealthy = &newStatus
|
||||
}
|
||||
isStatusChanged := newStatus != *n.isHealthy
|
||||
n.RUnlock()
|
||||
|
||||
if isStatusChanged {
|
||||
n.Lock()
|
||||
// Double-check the condition to ensure it hasn't changed since the first check.
|
||||
n.isHealthy = &newStatus
|
||||
n.Unlock() // It's better to unlock as soon as the protected section is over.
|
||||
n.healthChan <- newStatus
|
||||
}
|
||||
return newStatus
|
||||
}
|
||||
20
api/client/beacon/health/BUILD.bazel
Normal file
20
api/client/beacon/health/BUILD.bazel
Normal file
@@ -0,0 +1,20 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"health_mock.go",
|
||||
"interfaces.go",
|
||||
"tracker.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/api/client/beacon/health",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = ["@org_uber_go_mock//gomock:go_default_library"],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["tracker_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = ["@org_uber_go_mock//gomock:go_default_library"],
|
||||
)
|
||||
@@ -1,21 +1,26 @@
|
||||
package testing
|
||||
package health
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/iface"
|
||||
"go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
var (
|
||||
_ = iface.HealthNode(&MockHealthClient{})
|
||||
)
|
||||
// NewMockHealthClient creates a new mock instance.
|
||||
func NewMockHealthClient(ctrl *gomock.Controller) *MockHealthClient {
|
||||
mock := &MockHealthClient{ctrl: ctrl}
|
||||
mock.recorder = &MockHealthClientMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// MockHealthClient is a mock of HealthClient interface.
|
||||
type MockHealthClient struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockHealthClientMockRecorder
|
||||
Health bool
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
// MockHealthClientMockRecorder is the mock recorder for MockHealthClient.
|
||||
@@ -25,6 +30,8 @@ type MockHealthClientMockRecorder struct {
|
||||
|
||||
// IsHealthy mocks base method.
|
||||
func (m *MockHealthClient) IsHealthy(arg0 context.Context) bool {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "IsHealthy", arg0)
|
||||
ret0, ok := ret[0].(bool)
|
||||
@@ -34,6 +41,16 @@ func (m *MockHealthClient) IsHealthy(arg0 context.Context) bool {
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (m *MockHealthClient) HealthUpdates() <-chan bool {
|
||||
ch := make(chan bool, 2)
|
||||
ch <- m.Health
|
||||
return ch
|
||||
}
|
||||
|
||||
func (m *MockHealthClient) CheckHealth(_ context.Context) bool {
|
||||
return m.Health
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockHealthClient) EXPECT() *MockHealthClientMockRecorder {
|
||||
return m.recorder
|
||||
@@ -41,13 +58,8 @@ func (m *MockHealthClient) EXPECT() *MockHealthClientMockRecorder {
|
||||
|
||||
// IsHealthy indicates an expected call of IsHealthy.
|
||||
func (mr *MockHealthClientMockRecorder) IsHealthy(arg0 any) *gomock.Call {
|
||||
mr.mock.Lock()
|
||||
defer mr.mock.Unlock()
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsHealthy", reflect.TypeOf((*MockHealthClient)(nil).IsHealthy), arg0)
|
||||
}
|
||||
|
||||
// NewMockHealthClient creates a new mock instance.
|
||||
func NewMockHealthClient(ctrl *gomock.Controller) *MockHealthClient {
|
||||
mock := &MockHealthClient{ctrl: ctrl}
|
||||
mock.recorder = &MockHealthClientMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
package iface
|
||||
package health
|
||||
|
||||
import "context"
|
||||
|
||||
type HealthTracker interface {
|
||||
HealthUpdates() <-chan bool
|
||||
IsHealthy() bool
|
||||
IsHealthy(ctx context.Context) bool
|
||||
CheckHealth(ctx context.Context) bool
|
||||
}
|
||||
|
||||
58
api/client/beacon/health/tracker.go
Normal file
58
api/client/beacon/health/tracker.go
Normal file
@@ -0,0 +1,58 @@
|
||||
package health
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type healthTracker struct {
|
||||
isHealthy *bool
|
||||
healthChan chan bool
|
||||
node HealthNode
|
||||
sync.RWMutex
|
||||
}
|
||||
|
||||
func NewTracker(node HealthNode) HealthTracker {
|
||||
return &healthTracker{
|
||||
node: node,
|
||||
healthChan: make(chan bool, 1),
|
||||
}
|
||||
}
|
||||
|
||||
// HealthUpdates provides a read-only channel for health updates.
|
||||
func (n *healthTracker) HealthUpdates() <-chan bool {
|
||||
return n.healthChan
|
||||
}
|
||||
|
||||
func (n *healthTracker) IsHealthy(_ context.Context) bool {
|
||||
n.RLock()
|
||||
defer n.RUnlock()
|
||||
if n.isHealthy == nil {
|
||||
return false
|
||||
}
|
||||
return *n.isHealthy
|
||||
}
|
||||
|
||||
func (n *healthTracker) CheckHealth(ctx context.Context) bool {
|
||||
n.Lock()
|
||||
defer n.Unlock()
|
||||
|
||||
newStatus := n.node.IsHealthy(ctx)
|
||||
if n.isHealthy == nil {
|
||||
n.isHealthy = &newStatus
|
||||
}
|
||||
|
||||
isStatusChanged := newStatus != *n.isHealthy
|
||||
if isStatusChanged {
|
||||
// Update the health status
|
||||
n.isHealthy = &newStatus
|
||||
// Send the new status to the health channel, potentially overwriting the existing value
|
||||
select {
|
||||
case <-n.healthChan:
|
||||
n.healthChan <- newStatus
|
||||
default:
|
||||
n.healthChan <- newStatus
|
||||
}
|
||||
}
|
||||
return newStatus
|
||||
}
|
||||
@@ -1,14 +1,17 @@
|
||||
package beacon
|
||||
package health
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
healthTesting "github.com/prysmaticlabs/prysm/v5/api/client/beacon/testing"
|
||||
"go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
var (
|
||||
_ = HealthTracker(&MockHealthClient{})
|
||||
)
|
||||
|
||||
func TestNodeHealth_IsHealthy(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -20,11 +23,11 @@ func TestNodeHealth_IsHealthy(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
n := &NodeHealthTracker{
|
||||
n := &healthTracker{
|
||||
isHealthy: &tt.isHealthy,
|
||||
healthChan: make(chan bool, 1),
|
||||
}
|
||||
if got := n.IsHealthy(); got != tt.want {
|
||||
if got := n.IsHealthy(context.Background()); got != tt.want {
|
||||
t.Errorf("IsHealthy() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
@@ -47,9 +50,9 @@ func TestNodeHealth_UpdateNodeHealth(t *testing.T) {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
client := healthTesting.NewMockHealthClient(ctrl)
|
||||
client := NewMockHealthClient(ctrl)
|
||||
client.EXPECT().IsHealthy(gomock.Any()).Return(tt.newStatus)
|
||||
n := &NodeHealthTracker{
|
||||
n := &healthTracker{
|
||||
isHealthy: &tt.initial,
|
||||
node: client,
|
||||
healthChan: make(chan bool, 1),
|
||||
@@ -80,28 +83,22 @@ func TestNodeHealth_UpdateNodeHealth(t *testing.T) {
|
||||
func TestNodeHealth_Concurrency(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
client := healthTesting.NewMockHealthClient(ctrl)
|
||||
n := NewNodeHealthTracker(client)
|
||||
client := NewMockHealthClient(ctrl)
|
||||
n := NewTracker(client)
|
||||
var wg sync.WaitGroup
|
||||
|
||||
// Number of goroutines to spawn for both reading and writing
|
||||
numGoroutines := 6
|
||||
|
||||
go func() {
|
||||
for range n.HealthUpdates() {
|
||||
// Consume values to avoid blocking on channel send.
|
||||
}
|
||||
}()
|
||||
|
||||
wg.Add(numGoroutines * 2) // for readers and writers
|
||||
|
||||
// Concurrently update health status
|
||||
for i := 0; i < numGoroutines; i++ {
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
client.EXPECT().IsHealthy(gomock.Any()).Return(false)
|
||||
client.EXPECT().IsHealthy(gomock.Any()).Return(false).Times(1)
|
||||
n.CheckHealth(context.Background())
|
||||
client.EXPECT().IsHealthy(gomock.Any()).Return(true)
|
||||
client.EXPECT().IsHealthy(gomock.Any()).Return(true).Times(1)
|
||||
n.CheckHealth(context.Background())
|
||||
}()
|
||||
}
|
||||
@@ -110,7 +107,7 @@ func TestNodeHealth_Concurrency(t *testing.T) {
|
||||
for i := 0; i < numGoroutines; i++ {
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
_ = n.IsHealthy() // Just read the value
|
||||
_ = n.IsHealthy(context.Background()) // Just read the value
|
||||
}()
|
||||
}
|
||||
|
||||
@@ -1,24 +1,28 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_library")
|
||||
|
||||
package(default_testonly = True)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"beacon_chain_client_mock.go",
|
||||
"beacon_block_converter_mock.go",
|
||||
"chain_client_mock.go",
|
||||
"duties_mock.go",
|
||||
"genesis_mock.go",
|
||||
"json_rest_handler_mock.go",
|
||||
"node_client_mock.go",
|
||||
"prysm_beacon_chain_client_mock.go",
|
||||
"prysm_chain_client_mock.go",
|
||||
"state_validators_mock.go",
|
||||
"validator_client_mock.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/testing/validator-mock",
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/api/client/beacon/mock",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//api/client/beacon:go_default_library",
|
||||
"//api/client/beacon/health:go_default_library",
|
||||
"//api/client/event:go_default_library",
|
||||
"//api/server/structs:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//consensus-types/validator:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//validator/client/iface:go_default_library",
|
||||
"@org_golang_google_protobuf//types/known/emptypb:go_default_library",
|
||||
"@org_uber_go_mock//gomock:go_default_library",
|
||||
],
|
||||
132
api/client/beacon/mock/chain_client_mock.go
generated
Normal file
132
api/client/beacon/mock/chain_client_mock.go
generated
Normal file
@@ -0,0 +1,132 @@
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: github.com/prysmaticlabs/prysm/v5/validator/client/iface (interfaces: ChainClient)
|
||||
//
|
||||
// Generated by this command:
|
||||
//
|
||||
// mockgen -package=validator_mock -destination=testing/validator-mock/chain_client_mock.go github.com/prysmaticlabs/prysm/v5/validator/client/iface ChainClient
|
||||
//
|
||||
|
||||
// Package validator_mock is a generated GoMock package.
|
||||
package mock
|
||||
|
||||
import (
|
||||
context "context"
|
||||
reflect "reflect"
|
||||
|
||||
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
emptypb "google.golang.org/protobuf/types/known/emptypb"
|
||||
)
|
||||
|
||||
// MockChainClient is a mock of ChainClient interface.
|
||||
type MockChainClient struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockChainClientMockRecorder
|
||||
}
|
||||
|
||||
// MockChainClientMockRecorder is the mock recorder for MockChainClient.
|
||||
type MockChainClientMockRecorder struct {
|
||||
mock *MockChainClient
|
||||
}
|
||||
|
||||
// NewMockChainClient creates a new mock instance.
|
||||
func NewMockChainClient(ctrl *gomock.Controller) *MockChainClient {
|
||||
mock := &MockChainClient{ctrl: ctrl}
|
||||
mock.recorder = &MockChainClientMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockChainClient) EXPECT() *MockChainClientMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// ChainHead mocks base method.
|
||||
func (m *MockChainClient) ChainHead(arg0 context.Context, arg1 *emptypb.Empty) (*eth.ChainHead, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ChainHead", arg0, arg1)
|
||||
ret0, _ := ret[0].(*eth.ChainHead)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// ChainHead indicates an expected call of ChainHead.
|
||||
func (mr *MockChainClientMockRecorder) ChainHead(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChainHead", reflect.TypeOf((*MockChainClient)(nil).ChainHead), arg0, arg1)
|
||||
}
|
||||
|
||||
// ValidatorBalances mocks base method.
|
||||
func (m *MockChainClient) ValidatorBalances(arg0 context.Context, arg1 *eth.ListValidatorBalancesRequest) (*eth.ValidatorBalances, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ValidatorBalances", arg0, arg1)
|
||||
ret0, _ := ret[0].(*eth.ValidatorBalances)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// ValidatorBalances indicates an expected call of ValidatorBalances.
|
||||
func (mr *MockChainClientMockRecorder) ValidatorBalances(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidatorBalances", reflect.TypeOf((*MockChainClient)(nil).ValidatorBalances), arg0, arg1)
|
||||
}
|
||||
|
||||
// ValidatorParticipation mocks base method.
|
||||
func (m *MockChainClient) ValidatorParticipation(arg0 context.Context, arg1 *eth.GetValidatorParticipationRequest) (*eth.ValidatorParticipationResponse, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ValidatorParticipation", arg0, arg1)
|
||||
ret0, _ := ret[0].(*eth.ValidatorParticipationResponse)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// ValidatorParticipation indicates an expected call of ValidatorParticipation.
|
||||
func (mr *MockChainClientMockRecorder) ValidatorParticipation(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidatorParticipation", reflect.TypeOf((*MockChainClient)(nil).ValidatorParticipation), arg0, arg1)
|
||||
}
|
||||
|
||||
// ValidatorPerformance mocks base method.
|
||||
func (m *MockChainClient) ValidatorPerformance(arg0 context.Context, arg1 *eth.ValidatorPerformanceRequest) (*eth.ValidatorPerformanceResponse, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ValidatorPerformance", arg0, arg1)
|
||||
ret0, _ := ret[0].(*eth.ValidatorPerformanceResponse)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// ValidatorPerformance indicates an expected call of ValidatorPerformance.
|
||||
func (mr *MockChainClientMockRecorder) ValidatorPerformance(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidatorPerformance", reflect.TypeOf((*MockChainClient)(nil).ValidatorPerformance), arg0, arg1)
|
||||
}
|
||||
|
||||
// ValidatorQueue mocks base method.
|
||||
func (m *MockChainClient) ValidatorQueue(arg0 context.Context, arg1 *emptypb.Empty) (*eth.ValidatorQueue, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ValidatorQueue", arg0, arg1)
|
||||
ret0, _ := ret[0].(*eth.ValidatorQueue)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// ValidatorQueue indicates an expected call of ValidatorQueue.
|
||||
func (mr *MockChainClientMockRecorder) ValidatorQueue(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidatorQueue", reflect.TypeOf((*MockChainClient)(nil).ValidatorQueue), arg0, arg1)
|
||||
}
|
||||
|
||||
// Validators mocks base method.
|
||||
func (m *MockChainClient) Validators(arg0 context.Context, arg1 *eth.ListValidatorsRequest) (*eth.Validators, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Validators", arg0, arg1)
|
||||
ret0, _ := ret[0].(*eth.Validators)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Validators indicates an expected call of Validators.
|
||||
func (mr *MockChainClientMockRecorder) Validators(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Validators", reflect.TypeOf((*MockChainClient)(nil).Validators), arg0, arg1)
|
||||
}
|
||||
102
api/client/beacon/mock/duties_mock.go
generated
Normal file
102
api/client/beacon/mock/duties_mock.go
generated
Normal file
@@ -0,0 +1,102 @@
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: validator/client/beacon-api/duties.go
|
||||
//
|
||||
// Generated by this command:
|
||||
//
|
||||
// mockgen -package=mock -source=validator/client/beacon-api/duties.go -destination=validator/client/beacon-api/mock/duties_mock.go
|
||||
//
|
||||
|
||||
// Package mock is a generated GoMock package.
|
||||
package mock
|
||||
|
||||
import (
|
||||
context "context"
|
||||
reflect "reflect"
|
||||
|
||||
structs "github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
primitives "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
// MockdutiesProvider is a mock of dutiesProvider interface.
|
||||
type MockdutiesProvider struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockdutiesProviderMockRecorder
|
||||
}
|
||||
|
||||
// MockdutiesProviderMockRecorder is the mock recorder for MockdutiesProvider.
|
||||
type MockdutiesProviderMockRecorder struct {
|
||||
mock *MockdutiesProvider
|
||||
}
|
||||
|
||||
// NewMockdutiesProvider creates a new mock instance.
|
||||
func NewMockdutiesProvider(ctrl *gomock.Controller) *MockdutiesProvider {
|
||||
mock := &MockdutiesProvider{ctrl: ctrl}
|
||||
mock.recorder = &MockdutiesProviderMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockdutiesProvider) EXPECT() *MockdutiesProviderMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// AttesterDuties mocks base method.
|
||||
func (m *MockdutiesProvider) AttesterDuties(ctx context.Context, epoch primitives.Epoch, validatorIndices []primitives.ValidatorIndex) ([]*structs.AttesterDuty, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "AttesterDuties", ctx, epoch, validatorIndices)
|
||||
ret0, _ := ret[0].([]*structs.AttesterDuty)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// AttesterDuties indicates an expected call of AttesterDuties.
|
||||
func (mr *MockdutiesProviderMockRecorder) AttesterDuties(ctx, epoch, validatorIndices any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AttesterDuties", reflect.TypeOf((*MockdutiesProvider)(nil).AttesterDuties), ctx, epoch, validatorIndices)
|
||||
}
|
||||
|
||||
// Committees mocks base method.
|
||||
func (m *MockdutiesProvider) Committees(ctx context.Context, epoch primitives.Epoch) ([]*structs.Committee, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Committees", ctx, epoch)
|
||||
ret0, _ := ret[0].([]*structs.Committee)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Committees indicates an expected call of Committees.
|
||||
func (mr *MockdutiesProviderMockRecorder) Committees(ctx, epoch any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Committees", reflect.TypeOf((*MockdutiesProvider)(nil).Committees), ctx, epoch)
|
||||
}
|
||||
|
||||
// ProposerDuties mocks base method.
|
||||
func (m *MockdutiesProvider) ProposerDuties(ctx context.Context, epoch primitives.Epoch) ([]*structs.ProposerDuty, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ProposerDuties", ctx, epoch)
|
||||
ret0, _ := ret[0].([]*structs.ProposerDuty)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// ProposerDuties indicates an expected call of ProposerDuties.
|
||||
func (mr *MockdutiesProviderMockRecorder) ProposerDuties(ctx, epoch any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProposerDuties", reflect.TypeOf((*MockdutiesProvider)(nil).ProposerDuties), ctx, epoch)
|
||||
}
|
||||
|
||||
// SyncDuties mocks base method.
|
||||
func (m *MockdutiesProvider) SyncDuties(ctx context.Context, epoch primitives.Epoch, validatorIndices []primitives.ValidatorIndex) ([]*structs.SyncCommitteeDuty, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SyncDuties", ctx, epoch, validatorIndices)
|
||||
ret0, _ := ret[0].([]*structs.SyncCommitteeDuty)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// SyncDuties indicates an expected call of SyncDuties.
|
||||
func (mr *MockdutiesProviderMockRecorder) SyncDuties(ctx, epoch, validatorIndices any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SyncDuties", reflect.TypeOf((*MockdutiesProvider)(nil).SyncDuties), ctx, epoch, validatorIndices)
|
||||
}
|
||||
@@ -40,17 +40,17 @@ func (m *MockGenesisProvider) EXPECT() *MockGenesisProviderMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// GetGenesis mocks base method.
|
||||
func (m *MockGenesisProvider) GetGenesis(ctx context.Context) (*structs.Genesis, error) {
|
||||
// Genesis mocks base method.
|
||||
func (m *MockGenesisProvider) Genesis(ctx context.Context) (*structs.Genesis, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetGenesis", ctx)
|
||||
ret := m.ctrl.Call(m, "Genesis", ctx)
|
||||
ret0, _ := ret[0].(*structs.Genesis)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetGenesis indicates an expected call of GetGenesis.
|
||||
func (mr *MockGenesisProviderMockRecorder) GetGenesis(ctx any) *gomock.Call {
|
||||
// Genesis indicates an expected call of Genesis.
|
||||
func (mr *MockGenesisProviderMockRecorder) Genesis(ctx any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetGenesis", reflect.TypeOf((*MockGenesisProvider)(nil).GetGenesis), ctx)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Genesis", reflect.TypeOf((*MockGenesisProvider)(nil).Genesis), ctx)
|
||||
}
|
||||
@@ -12,7 +12,7 @@ package mock
|
||||
import (
|
||||
bytes "bytes"
|
||||
context "context"
|
||||
"net/http"
|
||||
http "net/http"
|
||||
reflect "reflect"
|
||||
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
@@ -36,14 +36,6 @@ func NewMockJsonRestHandler(ctrl *gomock.Controller) *MockJsonRestHandler {
|
||||
return mock
|
||||
}
|
||||
|
||||
func (mr *MockJsonRestHandler) HttpClient() *http.Client {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mr *MockJsonRestHandler) Host() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockJsonRestHandler) EXPECT() *MockJsonRestHandlerMockRecorder {
|
||||
return m.recorder
|
||||
@@ -63,6 +55,34 @@ func (mr *MockJsonRestHandlerMockRecorder) Get(ctx, endpoint, resp any) *gomock.
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockJsonRestHandler)(nil).Get), ctx, endpoint, resp)
|
||||
}
|
||||
|
||||
// Host mocks base method.
|
||||
func (m *MockJsonRestHandler) Host() string {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Host")
|
||||
ret0, _ := ret[0].(string)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Host indicates an expected call of Host.
|
||||
func (mr *MockJsonRestHandlerMockRecorder) Host() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Host", reflect.TypeOf((*MockJsonRestHandler)(nil).Host))
|
||||
}
|
||||
|
||||
// HttpClient mocks base method.
|
||||
func (m *MockJsonRestHandler) HttpClient() *http.Client {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "HttpClient")
|
||||
ret0, _ := ret[0].(*http.Client)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// HttpClient indicates an expected call of HttpClient.
|
||||
func (mr *MockJsonRestHandlerMockRecorder) HttpClient() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HttpClient", reflect.TypeOf((*MockJsonRestHandler)(nil).HttpClient))
|
||||
}
|
||||
|
||||
// Post mocks base method.
|
||||
func (m *MockJsonRestHandler) Post(ctx context.Context, endpoint string, headers map[string]string, data *bytes.Buffer, resp any) error {
|
||||
m.ctrl.T.Helper()
|
||||
@@ -77,3 +97,14 @@ func (mr *MockJsonRestHandlerMockRecorder) Post(ctx, endpoint, headers, data, re
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Post", reflect.TypeOf((*MockJsonRestHandler)(nil).Post), ctx, endpoint, headers, data, resp)
|
||||
}
|
||||
|
||||
// SetHost mocks base method.
|
||||
func (m *MockJsonRestHandler) SetHost(host string) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "SetHost", host)
|
||||
}
|
||||
|
||||
// SetHost indicates an expected call of SetHost.
|
||||
func (mr *MockJsonRestHandlerMockRecorder) SetHost(host any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetHost", reflect.TypeOf((*MockJsonRestHandler)(nil).SetHost), host)
|
||||
}
|
||||
115
api/client/beacon/mock/node_client_mock.go
generated
Normal file
115
api/client/beacon/mock/node_client_mock.go
generated
Normal file
@@ -0,0 +1,115 @@
|
||||
//
|
||||
// Generated by this command:
|
||||
//
|
||||
// mockgen -package=validator_mock -destination=testing/validator-mock/node_client_mock.go github.com/prysmaticlabs/prysm/v5/validator/client/iface NodeClient
|
||||
//
|
||||
|
||||
// Package validator_mock is a generated GoMock package.
|
||||
package mock
|
||||
|
||||
import (
|
||||
context "context"
|
||||
reflect "reflect"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/health"
|
||||
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
emptypb "google.golang.org/protobuf/types/known/emptypb"
|
||||
)
|
||||
|
||||
// MockNodeClient is a mock of NodeClient interface.
|
||||
type MockNodeClient struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockNodeClientMockRecorder
|
||||
}
|
||||
|
||||
// MockNodeClientMockRecorder is the mock recorder for MockNodeClient.
|
||||
type MockNodeClientMockRecorder struct {
|
||||
mock *MockNodeClient
|
||||
}
|
||||
|
||||
// NewMockNodeClient creates a new mock instance.
|
||||
func NewMockNodeClient(ctrl *gomock.Controller) *MockNodeClient {
|
||||
mock := &MockNodeClient{ctrl: ctrl}
|
||||
mock.recorder = &MockNodeClientMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockNodeClient) EXPECT() *MockNodeClientMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// Genesis mocks base method.
|
||||
func (m *MockNodeClient) Genesis(arg0 context.Context, arg1 *emptypb.Empty) (*eth.Genesis, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Genesis", arg0, arg1)
|
||||
ret0, _ := ret[0].(*eth.Genesis)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Genesis indicates an expected call of Genesis.
|
||||
func (mr *MockNodeClientMockRecorder) Genesis(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Genesis", reflect.TypeOf((*MockNodeClient)(nil).Genesis), arg0, arg1)
|
||||
}
|
||||
|
||||
// HealthTracker mocks base method.
|
||||
func (m *MockNodeClient) HealthTracker() health.HealthTracker {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "HealthTracker")
|
||||
ret0, _ := ret[0].(health.HealthTracker)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// HealthTracker indicates an expected call of HealthTracker.
|
||||
func (mr *MockNodeClientMockRecorder) HealthTracker() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HealthTracker", reflect.TypeOf((*MockNodeClient)(nil).HealthTracker))
|
||||
}
|
||||
|
||||
// Peers mocks base method.
|
||||
func (m *MockNodeClient) Peers(arg0 context.Context, arg1 *emptypb.Empty) (*eth.Peers, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Peers", arg0, arg1)
|
||||
ret0, _ := ret[0].(*eth.Peers)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Peers indicates an expected call of Peers.
|
||||
func (mr *MockNodeClientMockRecorder) Peers(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Peers", reflect.TypeOf((*MockNodeClient)(nil).Peers), arg0, arg1)
|
||||
}
|
||||
|
||||
// SyncStatus mocks base method.
|
||||
func (m *MockNodeClient) SyncStatus(arg0 context.Context, arg1 *emptypb.Empty) (*eth.SyncStatus, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SyncStatus", arg0, arg1)
|
||||
ret0, _ := ret[0].(*eth.SyncStatus)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// SyncStatus indicates an expected call of SyncStatus.
|
||||
func (mr *MockNodeClientMockRecorder) SyncStatus(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SyncStatus", reflect.TypeOf((*MockNodeClient)(nil).SyncStatus), arg0, arg1)
|
||||
}
|
||||
|
||||
// Version mocks base method.
|
||||
func (m *MockNodeClient) Version(arg0 context.Context, arg1 *emptypb.Empty) (*eth.Version, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Version", arg0, arg1)
|
||||
ret0, _ := ret[0].(*eth.Version)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Version indicates an expected call of Version.
|
||||
func (mr *MockNodeClientMockRecorder) Version(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Version", reflect.TypeOf((*MockNodeClient)(nil).Version), arg0, arg1)
|
||||
}
|
||||
73
api/client/beacon/mock/prysm_chain_client_mock.go
generated
Normal file
73
api/client/beacon/mock/prysm_chain_client_mock.go
generated
Normal file
@@ -0,0 +1,73 @@
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: github.com/prysmaticlabs/prysm/v5/validator/client/iface (interfaces: PrysmChainClient)
|
||||
//
|
||||
// Generated by this command:
|
||||
//
|
||||
// mockgen -package=validator_mock -destination=testing/validator-mock/prysm_chain_client_mock.go github.com/prysmaticlabs/prysm/v5/validator/client/iface PrysmChainClient
|
||||
//
|
||||
|
||||
// Package validator_mock is a generated GoMock package.
|
||||
package mock
|
||||
|
||||
import (
|
||||
context "context"
|
||||
reflect "reflect"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon"
|
||||
validator "github.com/prysmaticlabs/prysm/v5/consensus-types/validator"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
// MockPrysmChainClient is a mock of PrysmChainClient interface.
|
||||
type MockPrysmChainClient struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockPrysmChainClientMockRecorder
|
||||
}
|
||||
|
||||
// MockPrysmChainClientMockRecorder is the mock recorder for MockPrysmChainClient.
|
||||
type MockPrysmChainClientMockRecorder struct {
|
||||
mock *MockPrysmChainClient
|
||||
}
|
||||
|
||||
// NewMockPrysmChainClient creates a new mock instance.
|
||||
func NewMockPrysmChainClient(ctrl *gomock.Controller) *MockPrysmChainClient {
|
||||
mock := &MockPrysmChainClient{ctrl: ctrl}
|
||||
mock.recorder = &MockPrysmChainClientMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockPrysmChainClient) EXPECT() *MockPrysmChainClientMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// ValidatorCount mocks base method.
|
||||
func (m *MockPrysmChainClient) ValidatorCount(arg0 context.Context, arg1 string, arg2 []validator.Status) ([]beacon.ValidatorCount, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ValidatorCount", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].([]beacon.ValidatorCount)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// ValidatorCount indicates an expected call of ValidatorCount.
|
||||
func (mr *MockPrysmChainClientMockRecorder) ValidatorCount(arg0, arg1, arg2 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidatorCount", reflect.TypeOf((*MockPrysmChainClient)(nil).ValidatorCount), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// ValidatorPerformance mocks base method.
|
||||
func (m *MockPrysmChainClient) ValidatorPerformance(arg0 context.Context, arg1 *ethpb.ValidatorPerformanceRequest) (*ethpb.ValidatorPerformanceResponse, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ValidatorPerformance", arg0, arg1)
|
||||
ret0, _ := ret[0].(*ethpb.ValidatorPerformanceResponse)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// ValidatorPerformance indicates an expected call of ValidatorPerformance.
|
||||
func (mr *MockPrysmChainClientMockRecorder) ValidatorPerformance(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidatorCount", reflect.TypeOf((*MockPrysmChainClient)(nil).ValidatorPerformance), arg0, arg1)
|
||||
}
|
||||
87
api/client/beacon/mock/state_validators_mock.go
generated
Normal file
87
api/client/beacon/mock/state_validators_mock.go
generated
Normal file
@@ -0,0 +1,87 @@
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: validator/client/beacon-api/state_validators.go
|
||||
//
|
||||
// Generated by this command:
|
||||
//
|
||||
// mockgen -package=mock -source=validator/client/beacon-api/state_validators.go -destination=validator/client/beacon-api/mock/state_validators_mock.go
|
||||
//
|
||||
|
||||
// Package mock is a generated GoMock package.
|
||||
package mock
|
||||
|
||||
import (
|
||||
context "context"
|
||||
reflect "reflect"
|
||||
|
||||
structs "github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
primitives "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
// MockStateValidatorsProvider is a mock of StateValidatorsProvider interface.
|
||||
type MockStateValidatorsProvider struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockStateValidatorsProviderMockRecorder
|
||||
}
|
||||
|
||||
// MockStateValidatorsProviderMockRecorder is the mock recorder for MockStateValidatorsProvider.
|
||||
type MockStateValidatorsProviderMockRecorder struct {
|
||||
mock *MockStateValidatorsProvider
|
||||
}
|
||||
|
||||
// NewMockStateValidatorsProvider creates a new mock instance.
|
||||
func NewMockStateValidatorsProvider(ctrl *gomock.Controller) *MockStateValidatorsProvider {
|
||||
mock := &MockStateValidatorsProvider{ctrl: ctrl}
|
||||
mock.recorder = &MockStateValidatorsProviderMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockStateValidatorsProvider) EXPECT() *MockStateValidatorsProviderMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// StateValidators mocks base method.
|
||||
func (m *MockStateValidatorsProvider) StateValidators(arg0 context.Context, arg1 []string, arg2 []primitives.ValidatorIndex, arg3 []string) (*structs.GetValidatorsResponse, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "StateValidators", arg0, arg1, arg2, arg3)
|
||||
ret0, _ := ret[0].(*structs.GetValidatorsResponse)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// StateValidators indicates an expected call of StateValidators.
|
||||
func (mr *MockStateValidatorsProviderMockRecorder) StateValidators(arg0, arg1, arg2, arg3 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateValidators", reflect.TypeOf((*MockStateValidatorsProvider)(nil).StateValidators), arg0, arg1, arg2, arg3)
|
||||
}
|
||||
|
||||
// StateValidatorsForHead mocks base method.
|
||||
func (m *MockStateValidatorsProvider) StateValidatorsForHead(arg0 context.Context, arg1 []string, arg2 []primitives.ValidatorIndex, arg3 []string) (*structs.GetValidatorsResponse, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "StateValidatorsForHead", arg0, arg1, arg2, arg3)
|
||||
ret0, _ := ret[0].(*structs.GetValidatorsResponse)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// StateValidatorsForHead indicates an expected call of StateValidatorsForHead.
|
||||
func (mr *MockStateValidatorsProviderMockRecorder) StateValidatorsForHead(arg0, arg1, arg2, arg3 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateValidatorsForHead", reflect.TypeOf((*MockStateValidatorsProvider)(nil).StateValidatorsForHead), arg0, arg1, arg2, arg3)
|
||||
}
|
||||
|
||||
// StateValidatorsForSlot mocks base method.
|
||||
func (m *MockStateValidatorsProvider) StateValidatorsForSlot(arg0 context.Context, arg1 primitives.Slot, arg2 []string, arg3 []primitives.ValidatorIndex, arg4 []string) (*structs.GetValidatorsResponse, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "StateValidatorsForSlot", arg0, arg1, arg2, arg3, arg4)
|
||||
ret0, _ := ret[0].(*structs.GetValidatorsResponse)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// StateValidatorsForSlot indicates an expected call of StateValidatorsForSlot.
|
||||
func (mr *MockStateValidatorsProviderMockRecorder) StateValidatorsForSlot(arg0, arg1, arg2, arg3, arg4 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateValidatorsForSlot", reflect.TypeOf((*MockStateValidatorsProvider)(nil).StateValidatorsForSlot), arg0, arg1, arg2, arg3, arg4)
|
||||
}
|
||||
@@ -7,16 +7,16 @@
|
||||
//
|
||||
|
||||
// Package validator_mock is a generated GoMock package.
|
||||
package validator_mock
|
||||
package mock
|
||||
|
||||
import (
|
||||
context "context"
|
||||
reflect "reflect"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon"
|
||||
event "github.com/prysmaticlabs/prysm/v5/api/client/event"
|
||||
primitives "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
iface "github.com/prysmaticlabs/prysm/v5/validator/client/iface"
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
emptypb "google.golang.org/protobuf/types/known/emptypb"
|
||||
)
|
||||
@@ -44,6 +44,66 @@ func (m *MockValidatorClient) EXPECT() *MockValidatorClientMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// AggregatedSelections mocks base method.
|
||||
func (m *MockValidatorClient) AggregatedSelections(arg0 context.Context, arg1 []beacon.BeaconCommitteeSelection) ([]beacon.BeaconCommitteeSelection, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "AggregatedSelections", arg0, arg1)
|
||||
ret0, _ := ret[0].([]beacon.BeaconCommitteeSelection)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// AggregatedSelections indicates an expected call of AggregatedSelections.
|
||||
func (mr *MockValidatorClientMockRecorder) AggregatedSelections(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AggregatedSelections", reflect.TypeOf((*MockValidatorClient)(nil).AggregatedSelections), arg0, arg1)
|
||||
}
|
||||
|
||||
// AggregatedSyncSelections mocks base method.
|
||||
func (m *MockValidatorClient) AggregatedSyncSelections(arg0 context.Context, arg1 []beacon.SyncCommitteeSelection) ([]beacon.SyncCommitteeSelection, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "AggregatedSyncSelections", arg0, arg1)
|
||||
ret0, _ := ret[0].([]beacon.SyncCommitteeSelection)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// AggregatedSyncSelections indicates an expected call of AggregatedSyncSelections.
|
||||
func (mr *MockValidatorClientMockRecorder) AggregatedSyncSelections(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AggregatedSyncSelections", reflect.TypeOf((*MockValidatorClient)(nil).AggregatedSyncSelections), arg0, arg1)
|
||||
}
|
||||
|
||||
// AttestationData mocks base method.
|
||||
func (m *MockValidatorClient) AttestationData(arg0 context.Context, arg1 *eth.AttestationDataRequest) (*eth.AttestationData, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "AttestationData", arg0, arg1)
|
||||
ret0, _ := ret[0].(*eth.AttestationData)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// AttestationData indicates an expected call of AttestationData.
|
||||
func (mr *MockValidatorClientMockRecorder) AttestationData(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AttestationData", reflect.TypeOf((*MockValidatorClient)(nil).AttestationData), arg0, arg1)
|
||||
}
|
||||
|
||||
// BeaconBlock mocks base method.
|
||||
func (m *MockValidatorClient) BeaconBlock(arg0 context.Context, arg1 *eth.BlockRequest) (*eth.GenericBeaconBlock, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "BeaconBlock", arg0, arg1)
|
||||
ret0, _ := ret[0].(*eth.GenericBeaconBlock)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// BeaconBlock indicates an expected call of BeaconBlock.
|
||||
func (mr *MockValidatorClientMockRecorder) BeaconBlock(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BeaconBlock", reflect.TypeOf((*MockValidatorClient)(nil).BeaconBlock), arg0, arg1)
|
||||
}
|
||||
|
||||
// CheckDoppelGanger mocks base method.
|
||||
func (m *MockValidatorClient) CheckDoppelGanger(arg0 context.Context, arg1 *eth.DoppelGangerRequest) (*eth.DoppelGangerResponse, error) {
|
||||
m.ctrl.T.Helper()
|
||||
@@ -74,6 +134,21 @@ func (mr *MockValidatorClientMockRecorder) DomainData(arg0, arg1 any) *gomock.Ca
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DomainData", reflect.TypeOf((*MockValidatorClient)(nil).DomainData), arg0, arg1)
|
||||
}
|
||||
|
||||
// Duties mocks base method.
|
||||
func (m *MockValidatorClient) Duties(arg0 context.Context, arg1 *eth.DutiesRequest) (*eth.ValidatorDutiesContainer, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Duties", arg0, arg1)
|
||||
ret0, _ := ret[0].(*eth.ValidatorDutiesContainer)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Duties indicates an expected call of Duties.
|
||||
func (mr *MockValidatorClientMockRecorder) Duties(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Duties", reflect.TypeOf((*MockValidatorClient)(nil).Duties), arg0, arg1)
|
||||
}
|
||||
|
||||
// EventStreamIsRunning mocks base method.
|
||||
func (m *MockValidatorClient) EventStreamIsRunning() bool {
|
||||
m.ctrl.T.Helper()
|
||||
@@ -88,139 +163,33 @@ func (mr *MockValidatorClientMockRecorder) EventStreamIsRunning() *gomock.Call {
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EventStreamIsRunning", reflect.TypeOf((*MockValidatorClient)(nil).EventStreamIsRunning))
|
||||
}
|
||||
|
||||
// GetAggregatedSelections mocks base method.
|
||||
func (m *MockValidatorClient) GetAggregatedSelections(arg0 context.Context, arg1 []iface.BeaconCommitteeSelection) ([]iface.BeaconCommitteeSelection, error) {
|
||||
// FeeRecipientByPubKey mocks base method.
|
||||
func (m *MockValidatorClient) FeeRecipientByPubKey(arg0 context.Context, arg1 *eth.FeeRecipientByPubKeyRequest) (*eth.FeeRecipientByPubKeyResponse, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetAggregatedSelections", arg0, arg1)
|
||||
ret0, _ := ret[0].([]iface.BeaconCommitteeSelection)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetAggregatedSelections indicates an expected call of GetAggregatedSelections.
|
||||
func (mr *MockValidatorClientMockRecorder) GetAggregatedSelections(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAggregatedSelections", reflect.TypeOf((*MockValidatorClient)(nil).GetAggregatedSelections), arg0, arg1)
|
||||
}
|
||||
|
||||
// GetAggregatedSyncSelections mocks base method.
|
||||
func (m *MockValidatorClient) GetAggregatedSyncSelections(arg0 context.Context, arg1 []iface.SyncCommitteeSelection) ([]iface.SyncCommitteeSelection, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetAggregatedSyncSelections", arg0, arg1)
|
||||
ret0, _ := ret[0].([]iface.SyncCommitteeSelection)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetAggregatedSyncSelections indicates an expected call of GetAggregatedSyncSelections.
|
||||
func (mr *MockValidatorClientMockRecorder) GetAggregatedSyncSelections(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAggregatedSyncSelections", reflect.TypeOf((*MockValidatorClient)(nil).GetAggregatedSyncSelections), arg0, arg1)
|
||||
}
|
||||
|
||||
// GetAttestationData mocks base method.
|
||||
func (m *MockValidatorClient) GetAttestationData(arg0 context.Context, arg1 *eth.AttestationDataRequest) (*eth.AttestationData, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetAttestationData", arg0, arg1)
|
||||
ret0, _ := ret[0].(*eth.AttestationData)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetAttestationData indicates an expected call of GetAttestationData.
|
||||
func (mr *MockValidatorClientMockRecorder) GetAttestationData(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAttestationData", reflect.TypeOf((*MockValidatorClient)(nil).GetAttestationData), arg0, arg1)
|
||||
}
|
||||
|
||||
// GetBeaconBlock mocks base method.
|
||||
func (m *MockValidatorClient) GetBeaconBlock(arg0 context.Context, arg1 *eth.BlockRequest) (*eth.GenericBeaconBlock, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetBeaconBlock", arg0, arg1)
|
||||
ret0, _ := ret[0].(*eth.GenericBeaconBlock)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetBeaconBlock indicates an expected call of GetBeaconBlock.
|
||||
func (mr *MockValidatorClientMockRecorder) GetBeaconBlock(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBeaconBlock", reflect.TypeOf((*MockValidatorClient)(nil).GetBeaconBlock), arg0, arg1)
|
||||
}
|
||||
|
||||
// GetDuties mocks base method.
|
||||
func (m *MockValidatorClient) GetDuties(arg0 context.Context, arg1 *eth.DutiesRequest) (*eth.DutiesResponse, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetDuties", arg0, arg1)
|
||||
ret0, _ := ret[0].(*eth.DutiesResponse)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetDuties indicates an expected call of GetDuties.
|
||||
func (mr *MockValidatorClientMockRecorder) GetDuties(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDuties", reflect.TypeOf((*MockValidatorClient)(nil).GetDuties), arg0, arg1)
|
||||
}
|
||||
|
||||
// GetFeeRecipientByPubKey mocks base method.
|
||||
func (m *MockValidatorClient) GetFeeRecipientByPubKey(arg0 context.Context, arg1 *eth.FeeRecipientByPubKeyRequest) (*eth.FeeRecipientByPubKeyResponse, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetFeeRecipientByPubKey", arg0, arg1)
|
||||
ret := m.ctrl.Call(m, "FeeRecipientByPubKey", arg0, arg1)
|
||||
ret0, _ := ret[0].(*eth.FeeRecipientByPubKeyResponse)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetFeeRecipientByPubKey indicates an expected call of GetFeeRecipientByPubKey.
|
||||
func (mr *MockValidatorClientMockRecorder) GetFeeRecipientByPubKey(arg0, arg1 any) *gomock.Call {
|
||||
// FeeRecipientByPubKey indicates an expected call of FeeRecipientByPubKey.
|
||||
func (mr *MockValidatorClientMockRecorder) FeeRecipientByPubKey(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetFeeRecipientByPubKey", reflect.TypeOf((*MockValidatorClient)(nil).GetFeeRecipientByPubKey), arg0, arg1)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FeeRecipientByPubKey", reflect.TypeOf((*MockValidatorClient)(nil).FeeRecipientByPubKey), arg0, arg1)
|
||||
}
|
||||
|
||||
// GetSyncCommitteeContribution mocks base method.
|
||||
func (m *MockValidatorClient) GetSyncCommitteeContribution(arg0 context.Context, arg1 *eth.SyncCommitteeContributionRequest) (*eth.SyncCommitteeContribution, error) {
|
||||
// Host mocks base method.
|
||||
func (m *MockValidatorClient) Host() string {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetSyncCommitteeContribution", arg0, arg1)
|
||||
ret0, _ := ret[0].(*eth.SyncCommitteeContribution)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
ret := m.ctrl.Call(m, "Host")
|
||||
ret0, _ := ret[0].(string)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetSyncCommitteeContribution indicates an expected call of GetSyncCommitteeContribution.
|
||||
func (mr *MockValidatorClientMockRecorder) GetSyncCommitteeContribution(arg0, arg1 any) *gomock.Call {
|
||||
// Host indicates an expected call of Host.
|
||||
func (mr *MockValidatorClientMockRecorder) Host() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSyncCommitteeContribution", reflect.TypeOf((*MockValidatorClient)(nil).GetSyncCommitteeContribution), arg0, arg1)
|
||||
}
|
||||
|
||||
// GetSyncMessageBlockRoot mocks base method.
|
||||
func (m *MockValidatorClient) GetSyncMessageBlockRoot(arg0 context.Context, arg1 *emptypb.Empty) (*eth.SyncMessageBlockRootResponse, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetSyncMessageBlockRoot", arg0, arg1)
|
||||
ret0, _ := ret[0].(*eth.SyncMessageBlockRootResponse)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetSyncMessageBlockRoot indicates an expected call of GetSyncMessageBlockRoot.
|
||||
func (mr *MockValidatorClientMockRecorder) GetSyncMessageBlockRoot(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSyncMessageBlockRoot", reflect.TypeOf((*MockValidatorClient)(nil).GetSyncMessageBlockRoot), arg0, arg1)
|
||||
}
|
||||
|
||||
// GetSyncSubcommitteeIndex mocks base method.
|
||||
func (m *MockValidatorClient) GetSyncSubcommitteeIndex(arg0 context.Context, arg1 *eth.SyncSubcommitteeIndexRequest) (*eth.SyncSubcommitteeIndexResponse, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetSyncSubcommitteeIndex", arg0, arg1)
|
||||
ret0, _ := ret[0].(*eth.SyncSubcommitteeIndexResponse)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetSyncSubcommitteeIndex indicates an expected call of GetSyncSubcommitteeIndex.
|
||||
func (mr *MockValidatorClientMockRecorder) GetSyncSubcommitteeIndex(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSyncSubcommitteeIndex", reflect.TypeOf((*MockValidatorClient)(nil).GetSyncSubcommitteeIndex), arg0, arg1)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Host", reflect.TypeOf((*MockValidatorClient)(nil).Host))
|
||||
}
|
||||
|
||||
// MultipleValidatorStatus mocks base method.
|
||||
@@ -268,6 +237,21 @@ func (mr *MockValidatorClientMockRecorder) ProposeAttestation(arg0, arg1 any) *g
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProposeAttestation", reflect.TypeOf((*MockValidatorClient)(nil).ProposeAttestation), arg0, arg1)
|
||||
}
|
||||
|
||||
// ProposeAttestationElectra mocks base method.
|
||||
func (m *MockValidatorClient) ProposeAttestationElectra(arg0 context.Context, arg1 *eth.SingleAttestation) (*eth.AttestResponse, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ProposeAttestationElectra", arg0, arg1)
|
||||
ret0, _ := ret[0].(*eth.AttestResponse)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// ProposeAttestationElectra indicates an expected call of ProposeAttestationElectra.
|
||||
func (mr *MockValidatorClientMockRecorder) ProposeAttestationElectra(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProposeAttestationElectra", reflect.TypeOf((*MockValidatorClient)(nil).ProposeAttestationElectra), arg0, arg1)
|
||||
}
|
||||
|
||||
// ProposeBeaconBlock mocks base method.
|
||||
func (m *MockValidatorClient) ProposeBeaconBlock(arg0 context.Context, arg1 *eth.GenericSignedBeaconBlock) (*eth.ProposeResponse, error) {
|
||||
m.ctrl.T.Helper()
|
||||
@@ -298,6 +282,18 @@ func (mr *MockValidatorClientMockRecorder) ProposeExit(arg0, arg1 any) *gomock.C
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProposeExit", reflect.TypeOf((*MockValidatorClient)(nil).ProposeExit), arg0, arg1)
|
||||
}
|
||||
|
||||
// SetHost mocks base method.
|
||||
func (m *MockValidatorClient) SetHost(arg0 string) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "SetHost", arg0)
|
||||
}
|
||||
|
||||
// SetHost indicates an expected call of SetHost.
|
||||
func (mr *MockValidatorClientMockRecorder) SetHost(arg0 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetHost", reflect.TypeOf((*MockValidatorClient)(nil).SetHost), arg0)
|
||||
}
|
||||
|
||||
// StartEventStream mocks base method.
|
||||
func (m *MockValidatorClient) StartEventStream(arg0 context.Context, arg1 []string, arg2 chan<- *event.Event) {
|
||||
m.ctrl.T.Helper()
|
||||
@@ -325,6 +321,21 @@ func (mr *MockValidatorClientMockRecorder) SubmitAggregateSelectionProof(arg0, a
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitAggregateSelectionProof", reflect.TypeOf((*MockValidatorClient)(nil).SubmitAggregateSelectionProof), arg0, arg1, arg2, arg3)
|
||||
}
|
||||
|
||||
// SubmitAggregateSelectionProofElectra mocks base method.
|
||||
func (m *MockValidatorClient) SubmitAggregateSelectionProofElectra(arg0 context.Context, arg1 *eth.AggregateSelectionRequest, arg2 primitives.ValidatorIndex, arg3 uint64) (*eth.AggregateSelectionElectraResponse, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SubmitAggregateSelectionProofElectra", arg0, arg1, arg2, arg3)
|
||||
ret0, _ := ret[0].(*eth.AggregateSelectionElectraResponse)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// SubmitAggregateSelectionProofElectra indicates an expected call of SubmitAggregateSelectionProofElectra.
|
||||
func (mr *MockValidatorClientMockRecorder) SubmitAggregateSelectionProofElectra(arg0, arg1, arg2, arg3 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitAggregateSelectionProofElectra", reflect.TypeOf((*MockValidatorClient)(nil).SubmitAggregateSelectionProofElectra), arg0, arg1, arg2, arg3)
|
||||
}
|
||||
|
||||
// SubmitSignedAggregateSelectionProof mocks base method.
|
||||
func (m *MockValidatorClient) SubmitSignedAggregateSelectionProof(arg0 context.Context, arg1 *eth.SignedAggregateSubmitRequest) (*eth.SignedAggregateSubmitResponse, error) {
|
||||
m.ctrl.T.Helper()
|
||||
@@ -340,6 +351,21 @@ func (mr *MockValidatorClientMockRecorder) SubmitSignedAggregateSelectionProof(a
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitSignedAggregateSelectionProof", reflect.TypeOf((*MockValidatorClient)(nil).SubmitSignedAggregateSelectionProof), arg0, arg1)
|
||||
}
|
||||
|
||||
// SubmitSignedAggregateSelectionProofElectra mocks base method.
|
||||
func (m *MockValidatorClient) SubmitSignedAggregateSelectionProofElectra(arg0 context.Context, arg1 *eth.SignedAggregateSubmitElectraRequest) (*eth.SignedAggregateSubmitResponse, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SubmitSignedAggregateSelectionProofElectra", arg0, arg1)
|
||||
ret0, _ := ret[0].(*eth.SignedAggregateSubmitResponse)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// SubmitSignedAggregateSelectionProofElectra indicates an expected call of SubmitSignedAggregateSelectionProofElectra.
|
||||
func (mr *MockValidatorClientMockRecorder) SubmitSignedAggregateSelectionProofElectra(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitSignedAggregateSelectionProofElectra", reflect.TypeOf((*MockValidatorClient)(nil).SubmitSignedAggregateSelectionProofElectra), arg0, arg1)
|
||||
}
|
||||
|
||||
// SubmitSignedContributionAndProof mocks base method.
|
||||
func (m *MockValidatorClient) SubmitSignedContributionAndProof(arg0 context.Context, arg1 *eth.SignedContributionAndProof) (*emptypb.Empty, error) {
|
||||
m.ctrl.T.Helper()
|
||||
@@ -386,7 +412,7 @@ func (mr *MockValidatorClientMockRecorder) SubmitValidatorRegistrations(arg0, ar
|
||||
}
|
||||
|
||||
// SubscribeCommitteeSubnets mocks base method.
|
||||
func (m *MockValidatorClient) SubscribeCommitteeSubnets(arg0 context.Context, arg1 *eth.CommitteeSubnetsSubscribeRequest, arg2 []*eth.DutiesResponse_Duty) (*emptypb.Empty, error) {
|
||||
func (m *MockValidatorClient) SubscribeCommitteeSubnets(arg0 context.Context, arg1 *eth.CommitteeSubnetsSubscribeRequest, arg2 []*eth.ValidatorDuty) (*emptypb.Empty, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SubscribeCommitteeSubnets", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(*emptypb.Empty)
|
||||
@@ -400,6 +426,51 @@ func (mr *MockValidatorClientMockRecorder) SubscribeCommitteeSubnets(arg0, arg1,
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubscribeCommitteeSubnets", reflect.TypeOf((*MockValidatorClient)(nil).SubscribeCommitteeSubnets), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// SyncCommitteeContribution mocks base method.
|
||||
func (m *MockValidatorClient) SyncCommitteeContribution(arg0 context.Context, arg1 *eth.SyncCommitteeContributionRequest) (*eth.SyncCommitteeContribution, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SyncCommitteeContribution", arg0, arg1)
|
||||
ret0, _ := ret[0].(*eth.SyncCommitteeContribution)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// SyncCommitteeContribution indicates an expected call of SyncCommitteeContribution.
|
||||
func (mr *MockValidatorClientMockRecorder) SyncCommitteeContribution(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SyncCommitteeContribution", reflect.TypeOf((*MockValidatorClient)(nil).SyncCommitteeContribution), arg0, arg1)
|
||||
}
|
||||
|
||||
// SyncMessageBlockRoot mocks base method.
|
||||
func (m *MockValidatorClient) SyncMessageBlockRoot(arg0 context.Context, arg1 *emptypb.Empty) (*eth.SyncMessageBlockRootResponse, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SyncMessageBlockRoot", arg0, arg1)
|
||||
ret0, _ := ret[0].(*eth.SyncMessageBlockRootResponse)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// SyncMessageBlockRoot indicates an expected call of SyncMessageBlockRoot.
|
||||
func (mr *MockValidatorClientMockRecorder) SyncMessageBlockRoot(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SyncMessageBlockRoot", reflect.TypeOf((*MockValidatorClient)(nil).SyncMessageBlockRoot), arg0, arg1)
|
||||
}
|
||||
|
||||
// SyncSubcommitteeIndex mocks base method.
|
||||
func (m *MockValidatorClient) SyncSubcommitteeIndex(arg0 context.Context, arg1 *eth.SyncSubcommitteeIndexRequest) (*eth.SyncSubcommitteeIndexResponse, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SyncSubcommitteeIndex", arg0, arg1)
|
||||
ret0, _ := ret[0].(*eth.SyncSubcommitteeIndexResponse)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// SyncSubcommitteeIndex indicates an expected call of SyncSubcommitteeIndex.
|
||||
func (mr *MockValidatorClientMockRecorder) SyncSubcommitteeIndex(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SyncSubcommitteeIndex", reflect.TypeOf((*MockValidatorClient)(nil).SyncSubcommitteeIndex), arg0, arg1)
|
||||
}
|
||||
|
||||
// ValidatorIndex mocks base method.
|
||||
func (m *MockValidatorClient) ValidatorIndex(arg0 context.Context, arg1 *eth.ValidatorIndexRequest) (*eth.ValidatorIndexResponse, error) {
|
||||
m.ctrl.T.Helper()
|
||||
@@ -430,21 +501,6 @@ func (mr *MockValidatorClientMockRecorder) ValidatorStatus(arg0, arg1 any) *gomo
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidatorStatus", reflect.TypeOf((*MockValidatorClient)(nil).ValidatorStatus), arg0, arg1)
|
||||
}
|
||||
|
||||
// WaitForActivation mocks base method.
|
||||
func (m *MockValidatorClient) WaitForActivation(arg0 context.Context, arg1 *eth.ValidatorActivationRequest) (eth.BeaconNodeValidator_WaitForActivationClient, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "WaitForActivation", arg0, arg1)
|
||||
ret0, _ := ret[0].(eth.BeaconNodeValidator_WaitForActivationClient)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// WaitForActivation indicates an expected call of WaitForActivation.
|
||||
func (mr *MockValidatorClientMockRecorder) WaitForActivation(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WaitForActivation", reflect.TypeOf((*MockValidatorClient)(nil).WaitForActivation), arg0, arg1)
|
||||
}
|
||||
|
||||
// WaitForChainStart mocks base method.
|
||||
func (m *MockValidatorClient) WaitForChainStart(arg0 context.Context, arg1 *emptypb.Empty) (*eth.ChainStartResponse, error) {
|
||||
m.ctrl.T.Helper()
|
||||
44
api/client/beacon/node/BUILD.bazel
Normal file
44
api/client/beacon/node/BUILD.bazel
Normal file
@@ -0,0 +1,44 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"client.go",
|
||||
"grpc_node_client.go",
|
||||
"interfaces.go",
|
||||
"rest_client.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/api/client/beacon/node",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//api/client:go_default_library",
|
||||
"//api/client/beacon/health:go_default_library",
|
||||
"//api/client/beacon/shared_providers:go_default_library",
|
||||
"//api/server/structs:go_default_library",
|
||||
"//config/features:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//validator/helpers:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
"@com_github_golang_protobuf//ptypes/empty",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@org_golang_google_grpc//:go_default_library",
|
||||
"@org_golang_google_protobuf//types/known/timestamppb:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["rest_client_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//api/client/beacon/mock:go_default_library",
|
||||
"//api/server/structs:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
"@org_golang_google_protobuf//types/known/emptypb:go_default_library",
|
||||
"@org_golang_google_protobuf//types/known/timestamppb:go_default_library",
|
||||
"@org_uber_go_mock//gomock:go_default_library",
|
||||
],
|
||||
)
|
||||
28
api/client/beacon/node/client.go
Normal file
28
api/client/beacon/node/client.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/health"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/shared_providers"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/features"
|
||||
validatorHelpers "github.com/prysmaticlabs/prysm/v5/validator/helpers"
|
||||
)
|
||||
|
||||
func NewClient(validatorConn validatorHelpers.NodeConnection, jsonRestHandler client.JsonRestHandler) Client {
|
||||
grpcClient := NewNodeClient(validatorConn.GetGrpcClientConn())
|
||||
if features.Get().EnableBeaconRESTApi {
|
||||
return NewNodeClientWithFallback(jsonRestHandler, grpcClient)
|
||||
} else {
|
||||
return grpcClient
|
||||
}
|
||||
}
|
||||
|
||||
func NewNodeClientWithFallback(jsonRestHandler client.JsonRestHandler, fallbackClient Client) Client {
|
||||
b := &beaconapiNodeClient{
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
fallbackClient: fallbackClient,
|
||||
genesisProvider: shared_providers.NewGenesis(jsonRestHandler),
|
||||
}
|
||||
b.healthTracker = health.NewTracker(b)
|
||||
return b
|
||||
}
|
||||
55
api/client/beacon/node/grpc_node_client.go
Normal file
55
api/client/beacon/node/grpc_node_client.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/health"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
var (
|
||||
_ = Client(&grpcNodeClient{})
|
||||
)
|
||||
|
||||
type grpcNodeClient struct {
|
||||
nodeClient ethpb.NodeClient
|
||||
healthTracker health.HealthTracker
|
||||
}
|
||||
|
||||
func (c *grpcNodeClient) SyncStatus(ctx context.Context, in *empty.Empty) (*ethpb.SyncStatus, error) {
|
||||
return c.nodeClient.GetSyncStatus(ctx, in)
|
||||
}
|
||||
|
||||
func (c *grpcNodeClient) Genesis(ctx context.Context, in *empty.Empty) (*ethpb.Genesis, error) {
|
||||
return c.nodeClient.GetGenesis(ctx, in)
|
||||
}
|
||||
|
||||
func (c *grpcNodeClient) Version(ctx context.Context, in *empty.Empty) (*ethpb.Version, error) {
|
||||
return c.nodeClient.GetVersion(ctx, in)
|
||||
}
|
||||
|
||||
func (c *grpcNodeClient) Peers(ctx context.Context, in *empty.Empty) (*ethpb.Peers, error) {
|
||||
return c.nodeClient.ListPeers(ctx, in)
|
||||
}
|
||||
|
||||
func (c *grpcNodeClient) IsHealthy(ctx context.Context) bool {
|
||||
_, err := c.nodeClient.GetHealth(ctx, ðpb.HealthRequest{})
|
||||
if err != nil {
|
||||
log.WithError(err).Debug("failed to get health of node")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *grpcNodeClient) HealthTracker() health.HealthTracker {
|
||||
return c.healthTracker
|
||||
}
|
||||
|
||||
func NewNodeClient(cc grpc.ClientConnInterface) Client {
|
||||
g := &grpcNodeClient{nodeClient: ethpb.NewNodeClient(cc)}
|
||||
g.healthTracker = health.NewTracker(g)
|
||||
return g
|
||||
}
|
||||
17
api/client/beacon/node/interfaces.go
Normal file
17
api/client/beacon/node/interfaces.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/health"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
type Client interface {
|
||||
SyncStatus(ctx context.Context, in *empty.Empty) (*ethpb.SyncStatus, error)
|
||||
Genesis(ctx context.Context, in *empty.Empty) (*ethpb.Genesis, error)
|
||||
Version(ctx context.Context, in *empty.Empty) (*ethpb.Version, error)
|
||||
Peers(ctx context.Context, in *empty.Empty) (*ethpb.Peers, error)
|
||||
HealthTracker() health.HealthTracker
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package node
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -7,25 +7,26 @@ import (
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/health"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/shared_providers"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/validator/client/iface"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
|
||||
var (
|
||||
_ = iface.NodeClient(&beaconApiNodeClient{})
|
||||
_ = Client(&beaconapiNodeClient{})
|
||||
)
|
||||
|
||||
type beaconApiNodeClient struct {
|
||||
fallbackClient iface.NodeClient
|
||||
jsonRestHandler JsonRestHandler
|
||||
genesisProvider GenesisProvider
|
||||
healthTracker *beacon.NodeHealthTracker
|
||||
type beaconapiNodeClient struct {
|
||||
fallbackClient Client
|
||||
jsonRestHandler client.JsonRestHandler
|
||||
genesisProvider shared_providers.Genesis
|
||||
healthTracker health.HealthTracker
|
||||
}
|
||||
|
||||
func (c *beaconApiNodeClient) GetSyncStatus(ctx context.Context, _ *empty.Empty) (*ethpb.SyncStatus, error) {
|
||||
func (c *beaconapiNodeClient) SyncStatus(ctx context.Context, _ *empty.Empty) (*ethpb.SyncStatus, error) {
|
||||
syncingResponse := structs.SyncStatusResponse{}
|
||||
if err := c.jsonRestHandler.Get(ctx, "/eth/v1/node/syncing", &syncingResponse); err != nil {
|
||||
return nil, err
|
||||
@@ -40,8 +41,8 @@ func (c *beaconApiNodeClient) GetSyncStatus(ctx context.Context, _ *empty.Empty)
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *beaconApiNodeClient) GetGenesis(ctx context.Context, _ *empty.Empty) (*ethpb.Genesis, error) {
|
||||
genesisJson, err := c.genesisProvider.GetGenesis(ctx)
|
||||
func (c *beaconapiNodeClient) Genesis(ctx context.Context, _ *empty.Empty) (*ethpb.Genesis, error) {
|
||||
genesisJson, err := c.genesisProvider.Genesis(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get genesis")
|
||||
}
|
||||
@@ -79,7 +80,7 @@ func (c *beaconApiNodeClient) GetGenesis(ctx context.Context, _ *empty.Empty) (*
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *beaconApiNodeClient) GetVersion(ctx context.Context, _ *empty.Empty) (*ethpb.Version, error) {
|
||||
func (c *beaconapiNodeClient) Version(ctx context.Context, _ *empty.Empty) (*ethpb.Version, error) {
|
||||
var versionResponse structs.GetVersionResponse
|
||||
if err := c.jsonRestHandler.Get(ctx, "/eth/v1/node/version", &versionResponse); err != nil {
|
||||
return nil, err
|
||||
@@ -94,29 +95,19 @@ func (c *beaconApiNodeClient) GetVersion(ctx context.Context, _ *empty.Empty) (*
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *beaconApiNodeClient) ListPeers(ctx context.Context, in *empty.Empty) (*ethpb.Peers, error) {
|
||||
func (c *beaconapiNodeClient) Peers(ctx context.Context, in *empty.Empty) (*ethpb.Peers, error) {
|
||||
if c.fallbackClient != nil {
|
||||
return c.fallbackClient.ListPeers(ctx, in)
|
||||
return c.fallbackClient.Peers(ctx, in)
|
||||
}
|
||||
|
||||
// TODO: Implement me
|
||||
panic("beaconApiNodeClient.ListPeers is not implemented. To use a fallback client, pass a fallback client as the last argument of NewBeaconApiNodeClientWithFallback.")
|
||||
return nil, errors.New("beaconapiNodeClient.Peers is not implemented. To use a fallback client, pass a fallback client as the last argument of NewBeaconApiNodeClientWithFallback.")
|
||||
}
|
||||
|
||||
func (c *beaconApiNodeClient) IsHealthy(ctx context.Context) bool {
|
||||
func (c *beaconapiNodeClient) IsHealthy(ctx context.Context) bool {
|
||||
return c.jsonRestHandler.Get(ctx, "/eth/v1/node/health", nil) == nil
|
||||
}
|
||||
|
||||
func (c *beaconApiNodeClient) HealthTracker() *beacon.NodeHealthTracker {
|
||||
func (c *beaconapiNodeClient) HealthTracker() health.HealthTracker {
|
||||
return c.healthTracker
|
||||
}
|
||||
|
||||
func NewNodeClientWithFallback(jsonRestHandler JsonRestHandler, fallbackClient iface.NodeClient) iface.NodeClient {
|
||||
b := &beaconApiNodeClient{
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
fallbackClient: fallbackClient,
|
||||
genesisProvider: beaconApiGenesisProvider{jsonRestHandler: jsonRestHandler},
|
||||
}
|
||||
b.healthTracker = beacon.NewNodeHealthTracker(b)
|
||||
return b
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package node
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -6,10 +6,10 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/mock"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api/mock"
|
||||
"go.uber.org/mock/gomock"
|
||||
"google.golang.org/protobuf/types/known/emptypb"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
@@ -112,8 +112,8 @@ func TestGetGenesis(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
genesisProvider := mock.NewMockGenesisProvider(ctrl)
|
||||
genesisProvider.EXPECT().GetGenesis(
|
||||
ctx,
|
||||
genesisProvider.EXPECT().Genesis(
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
testCase.genesisResponse,
|
||||
testCase.genesisError,
|
||||
@@ -124,7 +124,7 @@ func TestGetGenesis(t *testing.T) {
|
||||
|
||||
if testCase.queriesDepositContract {
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
"/eth/v1/config/deposit_contract",
|
||||
&depositContractJson,
|
||||
).Return(
|
||||
@@ -135,11 +135,11 @@ func TestGetGenesis(t *testing.T) {
|
||||
)
|
||||
}
|
||||
|
||||
nodeClient := &beaconApiNodeClient{
|
||||
nodeClient := &beaconapiNodeClient{
|
||||
genesisProvider: genesisProvider,
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
}
|
||||
response, err := nodeClient.GetGenesis(ctx, &emptypb.Empty{})
|
||||
response, err := nodeClient.Genesis(ctx, &emptypb.Empty{})
|
||||
|
||||
if testCase.expectedResponse == nil {
|
||||
assert.ErrorContains(t, testCase.expectedError, err)
|
||||
@@ -203,7 +203,7 @@ func TestGetSyncStatus(t *testing.T) {
|
||||
syncingResponse := structs.SyncStatusResponse{}
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
syncingEndpoint,
|
||||
&syncingResponse,
|
||||
).Return(
|
||||
@@ -213,8 +213,8 @@ func TestGetSyncStatus(t *testing.T) {
|
||||
testCase.restEndpointResponse,
|
||||
)
|
||||
|
||||
nodeClient := &beaconApiNodeClient{jsonRestHandler: jsonRestHandler}
|
||||
syncStatus, err := nodeClient.GetSyncStatus(ctx, &emptypb.Empty{})
|
||||
nodeClient := &beaconapiNodeClient{jsonRestHandler: jsonRestHandler}
|
||||
syncStatus, err := nodeClient.SyncStatus(ctx, &emptypb.Empty{})
|
||||
|
||||
if testCase.expectedResponse == nil {
|
||||
assert.ErrorContains(t, testCase.expectedError, err)
|
||||
@@ -267,7 +267,7 @@ func TestGetVersion(t *testing.T) {
|
||||
var versionResponse structs.GetVersionResponse
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
versionEndpoint,
|
||||
&versionResponse,
|
||||
).Return(
|
||||
@@ -277,8 +277,8 @@ func TestGetVersion(t *testing.T) {
|
||||
testCase.restEndpointResponse,
|
||||
)
|
||||
|
||||
nodeClient := &beaconApiNodeClient{jsonRestHandler: jsonRestHandler}
|
||||
version, err := nodeClient.GetVersion(ctx, &emptypb.Empty{})
|
||||
nodeClient := &beaconapiNodeClient{jsonRestHandler: jsonRestHandler}
|
||||
version, err := nodeClient.Version(ctx, &emptypb.Empty{})
|
||||
|
||||
if testCase.expectedResponse == nil {
|
||||
assert.ErrorContains(t, testCase.expectedError, err)
|
||||
@@ -3,56 +3,53 @@ load("@prysm//tools/go:def.bzl", "go_library", "go_test")
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"grpc_beacon_chain_client.go",
|
||||
"grpc_node_client.go",
|
||||
"grpc_prysm_beacon_chain_client.go",
|
||||
"grpc_validator_client.go",
|
||||
"client.go",
|
||||
"grpc_client.go",
|
||||
"interfaces.go",
|
||||
"rest_client.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/validator/client/grpc-api",
|
||||
visibility = ["//validator:__subpackages__"],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/api/client/beacon/prysm_api",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//api/client:go_default_library",
|
||||
"//api/client/apiutil:go_default_library",
|
||||
"//api/client/beacon:go_default_library",
|
||||
"//api/client/event:go_default_library",
|
||||
"//api/client/beacon/chain:go_default_library",
|
||||
"//api/client/beacon/node:go_default_library",
|
||||
"//api/server/structs:go_default_library",
|
||||
"//beacon-chain/rpc/eth/helpers:go_default_library",
|
||||
"//beacon-chain/state/state-native:go_default_library",
|
||||
"//config/features:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//consensus-types/validator:go_default_library",
|
||||
"//proto/eth/v1:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//validator/client/iface:go_default_library",
|
||||
"//validator/helpers:go_default_library",
|
||||
"@com_github_golang_protobuf//ptypes/empty",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@io_opencensus_go//trace:go_default_library",
|
||||
"@org_golang_google_grpc//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
size = "small",
|
||||
srcs = [
|
||||
"grpc_prysm_beacon_chain_client_test.go",
|
||||
"grpc_validator_client_test.go",
|
||||
"grpc_client_test.go",
|
||||
"rest_client_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//api/client/event:go_default_library",
|
||||
"//api/client/beacon:go_default_library",
|
||||
"//api/client/beacon/mock:go_default_library",
|
||||
"//api/client/beacon/node:go_default_library",
|
||||
"//api/server/structs:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//consensus-types/validator:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/mock:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"//testing/util:go_default_library",
|
||||
"//testing/validator-mock:go_default_library",
|
||||
"//validator/client/iface:go_default_library",
|
||||
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
|
||||
"@org_golang_google_protobuf//types/known/emptypb:go_default_library",
|
||||
"@org_uber_go_mock//gomock:go_default_library",
|
||||
],
|
||||
)
|
||||
30
api/client/beacon/prysm_api/client.go
Normal file
30
api/client/beacon/prysm_api/client.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package prysm_api
|
||||
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/chain"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/node"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/features"
|
||||
validatorHelpers "github.com/prysmaticlabs/prysm/v5/validator/helpers"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
func NewClient(validatorConn validatorHelpers.NodeConnection, jsonRestHandler client.JsonRestHandler) Client {
|
||||
if features.Get().EnableBeaconRESTApi {
|
||||
return NewPrysmChainRestClient(jsonRestHandler, node.NewClient(validatorConn, jsonRestHandler))
|
||||
} else {
|
||||
return NewGrpcPrysmChainClient(validatorConn.GetGrpcClientConn())
|
||||
}
|
||||
}
|
||||
|
||||
// NewPrysmChainClient returns implementation of Client.
|
||||
func NewPrysmChainRestClient(jsonRestHandler client.JsonRestHandler, nodeClient node.Client) Client {
|
||||
return prysmChainClient{
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
nodeClient: nodeClient,
|
||||
}
|
||||
}
|
||||
|
||||
func NewGrpcPrysmChainClient(cc grpc.ClientConnInterface) Client {
|
||||
return &grpcPrysmChainClient{chainClient: chain.NewGrpcChainClient(cc)}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package grpc_api
|
||||
package prysm_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -6,24 +6,23 @@ import (
|
||||
"sort"
|
||||
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/chain"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/eth/helpers"
|
||||
statenative "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/validator"
|
||||
eth "github.com/prysmaticlabs/prysm/v5/proto/eth/v1"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/validator/client/iface"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
type grpcPrysmBeaconChainClient struct {
|
||||
beaconChainClient iface.BeaconChainClient
|
||||
type grpcPrysmChainClient struct {
|
||||
chainClient chain.Client
|
||||
}
|
||||
|
||||
func (g grpcPrysmBeaconChainClient) GetValidatorCount(ctx context.Context, _ string, statuses []validator.Status) ([]iface.ValidatorCount, error) {
|
||||
resp, err := g.beaconChainClient.ListValidators(ctx, ðpb.ListValidatorsRequest{PageSize: 0})
|
||||
func (g grpcPrysmChainClient) ValidatorCount(ctx context.Context, _ string, statuses []validator.Status) ([]beacon.ValidatorCount, error) {
|
||||
resp, err := g.chainClient.Validators(ctx, ðpb.ListValidatorsRequest{PageSize: 0})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "list validators failed")
|
||||
}
|
||||
@@ -33,7 +32,7 @@ func (g grpcPrysmBeaconChainClient) GetValidatorCount(ctx context.Context, _ str
|
||||
vals = append(vals, val.Validator)
|
||||
}
|
||||
|
||||
head, err := g.beaconChainClient.GetChainHead(ctx, &empty.Empty{})
|
||||
head, err := g.chainClient.ChainHead(ctx, &empty.Empty{})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "get chain head")
|
||||
}
|
||||
@@ -53,20 +52,20 @@ func (g grpcPrysmBeaconChainClient) GetValidatorCount(ctx context.Context, _ str
|
||||
}
|
||||
|
||||
// validatorCountByStatus returns a slice of validator count for each status in the given epoch.
|
||||
func validatorCountByStatus(validators []*ethpb.Validator, statuses []validator.Status, epoch primitives.Epoch) ([]iface.ValidatorCount, error) {
|
||||
func validatorCountByStatus(validators []*ethpb.Validator, statuses []validator.Status, epoch primitives.Epoch) ([]beacon.ValidatorCount, error) {
|
||||
countByStatus := make(map[validator.Status]uint64)
|
||||
for _, val := range validators {
|
||||
readOnlyVal, err := statenative.NewValidator(val)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not convert validator: %v", err)
|
||||
return nil, fmt.Errorf("could not convert validator: %w", err)
|
||||
}
|
||||
valStatus, err := helpers.ValidatorStatus(readOnlyVal, epoch)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get validator status: %v", err)
|
||||
return nil, fmt.Errorf("could not get validator status: %w", err)
|
||||
}
|
||||
valSubStatus, err := helpers.ValidatorSubStatus(readOnlyVal, epoch)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get validator sub status: %v", err)
|
||||
return nil, fmt.Errorf("could not get validator sub status: %w", err)
|
||||
}
|
||||
|
||||
for _, status := range statuses {
|
||||
@@ -76,9 +75,9 @@ func validatorCountByStatus(validators []*ethpb.Validator, statuses []validator.
|
||||
}
|
||||
}
|
||||
|
||||
var resp []iface.ValidatorCount
|
||||
var resp []beacon.ValidatorCount
|
||||
for status, count := range countByStatus {
|
||||
resp = append(resp, iface.ValidatorCount{
|
||||
resp = append(resp, beacon.ValidatorCount{
|
||||
Status: status.String(),
|
||||
Count: count,
|
||||
})
|
||||
@@ -92,6 +91,6 @@ func validatorCountByStatus(validators []*ethpb.Validator, statuses []validator.
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func NewGrpcPrysmBeaconChainClient(cc grpc.ClientConnInterface) iface.PrysmBeaconChainClient {
|
||||
return &grpcPrysmBeaconChainClient{beaconChainClient: &grpcBeaconChainClient{ethpb.NewBeaconChainClient(cc)}}
|
||||
func (c *grpcPrysmChainClient) ValidatorPerformance(ctx context.Context, in *ethpb.ValidatorPerformanceRequest) (*ethpb.ValidatorPerformanceResponse, error) {
|
||||
return c.chainClient.ValidatorPerformance(ctx, in)
|
||||
}
|
||||
@@ -1,21 +1,21 @@
|
||||
package grpc_api
|
||||
package prysm_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/mock"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/validator"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/util"
|
||||
mock "github.com/prysmaticlabs/prysm/v5/testing/validator-mock"
|
||||
"github.com/prysmaticlabs/prysm/v5/validator/client/iface"
|
||||
"go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
func TestGetValidatorCount(t *testing.T) {
|
||||
func TestGRPC_GetValidatorCount(t *testing.T) {
|
||||
st, _ := util.DeterministicGenesisState(t, 10)
|
||||
farFutureEpoch := params.BeaconConfig().FarFutureEpoch
|
||||
validators := []*ethpb.Validator{
|
||||
@@ -83,8 +83,8 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
Slashed: false,
|
||||
},
|
||||
}
|
||||
for _, validator := range validators {
|
||||
require.NoError(t, st.AppendValidator(validator))
|
||||
for _, v := range validators {
|
||||
require.NoError(t, st.AppendValidator(v))
|
||||
require.NoError(t, st.AppendBalance(params.BeaconConfig().MaxEffectiveBalance))
|
||||
}
|
||||
|
||||
@@ -92,12 +92,12 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
name string
|
||||
statuses []string
|
||||
currentEpoch int
|
||||
expectedResponse []iface.ValidatorCount
|
||||
expectedResponse []beacon.ValidatorCount
|
||||
}{
|
||||
{
|
||||
name: "Head count active validators",
|
||||
statuses: []string{"active"},
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
expectedResponse: []beacon.ValidatorCount{
|
||||
{
|
||||
Status: "active",
|
||||
Count: 13,
|
||||
@@ -107,7 +107,7 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
{
|
||||
name: "Head count active ongoing validators",
|
||||
statuses: []string{"active_ongoing"},
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
expectedResponse: []beacon.ValidatorCount{
|
||||
{
|
||||
Status: "active_ongoing",
|
||||
Count: 11,
|
||||
@@ -117,7 +117,7 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
{
|
||||
name: "Head count active exiting validators",
|
||||
statuses: []string{"active_exiting"},
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
expectedResponse: []beacon.ValidatorCount{
|
||||
{
|
||||
Status: "active_exiting",
|
||||
Count: 1,
|
||||
@@ -127,7 +127,7 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
{
|
||||
name: "Head count active slashed validators",
|
||||
statuses: []string{"active_slashed"},
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
expectedResponse: []beacon.ValidatorCount{
|
||||
{
|
||||
Status: "active_slashed",
|
||||
Count: 1,
|
||||
@@ -137,7 +137,7 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
{
|
||||
name: "Head count pending validators",
|
||||
statuses: []string{"pending"},
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
expectedResponse: []beacon.ValidatorCount{
|
||||
{
|
||||
Status: "pending",
|
||||
Count: 6,
|
||||
@@ -147,7 +147,7 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
{
|
||||
name: "Head count pending initialized validators",
|
||||
statuses: []string{"pending_initialized"},
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
expectedResponse: []beacon.ValidatorCount{
|
||||
{
|
||||
Status: "pending_initialized",
|
||||
Count: 1,
|
||||
@@ -157,7 +157,7 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
{
|
||||
name: "Head count pending queued validators",
|
||||
statuses: []string{"pending_queued"},
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
expectedResponse: []beacon.ValidatorCount{
|
||||
{
|
||||
Status: "pending_queued",
|
||||
Count: 5,
|
||||
@@ -168,7 +168,7 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
name: "Head count exited validators",
|
||||
statuses: []string{"exited"},
|
||||
currentEpoch: 35,
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
expectedResponse: []beacon.ValidatorCount{
|
||||
{
|
||||
Status: "exited",
|
||||
Count: 6,
|
||||
@@ -179,7 +179,7 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
name: "Head count exited slashed validators",
|
||||
statuses: []string{"exited_slashed"},
|
||||
currentEpoch: 35,
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
expectedResponse: []beacon.ValidatorCount{
|
||||
{
|
||||
Status: "exited_slashed",
|
||||
Count: 2,
|
||||
@@ -190,7 +190,7 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
name: "Head count exited unslashed validators",
|
||||
statuses: []string{"exited_unslashed"},
|
||||
currentEpoch: 35,
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
expectedResponse: []beacon.ValidatorCount{
|
||||
{
|
||||
Status: "exited_unslashed",
|
||||
Count: 4,
|
||||
@@ -201,7 +201,7 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
name: "Head count withdrawal validators",
|
||||
statuses: []string{"withdrawal"},
|
||||
currentEpoch: 45,
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
expectedResponse: []beacon.ValidatorCount{
|
||||
{
|
||||
Status: "withdrawal",
|
||||
Count: 2,
|
||||
@@ -212,7 +212,7 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
name: "Head count withdrawal possible validators",
|
||||
statuses: []string{"withdrawal_possible"},
|
||||
currentEpoch: 45,
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
expectedResponse: []beacon.ValidatorCount{
|
||||
{
|
||||
Status: "withdrawal_possible",
|
||||
Count: 1,
|
||||
@@ -223,7 +223,7 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
name: "Head count withdrawal done validators",
|
||||
statuses: []string{"withdrawal_done"},
|
||||
currentEpoch: 45,
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
expectedResponse: []beacon.ValidatorCount{
|
||||
{
|
||||
Status: "withdrawal_done",
|
||||
Count: 1,
|
||||
@@ -233,7 +233,7 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
{
|
||||
name: "Head count active and pending validators",
|
||||
statuses: []string{"active", "pending"},
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
expectedResponse: []beacon.ValidatorCount{
|
||||
{
|
||||
Status: "active",
|
||||
Count: 13,
|
||||
@@ -246,7 +246,7 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "Head count of ALL validators",
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
expectedResponse: []beacon.ValidatorCount{
|
||||
{
|
||||
Status: "active",
|
||||
Count: 13,
|
||||
@@ -291,8 +291,8 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
beaconChainClient := mock.NewMockBeaconChainClient(ctrl)
|
||||
beaconChainClient.EXPECT().ListValidators(
|
||||
chainClient := mock.NewMockChainClient(ctrl)
|
||||
chainClient.EXPECT().Validators(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
@@ -300,7 +300,7 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
nil,
|
||||
)
|
||||
|
||||
beaconChainClient.EXPECT().GetChainHead(
|
||||
chainClient.EXPECT().ChainHead(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
@@ -308,8 +308,8 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
nil,
|
||||
)
|
||||
|
||||
prysmBeaconChainClient := &grpcPrysmBeaconChainClient{
|
||||
beaconChainClient: beaconChainClient,
|
||||
prysmBeaconChainClient := &grpcPrysmChainClient{
|
||||
chainClient: chainClient,
|
||||
}
|
||||
|
||||
var statuses []validator.Status
|
||||
@@ -318,7 +318,7 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
require.Equal(t, true, ok)
|
||||
statuses = append(statuses, valStatus)
|
||||
}
|
||||
vcCountResp, err := prysmBeaconChainClient.GetValidatorCount(context.Background(), "", statuses)
|
||||
vcCountResp, err := prysmBeaconChainClient.ValidatorCount(context.Background(), "", statuses)
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, test.expectedResponse, vcCountResp)
|
||||
})
|
||||
15
api/client/beacon/prysm_api/interfaces.go
Normal file
15
api/client/beacon/prysm_api/interfaces.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package prysm_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/validator"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
// Client defines an interface required to implement all the prysm specific custom endpoints.
|
||||
type Client interface {
|
||||
ValidatorCount(context.Context, string, []validator.Status) ([]beacon.ValidatorCount, error)
|
||||
ValidatorPerformance(context.Context, *ethpb.ValidatorPerformanceRequest) (*ethpb.ValidatorPerformanceResponse, error)
|
||||
}
|
||||
108
api/client/beacon/prysm_api/rest_client.go
Normal file
108
api/client/beacon/prysm_api/rest_client.go
Normal file
@@ -0,0 +1,108 @@
|
||||
package prysm_api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
neturl "net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/apiutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/node"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
validator2 "github.com/prysmaticlabs/prysm/v5/consensus-types/validator"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
type prysmChainClient struct {
|
||||
jsonRestHandler client.JsonRestHandler
|
||||
nodeClient node.Client
|
||||
}
|
||||
|
||||
func (c prysmChainClient) ValidatorCount(ctx context.Context, stateID string, statuses []validator2.Status) ([]beacon.ValidatorCount, error) {
|
||||
// Check node version for prysm beacon node as it is a custom endpoint for prysm beacon node.
|
||||
nodeVersion, err := c.nodeClient.Version(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get node version")
|
||||
}
|
||||
|
||||
if !strings.Contains(strings.ToLower(nodeVersion.Version), "prysm") {
|
||||
return nil, client.ErrNotSupported
|
||||
}
|
||||
|
||||
queryParams := neturl.Values{}
|
||||
for _, status := range statuses {
|
||||
queryParams.Add("status", status.String())
|
||||
}
|
||||
|
||||
queryUrl := apiutil.BuildURL(fmt.Sprintf("/eth/v1/beacon/states/%s/validator_count", stateID), queryParams)
|
||||
|
||||
var validatorCountResponse structs.GetValidatorCountResponse
|
||||
if err = c.jsonRestHandler.Get(ctx, queryUrl, &validatorCountResponse); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if validatorCountResponse.Data == nil {
|
||||
return nil, errors.New("validator count data is nil")
|
||||
}
|
||||
|
||||
if len(statuses) != 0 && len(statuses) != len(validatorCountResponse.Data) {
|
||||
return nil, errors.New("mismatch between validator count data and the number of statuses provided")
|
||||
}
|
||||
|
||||
var resp []beacon.ValidatorCount
|
||||
for _, vc := range validatorCountResponse.Data {
|
||||
count, err := strconv.ParseUint(vc.Count, 10, 64)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse validator count %s", vc.Count)
|
||||
}
|
||||
|
||||
resp = append(resp, beacon.ValidatorCount{
|
||||
Status: vc.Status,
|
||||
Count: count,
|
||||
})
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (c prysmChainClient) ValidatorPerformance(ctx context.Context, in *ethpb.ValidatorPerformanceRequest) (*ethpb.ValidatorPerformanceResponse, error) {
|
||||
// Check node version for prysm beacon node as it is a custom endpoint for prysm beacon node.
|
||||
nodeVersion, err := c.nodeClient.Version(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get node version")
|
||||
}
|
||||
|
||||
if !strings.Contains(strings.ToLower(nodeVersion.Version), "prysm") {
|
||||
return nil, client.ErrNotSupported
|
||||
}
|
||||
|
||||
request, err := json.Marshal(structs.GetValidatorPerformanceRequest{
|
||||
PublicKeys: in.PublicKeys,
|
||||
Indices: in.Indices,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to marshal request")
|
||||
}
|
||||
resp := &structs.GetValidatorPerformanceResponse{}
|
||||
if err = c.jsonRestHandler.Post(ctx, "/prysm/validators/performance", nil, bytes.NewBuffer(request), resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ðpb.ValidatorPerformanceResponse{
|
||||
CurrentEffectiveBalances: resp.CurrentEffectiveBalances,
|
||||
CorrectlyVotedSource: resp.CorrectlyVotedSource,
|
||||
CorrectlyVotedTarget: resp.CorrectlyVotedTarget,
|
||||
CorrectlyVotedHead: resp.CorrectlyVotedHead,
|
||||
BalancesBeforeEpochTransition: resp.BalancesBeforeEpochTransition,
|
||||
BalancesAfterEpochTransition: resp.BalancesAfterEpochTransition,
|
||||
MissingValidators: resp.MissingValidators,
|
||||
PublicKeys: resp.PublicKeys,
|
||||
InactivityScores: resp.InactivityScores,
|
||||
}, nil
|
||||
}
|
||||
@@ -1,15 +1,20 @@
|
||||
package beacon_api
|
||||
package prysm_api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/mock"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/node"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/validator"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api/mock"
|
||||
"github.com/prysmaticlabs/prysm/v5/validator/client/iface"
|
||||
"go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
@@ -23,7 +28,7 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
versionResponse structs.GetVersionResponse
|
||||
validatorCountResponse structs.GetValidatorCountResponse
|
||||
validatorCountCalled int
|
||||
expectedResponse []iface.ValidatorCount
|
||||
expectedResponse []beacon.ValidatorCount
|
||||
expectedError string
|
||||
}{
|
||||
{
|
||||
@@ -42,7 +47,7 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
},
|
||||
},
|
||||
validatorCountCalled: 1,
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
expectedResponse: []beacon.ValidatorCount{
|
||||
{
|
||||
Status: "active",
|
||||
Count: 10,
|
||||
@@ -118,7 +123,7 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
// Expect node version endpoint call.
|
||||
var nodeVersionResponse structs.GetVersionResponse
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
"/eth/v1/node/version",
|
||||
&nodeVersionResponse,
|
||||
).Return(
|
||||
@@ -130,7 +135,7 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
|
||||
var validatorCountResponse structs.GetValidatorCountResponse
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
"/eth/v1/beacon/states/head/validator_count?status=active",
|
||||
&validatorCountResponse,
|
||||
).Return(
|
||||
@@ -141,12 +146,12 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
).Times(test.validatorCountCalled)
|
||||
|
||||
// Type assertion.
|
||||
var client iface.PrysmBeaconChainClient = &prysmBeaconChainClient{
|
||||
nodeClient: &beaconApiNodeClient{jsonRestHandler: jsonRestHandler},
|
||||
var client Client = &prysmChainClient{
|
||||
nodeClient: node.NewNodeClientWithFallback(jsonRestHandler, nil),
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
}
|
||||
|
||||
countResponse, err := client.GetValidatorCount(ctx, "head", []validator.Status{validator.Active})
|
||||
countResponse, err := client.ValidatorCount(ctx, "head", []validator.Status{validator.Active})
|
||||
|
||||
if len(test.expectedResponse) == 0 {
|
||||
require.ErrorContains(t, test.expectedError, err)
|
||||
@@ -156,5 +161,61 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func Test_beaconApiBeaconChainClient_GetValidatorPerformance(t *testing.T) {
|
||||
const nodeVersion = "prysm/v0.0.1"
|
||||
publicKeys := [][48]byte{
|
||||
bytesutil.ToBytes48([]byte{1}),
|
||||
bytesutil.ToBytes48([]byte{2}),
|
||||
bytesutil.ToBytes48([]byte{3}),
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
request, err := json.Marshal(structs.GetValidatorPerformanceRequest{
|
||||
PublicKeys: [][]byte{publicKeys[0][:], publicKeys[2][:], publicKeys[1][:]},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
// Expect node version endpoint call.
|
||||
var nodeVersionResponse structs.GetVersionResponse
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
"/eth/v1/node/version",
|
||||
&nodeVersionResponse,
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
2,
|
||||
structs.GetVersionResponse{
|
||||
Data: &structs.Version{Version: nodeVersion},
|
||||
},
|
||||
)
|
||||
|
||||
wantResponse := &structs.GetValidatorPerformanceResponse{}
|
||||
want := ðpb.ValidatorPerformanceResponse{}
|
||||
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
gomock.Any(),
|
||||
"/prysm/validators/performance",
|
||||
nil,
|
||||
bytes.NewBuffer(request),
|
||||
wantResponse,
|
||||
).Return(
|
||||
nil,
|
||||
)
|
||||
|
||||
var client Client = &prysmChainClient{
|
||||
nodeClient: node.NewNodeClientWithFallback(jsonRestHandler, nil),
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
}
|
||||
|
||||
got, err := client.ValidatorPerformance(ctx, ðpb.ValidatorPerformanceRequest{
|
||||
PublicKeys: [][]byte{publicKeys[0][:], publicKeys[2][:], publicKeys[1][:]},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, want.PublicKeys, got.PublicKeys)
|
||||
}
|
||||
42
api/client/beacon/shared_providers/BUILD.bazel
Normal file
42
api/client/beacon/shared_providers/BUILD.bazel
Normal file
@@ -0,0 +1,42 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"duties.go",
|
||||
"genesis.go",
|
||||
"interfaces.go",
|
||||
"providers.go",
|
||||
"state_validators.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/api/client/beacon/shared_providers",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//api/client:go_default_library",
|
||||
"//api/client/apiutil:go_default_library",
|
||||
"//api/server/structs:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"duties_test.go",
|
||||
"genesis_test.go",
|
||||
"state_validators_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//api/client/apiutil:go_default_library",
|
||||
"//api/client/beacon/mock:go_default_library",
|
||||
"//api/server/structs:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@org_uber_go_mock//gomock:go_default_library",
|
||||
],
|
||||
)
|
||||
132
api/client/beacon/shared_providers/duties.go
Normal file
132
api/client/beacon/shared_providers/duties.go
Normal file
@@ -0,0 +1,132 @@
|
||||
package shared_providers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/apiutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
)
|
||||
|
||||
type dutiesProvider struct {
|
||||
jsonRestHandler client.JsonRestHandler
|
||||
}
|
||||
|
||||
// Committees retrieves the committees for the given epoch
|
||||
func (c dutiesProvider) Committees(ctx context.Context, epoch primitives.Epoch) ([]*structs.Committee, error) {
|
||||
committeeParams := url.Values{}
|
||||
committeeParams.Add("epoch", strconv.FormatUint(uint64(epoch), 10))
|
||||
committeesRequest := apiutil.BuildURL("/eth/v1/beacon/states/head/committees", committeeParams)
|
||||
|
||||
var stateCommittees structs.GetCommitteesResponse
|
||||
if err := c.jsonRestHandler.Get(ctx, committeesRequest, &stateCommittees); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if stateCommittees.Data == nil {
|
||||
return nil, errors.New("state committees data is nil")
|
||||
}
|
||||
|
||||
for index, committee := range stateCommittees.Data {
|
||||
if committee == nil {
|
||||
return nil, errors.Errorf("committee at index `%d` is nil", index)
|
||||
}
|
||||
}
|
||||
|
||||
return stateCommittees.Data, nil
|
||||
}
|
||||
|
||||
// AttesterDuties retrieves the attester duties for the given epoch and validatorIndices
|
||||
func (c dutiesProvider) AttesterDuties(ctx context.Context, epoch primitives.Epoch, validatorIndices []primitives.ValidatorIndex) ([]*structs.AttesterDuty, error) {
|
||||
jsonValidatorIndices := make([]string, len(validatorIndices))
|
||||
for index, validatorIndex := range validatorIndices {
|
||||
jsonValidatorIndices[index] = strconv.FormatUint(uint64(validatorIndex), 10)
|
||||
}
|
||||
|
||||
validatorIndicesBytes, err := json.Marshal(jsonValidatorIndices)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to marshal validator indices")
|
||||
}
|
||||
|
||||
attesterDuties := &structs.GetAttesterDutiesResponse{}
|
||||
if err = c.jsonRestHandler.Post(
|
||||
ctx,
|
||||
fmt.Sprintf("/eth/v1/validator/duties/attester/%d", epoch),
|
||||
nil,
|
||||
bytes.NewBuffer(validatorIndicesBytes),
|
||||
attesterDuties,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for index, attesterDuty := range attesterDuties.Data {
|
||||
if attesterDuty == nil {
|
||||
return nil, errors.Errorf("attester duty at index `%d` is nil", index)
|
||||
}
|
||||
}
|
||||
|
||||
return attesterDuties.Data, nil
|
||||
}
|
||||
|
||||
// ProposerDuties retrieves the proposer duties for the given epoch
|
||||
func (c dutiesProvider) ProposerDuties(ctx context.Context, epoch primitives.Epoch) ([]*structs.ProposerDuty, error) {
|
||||
proposerDuties := structs.GetProposerDutiesResponse{}
|
||||
if err := c.jsonRestHandler.Get(ctx, fmt.Sprintf("/eth/v1/validator/duties/proposer/%d", epoch), &proposerDuties); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if proposerDuties.Data == nil {
|
||||
return nil, errors.New("proposer duties data is nil")
|
||||
}
|
||||
|
||||
for index, proposerDuty := range proposerDuties.Data {
|
||||
if proposerDuty == nil {
|
||||
return nil, errors.Errorf("proposer duty at index `%d` is nil", index)
|
||||
}
|
||||
}
|
||||
|
||||
return proposerDuties.Data, nil
|
||||
}
|
||||
|
||||
// SyncDuties retrieves the sync committee duties for the given epoch and validatorIndices
|
||||
func (c dutiesProvider) SyncDuties(ctx context.Context, epoch primitives.Epoch, validatorIndices []primitives.ValidatorIndex) ([]*structs.SyncCommitteeDuty, error) {
|
||||
jsonValidatorIndices := make([]string, len(validatorIndices))
|
||||
for index, validatorIndex := range validatorIndices {
|
||||
jsonValidatorIndices[index] = strconv.FormatUint(uint64(validatorIndex), 10)
|
||||
}
|
||||
|
||||
validatorIndicesBytes, err := json.Marshal(jsonValidatorIndices)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to marshal validator indices")
|
||||
}
|
||||
|
||||
syncDuties := structs.GetSyncCommitteeDutiesResponse{}
|
||||
if err = c.jsonRestHandler.Post(
|
||||
ctx,
|
||||
fmt.Sprintf("/eth/v1/validator/duties/sync/%d", epoch),
|
||||
nil,
|
||||
bytes.NewBuffer(validatorIndicesBytes),
|
||||
&syncDuties,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if syncDuties.Data == nil {
|
||||
return nil, errors.New("sync duties data is nil")
|
||||
}
|
||||
|
||||
for index, syncDuty := range syncDuties.Data {
|
||||
if syncDuty == nil {
|
||||
return nil, errors.Errorf("sync duty at index `%d` is nil", index)
|
||||
}
|
||||
}
|
||||
|
||||
return syncDuties.Data, nil
|
||||
}
|
||||
508
api/client/beacon/shared_providers/duties_test.go
Normal file
508
api/client/beacon/shared_providers/duties_test.go
Normal file
@@ -0,0 +1,508 @@
|
||||
package shared_providers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/mock"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
const getAttesterDutiesTestEndpoint = "/eth/v1/validator/duties/attester"
|
||||
const getProposerDutiesTestEndpoint = "/eth/v1/validator/duties/proposer"
|
||||
const getSyncDutiesTestEndpoint = "/eth/v1/validator/duties/sync"
|
||||
const getCommitteesTestEndpoint = "/eth/v1/beacon/states/head/committees"
|
||||
|
||||
func TestGetAttesterDuties_Valid(t *testing.T) {
|
||||
stringValidatorIndices := []string{"2", "9"}
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
validatorIndicesBytes, err := json.Marshal(stringValidatorIndices)
|
||||
require.NoError(t, err)
|
||||
|
||||
expectedAttesterDuties := structs.GetAttesterDutiesResponse{
|
||||
Data: []*structs.AttesterDuty{
|
||||
{
|
||||
Pubkey: hexutil.Encode([]byte{1}),
|
||||
ValidatorIndex: "2",
|
||||
CommitteeIndex: "3",
|
||||
CommitteeLength: "4",
|
||||
CommitteesAtSlot: "5",
|
||||
ValidatorCommitteeIndex: "6",
|
||||
Slot: "7",
|
||||
},
|
||||
{
|
||||
Pubkey: hexutil.Encode([]byte{8}),
|
||||
ValidatorIndex: "9",
|
||||
CommitteeIndex: "10",
|
||||
CommitteeLength: "11",
|
||||
CommitteesAtSlot: "12",
|
||||
ValidatorCommitteeIndex: "13",
|
||||
Slot: "14",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
validatorIndices := []primitives.ValidatorIndex{2, 9}
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s/%d", getAttesterDutiesTestEndpoint, epoch),
|
||||
nil,
|
||||
bytes.NewBuffer(validatorIndicesBytes),
|
||||
&structs.GetAttesterDutiesResponse{},
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
4,
|
||||
expectedAttesterDuties,
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &dutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
attesterDuties, err := dutiesProvider.AttesterDuties(ctx, epoch, validatorIndices)
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, expectedAttesterDuties.Data, attesterDuties)
|
||||
}
|
||||
|
||||
func TestGetAttesterDuties_HttpError(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s/%d", getAttesterDutiesTestEndpoint, epoch),
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
errors.New("foo error"),
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &dutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := dutiesProvider.AttesterDuties(ctx, epoch, nil)
|
||||
assert.ErrorContains(t, "foo error", err)
|
||||
}
|
||||
|
||||
func TestGetAttesterDuties_NilAttesterDuty(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s/%d", getAttesterDutiesTestEndpoint, epoch),
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
4,
|
||||
structs.GetAttesterDutiesResponse{
|
||||
Data: []*structs.AttesterDuty{nil},
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &dutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := dutiesProvider.AttesterDuties(ctx, epoch, nil)
|
||||
assert.ErrorContains(t, "attester duty at index `0` is nil", err)
|
||||
}
|
||||
|
||||
func TestGetProposerDuties_Valid(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
expectedProposerDuties := structs.GetProposerDutiesResponse{
|
||||
Data: []*structs.ProposerDuty{
|
||||
{
|
||||
Pubkey: hexutil.Encode([]byte{1}),
|
||||
ValidatorIndex: "2",
|
||||
Slot: "3",
|
||||
},
|
||||
{
|
||||
Pubkey: hexutil.Encode([]byte{4}),
|
||||
ValidatorIndex: "5",
|
||||
Slot: "6",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s/%d", getProposerDutiesTestEndpoint, epoch),
|
||||
&structs.GetProposerDutiesResponse{},
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
2,
|
||||
expectedProposerDuties,
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &dutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
proposerDuties, err := dutiesProvider.ProposerDuties(ctx, epoch)
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, expectedProposerDuties.Data, proposerDuties)
|
||||
}
|
||||
|
||||
func TestGetProposerDuties_HttpError(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s/%d", getProposerDutiesTestEndpoint, epoch),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
errors.New("foo error"),
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &dutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := dutiesProvider.ProposerDuties(ctx, epoch)
|
||||
assert.ErrorContains(t, "foo error", err)
|
||||
}
|
||||
|
||||
func TestGetProposerDuties_NilData(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s/%d", getProposerDutiesTestEndpoint, epoch),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
2,
|
||||
structs.GetProposerDutiesResponse{
|
||||
Data: nil,
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &dutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := dutiesProvider.ProposerDuties(ctx, epoch)
|
||||
assert.ErrorContains(t, "proposer duties data is nil", err)
|
||||
}
|
||||
|
||||
func TestGetProposerDuties_NilProposerDuty(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s/%d", getProposerDutiesTestEndpoint, epoch),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
2,
|
||||
structs.GetProposerDutiesResponse{
|
||||
Data: []*structs.ProposerDuty{nil},
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &dutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := dutiesProvider.ProposerDuties(ctx, epoch)
|
||||
assert.ErrorContains(t, "proposer duty at index `0` is nil", err)
|
||||
}
|
||||
|
||||
func TestGetSyncDuties_Valid(t *testing.T) {
|
||||
stringValidatorIndices := []string{"2", "6"}
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
validatorIndicesBytes, err := json.Marshal(stringValidatorIndices)
|
||||
require.NoError(t, err)
|
||||
|
||||
expectedSyncDuties := structs.GetSyncCommitteeDutiesResponse{
|
||||
Data: []*structs.SyncCommitteeDuty{
|
||||
{
|
||||
Pubkey: hexutil.Encode([]byte{1}),
|
||||
ValidatorIndex: "2",
|
||||
ValidatorSyncCommitteeIndices: []string{
|
||||
"3",
|
||||
"4",
|
||||
},
|
||||
},
|
||||
{
|
||||
Pubkey: hexutil.Encode([]byte{5}),
|
||||
ValidatorIndex: "6",
|
||||
ValidatorSyncCommitteeIndices: []string{
|
||||
"7",
|
||||
"8",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
validatorIndices := []primitives.ValidatorIndex{2, 6}
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s/%d", getSyncDutiesTestEndpoint, epoch),
|
||||
nil,
|
||||
bytes.NewBuffer(validatorIndicesBytes),
|
||||
&structs.GetSyncCommitteeDutiesResponse{},
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
4,
|
||||
expectedSyncDuties,
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &dutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
syncDuties, err := dutiesProvider.SyncDuties(ctx, epoch, validatorIndices)
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, expectedSyncDuties.Data, syncDuties)
|
||||
}
|
||||
|
||||
func TestGetSyncDuties_HttpError(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s/%d", getSyncDutiesTestEndpoint, epoch),
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
errors.New("foo error"),
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &dutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := dutiesProvider.SyncDuties(ctx, epoch, nil)
|
||||
assert.ErrorContains(t, "foo error", err)
|
||||
}
|
||||
|
||||
func TestGetSyncDuties_NilData(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s/%d", getSyncDutiesTestEndpoint, epoch),
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
4,
|
||||
structs.GetSyncCommitteeDutiesResponse{
|
||||
Data: nil,
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &dutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := dutiesProvider.SyncDuties(ctx, epoch, nil)
|
||||
assert.ErrorContains(t, "sync duties data is nil", err)
|
||||
}
|
||||
|
||||
func TestGetSyncDuties_NilSyncDuty(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s/%d", getSyncDutiesTestEndpoint, epoch),
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
4,
|
||||
structs.GetSyncCommitteeDutiesResponse{
|
||||
Data: []*structs.SyncCommitteeDuty{nil},
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &dutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := dutiesProvider.SyncDuties(ctx, epoch, nil)
|
||||
assert.ErrorContains(t, "sync duty at index `0` is nil", err)
|
||||
}
|
||||
|
||||
func TestGetCommittees_Valid(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
expectedCommittees := structs.GetCommitteesResponse{
|
||||
Data: []*structs.Committee{
|
||||
{
|
||||
Index: "1",
|
||||
Slot: "2",
|
||||
Validators: []string{
|
||||
"3",
|
||||
"4",
|
||||
},
|
||||
},
|
||||
{
|
||||
Index: "5",
|
||||
Slot: "6",
|
||||
Validators: []string{
|
||||
"7",
|
||||
"8",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s?epoch=%d", getCommitteesTestEndpoint, epoch),
|
||||
&structs.GetCommitteesResponse{},
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
2,
|
||||
expectedCommittees,
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &dutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
committees, err := dutiesProvider.Committees(ctx, epoch)
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, expectedCommittees.Data, committees)
|
||||
}
|
||||
|
||||
func TestGetCommittees_HttpError(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s?epoch=%d", getCommitteesTestEndpoint, epoch),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
errors.New("foo error"),
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &dutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := dutiesProvider.Committees(ctx, epoch)
|
||||
assert.ErrorContains(t, "foo error", err)
|
||||
}
|
||||
|
||||
func TestGetCommittees_NilData(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s?epoch=%d", getCommitteesTestEndpoint, epoch),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
2,
|
||||
structs.GetCommitteesResponse{
|
||||
Data: nil,
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &dutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := dutiesProvider.Committees(ctx, epoch)
|
||||
assert.ErrorContains(t, "state committees data is nil", err)
|
||||
}
|
||||
|
||||
func TestGetCommittees_NilCommittee(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s?epoch=%d", getCommitteesTestEndpoint, epoch),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
2,
|
||||
structs.GetCommitteesResponse{
|
||||
Data: []*structs.Committee{nil},
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &dutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := dutiesProvider.Committees(ctx, epoch)
|
||||
assert.ErrorContains(t, "committee at index `0` is nil", err)
|
||||
}
|
||||
38
api/client/beacon/shared_providers/genesis.go
Normal file
38
api/client/beacon/shared_providers/genesis.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package shared_providers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
)
|
||||
|
||||
type genesisProvider struct {
|
||||
jsonRestHandler client.JsonRestHandler
|
||||
genesis *structs.Genesis
|
||||
once sync.Once
|
||||
}
|
||||
|
||||
// GetGenesis gets the genesis information from the beacon node via the /eth/v1/beacon/genesis endpoint
|
||||
func (c *genesisProvider) Genesis(ctx context.Context) (*structs.Genesis, error) {
|
||||
genesisJson := &structs.GetGenesisResponse{}
|
||||
var doErr error
|
||||
c.once.Do(func() {
|
||||
if err := c.jsonRestHandler.Get(ctx, "/eth/v1/beacon/genesis", genesisJson); err != nil {
|
||||
doErr = err
|
||||
return
|
||||
}
|
||||
if genesisJson.Data == nil {
|
||||
doErr = errors.New("genesis data is nil")
|
||||
return
|
||||
}
|
||||
c.genesis = genesisJson.Data
|
||||
})
|
||||
if doErr != nil {
|
||||
// Allow another call because the current one returned an error
|
||||
c.once = sync.Once{}
|
||||
}
|
||||
return c.genesis, doErr
|
||||
}
|
||||
144
api/client/beacon/shared_providers/genesis_test.go
Normal file
144
api/client/beacon/shared_providers/genesis_test.go
Normal file
@@ -0,0 +1,144 @@
|
||||
package shared_providers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/mock"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
func TestGetGenesis_ValidGenesis(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
genesisResponseJson := structs.GetGenesisResponse{}
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
"/eth/v1/beacon/genesis",
|
||||
&genesisResponseJson,
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
2,
|
||||
structs.GetGenesisResponse{
|
||||
Data: &structs.Genesis{
|
||||
GenesisTime: "1234",
|
||||
GenesisValidatorsRoot: "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
|
||||
},
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
genesisProvider := &genesisProvider{jsonRestHandler: jsonRestHandler}
|
||||
resp, err := genesisProvider.Genesis(ctx)
|
||||
assert.NoError(t, err)
|
||||
require.NotNil(t, resp)
|
||||
assert.Equal(t, "1234", resp.GenesisTime)
|
||||
assert.Equal(t, "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", resp.GenesisValidatorsRoot)
|
||||
}
|
||||
|
||||
func TestGetGenesis_NilData(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
genesisResponseJson := structs.GetGenesisResponse{}
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
"/eth/v1/beacon/genesis",
|
||||
&genesisResponseJson,
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
2,
|
||||
structs.GetGenesisResponse{Data: nil},
|
||||
).Times(1)
|
||||
|
||||
genesisProvider := &genesisProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := genesisProvider.Genesis(ctx)
|
||||
assert.ErrorContains(t, "genesis data is nil", err)
|
||||
}
|
||||
|
||||
func TestGetGenesis_EndpointCalledOnlyOnce(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
genesisResponseJson := structs.GetGenesisResponse{}
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
"/eth/v1/beacon/genesis",
|
||||
&genesisResponseJson,
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
2,
|
||||
structs.GetGenesisResponse{
|
||||
Data: &structs.Genesis{
|
||||
GenesisTime: "1234",
|
||||
GenesisValidatorsRoot: "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
|
||||
},
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
genesisProvider := &genesisProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := genesisProvider.Genesis(ctx)
|
||||
assert.NoError(t, err)
|
||||
resp, err := genesisProvider.Genesis(ctx)
|
||||
assert.NoError(t, err)
|
||||
require.NotNil(t, resp)
|
||||
assert.Equal(t, "1234", resp.GenesisTime)
|
||||
assert.Equal(t, "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", resp.GenesisValidatorsRoot)
|
||||
}
|
||||
|
||||
func TestGetGenesis_EndpointCanBeCalledAgainAfterError(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
genesisResponseJson := structs.GetGenesisResponse{}
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
"/eth/v1/beacon/genesis",
|
||||
&genesisResponseJson,
|
||||
).Return(
|
||||
errors.New("foo"),
|
||||
).Times(1)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
"/eth/v1/beacon/genesis",
|
||||
&genesisResponseJson,
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
2,
|
||||
structs.GetGenesisResponse{
|
||||
Data: &structs.Genesis{
|
||||
GenesisTime: "1234",
|
||||
GenesisValidatorsRoot: "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
|
||||
},
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
genesisProvider := &genesisProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := genesisProvider.Genesis(ctx)
|
||||
require.ErrorContains(t, "foo", err)
|
||||
resp, err := genesisProvider.Genesis(ctx)
|
||||
assert.NoError(t, err)
|
||||
require.NotNil(t, resp)
|
||||
assert.Equal(t, "1234", resp.GenesisTime)
|
||||
assert.Equal(t, "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", resp.GenesisValidatorsRoot)
|
||||
}
|
||||
25
api/client/beacon/shared_providers/interfaces.go
Normal file
25
api/client/beacon/shared_providers/interfaces.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package shared_providers
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
)
|
||||
|
||||
type Genesis interface {
|
||||
Genesis(ctx context.Context) (*structs.Genesis, error)
|
||||
}
|
||||
|
||||
type StateValidators interface {
|
||||
StateValidators(context.Context, []string, []primitives.ValidatorIndex, []string) (*structs.GetValidatorsResponse, error)
|
||||
StateValidatorsForSlot(context.Context, primitives.Slot, []string, []primitives.ValidatorIndex, []string) (*structs.GetValidatorsResponse, error)
|
||||
StateValidatorsForHead(context.Context, []string, []primitives.ValidatorIndex, []string) (*structs.GetValidatorsResponse, error)
|
||||
}
|
||||
|
||||
type Duties interface {
|
||||
AttesterDuties(ctx context.Context, epoch primitives.Epoch, validatorIndices []primitives.ValidatorIndex) ([]*structs.AttesterDuty, error)
|
||||
ProposerDuties(ctx context.Context, epoch primitives.Epoch) ([]*structs.ProposerDuty, error)
|
||||
SyncDuties(ctx context.Context, epoch primitives.Epoch, validatorIndices []primitives.ValidatorIndex) ([]*structs.SyncCommitteeDuty, error)
|
||||
Committees(ctx context.Context, epoch primitives.Epoch) ([]*structs.Committee, error)
|
||||
}
|
||||
17
api/client/beacon/shared_providers/providers.go
Normal file
17
api/client/beacon/shared_providers/providers.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package shared_providers
|
||||
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client"
|
||||
)
|
||||
|
||||
func NewStateValidators(jsonRestHandler client.JsonRestHandler) StateValidators {
|
||||
return &stateValidatorsProvider{jsonRestHandler: jsonRestHandler}
|
||||
}
|
||||
|
||||
func NewDuties(jsonRestHandler client.JsonRestHandler) Duties {
|
||||
return &dutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
}
|
||||
|
||||
func NewGenesis(jsonRestHandler client.JsonRestHandler) Genesis {
|
||||
return &genesisProvider{jsonRestHandler: jsonRestHandler}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package shared_providers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -9,21 +9,17 @@ import (
|
||||
"strconv"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/apiutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
)
|
||||
|
||||
type StateValidatorsProvider interface {
|
||||
GetStateValidators(context.Context, []string, []primitives.ValidatorIndex, []string) (*structs.GetValidatorsResponse, error)
|
||||
GetStateValidatorsForSlot(context.Context, primitives.Slot, []string, []primitives.ValidatorIndex, []string) (*structs.GetValidatorsResponse, error)
|
||||
GetStateValidatorsForHead(context.Context, []string, []primitives.ValidatorIndex, []string) (*structs.GetValidatorsResponse, error)
|
||||
type stateValidatorsProvider struct {
|
||||
jsonRestHandler client.JsonRestHandler
|
||||
}
|
||||
|
||||
type beaconApiStateValidatorsProvider struct {
|
||||
jsonRestHandler JsonRestHandler
|
||||
}
|
||||
|
||||
func (c beaconApiStateValidatorsProvider) GetStateValidators(
|
||||
func (c stateValidatorsProvider) StateValidators(
|
||||
ctx context.Context,
|
||||
stringPubkeys []string,
|
||||
indexes []primitives.ValidatorIndex,
|
||||
@@ -33,7 +29,7 @@ func (c beaconApiStateValidatorsProvider) GetStateValidators(
|
||||
return c.getStateValidatorsHelper(ctx, "/eth/v1/beacon/states/head/validators", append(stringIndices, stringPubkeys...), statuses)
|
||||
}
|
||||
|
||||
func (c beaconApiStateValidatorsProvider) GetStateValidatorsForSlot(
|
||||
func (c stateValidatorsProvider) StateValidatorsForSlot(
|
||||
ctx context.Context,
|
||||
slot primitives.Slot,
|
||||
stringPubkeys []string,
|
||||
@@ -41,11 +37,10 @@ func (c beaconApiStateValidatorsProvider) GetStateValidatorsForSlot(
|
||||
statuses []string,
|
||||
) (*structs.GetValidatorsResponse, error) {
|
||||
stringIndices := convertValidatorIndicesToStrings(indices)
|
||||
url := fmt.Sprintf("/eth/v1/beacon/states/%d/validators", slot)
|
||||
return c.getStateValidatorsHelper(ctx, url, append(stringIndices, stringPubkeys...), statuses)
|
||||
return c.getStateValidatorsHelper(ctx, fmt.Sprintf("/eth/v1/beacon/states/%d/validators", slot), append(stringIndices, stringPubkeys...), statuses)
|
||||
}
|
||||
|
||||
func (c beaconApiStateValidatorsProvider) GetStateValidatorsForHead(
|
||||
func (c stateValidatorsProvider) StateValidatorsForHead(
|
||||
ctx context.Context,
|
||||
stringPubkeys []string,
|
||||
indices []primitives.ValidatorIndex,
|
||||
@@ -67,7 +62,7 @@ func convertValidatorIndicesToStrings(indices []primitives.ValidatorIndex) []str
|
||||
return result
|
||||
}
|
||||
|
||||
func (c beaconApiStateValidatorsProvider) getStateValidatorsHelper(
|
||||
func (c stateValidatorsProvider) getStateValidatorsHelper(
|
||||
ctx context.Context,
|
||||
endpoint string,
|
||||
vals []string,
|
||||
@@ -113,7 +108,7 @@ func (c beaconApiStateValidatorsProvider) getStateValidatorsHelper(
|
||||
queryParams.Add("status", st)
|
||||
}
|
||||
|
||||
query := buildURL(endpoint, queryParams)
|
||||
query := apiutil.BuildURL(endpoint, queryParams)
|
||||
|
||||
err = c.jsonRestHandler.Get(ctx, query, stateValidatorsJson)
|
||||
if err != nil {
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package shared_providers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -8,11 +8,12 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/apiutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/mock"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api/mock"
|
||||
"go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
@@ -70,7 +71,7 @@ func TestGetStateValidators_Nominal_POST(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
"/eth/v1/beacon/states/head/validators",
|
||||
nil,
|
||||
bytes.NewBuffer(reqBytes),
|
||||
@@ -84,8 +85,8 @@ func TestGetStateValidators_Nominal_POST(t *testing.T) {
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
stateValidatorsProvider := beaconApiStateValidatorsProvider{jsonRestHandler: jsonRestHandler}
|
||||
actual, err := stateValidatorsProvider.GetStateValidators(ctx, []string{
|
||||
stateValidatorsProvider := stateValidatorsProvider{jsonRestHandler: jsonRestHandler}
|
||||
actual, err := stateValidatorsProvider.StateValidators(ctx, []string{
|
||||
"0x8000091c2ae64ee414a54c1cc1fc67dec663408bc636cb86756e0200e41a75c8f86603f104f02c856983d2783116be13", // active_ongoing
|
||||
"0x80000e851c0f53c3246ff726d7ff7766661ca5e12a07c45c114d208d54f0f8233d4380b2e9aff759d69795d1df905526", // active_exiting
|
||||
"0x424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242", // does not exist
|
||||
@@ -157,7 +158,7 @@ func TestGetStateValidators_Nominal_GET(t *testing.T) {
|
||||
|
||||
// First return an error from POST call.
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
"/eth/v1/beacon/states/head/validators",
|
||||
nil,
|
||||
bytes.NewBuffer(reqBytes),
|
||||
@@ -175,10 +176,10 @@ func TestGetStateValidators_Nominal_GET(t *testing.T) {
|
||||
queryParams.Add("status", st)
|
||||
}
|
||||
|
||||
query := buildURL("/eth/v1/beacon/states/head/validators", queryParams)
|
||||
query := apiutil.BuildURL("/eth/v1/beacon/states/head/validators", queryParams)
|
||||
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
query,
|
||||
&stateValidatorsResponseJson,
|
||||
).Return(
|
||||
@@ -190,8 +191,8 @@ func TestGetStateValidators_Nominal_GET(t *testing.T) {
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
stateValidatorsProvider := beaconApiStateValidatorsProvider{jsonRestHandler: jsonRestHandler}
|
||||
actual, err := stateValidatorsProvider.GetStateValidators(ctx, []string{
|
||||
stateValidatorsProvider := stateValidatorsProvider{jsonRestHandler: jsonRestHandler}
|
||||
actual, err := stateValidatorsProvider.StateValidators(ctx, []string{
|
||||
"0x8000091c2ae64ee414a54c1cc1fc67dec663408bc636cb86756e0200e41a75c8f86603f104f02c856983d2783116be13", // active_ongoing
|
||||
"0x80000e851c0f53c3246ff726d7ff7766661ca5e12a07c45c114d208d54f0f8233d4380b2e9aff759d69795d1df905526", // active_exiting
|
||||
"0x424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242", // does not exist
|
||||
@@ -226,7 +227,7 @@ func TestGetStateValidators_GetRestJsonResponseOnError(t *testing.T) {
|
||||
|
||||
// First call POST.
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
"/eth/v1/beacon/states/head/validators",
|
||||
nil,
|
||||
bytes.NewBuffer(reqBytes),
|
||||
@@ -244,18 +245,18 @@ func TestGetStateValidators_GetRestJsonResponseOnError(t *testing.T) {
|
||||
queryParams.Add("status", st)
|
||||
}
|
||||
|
||||
query := buildURL("/eth/v1/beacon/states/head/validators", queryParams)
|
||||
query := apiutil.BuildURL("/eth/v1/beacon/states/head/validators", queryParams)
|
||||
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
query,
|
||||
&stateValidatorsResponseJson,
|
||||
).Return(
|
||||
errors.New("an error"),
|
||||
).Times(1)
|
||||
|
||||
stateValidatorsProvider := beaconApiStateValidatorsProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err = stateValidatorsProvider.GetStateValidators(ctx, []string{
|
||||
stateValidatorsProvider := stateValidatorsProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err = stateValidatorsProvider.StateValidators(ctx, []string{
|
||||
"0x8000091c2ae64ee414a54c1cc1fc67dec663408bc636cb86756e0200e41a75c8f86603f104f02c856983d2783116be13", // active_ongoing
|
||||
},
|
||||
nil,
|
||||
@@ -280,7 +281,7 @@ func TestGetStateValidators_DataIsNil_POST(t *testing.T) {
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
"/eth/v1/beacon/states/head/validators",
|
||||
nil, bytes.NewBuffer(reqBytes),
|
||||
&stateValidatorsResponseJson,
|
||||
@@ -293,8 +294,8 @@ func TestGetStateValidators_DataIsNil_POST(t *testing.T) {
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
stateValidatorsProvider := beaconApiStateValidatorsProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err = stateValidatorsProvider.GetStateValidators(ctx, []string{
|
||||
stateValidatorsProvider := stateValidatorsProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err = stateValidatorsProvider.StateValidators(ctx, []string{
|
||||
"0x8000091c2ae64ee414a54c1cc1fc67dec663408bc636cb86756e0200e41a75c8f86603f104f02c856983d2783116be13", // active_ongoing
|
||||
},
|
||||
nil,
|
||||
@@ -320,7 +321,7 @@ func TestGetStateValidators_DataIsNil_GET(t *testing.T) {
|
||||
|
||||
// First call POST which will return an error.
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
"/eth/v1/beacon/states/head/validators",
|
||||
nil,
|
||||
bytes.NewBuffer(reqBytes),
|
||||
@@ -338,10 +339,10 @@ func TestGetStateValidators_DataIsNil_GET(t *testing.T) {
|
||||
queryParams.Add("status", st)
|
||||
}
|
||||
|
||||
query := buildURL("/eth/v1/beacon/states/head/validators", queryParams)
|
||||
query := apiutil.BuildURL("/eth/v1/beacon/states/head/validators", queryParams)
|
||||
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
query,
|
||||
&stateValidatorsResponseJson,
|
||||
).Return(
|
||||
@@ -353,8 +354,8 @@ func TestGetStateValidators_DataIsNil_GET(t *testing.T) {
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
stateValidatorsProvider := beaconApiStateValidatorsProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err = stateValidatorsProvider.GetStateValidators(ctx, []string{
|
||||
stateValidatorsProvider := stateValidatorsProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err = stateValidatorsProvider.StateValidators(ctx, []string{
|
||||
"0x8000091c2ae64ee414a54c1cc1fc67dec663408bc636cb86756e0200e41a75c8f86603f104f02c856983d2783116be13", // active_ongoing
|
||||
},
|
||||
nil,
|
||||
145
api/client/beacon/structs.go
Normal file
145
api/client/beacon/structs.go
Normal file
@@ -0,0 +1,145 @@
|
||||
package beacon
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
type BeaconCommitteeSelection struct {
|
||||
SelectionProof []byte
|
||||
Slot primitives.Slot
|
||||
ValidatorIndex primitives.ValidatorIndex
|
||||
}
|
||||
|
||||
type beaconCommitteeSelectionJson struct {
|
||||
SelectionProof string `json:"selection_proof"`
|
||||
Slot string `json:"slot"`
|
||||
ValidatorIndex string `json:"validator_index"`
|
||||
}
|
||||
|
||||
func (b *BeaconCommitteeSelection) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(beaconCommitteeSelectionJson{
|
||||
SelectionProof: hexutil.Encode(b.SelectionProof),
|
||||
Slot: strconv.FormatUint(uint64(b.Slot), 10),
|
||||
ValidatorIndex: strconv.FormatUint(uint64(b.ValidatorIndex), 10),
|
||||
})
|
||||
}
|
||||
|
||||
func (b *BeaconCommitteeSelection) UnmarshalJSON(input []byte) error {
|
||||
var bjson beaconCommitteeSelectionJson
|
||||
err := json.Unmarshal(input, &bjson)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to unmarshal beacon committee selection")
|
||||
}
|
||||
|
||||
slot, err := strconv.ParseUint(bjson.Slot, 10, 64)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to parse slot")
|
||||
}
|
||||
|
||||
vIdx, err := strconv.ParseUint(bjson.ValidatorIndex, 10, 64)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to parse validator index")
|
||||
}
|
||||
|
||||
selectionProof, err := hexutil.Decode(bjson.SelectionProof)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to parse selection proof")
|
||||
}
|
||||
|
||||
b.Slot = primitives.Slot(slot)
|
||||
b.SelectionProof = selectionProof
|
||||
b.ValidatorIndex = primitives.ValidatorIndex(vIdx)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type SyncCommitteeSelection struct {
|
||||
SelectionProof []byte
|
||||
Slot primitives.Slot
|
||||
SubcommitteeIndex primitives.CommitteeIndex
|
||||
ValidatorIndex primitives.ValidatorIndex
|
||||
}
|
||||
|
||||
type syncCommitteeSelectionJson struct {
|
||||
SelectionProof string `json:"selection_proof"`
|
||||
Slot string `json:"slot"`
|
||||
SubcommitteeIndex string `json:"subcommittee_index"`
|
||||
ValidatorIndex string `json:"validator_index"`
|
||||
}
|
||||
|
||||
func (s *SyncCommitteeSelection) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(syncCommitteeSelectionJson{
|
||||
SelectionProof: hexutil.Encode(s.SelectionProof),
|
||||
Slot: strconv.FormatUint(uint64(s.Slot), 10),
|
||||
SubcommitteeIndex: strconv.FormatUint(uint64(s.SubcommitteeIndex), 10),
|
||||
ValidatorIndex: strconv.FormatUint(uint64(s.ValidatorIndex), 10),
|
||||
})
|
||||
}
|
||||
|
||||
func (s *SyncCommitteeSelection) UnmarshalJSON(input []byte) error {
|
||||
var resJson syncCommitteeSelectionJson
|
||||
err := json.Unmarshal(input, &resJson)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to unmarshal sync committee selection")
|
||||
}
|
||||
|
||||
slot, err := strconv.ParseUint(resJson.Slot, 10, 64)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to parse slot")
|
||||
}
|
||||
|
||||
vIdx, err := strconv.ParseUint(resJson.ValidatorIndex, 10, 64)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to parse validator index")
|
||||
}
|
||||
|
||||
subcommIdx, err := strconv.ParseUint(resJson.SubcommitteeIndex, 10, 64)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to parse subcommittee index")
|
||||
}
|
||||
|
||||
selectionProof, err := hexutil.Decode(resJson.SelectionProof)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to parse selection proof")
|
||||
}
|
||||
|
||||
s.Slot = primitives.Slot(slot)
|
||||
s.SelectionProof = selectionProof
|
||||
s.ValidatorIndex = primitives.ValidatorIndex(vIdx)
|
||||
s.SubcommitteeIndex = primitives.CommitteeIndex(subcommIdx)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type AggregatedSelectionResponse struct {
|
||||
Data []BeaconCommitteeSelection `json:"data"`
|
||||
}
|
||||
|
||||
type AggregatedSyncSelectionResponse struct {
|
||||
Data []SyncCommitteeSelection `json:"data"`
|
||||
}
|
||||
|
||||
type AttesterDuty struct {
|
||||
CommitteeIndex primitives.CommitteeIndex
|
||||
Slot primitives.Slot
|
||||
CommitteeLength uint64
|
||||
ValidatorCommitteeIndex uint64
|
||||
CommitteesAtSlot uint64
|
||||
}
|
||||
|
||||
type ValidatorForDuty struct {
|
||||
Pubkey []byte
|
||||
Index primitives.ValidatorIndex
|
||||
Status ethpb.ValidatorStatus
|
||||
}
|
||||
|
||||
type ValidatorCount struct {
|
||||
Status string
|
||||
Count uint64
|
||||
}
|
||||
34
api/client/beacon/template.go
Normal file
34
api/client/beacon/template.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package beacon
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
type templateFn func(StateOrBlockId) string
|
||||
|
||||
var getBlockRootTpl templateFn
|
||||
var getForkTpl templateFn
|
||||
|
||||
func init() {
|
||||
// idTemplate is used to create template functions that can interpolate StateOrBlockId values.
|
||||
idTemplate := func(ts string) func(StateOrBlockId) string {
|
||||
t := template.Must(template.New("").Parse(ts))
|
||||
f := func(id StateOrBlockId) string {
|
||||
b := bytes.NewBuffer(nil)
|
||||
err := t.Execute(b, struct{ Id string }{Id: string(id)})
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("invalid idTemplate: %s", ts))
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
// run the template to ensure that it is valid
|
||||
// this should happen load time (using package scoped vars) to ensure runtime errors aren't possible
|
||||
_ = f(IdGenesis)
|
||||
return f
|
||||
}
|
||||
|
||||
getBlockRootTpl = idTemplate(getBlockRootPath)
|
||||
getForkTpl = idTemplate(getForkForStatePath)
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["mock.go"],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/api/client/beacon/testing",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//api/client/beacon/iface:go_default_library",
|
||||
"@org_uber_go_mock//gomock:go_default_library",
|
||||
],
|
||||
)
|
||||
@@ -3,32 +3,27 @@ load("@prysm//tools/go:def.bzl", "go_library", "go_test")
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"activation.go",
|
||||
"attestation_data.go",
|
||||
"beacon_api_beacon_chain_client.go",
|
||||
"beacon_api_helpers.go",
|
||||
"beacon_api_node_client.go",
|
||||
"beacon_api_validator_client.go",
|
||||
"beacon_block_converter.go",
|
||||
"beacon_block_json_helpers.go",
|
||||
"beacon_block_proto_helpers.go",
|
||||
"beacon_committee_selections.go",
|
||||
"client.go",
|
||||
"domain_data.go",
|
||||
"doppelganger.go",
|
||||
"duties.go",
|
||||
"genesis.go",
|
||||
"get_beacon_block.go",
|
||||
"grpc_client.go",
|
||||
"index.go",
|
||||
"json_rest_handler.go",
|
||||
"interfaces.go",
|
||||
"log.go",
|
||||
"metrics.go",
|
||||
"prepare_beacon_proposer.go",
|
||||
"propose_attestation.go",
|
||||
"propose_beacon_block.go",
|
||||
"propose_exit.go",
|
||||
"prysm_beacon_chain_client.go",
|
||||
"registration.go",
|
||||
"state_validators.go",
|
||||
"rest_client.go",
|
||||
"status.go",
|
||||
"stream_blocks.go",
|
||||
"submit_aggregate_selection_proof.go",
|
||||
@@ -38,26 +33,32 @@ go_library(
|
||||
"sync_committee.go",
|
||||
"sync_committee_selections.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api",
|
||||
visibility = ["//validator:__subpackages__"],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/api/client/beacon/validator_api",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//api:go_default_library",
|
||||
"//api/client:go_default_library",
|
||||
"//api/client/apiutil:go_default_library",
|
||||
"//api/client/beacon:go_default_library",
|
||||
"//api/client/beacon/node:go_default_library",
|
||||
"//api/client/beacon/prysm_api:go_default_library",
|
||||
"//api/client/beacon/shared_providers:go_default_library",
|
||||
"//api/client/event:go_default_library",
|
||||
"//api/server/structs:go_default_library",
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/core/signing:go_default_library",
|
||||
"//config/features:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//consensus-types/validator:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//monitoring/tracing/trace:go_default_library",
|
||||
"//network/forks:go_default_library",
|
||||
"//network/httputil:go_default_library",
|
||||
"//proto/engine/v1:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//runtime/version:go_default_library",
|
||||
"//time/slots:go_default_library",
|
||||
"//validator/client/iface:go_default_library",
|
||||
"//validator/helpers:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
"@com_github_golang_protobuf//ptypes/empty",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
@@ -65,46 +66,41 @@ go_library(
|
||||
"@com_github_prometheus_client_golang//prometheus/promauto:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@org_golang_google_grpc//:go_default_library",
|
||||
"@org_golang_google_protobuf//types/known/timestamppb:go_default_library",
|
||||
"@org_golang_x_sync//errgroup:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
size = "small",
|
||||
srcs = [
|
||||
"activation_test.go",
|
||||
"attestation_data_test.go",
|
||||
"beacon_api_beacon_chain_client_test.go",
|
||||
"beacon_api_helpers_test.go",
|
||||
"beacon_api_node_client_test.go",
|
||||
"beacon_api_validator_client_test.go",
|
||||
"beacon_block_converter_test.go",
|
||||
"beacon_block_json_helpers_test.go",
|
||||
"beacon_block_proto_helpers_test.go",
|
||||
"beacon_committee_selections_test.go",
|
||||
"domain_data_test.go",
|
||||
"doppelganger_test.go",
|
||||
"duties_test.go",
|
||||
"genesis_test.go",
|
||||
"get_beacon_block_test.go",
|
||||
"grpc_client_test.go",
|
||||
"index_test.go",
|
||||
"json_rest_handler_test.go",
|
||||
"prepare_beacon_proposer_test.go",
|
||||
"propose_attestation_test.go",
|
||||
"propose_beacon_block_altair_test.go",
|
||||
"propose_beacon_block_bellatrix_test.go",
|
||||
"propose_beacon_block_blinded_bellatrix_test.go",
|
||||
"propose_beacon_block_blinded_capella_test.go",
|
||||
"propose_beacon_block_blinded_deneb_test.go",
|
||||
"propose_beacon_block_blinded_electra_test.go",
|
||||
"propose_beacon_block_blinded_fulu_test.go",
|
||||
"propose_beacon_block_capella_test.go",
|
||||
"propose_beacon_block_deneb_test.go",
|
||||
"propose_beacon_block_electra_test.go",
|
||||
"propose_beacon_block_fulu_test.go",
|
||||
"propose_beacon_block_phase0_test.go",
|
||||
"propose_beacon_block_test.go",
|
||||
"propose_exit_test.go",
|
||||
"registration_test.go",
|
||||
"state_validators_test.go",
|
||||
"rest_client_test.go",
|
||||
"status_test.go",
|
||||
"stream_blocks_test.go",
|
||||
"submit_aggregate_selection_proof_test.go",
|
||||
@@ -113,32 +109,38 @@ go_test(
|
||||
"subscribe_committee_subnets_test.go",
|
||||
"sync_committee_selections_test.go",
|
||||
"sync_committee_test.go",
|
||||
"validator_count_test.go",
|
||||
"wait_for_chain_start_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//api:go_default_library",
|
||||
"//api/client:go_default_library",
|
||||
"//api/client/apiutil:go_default_library",
|
||||
"//api/client/beacon:go_default_library",
|
||||
"//api/client/beacon/mock:go_default_library",
|
||||
"//api/client/beacon/node:go_default_library",
|
||||
"//api/client/beacon/prysm_api:go_default_library",
|
||||
"//api/client/beacon/shared_providers:go_default_library",
|
||||
"//api/client/beacon/validator_api/test_helpers:go_default_library",
|
||||
"//api/client/event:go_default_library",
|
||||
"//api/server/structs:go_default_library",
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/rpc/eth/shared/testing:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//consensus-types/validator:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//network/httputil:go_default_library",
|
||||
"//proto/engine/v1:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//runtime/version:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/mock:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"//time/slots:go_default_library",
|
||||
"//validator/client/beacon-api/mock:go_default_library",
|
||||
"//validator/client/beacon-api/test-helpers:go_default_library",
|
||||
"//validator/client/iface:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
"@com_github_golang_protobuf//ptypes/empty",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
|
||||
"@org_golang_google_protobuf//types/known/emptypb:go_default_library",
|
||||
"@org_golang_google_protobuf//types/known/timestamppb:go_default_library",
|
||||
"@org_uber_go_mock//gomock:go_default_library",
|
||||
],
|
||||
)
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -7,12 +7,13 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/apiutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
func (c beaconApiValidatorClient) getAttestationData(
|
||||
func (c *beaconApiValidatorClient) attestationData(
|
||||
ctx context.Context,
|
||||
reqSlot primitives.Slot,
|
||||
reqCommitteeIndex primitives.CommitteeIndex,
|
||||
@@ -21,7 +22,7 @@ func (c beaconApiValidatorClient) getAttestationData(
|
||||
params.Add("slot", strconv.FormatUint(uint64(reqSlot), 10))
|
||||
params.Add("committee_index", strconv.FormatUint(uint64(reqCommitteeIndex), 10))
|
||||
|
||||
query := buildURL("/eth/v1/validator/attestation_data", params)
|
||||
query := apiutil.BuildURL("/eth/v1/validator/attestation_data", params)
|
||||
produceAttestationDataResponseJson := structs.GetAttestationDataResponse{}
|
||||
|
||||
if err := c.jsonRestHandler.Get(ctx, query, &produceAttestationDataResponseJson); err != nil {
|
||||
@@ -38,7 +39,7 @@ func (c beaconApiValidatorClient) getAttestationData(
|
||||
return nil, errors.Wrapf(err, "failed to parse attestation committee index: %s", attestationData.CommitteeIndex)
|
||||
}
|
||||
|
||||
if !validRoot(attestationData.BeaconBlockRoot) {
|
||||
if !apiutil.ValidRoot(attestationData.BeaconBlockRoot) {
|
||||
return nil, errors.Errorf("invalid beacon block root: %s", attestationData.BeaconBlockRoot)
|
||||
}
|
||||
|
||||
@@ -61,7 +62,7 @@ func (c beaconApiValidatorClient) getAttestationData(
|
||||
return nil, errors.Wrapf(err, "failed to parse attestation source epoch: %s", attestationData.Source.Epoch)
|
||||
}
|
||||
|
||||
if !validRoot(attestationData.Source.Root) {
|
||||
if !apiutil.ValidRoot(attestationData.Source.Root) {
|
||||
return nil, errors.Errorf("invalid attestation source root: %s", attestationData.Source.Root)
|
||||
}
|
||||
|
||||
@@ -79,7 +80,7 @@ func (c beaconApiValidatorClient) getAttestationData(
|
||||
return nil, errors.Wrapf(err, "failed to parse attestation target epoch: %s", attestationData.Target.Epoch)
|
||||
}
|
||||
|
||||
if !validRoot(attestationData.Target.Root) {
|
||||
if !apiutil.ValidRoot(attestationData.Target.Root) {
|
||||
return nil, errors.Errorf("invalid attestation target root: %s", attestationData.Target.Root)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -8,11 +8,11 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/mock"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api/mock"
|
||||
"go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
@@ -33,7 +33,7 @@ func TestGetAttestationData_ValidAttestation(t *testing.T) {
|
||||
produceAttestationDataResponseJson := structs.GetAttestationDataResponse{}
|
||||
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("/eth/v1/validator/attestation_data?committee_index=%d&slot=%d", expectedCommitteeIndex, expectedSlot),
|
||||
&produceAttestationDataResponseJson,
|
||||
).Return(
|
||||
@@ -58,7 +58,7 @@ func TestGetAttestationData_ValidAttestation(t *testing.T) {
|
||||
).Times(1)
|
||||
|
||||
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
|
||||
resp, err := validatorClient.getAttestationData(ctx, primitives.Slot(expectedSlot), primitives.CommitteeIndex(expectedCommitteeIndex))
|
||||
resp, err := validatorClient.attestationData(ctx, primitives.Slot(expectedSlot), primitives.CommitteeIndex(expectedCommitteeIndex))
|
||||
assert.NoError(t, err)
|
||||
|
||||
require.NotNil(t, resp)
|
||||
@@ -183,7 +183,7 @@ func TestGetAttestationData_InvalidData(t *testing.T) {
|
||||
produceAttestationDataResponseJson := structs.GetAttestationDataResponse{}
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
"/eth/v1/validator/attestation_data?committee_index=2&slot=1",
|
||||
&produceAttestationDataResponseJson,
|
||||
).Return(
|
||||
@@ -194,7 +194,7 @@ func TestGetAttestationData_InvalidData(t *testing.T) {
|
||||
).Times(1)
|
||||
|
||||
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
|
||||
_, err := validatorClient.getAttestationData(ctx, 1, 2)
|
||||
_, err := validatorClient.attestationData(ctx, 1, 2)
|
||||
assert.ErrorContains(t, testCase.expectedErrorMessage, err)
|
||||
})
|
||||
}
|
||||
@@ -212,7 +212,7 @@ func TestGetAttestationData_JsonResponseError(t *testing.T) {
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
produceAttestationDataResponseJson := structs.GetAttestationDataResponse{}
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("/eth/v1/validator/attestation_data?committee_index=%d&slot=%d", committeeIndex, slot),
|
||||
&produceAttestationDataResponseJson,
|
||||
).Return(
|
||||
@@ -220,11 +220,11 @@ func TestGetAttestationData_JsonResponseError(t *testing.T) {
|
||||
).Times(1)
|
||||
|
||||
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
|
||||
_, err := validatorClient.getAttestationData(ctx, slot, committeeIndex)
|
||||
_, err := validatorClient.attestationData(ctx, slot, committeeIndex)
|
||||
assert.ErrorContains(t, "some specific json response error", err)
|
||||
}
|
||||
|
||||
func generateValidAttestation(slot uint64, committeeIndex uint64) structs.GetAttestationDataResponse {
|
||||
func generateValidAttestation(slot, committeeIndex uint64) structs.GetAttestationDataResponse {
|
||||
return structs.GetAttestationDataResponse{
|
||||
Data: &structs.AttestationData{
|
||||
Slot: strconv.FormatUint(slot, 10),
|
||||
@@ -1,18 +1,14 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
neturl "net/url"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
@@ -28,27 +24,7 @@ var beaconAPITogRPCValidatorStatus = map[string]ethpb.ValidatorStatus{
|
||||
"withdrawal_done": ethpb.ValidatorStatus_EXITED,
|
||||
}
|
||||
|
||||
func validRoot(root string) bool {
|
||||
matchesRegex, err := regexp.MatchString("^0x[a-fA-F0-9]{64}$", root)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return matchesRegex
|
||||
}
|
||||
|
||||
func uint64ToString[T uint64 | primitives.Slot | primitives.ValidatorIndex | primitives.CommitteeIndex | primitives.Epoch](val T) string {
|
||||
return strconv.FormatUint(uint64(val), 10)
|
||||
}
|
||||
|
||||
func buildURL(path string, queryParams ...neturl.Values) string {
|
||||
if len(queryParams) == 0 {
|
||||
return path
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s?%s", path, queryParams[0].Encode())
|
||||
}
|
||||
|
||||
func (c *beaconApiValidatorClient) getFork(ctx context.Context) (*structs.GetStateForkResponse, error) {
|
||||
func (c *beaconApiValidatorClient) fork(ctx context.Context) (*structs.GetStateForkResponse, error) {
|
||||
const endpoint = "/eth/v1/beacon/states/head/fork"
|
||||
|
||||
stateForkResponseJson := &structs.GetStateForkResponse{}
|
||||
@@ -60,7 +36,7 @@ func (c *beaconApiValidatorClient) getFork(ctx context.Context) (*structs.GetSta
|
||||
return stateForkResponseJson, nil
|
||||
}
|
||||
|
||||
func (c *beaconApiValidatorClient) getHeaders(ctx context.Context) (*structs.GetBlockHeadersResponse, error) {
|
||||
func (c *beaconApiValidatorClient) headers(ctx context.Context) (*structs.GetBlockHeadersResponse, error) {
|
||||
const endpoint = "/eth/v1/beacon/headers"
|
||||
|
||||
blockHeadersResponseJson := &structs.GetBlockHeadersResponse{}
|
||||
@@ -72,7 +48,7 @@ func (c *beaconApiValidatorClient) getHeaders(ctx context.Context) (*structs.Get
|
||||
return blockHeadersResponseJson, nil
|
||||
}
|
||||
|
||||
func (c *beaconApiValidatorClient) getLiveness(ctx context.Context, epoch primitives.Epoch, validatorIndexes []string) (*structs.GetLivenessResponse, error) {
|
||||
func (c *beaconApiValidatorClient) liveness(ctx context.Context, epoch primitives.Epoch, validatorIndexes []string) (*structs.GetLivenessResponse, error) {
|
||||
const endpoint = "/eth/v1/validator/liveness/"
|
||||
url := endpoint + strconv.FormatUint(uint64(epoch), 10)
|
||||
|
||||
@@ -90,7 +66,7 @@ func (c *beaconApiValidatorClient) getLiveness(ctx context.Context, epoch primit
|
||||
return livenessResponseJson, nil
|
||||
}
|
||||
|
||||
func (c *beaconApiValidatorClient) getSyncing(ctx context.Context) (*structs.SyncStatusResponse, error) {
|
||||
func (c *beaconApiValidatorClient) syncing(ctx context.Context) (*structs.SyncStatusResponse, error) {
|
||||
const endpoint = "/eth/v1/node/syncing"
|
||||
|
||||
syncingResponseJson := &structs.SyncStatusResponse{}
|
||||
@@ -103,7 +79,7 @@ func (c *beaconApiValidatorClient) getSyncing(ctx context.Context) (*structs.Syn
|
||||
}
|
||||
|
||||
func (c *beaconApiValidatorClient) isSyncing(ctx context.Context) (bool, error) {
|
||||
response, err := c.getSyncing(ctx)
|
||||
response, err := c.syncing(ctx)
|
||||
if err != nil || response == nil || response.Data == nil {
|
||||
return true, errors.Wrapf(err, "failed to get syncing status")
|
||||
}
|
||||
@@ -112,7 +88,7 @@ func (c *beaconApiValidatorClient) isSyncing(ctx context.Context) (bool, error)
|
||||
}
|
||||
|
||||
func (c *beaconApiValidatorClient) isOptimistic(ctx context.Context) (bool, error) {
|
||||
response, err := c.getSyncing(ctx)
|
||||
response, err := c.syncing(ctx)
|
||||
if err != nil || response == nil || response.Data == nil {
|
||||
return true, errors.Wrapf(err, "failed to get syncing status")
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -8,11 +8,12 @@ import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/api/apiutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/mock"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api/mock"
|
||||
"go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
@@ -56,7 +57,7 @@ func TestBeaconApiHelpers(t *testing.T) {
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert.Equal(t, tt.valid, validRoot(tt.input))
|
||||
assert.Equal(t, tt.valid, apiutil.ValidRoot(tt.input))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -65,16 +66,16 @@ func TestBeaconApiHelpers_TestUint64ToString(t *testing.T) {
|
||||
const expectedResult = "1234"
|
||||
const val = uint64(1234)
|
||||
|
||||
assert.Equal(t, expectedResult, uint64ToString(val))
|
||||
assert.Equal(t, expectedResult, uint64ToString(primitives.Slot(val)))
|
||||
assert.Equal(t, expectedResult, uint64ToString(primitives.ValidatorIndex(val)))
|
||||
assert.Equal(t, expectedResult, uint64ToString(primitives.CommitteeIndex(val)))
|
||||
assert.Equal(t, expectedResult, uint64ToString(primitives.Epoch(val)))
|
||||
assert.Equal(t, expectedResult, apiutil.Uint64ToString(val))
|
||||
assert.Equal(t, expectedResult, apiutil.Uint64ToString(primitives.Slot(val)))
|
||||
assert.Equal(t, expectedResult, apiutil.Uint64ToString(primitives.ValidatorIndex(val)))
|
||||
assert.Equal(t, expectedResult, apiutil.Uint64ToString(primitives.CommitteeIndex(val)))
|
||||
assert.Equal(t, expectedResult, apiutil.Uint64ToString(primitives.Epoch(val)))
|
||||
}
|
||||
|
||||
func TestBuildURL_NoParams(t *testing.T) {
|
||||
wanted := "/aaa/bbb/ccc"
|
||||
actual := buildURL("/aaa/bbb/ccc")
|
||||
actual := apiutil.BuildURL("/aaa/bbb/ccc")
|
||||
assert.Equal(t, wanted, actual)
|
||||
}
|
||||
|
||||
@@ -85,7 +86,7 @@ func TestBuildURL_WithParams(t *testing.T) {
|
||||
params.Add("zzzz", "3")
|
||||
|
||||
wanted := "/aaa/bbb/ccc?xxxx=1&yyyy=2&zzzz=3"
|
||||
actual := buildURL("/aaa/bbb/ccc", params)
|
||||
actual := apiutil.BuildURL("/aaa/bbb/ccc", params)
|
||||
assert.Equal(t, wanted, actual)
|
||||
}
|
||||
|
||||
@@ -109,7 +110,7 @@ func TestGetFork_Nominal(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
forkEndpoint,
|
||||
&stateForkResponseJson,
|
||||
).Return(
|
||||
@@ -123,7 +124,7 @@ func TestGetFork_Nominal(t *testing.T) {
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
}
|
||||
|
||||
fork, err := validatorClient.getFork(ctx)
|
||||
fork, err := validatorClient.fork(ctx)
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, &expected, fork)
|
||||
}
|
||||
@@ -137,7 +138,7 @@ func TestGetFork_Invalid(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
forkEndpoint,
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
@@ -148,7 +149,7 @@ func TestGetFork_Invalid(t *testing.T) {
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
}
|
||||
|
||||
_, err := validatorClient.getFork(ctx)
|
||||
_, err := validatorClient.fork(ctx)
|
||||
require.ErrorContains(t, "custom error", err)
|
||||
}
|
||||
|
||||
@@ -176,7 +177,7 @@ func TestGetHeaders_Nominal(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
headersEndpoint,
|
||||
&blockHeadersResponseJson,
|
||||
).Return(
|
||||
@@ -190,7 +191,7 @@ func TestGetHeaders_Nominal(t *testing.T) {
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
}
|
||||
|
||||
headers, err := validatorClient.getHeaders(ctx)
|
||||
headers, err := validatorClient.headers(ctx)
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, &expected, headers)
|
||||
}
|
||||
@@ -204,7 +205,7 @@ func TestGetHeaders_Invalid(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
headersEndpoint,
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
@@ -215,7 +216,7 @@ func TestGetHeaders_Invalid(t *testing.T) {
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
}
|
||||
|
||||
_, err := validatorClient.getHeaders(ctx)
|
||||
_, err := validatorClient.headers(ctx)
|
||||
require.ErrorContains(t, "custom error", err)
|
||||
}
|
||||
|
||||
@@ -248,7 +249,7 @@ func TestGetLiveness_Nominal(t *testing.T) {
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
livenessEndpoint,
|
||||
nil,
|
||||
bytes.NewBuffer(marshalledIndexes),
|
||||
@@ -261,7 +262,7 @@ func TestGetLiveness_Nominal(t *testing.T) {
|
||||
).Times(1)
|
||||
|
||||
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
|
||||
liveness, err := validatorClient.getLiveness(ctx, 42, indexes)
|
||||
liveness, err := validatorClient.liveness(ctx, 42, indexes)
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, &expected, liveness)
|
||||
@@ -275,7 +276,7 @@ func TestGetLiveness_Invalid(t *testing.T) {
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
livenessEndpoint,
|
||||
nil,
|
||||
gomock.Any(),
|
||||
@@ -285,12 +286,12 @@ func TestGetLiveness_Invalid(t *testing.T) {
|
||||
).Times(1)
|
||||
|
||||
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
|
||||
_, err := validatorClient.getLiveness(ctx, 42, nil)
|
||||
_, err := validatorClient.liveness(ctx, 42, nil)
|
||||
|
||||
require.ErrorContains(t, "custom error", err)
|
||||
}
|
||||
|
||||
const syncingEnpoint = "/eth/v1/node/syncing"
|
||||
const syncingEndpoint = "/eth/v1/node/syncing"
|
||||
|
||||
func TestGetIsSyncing_Nominal(t *testing.T) {
|
||||
testCases := []struct {
|
||||
@@ -324,8 +325,8 @@ func TestGetIsSyncing_Nominal(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
ctx,
|
||||
syncingEnpoint,
|
||||
gomock.Any(),
|
||||
syncingEndpoint,
|
||||
&syncingResponseJson,
|
||||
).Return(
|
||||
nil,
|
||||
@@ -355,8 +356,8 @@ func TestGetIsSyncing_Invalid(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
ctx,
|
||||
syncingEnpoint,
|
||||
gomock.Any(),
|
||||
syncingEndpoint,
|
||||
&syncingResponseJson,
|
||||
).Return(
|
||||
errors.New("custom error"),
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
@@ -1,12 +1,12 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/validator_api/test_helpers"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
test_helpers "github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api/test-helpers"
|
||||
)
|
||||
|
||||
func TestGetBeaconBlockConverter_Phase0Valid(t *testing.T) {
|
||||
@@ -1,9 +1,10 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/apiutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
@@ -22,7 +23,7 @@ func jsonifyBlsToExecutionChanges(blsToExecutionChanges []*ethpb.SignedBLSToExec
|
||||
jsonBlsToExecutionChanges := make([]*structs.SignedBLSToExecutionChange, len(blsToExecutionChanges))
|
||||
for index, signedBlsToExecutionChange := range blsToExecutionChanges {
|
||||
blsToExecutionChangeJson := &structs.BLSToExecutionChange{
|
||||
ValidatorIndex: uint64ToString(signedBlsToExecutionChange.Message.ValidatorIndex),
|
||||
ValidatorIndex: apiutil.Uint64ToString(signedBlsToExecutionChange.Message.ValidatorIndex),
|
||||
FromBLSPubkey: hexutil.Encode(signedBlsToExecutionChange.Message.FromBlsPubkey),
|
||||
ToExecutionAddress: hexutil.Encode(signedBlsToExecutionChange.Message.ToExecutionAddress),
|
||||
}
|
||||
@@ -38,7 +39,7 @@ func jsonifyBlsToExecutionChanges(blsToExecutionChanges []*ethpb.SignedBLSToExec
|
||||
func jsonifyEth1Data(eth1Data *ethpb.Eth1Data) *structs.Eth1Data {
|
||||
return &structs.Eth1Data{
|
||||
BlockHash: hexutil.Encode(eth1Data.BlockHash),
|
||||
DepositCount: uint64ToString(eth1Data.DepositCount),
|
||||
DepositCount: apiutil.Uint64ToString(eth1Data.DepositCount),
|
||||
DepositRoot: hexutil.Encode(eth1Data.DepositRoot),
|
||||
}
|
||||
}
|
||||
@@ -51,6 +52,14 @@ func jsonifyAttestations(attestations []*ethpb.Attestation) []*structs.Attestati
|
||||
return jsonAttestations
|
||||
}
|
||||
|
||||
func jsonifySingleAttestations(attestations []*ethpb.SingleAttestation) []*structs.SingleAttestation {
|
||||
jsonAttestations := make([]*structs.SingleAttestation, len(attestations))
|
||||
for index, attestation := range attestations {
|
||||
jsonAttestations[index] = jsonifySingleAttestation(attestation)
|
||||
}
|
||||
return jsonAttestations
|
||||
}
|
||||
|
||||
func jsonifyAttesterSlashings(attesterSlashings []*ethpb.AttesterSlashing) []*structs.AttesterSlashing {
|
||||
jsonAttesterSlashings := make([]*structs.AttesterSlashing, len(attesterSlashings))
|
||||
for index, attesterSlashing := range attesterSlashings {
|
||||
@@ -73,7 +82,7 @@ func jsonifyDeposits(deposits []*ethpb.Deposit) []*structs.Deposit {
|
||||
|
||||
jsonDeposit := &structs.Deposit{
|
||||
Data: &structs.DepositData{
|
||||
Amount: uint64ToString(deposit.Data.Amount),
|
||||
Amount: apiutil.Uint64ToString(deposit.Data.Amount),
|
||||
Pubkey: hexutil.Encode(deposit.Data.PublicKey),
|
||||
Signature: hexutil.Encode(deposit.Data.Signature),
|
||||
WithdrawalCredentials: hexutil.Encode(deposit.Data.WithdrawalCredentials),
|
||||
@@ -103,8 +112,8 @@ func JsonifySignedVoluntaryExits(voluntaryExits []*ethpb.SignedVoluntaryExit) []
|
||||
for index, signedVoluntaryExit := range voluntaryExits {
|
||||
jsonSignedVoluntaryExit := &structs.SignedVoluntaryExit{
|
||||
Message: &structs.VoluntaryExit{
|
||||
Epoch: uint64ToString(signedVoluntaryExit.Exit.Epoch),
|
||||
ValidatorIndex: uint64ToString(signedVoluntaryExit.Exit.ValidatorIndex),
|
||||
Epoch: apiutil.Uint64ToString(signedVoluntaryExit.Exit.Epoch),
|
||||
ValidatorIndex: apiutil.Uint64ToString(signedVoluntaryExit.Exit.ValidatorIndex),
|
||||
},
|
||||
Signature: hexutil.Encode(signedVoluntaryExit.Signature),
|
||||
}
|
||||
@@ -118,8 +127,8 @@ func jsonifySignedBeaconBlockHeader(signedBeaconBlockHeader *ethpb.SignedBeaconB
|
||||
Message: &structs.BeaconBlockHeader{
|
||||
BodyRoot: hexutil.Encode(signedBeaconBlockHeader.Header.BodyRoot),
|
||||
ParentRoot: hexutil.Encode(signedBeaconBlockHeader.Header.ParentRoot),
|
||||
ProposerIndex: uint64ToString(signedBeaconBlockHeader.Header.ProposerIndex),
|
||||
Slot: uint64ToString(signedBeaconBlockHeader.Header.Slot),
|
||||
ProposerIndex: apiutil.Uint64ToString(signedBeaconBlockHeader.Header.ProposerIndex),
|
||||
Slot: apiutil.Uint64ToString(signedBeaconBlockHeader.Header.Slot),
|
||||
StateRoot: hexutil.Encode(signedBeaconBlockHeader.Header.StateRoot),
|
||||
},
|
||||
Signature: hexutil.Encode(signedBeaconBlockHeader.Signature),
|
||||
@@ -129,7 +138,7 @@ func jsonifySignedBeaconBlockHeader(signedBeaconBlockHeader *ethpb.SignedBeaconB
|
||||
func jsonifyIndexedAttestation(indexedAttestation *ethpb.IndexedAttestation) *structs.IndexedAttestation {
|
||||
attestingIndices := make([]string, len(indexedAttestation.AttestingIndices))
|
||||
for index, attestingIndex := range indexedAttestation.AttestingIndices {
|
||||
attestingIndex := uint64ToString(attestingIndex)
|
||||
attestingIndex := apiutil.Uint64ToString(attestingIndex)
|
||||
attestingIndices[index] = attestingIndex
|
||||
}
|
||||
|
||||
@@ -143,14 +152,14 @@ func jsonifyIndexedAttestation(indexedAttestation *ethpb.IndexedAttestation) *st
|
||||
func jsonifyAttestationData(attestationData *ethpb.AttestationData) *structs.AttestationData {
|
||||
return &structs.AttestationData{
|
||||
BeaconBlockRoot: hexutil.Encode(attestationData.BeaconBlockRoot),
|
||||
CommitteeIndex: uint64ToString(attestationData.CommitteeIndex),
|
||||
Slot: uint64ToString(attestationData.Slot),
|
||||
CommitteeIndex: apiutil.Uint64ToString(attestationData.CommitteeIndex),
|
||||
Slot: apiutil.Uint64ToString(attestationData.Slot),
|
||||
Source: &structs.Checkpoint{
|
||||
Epoch: uint64ToString(attestationData.Source.Epoch),
|
||||
Epoch: apiutil.Uint64ToString(attestationData.Source.Epoch),
|
||||
Root: hexutil.Encode(attestationData.Source.Root),
|
||||
},
|
||||
Target: &structs.Checkpoint{
|
||||
Epoch: uint64ToString(attestationData.Target.Epoch),
|
||||
Epoch: apiutil.Uint64ToString(attestationData.Target.Epoch),
|
||||
Root: hexutil.Encode(attestationData.Target.Root),
|
||||
},
|
||||
}
|
||||
@@ -164,10 +173,28 @@ func jsonifyAttestation(attestation *ethpb.Attestation) *structs.Attestation {
|
||||
}
|
||||
}
|
||||
|
||||
func jsonifyAttestationElectra(attestation *ethpb.AttestationElectra) *structs.AttestationElectra {
|
||||
return &structs.AttestationElectra{
|
||||
AggregationBits: hexutil.Encode(attestation.AggregationBits),
|
||||
Data: jsonifyAttestationData(attestation.Data),
|
||||
Signature: hexutil.Encode(attestation.Signature),
|
||||
CommitteeBits: hexutil.Encode(attestation.CommitteeBits),
|
||||
}
|
||||
}
|
||||
|
||||
func jsonifySingleAttestation(attestation *ethpb.SingleAttestation) *structs.SingleAttestation {
|
||||
return &structs.SingleAttestation{
|
||||
CommitteeIndex: apiutil.Uint64ToString(attestation.CommitteeId),
|
||||
AttesterIndex: apiutil.Uint64ToString(attestation.AttesterIndex),
|
||||
Data: jsonifyAttestationData(attestation.Data),
|
||||
Signature: hexutil.Encode(attestation.Signature),
|
||||
}
|
||||
}
|
||||
|
||||
func jsonifySignedAggregateAndProof(signedAggregateAndProof *ethpb.SignedAggregateAttestationAndProof) *structs.SignedAggregateAttestationAndProof {
|
||||
return &structs.SignedAggregateAttestationAndProof{
|
||||
Message: &structs.AggregateAttestationAndProof{
|
||||
AggregatorIndex: uint64ToString(signedAggregateAndProof.Message.AggregatorIndex),
|
||||
AggregatorIndex: apiutil.Uint64ToString(signedAggregateAndProof.Message.AggregatorIndex),
|
||||
Aggregate: jsonifyAttestation(signedAggregateAndProof.Message.Aggregate),
|
||||
SelectionProof: hexutil.Encode(signedAggregateAndProof.Message.SelectionProof),
|
||||
},
|
||||
@@ -175,6 +202,17 @@ func jsonifySignedAggregateAndProof(signedAggregateAndProof *ethpb.SignedAggrega
|
||||
}
|
||||
}
|
||||
|
||||
func jsonifySignedAggregateAndProofElectra(signedAggregateAndProof *ethpb.SignedAggregateAttestationAndProofElectra) *structs.SignedAggregateAttestationAndProofElectra {
|
||||
return &structs.SignedAggregateAttestationAndProofElectra{
|
||||
Message: &structs.AggregateAttestationAndProofElectra{
|
||||
AggregatorIndex: apiutil.Uint64ToString(signedAggregateAndProof.Message.AggregatorIndex),
|
||||
Aggregate: jsonifyAttestationElectra(signedAggregateAndProof.Message.Aggregate),
|
||||
SelectionProof: hexutil.Encode(signedAggregateAndProof.Message.SelectionProof),
|
||||
},
|
||||
Signature: hexutil.Encode(signedAggregateAndProof.Signature),
|
||||
}
|
||||
}
|
||||
|
||||
func jsonifyWithdrawals(withdrawals []*enginev1.Withdrawal) []*structs.Withdrawal {
|
||||
jsonWithdrawals := make([]*structs.Withdrawal, len(withdrawals))
|
||||
for index, withdrawal := range withdrawals {
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"testing"
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
@@ -197,6 +197,39 @@ func convertAttestationToProto(jsonAttestation *structs.Attestation) (*ethpb.Att
|
||||
}, nil
|
||||
}
|
||||
|
||||
func convertAttestationElectraToProto(jsonAttestation *structs.AttestationElectra) (*ethpb.AttestationElectra, error) {
|
||||
if jsonAttestation == nil {
|
||||
return nil, errors.New("json attestation is nil")
|
||||
}
|
||||
|
||||
aggregationBits, err := hexutil.Decode(jsonAttestation.AggregationBits)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to decode aggregation bits `%s`", jsonAttestation.AggregationBits)
|
||||
}
|
||||
|
||||
attestationData, err := convertAttestationDataToProto(jsonAttestation.Data)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get attestation data")
|
||||
}
|
||||
|
||||
signature, err := hexutil.Decode(jsonAttestation.Signature)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to decode attestation signature `%s`", jsonAttestation.Signature)
|
||||
}
|
||||
|
||||
committeeBits, err := hexutil.Decode(jsonAttestation.CommitteeBits)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to decode committee bits `%s`", jsonAttestation.CommitteeBits)
|
||||
}
|
||||
|
||||
return ðpb.AttestationElectra{
|
||||
AggregationBits: aggregationBits,
|
||||
Data: attestationData,
|
||||
Signature: signature,
|
||||
CommitteeBits: committeeBits,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func convertAttestationsToProto(jsonAttestations []*structs.Attestation) ([]*ethpb.Attestation, error) {
|
||||
var attestations []*ethpb.Attestation
|
||||
for index, jsonAttestation := range jsonAttestations {
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"testing"
|
||||
38
api/client/beacon/validator_api/client.go
Normal file
38
api/client/beacon/validator_api/client.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/node"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/prysm_api"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/shared_providers"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/features"
|
||||
validatorHelpers "github.com/prysmaticlabs/prysm/v5/validator/helpers"
|
||||
)
|
||||
|
||||
func NewClient(
|
||||
validatorConn validatorHelpers.NodeConnection,
|
||||
jsonRestHandler client.JsonRestHandler,
|
||||
opt ...ValidatorClientOpt,
|
||||
) Client {
|
||||
if features.Get().EnableBeaconRESTApi {
|
||||
return NewBeaconApiValidatorClient(jsonRestHandler, opt...)
|
||||
} else {
|
||||
return NewGrpcValidatorClient(validatorConn.GetGrpcClientConn())
|
||||
}
|
||||
}
|
||||
|
||||
func NewBeaconApiValidatorClient(jsonRestHandler client.JsonRestHandler, opts ...ValidatorClientOpt) Client {
|
||||
c := &beaconApiValidatorClient{
|
||||
genesisProvider: shared_providers.NewGenesis(jsonRestHandler),
|
||||
dutiesProvider: shared_providers.NewDuties(jsonRestHandler),
|
||||
stateValidatorsProvider: shared_providers.NewStateValidators(jsonRestHandler),
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
beaconBlockConverter: beaconApiBeaconBlockConverter{},
|
||||
prysmChainClient: prysm_api.NewPrysmChainRestClient(jsonRestHandler, node.NewNodeClientWithFallback(jsonRestHandler, nil)), //TODO: this is really bad design...
|
||||
isEventStreamRunning: false,
|
||||
}
|
||||
for _, o := range opts {
|
||||
o(c)
|
||||
}
|
||||
return c
|
||||
}
|
||||
@@ -1,17 +1,18 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/apiutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/signing"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/network/forks"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
func (c beaconApiValidatorClient) getDomainData(ctx context.Context, epoch primitives.Epoch, domainType [4]byte) (*ethpb.DomainResponse, error) {
|
||||
func (c *beaconApiValidatorClient) domainData(ctx context.Context, epoch primitives.Epoch, domainType [4]byte) (*ethpb.DomainResponse, error) {
|
||||
// Get the fork version from the given epoch
|
||||
fork, err := forks.Fork(epoch)
|
||||
if err != nil {
|
||||
@@ -19,12 +20,12 @@ func (c beaconApiValidatorClient) getDomainData(ctx context.Context, epoch primi
|
||||
}
|
||||
|
||||
// Get the genesis validator root
|
||||
genesis, err := c.genesisProvider.GetGenesis(ctx)
|
||||
genesis, err := c.genesisProvider.Genesis(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to get genesis info")
|
||||
}
|
||||
|
||||
if !validRoot(genesis.GenesisValidatorsRoot) {
|
||||
if !apiutil.ValidRoot(genesis.GenesisValidatorsRoot) {
|
||||
return nil, errors.Errorf("invalid genesis validators root: %s", genesis.GenesisValidatorsRoot)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -6,12 +6,12 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/mock"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api/mock"
|
||||
"go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
@@ -35,15 +35,15 @@ func TestGetDomainData_ValidDomainData(t *testing.T) {
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
// Make sure that GetGenesis() is called exactly once
|
||||
// Make sure that Genesis() is called exactly once
|
||||
genesisProvider := mock.NewMockGenesisProvider(ctrl)
|
||||
genesisProvider.EXPECT().GetGenesis(ctx).Return(
|
||||
genesisProvider.EXPECT().Genesis(gomock.Any()).Return(
|
||||
&structs.Genesis{GenesisValidatorsRoot: genesisValidatorRoot},
|
||||
nil,
|
||||
).Times(1)
|
||||
|
||||
validatorClient := &beaconApiValidatorClient{genesisProvider: genesisProvider}
|
||||
resp, err := validatorClient.getDomainData(ctx, epoch, domainType)
|
||||
resp, err := validatorClient.domainData(ctx, epoch, domainType)
|
||||
assert.NoError(t, err)
|
||||
require.NotNil(t, resp)
|
||||
|
||||
@@ -64,12 +64,12 @@ func TestGetDomainData_GenesisError(t *testing.T) {
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
// Make sure that GetGenesis() is called exactly once
|
||||
// Make sure that Genesis() is called exactly once
|
||||
genesisProvider := mock.NewMockGenesisProvider(ctrl)
|
||||
genesisProvider.EXPECT().GetGenesis(ctx).Return(nil, errors.New("foo error")).Times(1)
|
||||
genesisProvider.EXPECT().Genesis(gomock.Any()).Return(nil, errors.New("foo error")).Times(1)
|
||||
|
||||
validatorClient := &beaconApiValidatorClient{genesisProvider: genesisProvider}
|
||||
_, err := validatorClient.getDomainData(ctx, epoch, domainType)
|
||||
_, err := validatorClient.domainData(ctx, epoch, domainType)
|
||||
assert.ErrorContains(t, "failed to get genesis info", err)
|
||||
assert.ErrorContains(t, "foo error", err)
|
||||
}
|
||||
@@ -83,14 +83,14 @@ func TestGetDomainData_InvalidGenesisRoot(t *testing.T) {
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
// Make sure that GetGenesis() is called exactly once
|
||||
// Make sure that Genesis() is called exactly once
|
||||
genesisProvider := mock.NewMockGenesisProvider(ctrl)
|
||||
genesisProvider.EXPECT().GetGenesis(ctx).Return(
|
||||
genesisProvider.EXPECT().Genesis(gomock.Any()).Return(
|
||||
&structs.Genesis{GenesisValidatorsRoot: "foo"},
|
||||
nil,
|
||||
).Times(1)
|
||||
|
||||
validatorClient := &beaconApiValidatorClient{genesisProvider: genesisProvider}
|
||||
_, err := validatorClient.getDomainData(ctx, epoch, domainType)
|
||||
_, err := validatorClient.domainData(ctx, epoch, domainType)
|
||||
assert.ErrorContains(t, "invalid genesis validators root: foo", err)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -6,9 +6,8 @@ import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
@@ -73,7 +72,7 @@ func (c *beaconApiValidatorClient) checkDoppelGanger(ctx context.Context, in *et
|
||||
}
|
||||
|
||||
// Retrieve fork version -- Return early if we are in phase0.
|
||||
forkResponse, err := c.getFork(ctx)
|
||||
forkResponse, err := c.fork(ctx)
|
||||
if err != nil || forkResponse == nil || forkResponse.Data == nil {
|
||||
return nil, errors.Wrapf(err, "failed to get fork")
|
||||
}
|
||||
@@ -91,7 +90,7 @@ func (c *beaconApiValidatorClient) checkDoppelGanger(ctx context.Context, in *et
|
||||
}
|
||||
|
||||
// Retrieve current epoch.
|
||||
headers, err := c.getHeaders(ctx)
|
||||
headers, err := c.headers(ctx)
|
||||
if err != nil || headers == nil || headers.Data == nil || len(headers.Data) == 0 ||
|
||||
headers.Data[0].Header == nil || headers.Data[0].Header.Message == nil {
|
||||
return nil, errors.Wrapf(err, "failed to get headers")
|
||||
@@ -127,7 +126,7 @@ func (c *beaconApiValidatorClient) checkDoppelGanger(ctx context.Context, in *et
|
||||
}
|
||||
|
||||
// Retrieve correspondence between validator pubkey and index.
|
||||
stateValidators, err := c.stateValidatorsProvider.GetStateValidators(ctx, notRecentStringPubKeys, nil, nil)
|
||||
stateValidators, err := c.stateValidatorsProvider.StateValidators(ctx, notRecentStringPubKeys, nil, nil)
|
||||
if err != nil || stateValidators == nil || stateValidators.Data == nil {
|
||||
return nil, errors.Wrapf(err, "failed to get state validators")
|
||||
}
|
||||
@@ -156,13 +155,13 @@ func (c *beaconApiValidatorClient) checkDoppelGanger(ctx context.Context, in *et
|
||||
// since we assume that we are not in phase0.
|
||||
previousEpoch := currentEpoch - 1
|
||||
|
||||
indexToPreviousLiveness, err := c.getIndexToLiveness(ctx, previousEpoch, indexes)
|
||||
indexToPreviousLiveness, err := c.indexToLiveness(ctx, previousEpoch, indexes)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to get map from validator index to liveness for previous epoch %d", previousEpoch)
|
||||
}
|
||||
|
||||
// Get validators liveness for the current epoch.
|
||||
indexToCurrentLiveness, err := c.getIndexToLiveness(ctx, currentEpoch, indexes)
|
||||
indexToCurrentLiveness, err := c.indexToLiveness(ctx, currentEpoch, indexes)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to get map from validator index to liveness for current epoch %d", currentEpoch)
|
||||
}
|
||||
@@ -218,10 +217,10 @@ func buildResponse(
|
||||
}
|
||||
}
|
||||
|
||||
func (c *beaconApiValidatorClient) getIndexToLiveness(ctx context.Context, epoch primitives.Epoch, indexes []string) (map[string]bool, error) {
|
||||
livenessResponse, err := c.getLiveness(ctx, epoch, indexes)
|
||||
func (c *beaconApiValidatorClient) indexToLiveness(ctx context.Context, epoch primitives.Epoch, indexes []string) (map[string]bool, error) {
|
||||
livenessResponse, err := c.liveness(ctx, epoch, indexes)
|
||||
if err != nil || livenessResponse.Data == nil {
|
||||
return nil, errors.Wrapf(err, fmt.Sprintf("failed to get liveness for epoch %d", epoch))
|
||||
return nil, errors.Wrapf(err, "failed to get liveness for epoch %d", epoch)
|
||||
}
|
||||
|
||||
indexToLiveness := make(map[string]bool, len(livenessResponse.Data))
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -8,11 +8,11 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/mock"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api/mock"
|
||||
"go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
@@ -228,7 +228,7 @@ func TestCheckDoppelGanger_Nominal(t *testing.T) {
|
||||
{Index: "22222", Validator: &structs.Validator{Pubkey: stringPubKey2}}, // not recent - duplicate on previous epoch
|
||||
{Index: "33333", Validator: &structs.Validator{Pubkey: stringPubKey3}}, // not recent - duplicate on current epoch
|
||||
{Index: "44444", Validator: &structs.Validator{Pubkey: stringPubKey4}}, // not recent - duplicate on both previous and current epoch
|
||||
// No "55555" sicee corresponding validator does not exist
|
||||
// No "55555" since corresponding validator does not exist
|
||||
{Index: "66666", Validator: &structs.Validator{Pubkey: stringPubKey6}}, // not recent - not duplicate
|
||||
},
|
||||
},
|
||||
@@ -291,14 +291,12 @@ func TestCheckDoppelGanger_Nominal(t *testing.T) {
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
if testCase.getSyncingOutput != nil {
|
||||
syncingResponseJson := structs.SyncStatusResponse{}
|
||||
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
ctx,
|
||||
syncingEnpoint,
|
||||
gomock.Any(),
|
||||
syncingEndpoint,
|
||||
&syncingResponseJson,
|
||||
).Return(
|
||||
nil,
|
||||
@@ -312,7 +310,7 @@ func TestCheckDoppelGanger_Nominal(t *testing.T) {
|
||||
stateForkResponseJson := structs.GetStateForkResponse{}
|
||||
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
forkEndpoint,
|
||||
&stateForkResponseJson,
|
||||
).Return(
|
||||
@@ -327,7 +325,7 @@ func TestCheckDoppelGanger_Nominal(t *testing.T) {
|
||||
blockHeadersResponseJson := structs.GetBlockHeadersResponse{}
|
||||
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
headersEndpoint,
|
||||
&blockHeadersResponseJson,
|
||||
).Return(
|
||||
@@ -346,7 +344,7 @@ func TestCheckDoppelGanger_Nominal(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
iface.inputUrl,
|
||||
nil,
|
||||
bytes.NewBuffer(marshalledIndexes),
|
||||
@@ -363,8 +361,8 @@ func TestCheckDoppelGanger_Nominal(t *testing.T) {
|
||||
stateValidatorsProvider := mock.NewMockStateValidatorsProvider(ctrl)
|
||||
|
||||
if testCase.getStateValidatorsInterface != nil {
|
||||
stateValidatorsProvider.EXPECT().GetStateValidators(
|
||||
ctx,
|
||||
stateValidatorsProvider.EXPECT().StateValidators(
|
||||
gomock.Any(),
|
||||
testCase.getStateValidatorsInterface.input,
|
||||
nil,
|
||||
nil,
|
||||
@@ -489,7 +487,7 @@ func TestCheckDoppelGanger_Errors(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "getFork on error",
|
||||
name: "fork on error",
|
||||
expectedErrorMessage: "failed to get fork",
|
||||
inputValidatorRequests: standardInputValidatorRequests,
|
||||
getSyncingOutput: standardGetSyncingOutput,
|
||||
@@ -727,14 +725,12 @@ func TestCheckDoppelGanger_Errors(t *testing.T) {
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
if testCase.getSyncingOutput != nil {
|
||||
syncingResponseJson := structs.SyncStatusResponse{}
|
||||
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
ctx,
|
||||
syncingEnpoint,
|
||||
gomock.Any(),
|
||||
syncingEndpoint,
|
||||
&syncingResponseJson,
|
||||
).Return(
|
||||
testCase.getSyncingError,
|
||||
@@ -748,7 +744,7 @@ func TestCheckDoppelGanger_Errors(t *testing.T) {
|
||||
stateForkResponseJson := structs.GetStateForkResponse{}
|
||||
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
forkEndpoint,
|
||||
&stateForkResponseJson,
|
||||
).Return(
|
||||
@@ -763,7 +759,7 @@ func TestCheckDoppelGanger_Errors(t *testing.T) {
|
||||
blockHeadersResponseJson := structs.GetBlockHeadersResponse{}
|
||||
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
headersEndpoint,
|
||||
&blockHeadersResponseJson,
|
||||
).Return(
|
||||
@@ -777,8 +773,8 @@ func TestCheckDoppelGanger_Errors(t *testing.T) {
|
||||
stateValidatorsProvider := mock.NewMockStateValidatorsProvider(ctrl)
|
||||
|
||||
if testCase.getStateValidatorsInterface != nil {
|
||||
stateValidatorsProvider.EXPECT().GetStateValidators(
|
||||
ctx,
|
||||
stateValidatorsProvider.EXPECT().StateValidators(
|
||||
gomock.Any(),
|
||||
testCase.getStateValidatorsInterface.input,
|
||||
nil,
|
||||
nil,
|
||||
@@ -796,7 +792,7 @@ func TestCheckDoppelGanger_Errors(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
iface.inputUrl,
|
||||
nil,
|
||||
bytes.NewBuffer(marshalledIndexes),
|
||||
228
api/client/beacon/validator_api/duties.go
Normal file
228
api/client/beacon/validator_api/duties.go
Normal file
@@ -0,0 +1,228 @@
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/validator"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
func (c *beaconApiValidatorClient) duties(ctx context.Context, in *ethpb.DutiesRequest) (*ethpb.ValidatorDutiesContainer, error) {
|
||||
vals, err := c.validatorsForDuties(ctx, in.PublicKeys)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get validators for duties")
|
||||
}
|
||||
|
||||
// Sync committees are an Altair feature
|
||||
fetchSyncDuties := in.Epoch >= params.BeaconConfig().AltairForkEpoch
|
||||
|
||||
errCh := make(chan error, 1)
|
||||
|
||||
var currentEpochDuties []*ethpb.ValidatorDuty
|
||||
go func() {
|
||||
currentEpochDuties, err = c.dutiesForEpoch(ctx, in.Epoch, vals, fetchSyncDuties)
|
||||
if err != nil {
|
||||
errCh <- errors.Wrapf(err, "failed to get duties for current epoch `%d`", in.Epoch)
|
||||
return
|
||||
}
|
||||
errCh <- nil
|
||||
}()
|
||||
|
||||
nextEpochDuties, err := c.dutiesForEpoch(ctx, in.Epoch+1, vals, fetchSyncDuties)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to get duties for next epoch `%d`", in.Epoch+1)
|
||||
}
|
||||
|
||||
if err = <-errCh; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ðpb.ValidatorDutiesContainer{
|
||||
CurrentEpochDuties: currentEpochDuties,
|
||||
NextEpochDuties: nextEpochDuties,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *beaconApiValidatorClient) dutiesForEpoch(
|
||||
ctx context.Context,
|
||||
epoch primitives.Epoch,
|
||||
vals []beacon.ValidatorForDuty,
|
||||
fetchSyncDuties bool,
|
||||
) ([]*ethpb.ValidatorDuty, error) {
|
||||
indices := make([]primitives.ValidatorIndex, len(vals))
|
||||
for i, v := range vals {
|
||||
indices[i] = v.Index
|
||||
}
|
||||
|
||||
// Below variables MUST NOT be used in the main function before wg.Wait().
|
||||
// This is because they are populated in goroutines and wg.Wait()
|
||||
// will return only once all goroutines finish their execution.
|
||||
|
||||
// Mapping from a validator index to its attesting committee's index and slot
|
||||
attesterDutiesMapping := make(map[primitives.ValidatorIndex]beacon.AttesterDuty)
|
||||
// Set containing all validator indices that are part of a sync committee for this epoch
|
||||
syncDutiesMapping := make(map[primitives.ValidatorIndex]bool)
|
||||
// Mapping from a validator index to its proposal slot
|
||||
proposerDutySlots := make(map[primitives.ValidatorIndex][]primitives.Slot)
|
||||
|
||||
var wg errgroup.Group
|
||||
|
||||
wg.Go(func() error {
|
||||
attesterDuties, err := c.dutiesProvider.AttesterDuties(ctx, epoch, indices)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get attester duties for epoch `%d`", epoch)
|
||||
}
|
||||
|
||||
for _, duty := range attesterDuties {
|
||||
validatorIndex, err := strconv.ParseUint(duty.ValidatorIndex, 10, 64)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to parse attester validator index `%s`", duty.ValidatorIndex)
|
||||
}
|
||||
slot, err := strconv.ParseUint(duty.Slot, 10, 64)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to parse attester slot `%s`", duty.Slot)
|
||||
}
|
||||
committeeIndex, err := strconv.ParseUint(duty.CommitteeIndex, 10, 64)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to parse attester committee index `%s`", duty.CommitteeIndex)
|
||||
}
|
||||
committeeLength, err := strconv.ParseUint(duty.CommitteeLength, 10, 64)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to parse attester committee length `%s`", duty.CommitteeLength)
|
||||
}
|
||||
validatorCommitteeIndex, err := strconv.ParseUint(duty.ValidatorCommitteeIndex, 10, 64)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to parse attester validator committee index `%s`", duty.ValidatorCommitteeIndex)
|
||||
}
|
||||
committeesAtSlot, err := strconv.ParseUint(duty.CommitteesAtSlot, 10, 64)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to parse attester committees at slot `%s`", duty.CommitteesAtSlot)
|
||||
}
|
||||
attesterDutiesMapping[primitives.ValidatorIndex(validatorIndex)] = beacon.AttesterDuty{
|
||||
Slot: primitives.Slot(slot),
|
||||
CommitteeIndex: primitives.CommitteeIndex(committeeIndex),
|
||||
CommitteeLength: committeeLength,
|
||||
ValidatorCommitteeIndex: validatorCommitteeIndex,
|
||||
CommitteesAtSlot: committeesAtSlot,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if fetchSyncDuties {
|
||||
wg.Go(func() error {
|
||||
syncDuties, err := c.dutiesProvider.SyncDuties(ctx, epoch, indices)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get sync duties for epoch `%d`", epoch)
|
||||
}
|
||||
for _, syncDuty := range syncDuties {
|
||||
validatorIndex, err := strconv.ParseUint(syncDuty.ValidatorIndex, 10, 64)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to parse sync validator index `%s`", syncDuty.ValidatorIndex)
|
||||
}
|
||||
syncDutiesMapping[primitives.ValidatorIndex(validatorIndex)] = true
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
wg.Go(func() error {
|
||||
proposerDuties, err := c.dutiesProvider.ProposerDuties(ctx, epoch)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get proposer duties for epoch `%d`", epoch)
|
||||
}
|
||||
|
||||
for _, proposerDuty := range proposerDuties {
|
||||
validatorIndex, err := strconv.ParseUint(proposerDuty.ValidatorIndex, 10, 64)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to parse proposer validator index `%s`", proposerDuty.ValidatorIndex)
|
||||
}
|
||||
slot, err := strconv.ParseUint(proposerDuty.Slot, 10, 64)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to parse proposer slot `%s`", proposerDuty.Slot)
|
||||
}
|
||||
proposerDutySlots[primitives.ValidatorIndex(validatorIndex)] =
|
||||
append(proposerDutySlots[primitives.ValidatorIndex(validatorIndex)], primitives.Slot(slot))
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err := wg.Wait(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
duties := make([]*ethpb.ValidatorDuty, len(vals))
|
||||
for i, v := range vals {
|
||||
att, ok := attesterDutiesMapping[v.Index]
|
||||
if !ok {
|
||||
log.Debugf("failed to find attester duty for validator `%d`", v.Index)
|
||||
}
|
||||
|
||||
duties[i] = ðpb.ValidatorDuty{
|
||||
ValidatorCommitteeIndex: att.ValidatorCommitteeIndex,
|
||||
CommitteeLength: att.CommitteeLength,
|
||||
CommitteeIndex: att.CommitteeIndex,
|
||||
AttesterSlot: att.Slot,
|
||||
CommitteesAtSlot: att.CommitteesAtSlot,
|
||||
ProposerSlots: proposerDutySlots[v.Index],
|
||||
PublicKey: v.Pubkey,
|
||||
Status: v.Status,
|
||||
ValidatorIndex: v.Index,
|
||||
IsSyncCommittee: syncDutiesMapping[v.Index],
|
||||
}
|
||||
}
|
||||
|
||||
return duties, nil
|
||||
}
|
||||
|
||||
func (c *beaconApiValidatorClient) validatorsForDuties(ctx context.Context, pubkeys [][]byte) ([]beacon.ValidatorForDuty, error) {
|
||||
vals := make([]beacon.ValidatorForDuty, 0, len(pubkeys))
|
||||
stringPubkeysToPubkeys := make(map[string][]byte, len(pubkeys))
|
||||
stringPubkeys := make([]string, len(pubkeys))
|
||||
|
||||
for i, pk := range pubkeys {
|
||||
stringPk := hexutil.Encode(pk)
|
||||
stringPubkeysToPubkeys[stringPk] = pk
|
||||
stringPubkeys[i] = stringPk
|
||||
}
|
||||
|
||||
statusesWithDuties := []string{validator.ActiveOngoing.String(), validator.ActiveExiting.String()}
|
||||
stateValidatorsResponse, err := c.stateValidatorsProvider.StateValidators(ctx, stringPubkeys, nil, statusesWithDuties)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get state validators")
|
||||
}
|
||||
|
||||
for _, validatorContainer := range stateValidatorsResponse.Data {
|
||||
val := beacon.ValidatorForDuty{}
|
||||
|
||||
validatorIndex, err := strconv.ParseUint(validatorContainer.Index, 10, 64)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse validator index %s", validatorContainer.Index)
|
||||
}
|
||||
val.Index = primitives.ValidatorIndex(validatorIndex)
|
||||
|
||||
stringPubkey := validatorContainer.Validator.Pubkey
|
||||
pubkey, ok := stringPubkeysToPubkeys[stringPubkey]
|
||||
if !ok {
|
||||
return nil, errors.Wrapf(err, "returned public key %s not requested", stringPubkey)
|
||||
}
|
||||
val.Pubkey = pubkey
|
||||
|
||||
status, ok := beaconAPITogRPCValidatorStatus[validatorContainer.Status]
|
||||
if !ok {
|
||||
return nil, errors.New("invalid validator status " + validatorContainer.Status)
|
||||
}
|
||||
val.Status = status
|
||||
|
||||
vals = append(vals, val)
|
||||
}
|
||||
|
||||
return vals, nil
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/apiutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/network/httputil"
|
||||
@@ -22,7 +23,7 @@ type abstractProduceBlockResponseJson struct {
|
||||
Data json.RawMessage `json:"data"`
|
||||
}
|
||||
|
||||
func (c beaconApiValidatorClient) getBeaconBlock(ctx context.Context, slot primitives.Slot, randaoReveal []byte, graffiti []byte) (*ethpb.GenericBeaconBlock, error) {
|
||||
func (c *beaconApiValidatorClient) beaconBlock(ctx context.Context, slot primitives.Slot, randaoReveal, graffiti []byte) (*ethpb.GenericBeaconBlock, error) {
|
||||
queryParams := neturl.Values{}
|
||||
queryParams.Add("randao_reveal", hexutil.Encode(randaoReveal))
|
||||
if len(graffiti) > 0 {
|
||||
@@ -35,7 +36,7 @@ func (c beaconApiValidatorClient) getBeaconBlock(ctx context.Context, slot primi
|
||||
|
||||
// Try v3 endpoint first. If it's not supported, then we fall back to older endpoints.
|
||||
// We try the blinded block endpoint first. If it fails, we assume that we got a full block and try the full block endpoint.
|
||||
queryUrl := buildURL(fmt.Sprintf("/eth/v3/validator/blocks/%d", slot), queryParams)
|
||||
queryUrl := apiutil.BuildURL(fmt.Sprintf("/eth/v3/validator/blocks/%d", slot), queryParams)
|
||||
produceBlockV3ResponseJson := structs.ProduceBlockV3Response{}
|
||||
err := c.jsonRestHandler.Get(ctx, queryUrl, &produceBlockV3ResponseJson)
|
||||
errJson := &httputil.DefaultJsonError{}
|
||||
@@ -69,8 +70,15 @@ func (c beaconApiValidatorClient) getBeaconBlock(ctx context.Context, slot primi
|
||||
blinded = produceBlockV3ResponseJson.ExecutionPayloadBlinded
|
||||
decoder = json.NewDecoder(bytes.NewReader(produceBlockV3ResponseJson.Data))
|
||||
}
|
||||
return processBlockResponse(ver, blinded, decoder)
|
||||
}
|
||||
|
||||
// nolint: gocognit
|
||||
func processBlockResponse(ver string, isBlinded bool, decoder *json.Decoder) (*ethpb.GenericBeaconBlock, error) {
|
||||
var response *ethpb.GenericBeaconBlock
|
||||
if decoder == nil {
|
||||
return nil, errors.New("no produce block json decoder found")
|
||||
}
|
||||
switch ver {
|
||||
case version.String(version.Phase0):
|
||||
jsonPhase0Block := structs.BeaconBlock{}
|
||||
@@ -93,7 +101,7 @@ func (c beaconApiValidatorClient) getBeaconBlock(ctx context.Context, slot primi
|
||||
}
|
||||
response = genericBlock
|
||||
case version.String(version.Bellatrix):
|
||||
if blinded {
|
||||
if isBlinded {
|
||||
jsonBellatrixBlock := structs.BlindedBeaconBlockBellatrix{}
|
||||
if err := decoder.Decode(&jsonBellatrixBlock); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to decode blinded bellatrix block response json")
|
||||
@@ -115,7 +123,7 @@ func (c beaconApiValidatorClient) getBeaconBlock(ctx context.Context, slot primi
|
||||
response = genericBlock
|
||||
}
|
||||
case version.String(version.Capella):
|
||||
if blinded {
|
||||
if isBlinded {
|
||||
jsonCapellaBlock := structs.BlindedBeaconBlockCapella{}
|
||||
if err := decoder.Decode(&jsonCapellaBlock); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to decode blinded capella block response json")
|
||||
@@ -137,7 +145,7 @@ func (c beaconApiValidatorClient) getBeaconBlock(ctx context.Context, slot primi
|
||||
response = genericBlock
|
||||
}
|
||||
case version.String(version.Deneb):
|
||||
if blinded {
|
||||
if isBlinded {
|
||||
jsonDenebBlock := structs.BlindedBeaconBlockDeneb{}
|
||||
if err := decoder.Decode(&jsonDenebBlock); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to decode blinded deneb block response json")
|
||||
@@ -158,32 +166,76 @@ func (c beaconApiValidatorClient) getBeaconBlock(ctx context.Context, slot primi
|
||||
}
|
||||
response = genericBlock
|
||||
}
|
||||
case version.String(version.Electra):
|
||||
if isBlinded {
|
||||
jsonElectraBlock := structs.BlindedBeaconBlockElectra{}
|
||||
if err := decoder.Decode(&jsonElectraBlock); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to decode blinded electra block response json")
|
||||
}
|
||||
genericBlock, err := jsonElectraBlock.ToGeneric()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get blinded electra block")
|
||||
}
|
||||
response = genericBlock
|
||||
} else {
|
||||
jsonElectraBlockContents := structs.BeaconBlockContentsElectra{}
|
||||
if err := decoder.Decode(&jsonElectraBlockContents); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to decode electra block response json")
|
||||
}
|
||||
genericBlock, err := jsonElectraBlockContents.ToGeneric()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get electra block")
|
||||
}
|
||||
response = genericBlock
|
||||
}
|
||||
case version.String(version.Fulu):
|
||||
if isBlinded {
|
||||
jsonFuluBlock := structs.BlindedBeaconBlockFulu{}
|
||||
if err := decoder.Decode(&jsonFuluBlock); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to decode blinded fulu block response json")
|
||||
}
|
||||
genericBlock, err := jsonFuluBlock.ToGeneric()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get blinded fulu block")
|
||||
}
|
||||
response = genericBlock
|
||||
} else {
|
||||
jsonFuluBlockContents := structs.BeaconBlockContentsFulu{}
|
||||
if err := decoder.Decode(&jsonFuluBlockContents); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to decode fulu block response json")
|
||||
}
|
||||
genericBlock, err := jsonFuluBlockContents.ToGeneric()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get fulu block")
|
||||
}
|
||||
response = genericBlock
|
||||
}
|
||||
default:
|
||||
return nil, errors.Errorf("unsupported consensus version `%s`", ver)
|
||||
}
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (c beaconApiValidatorClient) fallBackToBlinded(
|
||||
func (c *beaconApiValidatorClient) fallBackToBlinded(
|
||||
ctx context.Context,
|
||||
slot primitives.Slot,
|
||||
queryParams neturl.Values,
|
||||
) (*abstractProduceBlockResponseJson, error) {
|
||||
resp := &abstractProduceBlockResponseJson{}
|
||||
url := buildURL(fmt.Sprintf("/eth/v1/validator/blinded_blocks/%d", slot), queryParams)
|
||||
url := apiutil.BuildURL(fmt.Sprintf("/eth/v1/validator/blinded_blocks/%d", slot), queryParams)
|
||||
if err := c.jsonRestHandler.Get(ctx, url, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (c beaconApiValidatorClient) fallBackToFull(
|
||||
func (c *beaconApiValidatorClient) fallBackToFull(
|
||||
ctx context.Context,
|
||||
slot primitives.Slot,
|
||||
queryParams neturl.Values,
|
||||
) (*abstractProduceBlockResponseJson, error) {
|
||||
resp := &abstractProduceBlockResponseJson{}
|
||||
url := buildURL(fmt.Sprintf("/eth/v2/validator/blocks/%d", slot), queryParams)
|
||||
url := apiutil.BuildURL(fmt.Sprintf("/eth/v2/validator/blocks/%d", slot), queryParams)
|
||||
if err := c.jsonRestHandler.Get(ctx, url, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -9,14 +9,14 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/mock"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/validator_api/test_helpers"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/network/httputil"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api/mock"
|
||||
test_helpers "github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api/test-helpers"
|
||||
"go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
@@ -28,7 +28,7 @@ func TestGetBeaconBlock_RequestFailed(t *testing.T) {
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
@@ -36,7 +36,7 @@ func TestGetBeaconBlock_RequestFailed(t *testing.T) {
|
||||
).Times(1)
|
||||
|
||||
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
|
||||
_, err := validatorClient.getBeaconBlock(ctx, 1, []byte{1}, []byte{2})
|
||||
_, err := validatorClient.beaconBlock(ctx, 1, []byte{1}, []byte{2})
|
||||
assert.ErrorContains(t, "foo error", err)
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ func TestGetBeaconBlock_Error(t *testing.T) {
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
&structs.ProduceBlockV3Response{},
|
||||
).SetArg(
|
||||
@@ -139,7 +139,7 @@ func TestGetBeaconBlock_Error(t *testing.T) {
|
||||
).Times(1)
|
||||
|
||||
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
|
||||
_, err := validatorClient.getBeaconBlock(ctx, 1, []byte{1}, []byte{2})
|
||||
_, err := validatorClient.beaconBlock(ctx, 1, []byte{1}, []byte{2})
|
||||
assert.ErrorContains(t, testCase.expectedErrorMessage, err)
|
||||
})
|
||||
}
|
||||
@@ -161,7 +161,7 @@ func TestGetBeaconBlock_Phase0Valid(t *testing.T) {
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
|
||||
&structs.ProduceBlockV3Response{},
|
||||
).SetArg(
|
||||
@@ -175,7 +175,7 @@ func TestGetBeaconBlock_Phase0Valid(t *testing.T) {
|
||||
).Times(1)
|
||||
|
||||
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
|
||||
beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti)
|
||||
beaconBlock, err := validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti)
|
||||
require.NoError(t, err)
|
||||
|
||||
expectedBeaconBlock := ðpb.GenericBeaconBlock{
|
||||
@@ -204,7 +204,7 @@ func TestGetBeaconBlock_AltairValid(t *testing.T) {
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
|
||||
&structs.ProduceBlockV3Response{},
|
||||
).SetArg(
|
||||
@@ -218,7 +218,7 @@ func TestGetBeaconBlock_AltairValid(t *testing.T) {
|
||||
).Times(1)
|
||||
|
||||
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
|
||||
beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti)
|
||||
beaconBlock, err := validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti)
|
||||
require.NoError(t, err)
|
||||
|
||||
expectedBeaconBlock := ðpb.GenericBeaconBlock{
|
||||
@@ -247,7 +247,7 @@ func TestGetBeaconBlock_BellatrixValid(t *testing.T) {
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
|
||||
&structs.ProduceBlockV3Response{},
|
||||
).SetArg(
|
||||
@@ -262,7 +262,7 @@ func TestGetBeaconBlock_BellatrixValid(t *testing.T) {
|
||||
).Times(1)
|
||||
|
||||
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
|
||||
beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti)
|
||||
beaconBlock, err := validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti)
|
||||
require.NoError(t, err)
|
||||
|
||||
expectedBeaconBlock := ðpb.GenericBeaconBlock{
|
||||
@@ -292,7 +292,7 @@ func TestGetBeaconBlock_BlindedBellatrixValid(t *testing.T) {
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
|
||||
&structs.ProduceBlockV3Response{},
|
||||
).SetArg(
|
||||
@@ -307,7 +307,7 @@ func TestGetBeaconBlock_BlindedBellatrixValid(t *testing.T) {
|
||||
).Times(1)
|
||||
|
||||
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
|
||||
beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti)
|
||||
beaconBlock, err := validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti)
|
||||
require.NoError(t, err)
|
||||
|
||||
expectedBeaconBlock := ðpb.GenericBeaconBlock{
|
||||
@@ -337,7 +337,7 @@ func TestGetBeaconBlock_CapellaValid(t *testing.T) {
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
|
||||
&structs.ProduceBlockV3Response{},
|
||||
).SetArg(
|
||||
@@ -352,7 +352,7 @@ func TestGetBeaconBlock_CapellaValid(t *testing.T) {
|
||||
).Times(1)
|
||||
|
||||
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
|
||||
beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti)
|
||||
beaconBlock, err := validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti)
|
||||
require.NoError(t, err)
|
||||
|
||||
expectedBeaconBlock := ðpb.GenericBeaconBlock{
|
||||
@@ -382,7 +382,7 @@ func TestGetBeaconBlock_BlindedCapellaValid(t *testing.T) {
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
|
||||
&structs.ProduceBlockV3Response{},
|
||||
).SetArg(
|
||||
@@ -397,7 +397,7 @@ func TestGetBeaconBlock_BlindedCapellaValid(t *testing.T) {
|
||||
).Times(1)
|
||||
|
||||
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
|
||||
beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti)
|
||||
beaconBlock, err := validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti)
|
||||
require.NoError(t, err)
|
||||
|
||||
expectedBeaconBlock := ðpb.GenericBeaconBlock{
|
||||
@@ -427,7 +427,7 @@ func TestGetBeaconBlock_DenebValid(t *testing.T) {
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
|
||||
&structs.ProduceBlockV3Response{},
|
||||
).SetArg(
|
||||
@@ -442,7 +442,7 @@ func TestGetBeaconBlock_DenebValid(t *testing.T) {
|
||||
).Times(1)
|
||||
|
||||
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
|
||||
beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti)
|
||||
beaconBlock, err := validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti)
|
||||
require.NoError(t, err)
|
||||
|
||||
expectedBeaconBlock := ðpb.GenericBeaconBlock{
|
||||
@@ -472,7 +472,7 @@ func TestGetBeaconBlock_BlindedDenebValid(t *testing.T) {
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
|
||||
&structs.ProduceBlockV3Response{},
|
||||
).SetArg(
|
||||
@@ -487,7 +487,7 @@ func TestGetBeaconBlock_BlindedDenebValid(t *testing.T) {
|
||||
).Times(1)
|
||||
|
||||
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
|
||||
beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti)
|
||||
beaconBlock, err := validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti)
|
||||
require.NoError(t, err)
|
||||
|
||||
expectedBeaconBlock := ðpb.GenericBeaconBlock{
|
||||
@@ -500,6 +500,96 @@ func TestGetBeaconBlock_BlindedDenebValid(t *testing.T) {
|
||||
assert.DeepEqual(t, expectedBeaconBlock, beaconBlock)
|
||||
}
|
||||
|
||||
func TestGetBeaconBlock_ElectraValid(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
proto := test_helpers.GenerateProtoElectraBeaconBlockContents()
|
||||
block := test_helpers.GenerateJsonElectraBeaconBlockContents()
|
||||
bytes, err := json.Marshal(block)
|
||||
require.NoError(t, err)
|
||||
|
||||
const slot = primitives.Slot(1)
|
||||
randaoReveal := []byte{2}
|
||||
graffiti := []byte{3}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
|
||||
&structs.ProduceBlockV3Response{},
|
||||
).SetArg(
|
||||
2,
|
||||
structs.ProduceBlockV3Response{
|
||||
Version: "electra",
|
||||
ExecutionPayloadBlinded: false,
|
||||
Data: bytes,
|
||||
},
|
||||
).Return(
|
||||
nil,
|
||||
).Times(1)
|
||||
|
||||
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
|
||||
beaconBlock, err := validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti)
|
||||
require.NoError(t, err)
|
||||
|
||||
expectedBeaconBlock := ðpb.GenericBeaconBlock{
|
||||
Block: ðpb.GenericBeaconBlock_Electra{
|
||||
Electra: proto,
|
||||
},
|
||||
IsBlinded: false,
|
||||
}
|
||||
|
||||
assert.DeepEqual(t, expectedBeaconBlock, beaconBlock)
|
||||
}
|
||||
|
||||
func TestGetBeaconBlock_BlindedElectraValid(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
proto := test_helpers.GenerateProtoBlindedElectraBeaconBlock()
|
||||
block := test_helpers.GenerateJsonBlindedElectraBeaconBlock()
|
||||
bytes, err := json.Marshal(block)
|
||||
require.NoError(t, err)
|
||||
|
||||
const slot = primitives.Slot(1)
|
||||
randaoReveal := []byte{2}
|
||||
graffiti := []byte{3}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
|
||||
&structs.ProduceBlockV3Response{},
|
||||
).SetArg(
|
||||
2,
|
||||
structs.ProduceBlockV3Response{
|
||||
Version: "electra",
|
||||
ExecutionPayloadBlinded: true,
|
||||
Data: bytes,
|
||||
},
|
||||
).Return(
|
||||
nil,
|
||||
).Times(1)
|
||||
|
||||
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
|
||||
beaconBlock, err := validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti)
|
||||
require.NoError(t, err)
|
||||
|
||||
expectedBeaconBlock := ðpb.GenericBeaconBlock{
|
||||
Block: ðpb.GenericBeaconBlock_BlindedElectra{
|
||||
BlindedElectra: proto,
|
||||
},
|
||||
IsBlinded: true,
|
||||
}
|
||||
|
||||
assert.DeepEqual(t, expectedBeaconBlock, beaconBlock)
|
||||
}
|
||||
|
||||
func TestGetBeaconBlock_FallbackToBlindedBlock(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
@@ -517,14 +607,14 @@ func TestGetBeaconBlock_FallbackToBlindedBlock(t *testing.T) {
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
|
||||
&structs.ProduceBlockV3Response{},
|
||||
).Return(
|
||||
&httputil.DefaultJsonError{Code: http.StatusNotFound},
|
||||
).Times(1)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("/eth/v1/validator/blinded_blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
|
||||
&abstractProduceBlockResponseJson{},
|
||||
).SetArg(
|
||||
@@ -538,7 +628,7 @@ func TestGetBeaconBlock_FallbackToBlindedBlock(t *testing.T) {
|
||||
).Times(1)
|
||||
|
||||
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
|
||||
beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti)
|
||||
beaconBlock, err := validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti)
|
||||
require.NoError(t, err)
|
||||
|
||||
expectedBeaconBlock := ðpb.GenericBeaconBlock{
|
||||
@@ -568,14 +658,14 @@ func TestGetBeaconBlock_FallbackToFullBlock(t *testing.T) {
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
|
||||
&structs.ProduceBlockV3Response{},
|
||||
).Return(
|
||||
&httputil.DefaultJsonError{Code: http.StatusNotFound},
|
||||
).Times(1)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("/eth/v1/validator/blinded_blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
|
||||
&abstractProduceBlockResponseJson{},
|
||||
).Return(
|
||||
@@ -596,7 +686,7 @@ func TestGetBeaconBlock_FallbackToFullBlock(t *testing.T) {
|
||||
).Times(1)
|
||||
|
||||
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
|
||||
beaconBlock, err := validatorClient.getBeaconBlock(ctx, slot, randaoReveal, graffiti)
|
||||
beaconBlock, err := validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti)
|
||||
require.NoError(t, err)
|
||||
|
||||
expectedBeaconBlock := ðpb.GenericBeaconBlock{
|
||||
@@ -1,4 +1,4 @@
|
||||
package grpc_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -8,13 +8,13 @@ import (
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon"
|
||||
eventClient "github.com/prysmaticlabs/prysm/v5/api/client/event"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/validator/client/iface"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"go.opencensus.io/trace"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
@@ -23,8 +23,59 @@ type grpcValidatorClient struct {
|
||||
isEventStreamRunning bool
|
||||
}
|
||||
|
||||
func (c *grpcValidatorClient) GetDuties(ctx context.Context, in *ethpb.DutiesRequest) (*ethpb.DutiesResponse, error) {
|
||||
return c.beaconNodeValidatorClient.GetDuties(ctx, in)
|
||||
func (c *grpcValidatorClient) Duties(ctx context.Context, in *ethpb.DutiesRequest) (*ethpb.ValidatorDutiesContainer, error) {
|
||||
dutiesResponse, err := c.beaconNodeValidatorClient.GetDuties(ctx, in)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return toValidatorDutiesContainer(dutiesResponse)
|
||||
}
|
||||
|
||||
func toValidatorDutiesContainer(dutiesResponse *ethpb.DutiesResponse) (*ethpb.ValidatorDutiesContainer, error) {
|
||||
currentDuties := make([]*ethpb.ValidatorDuty, len(dutiesResponse.CurrentEpochDuties))
|
||||
for i, cd := range dutiesResponse.CurrentEpochDuties {
|
||||
duty, err := toValidatorDuty(cd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
currentDuties[i] = duty
|
||||
}
|
||||
nextDuties := make([]*ethpb.ValidatorDuty, len(dutiesResponse.NextEpochDuties))
|
||||
for i, nd := range dutiesResponse.NextEpochDuties {
|
||||
duty, err := toValidatorDuty(nd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
nextDuties[i] = duty
|
||||
}
|
||||
return ðpb.ValidatorDutiesContainer{
|
||||
CurrentEpochDuties: currentDuties,
|
||||
NextEpochDuties: nextDuties,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func toValidatorDuty(duty *ethpb.DutiesResponse_Duty) (*ethpb.ValidatorDuty, error) {
|
||||
var valIndexInCommittee uint64
|
||||
// valIndexInCommittee will be 0 in case we don't get a match. This is a potential false positive,
|
||||
// however it's an impossible condition because every validator must be assigned to a committee.
|
||||
for cIndex, vIndex := range duty.Committee {
|
||||
if vIndex == duty.ValidatorIndex {
|
||||
valIndexInCommittee = uint64(cIndex)
|
||||
break
|
||||
}
|
||||
}
|
||||
return ðpb.ValidatorDuty{
|
||||
CommitteeLength: uint64(len(duty.Committee)),
|
||||
CommitteeIndex: duty.CommitteeIndex,
|
||||
CommitteesAtSlot: duty.CommitteesAtSlot, // GRPC doesn't use this value though
|
||||
ValidatorCommitteeIndex: valIndexInCommittee,
|
||||
AttesterSlot: duty.AttesterSlot,
|
||||
ProposerSlots: duty.ProposerSlots,
|
||||
PublicKey: bytesutil.SafeCopyBytes(duty.PublicKey),
|
||||
Status: duty.Status,
|
||||
ValidatorIndex: duty.ValidatorIndex,
|
||||
IsSyncCommittee: duty.IsSyncCommittee,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *grpcValidatorClient) CheckDoppelGanger(ctx context.Context, in *ethpb.DoppelGangerRequest) (*ethpb.DoppelGangerResponse, error) {
|
||||
@@ -35,27 +86,27 @@ func (c *grpcValidatorClient) DomainData(ctx context.Context, in *ethpb.DomainRe
|
||||
return c.beaconNodeValidatorClient.DomainData(ctx, in)
|
||||
}
|
||||
|
||||
func (c *grpcValidatorClient) GetAttestationData(ctx context.Context, in *ethpb.AttestationDataRequest) (*ethpb.AttestationData, error) {
|
||||
func (c *grpcValidatorClient) AttestationData(ctx context.Context, in *ethpb.AttestationDataRequest) (*ethpb.AttestationData, error) {
|
||||
return c.beaconNodeValidatorClient.GetAttestationData(ctx, in)
|
||||
}
|
||||
|
||||
func (c *grpcValidatorClient) GetBeaconBlock(ctx context.Context, in *ethpb.BlockRequest) (*ethpb.GenericBeaconBlock, error) {
|
||||
func (c *grpcValidatorClient) BeaconBlock(ctx context.Context, in *ethpb.BlockRequest) (*ethpb.GenericBeaconBlock, error) {
|
||||
return c.beaconNodeValidatorClient.GetBeaconBlock(ctx, in)
|
||||
}
|
||||
|
||||
func (c *grpcValidatorClient) GetFeeRecipientByPubKey(ctx context.Context, in *ethpb.FeeRecipientByPubKeyRequest) (*ethpb.FeeRecipientByPubKeyResponse, error) {
|
||||
func (c *grpcValidatorClient) FeeRecipientByPubKey(ctx context.Context, in *ethpb.FeeRecipientByPubKeyRequest) (*ethpb.FeeRecipientByPubKeyResponse, error) {
|
||||
return c.beaconNodeValidatorClient.GetFeeRecipientByPubKey(ctx, in)
|
||||
}
|
||||
|
||||
func (c *grpcValidatorClient) GetSyncCommitteeContribution(ctx context.Context, in *ethpb.SyncCommitteeContributionRequest) (*ethpb.SyncCommitteeContribution, error) {
|
||||
func (c *grpcValidatorClient) SyncCommitteeContribution(ctx context.Context, in *ethpb.SyncCommitteeContributionRequest) (*ethpb.SyncCommitteeContribution, error) {
|
||||
return c.beaconNodeValidatorClient.GetSyncCommitteeContribution(ctx, in)
|
||||
}
|
||||
|
||||
func (c *grpcValidatorClient) GetSyncMessageBlockRoot(ctx context.Context, in *empty.Empty) (*ethpb.SyncMessageBlockRootResponse, error) {
|
||||
func (c *grpcValidatorClient) SyncMessageBlockRoot(ctx context.Context, in *empty.Empty) (*ethpb.SyncMessageBlockRootResponse, error) {
|
||||
return c.beaconNodeValidatorClient.GetSyncMessageBlockRoot(ctx, in)
|
||||
}
|
||||
|
||||
func (c *grpcValidatorClient) GetSyncSubcommitteeIndex(ctx context.Context, in *ethpb.SyncSubcommitteeIndexRequest) (*ethpb.SyncSubcommitteeIndexResponse, error) {
|
||||
func (c *grpcValidatorClient) SyncSubcommitteeIndex(ctx context.Context, in *ethpb.SyncSubcommitteeIndexRequest) (*ethpb.SyncSubcommitteeIndexResponse, error) {
|
||||
return c.beaconNodeValidatorClient.GetSyncSubcommitteeIndex(ctx, in)
|
||||
}
|
||||
|
||||
@@ -71,6 +122,10 @@ func (c *grpcValidatorClient) ProposeAttestation(ctx context.Context, in *ethpb.
|
||||
return c.beaconNodeValidatorClient.ProposeAttestation(ctx, in)
|
||||
}
|
||||
|
||||
func (c *grpcValidatorClient) ProposeAttestationElectra(ctx context.Context, in *ethpb.SingleAttestation) (*ethpb.AttestResponse, error) {
|
||||
return c.beaconNodeValidatorClient.ProposeAttestationElectra(ctx, in)
|
||||
}
|
||||
|
||||
func (c *grpcValidatorClient) ProposeBeaconBlock(ctx context.Context, in *ethpb.GenericSignedBeaconBlock) (*ethpb.ProposeResponse, error) {
|
||||
return c.beaconNodeValidatorClient.ProposeBeaconBlock(ctx, in)
|
||||
}
|
||||
@@ -87,10 +142,18 @@ func (c *grpcValidatorClient) SubmitAggregateSelectionProof(ctx context.Context,
|
||||
return c.beaconNodeValidatorClient.SubmitAggregateSelectionProof(ctx, in)
|
||||
}
|
||||
|
||||
func (c *grpcValidatorClient) SubmitAggregateSelectionProofElectra(ctx context.Context, in *ethpb.AggregateSelectionRequest, _ primitives.ValidatorIndex, _ uint64) (*ethpb.AggregateSelectionElectraResponse, error) {
|
||||
return c.beaconNodeValidatorClient.SubmitAggregateSelectionProofElectra(ctx, in)
|
||||
}
|
||||
|
||||
func (c *grpcValidatorClient) SubmitSignedAggregateSelectionProof(ctx context.Context, in *ethpb.SignedAggregateSubmitRequest) (*ethpb.SignedAggregateSubmitResponse, error) {
|
||||
return c.beaconNodeValidatorClient.SubmitSignedAggregateSelectionProof(ctx, in)
|
||||
}
|
||||
|
||||
func (c *grpcValidatorClient) SubmitSignedAggregateSelectionProofElectra(ctx context.Context, in *ethpb.SignedAggregateSubmitElectraRequest) (*ethpb.SignedAggregateSubmitResponse, error) {
|
||||
return c.beaconNodeValidatorClient.SubmitSignedAggregateSelectionProofElectra(ctx, in)
|
||||
}
|
||||
|
||||
func (c *grpcValidatorClient) SubmitSignedContributionAndProof(ctx context.Context, in *ethpb.SignedContributionAndProof) (*empty.Empty, error) {
|
||||
return c.beaconNodeValidatorClient.SubmitSignedContributionAndProof(ctx, in)
|
||||
}
|
||||
@@ -103,7 +166,7 @@ func (c *grpcValidatorClient) SubmitValidatorRegistrations(ctx context.Context,
|
||||
return c.beaconNodeValidatorClient.SubmitValidatorRegistrations(ctx, in)
|
||||
}
|
||||
|
||||
func (c *grpcValidatorClient) SubscribeCommitteeSubnets(ctx context.Context, in *ethpb.CommitteeSubnetsSubscribeRequest, _ []*ethpb.DutiesResponse_Duty) (*empty.Empty, error) {
|
||||
func (c *grpcValidatorClient) SubscribeCommitteeSubnets(ctx context.Context, in *ethpb.CommitteeSubnetsSubscribeRequest, _ []*ethpb.ValidatorDuty) (*empty.Empty, error) {
|
||||
return c.beaconNodeValidatorClient.SubscribeCommitteeSubnets(ctx, in)
|
||||
}
|
||||
|
||||
@@ -115,10 +178,6 @@ func (c *grpcValidatorClient) ValidatorStatus(ctx context.Context, in *ethpb.Val
|
||||
return c.beaconNodeValidatorClient.ValidatorStatus(ctx, in)
|
||||
}
|
||||
|
||||
func (c *grpcValidatorClient) WaitForActivation(ctx context.Context, in *ethpb.ValidatorActivationRequest) (ethpb.BeaconNodeValidator_WaitForActivationClient, error) {
|
||||
return c.beaconNodeValidatorClient.WaitForActivation(ctx, in)
|
||||
}
|
||||
|
||||
// Deprecated: Do not use.
|
||||
func (c *grpcValidatorClient) WaitForChainStart(ctx context.Context, in *empty.Empty) (*ethpb.ChainStartResponse, error) {
|
||||
stream, err := c.beaconNodeValidatorClient.WaitForChainStart(ctx, in)
|
||||
@@ -142,15 +201,15 @@ func (c *grpcValidatorClient) AggregatedSigAndAggregationBits(
|
||||
return c.beaconNodeValidatorClient.AggregatedSigAndAggregationBits(ctx, in)
|
||||
}
|
||||
|
||||
func (grpcValidatorClient) GetAggregatedSelections(context.Context, []iface.BeaconCommitteeSelection) ([]iface.BeaconCommitteeSelection, error) {
|
||||
return nil, iface.ErrNotSupported
|
||||
func (*grpcValidatorClient) AggregatedSelections(context.Context, []beacon.BeaconCommitteeSelection) ([]beacon.BeaconCommitteeSelection, error) {
|
||||
return nil, client.ErrNotSupported
|
||||
}
|
||||
|
||||
func (grpcValidatorClient) GetAggregatedSyncSelections(context.Context, []iface.SyncCommitteeSelection) ([]iface.SyncCommitteeSelection, error) {
|
||||
return nil, iface.ErrNotSupported
|
||||
func (*grpcValidatorClient) AggregatedSyncSelections(context.Context, []beacon.SyncCommitteeSelection) ([]beacon.SyncCommitteeSelection, error) {
|
||||
return nil, client.ErrNotSupported
|
||||
}
|
||||
|
||||
func NewGrpcValidatorClient(cc grpc.ClientConnInterface) iface.ValidatorClient {
|
||||
func NewGrpcValidatorClient(cc grpc.ClientConnInterface) Client {
|
||||
return &grpcValidatorClient{ethpb.NewBeaconNodeValidatorClient(cc), false}
|
||||
}
|
||||
|
||||
@@ -245,3 +304,12 @@ func (c *grpcValidatorClient) StartEventStream(ctx context.Context, topics []str
|
||||
func (c *grpcValidatorClient) EventStreamIsRunning() bool {
|
||||
return c.isEventStreamRunning
|
||||
}
|
||||
|
||||
func (*grpcValidatorClient) Host() string {
|
||||
log.Warn(client.ErrNotSupported)
|
||||
return ""
|
||||
}
|
||||
|
||||
func (*grpcValidatorClient) SetHost(_ string) {
|
||||
log.Warn(client.ErrNotSupported)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package grpc_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
|
||||
eventClient "github.com/prysmaticlabs/prysm/v5/api/client/event"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/assert"
|
||||
mock2 "github.com/prysmaticlabs/prysm/v5/testing/mock"
|
||||
@@ -18,6 +19,58 @@ import (
|
||||
"google.golang.org/protobuf/types/known/emptypb"
|
||||
)
|
||||
|
||||
// toValidatorDutiesContainer is assumed to be available from your package, returning a *v1alpha1.ValidatorDutiesContainer.
|
||||
func TestToValidatorDutiesContainer_HappyPath(t *testing.T) {
|
||||
// Create a mock DutiesResponse with current and next duties.
|
||||
dutiesResp := ð.DutiesResponse{
|
||||
CurrentEpochDuties: []*eth.DutiesResponse_Duty{
|
||||
{
|
||||
Committee: []primitives.ValidatorIndex{100, 101},
|
||||
CommitteeIndex: 4,
|
||||
AttesterSlot: 200,
|
||||
ProposerSlots: []primitives.Slot{400},
|
||||
PublicKey: []byte{0xAA, 0xBB},
|
||||
Status: eth.ValidatorStatus_ACTIVE,
|
||||
ValidatorIndex: 101,
|
||||
IsSyncCommittee: false,
|
||||
CommitteesAtSlot: 2,
|
||||
},
|
||||
},
|
||||
NextEpochDuties: []*eth.DutiesResponse_Duty{
|
||||
{
|
||||
Committee: []primitives.ValidatorIndex{300, 301},
|
||||
CommitteeIndex: 8,
|
||||
AttesterSlot: 600,
|
||||
ProposerSlots: []primitives.Slot{700, 701},
|
||||
PublicKey: []byte{0xCC, 0xDD},
|
||||
Status: eth.ValidatorStatus_ACTIVE,
|
||||
ValidatorIndex: 301,
|
||||
IsSyncCommittee: true,
|
||||
CommitteesAtSlot: 3,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
gotContainer, err := toValidatorDutiesContainer(dutiesResp)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Validate we have the correct number of duties in current and next epochs.
|
||||
assert.Equal(t, len(gotContainer.CurrentEpochDuties), len(dutiesResp.CurrentEpochDuties))
|
||||
assert.Equal(t, len(gotContainer.NextEpochDuties), len(dutiesResp.NextEpochDuties))
|
||||
|
||||
firstCurrentDuty := gotContainer.CurrentEpochDuties[0]
|
||||
expectedCurrentDuty := dutiesResp.CurrentEpochDuties[0]
|
||||
assert.DeepEqual(t, firstCurrentDuty.PublicKey, expectedCurrentDuty.PublicKey)
|
||||
assert.Equal(t, firstCurrentDuty.ValidatorIndex, expectedCurrentDuty.ValidatorIndex)
|
||||
assert.DeepEqual(t, firstCurrentDuty.ProposerSlots, expectedCurrentDuty.ProposerSlots)
|
||||
|
||||
firstNextDuty := gotContainer.NextEpochDuties[0]
|
||||
expectedNextDuty := dutiesResp.NextEpochDuties[0]
|
||||
assert.DeepEqual(t, firstNextDuty.PublicKey, expectedNextDuty.PublicKey)
|
||||
assert.Equal(t, firstNextDuty.ValidatorIndex, expectedNextDuty.ValidatorIndex)
|
||||
assert.DeepEqual(t, firstNextDuty.ProposerSlots, expectedNextDuty.ProposerSlots)
|
||||
}
|
||||
|
||||
func TestWaitForChainStart_StreamSetupFails(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -28,10 +28,10 @@ func (e *IndexNotFoundError) Error() string {
|
||||
return e.message
|
||||
}
|
||||
|
||||
func (c beaconApiValidatorClient) validatorIndex(ctx context.Context, in *ethpb.ValidatorIndexRequest) (*ethpb.ValidatorIndexResponse, error) {
|
||||
func (c *beaconApiValidatorClient) validatorIndex(ctx context.Context, in *ethpb.ValidatorIndexRequest) (*ethpb.ValidatorIndexResponse, error) {
|
||||
stringPubKey := hexutil.Encode(in.PublicKey)
|
||||
|
||||
stateValidator, err := c.stateValidatorsProvider.GetStateValidators(ctx, []string{stringPubKey}, nil, nil)
|
||||
stateValidator, err := c.stateValidatorsProvider.StateValidators(ctx, []string{stringPubKey}, nil, nil)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get state validator")
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -9,12 +9,14 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/apiutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/mock"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/shared_providers"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api/mock"
|
||||
"go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
@@ -44,7 +46,7 @@ func TestIndex_Nominal(t *testing.T) {
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
"/eth/v1/beacon/states/head/validators",
|
||||
nil,
|
||||
reqBuffer,
|
||||
@@ -67,9 +69,7 @@ func TestIndex_Nominal(t *testing.T) {
|
||||
).Times(1)
|
||||
|
||||
validatorClient := beaconApiValidatorClient{
|
||||
stateValidatorsProvider: beaconApiStateValidatorsProvider{
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
},
|
||||
stateValidatorsProvider: shared_providers.NewStateValidators(jsonRestHandler),
|
||||
}
|
||||
|
||||
validatorIndex, err := validatorClient.ValidatorIndex(
|
||||
@@ -94,7 +94,7 @@ func TestIndex_UnexistingValidator(t *testing.T) {
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
"/eth/v1/beacon/states/head/validators",
|
||||
nil,
|
||||
reqBuffer,
|
||||
@@ -109,9 +109,7 @@ func TestIndex_UnexistingValidator(t *testing.T) {
|
||||
).Times(1)
|
||||
|
||||
validatorClient := beaconApiValidatorClient{
|
||||
stateValidatorsProvider: beaconApiStateValidatorsProvider{
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
},
|
||||
stateValidatorsProvider: shared_providers.NewStateValidators(jsonRestHandler),
|
||||
}
|
||||
|
||||
_, err := validatorClient.ValidatorIndex(
|
||||
@@ -136,7 +134,7 @@ func TestIndex_BadIndexError(t *testing.T) {
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
"/eth/v1/beacon/states/head/validators",
|
||||
nil,
|
||||
reqBuffer,
|
||||
@@ -159,9 +157,7 @@ func TestIndex_BadIndexError(t *testing.T) {
|
||||
).Times(1)
|
||||
|
||||
validatorClient := beaconApiValidatorClient{
|
||||
stateValidatorsProvider: beaconApiStateValidatorsProvider{
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
},
|
||||
stateValidatorsProvider: shared_providers.NewStateValidators(jsonRestHandler),
|
||||
}
|
||||
|
||||
_, err := validatorClient.ValidatorIndex(
|
||||
@@ -185,7 +181,7 @@ func TestIndex_JsonResponseError(t *testing.T) {
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
"/eth/v1/beacon/states/head/validators",
|
||||
nil,
|
||||
reqBuffer,
|
||||
@@ -208,17 +204,15 @@ func TestIndex_JsonResponseError(t *testing.T) {
|
||||
}
|
||||
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
ctx,
|
||||
buildURL("/eth/v1/beacon/states/head/validators", queryParams),
|
||||
gomock.Any(),
|
||||
apiutil.BuildURL("/eth/v1/beacon/states/head/validators", queryParams),
|
||||
&stateValidatorsResponseJson,
|
||||
).Return(
|
||||
errors.New("some specific json error"),
|
||||
).Times(1)
|
||||
|
||||
validatorClient := beaconApiValidatorClient{
|
||||
stateValidatorsProvider: beaconApiStateValidatorsProvider{
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
},
|
||||
stateValidatorsProvider: shared_providers.NewStateValidators(jsonRestHandler),
|
||||
}
|
||||
|
||||
_, err := validatorClient.ValidatorIndex(
|
||||
46
api/client/beacon/validator_api/interfaces.go
Normal file
46
api/client/beacon/validator_api/interfaces.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/event"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
type Client interface {
|
||||
Duties(ctx context.Context, in *ethpb.DutiesRequest) (*ethpb.ValidatorDutiesContainer, error)
|
||||
DomainData(ctx context.Context, in *ethpb.DomainRequest) (*ethpb.DomainResponse, error)
|
||||
WaitForChainStart(ctx context.Context, in *empty.Empty) (*ethpb.ChainStartResponse, error)
|
||||
ValidatorIndex(ctx context.Context, in *ethpb.ValidatorIndexRequest) (*ethpb.ValidatorIndexResponse, error)
|
||||
ValidatorStatus(ctx context.Context, in *ethpb.ValidatorStatusRequest) (*ethpb.ValidatorStatusResponse, error)
|
||||
MultipleValidatorStatus(ctx context.Context, in *ethpb.MultipleValidatorStatusRequest) (*ethpb.MultipleValidatorStatusResponse, error)
|
||||
BeaconBlock(ctx context.Context, in *ethpb.BlockRequest) (*ethpb.GenericBeaconBlock, error)
|
||||
ProposeBeaconBlock(ctx context.Context, in *ethpb.GenericSignedBeaconBlock) (*ethpb.ProposeResponse, error)
|
||||
PrepareBeaconProposer(ctx context.Context, in *ethpb.PrepareBeaconProposerRequest) (*empty.Empty, error)
|
||||
FeeRecipientByPubKey(ctx context.Context, in *ethpb.FeeRecipientByPubKeyRequest) (*ethpb.FeeRecipientByPubKeyResponse, error)
|
||||
AttestationData(ctx context.Context, in *ethpb.AttestationDataRequest) (*ethpb.AttestationData, error)
|
||||
ProposeAttestation(ctx context.Context, in *ethpb.Attestation) (*ethpb.AttestResponse, error)
|
||||
ProposeAttestationElectra(ctx context.Context, in *ethpb.SingleAttestation) (*ethpb.AttestResponse, error)
|
||||
SubmitAggregateSelectionProof(ctx context.Context, in *ethpb.AggregateSelectionRequest, index primitives.ValidatorIndex, committeeLength uint64) (*ethpb.AggregateSelectionResponse, error)
|
||||
SubmitAggregateSelectionProofElectra(ctx context.Context, in *ethpb.AggregateSelectionRequest, _ primitives.ValidatorIndex, _ uint64) (*ethpb.AggregateSelectionElectraResponse, error)
|
||||
SubmitSignedAggregateSelectionProof(ctx context.Context, in *ethpb.SignedAggregateSubmitRequest) (*ethpb.SignedAggregateSubmitResponse, error)
|
||||
SubmitSignedAggregateSelectionProofElectra(ctx context.Context, in *ethpb.SignedAggregateSubmitElectraRequest) (*ethpb.SignedAggregateSubmitResponse, error)
|
||||
ProposeExit(ctx context.Context, in *ethpb.SignedVoluntaryExit) (*ethpb.ProposeExitResponse, error)
|
||||
SubscribeCommitteeSubnets(ctx context.Context, in *ethpb.CommitteeSubnetsSubscribeRequest, duties []*ethpb.ValidatorDuty) (*empty.Empty, error)
|
||||
CheckDoppelGanger(ctx context.Context, in *ethpb.DoppelGangerRequest) (*ethpb.DoppelGangerResponse, error)
|
||||
SyncMessageBlockRoot(ctx context.Context, in *empty.Empty) (*ethpb.SyncMessageBlockRootResponse, error)
|
||||
SubmitSyncMessage(ctx context.Context, in *ethpb.SyncCommitteeMessage) (*empty.Empty, error)
|
||||
SyncSubcommitteeIndex(ctx context.Context, in *ethpb.SyncSubcommitteeIndexRequest) (*ethpb.SyncSubcommitteeIndexResponse, error)
|
||||
SyncCommitteeContribution(ctx context.Context, in *ethpb.SyncCommitteeContributionRequest) (*ethpb.SyncCommitteeContribution, error)
|
||||
SubmitSignedContributionAndProof(ctx context.Context, in *ethpb.SignedContributionAndProof) (*empty.Empty, error)
|
||||
SubmitValidatorRegistrations(ctx context.Context, in *ethpb.SignedValidatorRegistrationsV1) (*empty.Empty, error)
|
||||
StartEventStream(ctx context.Context, topics []string, eventsChannel chan<- *event.Event)
|
||||
EventStreamIsRunning() bool
|
||||
AggregatedSelections(ctx context.Context, selections []beacon.BeaconCommitteeSelection) ([]beacon.BeaconCommitteeSelection, error)
|
||||
AggregatedSyncSelections(ctx context.Context, selections []beacon.SyncCommitteeSelection) ([]beacon.SyncCommitteeSelection, error)
|
||||
Host() string
|
||||
SetHost(host string)
|
||||
}
|
||||
5
api/client/beacon/validator_api/log.go
Normal file
5
api/client/beacon/validator_api/log.go
Normal file
@@ -0,0 +1,5 @@
|
||||
package validator_api
|
||||
|
||||
import "github.com/sirupsen/logrus"
|
||||
|
||||
var log = logrus.WithField("prefix", "beacon-api")
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user