mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-10 13:58:09 -05:00
Compare commits
33 Commits
v1.0.0.rc.
...
v1.0.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fc7c6776f6 | ||
|
|
b150acffca | ||
|
|
54a42ce4a8 | ||
|
|
9d174d5927 | ||
|
|
1b1b36497f | ||
|
|
04615cb97b | ||
|
|
b243665d3e | ||
|
|
654ef1afe5 | ||
|
|
0dbf5c4e63 | ||
|
|
c456dcdce8 | ||
|
|
10857223d0 | ||
|
|
4ef8a0f99e | ||
|
|
af0977b8d0 | ||
|
|
528272fc66 | ||
|
|
c5c868d0a6 | ||
|
|
622ab94465 | ||
|
|
ae8a619775 | ||
|
|
36b1eb66d5 | ||
|
|
639dcb028c | ||
|
|
edb40ddea4 | ||
|
|
0d2e3d978c | ||
|
|
29c6a0c42c | ||
|
|
aefa3e191a | ||
|
|
987205afc6 | ||
|
|
3ae4b793e6 | ||
|
|
600427bdb0 | ||
|
|
c7dd33431f | ||
|
|
0cf9800b75 | ||
|
|
3cc2ebc5d5 | ||
|
|
2cb814648a | ||
|
|
dc897a2007 | ||
|
|
a051e684ae | ||
|
|
64be627a6d |
218
.well-known/security.pub
Normal file
218
.well-known/security.pub
Normal file
@@ -0,0 +1,218 @@
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mQINBFpZUO0BEAC/tqN6QctJKSOF+A7jrBzvNvs6rVEi9Hn55u/scKNIPkSRJRTy
|
||||
8kVsDMha+EKXka8oQiVM+sHoHMIMCa3tdicm1/k5f67X8dqadQmFP4DhYRYIKCKT
|
||||
TkntNG568ynf/yUs/YY9Ce8H17JvgytkLK50mxMxycUlYREMaRPMR8Wt1Arrd9QT
|
||||
U0I2cZemeqUORKuiVuZjj/7BVDHvSXHvzpi5zKI86sJQTnzcuGqyNsrUU4n4sYrb
|
||||
I+0TfEHzmSdxoAXSaMYjomPLmbaSdBiK/CeNKF8xuFCKJRd8wOUe5FcIN3DCdk0e
|
||||
yoFye5RMC+W09Ro+tK/jTQ/sTUuNLJm0VUlddQQeoGlhQdLLwiU4PJqcyeL4KaN1
|
||||
l8cVml7xr1CdemhGV4wmEqAgxnNFN5mKnS2KcDaHxRz7MoGNdgVVQuxxaE0+OsdJ
|
||||
zCKtA12Q/OcR24qYVFg5+O+bUNhy23mqIxx0HiQ0DsK+IDvcLLWqta0aP9wd9wxG
|
||||
eObh9WkCxELTLg8xlbe0d7R3juaRjBLdD5d3UyjqGh+7zUflMsFhpUPraNXdKzvm
|
||||
AqT25cveadM7q/CNzFXeCwmKjZab8Jic8VB80KcikmX6y9eGOHwjFixBogxowlBq
|
||||
3KpeNTqJMNHYBzEb0V18P8huKVO0SMfg11Z1/nU4NA4lcjiVImb5xnJS0wARAQAB
|
||||
tCxQcmVzdG9uIFZhbiBMb29uIDxwcmVzdG9uQHByeXNtYXRpY2xhYnMuY29tPokC
|
||||
NwQTAQgAIQUCWuZ7uwIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRBy4z5N
|
||||
8aUDbtchD/4hQDTj7qsccQKpaL8furw+OWuoZtX38smO9LrcSoLaZlk5NRxFNlhQ
|
||||
FaL6iyDLoDkWUXEPg94x1dMFBUfMdIuh6iEF2pcvCN6WG3Pd2j2kG6OxaIx+rI7a
|
||||
eaD2Wds312etYATu+7AI6pxlQVqPeZi6kZVvXo8r9qzEnl1nifo7d3L4ut6FerDz
|
||||
/ptvIuhW++BEgksILkwMA44U7owTllkZ5wSbXRJer0bI/jLPLTaRETVMgWmF5L2n
|
||||
PWKhBnhBXf/P00zTHVoba0peJ/RGdzlb1JZH+uCQk0wGBl0rBMUmiihIB8DZBZDX
|
||||
5prwMdoHG9qAT9SuJ8ZOjPKaBHVVVw4JOU6rX2+p9E49CVATsdoPfWVbNyVRGi5f
|
||||
Oo0bJPZU3uO10Q09CIeyqT6JPDCZYS7po2bpfFjQTDkoIv0uPWOsV5l3cvFxVlcD
|
||||
Pvir4669xhujmoVBOrp18mn/W/rMft2TJ84inp0seKSKdwBUeEyIZwwu1YTorFe4
|
||||
bgJghDu/Y+K4y0wq7rpPimoiXSoJOaaIPrOzsKAVu20zJB4eoulXlPwHexix8wwf
|
||||
xeVH4bGl3wtTFWKja0+EQVdxpt+uUlABvrheQbNlNGz5ROOAtjvwASI3YW/jVVaG
|
||||
wSbOUuMEHfC1rSnj5Y9fN6FbilxJAZ2UbvZE6iXqqemfRdFuB5yedbQmUHJlc3Rv
|
||||
biBWYW4gTG9vbiA8cHJlc3RvbjkwQGdtYWlsLmNvbT6JAjcEEwEIACEFAlqrvbMC
|
||||
GwMFCwkIBwIGFQgJCgsCBBYCAwECHgECF4AACgkQcuM+TfGlA269zg/9FynobfLE
|
||||
Vh+Aid7l5C6pprHflHpdNVhdHzjvosLKfPMCcBJLyCLAIueKC0vvKbt5kyNV6Adl
|
||||
6fibdO/vRrNsEdmKXTdfDnN03yVX+VO54rqyuweR09CbLHakECh5awWpk0x9E/Gc
|
||||
3MlU8YDCVNPcWAw8JPZZ0y6s50/MFFXya+/opw45neH6WXrbqbIapzZ4V1bhkloF
|
||||
TTz7LYp1dk6qjus/f1jHgujclJ6FazG+OqCpzJ22lnuwNYs8sv1DclW+lEUfIin5
|
||||
PvzcSRCCd6NilFRSGzfBhM7wxZrAp0JzWXpM1jmd2WHtgErusTaTXRTATjPf9Chg
|
||||
SE9UT3EJvJ5fPxuxm+qOAowpJwe8Irv+YuMzL8C6C2BhZIV8XID3/cErNeQbPocj
|
||||
QFksmBEwpe9EG3Yhd5SmSXRhCtBFnyFKyOqPpAE2s+U0b7qsnWc50UFbIytPEm4C
|
||||
YmdNL6IVilp/+LYFcRWWK/ppOtvtgbj8r7+Foidi/tCauJGt2BzhWH7DkLEdXGxk
|
||||
PfR/rTgyuAQZowl03DaNwAPKegY2SIuROO9kpQACwTWZNg4l2yrZv09qrKBhohyn
|
||||
b2i4pwHPZ5/bWLikdzENcJuvbH5qhf6tV0FIaNGbTkWX00uI++bvWAxxE25jZv56
|
||||
e7VTaWuMt8Ly4DBcwl5JyWuvZ74+yv7QGp20WlByZXN0b24gVmFuIExvb24gKDB4
|
||||
ZjcxRTlDNzY2Q2RmMTY5ZURGYkUyNzQ5NDkwOTQzQzFEQzZiOEE1NSkgPHByZXN0
|
||||
b25AbWFjaGluZXBvd2VyZWQuY29tPokCNwQTAQgAIQUCWllQ7QIbAwULCQgHAgYV
|
||||
CAkKCwIEFgIDAQIeAQIXgAAKCRBy4z5N8aUDbmvdD/4jkT1IXJyj65sgHus0HHYC
|
||||
MBp6mzvtpDcPljg/5Nl1WXydv4zYGnEnIwWIqDYwwvokOKllxAjgevcplHqZa0cb
|
||||
7XKCFk5h+56FLPHv9e0WK1fOFeo2ad3imNRstSHgaumGAWHJMg9vWbDisGv1zjQ0
|
||||
usFkrMKoX34YzMt8KBD7IuQyeBkYNupT8EfByeA9Ta+wkvS+X6BojsFB1UWDAFCY
|
||||
z8RgTcWIFjWtGZwIkWUKCzebqXbElpJF8ckZU9q4qVhyZ2DT+8BS/Lm0Sf4z6VTC
|
||||
4EN10ZuN+F+J3DMR2Zuudp4X5OUGkDG4KuU/kvj6EJRWpbTS1D9ReK7hoApIbV72
|
||||
Um6Mf7kC9EKvxgL1gOfl4aj3Io9M0R8FT/0WSMduQzf/jI3XqdNH0nYo2kTDdZm8
|
||||
S972cyvt6frKYy6RsOlPz1+S61iCmupsRY+HyKDTa0vnpXg2c4dE1neF5eMI6SVw
|
||||
viJvCG2cflctJ2PLiINZJYAg87gV5Rm1i/Lt2YG5zdxAXXJt2R0uuU9fv4DcHZLU
|
||||
yx69Yuh+5UiEaXYU7xoRCdZJYyHbvaC2hPcDGnEa3K1QbgnI5hGAtG3cwdbYC5e3
|
||||
bcaJb/LdwzkdRnHLgpxa/UTAIfejEI1U2kvVvNoe/HvEXq/OPrhFDvE4rW8AzbX+
|
||||
ISTWWRY0lLSr8/SD0TDJMbkBDQRam2geAQgA0kESOibOO3CcXrHtqP9lPGmj6rVe
|
||||
G18fRmPDJiWtx863QqJeByuuUKwrGkPW/sqtIa5Ano+iXVHpk7m955nRjBmz4gd8
|
||||
xqSGZd9XpNObYPA5iirAO8ztpgQvuvsHH9y9Ge50NnR7hQSMUbGVeCUU/vljwT60
|
||||
/U+UPnsTAmkhvkEI72x50l5Ih9ihcBcr5jJpi08XktE3sFOoannac0kZQJ6WXFrY
|
||||
4ILbv8fVqcRf44xMKOlFB9qHhleGW0H9ZUjTKs9quRt7r5D1MOiwrZDjNN3LqMco
|
||||
oWj37hb+3KkmIIsAYB2DjnWYkMPu2B0O4uSOHYAWfEJtRvA8qW7sWj+q1wARAQAB
|
||||
iQIlBBgBCAAPBQJam2geAhsgBQkB4TOAAAoJEHLjPk3xpQNulz0P/2m9veAAGGCO
|
||||
yPsqiNVVa8lrhmLGh/W+BaoszQ/r+pfin4xTOV5K5h3MC5CVJM0JxP/cxNol+Nmr
|
||||
cYGbZgq4QhLlH6PdQ7cReL5ED6Wi+eHb4ocvXJqUuZ2Gl8Z7gzQzp+WFbLrn8vXj
|
||||
LcyGGEETV84jy+X5cKu24eAjTFK+unfqwfxXFZP5vhIEVe7+uG6A/pMB5eLDqEUh
|
||||
FQUcWqCF2Imt08Kcn7HL31GoIY0ABHdD+ICXZE5lTm6iJGzpFBKdTMm/e5igCJ3v
|
||||
/tgtWZbnvyseLR/T/gU1JyheS9kNXP5sICwicBbY/vnGdEP6OKpDOSfQam5x4BBj
|
||||
cvsBnsNuonY7OJn4iLY6LviQ0MM91PbaJUUJrp9Uyi4hj9iO/MZBaG0Giu0FKjG6
|
||||
Vk+RlCYPjYIvHflQLZHe9BWLPN1AvaLKszt3IYaxS5seXCu0ZqHDGCBVqVCNDDJk
|
||||
MJbHlrOVZ9T6mZhA+aQ1EJvTWk3MNj1AOyCJdiXtOOdg+4Fm5dN7nLpumLIg2yP2
|
||||
afI7YfrPGA7sm+T0IMnOWxkK+KODC7OV9h/QjyBJDcUYGXLapuK9eP80cr8hKvH7
|
||||
S3G4Top/rXDpnBNQ2azCqmUwaJWNRhLucC80Vd00d4pWIOwAPWpiV70Fq8OhQFhT
|
||||
PNXwFXVLwtNfPvPxN1s+Vk+BBXp+M19AuQENBFqbaC8BCADSq89Z9xWRS2fvWI/N
|
||||
+yEWliIU8XiqC9Ch+/6mS2LEyzB1pPLIIQcRvM6rq2dxXIRveVGpb63ck9vUtuJG
|
||||
//es+DnDkO7re+ZmWHX+LAqMYNdaobSYxHkkR4CcY2HbPSEUbb//Zwk4BDyp3g3W
|
||||
bKK9noVbslZuSwWNrxjX/Hieh/dIGYkNFeWOlmNfUYsevzqNDjsziOagyXKxLc++
|
||||
hUM3GKgzXRQJBvBpgzQc4bRY+YGHXtZurk9AiZ4ZBhWv2Qrb5OYYislE9sdv3KWV
|
||||
Iv1EBpbkAJ9MM1HgS8bkIOIpNs4XxHY6fTWWdrXi+NgZXQwQRYaWTQsXL3mktarS
|
||||
fFfTABEBAAGJAiUEGAEIAA8FAlqbaC8CGwwFCQHhM4AACgkQcuM+TfGlA24vqg/8
|
||||
CsVBHO4mh8SSaxdWNEU+mG4pU230BRCwrfn42wuSKb7WNLTTcWMDNI0KY/JNcWSq
|
||||
G2qa6lngiAyOS72Jd635ptZ6Wvjd0WtBt90NN2jtn+aRqwQ8uItlYMQscofFzskj
|
||||
QnBF+NWER+44nxboghuQ041m6aI2XmYUErSOBZi6onbC3svH6coMldkkiueWFbdB
|
||||
qac3UXue4LUcaGR5T9pCQsLgTl3D8V5icEM+HpTVVGQZkVrOuKMKe6T9N5FS/WFu
|
||||
T6CuFf/OyU15a6RE4WW9QqKYsaHl8B6+0P7uqPoVIxs8hfJcwaUu9XwIiZYBZg7N
|
||||
yYCQ7JBapC5KZlIcTCfFSxby8lCJoZbIM3Pk/pgCuKxGaS9rHHUGuIvz8TfnM9FO
|
||||
2zlxl4E6k3NFgGKF3p6oiKayC74o6EOw50p6DMjrisG7kkWVsTRCMINF7CcfeVme
|
||||
MI9ljGAMB1hPtHPhl27hMRfq+/iIbR9gb7+Xw2yKQL2QRjMDIGGxP3q4NjD4tV8P
|
||||
VyTbAAwNARG8oMpNM628v3tsW+WYNot1SPUQuZbIx1pCwMeTqljWsdQxWRVW5UxM
|
||||
dnXTCqZhQwH0ICG/jbepbP6ciVB/CSa7TVohEK6jiTMorhqynRMMJ6p48Z6HIlyY
|
||||
0Ss8q9K29eXaqmLB8Oy3HmupqxH95TqMntqivzf6i6e5AQ0EWptoPQEIAL1OdDIl
|
||||
7E3VKAEWH5GnMzdnl9bju/ovoMjLqGevHS9Gyz4OPyZvCQ2pS8k0sgqwsn4F8vWM
|
||||
7L3xKTyQTSYOPby3do58+kxUrdTNlqGKEEcZDG+MSzxKyft7m+37fzbg6tcU+O3L
|
||||
/7m8nYWQSRKJeist7Q8HrQJzehuzcgAnNmpeBqXHnAwRBvtqORvz5cQAIQ4EsEvP
|
||||
f/unTjw95JtL1LtBOaOaynF9ap/TZ34OvDdARmZSdqPpRtEvjfgIboIYYt1dNmDH
|
||||
kiSaaKaqBLCJTD2z5KT8ccDeF8lzYHAYzNy8v2lTc9vagCZH+lf3d2d6umNcr4y1
|
||||
NGEN4ZEhrmt/lP0AEQEAAYkDRAQYAQgADwUCWptoPQIbAgUJAeEzgAEpCRBy4z5N
|
||||
8aUDbsBdIAQZAQgABgUCWptoPQAKCRD619WmVzqkJDTvB/49MQNQk8YJTwAnbdSH
|
||||
7stU2uQFBbkljE8Juz5WJK53lL6xUVUp/3gKrQio1F+z9uRVqRh0cQnqX6mPMe5a
|
||||
2dlHEIDHTJjSlR5GCCBRDbssV6SN72xSVgbxVGZ9L32qUYtiwGnxwXQC9D9KsonD
|
||||
YfGfUhD1CLAldr6HwhJkOq4QKz5GF4ty8sMKEcpM5UaR2sa2y6Ebn9Vzma10YaVp
|
||||
X7RlZM/iTiDhTmWuxLh7e21DI95k/eFqHpKA912N0n1BdzZPbwk83nVRxXg793NU
|
||||
RFpegzlLawtaCW9oVJOYqErMGOYN5nbXAHXsr5X7Or70v1Yo1khgzNOfnirO57T9
|
||||
VjT0J1QP/j1xobgMuNda7Fpwc0xo2oIKEf+SWY9GQrkUK7wCLDbpgbGVxTmREkyE
|
||||
6oyDzW1QpQXRjLS9Wvtun0J3Wn6r6Aar0VaGKa7uiiq8UORWtFkWQAzzyBj87Rjx
|
||||
eWZWV1dzLK7eMJdyN0gsOzcejrsOqf1sydzvhm4K66byjDZ78piv0DdyPIb4OsiQ
|
||||
QU2GH+QwGRYIkYlU9f9g+hSasAfzvrATHlJZNrOjOCgXbut/yP9ug3DHKj76wmoU
|
||||
n/Y4rpmskAzIQrZIpimkpNBmZVTGr4bkWcokVzrRFor3NCpl1qA1K9Cd43wARH8t
|
||||
Zwk4evI4abbqUId0vVNCKSSDyCCjgNwRsmU8RXdn7r0vs4ObKuWfY9Yl2y8tq3qO
|
||||
YPHr0r50YXWtKqUNy5JUc3Ow9DFR1p4O4yfmiSyTLUyOYbglfvtnO32OJkrrZ8Kq
|
||||
iSDnyiq9u2nYJAEHk7AchF5TJrTCnd8yWNIjohild+wc+rMKktspoEcxmT6zaK4T
|
||||
AymmEe3jzQhlxptpBm68t2E5kaYFQh+NnizXlRcmFjBgEhH2CxCoerUpK82Y+MuE
|
||||
S/ODmF9kULre14aXAAspj4vldQ/LJm0SYEfTkE1sDipJQUzv6oS5AFloQDXZPWTB
|
||||
15P+Xsj8sJV9hWCfJZVmppWuPg/pCYXwdjUHUYouTz3ZL6qnUbm2uQINBFpZUO0B
|
||||
EADZkfsbXPpDcMALUgVmB3cJU90tFqc8Q5guK9oSs3ibx4SmyhBVmeF2TF6PQNoK
|
||||
YvpUR50hAcx2AbwtY51u0XxrAr8kFiL6R5ce/0pVMfXGchcC58CJ3uf+O+OPt080
|
||||
ftyVSTsY9xEnBohMoJescn0L/IPaM6KkkIFIMAI4Ct3QCHox7WHgPLrqB7Efx2Dj
|
||||
Qkgjbioqj8zVKDwxTs0S3sknch675gOhsCkaI7KMcRGACDinKRF3wQha4brNa8En
|
||||
vPTV01Cv0ttCo6NCcbQzQi8QQYpMQcWVkquEJWweZQvL/OvYWdT13JgnIp66pkmo
|
||||
+JvGTOqQpSnIx6OQnV9yqwqsg4E0dkCE+9rDYAHpwvmRkaI2sItjN4KAEQdTWES8
|
||||
RgGVgfCtvNH87PqpaPIgarMDY/j5KqTDp/7Nc5oGLCmhwZiYzQa7Bm5uVNnYIyOO
|
||||
d1IjfclgVdVAzMOmrFytvXFCBcga1khL15taC7s6Vuld89TgMZdSot2RVz8W8Xc+
|
||||
39ZrBvzrCeYsPq5/U0Z85cnOSw4skwh06wsxTvL1D70SilI2c0YdR1sVgbhq04HN
|
||||
7FyE7SDQ1GqxyTJAU+OPH3Pk97Bl25vWD43RCCIjSUHhKzQRPno2ItObFepE+QJH
|
||||
lSO1YMXmZDAfsRts3dca3VSDOdAQely6G7HQu5kXWXGtRQARAQABiQIfBBgBCAAJ
|
||||
BQJaWVDtAhsMAAoJEHLjPk3xpQNuRlsQAKnkyjjXRvfMB3eKZ1PrWf7DBx5WL8Hk
|
||||
r2QAnv0diDeRTzotQyzKivf3/W3gQc9kQi/ilaPuuXeW+yKiNQaIbai7EC0DdyHa
|
||||
qG9s8F7UDoojFOGCc3OVpQvuucVbv4a6EpqXBI6ayrQW0jMXakiuIF/dL5uCGRLn
|
||||
sPMB87xJfMrkqEziymJMooQTRckgj2S9J2QYDZFxmKChPl1kXMlmx6Y4FhzrsYwo
|
||||
I47hW9hHG1+8129FOgwYTwELEuX6FKShcKpyy77b4Tar3UvdzNkfaysFPvX3O7Oh
|
||||
Bes2VgfslEZSgK2CScigvLIz9Ehe9CUw6WEC6LZW3bbC+Cbz624gOsm/GYI9Llsc
|
||||
5/NMMwQTCoTRm+b0UAYQvzHDS7km9yceNSfFlkpE/lWnIt9E0H+8bOwEbYF8y2qy
|
||||
yLXIm7MYEm4UnUZ0j8kihP+wSHsZP2xPhjEUcQw1ZWhWLACvzlEC0a3zsovoJ6U8
|
||||
zrqqfEBtuQgfwwJRWArMLQn/rlEJSrTrFfehwhvH3dPVSU36N5nBA8ls5YlSHBQv
|
||||
38dChpBXu3wzFhetkSuHxdlfopeZMtDmljnIkBNTEFg01oqJNPbyiX2JQcfKizCt
|
||||
maCIiJY+hOYIKkJdkt1FyOhADBciebxCQrpIIzWupeyQNuVj3I4g6YaQX00+kgiB
|
||||
H1XKrAg/dpMNmQENBFrHiEoBCADASg9zHYzaSU0/1q1hcmTHU6H4syCQXHHd3zF7
|
||||
n/RcsGnt4RBuUi/BUvNp3zYR6uFOyyk6LPV1hq2Ca8e/oSFrDYxqLladESQd9GNN
|
||||
stDeK3HinsWJCVwSbkzNJbUtyr6SclmWt66vNqBZngMallJRQe8QDqpg0ZSZj/0d
|
||||
VGxPBR16zc/2ddGnXJFe/V5XAWAap9SEo44pyGK4xf87Bgq8jT33LuQtd8exOk3E
|
||||
atkK5jLEn9xmiheoSePEhOoQSrJMHfMjFka0PYZlCeaaHw7r7yXb/VoHFOAPxb6k
|
||||
a1cunbp39b4z7Jy9kLBy0tbDnAs/sLp4LUN3Vx1JLoXBSIsHABEBAAG0JFJhdWwg
|
||||
Sm9yZGFuIDxyYXVsQHByeXNtYXRpY2xhYnMuY29tPokBNwQTAQoAIQUCWseISgIb
|
||||
AwULCQgHAwUVCgkICwUWAgMBAAIeAQIXgAAKCRCVRSpwGBD+26lmB/wJxChWwva0
|
||||
StjMRSk3V7JTBPi5RNQm3VY8UydUNjsXzHVvtjUczOj+zHfo8tYUYa/ypWujXEX9
|
||||
bVYVMr9JGNjm+rysI1gmW1gcx9pZr9gde4CR4Owfpwjh8oFnSrBBrcaelb0Krrv4
|
||||
Okms43fEw1bWpllayal5SqknOIxpw1ZiNpG3jVe/C9n1/3Nw4XF5R0RHDxXTu6Hu
|
||||
H3t7zRQwAJcOod6ccRdzNR9CsGdnOoNPG3pqs9w6zWUp0QETMAMcEpSLCJumaVfQ
|
||||
24PK+MF92F5JRwNVt80xSLA9KMyNnv/ZvxZXXLjkIhsAmwYkHUs3WSm5HJ4qqOCX
|
||||
V8VwFbwnea3eiQIzBBABCgAdFiEECuAFHWR7o8GpF69AcuM+TfGlA24FAl9zs2AA
|
||||
CgkQcuM+TfGlA24dMA/+N31SPAXVgwiNasBknb+YSq2/OQPogxQUc8tupvDcQ62H
|
||||
u0kvA7pUPUFjITJ1xsm8CRXfb7Hge9rNUw9Y2MNKf4sIDQs3bFeKOiAGVbO8Z055
|
||||
5VCTWWPhXzjWoR84YWrx0Go8WT/V3Lahy4frGA3Vsza6wzi2P6c7LF4jqX2iBD1l
|
||||
OpAYNGyt0sX/RLp3s2jOTWJwVyRR4UKSZOgpi9OTGLXrq5oU2dpwEIzBmhaWIs+u
|
||||
oD5/4TaAt4lEFu3Sxk5w8fJlUXbM4IG8A1l+dnRPF5rtjtfvuX0GeQcDtJ5e1qHj
|
||||
7PvVj8HjGPwxqsAjYHpg6QjyQCdtHYHdboEIU+OXMYRPRh2Iv0GUoeuMqoSsvFgn
|
||||
c9PGN8Ai5u+oNzKeLJhpxpLV7s9zAbsripdnvDBn7RwuNx2ziqZayxoYvFRCAQl5
|
||||
wzr0/eo/wq36D9EI7uJ2I3yt1g/VkwWQsAeE2skuGGbwed263cWTkl6g1w+vlDY3
|
||||
/jc3a8HcS0zIUX194ChrbbNezGb74mQFoLk6PksLfhXseAKCs8bvPaTwIm0JGTMT
|
||||
YzkRufrv1+I9KPFy3fTpvnMZTbud4nPCLsK179whk+Jrdv866i+E2WZ1JyzIZ9bB
|
||||
P1x+ABi82PMdzhTw+pTkR1CVHmrmOiSi2MHRYGMedM9ECGnPIdab5d75r1qkuvO5
|
||||
AQ0EWseISgEIAKHrgTVeZ0CWZMETk7NFjDTvBpoTMQDT7DDe2vFQHc8D2AvR3Aod
|
||||
+CUaOeY0Yp0GOemd7BEcUbpYbCQk1B9G8vHNcQqTMLjBgujXwF6w2c+lqEu2/tyI
|
||||
2/uGCOBDs4wuQZo+akCCMekqYjdZBfZV6nQzf/l7eQHIq+sNtnSiZmHdH46PLi7/
|
||||
17wR9GxzKvuv1R73DCyekCcz1Puo0b7lfGD28kESJK1Mg9SAOqVjtaS58Oxo+Y1M
|
||||
ZWRqh0tkAkgOBpdyddGy6TX/9c3a0U3eBQweRpNDh0eCEh5UsYDluL4NtXj7rVYd
|
||||
4mHONJzI3h1LnKWvpVYmk703MPmtgeJwNzEAEQEAAYkBHwQYAQoACQUCWseISgIb
|
||||
DAAKCRCVRSpwGBD+25PxCACNBj/2HBSpdYAxEGhNHSaw62y7Jwuf7NbsKIAqygzi
|
||||
m2+dxae7PbAm64jEXYJA5GaCOs4xO52S/2+1N87e5J86VRNg0vlA9/ivFzERAxEg
|
||||
rgIUyGXYfS8oA/4r5+PfKt/NvXO2wH3MPakrqZqXhOv+1IPvOt03wWoZKmYyVT6g
|
||||
YnzutOsvH6cbhUh/D0WpuU8ZgkrFu5Xe7ynZoLm1qQOA23pkxxQbeNs0uoKUja9v
|
||||
bx4eBtaliLc6rsXt+1WzdXA5ZRNqkdn87Tz5IU0FuQYVblYvPz9QoUlvx5siWVaP
|
||||
Mmc7dIctWaWyaJmgjkLKdy36ydS5axhqn158yIjOZV3emQINBF8h6lMBEACovC4z
|
||||
oieJ9iMZpWfylsLQKkeEmfSXnjcjW4RLUjs2CRWj+W6H7eCRy/MBOdx+6zAb8TE/
|
||||
n/TSlP5l5Xx40BGDAMUZVFrJVEkMPK5kUmNzybg7PiuMd3qZE+pNyHEXXlLU77Dn
|
||||
VO26TD9RvpKXdjm+ATsnQ6rvDNszkYI2Bj1tPxwZ7bRi96U/upL3WfYOsTLHirM3
|
||||
pEkI3zfMZj8ufDX9XlmGrQ384E/hTgjpLXmDm/jMRlX3mRzDkV1HO+gEicfePm5+
|
||||
K4eWlMCNXN5bcGwoEFY2LwAojRcbRaH/UH2S3btkG2eSK2fOFEwQ0G4vIyoLF60R
|
||||
cEk1s6cYIgk3kVsmNSzA5iJ81nD5bbfTceUKsjTZiw5RmN0Vh5g75pw+3uoXB+55
|
||||
egabEIt/GTZZlP6zhd/CKjTQR0R4+ZaEbZFOCtABukC5xfWGCRdNmXAWMBe0MYpW
|
||||
ub2TRLISLfNNc7GWM4Y17d9aRhaql9gY6QLIRNGYuvGPiRMaJADZx46LtbWo8YiG
|
||||
xLId7H8D+/0MSzMOg7RhELqYScYDigiVEXkTHA3QSprf/ohjm8woRhQY5CjCEZp5
|
||||
8MvhD40VAo4Gxgx1V8lwB3CD3kDgFEaUZh2H+N/fmRegACN2lzEm1krOiS7sAB48
|
||||
/Av99/1VXalLoBbzFTnuAYwnmLk8vdparT5LlwARAQABtChUZXJlbmNlIFRzYW8g
|
||||
PHRlcmVuY2VAcHJ5c21hdGljbGFicy5jb20+iQJOBBMBCAA4FiEEMX1ukQWPjzwj
|
||||
A7p3VjE+RFgSl6YFAl8h6lMCGwMFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQ
|
||||
VjE+RFgSl6YJgBAAqIAMzMFf/+qE896kuXYSlmaYtzhrMXgQVD09UgSq4JfVYudE
|
||||
e8EfamWz8RFV7znxHO/5Fp4yoWeDGc2b40DhivvRb1p4XSJi+F64moeHt+qn4Hay
|
||||
CDs5wGv40KJk0+2r7iILc3Gw4NP6r4c2HU2EqSW8fn/bYM3yxLsYEXt5zhgipKpR
|
||||
CB4WmqojW+CxXkj8dv4CyY+HlKJ6nZWstK42h736njM44rjMDSDt3lv0ZYykopTw
|
||||
09THnHkWOXY4PSrKOzE+OqsPMPOD3Gq3bYPqQ0ZgdS4FeuDesqqHjJabRX+7DgJK
|
||||
lLEnylfDlvDKf6I/tqrAfqCCdQvEjpdQXG84GSdK//wT1biunHvGeyHM/PZx9V5O
|
||||
X8YoecswcYjozU1F7x8buk8GxV7ZuJ2pbdXr7jTou1dA7e4Nas9Qu1RcK39MoTYc
|
||||
Ub467ONFCX+Y3MzELTnEyx4hSwTxlWg7VjCQ63zrFOd8VG0WUydlqiHgIE8WCJVE
|
||||
pQlrr2v/A6ieM1HY1Ftjt+mk/qncqibCdyIofyV4o5FrVo8arx74jR+Lhvkp1T9N
|
||||
uRj8V6M3g9vxJdAsy1O5/ZrdwKJ6Yy1n62+9b/uxhklYONK7DpDlWU0ZLWHlKEIV
|
||||
zzfILCiLf+nxMQdVwuthlcysg8JwYEE8xDXc851ciuj0ygv3Wm0BY44V6/m5Ag0E
|
||||
XyHqUwEQALuKzOAlo75p2vSYD7TecE/E0hBOS+cjs8kRH+oIzm5fx7sf00SC1jU2
|
||||
q5QLYLixNeT+l0bD70R7b8r2uFu1aZL7pQqbGIGisLHlxu8611+PCpE5AsQi3Wui
|
||||
IZ6Y8K7grJ28vviBiZUBY3iCCRH0LuvyZN3R0zgyMGbzouQk5wuGJUkRHJKtV5by
|
||||
FVEl3CYudRtAp5LPFw6j7UzT5yQqBmY6tXp5WMmmAvOtnu8ohpRhzY21dJMlSykX
|
||||
Ne9rcARy8mVWNdcXJUIc85z0BmyrdiA4YY0XiZTHD9mslj+af4QHsaS+p3aorTLD
|
||||
5BKkp5Ek79a1BUxBjrao4W2fljYf129/SHbwds/Dup26zB2vi/fhbfVPvevXLPpi
|
||||
Vm4uz8fE4D5lPYZAdu5GtO2V9kWbhDtU1R1SJSdFDI9Sev3B+NLrstclGfdbFQKF
|
||||
shbUxydjSX56OJvh5hee50PcCz+Ab+usoyUPkcOfET/L55AdqJo3cVYtnAKpOJG/
|
||||
mKP5Ih3LZVm9wCdWTCzboEtDfLlcjCc5kLiE9Pq7sKMnXm/NcXNFWBkRuaHg+Mt5
|
||||
Yk659/Q6oUG3yUrS2d7cSeuNRWNlaRlnk3hZtB13xpmoHGYmrMOe7wiEE5xEnOju
|
||||
1ctRRRX6lNUPlSvID83Y9JSYL9hYMbidRmFY28AIddT/PjVTgfi1ABEBAAGJAjYE
|
||||
GAEIACAWIQQxfW6RBY+PPCMDundWMT5EWBKXpgUCXyHqUwIbDAAKCRBWMT5EWBKX
|
||||
poMOD/4/sRLnK94pY2qtSSfNZEumOdQVvges08u34saG4mT1iLD9TcRgsFvgwcTV
|
||||
Pec9Git4iJmoJpFylvOzoBWmtDzJ7TB3JxvtwUfFH2uZ22k12eChyAFHI8TxASqI
|
||||
TV2YwkIgB2PTmva1GrdNKM6y5bfS1BdS0u+Etgp4zN9nyQECY2sM2accUi2S7JBV
|
||||
7o6lEJWCRgFUwIfY6fdfxhZo/w0g2u5wftUQYlbXWSQLImFFZBc/13k8EMxsfbMi
|
||||
LQ/wxKEfe1ZwFoXqIS6cq8CHTdj70QO7K9ah6krGPmL23LVuxlkQIR7mT5yFJtv2
|
||||
VRT4IYgOUl6rAd08B6MOy6MOMa14FpNrAybPK8Yd/eSdUNciVf17q33Yc15x+trs
|
||||
En1hHbDS82xaLJ/Ld4mANeJVt3FodgVmzZGpKheFEOFXXeuX1ZZ4c9TgX+0wBKoh
|
||||
aBb8EGBVo4aV4GbZ/gEa8wls5NNTwd56H4G94hiq+qFM39x4YjhAvkM0hLRYzR05
|
||||
tSCdlEbkh2K6RbOhBPsNHCbypWRt2fN8/q4uLPJJt7NRQ2zi6H/x04HGblhXdX6H
|
||||
mmYjJv1LTbem9VptcpvPauNsibeIvIWA2nYM2ncDWt6gJpOH9Zh4fHuaG4aCdNmJ
|
||||
hPNeJNnmLcpDQvR9wU5w7e5tC/ZSeTZ5ul1zOKa1qZ4lJ50BDQ==
|
||||
=a30p
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
@@ -3,24 +3,23 @@ Hash: SHA512
|
||||
|
||||
Contact: mailto:security@prysmaticlabs.com
|
||||
Encryption: openpgp4fpr:0AE0051D647BA3C1A917AF4072E33E4DF1A5036E
|
||||
Encryption: openpgp4fpr:341396BAFACC28C5082327F889725027FC8EC0D4
|
||||
Encryption: openpgp4fpr:FEE44615A19049DF0CA0C2735E2B7E5734DFADCB
|
||||
Encryption: openpgp4fpr:CD08DE68C60B82D3EE2A3F7D95452A701810FEDB
|
||||
Encryption: openpgp4fpr:317D6E91058F8F3C2303BA7756313E44581297A6
|
||||
Preferred-Languages: en
|
||||
Canonical: https://github.com/prysmaticlabs/prysm/tree/master/.well-known/security.txt
|
||||
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQIzBAEBCgAdFiEECuAFHWR7o8GpF69AcuM+TfGlA24FAl6HrcwACgkQcuM+TfGl
|
||||
A26voQ/8DFB5wUHP0uyY8k7FGbxhLzSeImxomnUHJaUGfdczbCdYPMEHc9zI1iZP
|
||||
6LRiy9wS6qhqj/GSKVwvDPr+ZymXuV3L22GOP2lRhl7Z9Mm21ZJNOcoQBFOZnyHu
|
||||
DAy9HeTmeuJxYkf8weqZYXyzEoKJBDmfuWmEFjrtMcFXUfT3aJn1E2A/AQdcVQIC
|
||||
9L+iGWwFwjsPhcfaMuwcB7QMheDO6KSB7XPPCbrZ036Np8UTZ4qbZ5y73tlfkcOc
|
||||
tYTrMSPtS4eNutiDOP5Np36cLzRtNpm/BziAK+7ZKiYY0HI5h9IkCTLO4x2UmAMX
|
||||
sPoeaAB5z2QLIwmU9J2NhJrwiNMGTpJ+0bowy8U4cgzAX20CXVjRqGhy+cir8Ewg
|
||||
DjEGjWINUw6W0yzJp0mKSKzuOhdTTmzIYBeMBsyce+pgN1KGFCxeIwxGxyJzADdw
|
||||
mYQdljRXn4yEYP/KEpu/F2o8L4ptRO2jZWKvTvdzSSGGSyKyF4HsIRJ7m98DaB6S
|
||||
0oGq1KpbKKTbQi5g8UShGV2gPeMCs5ZIIqK2b/cRzUet18aUuofLmR4lkKZa9yEG
|
||||
rbzuJq/gB2vgQwExUEgVQ3/DfVc+y80e3YZ5s+rzV0vbLxl4Gh4yExpLo7hRf9iY
|
||||
EFvMzH+BEEb5VfCwByZyV1BmesZVIosr7K6UmVtPe0bZGvv3uIg=
|
||||
=5qpD
|
||||
iQIzBAEBCgAdFiEECuAFHWR7o8GpF69AcuM+TfGlA24FAl++klgACgkQcuM+TfGl
|
||||
A27rQw/6A29p1W20J0v+h218p8XWLSUpTIGLnZTxw6KqdyVXMzlsQK0YG4G2s2AB
|
||||
0LKh7Ae/Di5E0U+Z4AjUW5nc5eaCxK36GMscH9Ah0rgJwNYxEJw7/2o8ZqVT/Ip2
|
||||
+56rFihRqxFZfaCNKFVuZFaL9jKewV9FKYP38ID6/SnTcrOHiu2AoAlyZGmB03p+
|
||||
iT57SPRHatygeY4xb/gwcfREFWEv+VHGyBTv8A+6ABZDxyurboCFMERHzFICrbmk
|
||||
8UdHxxlWZDnHAbAUyAwpERC5znx6IHXQJwF8TMtu6XY6a6axT2XBOyJDF9/mZOz+
|
||||
kdkz6loX5uxaQBGLtTv6Kqf1yUGANOZ16VhHvWwL209LmHmigIVQ+qSM6c79PsW/
|
||||
vrsqdz3GBsiMC5Fq2vYgnbgzpfE8Atjn0y7E+j4R7IvwOAE/Ro/b++nqnc4YqhME
|
||||
P/yTcfGftaCrdSNnQCXeoV9JxpFM5Xy8KV3eexvNKbcgA/9DtgxL5i+s5ZJkUT9A
|
||||
+qJvoRrRyIym32ghkHgtFJKB3PLCdobeoOVRk6EnMo9zKSiSK2rZEJW8Ccbo515D
|
||||
W9qUOn3GF7lNVuUFAU/YKEdmDp/AVaViZ7vH+8aq0LC0HBkZ8XlzWnWoArS8sMhw
|
||||
fX0R9g/HMgrwNte/d0mwim5lJ2Plgv60Bh4grJqwZJeWbU0zi1U=
|
||||
=uW+X
|
||||
-----END PGP SIGNATURE-----
|
||||
|
||||
@@ -352,9 +352,9 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "09a8377bd3abf76d3bd14570f001cc7f00ef0e11fe314cee626d3a3ccbae506e",
|
||||
sha256 = "117f5366af9cf009354ed1abe02f906168158473461d69c8056984b9b0292619",
|
||||
urls = [
|
||||
"https://github.com/prysmaticlabs/prysm-web-ui/releases/download/v1.0.0-beta.0/prysm-web-ui.tar.gz",
|
||||
"https://github.com/prysmaticlabs/prysm-web-ui/releases/download/v1.0.0-beta.2/prysm-web-ui.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
@@ -99,6 +100,14 @@ func (s *Service) processAttestation(subscribedToStateEvents chan struct{}) {
|
||||
<-stateChannel
|
||||
stateSub.Unsubscribe()
|
||||
|
||||
if s.genesisTime.IsZero() {
|
||||
log.Warn("ProcessAttestations routine waiting for genesis time")
|
||||
for s.genesisTime.IsZero() {
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
log.Warn("Genesis time received, now available to process attestations")
|
||||
}
|
||||
|
||||
st := slotutil.GetSlotTicker(s.genesisTime, params.BeaconConfig().SecondsPerSlot)
|
||||
for {
|
||||
select {
|
||||
|
||||
@@ -167,4 +167,10 @@ var (
|
||||
Name: "db-backup-output-dir",
|
||||
Usage: "Output directory for db backups",
|
||||
}
|
||||
// Eth1HeaderReqLimit defines a flag to set the maximum number of headers that a deposit log query can fetch. If none is set, 1000 will be the limit.
|
||||
Eth1HeaderReqLimit = &cli.Uint64Flag{
|
||||
Name: "eth1-header-req-limit",
|
||||
Usage: "Sets the maximum number of headers that a deposit log query can fetch.",
|
||||
Value: uint64(1000),
|
||||
}
|
||||
)
|
||||
|
||||
@@ -62,6 +62,7 @@ func (g *Gateway) Start() {
|
||||
ethpb.RegisterNodeHandler,
|
||||
ethpb.RegisterBeaconChainHandler,
|
||||
ethpb.RegisterBeaconNodeValidatorHandler,
|
||||
pbrpc.RegisterHealthHandler,
|
||||
}
|
||||
if g.enableDebugRPCEndpoints {
|
||||
handlers = append(handlers, pbrpc.RegisterDebugHandler)
|
||||
|
||||
@@ -57,6 +57,7 @@ var appFlags = []cli.Flag{
|
||||
flags.ChainID,
|
||||
flags.NetworkID,
|
||||
flags.WeakSubjectivityCheckpt,
|
||||
flags.Eth1HeaderReqLimit,
|
||||
cmd.MinimalConfigFlag,
|
||||
cmd.E2EConfigFlag,
|
||||
cmd.RPCMaxPageSizeFlag,
|
||||
|
||||
@@ -486,12 +486,13 @@ func (b *BeaconNode) registerPOWChainService() error {
|
||||
}
|
||||
|
||||
cfg := &powchain.Web3ServiceConfig{
|
||||
HTTPEndPoint: b.cliCtx.String(flags.HTTPWeb3ProviderFlag.Name),
|
||||
DepositContract: common.HexToAddress(depAddress),
|
||||
BeaconDB: b.db,
|
||||
DepositCache: b.depositCache,
|
||||
StateNotifier: b,
|
||||
StateGen: b.stateGen,
|
||||
HTTPEndPoint: b.cliCtx.String(flags.HTTPWeb3ProviderFlag.Name),
|
||||
DepositContract: common.HexToAddress(depAddress),
|
||||
BeaconDB: b.db,
|
||||
DepositCache: b.depositCache,
|
||||
StateNotifier: b,
|
||||
StateGen: b.stateGen,
|
||||
Eth1HeaderReqLimit: b.cliCtx.Uint64(flags.Eth1HeaderReqLimit.Name),
|
||||
}
|
||||
web3Service, err := powchain.NewService(b.ctx, cfg)
|
||||
if err != nil {
|
||||
@@ -507,7 +508,10 @@ func (b *BeaconNode) registerPOWChainService() error {
|
||||
}
|
||||
}
|
||||
if len(knownContract) > 0 && !bytes.Equal(cfg.DepositContract.Bytes(), knownContract) {
|
||||
return fmt.Errorf("database contract is %#x but tried to run with %#x", knownContract, cfg.DepositContract.Bytes())
|
||||
return fmt.Errorf("database contract is %#x but tried to run with %#x. This likely means "+
|
||||
"you are trying to run on a different network than what the database contains. You can run once with "+
|
||||
"'--clear-db' to wipe the old database or use an alternative data directory with '--datadir'",
|
||||
knownContract, cfg.DepositContract.Bytes())
|
||||
}
|
||||
|
||||
log.Infof("Deposit contract: %#x", cfg.DepositContract.Bytes())
|
||||
@@ -598,6 +602,8 @@ func (b *BeaconNode) registerRPCService() error {
|
||||
|
||||
host := b.cliCtx.String(flags.RPCHost.Name)
|
||||
port := b.cliCtx.String(flags.RPCPort.Name)
|
||||
beaconMonitoringHost := b.cliCtx.String(cmd.MonitoringHostFlag.Name)
|
||||
beaconMonitoringPort := b.cliCtx.Int(flags.MonitoringPortFlag.Name)
|
||||
cert := b.cliCtx.String(flags.CertFlag.Name)
|
||||
key := b.cliCtx.String(flags.KeyFlag.Name)
|
||||
mockEth1DataVotes := b.cliCtx.Bool(flags.InteropMockEth1DataVotesFlag.Name)
|
||||
@@ -607,6 +613,8 @@ func (b *BeaconNode) registerRPCService() error {
|
||||
rpcService := rpc.NewService(b.ctx, &rpc.Config{
|
||||
Host: host,
|
||||
Port: port,
|
||||
BeaconMonitoringHost: beaconMonitoringHost,
|
||||
BeaconMonitoringPort: beaconMonitoringPort,
|
||||
CertFlag: cert,
|
||||
KeyFlag: key,
|
||||
BeaconDB: b.db,
|
||||
|
||||
@@ -31,7 +31,7 @@ var (
|
||||
|
||||
const eth1LookBackPeriod = 100
|
||||
const eth1DataSavingInterval = 100
|
||||
const eth1HeaderReqLimit = 1000
|
||||
const defaultEth1HeaderReqLimit = uint64(1000)
|
||||
const depositlogRequestLimit = 10000
|
||||
|
||||
// Eth2GenesisPowchainInfo retrieves the genesis time and eth1 block number of the beacon chain
|
||||
@@ -276,7 +276,7 @@ func (s *Service) processPastLogs(ctx context.Context) error {
|
||||
}
|
||||
for currentBlockNum < latestFollowHeight {
|
||||
start := currentBlockNum
|
||||
end := currentBlockNum + eth1HeaderReqLimit
|
||||
end := currentBlockNum + s.eth1HeaderReqLimit
|
||||
// Appropriately bound the request, as we do not
|
||||
// want request blocks beyond the current follow distance.
|
||||
if end > latestFollowHeight {
|
||||
|
||||
@@ -149,16 +149,18 @@ type Service struct {
|
||||
runError error
|
||||
preGenesisState *stateTrie.BeaconState
|
||||
stateGen *stategen.State
|
||||
eth1HeaderReqLimit uint64
|
||||
}
|
||||
|
||||
// Web3ServiceConfig defines a config struct for web3 service to use through its life cycle.
|
||||
type Web3ServiceConfig struct {
|
||||
HTTPEndPoint string
|
||||
DepositContract common.Address
|
||||
BeaconDB db.HeadAccessDatabase
|
||||
DepositCache *depositcache.DepositCache
|
||||
StateNotifier statefeed.Notifier
|
||||
StateGen *stategen.State
|
||||
HTTPEndPoint string
|
||||
DepositContract common.Address
|
||||
BeaconDB db.HeadAccessDatabase
|
||||
DepositCache *depositcache.DepositCache
|
||||
StateNotifier statefeed.Notifier
|
||||
StateGen *stategen.State
|
||||
Eth1HeaderReqLimit uint64
|
||||
}
|
||||
|
||||
// NewService sets up a new instance with an ethclient when
|
||||
@@ -176,6 +178,11 @@ func NewService(ctx context.Context, config *Web3ServiceConfig) (*Service, error
|
||||
return nil, errors.Wrap(err, "could not setup genesis state")
|
||||
}
|
||||
|
||||
eth1HeaderReqLimit := config.Eth1HeaderReqLimit
|
||||
if eth1HeaderReqLimit == 0 {
|
||||
eth1HeaderReqLimit = defaultEth1HeaderReqLimit
|
||||
}
|
||||
|
||||
s := &Service{
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
@@ -201,6 +208,7 @@ func NewService(ctx context.Context, config *Web3ServiceConfig) (*Service, error
|
||||
preGenesisState: genState,
|
||||
headTicker: time.NewTicker(time.Duration(params.BeaconConfig().SecondsPerETH1Block) * time.Second),
|
||||
stateGen: config.StateGen,
|
||||
eth1HeaderReqLimit: eth1HeaderReqLimit,
|
||||
}
|
||||
|
||||
eth1Data, err := config.BeaconDB.PowchainData(ctx)
|
||||
@@ -377,20 +385,38 @@ func (s *Service) dialETH1Nodes() (*ethclient.Client, *gethRPC.Client, error) {
|
||||
return nil, nil, err
|
||||
}
|
||||
httpClient := ethclient.NewClient(httpRPCClient)
|
||||
|
||||
// Add a method to clean-up and close clients in the event
|
||||
// of any connection failure.
|
||||
closeClients := func() {
|
||||
httpRPCClient.Close()
|
||||
httpClient.Close()
|
||||
}
|
||||
syncProg, err := httpClient.SyncProgress(s.ctx)
|
||||
if err != nil {
|
||||
closeClients()
|
||||
return nil, nil, err
|
||||
}
|
||||
if syncProg != nil {
|
||||
closeClients()
|
||||
return nil, nil, errors.New("eth1 node has not finished syncing yet")
|
||||
}
|
||||
// Make a simple call to ensure we are actually connected to a working node.
|
||||
cID, err := httpClient.ChainID(s.ctx)
|
||||
if err != nil {
|
||||
closeClients()
|
||||
return nil, nil, err
|
||||
}
|
||||
nID, err := httpClient.NetworkID(s.ctx)
|
||||
if err != nil {
|
||||
closeClients()
|
||||
return nil, nil, err
|
||||
}
|
||||
if cID.Uint64() != params.BeaconNetworkConfig().ChainID {
|
||||
closeClients()
|
||||
return nil, nil, fmt.Errorf("eth1 node using incorrect chain id, %d != %d", cID.Uint64(), params.BeaconNetworkConfig().ChainID)
|
||||
}
|
||||
if nID.Uint64() != params.BeaconNetworkConfig().NetworkID {
|
||||
closeClients()
|
||||
return nil, nil, fmt.Errorf("eth1 node using incorrect network id, %d != %d", nID.Uint64(), params.BeaconNetworkConfig().NetworkID)
|
||||
}
|
||||
|
||||
|
||||
@@ -504,3 +504,26 @@ func TestNewService_EarliestVotingBlock(t *testing.T) {
|
||||
assert.Equal(t, followBlock-conf.Eth1FollowDistance, blk, "unexpected earliest voting block")
|
||||
|
||||
}
|
||||
|
||||
func TestNewService_Eth1HeaderRequLimit(t *testing.T) {
|
||||
testAcc, err := contracts.Setup()
|
||||
require.NoError(t, err, "Unable to set up simulated backend")
|
||||
beaconDB, _ := dbutil.SetupDB(t)
|
||||
|
||||
s1, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndPoint: endpoint,
|
||||
DepositContract: testAcc.ContractAddr,
|
||||
BeaconDB: beaconDB,
|
||||
})
|
||||
require.NoError(t, err, "unable to setup web3 ETH1.0 chain service")
|
||||
assert.Equal(t, defaultEth1HeaderReqLimit, s1.eth1HeaderReqLimit, "default eth1 header request limit not set")
|
||||
|
||||
s2, err := NewService(context.Background(), &Web3ServiceConfig{
|
||||
HTTPEndPoint: endpoint,
|
||||
DepositContract: testAcc.ContractAddr,
|
||||
BeaconDB: beaconDB,
|
||||
Eth1HeaderReqLimit: uint64(150),
|
||||
})
|
||||
require.NoError(t, err, "unable to setup web3 ETH1.0 chain service")
|
||||
assert.Equal(t, uint64(150), s2.eth1HeaderReqLimit, "unable to set eth1HeaderRequestLimit")
|
||||
}
|
||||
|
||||
@@ -265,7 +265,7 @@ func (bs *Server) StreamIndexedAttestations(
|
||||
}
|
||||
if data.Attestation == nil || data.Attestation.Aggregate == nil {
|
||||
// One nil attestation shouldn't stop the stream.
|
||||
log.Info("Indexed attestations stream got nil attestation or nil attestation aggregate")
|
||||
log.Debug("Indexed attestations stream got nil attestation or nil attestation aggregate")
|
||||
continue
|
||||
}
|
||||
bs.ReceivedAttestationsBuffer <- data.Attestation.Aggregate
|
||||
@@ -340,7 +340,7 @@ func (bs *Server) collectReceivedAttestations(ctx context.Context) {
|
||||
// We aggregate the received attestations, we know they all have the same data root.
|
||||
aggAtts, err := attaggregation.Aggregate(atts)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not aggregate collected attestations")
|
||||
log.WithError(err).Error("Could not aggregate attestations")
|
||||
continue
|
||||
}
|
||||
if len(aggAtts) == 0 {
|
||||
@@ -356,7 +356,7 @@ func (bs *Server) collectReceivedAttestations(ctx context.Context) {
|
||||
case att := <-bs.ReceivedAttestationsBuffer:
|
||||
attDataRoot, err := att.Data.HashTreeRoot()
|
||||
if err != nil {
|
||||
log.Errorf("Could not hash tree root data: %v", err)
|
||||
log.Errorf("Could not hash tree root attestation data: %v", err)
|
||||
continue
|
||||
}
|
||||
attsByRoot[attDataRoot] = append(attsByRoot[attDataRoot], att)
|
||||
|
||||
@@ -38,7 +38,7 @@ func (bs *Server) ListBlocks(
|
||||
case *ethpb.ListBlocksRequest_Epoch:
|
||||
blks, _, err := bs.BeaconDB.Blocks(ctx, filters.NewFilter().SetStartEpoch(q.Epoch).SetEndEpoch(q.Epoch))
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Failed to get blocks: %v", err)
|
||||
return nil, status.Errorf(codes.Internal, "Could not get blocks: %v", err)
|
||||
}
|
||||
|
||||
numBlks := len(blks)
|
||||
@@ -194,12 +194,12 @@ func (bs *Server) StreamBlocks(_ *ptypes.Empty, stream ethpb.BeaconChain_StreamB
|
||||
}
|
||||
headState, err := bs.HeadFetcher.HeadState(bs.Ctx)
|
||||
if err != nil {
|
||||
log.WithError(err).WithField("blockSlot", data.SignedBlock.Block.Slot).Warn("Could not get head state to verify block signature")
|
||||
log.WithError(err).WithField("blockSlot", data.SignedBlock.Block.Slot).Error("Could not get head state")
|
||||
continue
|
||||
}
|
||||
|
||||
if err := blocks.VerifyBlockSignature(headState, data.SignedBlock); err != nil {
|
||||
log.WithError(err).WithField("blockSlot", data.SignedBlock.Block.Slot).Warn("Could not verify block signature")
|
||||
log.WithError(err).WithField("blockSlot", data.SignedBlock.Block.Slot).Error("Could not verify block signature")
|
||||
continue
|
||||
}
|
||||
if err := stream.Send(data.SignedBlock); err != nil {
|
||||
|
||||
@@ -358,7 +358,7 @@ func (is *infostream) generatePendingValidatorInfo(info *ethpb.ValidatorInfo) (*
|
||||
if deposit.block != nil {
|
||||
info.Status = ethpb.ValidatorStatus_DEPOSITED
|
||||
if queueTimestamp, err := is.depositQueueTimestamp(deposit.block); err != nil {
|
||||
log.WithError(err).Error("Failed to obtain queue activation timestamp")
|
||||
log.WithError(err).Error("Could not obtain queue activation timestamp")
|
||||
} else {
|
||||
info.TransitionTimestamp = queueTimestamp
|
||||
}
|
||||
@@ -415,7 +415,7 @@ func (is *infostream) calculateActivationTimeForPendingValidators(res []*ethpb.V
|
||||
for curEpoch := epoch + 1; len(sortedIndices) > 0 && len(pendingValidators) > 0; curEpoch++ {
|
||||
toProcess, err := helpers.ValidatorChurnLimit(numAttestingValidators)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Failed to determine validator churn limit")
|
||||
log.WithError(err).Error("Could not determine validator churn limit")
|
||||
}
|
||||
if toProcess > uint64(len(sortedIndices)) {
|
||||
toProcess = uint64(len(sortedIndices))
|
||||
@@ -456,7 +456,7 @@ func (is *infostream) handleBlockProcessed() {
|
||||
is.currentEpoch = blockEpoch
|
||||
if err := is.sendValidatorsInfo(is.pubKeys); err != nil {
|
||||
// Client probably disconnected.
|
||||
log.WithError(err).Debug("Failed to send infostream response")
|
||||
log.WithError(err).Debug("Could not send infostream response")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ go_library(
|
||||
"//beacon-chain/db:go_default_library",
|
||||
"//beacon-chain/p2p:go_default_library",
|
||||
"//beacon-chain/sync:go_default_library",
|
||||
"//proto/beacon/rpc/v1:go_default_library",
|
||||
"//shared/version:go_default_library",
|
||||
"@com_github_gogo_protobuf//types:go_default_library",
|
||||
"@com_github_libp2p_go_libp2p_core//network:go_default_library",
|
||||
@@ -32,6 +33,7 @@ go_test(
|
||||
"//beacon-chain/p2p:go_default_library",
|
||||
"//beacon-chain/p2p/testing:go_default_library",
|
||||
"//beacon-chain/sync/initial-sync/testing:go_default_library",
|
||||
"//proto/beacon/rpc/v1:go_default_library",
|
||||
"//shared/bytesutil:go_default_library",
|
||||
"//shared/testutil:go_default_library",
|
||||
"//shared/testutil/assert:go_default_library",
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/sync"
|
||||
pbrpc "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/version"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
@@ -27,13 +28,15 @@ import (
|
||||
// providing RPC endpoints for verifying a beacon node's sync status, genesis and
|
||||
// version information, and services the node implements and runs.
|
||||
type Server struct {
|
||||
SyncChecker sync.Checker
|
||||
Server *grpc.Server
|
||||
BeaconDB db.ReadOnlyDatabase
|
||||
PeersFetcher p2p.PeersProvider
|
||||
PeerManager p2p.PeerManager
|
||||
GenesisTimeFetcher blockchain.TimeFetcher
|
||||
GenesisFetcher blockchain.GenesisFetcher
|
||||
SyncChecker sync.Checker
|
||||
Server *grpc.Server
|
||||
BeaconDB db.ReadOnlyDatabase
|
||||
PeersFetcher p2p.PeersProvider
|
||||
PeerManager p2p.PeerManager
|
||||
GenesisTimeFetcher blockchain.TimeFetcher
|
||||
GenesisFetcher blockchain.GenesisFetcher
|
||||
BeaconMonitoringHost string
|
||||
BeaconMonitoringPort int
|
||||
}
|
||||
|
||||
// GetSyncStatus checks the current network sync status of the node.
|
||||
@@ -117,6 +120,13 @@ func (ns *Server) GetHost(_ context.Context, _ *ptypes.Empty) (*ethpb.HostData,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetLogsEndpoint
|
||||
func (ns *Server) GetLogsEndpoint(_ context.Context, _ *ptypes.Empty) (*pbrpc.LogsEndpointResponse, error) {
|
||||
return &pbrpc.LogsEndpointResponse{
|
||||
BeaconLogsEndpoint: fmt.Sprintf("%s:%d", ns.BeaconMonitoringHost, ns.BeaconMonitoringPort),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetPeer returns the data known about the peer defined by the provided peer id.
|
||||
func (ns *Server) GetPeer(_ context.Context, peerReq *ethpb.PeerRequest) (*ethpb.Peer, error) {
|
||||
pid, err := peer.Decode(peerReq.PeerId)
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
|
||||
mockP2p "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing"
|
||||
mockSync "github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync/testing"
|
||||
pbrpc "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
|
||||
@@ -77,6 +78,19 @@ func TestNodeServer_GetVersion(t *testing.T) {
|
||||
assert.Equal(t, v, res.Version)
|
||||
}
|
||||
|
||||
func TestNodeServer_GetLogsEndpoint(t *testing.T) {
|
||||
ns := &Server{
|
||||
BeaconMonitoringHost: "localhost",
|
||||
BeaconMonitoringPort: 8080,
|
||||
}
|
||||
res, err := ns.GetLogsEndpoint(context.Background(), &ptypes.Empty{})
|
||||
require.NoError(t, err)
|
||||
want := &pbrpc.LogsEndpointResponse{
|
||||
BeaconLogsEndpoint: "localhost:8080",
|
||||
}
|
||||
assert.DeepEqual(t, want, res)
|
||||
}
|
||||
|
||||
func TestNodeServer_GetImplementedServices(t *testing.T) {
|
||||
server := grpc.NewServer()
|
||||
ns := &Server{
|
||||
|
||||
@@ -78,6 +78,8 @@ type Service struct {
|
||||
syncService chainSync.Checker
|
||||
host string
|
||||
port string
|
||||
beaconMonitoringHost string
|
||||
beaconMonitoringPort int
|
||||
listener net.Listener
|
||||
withCert string
|
||||
withKey string
|
||||
@@ -105,6 +107,8 @@ type Config struct {
|
||||
Port string
|
||||
CertFlag string
|
||||
KeyFlag string
|
||||
BeaconMonitoringHost string
|
||||
BeaconMonitoringPort int
|
||||
BeaconDB db.HeadAccessDatabase
|
||||
ChainInfoFetcher blockchain.ChainInfoFetcher
|
||||
HeadFetcher blockchain.HeadFetcher
|
||||
@@ -162,6 +166,8 @@ func NewService(ctx context.Context, cfg *Config) *Service {
|
||||
syncService: cfg.SyncService,
|
||||
host: cfg.Host,
|
||||
port: cfg.Port,
|
||||
beaconMonitoringHost: cfg.BeaconMonitoringHost,
|
||||
beaconMonitoringPort: cfg.BeaconMonitoringPort,
|
||||
withCert: cfg.CertFlag,
|
||||
withKey: cfg.KeyFlag,
|
||||
depositFetcher: cfg.DepositFetcher,
|
||||
@@ -250,13 +256,15 @@ func (s *Service) Start() {
|
||||
StateGen: s.stateGen,
|
||||
}
|
||||
nodeServer := &node.Server{
|
||||
BeaconDB: s.beaconDB,
|
||||
Server: s.grpcServer,
|
||||
SyncChecker: s.syncService,
|
||||
GenesisTimeFetcher: s.genesisTimeFetcher,
|
||||
PeersFetcher: s.peersFetcher,
|
||||
PeerManager: s.peerManager,
|
||||
GenesisFetcher: s.genesisFetcher,
|
||||
BeaconDB: s.beaconDB,
|
||||
Server: s.grpcServer,
|
||||
SyncChecker: s.syncService,
|
||||
GenesisTimeFetcher: s.genesisTimeFetcher,
|
||||
PeersFetcher: s.peersFetcher,
|
||||
PeerManager: s.peerManager,
|
||||
GenesisFetcher: s.genesisFetcher,
|
||||
BeaconMonitoringHost: s.beaconMonitoringHost,
|
||||
BeaconMonitoringPort: s.beaconMonitoringPort,
|
||||
}
|
||||
beaconChainServer := &beacon.Server{
|
||||
Ctx: s.ctx,
|
||||
@@ -298,6 +306,7 @@ func (s *Service) Start() {
|
||||
SyncChecker: s.syncService,
|
||||
}
|
||||
ethpb.RegisterNodeServer(s.grpcServer, nodeServer)
|
||||
pbrpc.RegisterHealthServer(s.grpcServer, nodeServer)
|
||||
ethpb.RegisterBeaconChainServer(s.grpcServer, beaconChainServer)
|
||||
ethpbv1.RegisterBeaconChainServer(s.grpcServer, beaconChainServerV1)
|
||||
if s.enableDebugRPCEndpoints {
|
||||
|
||||
@@ -39,6 +39,9 @@ func (vs *Server) StreamDuties(req *ethpb.DutiesRequest, stream ethpb.BeaconNode
|
||||
// If we are post-genesis time, then set the current epoch to
|
||||
// the number epochs since the genesis time, otherwise 0 by default.
|
||||
genesisTime := vs.GenesisTimeFetcher.GenesisTime()
|
||||
if genesisTime.IsZero() {
|
||||
return status.Error(codes.Unavailable, "genesis time is not set")
|
||||
}
|
||||
var currentEpoch uint64
|
||||
if genesisTime.Before(timeutils.Now()) {
|
||||
currentEpoch = slotutil.EpochsSinceGenesis(vs.GenesisTimeFetcher.GenesisTime())
|
||||
|
||||
@@ -64,7 +64,7 @@ func (vs *Server) GetAttestationData(ctx context.Context, req *ethpb.Attestation
|
||||
}
|
||||
defer func() {
|
||||
if err := vs.AttestationCache.MarkNotInProgress(req); err != nil {
|
||||
log.WithError(err).Error("Failed to mark cache not in progress")
|
||||
log.WithError(err).Error("Could not mark cache not in progress")
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -89,7 +89,7 @@ func (vs *Server) GetAttestationData(ctx context.Context, req *ethpb.Attestation
|
||||
}
|
||||
}
|
||||
if headState == nil {
|
||||
return nil, status.Error(codes.Internal, "Failed to lookup parent state from head.")
|
||||
return nil, status.Error(codes.Internal, "Could not lookup parent state from head.")
|
||||
}
|
||||
|
||||
if helpers.CurrentEpoch(headState) < helpers.SlotToEpoch(req.Slot) {
|
||||
|
||||
@@ -192,12 +192,12 @@ func (vs *Server) eth1Data(ctx context.Context, slot uint64) (*ethpb.Eth1Data, e
|
||||
// Look up most recent block up to timestamp
|
||||
blockNumber, err := vs.Eth1BlockFetcher.BlockNumberByTimestamp(ctx, eth1VotingPeriodStartTime)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Failed to get block number from timestamp")
|
||||
log.WithError(err).Error("Could not get block number from timestamp")
|
||||
return vs.randomETH1DataVote(ctx)
|
||||
}
|
||||
eth1Data, err := vs.defaultEth1DataResponse(ctx, blockNumber)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Failed to get eth1 data from block number")
|
||||
log.WithError(err).Error("Could not get eth1 data from block number")
|
||||
return vs.randomETH1DataVote(ctx)
|
||||
}
|
||||
|
||||
@@ -237,12 +237,12 @@ func (vs *Server) eth1DataMajorityVote(ctx context.Context, beaconState *stateTr
|
||||
|
||||
lastBlockByEarliestValidTime, err := vs.Eth1BlockFetcher.BlockNumberByTimestamp(ctx, earliestValidTime)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Failed to get last block by earliest valid time")
|
||||
log.WithError(err).Error("Could not get last block by earliest valid time")
|
||||
return vs.randomETH1DataVote(ctx)
|
||||
}
|
||||
timeOfLastBlockByEarliestValidTime, err := vs.Eth1BlockFetcher.BlockTimeByHeight(ctx, lastBlockByEarliestValidTime)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Failed to get time of last block by earliest valid time")
|
||||
log.WithError(err).Error("Could not get time of last block by earliest valid time")
|
||||
return vs.randomETH1DataVote(ctx)
|
||||
}
|
||||
// Increment the earliest block if the original block's time is before valid time.
|
||||
@@ -253,12 +253,12 @@ func (vs *Server) eth1DataMajorityVote(ctx context.Context, beaconState *stateTr
|
||||
|
||||
lastBlockByLatestValidTime, err := vs.Eth1BlockFetcher.BlockNumberByTimestamp(ctx, latestValidTime)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Failed to get last block by latest valid time")
|
||||
log.WithError(err).Error("Could not get last block by latest valid time")
|
||||
return vs.randomETH1DataVote(ctx)
|
||||
}
|
||||
timeOfLastBlockByLatestValidTime, err := vs.Eth1BlockFetcher.BlockTimeByHeight(ctx, lastBlockByLatestValidTime)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Failed to get time of last block by latest valid time")
|
||||
log.WithError(err).Error("Could not get time of last block by latest valid time")
|
||||
return vs.randomETH1DataVote(ctx)
|
||||
}
|
||||
if timeOfLastBlockByLatestValidTime < earliestValidTime {
|
||||
@@ -278,7 +278,7 @@ func (vs *Server) eth1DataMajorityVote(ctx context.Context, beaconState *stateTr
|
||||
if lastBlockDepositCount >= vs.HeadFetcher.HeadETH1Data().DepositCount {
|
||||
hash, err := vs.Eth1BlockFetcher.BlockHashByHeight(ctx, lastBlockByLatestValidTime)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Failed to get hash of last block by latest valid time")
|
||||
log.WithError(err).Error("Could not get hash of last block by latest valid time")
|
||||
return vs.randomETH1DataVote(ctx)
|
||||
}
|
||||
return ðpb.Eth1Data{
|
||||
@@ -507,7 +507,7 @@ func (vs *Server) canonicalEth1Data(
|
||||
|
||||
// Add in current vote, to get accurate vote tally
|
||||
if err := beaconState.AppendEth1DataVotes(currentVote); err != nil {
|
||||
return nil, nil, errors.Wrap(err, "failed to append eth1 data votes to state")
|
||||
return nil, nil, errors.Wrap(err, "could not append eth1 data votes to state")
|
||||
}
|
||||
hasSupport, err := blocks.Eth1DataHasEnoughSupport(beaconState, currentVote)
|
||||
if err != nil {
|
||||
|
||||
@@ -131,13 +131,13 @@ func (s *State) stateSummary(ctx context.Context, blockRoot [32]byte) (*pb.State
|
||||
}
|
||||
}
|
||||
if summary == nil {
|
||||
return s.recoverStateSummary(ctx, blockRoot)
|
||||
return s.RecoverStateSummary(ctx, blockRoot)
|
||||
}
|
||||
return summary, nil
|
||||
}
|
||||
|
||||
// This recovers state summary object of a given block root by using the saved block in DB.
|
||||
func (s *State) recoverStateSummary(ctx context.Context, blockRoot [32]byte) (*pb.StateSummary, error) {
|
||||
// RecoverStateSummary recovers state summary object of a given block root by using the saved block in DB.
|
||||
func (s *State) RecoverStateSummary(ctx context.Context, blockRoot [32]byte) (*pb.StateSummary, error) {
|
||||
if s.beaconDB.HasBlock(ctx, blockRoot) {
|
||||
b, err := s.beaconDB.Block(ctx, blockRoot)
|
||||
if err != nil {
|
||||
@@ -149,7 +149,7 @@ func (s *State) recoverStateSummary(ctx context.Context, blockRoot [32]byte) (*p
|
||||
}
|
||||
return summary, nil
|
||||
}
|
||||
return nil, errUnknownStateSummary
|
||||
return nil, errors.New("could not find block in DB")
|
||||
}
|
||||
|
||||
// This loads a beacon state from either the cache or DB then replay blocks up the requested block root.
|
||||
|
||||
@@ -232,7 +232,7 @@ func TestStateSummary_CanGetFromCacheOrDB(t *testing.T) {
|
||||
r := [32]byte{'a'}
|
||||
summary := &pb.StateSummary{Slot: 100}
|
||||
_, err := service.stateSummary(ctx, r)
|
||||
require.ErrorContains(t, errUnknownStateSummary.Error(), err)
|
||||
require.ErrorContains(t, "could not find block in DB", err)
|
||||
|
||||
service.stateSummaryCache.Put(r, summary)
|
||||
got, err := service.stateSummary(ctx, r)
|
||||
@@ -244,7 +244,7 @@ func TestStateSummary_CanGetFromCacheOrDB(t *testing.T) {
|
||||
r = [32]byte{'b'}
|
||||
summary = &pb.StateSummary{Root: r[:], Slot: 101}
|
||||
_, err = service.stateSummary(ctx, r)
|
||||
require.ErrorContains(t, errUnknownStateSummary.Error(), err)
|
||||
require.ErrorContains(t, "could not find block in DB", err)
|
||||
|
||||
require.NoError(t, service.beaconDB.SaveStateSummary(ctx, summary))
|
||||
got, err = service.stateSummary(ctx, r)
|
||||
|
||||
@@ -36,6 +36,10 @@ const (
|
||||
noRequiredPeersErrRefreshInterval = 15 * time.Second
|
||||
// maxResetAttempts number of times stale FSM is reset, before backtracking is triggered.
|
||||
maxResetAttempts = 4
|
||||
// startBackSlots defines number of slots before the current head, which defines a start position
|
||||
// of the initial machine. This allows more robustness in case of normal sync sets head to some
|
||||
// orphaned block: in that case starting earlier and re-fetching blocks allows to reorganize chain.
|
||||
startBackSlots = 32
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -173,6 +177,9 @@ func (q *blocksQueue) loop() {
|
||||
|
||||
// Define initial state machines.
|
||||
startSlot := q.chain.HeadSlot()
|
||||
if startSlot > startBackSlots {
|
||||
startSlot -= startBackSlots
|
||||
}
|
||||
blocksPerRequest := q.blocksFetcher.blocksPerSecond
|
||||
for i := startSlot; i < startSlot+blocksPerRequest*lookaheadSteps; i += blocksPerRequest {
|
||||
q.smm.addStateMachine(i)
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/kevinms/leakybucket-go"
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
@@ -1255,3 +1256,120 @@ func TestBlocksQueue_stuckInUnfavourableFork(t *testing.T) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestBlocksQueue_stuckWhenHeadIsSetToOrphanedBlock(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
beaconDB, _ := dbtest.SetupDB(t)
|
||||
p2p := p2pt.NewTestP2P(t)
|
||||
|
||||
chain := extendBlockSequence(t, []*eth.SignedBeaconBlock{}, 128)
|
||||
finalizedSlot := uint64(82)
|
||||
finalizedEpoch := helpers.SlotToEpoch(finalizedSlot)
|
||||
|
||||
genesisBlock := chain[0]
|
||||
require.NoError(t, beaconDB.SaveBlock(context.Background(), genesisBlock))
|
||||
genesisRoot, err := genesisBlock.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
st := testutil.NewBeaconState()
|
||||
mc := &mock.ChainService{
|
||||
State: st,
|
||||
Root: genesisRoot[:],
|
||||
DB: beaconDB,
|
||||
FinalizedCheckPoint: ð.Checkpoint{
|
||||
Epoch: finalizedEpoch,
|
||||
Root: []byte(fmt.Sprintf("finalized_root %d", finalizedEpoch)),
|
||||
},
|
||||
}
|
||||
|
||||
// Populate database with blocks with part of the chain, orphaned block will be added on top.
|
||||
for _, blk := range chain[1:84] {
|
||||
parentRoot := bytesutil.ToBytes32(blk.Block.ParentRoot)
|
||||
// Save block only if parent root is already in database or cache.
|
||||
if beaconDB.HasBlock(ctx, parentRoot) || mc.HasInitSyncBlock(parentRoot) {
|
||||
require.NoError(t, beaconDB.SaveBlock(ctx, blk))
|
||||
require.NoError(t, st.SetSlot(blk.Block.Slot))
|
||||
}
|
||||
}
|
||||
require.Equal(t, uint64(83), mc.HeadSlot())
|
||||
require.Equal(t, chain[83].Block.Slot, mc.HeadSlot())
|
||||
|
||||
// Set head to slot 85, while we do not have block with slot 84 in DB, so block is orphaned.
|
||||
// Moreover, block with slot 85 is a forked block and should be replaced, with block from peer.
|
||||
orphanedBlock := testutil.NewBeaconBlock()
|
||||
orphanedBlock.Block.Slot = 85
|
||||
orphanedBlock.Block.StateRoot = testutil.Random32Bytes(t)
|
||||
require.NoError(t, beaconDB.SaveBlock(ctx, orphanedBlock))
|
||||
require.NoError(t, st.SetSlot(orphanedBlock.Block.Slot))
|
||||
require.Equal(t, uint64(85), mc.HeadSlot())
|
||||
|
||||
fetcher := newBlocksFetcher(
|
||||
ctx,
|
||||
&blocksFetcherConfig{
|
||||
chain: mc,
|
||||
p2p: p2p,
|
||||
db: beaconDB,
|
||||
},
|
||||
)
|
||||
fetcher.rateLimiter = leakybucket.NewCollector(6400, 6400, false)
|
||||
|
||||
// Connect peer that has all the blocks available.
|
||||
allBlocksPeer := connectPeerHavingBlocks(t, p2p, chain, finalizedSlot, p2p.Peers())
|
||||
defer func() {
|
||||
p2p.Peers().SetConnectionState(allBlocksPeer, peers.PeerDisconnected)
|
||||
}()
|
||||
|
||||
// Queue should be able to fetch whole chain (including slot which comes before the currently set head).
|
||||
queue := newBlocksQueue(ctx, &blocksQueueConfig{
|
||||
blocksFetcher: fetcher,
|
||||
chain: mc,
|
||||
highestExpectedSlot: uint64(len(chain) - 1),
|
||||
mode: modeNonConstrained,
|
||||
})
|
||||
|
||||
require.NoError(t, queue.start())
|
||||
isProcessedBlock := func(ctx context.Context, blk *eth.SignedBeaconBlock, blkRoot [32]byte) bool {
|
||||
finalizedSlot, err := helpers.StartSlot(mc.FinalizedCheckpt().Epoch)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if blk.Block.Slot <= finalizedSlot || (beaconDB.HasBlock(ctx, blkRoot) || mc.HasInitSyncBlock(blkRoot)) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
select {
|
||||
case <-time.After(3 * time.Second):
|
||||
t.Fatal("test takes to long to complete")
|
||||
case data := <-queue.fetchedData:
|
||||
for _, blk := range data.blocks {
|
||||
blkRoot, err := blk.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
if isProcessedBlock(ctx, blk, blkRoot) {
|
||||
log.Errorf("slot: %d , root %#x: %v", blk.Block.Slot, blkRoot, errBlockAlreadyProcessed)
|
||||
continue
|
||||
}
|
||||
|
||||
parentRoot := bytesutil.ToBytes32(blk.Block.ParentRoot)
|
||||
if !beaconDB.HasBlock(ctx, parentRoot) && !mc.HasInitSyncBlock(parentRoot) {
|
||||
log.Errorf("%v: %#x", errParentDoesNotExist, blk.Block.ParentRoot)
|
||||
continue
|
||||
}
|
||||
|
||||
// Block is not already processed, and parent exists in database - process.
|
||||
require.NoError(t, beaconDB.SaveBlock(ctx, blk))
|
||||
require.NoError(t, st.SetSlot(blk.Block.Slot))
|
||||
}
|
||||
}
|
||||
require.NoError(t, queue.stop())
|
||||
|
||||
// Check that all blocks available in chain are produced by queue.
|
||||
for _, blk := range chain[:orphanedBlock.Block.Slot+32] {
|
||||
blkRoot, err := blk.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, beaconDB.HasBlock(ctx, blkRoot) || mc.HasInitSyncBlock(blkRoot), "slot %d", blk.Block.Slot)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ func (s *Service) processPendingAtts(ctx context.Context) error {
|
||||
log.WithFields(logrus.Fields{
|
||||
"blockRoot": hex.EncodeToString(bytesutil.Trunc(bRoot[:])),
|
||||
"pendingAttsCount": len(attestations),
|
||||
}).Info("Verified and saved pending attestations to pool")
|
||||
}).Debug("Verified and saved pending attestations to pool")
|
||||
|
||||
// Delete the missing block root key from pending attestation queue so a node will not request for the block again.
|
||||
s.pendingAttsLock.Lock()
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
p2ptest "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing"
|
||||
p2ptypes "github.com/prysmaticlabs/prysm/beacon-chain/p2p/types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/rand"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
@@ -44,6 +45,7 @@ func TestRegularSyncBeaconBlockSubscriber_ProcessPendingBlocks1(t *testing.T) {
|
||||
slotToPendingBlocks: gcache.New(time.Second, 2*time.Second),
|
||||
seenPendingBlocks: make(map[[32]byte]bool),
|
||||
stateSummaryCache: stateSummaryCache,
|
||||
stateGen: stategen.New(db, stateSummaryCache),
|
||||
}
|
||||
err := r.initCaches()
|
||||
require.NoError(t, err)
|
||||
@@ -172,6 +174,7 @@ func TestRegularSyncBeaconBlockSubscriber_ProcessPendingBlocks_2Chains(t *testin
|
||||
slotToPendingBlocks: gcache.New(time.Second, 2*time.Second),
|
||||
seenPendingBlocks: make(map[[32]byte]bool),
|
||||
stateSummaryCache: stateSummaryCache,
|
||||
stateGen: stategen.New(db, stateSummaryCache),
|
||||
}
|
||||
err := r.initCaches()
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -152,7 +152,10 @@ func (s *Service) validateBeaconBlock(ctx context.Context, blk *ethpb.SignedBeac
|
||||
hasStateSummaryDB := s.db.HasStateSummary(ctx, bytesutil.ToBytes32(blk.Block.ParentRoot))
|
||||
hasStateSummaryCache := s.stateSummaryCache.Has(bytesutil.ToBytes32(blk.Block.ParentRoot))
|
||||
if !hasStateSummaryDB && !hasStateSummaryCache {
|
||||
return errors.New("no access to parent state")
|
||||
_, err := s.stateGen.RecoverStateSummary(ctx, bytesutil.ToBytes32(blk.Block.ParentRoot))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
parentState, err := s.stateGen.StateByRoot(ctx, bytesutil.ToBytes32(blk.Block.ParentRoot))
|
||||
if err != nil {
|
||||
|
||||
@@ -121,6 +121,67 @@ func TestValidateBeaconBlockPubSub_BlockAlreadyPresentInDB(t *testing.T) {
|
||||
assert.Equal(t, false, result)
|
||||
}
|
||||
|
||||
func TestValidateBeaconBlockPubSub_CanRecoverStateSummary(t *testing.T) {
|
||||
db, stateSummaryCache := dbtest.SetupDB(t)
|
||||
p := p2ptest.NewTestP2P(t)
|
||||
ctx := context.Background()
|
||||
beaconState, privKeys := testutil.DeterministicGenesisState(t, 100)
|
||||
parentBlock := testutil.NewBeaconBlock()
|
||||
require.NoError(t, db.SaveBlock(ctx, parentBlock))
|
||||
bRoot, err := parentBlock.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, db.SaveState(ctx, beaconState, bRoot))
|
||||
copied := beaconState.Copy()
|
||||
require.NoError(t, copied.SetSlot(1))
|
||||
proposerIdx, err := helpers.BeaconProposerIndex(copied)
|
||||
require.NoError(t, err)
|
||||
msg := testutil.NewBeaconBlock()
|
||||
msg.Block.ParentRoot = bRoot[:]
|
||||
msg.Block.Slot = 1
|
||||
msg.Block.ProposerIndex = proposerIdx
|
||||
msg.Signature, err = helpers.ComputeDomainAndSign(beaconState, 0, msg.Block, params.BeaconConfig().DomainBeaconProposer, privKeys[proposerIdx])
|
||||
require.NoError(t, err)
|
||||
|
||||
c, err := lru.New(10)
|
||||
require.NoError(t, err)
|
||||
c2, err := lru.New(10)
|
||||
require.NoError(t, err)
|
||||
stateGen := stategen.New(db, stateSummaryCache)
|
||||
chainService := &mock.ChainService{Genesis: time.Unix(time.Now().Unix()-int64(params.BeaconConfig().SecondsPerSlot), 0),
|
||||
State: beaconState,
|
||||
FinalizedCheckPoint: ðpb.Checkpoint{
|
||||
Epoch: 0,
|
||||
Root: make([]byte, 32),
|
||||
},
|
||||
}
|
||||
r := &Service{
|
||||
db: db,
|
||||
p2p: p,
|
||||
initialSync: &mockSync.Sync{IsSyncing: false},
|
||||
chain: chainService,
|
||||
blockNotifier: chainService.BlockNotifier(),
|
||||
seenBlockCache: c,
|
||||
badBlockCache: c2,
|
||||
slotToPendingBlocks: gcache.New(time.Second, 2*time.Second),
|
||||
seenPendingBlocks: make(map[[32]byte]bool),
|
||||
stateSummaryCache: stateSummaryCache,
|
||||
stateGen: stateGen,
|
||||
}
|
||||
buf := new(bytes.Buffer)
|
||||
_, err = p.Encoding().EncodeGossip(buf, msg)
|
||||
require.NoError(t, err)
|
||||
topic := p2p.GossipTypeMapping[reflect.TypeOf(msg)]
|
||||
m := &pubsub.Message{
|
||||
Message: &pubsubpb.Message{
|
||||
Data: buf.Bytes(),
|
||||
Topic: &topic,
|
||||
},
|
||||
}
|
||||
result := r.validateBeaconBlockPubSub(ctx, "", m) == pubsub.ValidationAccept
|
||||
assert.Equal(t, true, result)
|
||||
assert.NotNil(t, m.ValidatorData, "Decoded message was not set on the message validator data")
|
||||
}
|
||||
|
||||
func TestValidateBeaconBlockPubSub_ValidProposerSignature(t *testing.T) {
|
||||
db, stateSummaryCache := dbtest.SetupDB(t)
|
||||
p := p2ptest.NewTestP2P(t)
|
||||
|
||||
@@ -112,6 +112,7 @@ var appHelpFlagGroups = []flagGroup{
|
||||
flags.WeakSubjectivityCheckpt,
|
||||
flags.EnableBackupWebhookFlag,
|
||||
flags.BackupWebhookOutputDir,
|
||||
flags.Eth1HeaderReqLimit,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
2
deps.bzl
2
deps.bzl
@@ -601,7 +601,7 @@ def prysm_deps():
|
||||
# Note: The keep directives help gazelle leave this alone.
|
||||
go_repository(
|
||||
name = "com_github_ethereum_go_ethereum",
|
||||
commit = "233538bfc3d8e62a179ffe2af8015d03842a9dc3", # keep
|
||||
commit = "1fb46e30795130091776dcb1359e75bd3ba7a356", # keep
|
||||
importpath = "github.com/ethereum/go-ethereum", # keep
|
||||
# Note: go-ethereum is not bazel-friendly with regards to cgo. We have a
|
||||
# a fork that has resolved these issues by disabling HID/USB support and
|
||||
|
||||
3
go.mod
3
go.mod
@@ -99,7 +99,6 @@ require (
|
||||
github.com/trailofbits/go-mutexasserts v0.0.0-20200708152505-19999e7d3cef
|
||||
github.com/tyler-smith/go-bip39 v1.0.2
|
||||
github.com/urfave/cli/v2 v2.2.0
|
||||
github.com/wealdtech/go-bytesutil v1.1.1
|
||||
github.com/wealdtech/go-eth2-util v1.6.2
|
||||
github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4 v1.1.1
|
||||
github.com/wercker/journalhook v0.0.0-20180428041537-5d0a5ae867b3
|
||||
@@ -132,6 +131,6 @@ require (
|
||||
k8s.io/utils v0.0.0-20200520001619-278ece378a50 // indirect
|
||||
)
|
||||
|
||||
replace github.com/ethereum/go-ethereum => github.com/prysmaticlabs/bazel-go-ethereum v0.0.0-20201116135122-233538bfc3d8
|
||||
replace github.com/ethereum/go-ethereum => github.com/prysmaticlabs/bazel-go-ethereum v0.0.0-20201126065335-1fb46e307951
|
||||
|
||||
replace github.com/json-iterator/go => github.com/prestonvanloon/go v1.1.7-0.20190722034630-4f2e55fcf87b
|
||||
|
||||
4
go.sum
4
go.sum
@@ -963,8 +963,8 @@ github.com/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38i
|
||||
github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4=
|
||||
github.com/protolambda/zssz v0.1.5 h1:7fjJjissZIIaa2QcvmhS/pZISMX21zVITt49sW1ouek=
|
||||
github.com/protolambda/zssz v0.1.5/go.mod h1:a4iwOX5FE7/JkKA+J/PH0Mjo9oXftN6P8NZyL28gpag=
|
||||
github.com/prysmaticlabs/bazel-go-ethereum v0.0.0-20201116135122-233538bfc3d8 h1:Fc6JMvJBFAAdI07o//gNgT5MiCCScpe1u/KM1A6MDGo=
|
||||
github.com/prysmaticlabs/bazel-go-ethereum v0.0.0-20201116135122-233538bfc3d8/go.mod h1:JIfVb6esrqALTExdz9hRYvrP0xBDf6wCncIu1hNwHpM=
|
||||
github.com/prysmaticlabs/bazel-go-ethereum v0.0.0-20201126065335-1fb46e307951 h1:Jncuyb/nIJgXbEe0iGz3MN5JmijPVGzwk3G5FR01phI=
|
||||
github.com/prysmaticlabs/bazel-go-ethereum v0.0.0-20201126065335-1fb46e307951/go.mod h1:JIfVb6esrqALTExdz9hRYvrP0xBDf6wCncIu1hNwHpM=
|
||||
github.com/prysmaticlabs/ethereumapis v0.0.0-20201117145913-073714f478fb h1:OUfQgEA6zB19I66EQ2nPtjdBbk+Vv7eCBf2+x3BTv5w=
|
||||
github.com/prysmaticlabs/ethereumapis v0.0.0-20201117145913-073714f478fb/go.mod h1:k7b2dxy6RppCG6kmOJkNOXzRpEoTdsPygc2aQhsUsZk=
|
||||
github.com/prysmaticlabs/go-bitfield v0.0.0-20200322041314-62c2aee71669 h1:cX6YRZnZ9sgMqM5U14llxUiXVNJ3u07Res1IIjTOgtI=
|
||||
|
||||
@@ -45,7 +45,7 @@ go_library(
|
||||
|
||||
proto_library(
|
||||
name = "v1_proto",
|
||||
srcs = ["debug.proto"],
|
||||
srcs = ["debug.proto", "health.proto"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//proto/beacon/p2p/v1:v1_proto",
|
||||
|
||||
422
proto/beacon/rpc/v1/health.pb.go
generated
Executable file
422
proto/beacon/rpc/v1/health.pb.go
generated
Executable file
@@ -0,0 +1,422 @@
|
||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: proto/beacon/rpc/v1/health.proto
|
||||
|
||||
package ethereum_beacon_rpc_v1
|
||||
|
||||
import (
|
||||
context "context"
|
||||
fmt "fmt"
|
||||
io "io"
|
||||
math "math"
|
||||
math_bits "math/bits"
|
||||
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
types "github.com/gogo/protobuf/types"
|
||||
_ "google.golang.org/genproto/googleapis/api/annotations"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type LogsEndpointResponse struct {
|
||||
BeaconLogsEndpoint string `protobuf:"bytes,1,opt,name=beacon_logs_endpoint,json=beaconLogsEndpoint,proto3" json:"beacon_logs_endpoint,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *LogsEndpointResponse) Reset() { *m = LogsEndpointResponse{} }
|
||||
func (m *LogsEndpointResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*LogsEndpointResponse) ProtoMessage() {}
|
||||
func (*LogsEndpointResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_2e4b7e98e3e10444, []int{0}
|
||||
}
|
||||
func (m *LogsEndpointResponse) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *LogsEndpointResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_LogsEndpointResponse.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *LogsEndpointResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_LogsEndpointResponse.Merge(m, src)
|
||||
}
|
||||
func (m *LogsEndpointResponse) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *LogsEndpointResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_LogsEndpointResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_LogsEndpointResponse proto.InternalMessageInfo
|
||||
|
||||
func (m *LogsEndpointResponse) GetBeaconLogsEndpoint() string {
|
||||
if m != nil {
|
||||
return m.BeaconLogsEndpoint
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*LogsEndpointResponse)(nil), "ethereum.beacon.rpc.v1.LogsEndpointResponse")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("proto/beacon/rpc/v1/health.proto", fileDescriptor_2e4b7e98e3e10444) }
|
||||
|
||||
var fileDescriptor_2e4b7e98e3e10444 = []byte{
|
||||
// 258 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x90, 0xc1, 0x4a, 0xc3, 0x40,
|
||||
0x10, 0x86, 0x59, 0x0f, 0x05, 0x17, 0x41, 0x58, 0x4a, 0x91, 0x2a, 0xa1, 0x04, 0x0f, 0x22, 0xb2,
|
||||
0x63, 0xf4, 0x0d, 0x84, 0x62, 0x0f, 0x9e, 0xfa, 0x02, 0x65, 0x13, 0xc7, 0x6c, 0x20, 0xdd, 0x59,
|
||||
0xb2, 0xd3, 0x80, 0x57, 0xbd, 0x7b, 0xf1, 0xa5, 0x3c, 0x0a, 0xbe, 0x80, 0x04, 0x1f, 0x44, 0x9a,
|
||||
0x6d, 0xa0, 0x87, 0x1e, 0x87, 0x6f, 0x7e, 0xfe, 0x6f, 0x46, 0xce, 0x7c, 0x43, 0x4c, 0x90, 0xa3,
|
||||
0x29, 0xc8, 0x41, 0xe3, 0x0b, 0x68, 0x33, 0xb0, 0x68, 0x6a, 0xb6, 0xba, 0x47, 0x6a, 0x82, 0x6c,
|
||||
0xb1, 0xc1, 0xcd, 0x5a, 0xc7, 0x25, 0xdd, 0xf8, 0x42, 0xb7, 0xd9, 0xf4, 0xa2, 0x24, 0x2a, 0x6b,
|
||||
0x04, 0xe3, 0x2b, 0x30, 0xce, 0x11, 0x1b, 0xae, 0xc8, 0x85, 0x98, 0x9a, 0x9e, 0xef, 0x68, 0x3f,
|
||||
0xe5, 0x9b, 0x17, 0xc0, 0xb5, 0xe7, 0xd7, 0x08, 0xd3, 0x85, 0x1c, 0x3f, 0x51, 0x19, 0xe6, 0xee,
|
||||
0xd9, 0x53, 0xe5, 0x78, 0x89, 0xc1, 0x93, 0x0b, 0xa8, 0x6e, 0xe5, 0x38, 0x76, 0xac, 0x6a, 0x2a,
|
||||
0xc3, 0x0a, 0x77, 0xfc, 0x4c, 0xcc, 0xc4, 0xd5, 0xf1, 0x52, 0x45, 0xb6, 0x9f, 0xbc, 0xfb, 0x10,
|
||||
0x72, 0xb4, 0xe8, 0x6d, 0xd5, 0xbb, 0x90, 0xa7, 0x8f, 0xc8, 0xfb, 0x58, 0x4d, 0x74, 0xd4, 0xd0,
|
||||
0x83, 0x86, 0x9e, 0x6f, 0x35, 0xa6, 0x37, 0xfa, 0xf0, 0x51, 0xfa, 0x90, 0x56, 0x7a, 0xfd, 0xf6,
|
||||
0xf3, 0xf7, 0x79, 0x74, 0xa9, 0x52, 0x40, 0xb6, 0xd0, 0x66, 0xa6, 0xf6, 0xd6, 0x0c, 0x5f, 0x82,
|
||||
0xad, 0x2a, 0x0c, 0xaa, 0x0f, 0x27, 0x5f, 0x5d, 0x22, 0xbe, 0xbb, 0x44, 0xfc, 0x76, 0x89, 0xc8,
|
||||
0x47, 0x7d, 0xef, 0xfd, 0x7f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x73, 0x6a, 0x3d, 0x50, 0x66, 0x01,
|
||||
0x00, 0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ grpc.ClientConn
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
const _ = grpc.SupportPackageIsVersion4
|
||||
|
||||
// HealthClient is the client API for Health service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||
type HealthClient interface {
|
||||
GetLogsEndpoint(ctx context.Context, in *types.Empty, opts ...grpc.CallOption) (*LogsEndpointResponse, error)
|
||||
}
|
||||
|
||||
type healthClient struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewHealthClient(cc *grpc.ClientConn) HealthClient {
|
||||
return &healthClient{cc}
|
||||
}
|
||||
|
||||
func (c *healthClient) GetLogsEndpoint(ctx context.Context, in *types.Empty, opts ...grpc.CallOption) (*LogsEndpointResponse, error) {
|
||||
out := new(LogsEndpointResponse)
|
||||
err := c.cc.Invoke(ctx, "/ethereum.beacon.rpc.v1.Health/GetLogsEndpoint", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// HealthServer is the server API for Health service.
|
||||
type HealthServer interface {
|
||||
GetLogsEndpoint(context.Context, *types.Empty) (*LogsEndpointResponse, error)
|
||||
}
|
||||
|
||||
// UnimplementedHealthServer can be embedded to have forward compatible implementations.
|
||||
type UnimplementedHealthServer struct {
|
||||
}
|
||||
|
||||
func (*UnimplementedHealthServer) GetLogsEndpoint(ctx context.Context, req *types.Empty) (*LogsEndpointResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetLogsEndpoint not implemented")
|
||||
}
|
||||
|
||||
func RegisterHealthServer(s *grpc.Server, srv HealthServer) {
|
||||
s.RegisterService(&_Health_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _Health_GetLogsEndpoint_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(types.Empty)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(HealthServer).GetLogsEndpoint(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/ethereum.beacon.rpc.v1.Health/GetLogsEndpoint",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(HealthServer).GetLogsEndpoint(ctx, req.(*types.Empty))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _Health_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "ethereum.beacon.rpc.v1.Health",
|
||||
HandlerType: (*HealthServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "GetLogsEndpoint",
|
||||
Handler: _Health_GetLogsEndpoint_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "proto/beacon/rpc/v1/health.proto",
|
||||
}
|
||||
|
||||
func (m *LogsEndpointResponse) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *LogsEndpointResponse) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.Size()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *LogsEndpointResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.XXX_unrecognized != nil {
|
||||
i -= len(m.XXX_unrecognized)
|
||||
copy(dAtA[i:], m.XXX_unrecognized)
|
||||
}
|
||||
if len(m.BeaconLogsEndpoint) > 0 {
|
||||
i -= len(m.BeaconLogsEndpoint)
|
||||
copy(dAtA[i:], m.BeaconLogsEndpoint)
|
||||
i = encodeVarintHealth(dAtA, i, uint64(len(m.BeaconLogsEndpoint)))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func encodeVarintHealth(dAtA []byte, offset int, v uint64) int {
|
||||
offset -= sovHealth(v)
|
||||
base := offset
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return base
|
||||
}
|
||||
func (m *LogsEndpointResponse) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
l = len(m.BeaconLogsEndpoint)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovHealth(uint64(l))
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
n += len(m.XXX_unrecognized)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovHealth(x uint64) (n int) {
|
||||
return (math_bits.Len64(x|1) + 6) / 7
|
||||
}
|
||||
func sozHealth(x uint64) (n int) {
|
||||
return sovHealth(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *LogsEndpointResponse) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowHealth
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: LogsEndpointResponse: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: LogsEndpointResponse: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field BeaconLogsEndpoint", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowHealth
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthHealth
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthHealth
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.BeaconLogsEndpoint = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipHealth(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthHealth
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
return ErrInvalidLengthHealth
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipHealth(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
depth := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowHealth
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowHealth
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowHealth
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthHealth
|
||||
}
|
||||
iNdEx += length
|
||||
case 3:
|
||||
depth++
|
||||
case 4:
|
||||
if depth == 0 {
|
||||
return 0, ErrUnexpectedEndOfGroupHealth
|
||||
}
|
||||
depth--
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
if iNdEx < 0 {
|
||||
return 0, ErrInvalidLengthHealth
|
||||
}
|
||||
if depth == 0 {
|
||||
return iNdEx, nil
|
||||
}
|
||||
}
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthHealth = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowHealth = fmt.Errorf("proto: integer overflow")
|
||||
ErrUnexpectedEndOfGroupHealth = fmt.Errorf("proto: unexpected end of group")
|
||||
)
|
||||
24
proto/beacon/rpc/v1/health.proto
Normal file
24
proto/beacon/rpc/v1/health.proto
Normal file
@@ -0,0 +1,24 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package ethereum.beacon.rpc.v1;
|
||||
|
||||
import "google/api/annotations.proto";
|
||||
import "google/protobuf/empty.proto";
|
||||
|
||||
// Health service API
|
||||
//
|
||||
// The health service is able to return important metadata about a beacon node
|
||||
// such as the address of the logs websocket endpoint used by web clients.
|
||||
service Health {
|
||||
// Returns the websocket endpoint which can be reached to subscribe
|
||||
// to logs from the beacon node.
|
||||
rpc GetLogsEndpoint(google.protobuf.Empty) returns (LogsEndpointResponse) {
|
||||
option (google.api.http) = {
|
||||
get: "/eth/v1alpha1/health/logs/endpoint"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
message LogsEndpointResponse {
|
||||
string beacon_logs_endpoint = 1;
|
||||
}
|
||||
253
proto/beacon/rpc/v1_gateway/health.pb.go
generated
Executable file
253
proto/beacon/rpc/v1_gateway/health.pb.go
generated
Executable file
@@ -0,0 +1,253 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.25.0
|
||||
// protoc v3.13.0
|
||||
// source: proto/beacon/rpc/v1/health.proto
|
||||
|
||||
package ethereum_beacon_rpc_v1
|
||||
|
||||
import (
|
||||
context "context"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
empty "github.com/golang/protobuf/ptypes/empty"
|
||||
_ "google.golang.org/genproto/googleapis/api/annotations"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
||||
// of the legacy proto package is being used.
|
||||
const _ = proto.ProtoPackageIsVersion4
|
||||
|
||||
type LogsEndpointResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
BeaconLogsEndpoint string `protobuf:"bytes,1,opt,name=beacon_logs_endpoint,json=beaconLogsEndpoint,proto3" json:"beacon_logs_endpoint,omitempty"`
|
||||
}
|
||||
|
||||
func (x *LogsEndpointResponse) Reset() {
|
||||
*x = LogsEndpointResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_proto_beacon_rpc_v1_health_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *LogsEndpointResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*LogsEndpointResponse) ProtoMessage() {}
|
||||
|
||||
func (x *LogsEndpointResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_beacon_rpc_v1_health_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use LogsEndpointResponse.ProtoReflect.Descriptor instead.
|
||||
func (*LogsEndpointResponse) Descriptor() ([]byte, []int) {
|
||||
return file_proto_beacon_rpc_v1_health_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *LogsEndpointResponse) GetBeaconLogsEndpoint() string {
|
||||
if x != nil {
|
||||
return x.BeaconLogsEndpoint
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
var File_proto_beacon_rpc_v1_health_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_proto_beacon_rpc_v1_health_proto_rawDesc = []byte{
|
||||
0x0a, 0x20, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x72,
|
||||
0x70, 0x63, 0x2f, 0x76, 0x31, 0x2f, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x2e, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x12, 0x16, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x62, 0x65, 0x61,
|
||||
0x63, 0x6f, 0x6e, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67,
|
||||
0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
|
||||
0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x48, 0x0a, 0x14, 0x4c, 0x6f, 0x67, 0x73, 0x45, 0x6e, 0x64,
|
||||
0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a,
|
||||
0x14, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x6c, 0x6f, 0x67, 0x73, 0x5f, 0x65, 0x6e, 0x64,
|
||||
0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x62, 0x65, 0x61,
|
||||
0x63, 0x6f, 0x6e, 0x4c, 0x6f, 0x67, 0x73, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x32,
|
||||
0x8e, 0x01, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x12, 0x83, 0x01, 0x0a, 0x0f, 0x47,
|
||||
0x65, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x16,
|
||||
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
|
||||
0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75,
|
||||
0x6d, 0x2e, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x76, 0x31, 0x2e,
|
||||
0x4c, 0x6f, 0x67, 0x73, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70,
|
||||
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x24, 0x12, 0x22, 0x2f, 0x65,
|
||||
0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x68, 0x65, 0x61, 0x6c,
|
||||
0x74, 0x68, 0x2f, 0x6c, 0x6f, 0x67, 0x73, 0x2f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74,
|
||||
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_proto_beacon_rpc_v1_health_proto_rawDescOnce sync.Once
|
||||
file_proto_beacon_rpc_v1_health_proto_rawDescData = file_proto_beacon_rpc_v1_health_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_proto_beacon_rpc_v1_health_proto_rawDescGZIP() []byte {
|
||||
file_proto_beacon_rpc_v1_health_proto_rawDescOnce.Do(func() {
|
||||
file_proto_beacon_rpc_v1_health_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_beacon_rpc_v1_health_proto_rawDescData)
|
||||
})
|
||||
return file_proto_beacon_rpc_v1_health_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_proto_beacon_rpc_v1_health_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
|
||||
var file_proto_beacon_rpc_v1_health_proto_goTypes = []interface{}{
|
||||
(*LogsEndpointResponse)(nil), // 0: ethereum.beacon.rpc.v1.LogsEndpointResponse
|
||||
(*empty.Empty)(nil), // 1: google.protobuf.Empty
|
||||
}
|
||||
var file_proto_beacon_rpc_v1_health_proto_depIdxs = []int32{
|
||||
1, // 0: ethereum.beacon.rpc.v1.Health.GetLogsEndpoint:input_type -> google.protobuf.Empty
|
||||
0, // 1: ethereum.beacon.rpc.v1.Health.GetLogsEndpoint:output_type -> ethereum.beacon.rpc.v1.LogsEndpointResponse
|
||||
1, // [1:2] is the sub-list for method output_type
|
||||
0, // [0:1] is the sub-list for method input_type
|
||||
0, // [0:0] is the sub-list for extension type_name
|
||||
0, // [0:0] is the sub-list for extension extendee
|
||||
0, // [0:0] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_proto_beacon_rpc_v1_health_proto_init() }
|
||||
func file_proto_beacon_rpc_v1_health_proto_init() {
|
||||
if File_proto_beacon_rpc_v1_health_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_proto_beacon_rpc_v1_health_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*LogsEndpointResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_proto_beacon_rpc_v1_health_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 1,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
GoTypes: file_proto_beacon_rpc_v1_health_proto_goTypes,
|
||||
DependencyIndexes: file_proto_beacon_rpc_v1_health_proto_depIdxs,
|
||||
MessageInfos: file_proto_beacon_rpc_v1_health_proto_msgTypes,
|
||||
}.Build()
|
||||
File_proto_beacon_rpc_v1_health_proto = out.File
|
||||
file_proto_beacon_rpc_v1_health_proto_rawDesc = nil
|
||||
file_proto_beacon_rpc_v1_health_proto_goTypes = nil
|
||||
file_proto_beacon_rpc_v1_health_proto_depIdxs = nil
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ grpc.ClientConnInterface
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
const _ = grpc.SupportPackageIsVersion6
|
||||
|
||||
// HealthClient is the client API for Health service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||
type HealthClient interface {
|
||||
GetLogsEndpoint(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*LogsEndpointResponse, error)
|
||||
}
|
||||
|
||||
type healthClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewHealthClient(cc grpc.ClientConnInterface) HealthClient {
|
||||
return &healthClient{cc}
|
||||
}
|
||||
|
||||
func (c *healthClient) GetLogsEndpoint(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*LogsEndpointResponse, error) {
|
||||
out := new(LogsEndpointResponse)
|
||||
err := c.cc.Invoke(ctx, "/ethereum.beacon.rpc.v1.Health/GetLogsEndpoint", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// HealthServer is the server API for Health service.
|
||||
type HealthServer interface {
|
||||
GetLogsEndpoint(context.Context, *empty.Empty) (*LogsEndpointResponse, error)
|
||||
}
|
||||
|
||||
// UnimplementedHealthServer can be embedded to have forward compatible implementations.
|
||||
type UnimplementedHealthServer struct {
|
||||
}
|
||||
|
||||
func (*UnimplementedHealthServer) GetLogsEndpoint(context.Context, *empty.Empty) (*LogsEndpointResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetLogsEndpoint not implemented")
|
||||
}
|
||||
|
||||
func RegisterHealthServer(s *grpc.Server, srv HealthServer) {
|
||||
s.RegisterService(&_Health_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _Health_GetLogsEndpoint_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(empty.Empty)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(HealthServer).GetLogsEndpoint(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/ethereum.beacon.rpc.v1.Health/GetLogsEndpoint",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(HealthServer).GetLogsEndpoint(ctx, req.(*empty.Empty))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _Health_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "ethereum.beacon.rpc.v1.Health",
|
||||
HandlerType: (*HealthServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "GetLogsEndpoint",
|
||||
Handler: _Health_GetLogsEndpoint_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "proto/beacon/rpc/v1/health.proto",
|
||||
}
|
||||
148
proto/beacon/rpc/v1_gateway/health.pb.gw.go
Executable file
148
proto/beacon/rpc/v1_gateway/health.pb.gw.go
Executable file
@@ -0,0 +1,148 @@
|
||||
// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT.
|
||||
// source: proto/beacon/rpc/v1/health.proto
|
||||
|
||||
/*
|
||||
Package ethereum_beacon_rpc_v1 is a reverse proxy.
|
||||
|
||||
It translates gRPC into RESTful JSON APIs.
|
||||
*/
|
||||
package ethereum_beacon_rpc_v1
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/golang/protobuf/descriptor"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
"github.com/grpc-ecosystem/grpc-gateway/runtime"
|
||||
"github.com/grpc-ecosystem/grpc-gateway/utilities"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// Suppress "imported and not used" errors
|
||||
var _ codes.Code
|
||||
var _ io.Reader
|
||||
var _ status.Status
|
||||
var _ = runtime.String
|
||||
var _ = utilities.NewDoubleArray
|
||||
var _ = descriptor.ForMessage
|
||||
|
||||
func request_Health_GetLogsEndpoint_0(ctx context.Context, marshaler runtime.Marshaler, client HealthClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq empty.Empty
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
msg, err := client.GetLogsEndpoint(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_Health_GetLogsEndpoint_0(ctx context.Context, marshaler runtime.Marshaler, server HealthServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq empty.Empty
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
msg, err := server.GetLogsEndpoint(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
// RegisterHealthHandlerServer registers the http handlers for service Health to "mux".
|
||||
// UnaryRPC :call HealthServer directly.
|
||||
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
|
||||
func RegisterHealthHandlerServer(ctx context.Context, mux *runtime.ServeMux, server HealthServer) error {
|
||||
|
||||
mux.Handle("GET", pattern_Health_GetLogsEndpoint_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_Health_GetLogsEndpoint_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Health_GetLogsEndpoint_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RegisterHealthHandlerFromEndpoint is same as RegisterHealthHandler but
|
||||
// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
|
||||
func RegisterHealthHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
|
||||
conn, err := grpc.Dial(endpoint, opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
if cerr := conn.Close(); cerr != nil {
|
||||
grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
|
||||
}
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
if cerr := conn.Close(); cerr != nil {
|
||||
grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
|
||||
}
|
||||
}()
|
||||
}()
|
||||
|
||||
return RegisterHealthHandler(ctx, mux, conn)
|
||||
}
|
||||
|
||||
// RegisterHealthHandler registers the http handlers for service Health to "mux".
|
||||
// The handlers forward requests to the grpc endpoint over "conn".
|
||||
func RegisterHealthHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
|
||||
return RegisterHealthHandlerClient(ctx, mux, NewHealthClient(conn))
|
||||
}
|
||||
|
||||
// RegisterHealthHandlerClient registers the http handlers for service Health
|
||||
// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "HealthClient".
|
||||
// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "HealthClient"
|
||||
// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
|
||||
// "HealthClient" to call the correct interceptors.
|
||||
func RegisterHealthHandlerClient(ctx context.Context, mux *runtime.ServeMux, client HealthClient) error {
|
||||
|
||||
mux.Handle("GET", pattern_Health_GetLogsEndpoint_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_Health_GetLogsEndpoint_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Health_GetLogsEndpoint_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
pattern_Health_GetLogsEndpoint_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"eth", "v1alpha1", "health", "logs", "endpoint"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
)
|
||||
|
||||
var (
|
||||
forward_Health_GetLogsEndpoint_0 = runtime.ForwardResponseMessage
|
||||
)
|
||||
479
proto/validator/accounts/v2/web_api.pb.go
generated
479
proto/validator/accounts/v2/web_api.pb.go
generated
@@ -830,6 +830,61 @@ func (m *NodeConnectionResponse) GetDepositContractAddress() []byte {
|
||||
return nil
|
||||
}
|
||||
|
||||
type LogsEndpointResponse struct {
|
||||
ValidatorLogsEndpoint string `protobuf:"bytes,1,opt,name=validator_logs_endpoint,json=validatorLogsEndpoint,proto3" json:"validator_logs_endpoint,omitempty"`
|
||||
BeaconLogsEndpoint string `protobuf:"bytes,2,opt,name=beacon_logs_endpoint,json=beaconLogsEndpoint,proto3" json:"beacon_logs_endpoint,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *LogsEndpointResponse) Reset() { *m = LogsEndpointResponse{} }
|
||||
func (m *LogsEndpointResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*LogsEndpointResponse) ProtoMessage() {}
|
||||
func (*LogsEndpointResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_8a5153635bfe042e, []int{12}
|
||||
}
|
||||
func (m *LogsEndpointResponse) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *LogsEndpointResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_LogsEndpointResponse.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *LogsEndpointResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_LogsEndpointResponse.Merge(m, src)
|
||||
}
|
||||
func (m *LogsEndpointResponse) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *LogsEndpointResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_LogsEndpointResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_LogsEndpointResponse proto.InternalMessageInfo
|
||||
|
||||
func (m *LogsEndpointResponse) GetValidatorLogsEndpoint() string {
|
||||
if m != nil {
|
||||
return m.ValidatorLogsEndpoint
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *LogsEndpointResponse) GetBeaconLogsEndpoint() string {
|
||||
if m != nil {
|
||||
return m.BeaconLogsEndpoint
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type ChangePasswordRequest struct {
|
||||
CurrentPassword string `protobuf:"bytes,1,opt,name=current_password,json=currentPassword,proto3" json:"current_password,omitempty"`
|
||||
Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"`
|
||||
@@ -843,7 +898,7 @@ func (m *ChangePasswordRequest) Reset() { *m = ChangePasswordRequest{} }
|
||||
func (m *ChangePasswordRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*ChangePasswordRequest) ProtoMessage() {}
|
||||
func (*ChangePasswordRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_8a5153635bfe042e, []int{12}
|
||||
return fileDescriptor_8a5153635bfe042e, []int{13}
|
||||
}
|
||||
func (m *ChangePasswordRequest) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -904,7 +959,7 @@ func (m *HasWalletResponse) Reset() { *m = HasWalletResponse{} }
|
||||
func (m *HasWalletResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*HasWalletResponse) ProtoMessage() {}
|
||||
func (*HasWalletResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_8a5153635bfe042e, []int{13}
|
||||
return fileDescriptor_8a5153635bfe042e, []int{14}
|
||||
}
|
||||
func (m *HasWalletResponse) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -952,7 +1007,7 @@ func (m *ImportKeystoresRequest) Reset() { *m = ImportKeystoresRequest{}
|
||||
func (m *ImportKeystoresRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*ImportKeystoresRequest) ProtoMessage() {}
|
||||
func (*ImportKeystoresRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_8a5153635bfe042e, []int{14}
|
||||
return fileDescriptor_8a5153635bfe042e, []int{15}
|
||||
}
|
||||
func (m *ImportKeystoresRequest) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -1006,7 +1061,7 @@ func (m *ImportKeystoresResponse) Reset() { *m = ImportKeystoresResponse
|
||||
func (m *ImportKeystoresResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*ImportKeystoresResponse) ProtoMessage() {}
|
||||
func (*ImportKeystoresResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_8a5153635bfe042e, []int{15}
|
||||
return fileDescriptor_8a5153635bfe042e, []int{16}
|
||||
}
|
||||
func (m *ImportKeystoresResponse) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -1054,7 +1109,7 @@ func (m *HasUsedWebResponse) Reset() { *m = HasUsedWebResponse{} }
|
||||
func (m *HasUsedWebResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*HasUsedWebResponse) ProtoMessage() {}
|
||||
func (*HasUsedWebResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_8a5153635bfe042e, []int{16}
|
||||
return fileDescriptor_8a5153635bfe042e, []int{17}
|
||||
}
|
||||
func (m *HasUsedWebResponse) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -1111,6 +1166,7 @@ func init() {
|
||||
proto.RegisterType((*AuthRequest)(nil), "ethereum.validator.accounts.v2.AuthRequest")
|
||||
proto.RegisterType((*AuthResponse)(nil), "ethereum.validator.accounts.v2.AuthResponse")
|
||||
proto.RegisterType((*NodeConnectionResponse)(nil), "ethereum.validator.accounts.v2.NodeConnectionResponse")
|
||||
proto.RegisterType((*LogsEndpointResponse)(nil), "ethereum.validator.accounts.v2.LogsEndpointResponse")
|
||||
proto.RegisterType((*ChangePasswordRequest)(nil), "ethereum.validator.accounts.v2.ChangePasswordRequest")
|
||||
proto.RegisterType((*HasWalletResponse)(nil), "ethereum.validator.accounts.v2.HasWalletResponse")
|
||||
proto.RegisterType((*ImportKeystoresRequest)(nil), "ethereum.validator.accounts.v2.ImportKeystoresRequest")
|
||||
@@ -1123,103 +1179,107 @@ func init() {
|
||||
}
|
||||
|
||||
var fileDescriptor_8a5153635bfe042e = []byte{
|
||||
// 1522 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0x4f, 0x6f, 0x1b, 0x45,
|
||||
0x14, 0x67, 0xe3, 0xc4, 0x71, 0x9e, 0x1d, 0xc7, 0x9d, 0xa4, 0xa9, 0xeb, 0xb4, 0x49, 0xba, 0x40,
|
||||
0x93, 0xa6, 0xad, 0x5d, 0xb9, 0xd0, 0x56, 0xbd, 0xa5, 0x8e, 0x69, 0xa3, 0xf4, 0x4f, 0xb4, 0x4d,
|
||||
0x89, 0xb8, 0x74, 0x35, 0xd9, 0x9d, 0xae, 0x47, 0xb1, 0x67, 0x96, 0xdd, 0x71, 0x9a, 0x94, 0x5b,
|
||||
0x85, 0x84, 0x84, 0xc4, 0x85, 0x1e, 0x10, 0x47, 0xfa, 0x09, 0x40, 0x42, 0xe2, 0x2b, 0x70, 0x44,
|
||||
0xe2, 0x03, 0x80, 0x2a, 0x2e, 0xc0, 0x97, 0x40, 0x33, 0x3b, 0xbb, 0xfe, 0x53, 0xbb, 0x4e, 0x0e,
|
||||
0xdc, 0x76, 0xdf, 0x7b, 0xf3, 0xe6, 0x37, 0xbf, 0xf9, 0xcd, 0x7b, 0x0f, 0x2e, 0xf9, 0x01, 0x17,
|
||||
0xbc, 0x72, 0x80, 0x9b, 0xd4, 0xc5, 0x82, 0x07, 0x15, 0xec, 0x38, 0xbc, 0xcd, 0x44, 0x58, 0x39,
|
||||
0xa8, 0x56, 0x9e, 0x93, 0x3d, 0x1b, 0xfb, 0xb4, 0xac, 0x62, 0xd0, 0x22, 0x11, 0x0d, 0x12, 0x90,
|
||||
0x76, 0xab, 0x9c, 0x44, 0x97, 0xe3, 0xe8, 0xf2, 0x41, 0xb5, 0x74, 0xce, 0xe3, 0xdc, 0x6b, 0x92,
|
||||
0x0a, 0xf6, 0x69, 0x05, 0x33, 0xc6, 0x05, 0x16, 0x94, 0xb3, 0x30, 0x5a, 0x5d, 0x5a, 0xd0, 0x5e,
|
||||
0xf5, 0xb7, 0xd7, 0x7e, 0x56, 0x21, 0x2d, 0x5f, 0x1c, 0x69, 0xe7, 0x55, 0x8f, 0x8a, 0x46, 0x7b,
|
||||
0xaf, 0xec, 0xf0, 0x56, 0xc5, 0xe3, 0x1e, 0xef, 0x44, 0xc9, 0xbf, 0x08, 0xa2, 0xfc, 0x8a, 0xc2,
|
||||
0xcd, 0x7f, 0xc7, 0x60, 0xb6, 0x16, 0x10, 0x2c, 0xc8, 0x2e, 0x6e, 0x36, 0x89, 0xb0, 0xc8, 0xe7,
|
||||
0x6d, 0x12, 0x0a, 0xf4, 0x10, 0x60, 0x9f, 0x1c, 0xb5, 0x30, 0xc3, 0x1e, 0x09, 0x8a, 0xc6, 0xb2,
|
||||
0xb1, 0x9a, 0xaf, 0x96, 0xcb, 0xef, 0x86, 0x5d, 0xde, 0x4a, 0x56, 0x6c, 0x51, 0xe6, 0x5a, 0x5d,
|
||||
0x19, 0xd0, 0x0a, 0xcc, 0x3c, 0x57, 0x1b, 0xd8, 0x3e, 0x0e, 0xc3, 0xe7, 0x3c, 0x70, 0x8b, 0x63,
|
||||
0xcb, 0xc6, 0xea, 0x94, 0x95, 0x8f, 0xcc, 0xdb, 0xda, 0x8a, 0x4a, 0x90, 0x69, 0x31, 0xd2, 0xe2,
|
||||
0x8c, 0x3a, 0xc5, 0x94, 0x8a, 0x48, 0xfe, 0xd1, 0x05, 0xc8, 0xb1, 0x76, 0xcb, 0x8e, 0xb7, 0x2c,
|
||||
0x8e, 0x2f, 0x1b, 0xab, 0xe3, 0x56, 0x96, 0xb5, 0x5b, 0xeb, 0xda, 0x84, 0x96, 0x20, 0x1b, 0x90,
|
||||
0x16, 0x17, 0xc4, 0xc6, 0xae, 0x1b, 0x14, 0x27, 0x54, 0x06, 0x88, 0x4c, 0xeb, 0xae, 0x1b, 0xa0,
|
||||
0x8b, 0x30, 0xa3, 0x03, 0x9c, 0x40, 0x82, 0x11, 0x8d, 0x62, 0x5a, 0x05, 0x4d, 0x47, 0xe6, 0x5a,
|
||||
0x20, 0xb6, 0xb1, 0x68, 0x74, 0xc5, 0xed, 0x93, 0xa3, 0x28, 0x6e, 0xb2, 0x3b, 0x6e, 0x8b, 0x1c,
|
||||
0xa9, 0xb8, 0xcb, 0x80, 0xe2, 0x7c, 0xb8, 0x93, 0x32, 0xa3, 0x42, 0x75, 0x86, 0x1a, 0xd6, 0x49,
|
||||
0xcd, 0xa7, 0x30, 0xd7, 0x4b, 0x76, 0xe8, 0x73, 0x16, 0x12, 0xf4, 0x09, 0xa4, 0x23, 0x1a, 0x14,
|
||||
0xd3, 0xd9, 0xd1, 0x4c, 0xf7, 0xae, 0xb7, 0xf4, 0x6a, 0xf3, 0x17, 0x03, 0xce, 0xd4, 0x5d, 0x2a,
|
||||
0x22, 0x77, 0x8d, 0xb3, 0x67, 0xd4, 0x8b, 0x6f, 0xb4, 0x8f, 0x19, 0xe3, 0x38, 0xcc, 0x8c, 0x1d,
|
||||
0x93, 0x99, 0xd4, 0xf1, 0x99, 0x19, 0x1f, 0xcc, 0xcc, 0x0d, 0x28, 0xde, 0x25, 0x8c, 0x04, 0x58,
|
||||
0x90, 0x07, 0xfa, 0xba, 0x13, 0x76, 0xba, 0x25, 0x61, 0xf4, 0x4a, 0xc2, 0xfc, 0xda, 0x80, 0x7c,
|
||||
0x1f, 0x99, 0x4b, 0x90, 0x4d, 0xa4, 0x26, 0x1a, 0xf1, 0x41, 0x63, 0x99, 0x89, 0x06, 0xda, 0x85,
|
||||
0x99, 0x8e, 0x32, 0xed, 0x7d, 0xca, 0x22, 0x2d, 0x9e, 0x5c, 0xe0, 0xf9, 0xfd, 0x9e, 0x7f, 0xf3,
|
||||
0x5b, 0x03, 0x66, 0xef, 0xd3, 0x50, 0xc4, 0x6a, 0x8c, 0xa9, 0xbf, 0x0a, 0xb3, 0x1e, 0x11, 0xb6,
|
||||
0x4b, 0x7c, 0x1e, 0x52, 0x61, 0x8b, 0x43, 0xdb, 0xc5, 0x02, 0x2b, 0x64, 0x19, 0xab, 0xe0, 0x11,
|
||||
0xb1, 0x11, 0x79, 0x76, 0x0e, 0x37, 0xb0, 0xc0, 0x68, 0x01, 0xa6, 0x7c, 0xec, 0x11, 0x3b, 0xa4,
|
||||
0x2f, 0x88, 0x42, 0x36, 0x61, 0x65, 0xa4, 0xe1, 0x31, 0x7d, 0x41, 0xd0, 0x79, 0x00, 0xe5, 0x14,
|
||||
0x7c, 0x9f, 0x30, 0x4d, 0xbc, 0x0a, 0xdf, 0x91, 0x06, 0x54, 0x80, 0x14, 0x6e, 0x36, 0x15, 0xcb,
|
||||
0x19, 0x4b, 0x7e, 0x9a, 0xaf, 0x0d, 0x98, 0xeb, 0x05, 0xa5, 0x79, 0xaa, 0x41, 0x26, 0x79, 0x49,
|
||||
0xc6, 0x72, 0x6a, 0x35, 0x5b, 0x5d, 0x19, 0x75, 0x7e, 0x9d, 0xc3, 0x4a, 0x16, 0x4a, 0x31, 0x30,
|
||||
0x72, 0x28, 0xa9, 0x4e, 0x30, 0x69, 0xd1, 0x48, 0xf3, 0x76, 0x82, 0xeb, 0x3c, 0x80, 0xe0, 0x02,
|
||||
0x37, 0xa3, 0x43, 0xa5, 0xd4, 0xa1, 0xa6, 0x94, 0x45, 0x9e, 0xca, 0xfc, 0xc9, 0x80, 0x49, 0x9d,
|
||||
0x1c, 0x55, 0xe1, 0xb4, 0xde, 0x9d, 0x32, 0xcf, 0xf6, 0xdb, 0x7b, 0x4d, 0xea, 0x48, 0xa9, 0x29,
|
||||
0xbe, 0x72, 0xd6, 0x6c, 0xc7, 0xb9, 0xad, 0x7c, 0x5b, 0xe4, 0x48, 0x56, 0x06, 0x0d, 0xc9, 0x66,
|
||||
0xb8, 0x45, 0x34, 0x86, 0xac, 0xb6, 0x3d, 0xc4, 0x2d, 0x22, 0x91, 0xf6, 0x5f, 0x40, 0x4a, 0x25,
|
||||
0x9c, 0x76, 0x7b, 0xd8, 0x5f, 0x91, 0x71, 0x01, 0x3d, 0x50, 0x25, 0xb7, 0x5b, 0xb3, 0xf9, 0x8e,
|
||||
0x59, 0x49, 0x76, 0x0b, 0xf2, 0x31, 0x1f, 0x9d, 0x27, 0xd6, 0x81, 0x1b, 0x91, 0x9a, 0xb3, 0xc0,
|
||||
0x8f, 0x51, 0x86, 0xa8, 0x08, 0x93, 0x94, 0xb9, 0xd4, 0x21, 0x61, 0x71, 0x6c, 0x39, 0xb5, 0x3a,
|
||||
0x6e, 0xc5, 0xbf, 0xe6, 0x53, 0xc8, 0xae, 0xb7, 0x45, 0x23, 0xce, 0x54, 0x82, 0x4c, 0x52, 0x27,
|
||||
0xb5, 0xe4, 0xe3, 0x7f, 0x74, 0x1d, 0x4e, 0xc7, 0xdf, 0xb6, 0x23, 0x9f, 0x78, 0xd0, 0x52, 0xa0,
|
||||
0xf4, 0xa1, 0xe7, 0x62, 0x67, 0xad, 0xcb, 0x67, 0x3e, 0x82, 0x5c, 0x94, 0x5f, 0x5f, 0xfe, 0x1c,
|
||||
0x4c, 0x44, 0xb7, 0x15, 0x65, 0x8f, 0x7e, 0xd0, 0x25, 0x28, 0xa8, 0x0f, 0x9b, 0x1c, 0xfa, 0x34,
|
||||
0xe8, 0x64, 0x1d, 0xb7, 0x66, 0x94, 0xbd, 0x9e, 0x98, 0xcd, 0x3f, 0x0c, 0x98, 0x7f, 0xc8, 0x5d,
|
||||
0x52, 0xe3, 0x8c, 0x11, 0x47, 0x9a, 0x92, 0xdc, 0xd7, 0x60, 0x6e, 0x8f, 0x60, 0x87, 0x33, 0x9b,
|
||||
0x71, 0x97, 0xd8, 0x84, 0xb9, 0x3e, 0xa7, 0x4c, 0xe8, 0xad, 0x50, 0xe4, 0x93, 0x6b, 0xeb, 0xda,
|
||||
0x83, 0xce, 0xc1, 0x94, 0x13, 0xe5, 0x21, 0xd1, 0x5b, 0xcc, 0x58, 0x1d, 0x83, 0x64, 0x2d, 0x3c,
|
||||
0x62, 0x0e, 0x65, 0x9e, 0xba, 0xb1, 0x8c, 0x15, 0xff, 0xca, 0x6b, 0xf7, 0x08, 0x23, 0x21, 0x0d,
|
||||
0x6d, 0x41, 0x5b, 0x24, 0x6e, 0x08, 0xda, 0xb6, 0x43, 0x5b, 0x04, 0xdd, 0x82, 0x62, 0x7c, 0xed,
|
||||
0x0e, 0x67, 0x22, 0xc0, 0x8e, 0x50, 0x05, 0x90, 0x84, 0xa1, 0xea, 0x0e, 0x39, 0x6b, 0x5e, 0xfb,
|
||||
0x6b, 0xda, 0xbd, 0x1e, 0x79, 0xcd, 0x57, 0x06, 0x9c, 0xae, 0x35, 0x30, 0xf3, 0x48, 0xdc, 0x9c,
|
||||
0xe2, 0xdb, 0xb9, 0x04, 0x05, 0xa7, 0x1d, 0x04, 0x84, 0x75, 0x75, 0xb3, 0xe8, 0x70, 0x33, 0xda,
|
||||
0xde, 0xdd, 0xce, 0xfa, 0x1a, 0xde, 0x31, 0x2e, 0x32, 0xf5, 0x8e, 0x8b, 0xbc, 0x05, 0xa7, 0xee,
|
||||
0xe1, 0xb0, 0xaf, 0xe4, 0xbd, 0x0f, 0xd3, 0xba, 0xe4, 0x91, 0x43, 0x1a, 0xaa, 0xf7, 0x2c, 0x79,
|
||||
0xca, 0x45, 0xc6, 0xba, 0xb2, 0x99, 0x07, 0x30, 0xbf, 0xd9, 0xf2, 0x79, 0x20, 0xa4, 0x14, 0x05,
|
||||
0x0f, 0x48, 0x57, 0x7d, 0x42, 0xfb, 0xb1, 0xcd, 0xa6, 0x2a, 0x86, 0xb8, 0x4a, 0xbe, 0x53, 0xd6,
|
||||
0xa9, 0xc4, 0xb3, 0xa9, 0x1d, 0xbd, 0xe1, 0x7d, 0xa7, 0xeb, 0x84, 0xc7, 0x14, 0x98, 0x5b, 0x70,
|
||||
0xe6, 0xad, 0x7d, 0x3b, 0x4a, 0x89, 0xb7, 0xb3, 0xdf, 0x7e, 0x39, 0x28, 0xf6, 0x25, 0xef, 0x3c,
|
||||
0x34, 0x77, 0x01, 0xdd, 0xc3, 0xe1, 0x93, 0x90, 0xb8, 0xbb, 0x64, 0x2f, 0xc9, 0x63, 0xc2, 0x74,
|
||||
0x03, 0x87, 0x76, 0x48, 0x3d, 0x46, 0x5c, 0xbb, 0xed, 0xeb, 0xf3, 0x67, 0x1b, 0x38, 0x7c, 0xac,
|
||||
0x6c, 0x4f, 0x7c, 0x59, 0x81, 0x64, 0x8c, 0xee, 0xb3, 0x5a, 0x64, 0x8d, 0x98, 0xca, 0xb5, 0x9b,
|
||||
0x90, 0xef, 0xad, 0xee, 0x28, 0x0b, 0x93, 0x1b, 0x75, 0x6b, 0xf3, 0xd3, 0xfa, 0x46, 0xe1, 0x3d,
|
||||
0x94, 0x83, 0xcc, 0xe6, 0x83, 0xed, 0x47, 0xd6, 0x4e, 0x7d, 0xa3, 0x60, 0x20, 0x80, 0xb4, 0x55,
|
||||
0x7f, 0xf0, 0x68, 0xa7, 0x5e, 0x18, 0xab, 0xfe, 0x3d, 0x0e, 0xe9, 0x28, 0x07, 0xfa, 0xc1, 0x80,
|
||||
0x5c, 0x77, 0x7f, 0x47, 0xd7, 0x47, 0x15, 0xd4, 0x01, 0xa3, 0x57, 0xe9, 0xa3, 0x93, 0x2d, 0x8a,
|
||||
0x28, 0x30, 0x2f, 0xbe, 0xfc, 0xfd, 0xaf, 0x57, 0x63, 0xcb, 0xe6, 0x82, 0x9c, 0x36, 0x3b, 0x33,
|
||||
0x68, 0x74, 0xdc, 0x8a, 0xa3, 0x96, 0xdc, 0x36, 0xd6, 0x90, 0x80, 0x5c, 0xf7, 0x74, 0x80, 0xe6,
|
||||
0xcb, 0xd1, 0x34, 0x59, 0x8e, 0xe7, 0xc4, 0x72, 0x5d, 0x4e, 0x93, 0xa5, 0x13, 0x8e, 0x20, 0xe6,
|
||||
0x39, 0xb5, 0xff, 0x3c, 0x9a, 0x1b, 0xb4, 0x3f, 0xfa, 0xc6, 0x80, 0x42, 0x7f, 0x7f, 0x1f, 0xba,
|
||||
0xf5, 0xad, 0x51, 0x5b, 0x0f, 0x9b, 0x14, 0xcc, 0x15, 0x05, 0xe2, 0x02, 0x5a, 0xea, 0x05, 0x11,
|
||||
0x4f, 0x0b, 0x15, 0x4f, 0x2f, 0x44, 0x3f, 0x1b, 0x30, 0xd3, 0x27, 0x4a, 0x74, 0x63, 0xd4, 0xb6,
|
||||
0x83, 0x5f, 0x4f, 0xe9, 0xe6, 0x89, 0xd7, 0x69, 0xb4, 0xd7, 0x14, 0xda, 0x35, 0xf3, 0xc3, 0x81,
|
||||
0x57, 0x96, 0x3c, 0xa4, 0x4a, 0xf4, 0x0c, 0x6e, 0x1b, 0x6b, 0xd5, 0x1f, 0xc7, 0x20, 0x93, 0x8c,
|
||||
0xba, 0xdf, 0x1b, 0x90, 0xeb, 0x6e, 0xec, 0xa3, 0xd5, 0x36, 0x60, 0x36, 0x19, 0xad, 0xb6, 0x41,
|
||||
0xb3, 0x83, 0xb9, 0xa8, 0xa0, 0x17, 0xd1, 0x7c, 0x2f, 0xf4, 0x64, 0x2c, 0xf8, 0xca, 0x80, 0x7c,
|
||||
0x6f, 0xed, 0x44, 0x1f, 0x8f, 0x94, 0xf5, 0xa0, 0x5a, 0x5b, 0x1a, 0x22, 0x92, 0x61, 0x7a, 0x8f,
|
||||
0xcb, 0x51, 0x85, 0xb8, 0x54, 0x51, 0xf6, 0xda, 0x80, 0xf4, 0x3d, 0x82, 0x9b, 0xa2, 0x81, 0xbe,
|
||||
0x33, 0xe0, 0xcc, 0x5d, 0x22, 0xee, 0x24, 0xfd, 0xa7, 0xd3, 0xbb, 0x86, 0x6a, 0x71, 0xa4, 0x28,
|
||||
0x06, 0xf7, 0x40, 0xf3, 0x8a, 0x82, 0x77, 0x11, 0x7d, 0xd0, 0x0b, 0xaf, 0xa1, 0x90, 0x54, 0x54,
|
||||
0x5f, 0x74, 0x92, 0x55, 0xd5, 0x7f, 0x52, 0x30, 0x2e, 0xdb, 0x33, 0xfa, 0x02, 0xa0, 0x53, 0xde,
|
||||
0x86, 0x82, 0xaa, 0x8e, 0x02, 0xf5, 0x76, 0x89, 0x34, 0x2f, 0x28, 0x40, 0x0b, 0xe8, 0x6c, 0x2f,
|
||||
0x20, 0xca, 0xa8, 0xa0, 0xb8, 0x49, 0x5f, 0x10, 0x17, 0xbd, 0x34, 0x60, 0xe2, 0x3e, 0xf7, 0x28,
|
||||
0x43, 0x97, 0x47, 0x0e, 0x82, 0x9d, 0x59, 0xa5, 0x74, 0xe5, 0x78, 0xc1, 0xbd, 0xca, 0x31, 0x67,
|
||||
0x7b, 0x71, 0x34, 0xe5, 0xbe, 0xb2, 0x3e, 0x7d, 0x69, 0x40, 0x5a, 0xd6, 0xec, 0xb6, 0xff, 0x7f,
|
||||
0xa2, 0x58, 0x52, 0x28, 0xce, 0x9a, 0x7d, 0xd5, 0x2a, 0x54, 0x1b, 0x4b, 0x18, 0x9f, 0x41, 0xfa,
|
||||
0x3e, 0xf7, 0x78, 0x5b, 0x0c, 0xbd, 0x84, 0x61, 0xc2, 0x1c, 0x92, 0xba, 0xa9, 0xb2, 0xdd, 0x36,
|
||||
0xd6, 0xee, 0xe4, 0x7e, 0x7d, 0xb3, 0x68, 0xfc, 0xf6, 0x66, 0xd1, 0xf8, 0xf3, 0xcd, 0xa2, 0xb1,
|
||||
0x97, 0x56, 0xcb, 0xaf, 0xff, 0x17, 0x00, 0x00, 0xff, 0xff, 0x51, 0xb5, 0x1d, 0x4b, 0x3e, 0x10,
|
||||
0x00, 0x00,
|
||||
// 1592 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0xcd, 0x6e, 0x23, 0xc7,
|
||||
0x11, 0xce, 0x90, 0x12, 0x45, 0x15, 0x29, 0x8a, 0x6e, 0xfd, 0xd1, 0xd4, 0x5a, 0xd2, 0x8e, 0xe3,
|
||||
0x95, 0x56, 0x6b, 0x93, 0x06, 0x37, 0x59, 0x2f, 0xf6, 0x26, 0x53, 0x8c, 0x57, 0xd0, 0xfe, 0x08,
|
||||
0x63, 0x39, 0x42, 0x2e, 0x1e, 0xb4, 0x66, 0xda, 0xc3, 0x86, 0xc8, 0xee, 0xc9, 0x4c, 0x53, 0x2b,
|
||||
0x6d, 0x2e, 0x81, 0x11, 0x20, 0x40, 0x80, 0x5c, 0xe2, 0x43, 0x90, 0x63, 0xf2, 0x04, 0x49, 0x10,
|
||||
0x20, 0xaf, 0x90, 0x63, 0x80, 0x3c, 0x40, 0x82, 0x45, 0x2e, 0x49, 0x5e, 0x22, 0xe8, 0x9e, 0x9e,
|
||||
0x3f, 0x2e, 0x69, 0x4a, 0x07, 0xdf, 0x66, 0xaa, 0xaa, 0xab, 0xbe, 0xae, 0xfe, 0xea, 0x07, 0xee,
|
||||
0xfb, 0x01, 0x17, 0xbc, 0x7d, 0x89, 0x07, 0xd4, 0xc5, 0x82, 0x07, 0x6d, 0xec, 0x38, 0x7c, 0xc4,
|
||||
0x44, 0xd8, 0xbe, 0xec, 0xb4, 0x5f, 0x91, 0x73, 0x1b, 0xfb, 0xb4, 0xa5, 0x6c, 0xd0, 0x16, 0x11,
|
||||
0x7d, 0x12, 0x90, 0xd1, 0xb0, 0x95, 0x58, 0xb7, 0x62, 0xeb, 0xd6, 0x65, 0xa7, 0x79, 0xc7, 0xe3,
|
||||
0xdc, 0x1b, 0x90, 0x36, 0xf6, 0x69, 0x1b, 0x33, 0xc6, 0x05, 0x16, 0x94, 0xb3, 0x30, 0x3a, 0xdd,
|
||||
0xdc, 0xd4, 0x5a, 0xf5, 0x77, 0x3e, 0xfa, 0xaa, 0x4d, 0x86, 0xbe, 0xb8, 0xd6, 0xca, 0x8f, 0x3c,
|
||||
0x2a, 0xfa, 0xa3, 0xf3, 0x96, 0xc3, 0x87, 0x6d, 0x8f, 0x7b, 0x3c, 0xb5, 0x92, 0x7f, 0x11, 0x44,
|
||||
0xf9, 0x15, 0x99, 0x9b, 0xff, 0x2b, 0xc0, 0x4a, 0x37, 0x20, 0x58, 0x90, 0x33, 0x3c, 0x18, 0x10,
|
||||
0x61, 0x91, 0x9f, 0x8e, 0x48, 0x28, 0xd0, 0x0b, 0x80, 0x0b, 0x72, 0x3d, 0xc4, 0x0c, 0x7b, 0x24,
|
||||
0x68, 0x18, 0x3b, 0xc6, 0x5e, 0xad, 0xd3, 0x6a, 0x7d, 0x3b, 0xec, 0xd6, 0x71, 0x72, 0xe2, 0x98,
|
||||
0x32, 0xd7, 0xca, 0x78, 0x40, 0xbb, 0xb0, 0xfc, 0x4a, 0x05, 0xb0, 0x7d, 0x1c, 0x86, 0xaf, 0x78,
|
||||
0xe0, 0x36, 0x0a, 0x3b, 0xc6, 0xde, 0xa2, 0x55, 0x8b, 0xc4, 0x27, 0x5a, 0x8a, 0x9a, 0x50, 0x1e,
|
||||
0x32, 0x32, 0xe4, 0x8c, 0x3a, 0x8d, 0xa2, 0xb2, 0x48, 0xfe, 0xd1, 0x5d, 0xa8, 0xb2, 0xd1, 0xd0,
|
||||
0x8e, 0x43, 0x36, 0xe6, 0x76, 0x8c, 0xbd, 0x39, 0xab, 0xc2, 0x46, 0xc3, 0x03, 0x2d, 0x42, 0xdb,
|
||||
0x50, 0x09, 0xc8, 0x90, 0x0b, 0x62, 0x63, 0xd7, 0x0d, 0x1a, 0xf3, 0xca, 0x03, 0x44, 0xa2, 0x03,
|
||||
0xd7, 0x0d, 0xd0, 0x3d, 0x58, 0xd6, 0x06, 0x4e, 0x20, 0xc1, 0x88, 0x7e, 0xa3, 0xa4, 0x8c, 0x96,
|
||||
0x22, 0x71, 0x37, 0x10, 0x27, 0x58, 0xf4, 0x33, 0x76, 0x17, 0xe4, 0x3a, 0xb2, 0x5b, 0xc8, 0xda,
|
||||
0x1d, 0x93, 0x6b, 0x65, 0xf7, 0x00, 0x50, 0xec, 0x0f, 0xa7, 0x2e, 0xcb, 0xca, 0x54, 0x7b, 0xe8,
|
||||
0x62, 0xed, 0xd4, 0xfc, 0x12, 0x56, 0xf3, 0xc9, 0x0e, 0x7d, 0xce, 0x42, 0x82, 0x7e, 0x04, 0xa5,
|
||||
0x28, 0x0d, 0x2a, 0xd3, 0x95, 0xd9, 0x99, 0xce, 0x9f, 0xb7, 0xf4, 0x69, 0xf3, 0xaf, 0x06, 0x6c,
|
||||
0xf4, 0x5c, 0x2a, 0x22, 0x75, 0x97, 0xb3, 0xaf, 0xa8, 0x17, 0xbf, 0xe8, 0x58, 0x66, 0x8c, 0x9b,
|
||||
0x64, 0xa6, 0x70, 0xc3, 0xcc, 0x14, 0x6f, 0x9e, 0x99, 0xb9, 0xc9, 0x99, 0x79, 0x04, 0x8d, 0xcf,
|
||||
0x08, 0x23, 0x01, 0x16, 0xe4, 0xb9, 0x7e, 0xee, 0x24, 0x3b, 0x59, 0x4a, 0x18, 0x79, 0x4a, 0x98,
|
||||
0xbf, 0x32, 0xa0, 0x36, 0x96, 0xcc, 0x6d, 0xa8, 0x24, 0x54, 0x13, 0xfd, 0xf8, 0xa2, 0x31, 0xcd,
|
||||
0x44, 0x1f, 0x9d, 0xc1, 0x72, 0xca, 0x4c, 0xfb, 0x82, 0xb2, 0x88, 0x8b, 0xb7, 0x27, 0x78, 0xed,
|
||||
0x22, 0xf7, 0x6f, 0xfe, 0xc6, 0x80, 0x95, 0x67, 0x34, 0x14, 0x31, 0x1b, 0xe3, 0xd4, 0x7f, 0x04,
|
||||
0x2b, 0x1e, 0x11, 0xb6, 0x4b, 0x7c, 0x1e, 0x52, 0x61, 0x8b, 0x2b, 0xdb, 0xc5, 0x02, 0x2b, 0x64,
|
||||
0x65, 0xab, 0xee, 0x11, 0x71, 0x18, 0x69, 0x4e, 0xaf, 0x0e, 0xb1, 0xc0, 0x68, 0x13, 0x16, 0x7d,
|
||||
0xec, 0x11, 0x3b, 0xa4, 0xaf, 0x89, 0x42, 0x36, 0x6f, 0x95, 0xa5, 0xe0, 0x73, 0xfa, 0x9a, 0xa0,
|
||||
0xf7, 0x00, 0x94, 0x52, 0xf0, 0x0b, 0xc2, 0x74, 0xe2, 0x95, 0xf9, 0xa9, 0x14, 0xa0, 0x3a, 0x14,
|
||||
0xf1, 0x60, 0xa0, 0xb2, 0x5c, 0xb6, 0xe4, 0xa7, 0xf9, 0x07, 0x03, 0x56, 0xf3, 0xa0, 0x74, 0x9e,
|
||||
0xba, 0x50, 0x4e, 0x2a, 0xc9, 0xd8, 0x29, 0xee, 0x55, 0x3a, 0xbb, 0xb3, 0xee, 0xaf, 0x7d, 0x58,
|
||||
0xc9, 0x41, 0x49, 0x06, 0x46, 0xae, 0x64, 0xaa, 0x13, 0x4c, 0x9a, 0x34, 0x52, 0x7c, 0x92, 0xe0,
|
||||
0x7a, 0x0f, 0x40, 0x70, 0x81, 0x07, 0xd1, 0xa5, 0x8a, 0xea, 0x52, 0x8b, 0x4a, 0x22, 0x6f, 0x65,
|
||||
0xfe, 0xc9, 0x80, 0x05, 0xed, 0x1c, 0x75, 0x60, 0x4d, 0x47, 0xa7, 0xcc, 0xb3, 0xfd, 0xd1, 0xf9,
|
||||
0x80, 0x3a, 0x92, 0x6a, 0x2a, 0x5f, 0x55, 0x6b, 0x25, 0x55, 0x9e, 0x28, 0xdd, 0x31, 0xb9, 0x96,
|
||||
0x9d, 0x41, 0x43, 0xb2, 0x19, 0x1e, 0x12, 0x8d, 0xa1, 0xa2, 0x65, 0x2f, 0xf0, 0x90, 0x48, 0xa4,
|
||||
0xe3, 0x0f, 0x50, 0x54, 0x0e, 0x97, 0xdc, 0x5c, 0xf6, 0x77, 0xa5, 0x5d, 0x40, 0x2f, 0x55, 0xcb,
|
||||
0xcd, 0x72, 0xb6, 0x96, 0x8a, 0x15, 0x65, 0x8f, 0xa1, 0x16, 0xe7, 0x23, 0x2d, 0xb1, 0x14, 0x6e,
|
||||
0x94, 0xd4, 0xaa, 0x05, 0x7e, 0x8c, 0x32, 0x44, 0x0d, 0x58, 0xa0, 0xcc, 0xa5, 0x0e, 0x09, 0x1b,
|
||||
0x85, 0x9d, 0xe2, 0xde, 0x9c, 0x15, 0xff, 0x9a, 0x5f, 0x42, 0xe5, 0x60, 0x24, 0xfa, 0xb1, 0xa7,
|
||||
0x26, 0x94, 0x93, 0x3e, 0xa9, 0x29, 0x1f, 0xff, 0xa3, 0x87, 0xb0, 0x16, 0x7f, 0xdb, 0x8e, 0x2c,
|
||||
0xf1, 0x60, 0xa8, 0x40, 0xe9, 0x4b, 0xaf, 0xc6, 0xca, 0x6e, 0x46, 0x67, 0xbe, 0x84, 0x6a, 0xe4,
|
||||
0x5f, 0x3f, 0xfe, 0x2a, 0xcc, 0x47, 0xaf, 0x15, 0x79, 0x8f, 0x7e, 0xd0, 0x7d, 0xa8, 0xab, 0x0f,
|
||||
0x9b, 0x5c, 0xf9, 0x34, 0x48, 0xbd, 0xce, 0x59, 0xcb, 0x4a, 0xde, 0x4b, 0xc4, 0xe6, 0x3f, 0x0d,
|
||||
0x58, 0x7f, 0xc1, 0x5d, 0xd2, 0xe5, 0x8c, 0x11, 0x47, 0x8a, 0x12, 0xdf, 0x1f, 0xc3, 0xea, 0x39,
|
||||
0xc1, 0x0e, 0x67, 0x36, 0xe3, 0x2e, 0xb1, 0x09, 0x73, 0x7d, 0x4e, 0x99, 0xd0, 0xa1, 0x50, 0xa4,
|
||||
0x93, 0x67, 0x7b, 0x5a, 0x83, 0xee, 0xc0, 0xa2, 0x13, 0xf9, 0x21, 0x51, 0x2d, 0x96, 0xad, 0x54,
|
||||
0x20, 0xb3, 0x16, 0x5e, 0x33, 0x87, 0x32, 0x4f, 0xbd, 0x58, 0xd9, 0x8a, 0x7f, 0xe5, 0xb3, 0x7b,
|
||||
0x84, 0x91, 0x90, 0x86, 0xb6, 0xa0, 0x43, 0x12, 0x0f, 0x04, 0x2d, 0x3b, 0xa5, 0x43, 0x82, 0x1e,
|
||||
0x43, 0x23, 0x7e, 0x76, 0x87, 0x33, 0x11, 0x60, 0x47, 0xa8, 0x06, 0x48, 0xc2, 0x50, 0x4d, 0x87,
|
||||
0xaa, 0xb5, 0xae, 0xf5, 0x5d, 0xad, 0x3e, 0x88, 0xb4, 0xe6, 0xcf, 0x65, 0xe1, 0x70, 0x2f, 0x8c,
|
||||
0x51, 0x26, 0xf7, 0x7b, 0x04, 0x1b, 0x49, 0x79, 0xd8, 0x03, 0xee, 0x85, 0xe3, 0x57, 0x5c, 0x4b,
|
||||
0xd4, 0xd9, 0xf3, 0x99, 0xbc, 0xe4, 0x0f, 0x15, 0xb2, 0x79, 0xc9, 0x9e, 0x30, 0xbf, 0x31, 0x60,
|
||||
0xad, 0xdb, 0xc7, 0xcc, 0x23, 0xf1, 0x7c, 0x8c, 0x09, 0x72, 0x1f, 0xea, 0xce, 0x28, 0x08, 0x08,
|
||||
0xcb, 0x0c, 0xd4, 0x28, 0xf8, 0xb2, 0x96, 0x67, 0x27, 0xea, 0xd8, 0xcc, 0xbd, 0x01, 0x97, 0x8a,
|
||||
0xdf, 0xc2, 0xa5, 0xc7, 0xf0, 0xce, 0x53, 0x1c, 0x8e, 0x75, 0xdd, 0xf7, 0x61, 0x49, 0x77, 0x5d,
|
||||
0x72, 0x45, 0x43, 0xd5, 0x52, 0xe4, 0x53, 0x55, 0x23, 0x61, 0x4f, 0xc9, 0xcc, 0x4b, 0x58, 0x3f,
|
||||
0x1a, 0xfa, 0x3c, 0x10, 0xb2, 0x1a, 0x04, 0x0f, 0x48, 0xa6, 0x45, 0xa2, 0x8b, 0x58, 0x66, 0x53,
|
||||
0x65, 0x43, 0x5c, 0x55, 0x41, 0x8b, 0xd6, 0x3b, 0x89, 0xe6, 0x48, 0x2b, 0xf2, 0xe6, 0x63, 0xb7,
|
||||
0x4b, 0xcd, 0xe3, 0x14, 0x98, 0xc7, 0xb0, 0xf1, 0x56, 0xdc, 0x94, 0xac, 0x71, 0x38, 0xfb, 0xed,
|
||||
0xe2, 0x45, 0xb1, 0x2e, 0x69, 0x35, 0xa1, 0x79, 0x06, 0xe8, 0x29, 0x0e, 0xbf, 0x08, 0x89, 0x7b,
|
||||
0x46, 0xce, 0x13, 0x3f, 0x26, 0x2c, 0xf5, 0x71, 0x68, 0x87, 0xd4, 0x63, 0xc4, 0xb5, 0x47, 0xbe,
|
||||
0xbe, 0x7f, 0xa5, 0x8f, 0xc3, 0xcf, 0x95, 0xec, 0x0b, 0x5f, 0x36, 0x41, 0x69, 0xa3, 0x47, 0xbd,
|
||||
0xe6, 0x79, 0x3f, 0x4e, 0xe5, 0xfe, 0x27, 0x50, 0xcb, 0x0f, 0x18, 0x54, 0x81, 0x85, 0xc3, 0x9e,
|
||||
0x75, 0xf4, 0xe3, 0xde, 0x61, 0xfd, 0x7b, 0xa8, 0x0a, 0xe5, 0xa3, 0xe7, 0x27, 0x2f, 0xad, 0xd3,
|
||||
0xde, 0x61, 0xdd, 0x40, 0x00, 0x25, 0xab, 0xf7, 0xfc, 0xe5, 0x69, 0xaf, 0x5e, 0xe8, 0xfc, 0x67,
|
||||
0x0e, 0x4a, 0x91, 0x0f, 0xf4, 0x7b, 0x03, 0xaa, 0xd9, 0x15, 0x03, 0x3d, 0x9c, 0xd5, 0xd3, 0x27,
|
||||
0x6c, 0x7f, 0xcd, 0x1f, 0xdc, 0xee, 0x50, 0x94, 0x02, 0xf3, 0xde, 0xd7, 0xff, 0xf8, 0xf7, 0x37,
|
||||
0x85, 0x1d, 0x73, 0x53, 0x2e, 0xbc, 0xe9, 0x1a, 0x1c, 0x5d, 0xb7, 0xed, 0xa8, 0x23, 0x4f, 0x8c,
|
||||
0x7d, 0x24, 0xa0, 0x9a, 0x5d, 0x50, 0xd0, 0x7a, 0x2b, 0x5a, 0x68, 0x5b, 0xf1, 0xaa, 0xda, 0xea,
|
||||
0xc9, 0x85, 0xb6, 0x79, 0xcb, 0x2d, 0xc8, 0xbc, 0xa3, 0xe2, 0xaf, 0xa3, 0xd5, 0x49, 0xf1, 0xd1,
|
||||
0xaf, 0x0d, 0xa8, 0x8f, 0xaf, 0x18, 0x53, 0x43, 0x3f, 0x9e, 0x15, 0x7a, 0xda, 0xb2, 0x62, 0xee,
|
||||
0x2a, 0x10, 0x77, 0xd1, 0x76, 0x1e, 0x44, 0xbc, 0xb0, 0xb4, 0x3d, 0x7d, 0x10, 0xfd, 0xc5, 0x80,
|
||||
0xe5, 0x31, 0x52, 0xa2, 0x47, 0xb3, 0xc2, 0x4e, 0xae, 0x9e, 0xe6, 0x27, 0xb7, 0x3e, 0xa7, 0xd1,
|
||||
0x7e, 0xac, 0xd0, 0xee, 0x9b, 0x1f, 0x4c, 0x7c, 0xb2, 0xa4, 0x90, 0xda, 0x51, 0x19, 0x3c, 0x31,
|
||||
0xf6, 0x3b, 0x7f, 0x2c, 0x40, 0x39, 0xd9, 0xb6, 0x7f, 0x67, 0x40, 0x35, 0xbb, 0x5b, 0xcc, 0x66,
|
||||
0xdb, 0x84, 0xf5, 0x68, 0x36, 0xdb, 0x26, 0xad, 0x2f, 0xe6, 0x96, 0x82, 0xde, 0x40, 0xeb, 0x79,
|
||||
0xe8, 0xc9, 0x66, 0xf2, 0x4b, 0x03, 0x6a, 0xf9, 0xde, 0x89, 0x7e, 0x38, 0x93, 0xd6, 0x93, 0x7a,
|
||||
0x6d, 0x73, 0x0a, 0x49, 0xa6, 0xf1, 0x3d, 0x6e, 0x47, 0x6d, 0xe2, 0x52, 0x95, 0xb2, 0x3f, 0x17,
|
||||
0xa0, 0xf4, 0x94, 0xe0, 0x81, 0xe8, 0xa3, 0xdf, 0x1a, 0xb0, 0xf1, 0x19, 0x11, 0x9f, 0x26, 0x23,
|
||||
0x30, 0x1d, 0x9f, 0x53, 0xb9, 0x38, 0x93, 0x14, 0x93, 0xc7, 0xb0, 0xf9, 0xa1, 0x82, 0x77, 0x0f,
|
||||
0x7d, 0x3f, 0x0f, 0xaf, 0xaf, 0x90, 0xb4, 0xd5, 0x68, 0x76, 0xd2, 0xe8, 0x51, 0x79, 0x88, 0xec,
|
||||
0xf8, 0x09, 0xa7, 0x42, 0x9a, 0xfd, 0x62, 0x13, 0xe6, 0xa6, 0xf9, 0x40, 0x01, 0xfa, 0x00, 0xbd,
|
||||
0x3f, 0x11, 0x90, 0x9c, 0x89, 0xed, 0x78, 0x26, 0x86, 0x9d, 0xff, 0x16, 0x61, 0x4e, 0x6e, 0x2c,
|
||||
0xe8, 0x67, 0x00, 0x69, 0xbb, 0x9d, 0x8a, 0xa8, 0x33, 0x0b, 0xd1, 0xdb, 0x2d, 0xdb, 0xbc, 0xab,
|
||||
0xf0, 0x6c, 0xa2, 0x77, 0xf3, 0x78, 0x28, 0xa3, 0x82, 0xe2, 0x01, 0x7d, 0x4d, 0x5c, 0xf4, 0xb5,
|
||||
0x01, 0xf3, 0xcf, 0xb8, 0x47, 0x19, 0x7a, 0x30, 0x73, 0x37, 0x4e, 0xd7, 0xb7, 0xe6, 0x87, 0x37,
|
||||
0x33, 0xce, 0x33, 0xd9, 0x5c, 0xc9, 0xe3, 0x18, 0xc8, 0xb8, 0xb2, 0x5f, 0xfe, 0xc2, 0x80, 0x92,
|
||||
0x9c, 0x21, 0x23, 0xff, 0xbb, 0x44, 0xb1, 0xad, 0x50, 0xbc, 0x6b, 0x8e, 0x75, 0xcf, 0x50, 0x05,
|
||||
0x96, 0x30, 0x7e, 0x02, 0xa5, 0x67, 0xdc, 0xe3, 0x23, 0x31, 0xf5, 0x11, 0xa6, 0x15, 0xca, 0x14,
|
||||
0xd7, 0x03, 0xe5, 0xed, 0x89, 0xb1, 0xff, 0x69, 0xf5, 0x6f, 0x6f, 0xb6, 0x8c, 0xbf, 0xbf, 0xd9,
|
||||
0x32, 0xfe, 0xf5, 0x66, 0xcb, 0x38, 0x2f, 0xa9, 0xe3, 0x0f, 0xff, 0x1f, 0x00, 0x00, 0xff, 0xff,
|
||||
0x48, 0x2e, 0xe9, 0xa6, 0x51, 0x11, 0x00, 0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
@@ -1523,6 +1583,7 @@ var _Accounts_serviceDesc = grpc.ServiceDesc{
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||
type HealthClient interface {
|
||||
GetBeaconNodeConnection(ctx context.Context, in *types.Empty, opts ...grpc.CallOption) (*NodeConnectionResponse, error)
|
||||
GetLogsEndpoints(ctx context.Context, in *types.Empty, opts ...grpc.CallOption) (*LogsEndpointResponse, error)
|
||||
}
|
||||
|
||||
type healthClient struct {
|
||||
@@ -1542,9 +1603,19 @@ func (c *healthClient) GetBeaconNodeConnection(ctx context.Context, in *types.Em
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *healthClient) GetLogsEndpoints(ctx context.Context, in *types.Empty, opts ...grpc.CallOption) (*LogsEndpointResponse, error) {
|
||||
out := new(LogsEndpointResponse)
|
||||
err := c.cc.Invoke(ctx, "/ethereum.validator.accounts.v2.Health/GetLogsEndpoints", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// HealthServer is the server API for Health service.
|
||||
type HealthServer interface {
|
||||
GetBeaconNodeConnection(context.Context, *types.Empty) (*NodeConnectionResponse, error)
|
||||
GetLogsEndpoints(context.Context, *types.Empty) (*LogsEndpointResponse, error)
|
||||
}
|
||||
|
||||
// UnimplementedHealthServer can be embedded to have forward compatible implementations.
|
||||
@@ -1554,6 +1625,9 @@ type UnimplementedHealthServer struct {
|
||||
func (*UnimplementedHealthServer) GetBeaconNodeConnection(ctx context.Context, req *types.Empty) (*NodeConnectionResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetBeaconNodeConnection not implemented")
|
||||
}
|
||||
func (*UnimplementedHealthServer) GetLogsEndpoints(ctx context.Context, req *types.Empty) (*LogsEndpointResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetLogsEndpoints not implemented")
|
||||
}
|
||||
|
||||
func RegisterHealthServer(s *grpc.Server, srv HealthServer) {
|
||||
s.RegisterService(&_Health_serviceDesc, srv)
|
||||
@@ -1577,6 +1651,24 @@ func _Health_GetBeaconNodeConnection_Handler(srv interface{}, ctx context.Contex
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Health_GetLogsEndpoints_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(types.Empty)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(HealthServer).GetLogsEndpoints(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/ethereum.validator.accounts.v2.Health/GetLogsEndpoints",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(HealthServer).GetLogsEndpoints(ctx, req.(*types.Empty))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _Health_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "ethereum.validator.accounts.v2.Health",
|
||||
HandlerType: (*HealthServer)(nil),
|
||||
@@ -1585,6 +1677,10 @@ var _Health_serviceDesc = grpc.ServiceDesc{
|
||||
MethodName: "GetBeaconNodeConnection",
|
||||
Handler: _Health_GetBeaconNodeConnection_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetLogsEndpoints",
|
||||
Handler: _Health_GetLogsEndpoints_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "proto/validator/accounts/v2/web_api.proto",
|
||||
@@ -2383,6 +2479,47 @@ func (m *NodeConnectionResponse) MarshalToSizedBuffer(dAtA []byte) (int, error)
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *LogsEndpointResponse) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *LogsEndpointResponse) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.Size()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *LogsEndpointResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.XXX_unrecognized != nil {
|
||||
i -= len(m.XXX_unrecognized)
|
||||
copy(dAtA[i:], m.XXX_unrecognized)
|
||||
}
|
||||
if len(m.BeaconLogsEndpoint) > 0 {
|
||||
i -= len(m.BeaconLogsEndpoint)
|
||||
copy(dAtA[i:], m.BeaconLogsEndpoint)
|
||||
i = encodeVarintWebApi(dAtA, i, uint64(len(m.BeaconLogsEndpoint)))
|
||||
i--
|
||||
dAtA[i] = 0x12
|
||||
}
|
||||
if len(m.ValidatorLogsEndpoint) > 0 {
|
||||
i -= len(m.ValidatorLogsEndpoint)
|
||||
copy(dAtA[i:], m.ValidatorLogsEndpoint)
|
||||
i = encodeVarintWebApi(dAtA, i, uint64(len(m.ValidatorLogsEndpoint)))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *ChangePasswordRequest) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
@@ -2897,6 +3034,26 @@ func (m *NodeConnectionResponse) Size() (n int) {
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *LogsEndpointResponse) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
l = len(m.ValidatorLogsEndpoint)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovWebApi(uint64(l))
|
||||
}
|
||||
l = len(m.BeaconLogsEndpoint)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovWebApi(uint64(l))
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
n += len(m.XXX_unrecognized)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *ChangePasswordRequest) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
@@ -4781,6 +4938,124 @@ func (m *NodeConnectionResponse) Unmarshal(dAtA []byte) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *LogsEndpointResponse) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowWebApi
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: LogsEndpointResponse: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: LogsEndpointResponse: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field ValidatorLogsEndpoint", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowWebApi
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthWebApi
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthWebApi
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.ValidatorLogsEndpoint = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field BeaconLogsEndpoint", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowWebApi
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthWebApi
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthWebApi
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.BeaconLogsEndpoint = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipWebApi(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthWebApi
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
return ErrInvalidLengthWebApi
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *ChangePasswordRequest) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
|
||||
@@ -50,6 +50,11 @@ service Health {
|
||||
get: "/v2/validator/health/node_connection"
|
||||
};
|
||||
}
|
||||
rpc GetLogsEndpoints(google.protobuf.Empty) returns (LogsEndpointResponse) {
|
||||
option (google.api.http) = {
|
||||
get: "/v2/validator/health/logs/endpoints"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
service Auth {
|
||||
@@ -198,6 +203,11 @@ message NodeConnectionResponse {
|
||||
bytes deposit_contract_address = 5;
|
||||
}
|
||||
|
||||
message LogsEndpointResponse {
|
||||
string validator_logs_endpoint = 1;
|
||||
string beacon_logs_endpoint = 2;
|
||||
}
|
||||
|
||||
message ChangePasswordRequest {
|
||||
string current_password = 1;
|
||||
string password = 2;
|
||||
|
||||
476
proto/validator/accounts/v2_gateway/web_api.pb.go
generated
476
proto/validator/accounts/v2_gateway/web_api.pb.go
generated
@@ -854,6 +854,61 @@ func (x *NodeConnectionResponse) GetDepositContractAddress() []byte {
|
||||
return nil
|
||||
}
|
||||
|
||||
type LogsEndpointResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
ValidatorLogsEndpoint string `protobuf:"bytes,1,opt,name=validator_logs_endpoint,json=validatorLogsEndpoint,proto3" json:"validator_logs_endpoint,omitempty"`
|
||||
BeaconLogsEndpoint string `protobuf:"bytes,2,opt,name=beacon_logs_endpoint,json=beaconLogsEndpoint,proto3" json:"beacon_logs_endpoint,omitempty"`
|
||||
}
|
||||
|
||||
func (x *LogsEndpointResponse) Reset() {
|
||||
*x = LogsEndpointResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_proto_validator_accounts_v2_web_api_proto_msgTypes[12]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *LogsEndpointResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*LogsEndpointResponse) ProtoMessage() {}
|
||||
|
||||
func (x *LogsEndpointResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_validator_accounts_v2_web_api_proto_msgTypes[12]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use LogsEndpointResponse.ProtoReflect.Descriptor instead.
|
||||
func (*LogsEndpointResponse) Descriptor() ([]byte, []int) {
|
||||
return file_proto_validator_accounts_v2_web_api_proto_rawDescGZIP(), []int{12}
|
||||
}
|
||||
|
||||
func (x *LogsEndpointResponse) GetValidatorLogsEndpoint() string {
|
||||
if x != nil {
|
||||
return x.ValidatorLogsEndpoint
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *LogsEndpointResponse) GetBeaconLogsEndpoint() string {
|
||||
if x != nil {
|
||||
return x.BeaconLogsEndpoint
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type ChangePasswordRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
@@ -867,7 +922,7 @@ type ChangePasswordRequest struct {
|
||||
func (x *ChangePasswordRequest) Reset() {
|
||||
*x = ChangePasswordRequest{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_proto_validator_accounts_v2_web_api_proto_msgTypes[12]
|
||||
mi := &file_proto_validator_accounts_v2_web_api_proto_msgTypes[13]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
@@ -880,7 +935,7 @@ func (x *ChangePasswordRequest) String() string {
|
||||
func (*ChangePasswordRequest) ProtoMessage() {}
|
||||
|
||||
func (x *ChangePasswordRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_validator_accounts_v2_web_api_proto_msgTypes[12]
|
||||
mi := &file_proto_validator_accounts_v2_web_api_proto_msgTypes[13]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@@ -893,7 +948,7 @@ func (x *ChangePasswordRequest) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use ChangePasswordRequest.ProtoReflect.Descriptor instead.
|
||||
func (*ChangePasswordRequest) Descriptor() ([]byte, []int) {
|
||||
return file_proto_validator_accounts_v2_web_api_proto_rawDescGZIP(), []int{12}
|
||||
return file_proto_validator_accounts_v2_web_api_proto_rawDescGZIP(), []int{13}
|
||||
}
|
||||
|
||||
func (x *ChangePasswordRequest) GetCurrentPassword() string {
|
||||
@@ -928,7 +983,7 @@ type HasWalletResponse struct {
|
||||
func (x *HasWalletResponse) Reset() {
|
||||
*x = HasWalletResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_proto_validator_accounts_v2_web_api_proto_msgTypes[13]
|
||||
mi := &file_proto_validator_accounts_v2_web_api_proto_msgTypes[14]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
@@ -941,7 +996,7 @@ func (x *HasWalletResponse) String() string {
|
||||
func (*HasWalletResponse) ProtoMessage() {}
|
||||
|
||||
func (x *HasWalletResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_validator_accounts_v2_web_api_proto_msgTypes[13]
|
||||
mi := &file_proto_validator_accounts_v2_web_api_proto_msgTypes[14]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@@ -954,7 +1009,7 @@ func (x *HasWalletResponse) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use HasWalletResponse.ProtoReflect.Descriptor instead.
|
||||
func (*HasWalletResponse) Descriptor() ([]byte, []int) {
|
||||
return file_proto_validator_accounts_v2_web_api_proto_rawDescGZIP(), []int{13}
|
||||
return file_proto_validator_accounts_v2_web_api_proto_rawDescGZIP(), []int{14}
|
||||
}
|
||||
|
||||
func (x *HasWalletResponse) GetWalletExists() bool {
|
||||
@@ -976,7 +1031,7 @@ type ImportKeystoresRequest struct {
|
||||
func (x *ImportKeystoresRequest) Reset() {
|
||||
*x = ImportKeystoresRequest{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_proto_validator_accounts_v2_web_api_proto_msgTypes[14]
|
||||
mi := &file_proto_validator_accounts_v2_web_api_proto_msgTypes[15]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
@@ -989,7 +1044,7 @@ func (x *ImportKeystoresRequest) String() string {
|
||||
func (*ImportKeystoresRequest) ProtoMessage() {}
|
||||
|
||||
func (x *ImportKeystoresRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_validator_accounts_v2_web_api_proto_msgTypes[14]
|
||||
mi := &file_proto_validator_accounts_v2_web_api_proto_msgTypes[15]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@@ -1002,7 +1057,7 @@ func (x *ImportKeystoresRequest) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use ImportKeystoresRequest.ProtoReflect.Descriptor instead.
|
||||
func (*ImportKeystoresRequest) Descriptor() ([]byte, []int) {
|
||||
return file_proto_validator_accounts_v2_web_api_proto_rawDescGZIP(), []int{14}
|
||||
return file_proto_validator_accounts_v2_web_api_proto_rawDescGZIP(), []int{15}
|
||||
}
|
||||
|
||||
func (x *ImportKeystoresRequest) GetKeystoresImported() []string {
|
||||
@@ -1030,7 +1085,7 @@ type ImportKeystoresResponse struct {
|
||||
func (x *ImportKeystoresResponse) Reset() {
|
||||
*x = ImportKeystoresResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_proto_validator_accounts_v2_web_api_proto_msgTypes[15]
|
||||
mi := &file_proto_validator_accounts_v2_web_api_proto_msgTypes[16]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
@@ -1043,7 +1098,7 @@ func (x *ImportKeystoresResponse) String() string {
|
||||
func (*ImportKeystoresResponse) ProtoMessage() {}
|
||||
|
||||
func (x *ImportKeystoresResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_validator_accounts_v2_web_api_proto_msgTypes[15]
|
||||
mi := &file_proto_validator_accounts_v2_web_api_proto_msgTypes[16]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@@ -1056,7 +1111,7 @@ func (x *ImportKeystoresResponse) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use ImportKeystoresResponse.ProtoReflect.Descriptor instead.
|
||||
func (*ImportKeystoresResponse) Descriptor() ([]byte, []int) {
|
||||
return file_proto_validator_accounts_v2_web_api_proto_rawDescGZIP(), []int{15}
|
||||
return file_proto_validator_accounts_v2_web_api_proto_rawDescGZIP(), []int{16}
|
||||
}
|
||||
|
||||
func (x *ImportKeystoresResponse) GetImportedPublicKeys() [][]byte {
|
||||
@@ -1078,7 +1133,7 @@ type HasUsedWebResponse struct {
|
||||
func (x *HasUsedWebResponse) Reset() {
|
||||
*x = HasUsedWebResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_proto_validator_accounts_v2_web_api_proto_msgTypes[16]
|
||||
mi := &file_proto_validator_accounts_v2_web_api_proto_msgTypes[17]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
@@ -1091,7 +1146,7 @@ func (x *HasUsedWebResponse) String() string {
|
||||
func (*HasUsedWebResponse) ProtoMessage() {}
|
||||
|
||||
func (x *HasUsedWebResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_validator_accounts_v2_web_api_proto_msgTypes[16]
|
||||
mi := &file_proto_validator_accounts_v2_web_api_proto_msgTypes[17]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@@ -1104,7 +1159,7 @@ func (x *HasUsedWebResponse) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use HasUsedWebResponse.ProtoReflect.Descriptor instead.
|
||||
func (*HasUsedWebResponse) Descriptor() ([]byte, []int) {
|
||||
return file_proto_validator_accounts_v2_web_api_proto_rawDescGZIP(), []int{16}
|
||||
return file_proto_validator_accounts_v2_web_api_proto_rawDescGZIP(), []int{17}
|
||||
}
|
||||
|
||||
func (x *HasUsedWebResponse) GetHasSignedUp() bool {
|
||||
@@ -1249,140 +1304,158 @@ var file_proto_validator_accounts_v2_web_api_proto_rawDesc = []byte{
|
||||
0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65,
|
||||
0x73, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x16, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69,
|
||||
0x74, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73,
|
||||
0x22, 0x93, 0x01, 0x0a, 0x15, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77,
|
||||
0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x75,
|
||||
0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x61, 0x73,
|
||||
0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72,
|
||||
0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72,
|
||||
0x64, 0x12, 0x33, 0x0a, 0x15, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x63, 0x6f,
|
||||
0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x14, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72,
|
||||
0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x38, 0x0a, 0x11, 0x48, 0x61, 0x73, 0x57, 0x61, 0x6c,
|
||||
0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x77,
|
||||
0x61, 0x6c, 0x6c, 0x65, 0x74, 0x5f, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x08, 0x52, 0x0c, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x45, 0x78, 0x69, 0x73, 0x74, 0x73,
|
||||
0x22, 0x76, 0x0a, 0x16, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f,
|
||||
0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x12, 0x6b, 0x65,
|
||||
0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64,
|
||||
0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x11, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65,
|
||||
0x73, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x12, 0x2d, 0x0a, 0x12, 0x6b, 0x65, 0x79,
|
||||
0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18,
|
||||
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73,
|
||||
0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x4b, 0x0a, 0x17, 0x49, 0x6d, 0x70, 0x6f,
|
||||
0x72, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x14, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f,
|
||||
0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28,
|
||||
0x0c, 0x52, 0x12, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x50, 0x75, 0x62, 0x6c, 0x69,
|
||||
0x63, 0x4b, 0x65, 0x79, 0x73, 0x22, 0x57, 0x0a, 0x12, 0x48, 0x61, 0x73, 0x55, 0x73, 0x65, 0x64,
|
||||
0x57, 0x65, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x68,
|
||||
0x61, 0x73, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x75, 0x70, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x08, 0x52, 0x0b, 0x68, 0x61, 0x73, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x55, 0x70, 0x12,
|
||||
0x1d, 0x0a, 0x0a, 0x68, 0x61, 0x73, 0x5f, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x08, 0x52, 0x09, 0x68, 0x61, 0x73, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2a, 0x37,
|
||||
0x0a, 0x0e, 0x4b, 0x65, 0x79, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x4b, 0x69, 0x6e, 0x64,
|
||||
0x12, 0x0b, 0x0a, 0x07, 0x44, 0x45, 0x52, 0x49, 0x56, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0c, 0x0a,
|
||||
0x08, 0x49, 0x4d, 0x50, 0x4f, 0x52, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x52,
|
||||
0x45, 0x4d, 0x4f, 0x54, 0x45, 0x10, 0x02, 0x32, 0xe9, 0x04, 0x0a, 0x06, 0x57, 0x61, 0x6c, 0x6c,
|
||||
0x65, 0x74, 0x12, 0xa1, 0x01, 0x0a, 0x0c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x61, 0x6c,
|
||||
0x6c, 0x65, 0x74, 0x12, 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x76,
|
||||
0x22, 0x80, 0x01, 0x0a, 0x14, 0x4c, 0x6f, 0x67, 0x73, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e,
|
||||
0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x17, 0x76, 0x61, 0x6c,
|
||||
0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x6c, 0x6f, 0x67, 0x73, 0x5f, 0x65, 0x6e, 0x64, 0x70,
|
||||
0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x76, 0x61, 0x6c, 0x69,
|
||||
0x64, 0x61, 0x74, 0x6f, 0x72, 0x4c, 0x6f, 0x67, 0x73, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e,
|
||||
0x74, 0x12, 0x30, 0x0a, 0x14, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x6c, 0x6f, 0x67, 0x73,
|
||||
0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x12, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x4c, 0x6f, 0x67, 0x73, 0x45, 0x6e, 0x64, 0x70, 0x6f,
|
||||
0x69, 0x6e, 0x74, 0x22, 0x93, 0x01, 0x0a, 0x15, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61,
|
||||
0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a,
|
||||
0x10, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72,
|
||||
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74,
|
||||
0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73,
|
||||
0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73,
|
||||
0x77, 0x6f, 0x72, 0x64, 0x12, 0x33, 0x0a, 0x15, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64,
|
||||
0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x14, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x43, 0x6f, 0x6e,
|
||||
0x66, 0x69, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x38, 0x0a, 0x11, 0x48, 0x61, 0x73,
|
||||
0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23,
|
||||
0x0a, 0x0d, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x5f, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x45, 0x78, 0x69,
|
||||
0x73, 0x74, 0x73, 0x22, 0x76, 0x0a, 0x16, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x4b, 0x65, 0x79,
|
||||
0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2d, 0x0a,
|
||||
0x12, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6f, 0x72,
|
||||
0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x11, 0x6b, 0x65, 0x79, 0x73, 0x74,
|
||||
0x6f, 0x72, 0x65, 0x73, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x12, 0x2d, 0x0a, 0x12,
|
||||
0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f,
|
||||
0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f,
|
||||
0x72, 0x65, 0x73, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x4b, 0x0a, 0x17, 0x49,
|
||||
0x6d, 0x70, 0x6f, 0x72, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x52, 0x65,
|
||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x14, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74,
|
||||
0x65, 0x64, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01,
|
||||
0x20, 0x03, 0x28, 0x0c, 0x52, 0x12, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x50, 0x75,
|
||||
0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x22, 0x57, 0x0a, 0x12, 0x48, 0x61, 0x73, 0x55,
|
||||
0x73, 0x65, 0x64, 0x57, 0x65, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x22,
|
||||
0x0a, 0x0d, 0x68, 0x61, 0x73, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x75, 0x70, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x68, 0x61, 0x73, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64,
|
||||
0x55, 0x70, 0x12, 0x1d, 0x0a, 0x0a, 0x68, 0x61, 0x73, 0x5f, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x68, 0x61, 0x73, 0x57, 0x61, 0x6c, 0x6c, 0x65,
|
||||
0x74, 0x2a, 0x37, 0x0a, 0x0e, 0x4b, 0x65, 0x79, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x4b,
|
||||
0x69, 0x6e, 0x64, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x45, 0x52, 0x49, 0x56, 0x45, 0x44, 0x10, 0x00,
|
||||
0x12, 0x0c, 0x0a, 0x08, 0x49, 0x4d, 0x50, 0x4f, 0x52, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0a,
|
||||
0x0a, 0x06, 0x52, 0x45, 0x4d, 0x4f, 0x54, 0x45, 0x10, 0x02, 0x32, 0xe9, 0x04, 0x0a, 0x06, 0x57,
|
||||
0x61, 0x6c, 0x6c, 0x65, 0x74, 0x12, 0xa1, 0x01, 0x0a, 0x0c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65,
|
||||
0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x12, 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75,
|
||||
0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x61, 0x63, 0x63, 0x6f,
|
||||
0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x61,
|
||||
0x6c, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x65, 0x74,
|
||||
0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72,
|
||||
0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x72, 0x65,
|
||||
0x61, 0x74, 0x65, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x22, 0x1b, 0x2f, 0x76, 0x32, 0x2f, 0x76,
|
||||
0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2f,
|
||||
0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x3a, 0x01, 0x2a, 0x12, 0x74, 0x0a, 0x0c, 0x57, 0x61, 0x6c,
|
||||
0x6c, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
|
||||
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74,
|
||||
0x79, 0x1a, 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x76, 0x61, 0x6c,
|
||||
0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e,
|
||||
0x76, 0x32, 0x2e, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x12, 0x14, 0x2f, 0x76, 0x32, 0x2f, 0x76,
|
||||
0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x12,
|
||||
0x8d, 0x01, 0x0a, 0x10, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x4d, 0x6e, 0x65, 0x6d,
|
||||
0x6f, 0x6e, 0x69, 0x63, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x38, 0x2e, 0x65,
|
||||
0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f,
|
||||
0x72, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65,
|
||||
0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x4d, 0x6e, 0x65, 0x6d, 0x6f, 0x6e, 0x69, 0x63, 0x52, 0x65,
|
||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x27, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x21, 0x12, 0x1f,
|
||||
0x2f, 0x76, 0x32, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x6d, 0x6e,
|
||||
0x65, 0x6d, 0x6f, 0x6e, 0x69, 0x63, 0x2f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x12,
|
||||
0xb4, 0x01, 0x0a, 0x0f, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f,
|
||||
0x72, 0x65, 0x73, 0x12, 0x36, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x76,
|
||||
0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74,
|
||||
0x73, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x61, 0x6c, 0x6c, 0x65,
|
||||
0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72,
|
||||
0x73, 0x2e, 0x76, 0x32, 0x2e, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x74,
|
||||
0x6f, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x65, 0x74,
|
||||
0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72,
|
||||
0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x49, 0x6d, 0x70,
|
||||
0x6f, 0x72, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70,
|
||||
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x30, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2a, 0x22, 0x25, 0x2f, 0x76,
|
||||
0x32, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x77, 0x61, 0x6c, 0x6c,
|
||||
0x65, 0x74, 0x2f, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x2f, 0x69, 0x6d, 0x70,
|
||||
0x6f, 0x72, 0x74, 0x3a, 0x01, 0x2a, 0x32, 0xb0, 0x02, 0x0a, 0x08, 0x41, 0x63, 0x63, 0x6f, 0x75,
|
||||
0x6e, 0x74, 0x73, 0x12, 0x99, 0x01, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x63, 0x6f,
|
||||
0x75, 0x6e, 0x74, 0x73, 0x12, 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e,
|
||||
0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e,
|
||||
0x74, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e,
|
||||
0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x65, 0x74, 0x68, 0x65,
|
||||
0x72, 0x65, 0x75, 0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x61,
|
||||
0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41,
|
||||
0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
|
||||
0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x12, 0x16, 0x2f, 0x76, 0x32, 0x2f, 0x76, 0x61, 0x6c,
|
||||
0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x12,
|
||||
0x87, 0x01, 0x0a, 0x0e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f,
|
||||
0x72, 0x64, 0x12, 0x35, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x76, 0x61,
|
||||
0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73,
|
||||
0x2e, 0x76, 0x32, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f,
|
||||
0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
|
||||
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74,
|
||||
0x79, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x22, 0x1b, 0x2f, 0x76, 0x32, 0x2f, 0x76,
|
||||
0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72,
|
||||
0x64, 0x2f, 0x65, 0x64, 0x69, 0x74, 0x3a, 0x01, 0x2a, 0x32, 0xb2, 0x02, 0x0a, 0x06, 0x48, 0x65,
|
||||
0x61, 0x6c, 0x74, 0x68, 0x12, 0x97, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x42, 0x65, 0x61, 0x63,
|
||||
0x6f, 0x6e, 0x4e, 0x6f, 0x64, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
|
||||
0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x36, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72,
|
||||
0x65, 0x75, 0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x61, 0x63,
|
||||
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65,
|
||||
0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26,
|
||||
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x22, 0x1b, 0x2f, 0x76, 0x32, 0x2f, 0x76, 0x61, 0x6c, 0x69,
|
||||
0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2f, 0x63, 0x72, 0x65,
|
||||
0x61, 0x74, 0x65, 0x3a, 0x01, 0x2a, 0x12, 0x74, 0x0a, 0x0c, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74,
|
||||
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x2e,
|
||||
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x43, 0x6f,
|
||||
0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||
0x22, 0x2c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x26, 0x12, 0x24, 0x2f, 0x76, 0x32, 0x2f, 0x76, 0x61,
|
||||
0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x2f, 0x6e,
|
||||
0x6f, 0x64, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x8d,
|
||||
0x01, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69,
|
||||
0x6e, 0x74, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x34, 0x2e, 0x65, 0x74,
|
||||
0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72,
|
||||
0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x4c, 0x6f, 0x67,
|
||||
0x73, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x12, 0x23, 0x2f, 0x76, 0x32, 0x2f, 0x76,
|
||||
0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x2f,
|
||||
0x6c, 0x6f, 0x67, 0x73, 0x2f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x32, 0xea,
|
||||
0x03, 0x0a, 0x04, 0x41, 0x75, 0x74, 0x68, 0x12, 0x7b, 0x0a, 0x0a, 0x48, 0x61, 0x73, 0x55, 0x73,
|
||||
0x65, 0x64, 0x57, 0x65, 0x62, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x32, 0x2e,
|
||||
0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74,
|
||||
0x6f, 0x72, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x48,
|
||||
0x61, 0x73, 0x55, 0x73, 0x65, 0x64, 0x57, 0x65, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x12, 0x19, 0x2f, 0x76, 0x32, 0x2f, 0x76,
|
||||
0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c,
|
||||
0x69, 0x7a, 0x65, 0x64, 0x12, 0x82, 0x01, 0x0a, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x2b,
|
||||
0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61,
|
||||
0x74, 0x6f, 0x72, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x2e,
|
||||
0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c,
|
||||
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x12, 0x14, 0x2f, 0x76, 0x32, 0x2f, 0x76, 0x61, 0x6c, 0x69,
|
||||
0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x12, 0x8d, 0x01, 0x0a,
|
||||
0x10, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x4d, 0x6e, 0x65, 0x6d, 0x6f, 0x6e, 0x69,
|
||||
0x63, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x38, 0x2e, 0x65, 0x74, 0x68, 0x65,
|
||||
0x72, 0x65, 0x75, 0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x61,
|
||||
0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72,
|
||||
0x61, 0x74, 0x65, 0x4d, 0x6e, 0x65, 0x6d, 0x6f, 0x6e, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x22, 0x27, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x21, 0x12, 0x1f, 0x2f, 0x76, 0x32,
|
||||
0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x6d, 0x6e, 0x65, 0x6d, 0x6f,
|
||||
0x6e, 0x69, 0x63, 0x2f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x12, 0xb4, 0x01, 0x0a,
|
||||
0x0f, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73,
|
||||
0x12, 0x36, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69,
|
||||
0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76,
|
||||
0x32, 0x2e, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65,
|
||||
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72,
|
||||
0x65, 0x75, 0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x61, 0x63,
|
||||
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74,
|
||||
0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x22, 0x30, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2a, 0x22, 0x25, 0x2f, 0x76, 0x32, 0x2f, 0x76,
|
||||
0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2f,
|
||||
0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x2f, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74,
|
||||
0x3a, 0x01, 0x2a, 0x32, 0xb0, 0x02, 0x0a, 0x08, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73,
|
||||
0x12, 0x99, 0x01, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74,
|
||||
0x73, 0x12, 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x76, 0x61, 0x6c,
|
||||
0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e,
|
||||
0x76, 0x32, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75,
|
||||
0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x61, 0x63, 0x63, 0x6f,
|
||||
0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x63, 0x6f,
|
||||
0x75, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3,
|
||||
0xe4, 0x93, 0x02, 0x18, 0x12, 0x16, 0x2f, 0x76, 0x32, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61,
|
||||
0x74, 0x6f, 0x72, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x12, 0x87, 0x01, 0x0a,
|
||||
0x0e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12,
|
||||
0x35, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64,
|
||||
0x61, 0x74, 0x6f, 0x72, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32,
|
||||
0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x26,
|
||||
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x22, 0x1b, 0x2f, 0x76, 0x32, 0x2f, 0x76, 0x61, 0x6c, 0x69,
|
||||
0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x2f, 0x65,
|
||||
0x64, 0x69, 0x74, 0x3a, 0x01, 0x2a, 0x32, 0xa2, 0x01, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x6c, 0x74,
|
||||
0x68, 0x12, 0x97, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x4e,
|
||||
0x6f, 0x64, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x2e,
|
||||
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
|
||||
0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x36, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d,
|
||||
0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75,
|
||||
0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65,
|
||||
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2c, 0x82,
|
||||
0xd3, 0xe4, 0x93, 0x02, 0x26, 0x12, 0x24, 0x2f, 0x76, 0x32, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64,
|
||||
0x61, 0x74, 0x6f, 0x72, 0x2f, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x2f, 0x6e, 0x6f, 0x64, 0x65,
|
||||
0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x32, 0xea, 0x03, 0x0a, 0x04,
|
||||
0x41, 0x75, 0x74, 0x68, 0x12, 0x7b, 0x0a, 0x0a, 0x48, 0x61, 0x73, 0x55, 0x73, 0x65, 0x64, 0x57,
|
||||
0x65, 0x62, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x32, 0x2e, 0x65, 0x74, 0x68,
|
||||
0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e,
|
||||
0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x48, 0x61, 0x73, 0x55,
|
||||
0x73, 0x65, 0x64, 0x57, 0x65, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21,
|
||||
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x12, 0x19, 0x2f, 0x76, 0x32, 0x2f, 0x76, 0x61, 0x6c, 0x69,
|
||||
0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65,
|
||||
0x64, 0x12, 0x82, 0x01, 0x0a, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x2b, 0x2e, 0x65, 0x74,
|
||||
0x41, 0x75, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x65, 0x74,
|
||||
0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72,
|
||||
0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x41, 0x75, 0x74,
|
||||
0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72,
|
||||
0x65, 0x75, 0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x61, 0x63,
|
||||
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x52, 0x65,
|
||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x22, 0x13,
|
||||
0x2f, 0x76, 0x32, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x6c, 0x6f,
|
||||
0x67, 0x69, 0x6e, 0x3a, 0x01, 0x2a, 0x12, 0x84, 0x01, 0x0a, 0x06, 0x53, 0x69, 0x67, 0x6e, 0x75,
|
||||
0x70, 0x12, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x76, 0x61, 0x6c,
|
||||
0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02,
|
||||
0x18, 0x22, 0x13, 0x2f, 0x76, 0x32, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72,
|
||||
0x2f, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x3a, 0x01, 0x2a, 0x12, 0x84, 0x01, 0x0a, 0x06, 0x53, 0x69,
|
||||
0x67, 0x6e, 0x75, 0x70, 0x12, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e,
|
||||
0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e,
|
||||
0x74, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||
0x74, 0x1a, 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x76, 0x61, 0x6c,
|
||||
0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e,
|
||||
0x76, 0x32, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c,
|
||||
0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61,
|
||||
0x74, 0x6f, 0x72, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x2e,
|
||||
0x41, 0x75, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3,
|
||||
0xe4, 0x93, 0x02, 0x19, 0x22, 0x14, 0x2f, 0x76, 0x32, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61,
|
||||
0x74, 0x6f, 0x72, 0x2f, 0x73, 0x69, 0x67, 0x6e, 0x75, 0x70, 0x3a, 0x01, 0x2a, 0x12, 0x59, 0x0a,
|
||||
0x06, 0x4c, 0x6f, 0x67, 0x6f, 0x75, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
|
||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a,
|
||||
0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
|
||||
0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x22,
|
||||
0x14, 0x2f, 0x76, 0x32, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x6c,
|
||||
0x6f, 0x67, 0x6f, 0x75, 0x74, 0x3a, 0x01, 0x2a, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x76, 0x32, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
|
||||
0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x22, 0x14, 0x2f, 0x76, 0x32, 0x2f, 0x76, 0x61, 0x6c,
|
||||
0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x73, 0x69, 0x67, 0x6e, 0x75, 0x70, 0x3a, 0x01, 0x2a,
|
||||
0x12, 0x59, 0x0a, 0x06, 0x4c, 0x6f, 0x67, 0x6f, 0x75, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f,
|
||||
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70,
|
||||
0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93,
|
||||
0x02, 0x19, 0x22, 0x14, 0x2f, 0x76, 0x32, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f,
|
||||
0x72, 0x2f, 0x6c, 0x6f, 0x67, 0x6f, 0x75, 0x74, 0x3a, 0x01, 0x2a, 0x62, 0x06, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -1398,7 +1471,7 @@ func file_proto_validator_accounts_v2_web_api_proto_rawDescGZIP() []byte {
|
||||
}
|
||||
|
||||
var file_proto_validator_accounts_v2_web_api_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
||||
var file_proto_validator_accounts_v2_web_api_proto_msgTypes = make([]protoimpl.MessageInfo, 17)
|
||||
var file_proto_validator_accounts_v2_web_api_proto_msgTypes = make([]protoimpl.MessageInfo, 18)
|
||||
var file_proto_validator_accounts_v2_web_api_proto_goTypes = []interface{}{
|
||||
(KeymanagerKind)(0), // 0: ethereum.validator.accounts.v2.KeymanagerKind
|
||||
(*CreateWalletRequest)(nil), // 1: ethereum.validator.accounts.v2.CreateWalletRequest
|
||||
@@ -1413,12 +1486,13 @@ var file_proto_validator_accounts_v2_web_api_proto_goTypes = []interface{}{
|
||||
(*AuthRequest)(nil), // 10: ethereum.validator.accounts.v2.AuthRequest
|
||||
(*AuthResponse)(nil), // 11: ethereum.validator.accounts.v2.AuthResponse
|
||||
(*NodeConnectionResponse)(nil), // 12: ethereum.validator.accounts.v2.NodeConnectionResponse
|
||||
(*ChangePasswordRequest)(nil), // 13: ethereum.validator.accounts.v2.ChangePasswordRequest
|
||||
(*HasWalletResponse)(nil), // 14: ethereum.validator.accounts.v2.HasWalletResponse
|
||||
(*ImportKeystoresRequest)(nil), // 15: ethereum.validator.accounts.v2.ImportKeystoresRequest
|
||||
(*ImportKeystoresResponse)(nil), // 16: ethereum.validator.accounts.v2.ImportKeystoresResponse
|
||||
(*HasUsedWebResponse)(nil), // 17: ethereum.validator.accounts.v2.HasUsedWebResponse
|
||||
(*empty.Empty)(nil), // 18: google.protobuf.Empty
|
||||
(*LogsEndpointResponse)(nil), // 13: ethereum.validator.accounts.v2.LogsEndpointResponse
|
||||
(*ChangePasswordRequest)(nil), // 14: ethereum.validator.accounts.v2.ChangePasswordRequest
|
||||
(*HasWalletResponse)(nil), // 15: ethereum.validator.accounts.v2.HasWalletResponse
|
||||
(*ImportKeystoresRequest)(nil), // 16: ethereum.validator.accounts.v2.ImportKeystoresRequest
|
||||
(*ImportKeystoresResponse)(nil), // 17: ethereum.validator.accounts.v2.ImportKeystoresResponse
|
||||
(*HasUsedWebResponse)(nil), // 18: ethereum.validator.accounts.v2.HasUsedWebResponse
|
||||
(*empty.Empty)(nil), // 19: google.protobuf.Empty
|
||||
}
|
||||
var file_proto_validator_accounts_v2_web_api_proto_depIdxs = []int32{
|
||||
0, // 0: ethereum.validator.accounts.v2.CreateWalletRequest.keymanager:type_name -> ethereum.validator.accounts.v2.KeymanagerKind
|
||||
@@ -1426,29 +1500,31 @@ var file_proto_validator_accounts_v2_web_api_proto_depIdxs = []int32{
|
||||
0, // 2: ethereum.validator.accounts.v2.WalletResponse.keymanager_kind:type_name -> ethereum.validator.accounts.v2.KeymanagerKind
|
||||
8, // 3: ethereum.validator.accounts.v2.ListAccountsResponse.accounts:type_name -> ethereum.validator.accounts.v2.Account
|
||||
1, // 4: ethereum.validator.accounts.v2.Wallet.CreateWallet:input_type -> ethereum.validator.accounts.v2.CreateWalletRequest
|
||||
18, // 5: ethereum.validator.accounts.v2.Wallet.WalletConfig:input_type -> google.protobuf.Empty
|
||||
18, // 6: ethereum.validator.accounts.v2.Wallet.GenerateMnemonic:input_type -> google.protobuf.Empty
|
||||
15, // 7: ethereum.validator.accounts.v2.Wallet.ImportKeystores:input_type -> ethereum.validator.accounts.v2.ImportKeystoresRequest
|
||||
19, // 5: ethereum.validator.accounts.v2.Wallet.WalletConfig:input_type -> google.protobuf.Empty
|
||||
19, // 6: ethereum.validator.accounts.v2.Wallet.GenerateMnemonic:input_type -> google.protobuf.Empty
|
||||
16, // 7: ethereum.validator.accounts.v2.Wallet.ImportKeystores:input_type -> ethereum.validator.accounts.v2.ImportKeystoresRequest
|
||||
6, // 8: ethereum.validator.accounts.v2.Accounts.ListAccounts:input_type -> ethereum.validator.accounts.v2.ListAccountsRequest
|
||||
13, // 9: ethereum.validator.accounts.v2.Accounts.ChangePassword:input_type -> ethereum.validator.accounts.v2.ChangePasswordRequest
|
||||
18, // 10: ethereum.validator.accounts.v2.Health.GetBeaconNodeConnection:input_type -> google.protobuf.Empty
|
||||
18, // 11: ethereum.validator.accounts.v2.Auth.HasUsedWeb:input_type -> google.protobuf.Empty
|
||||
10, // 12: ethereum.validator.accounts.v2.Auth.Login:input_type -> ethereum.validator.accounts.v2.AuthRequest
|
||||
10, // 13: ethereum.validator.accounts.v2.Auth.Signup:input_type -> ethereum.validator.accounts.v2.AuthRequest
|
||||
18, // 14: ethereum.validator.accounts.v2.Auth.Logout:input_type -> google.protobuf.Empty
|
||||
2, // 15: ethereum.validator.accounts.v2.Wallet.CreateWallet:output_type -> ethereum.validator.accounts.v2.CreateWalletResponse
|
||||
5, // 16: ethereum.validator.accounts.v2.Wallet.WalletConfig:output_type -> ethereum.validator.accounts.v2.WalletResponse
|
||||
4, // 17: ethereum.validator.accounts.v2.Wallet.GenerateMnemonic:output_type -> ethereum.validator.accounts.v2.GenerateMnemonicResponse
|
||||
16, // 18: ethereum.validator.accounts.v2.Wallet.ImportKeystores:output_type -> ethereum.validator.accounts.v2.ImportKeystoresResponse
|
||||
7, // 19: ethereum.validator.accounts.v2.Accounts.ListAccounts:output_type -> ethereum.validator.accounts.v2.ListAccountsResponse
|
||||
18, // 20: ethereum.validator.accounts.v2.Accounts.ChangePassword:output_type -> google.protobuf.Empty
|
||||
12, // 21: ethereum.validator.accounts.v2.Health.GetBeaconNodeConnection:output_type -> ethereum.validator.accounts.v2.NodeConnectionResponse
|
||||
17, // 22: ethereum.validator.accounts.v2.Auth.HasUsedWeb:output_type -> ethereum.validator.accounts.v2.HasUsedWebResponse
|
||||
11, // 23: ethereum.validator.accounts.v2.Auth.Login:output_type -> ethereum.validator.accounts.v2.AuthResponse
|
||||
11, // 24: ethereum.validator.accounts.v2.Auth.Signup:output_type -> ethereum.validator.accounts.v2.AuthResponse
|
||||
18, // 25: ethereum.validator.accounts.v2.Auth.Logout:output_type -> google.protobuf.Empty
|
||||
15, // [15:26] is the sub-list for method output_type
|
||||
4, // [4:15] is the sub-list for method input_type
|
||||
14, // 9: ethereum.validator.accounts.v2.Accounts.ChangePassword:input_type -> ethereum.validator.accounts.v2.ChangePasswordRequest
|
||||
19, // 10: ethereum.validator.accounts.v2.Health.GetBeaconNodeConnection:input_type -> google.protobuf.Empty
|
||||
19, // 11: ethereum.validator.accounts.v2.Health.GetLogsEndpoints:input_type -> google.protobuf.Empty
|
||||
19, // 12: ethereum.validator.accounts.v2.Auth.HasUsedWeb:input_type -> google.protobuf.Empty
|
||||
10, // 13: ethereum.validator.accounts.v2.Auth.Login:input_type -> ethereum.validator.accounts.v2.AuthRequest
|
||||
10, // 14: ethereum.validator.accounts.v2.Auth.Signup:input_type -> ethereum.validator.accounts.v2.AuthRequest
|
||||
19, // 15: ethereum.validator.accounts.v2.Auth.Logout:input_type -> google.protobuf.Empty
|
||||
2, // 16: ethereum.validator.accounts.v2.Wallet.CreateWallet:output_type -> ethereum.validator.accounts.v2.CreateWalletResponse
|
||||
5, // 17: ethereum.validator.accounts.v2.Wallet.WalletConfig:output_type -> ethereum.validator.accounts.v2.WalletResponse
|
||||
4, // 18: ethereum.validator.accounts.v2.Wallet.GenerateMnemonic:output_type -> ethereum.validator.accounts.v2.GenerateMnemonicResponse
|
||||
17, // 19: ethereum.validator.accounts.v2.Wallet.ImportKeystores:output_type -> ethereum.validator.accounts.v2.ImportKeystoresResponse
|
||||
7, // 20: ethereum.validator.accounts.v2.Accounts.ListAccounts:output_type -> ethereum.validator.accounts.v2.ListAccountsResponse
|
||||
19, // 21: ethereum.validator.accounts.v2.Accounts.ChangePassword:output_type -> google.protobuf.Empty
|
||||
12, // 22: ethereum.validator.accounts.v2.Health.GetBeaconNodeConnection:output_type -> ethereum.validator.accounts.v2.NodeConnectionResponse
|
||||
13, // 23: ethereum.validator.accounts.v2.Health.GetLogsEndpoints:output_type -> ethereum.validator.accounts.v2.LogsEndpointResponse
|
||||
18, // 24: ethereum.validator.accounts.v2.Auth.HasUsedWeb:output_type -> ethereum.validator.accounts.v2.HasUsedWebResponse
|
||||
11, // 25: ethereum.validator.accounts.v2.Auth.Login:output_type -> ethereum.validator.accounts.v2.AuthResponse
|
||||
11, // 26: ethereum.validator.accounts.v2.Auth.Signup:output_type -> ethereum.validator.accounts.v2.AuthResponse
|
||||
19, // 27: ethereum.validator.accounts.v2.Auth.Logout:output_type -> google.protobuf.Empty
|
||||
16, // [16:28] is the sub-list for method output_type
|
||||
4, // [4:16] is the sub-list for method input_type
|
||||
4, // [4:4] is the sub-list for extension type_name
|
||||
4, // [4:4] is the sub-list for extension extendee
|
||||
0, // [0:4] is the sub-list for field type_name
|
||||
@@ -1605,7 +1681,7 @@ func file_proto_validator_accounts_v2_web_api_proto_init() {
|
||||
}
|
||||
}
|
||||
file_proto_validator_accounts_v2_web_api_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ChangePasswordRequest); i {
|
||||
switch v := v.(*LogsEndpointResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
@@ -1617,7 +1693,7 @@ func file_proto_validator_accounts_v2_web_api_proto_init() {
|
||||
}
|
||||
}
|
||||
file_proto_validator_accounts_v2_web_api_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*HasWalletResponse); i {
|
||||
switch v := v.(*ChangePasswordRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
@@ -1629,7 +1705,7 @@ func file_proto_validator_accounts_v2_web_api_proto_init() {
|
||||
}
|
||||
}
|
||||
file_proto_validator_accounts_v2_web_api_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ImportKeystoresRequest); i {
|
||||
switch v := v.(*HasWalletResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
@@ -1641,7 +1717,7 @@ func file_proto_validator_accounts_v2_web_api_proto_init() {
|
||||
}
|
||||
}
|
||||
file_proto_validator_accounts_v2_web_api_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ImportKeystoresResponse); i {
|
||||
switch v := v.(*ImportKeystoresRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
@@ -1653,6 +1729,18 @@ func file_proto_validator_accounts_v2_web_api_proto_init() {
|
||||
}
|
||||
}
|
||||
file_proto_validator_accounts_v2_web_api_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ImportKeystoresResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_proto_validator_accounts_v2_web_api_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*HasUsedWebResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
@@ -1671,7 +1759,7 @@ func file_proto_validator_accounts_v2_web_api_proto_init() {
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_proto_validator_accounts_v2_web_api_proto_rawDesc,
|
||||
NumEnums: 1,
|
||||
NumMessages: 17,
|
||||
NumMessages: 18,
|
||||
NumExtensions: 0,
|
||||
NumServices: 4,
|
||||
},
|
||||
@@ -1987,6 +2075,7 @@ var _Accounts_serviceDesc = grpc.ServiceDesc{
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||
type HealthClient interface {
|
||||
GetBeaconNodeConnection(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*NodeConnectionResponse, error)
|
||||
GetLogsEndpoints(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*LogsEndpointResponse, error)
|
||||
}
|
||||
|
||||
type healthClient struct {
|
||||
@@ -2006,9 +2095,19 @@ func (c *healthClient) GetBeaconNodeConnection(ctx context.Context, in *empty.Em
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *healthClient) GetLogsEndpoints(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*LogsEndpointResponse, error) {
|
||||
out := new(LogsEndpointResponse)
|
||||
err := c.cc.Invoke(ctx, "/ethereum.validator.accounts.v2.Health/GetLogsEndpoints", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// HealthServer is the server API for Health service.
|
||||
type HealthServer interface {
|
||||
GetBeaconNodeConnection(context.Context, *empty.Empty) (*NodeConnectionResponse, error)
|
||||
GetLogsEndpoints(context.Context, *empty.Empty) (*LogsEndpointResponse, error)
|
||||
}
|
||||
|
||||
// UnimplementedHealthServer can be embedded to have forward compatible implementations.
|
||||
@@ -2018,6 +2117,9 @@ type UnimplementedHealthServer struct {
|
||||
func (*UnimplementedHealthServer) GetBeaconNodeConnection(context.Context, *empty.Empty) (*NodeConnectionResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetBeaconNodeConnection not implemented")
|
||||
}
|
||||
func (*UnimplementedHealthServer) GetLogsEndpoints(context.Context, *empty.Empty) (*LogsEndpointResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetLogsEndpoints not implemented")
|
||||
}
|
||||
|
||||
func RegisterHealthServer(s *grpc.Server, srv HealthServer) {
|
||||
s.RegisterService(&_Health_serviceDesc, srv)
|
||||
@@ -2041,6 +2143,24 @@ func _Health_GetBeaconNodeConnection_Handler(srv interface{}, ctx context.Contex
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Health_GetLogsEndpoints_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(empty.Empty)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(HealthServer).GetLogsEndpoints(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/ethereum.validator.accounts.v2.Health/GetLogsEndpoints",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(HealthServer).GetLogsEndpoints(ctx, req.(*empty.Empty))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _Health_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "ethereum.validator.accounts.v2.Health",
|
||||
HandlerType: (*HealthServer)(nil),
|
||||
@@ -2049,6 +2169,10 @@ var _Health_serviceDesc = grpc.ServiceDesc{
|
||||
MethodName: "GetBeaconNodeConnection",
|
||||
Handler: _Health_GetBeaconNodeConnection_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetLogsEndpoints",
|
||||
Handler: _Health_GetLogsEndpoints_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "proto/validator/accounts/v2/web_api.proto",
|
||||
|
||||
@@ -224,6 +224,24 @@ func local_request_Health_GetBeaconNodeConnection_0(ctx context.Context, marshal
|
||||
|
||||
}
|
||||
|
||||
func request_Health_GetLogsEndpoints_0(ctx context.Context, marshaler runtime.Marshaler, client HealthClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq empty.Empty
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
msg, err := client.GetLogsEndpoints(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_Health_GetLogsEndpoints_0(ctx context.Context, marshaler runtime.Marshaler, server HealthServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq empty.Empty
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
msg, err := server.GetLogsEndpoints(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_Auth_HasUsedWeb_0(ctx context.Context, marshaler runtime.Marshaler, client AuthClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq empty.Empty
|
||||
var metadata runtime.ServerMetadata
|
||||
@@ -505,6 +523,26 @@ func RegisterHealthHandlerServer(ctx context.Context, mux *runtime.ServeMux, ser
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_Health_GetLogsEndpoints_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_Health_GetLogsEndpoints_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Health_GetLogsEndpoints_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -888,15 +926,39 @@ func RegisterHealthHandlerClient(ctx context.Context, mux *runtime.ServeMux, cli
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_Health_GetLogsEndpoints_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_Health_GetLogsEndpoints_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Health_GetLogsEndpoints_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
pattern_Health_GetBeaconNodeConnection_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v2", "validator", "health", "node_connection"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_Health_GetLogsEndpoints_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"v2", "validator", "health", "logs", "endpoints"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
)
|
||||
|
||||
var (
|
||||
forward_Health_GetBeaconNodeConnection_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Health_GetLogsEndpoints_0 = runtime.ForwardResponseMessage
|
||||
)
|
||||
|
||||
// RegisterAuthHandlerFromEndpoint is same as RegisterAuthHandler but
|
||||
|
||||
@@ -13,10 +13,10 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
|
||||
var maxKeys = int64(100000)
|
||||
var maxKeys = int64(1000000)
|
||||
var pubkeyCache, _ = ristretto.NewCache(&ristretto.Config{
|
||||
NumCounters: maxKeys,
|
||||
MaxCost: 1 << 22, // ~4mb is cache max size
|
||||
MaxCost: 1 << 26, // ~64mb is cache max size
|
||||
BufferItems: 64,
|
||||
})
|
||||
|
||||
|
||||
@@ -36,18 +36,19 @@ type Flags struct {
|
||||
PyrmontTestnet bool // PyrmontTestnet defines the flag through which we can enable the node to run on the Pyrmont testnet.
|
||||
|
||||
// Feature related flags.
|
||||
WriteSSZStateTransitions bool // WriteSSZStateTransitions to tmp directory.
|
||||
SkipBLSVerify bool // Skips BLS verification across the runtime.
|
||||
EnableBlst bool // Enables new BLS library from supranational.
|
||||
PruneEpochBoundaryStates bool // PruneEpochBoundaryStates prunes the epoch boundary state before last finalized check point.
|
||||
EnableSnappyDBCompression bool // EnableSnappyDBCompression in the database.
|
||||
SlasherProtection bool // SlasherProtection protects validator fron sending over a slashable offense over the network using external slasher.
|
||||
EnableNoise bool // EnableNoise enables the beacon node to use NOISE instead of SECIO when performing a handshake with another peer.
|
||||
EnableEth1DataMajorityVote bool // EnableEth1DataMajorityVote uses the Voting With The Majority algorithm to vote for eth1data.
|
||||
EnablePeerScorer bool // EnablePeerScorer enables experimental peer scoring in p2p.
|
||||
EnablePruningDepositProofs bool // EnablePruningDepositProofs enables pruning deposit proofs which significantly reduces the size of a deposit
|
||||
EnableSyncBacktracking bool // EnableSyncBacktracking enables backtracking algorithm when searching for alternative forks during initial sync.
|
||||
EnableLargerGossipHistory bool // EnableLargerGossipHistory increases the gossip history we store in our caches.
|
||||
WriteSSZStateTransitions bool // WriteSSZStateTransitions to tmp directory.
|
||||
SkipBLSVerify bool // Skips BLS verification across the runtime.
|
||||
EnableBlst bool // Enables new BLS library from supranational.
|
||||
PruneEpochBoundaryStates bool // PruneEpochBoundaryStates prunes the epoch boundary state before last finalized check point.
|
||||
EnableSnappyDBCompression bool // EnableSnappyDBCompression in the database.
|
||||
SlasherProtection bool // SlasherProtection protects validator fron sending over a slashable offense over the network using external slasher.
|
||||
EnableNoise bool // EnableNoise enables the beacon node to use NOISE instead of SECIO when performing a handshake with another peer.
|
||||
EnableEth1DataMajorityVote bool // EnableEth1DataMajorityVote uses the Voting With The Majority algorithm to vote for eth1data.
|
||||
EnablePeerScorer bool // EnablePeerScorer enables experimental peer scoring in p2p.
|
||||
EnablePruningDepositProofs bool // EnablePruningDepositProofs enables pruning deposit proofs which significantly reduces the size of a deposit
|
||||
EnableSyncBacktracking bool // EnableSyncBacktracking enables backtracking algorithm when searching for alternative forks during initial sync.
|
||||
EnableLargerGossipHistory bool // EnableLargerGossipHistory increases the gossip history we store in our caches.
|
||||
WriteWalletPasswordOnWebOnboarding bool // WriteWalletPasswordOnWebOnboarding writes the password to disk after Prysm web signup.
|
||||
|
||||
// Logging related toggles.
|
||||
DisableGRPCConnectionLogs bool // Disables logging when a new grpc client has connected.
|
||||
@@ -206,6 +207,16 @@ func ConfigureValidator(ctx *cli.Context) {
|
||||
log.Warn("Enabled validator attestation and block slashing protection using an external slasher.")
|
||||
cfg.SlasherProtection = true
|
||||
}
|
||||
if ctx.Bool(writeWalletPasswordOnWebOnboarding.Name) {
|
||||
log.Warn("Enabled full web mode, wallet password will be written to disk at the wallet directory " +
|
||||
"upon completing web onboarding.")
|
||||
cfg.WriteWalletPasswordOnWebOnboarding = true
|
||||
}
|
||||
cfg.EnableBlst = true
|
||||
if ctx.Bool(disableBlst.Name) {
|
||||
log.Warn("Disabling new BLS library blst")
|
||||
cfg.EnableBlst = false
|
||||
}
|
||||
Init(cfg)
|
||||
}
|
||||
|
||||
|
||||
@@ -84,6 +84,11 @@ var (
|
||||
Name: "enable-larger-gossip-history",
|
||||
Usage: "Enables the node to store a larger amount of gossip messages in its cache.",
|
||||
}
|
||||
writeWalletPasswordOnWebOnboarding = &cli.BoolFlag{
|
||||
Name: "write-wallet-password-on-web-onboarding",
|
||||
Usage: "(Danger): Writes the wallet password to the wallet directory on completing Prysm web onboarding. " +
|
||||
"We recommend against this flag unless you are an advanced user.",
|
||||
}
|
||||
)
|
||||
|
||||
// devModeFlags holds list of flags that are set when development mode is on.
|
||||
@@ -94,6 +99,7 @@ var devModeFlags = []cli.Flag{
|
||||
|
||||
// ValidatorFlags contains a list of all the feature flags that apply to the validator client.
|
||||
var ValidatorFlags = append(deprecatedFlags, []cli.Flag{
|
||||
writeWalletPasswordOnWebOnboarding,
|
||||
enableExternalSlasherProtectionFlag,
|
||||
ToledoTestnet,
|
||||
PyrmontTestnet,
|
||||
|
||||
@@ -23,8 +23,5 @@ go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["stream_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//shared/testutil/require:go_default_library",
|
||||
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
|
||||
],
|
||||
deps = ["//shared/testutil/require:go_default_library"],
|
||||
)
|
||||
|
||||
@@ -3,7 +3,6 @@ package logutil
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
@@ -31,7 +30,7 @@ var (
|
||||
WriteBufferSize: 1024,
|
||||
CheckOrigin: func(r *http.Request) bool {
|
||||
// Only allow requests from localhost.
|
||||
return strings.Contains(r.Host, "localhost")
|
||||
return true
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
logTest "github.com/sirupsen/logrus/hooks/test"
|
||||
)
|
||||
|
||||
type fakeAddr int
|
||||
@@ -53,32 +52,6 @@ func (resp *testResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
||||
return fakeNetConn{strings.NewReader(""), resp.brw}, rw, nil
|
||||
}
|
||||
|
||||
func TestLogStreamServer_DisallowsNonLocalhostOrigin(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
ss := NewLogStreamServer()
|
||||
br := bufio.NewReader(strings.NewReader(""))
|
||||
buf := new(bytes.Buffer)
|
||||
bw := bufio.NewWriter(buf)
|
||||
rw := httptest.NewRecorder()
|
||||
resp := &testResponseWriter{
|
||||
brw: bufio.NewReadWriter(br, bw),
|
||||
ResponseWriter: rw,
|
||||
}
|
||||
req := &http.Request{
|
||||
Method: "GET",
|
||||
Host: "externalsource",
|
||||
Header: http.Header{
|
||||
"Upgrade": []string{"websocket"},
|
||||
"Connection": []string{"upgrade"},
|
||||
"Sec-Websocket-Key": []string{"dGhlIHNhbXBsZSBub25jZQ=="},
|
||||
"Sec-Websocket-Version": []string{"13"},
|
||||
},
|
||||
}
|
||||
ss.Handler(resp, req)
|
||||
require.NoError(t, resp.brw.Flush())
|
||||
require.LogsContain(t, hook, "origin not allowed")
|
||||
}
|
||||
|
||||
func TestLogStreamServer_BackfillsMessages(t *testing.T) {
|
||||
ss := NewLogStreamServer()
|
||||
msgs := [][]byte{
|
||||
|
||||
@@ -38,10 +38,19 @@ var mainnetNetworkConfig = &NetworkConfig{
|
||||
BootstrapNodes: []string{
|
||||
// Teku team's bootnode
|
||||
"enr:-KG4QOtcP9X1FbIMOe17QNMKqDxCpm14jcX5tiOE4_TyMrFqbmhPZHK_ZPG2Gxb1GE2xdtodOfx9-cgvNtxnRyHEmC0ghGV0aDKQ9aX9QgAAAAD__________4JpZIJ2NIJpcIQDE8KdiXNlY3AyNTZrMaEDhpehBDbZjM_L9ek699Y7vhUJ-eAdMyQW_Fil522Y0fODdGNwgiMog3VkcIIjKA",
|
||||
"enr:-KG4QDyytgmE4f7AnvW-ZaUOIi9i79qX4JwjRAiXBZCU65wOfBu-3Nb5I7b_Rmg3KCOcZM_C3y5pg7EBU5XGrcLTduQEhGV0aDKQ9aX9QgAAAAD__________4JpZIJ2NIJpcIQ2_DUbiXNlY3AyNTZrMaEDKnz_-ps3UUOfHWVYaskI5kWYO_vtYMGYCQRAR3gHDouDdGNwgiMog3VkcIIjKA",
|
||||
// Prylab team's bootnodes
|
||||
"enr:-Ku4QImhMc1z8yCiNJ1TyUxdcfNucje3BGwEHzodEZUan8PherEo4sF7pPHPSIB1NNuSg5fZy7qFsjmUKs2ea1Whi0EBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpD1pf1CAAAAAP__________gmlkgnY0gmlwhBLf22SJc2VjcDI1NmsxoQOVphkDqal4QzPMksc5wnpuC3gvSC8AfbFOnZY_On34wIN1ZHCCIyg",
|
||||
"enr:-Ku4QP2xDnEtUXIjzJ_DhlCRN9SN99RYQPJL92TMlSv7U5C1YnYLjwOQHgZIUXw6c-BvRg2Yc2QsZxxoS_pPRVe0yK8Bh2F0dG5ldHOIAAAAAAAAAACEZXRoMpD1pf1CAAAAAP__________gmlkgnY0gmlwhBLf22SJc2VjcDI1NmsxoQMeFF5GrS7UZpAH2Ly84aLK-TyvH-dRo0JM1i8yygH50YN1ZHCCJxA",
|
||||
"enr:-Ku4QPp9z1W4tAO8Ber_NQierYaOStqhDqQdOPY3bB3jDgkjcbk6YrEnVYIiCBbTxuar3CzS528d2iE7TdJsrL-dEKoBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpD1pf1CAAAAAP__________gmlkgnY0gmlwhBLf22SJc2VjcDI1NmsxoQMw5fqqkw2hHC4F5HZZDPsNmPdB1Gi8JPQK7pRc9XHh-oN1ZHCCKvg",
|
||||
// Lighthouse team's bootnodes
|
||||
"enr:-IS4QLkKqDMy_ExrpOEWa59NiClemOnor-krjp4qoeZwIw2QduPC-q7Kz4u1IOWf3DDbdxqQIgC4fejavBOuUPy-HE4BgmlkgnY0gmlwhCLzAHqJc2VjcDI1NmsxoQLQSJfEAHZApkm5edTCZ_4qps_1k_ub2CxHFxi-gr2JMIN1ZHCCIyg",
|
||||
"enr:-IS4QDAyibHCzYZmIYZCjXwU9BqpotWmv2BsFlIq1V31BwDDMJPFEbox1ijT5c2Ou3kvieOKejxuaCqIcjxBjJ_3j_cBgmlkgnY0gmlwhAMaHiCJc2VjcDI1NmsxoQJIdpj_foZ02MXz4It8xKD7yUHTBx7lVFn3oeRP21KRV4N1ZHCCIyg",
|
||||
// EF bootnodes
|
||||
"enr:-Ku4QHqVeJ8PPICcWk1vSn_XcSkjOkNiTg6Fmii5j6vUQgvzMc9L1goFnLKgXqBJspJjIsB91LTOleFmyWWrFVATGngBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpC1MD8qAAAAAP__________gmlkgnY0gmlwhAMRHkWJc2VjcDI1NmsxoQKLVXFOhp2uX6jeT0DvvDpPcU8FWMjQdR4wMuORMhpX24N1ZHCCIyg",
|
||||
"enr:-Ku4QG-2_Md3sZIAUebGYT6g0SMskIml77l6yR-M_JXc-UdNHCmHQeOiMLbylPejyJsdAPsTHJyjJB2sYGDLe0dn8uYBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpC1MD8qAAAAAP__________gmlkgnY0gmlwhBLY-NyJc2VjcDI1NmsxoQORcM6e19T1T9gi7jxEZjk_sjVLGFscUNqAY9obgZaxbIN1ZHCCIyg",
|
||||
"enr:-Ku4QPn5eVhcoF1opaFEvg1b6JNFD2rqVkHQ8HApOKK61OIcIXD127bKWgAtbwI7pnxx6cDyk_nI88TrZKQaGMZj0q0Bh2F0dG5ldHOIAAAAAAAAAACEZXRoMpC1MD8qAAAAAP__________gmlkgnY0gmlwhDayLMaJc2VjcDI1NmsxoQK2sBOLGcUb4AwuYzFuAVCaNHA-dy24UuEKkeFNgCVCsIN1ZHCCIyg",
|
||||
"enr:-Ku4QEWzdnVtXc2Q0ZVigfCGggOVB2Vc1ZCPEc6j21NIFLODSJbvNaef1g4PxhPwl_3kax86YPheFUSLXPRs98vvYsoBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpC1MD8qAAAAAP__________gmlkgnY0gmlwhDZBrP2Jc2VjcDI1NmsxoQM6jr8Rb1ktLEsVcKAPa08wCsKUmvoQ8khiOl_SLozf9IN1ZHCCIyg",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ func (s *SlotTicker) Done() {
|
||||
|
||||
// GetSlotTicker is the constructor for SlotTicker.
|
||||
func GetSlotTicker(genesisTime time.Time, secondsPerSlot uint64) *SlotTicker {
|
||||
if genesisTime.Unix() == 0 {
|
||||
if genesisTime.IsZero() {
|
||||
panic("zero genesis time")
|
||||
}
|
||||
ticker := &SlotTicker{
|
||||
|
||||
@@ -173,7 +173,6 @@ func prepareClients(cliCtx *cli.Context) (*ethpb.BeaconNodeValidatorClient, *eth
|
||||
dialOpts := client.ConstructDialOptions(
|
||||
cliCtx.Int(cmd.GrpcMaxCallRecvMsgSizeFlag.Name),
|
||||
cliCtx.String(flags.CertFlag.Name),
|
||||
strings.Split(cliCtx.String(flags.GrpcHeadersFlag.Name), ","),
|
||||
cliCtx.Uint(flags.GrpcRetriesFlag.Name),
|
||||
cliCtx.Duration(flags.GrpcRetryDelayFlag.Name),
|
||||
)
|
||||
|
||||
@@ -33,7 +33,9 @@ const (
|
||||
WalletPasswordPromptText = "Wallet password"
|
||||
// ConfirmPasswordPromptText for confirming a wallet password.
|
||||
ConfirmPasswordPromptText = "Confirm password"
|
||||
hashCost = 8
|
||||
// DefaultWalletPasswordFile used to store a wallet password with appropriate permissions
|
||||
// if a user signs up via the Prysm web UI via RPC.
|
||||
DefaultWalletPasswordFile = "walletpassword.txt"
|
||||
// CheckExistsErrMsg for when there is an error while checking for a wallet
|
||||
CheckExistsErrMsg = "could not check if wallet exists"
|
||||
// CheckValidityErrMsg for when there is an error while checking wallet validity
|
||||
|
||||
@@ -21,6 +21,7 @@ go_library(
|
||||
visibility = ["//validator:__subpackages__"],
|
||||
deps = [
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//proto/beacon/rpc/v1:go_default_library",
|
||||
"//proto/validator/accounts/v2:go_default_library",
|
||||
"//shared/blockutil:go_default_library",
|
||||
"//shared/bls:go_default_library",
|
||||
|
||||
@@ -64,10 +64,10 @@ func (v *validator) SubmitAttestation(ctx context.Context, slot uint64, pubKey [
|
||||
Data: data,
|
||||
}
|
||||
if err := v.preAttSignValidations(ctx, indexedAtt, pubKey); err != nil {
|
||||
log.WithFields(logrus.Fields{
|
||||
"sourceEpoch": indexedAtt.Data.Source.Epoch,
|
||||
"targetEpoch": indexedAtt.Data.Target.Epoch,
|
||||
}).WithError(err).Error("Failed attestation safety check")
|
||||
log.WithError(err).Error("Failed attestation slashing protection check")
|
||||
log.WithFields(
|
||||
attestationLogFields(pubKey, indexedAtt),
|
||||
).Debug("Attempted slashable attestation details")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -107,13 +107,15 @@ func (v *validator) SubmitAttestation(ctx context.Context, slot uint64, pubKey [
|
||||
|
||||
indexedAtt.Signature = sig
|
||||
if err := v.postAttSignUpdate(ctx, indexedAtt, pubKey, signingRoot); err != nil {
|
||||
log.WithFields(logrus.Fields{
|
||||
"sourceEpoch": indexedAtt.Data.Source.Epoch,
|
||||
"targetEpoch": indexedAtt.Data.Target.Epoch,
|
||||
}).WithError(err).Error("Failed post attestation signing updates")
|
||||
log.WithError(err).Error("Failed attestation slashing protection check")
|
||||
log.WithFields(
|
||||
attestationLogFields(pubKey, indexedAtt),
|
||||
).Debug("Attempted slashable attestation details")
|
||||
return
|
||||
}
|
||||
|
||||
if err := v.SaveProtection(ctx, pubKey); err != nil {
|
||||
log.WithError(err).Errorf("Could not save validator: %#x protection", pubKey)
|
||||
}
|
||||
attResp, err := v.validatorClient.ProposeAttestation(ctx, attestation)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not submit attestation to beacon node")
|
||||
@@ -122,9 +124,6 @@ func (v *validator) SubmitAttestation(ctx context.Context, slot uint64, pubKey [
|
||||
}
|
||||
return
|
||||
}
|
||||
if err := v.SaveProtection(ctx, pubKey); err != nil {
|
||||
log.WithError(err).Errorf("Could not save validator: %#x protection", pubKey)
|
||||
}
|
||||
|
||||
if err := v.saveAttesterIndexToData(data, duty.ValidatorIndex); err != nil {
|
||||
log.WithError(err).Error("Could not save validator index for logging")
|
||||
@@ -227,3 +226,17 @@ func (v *validator) waitToSlotOneThird(ctx context.Context, slot uint64) {
|
||||
finalTime := startTime.Add(delay)
|
||||
time.Sleep(timeutils.Until(finalTime))
|
||||
}
|
||||
|
||||
func attestationLogFields(pubKey [48]byte, indexedAtt *ethpb.IndexedAttestation) logrus.Fields {
|
||||
return logrus.Fields{
|
||||
"attesterPublicKey": fmt.Sprintf("%#x", pubKey),
|
||||
"attestationSlot": indexedAtt.Data.Slot,
|
||||
"committeeIndex": indexedAtt.Data.CommitteeIndex,
|
||||
"beaconBlockRoot": fmt.Sprintf("%#x", indexedAtt.Data.BeaconBlockRoot),
|
||||
"sourceEpoch": indexedAtt.Data.Source.Epoch,
|
||||
"sourceRoot": fmt.Sprintf("%#x", indexedAtt.Data.Source.Root),
|
||||
"targetEpoch": indexedAtt.Data.Target.Epoch,
|
||||
"targetRoot": fmt.Sprintf("%#x", indexedAtt.Data.Target.Root),
|
||||
"signature": fmt.Sprintf("%#x", indexedAtt.Signature),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/validator/db/kv"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var failedAttLocalProtectionErr = "attempted to make slashable attestation, rejected by local slashing protection"
|
||||
@@ -18,24 +19,43 @@ var failedPostAttSignExternalErr = "external slasher service detected a submitte
|
||||
|
||||
func (v *validator) preAttSignValidations(ctx context.Context, indexedAtt *ethpb.IndexedAttestation, pubKey [48]byte) error {
|
||||
fmtKey := fmt.Sprintf("%#x", pubKey[:])
|
||||
|
||||
v.attesterHistoryByPubKeyLock.RLock()
|
||||
attesterHistory, ok := v.attesterHistoryByPubKey[pubKey]
|
||||
v.attesterHistoryByPubKeyLock.RUnlock()
|
||||
if !ok {
|
||||
AttestationMapMiss.Inc()
|
||||
attesterHistoryMap, err := v.db.AttestationHistoryForPubKeysV2(ctx, [][48]byte{pubKey})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get attester history")
|
||||
}
|
||||
attesterHistory, ok = attesterHistoryMap[pubKey]
|
||||
if !ok {
|
||||
log.WithField("publicKey", fmtKey).Debug("Could not get local slashing protection data for validator in pre validation")
|
||||
}
|
||||
} else {
|
||||
AttestationMapHit.Inc()
|
||||
}
|
||||
_, sr, err := v.getDomainAndSigningRoot(ctx, indexedAtt.Data)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not get domain and signing root from attestation")
|
||||
return err
|
||||
}
|
||||
if ok && isNewAttSlashable(ctx, attesterHistory, indexedAtt.Data.Source.Epoch, indexedAtt.Data.Target.Epoch, sr) {
|
||||
slashable, err := isNewAttSlashable(
|
||||
ctx,
|
||||
attesterHistory,
|
||||
indexedAtt.Data.Source.Epoch,
|
||||
indexedAtt.Data.Target.Epoch,
|
||||
sr,
|
||||
)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not check if attestation is slashable")
|
||||
}
|
||||
if slashable {
|
||||
if v.emitAccountMetrics {
|
||||
ValidatorAttestFailVec.WithLabelValues(fmtKey).Inc()
|
||||
}
|
||||
return errors.New(failedAttLocalProtectionErr)
|
||||
} else if !ok {
|
||||
log.WithField("publicKey", fmtKey).Debug("Could not get local slashing protection data for validator in pre validation")
|
||||
}
|
||||
|
||||
if featureconfig.Get().SlasherProtection && v.protector != nil {
|
||||
if !v.protector.CheckAttestationSafety(ctx, indexedAtt) {
|
||||
if v.emitAccountMetrics {
|
||||
@@ -52,18 +72,48 @@ func (v *validator) postAttSignUpdate(ctx context.Context, indexedAtt *ethpb.Ind
|
||||
v.attesterHistoryByPubKeyLock.Lock()
|
||||
defer v.attesterHistoryByPubKeyLock.Unlock()
|
||||
attesterHistory, ok := v.attesterHistoryByPubKey[pubKey]
|
||||
if ok {
|
||||
if isNewAttSlashable(ctx, attesterHistory, indexedAtt.Data.Source.Epoch, indexedAtt.Data.Target.Epoch, signingRoot) {
|
||||
if v.emitAccountMetrics {
|
||||
ValidatorAttestFailVec.WithLabelValues(fmtKey).Inc()
|
||||
}
|
||||
return errors.New(failedAttLocalProtectionErr)
|
||||
if !ok {
|
||||
AttestationMapMiss.Inc()
|
||||
attesterHistoryMap, err := v.db.AttestationHistoryForPubKeysV2(ctx, [][48]byte{pubKey})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get attester history")
|
||||
}
|
||||
attesterHistory, ok = attesterHistoryMap[pubKey]
|
||||
if !ok {
|
||||
log.WithField("publicKey", fmtKey).Debug("Could not get local slashing protection data for validator in post validation")
|
||||
}
|
||||
attesterHistory = markAttestationForTargetEpoch(ctx, attesterHistory, indexedAtt.Data.Source.Epoch, indexedAtt.Data.Target.Epoch, signingRoot)
|
||||
v.attesterHistoryByPubKey[pubKey] = attesterHistory
|
||||
} else {
|
||||
log.WithField("publicKey", fmtKey).Debug("Could not get local slashing protection data for validator in post validation")
|
||||
AttestationMapHit.Inc()
|
||||
}
|
||||
slashable, err := isNewAttSlashable(
|
||||
ctx,
|
||||
attesterHistory,
|
||||
indexedAtt.Data.Source.Epoch,
|
||||
indexedAtt.Data.Target.Epoch,
|
||||
signingRoot,
|
||||
)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not check if attestation is slashable")
|
||||
}
|
||||
if slashable {
|
||||
if v.emitAccountMetrics {
|
||||
ValidatorAttestFailVec.WithLabelValues(fmtKey).Inc()
|
||||
}
|
||||
return errors.New(failedAttLocalProtectionErr)
|
||||
}
|
||||
newHistory, err := kv.MarkAllAsAttestedSinceLatestWrittenEpoch(
|
||||
ctx,
|
||||
attesterHistory,
|
||||
indexedAtt.Data.Target.Epoch,
|
||||
&kv.HistoryData{
|
||||
Source: indexedAtt.Data.Source.Epoch,
|
||||
SigningRoot: signingRoot[:],
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not mark epoch %d as attested", indexedAtt.Data.Target.Epoch)
|
||||
}
|
||||
v.attesterHistoryByPubKey[pubKey] = newHistory
|
||||
|
||||
if featureconfig.Get().SlasherProtection && v.protector != nil {
|
||||
if !v.protector.CommitAttestation(ctx, indexedAtt) {
|
||||
@@ -73,119 +123,154 @@ func (v *validator) postAttSignUpdate(ctx context.Context, indexedAtt *ethpb.Ind
|
||||
return errors.New(failedPostAttSignExternalErr)
|
||||
}
|
||||
}
|
||||
|
||||
// Save source and target epochs to satisfy EIP3076 requirements.
|
||||
// The DB methods below will replace the lowest epoch in DB if necessary.
|
||||
if err := v.db.SaveLowestSignedSourceEpoch(ctx, pubKey, indexedAtt.Data.Source.Epoch); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := v.db.SaveLowestSignedTargetEpoch(ctx, pubKey, indexedAtt.Data.Target.Epoch); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// isNewAttSlashable uses the attestation history to determine if an attestation of sourceEpoch
|
||||
// and targetEpoch would be slashable. It can detect double, surrounding, and surrounded votes.
|
||||
func isNewAttSlashable(ctx context.Context, history kv.EncHistoryData, sourceEpoch, targetEpoch uint64, signingRoot [32]byte) bool {
|
||||
func isNewAttSlashable(
|
||||
ctx context.Context,
|
||||
history kv.EncHistoryData,
|
||||
sourceEpoch,
|
||||
targetEpoch uint64,
|
||||
signingRoot [32]byte,
|
||||
) (bool, error) {
|
||||
if history == nil {
|
||||
return false
|
||||
return false, nil
|
||||
}
|
||||
wsPeriod := params.BeaconConfig().WeakSubjectivityPeriod
|
||||
// Previously pruned, we should return false.
|
||||
latestEpochWritten, err := history.GetLatestEpochWritten(ctx)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not get latest epoch written from encapsulated data")
|
||||
return false
|
||||
return false, err
|
||||
}
|
||||
|
||||
if latestEpochWritten >= wsPeriod && targetEpoch <= latestEpochWritten-wsPeriod { //Underflow protected older then weak subjectivity check.
|
||||
return false
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// Check if there has already been a vote for this target epoch.
|
||||
hd, err := history.GetTargetData(ctx, targetEpoch)
|
||||
if err != nil {
|
||||
log.WithError(err).Errorf("Could not get target data for target epoch: %d", targetEpoch)
|
||||
return false
|
||||
return false, errors.Wrapf(err, "could not get target data for epoch: %d", targetEpoch)
|
||||
}
|
||||
if !hd.IsEmpty() && !bytes.Equal(signingRoot[:], hd.SigningRoot) {
|
||||
return true
|
||||
log.WithFields(logrus.Fields{
|
||||
"signingRoot": fmt.Sprintf("%#x", signingRoot),
|
||||
"targetEpoch": targetEpoch,
|
||||
"previouslyAttestedSigningRoot": fmt.Sprintf("%#x", hd.SigningRoot),
|
||||
}).Warn("Attempted to submit a double vote, but blocked by slashing protection")
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// Check if the new attestation would be surrounding another attestation.
|
||||
isSurround, err := isSurroundVote(ctx, history, latestEpochWritten, sourceEpoch, targetEpoch)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "could not check if attestation is surround vote")
|
||||
}
|
||||
return isSurround, nil
|
||||
}
|
||||
|
||||
func isSurroundVote(
|
||||
ctx context.Context,
|
||||
history kv.EncHistoryData,
|
||||
latestEpochWritten,
|
||||
sourceEpoch,
|
||||
targetEpoch uint64,
|
||||
) (bool, error) {
|
||||
for i := sourceEpoch; i <= targetEpoch; i++ {
|
||||
// Unattested for epochs are marked as (*kv.HistoryData)(nil).
|
||||
historyBoundary := safeTargetToSource(ctx, history, i)
|
||||
if historyBoundary.IsEmpty() {
|
||||
historicalAtt, err := checkHistoryAtTargetEpoch(ctx, history, latestEpochWritten, i)
|
||||
if err != nil {
|
||||
return false, errors.Wrapf(err, "could not check historical attestation at target epoch: %d", i)
|
||||
}
|
||||
if historicalAtt.IsEmpty() {
|
||||
continue
|
||||
}
|
||||
if historyBoundary.Source > sourceEpoch {
|
||||
return true
|
||||
prevTarget := i
|
||||
prevSource := historicalAtt.Source
|
||||
if surroundingPrevAttestation(prevSource, prevTarget, sourceEpoch, targetEpoch) {
|
||||
// Surrounding attestation caught.
|
||||
log.WithFields(logrus.Fields{
|
||||
"targetEpoch": targetEpoch,
|
||||
"sourceEpoch": sourceEpoch,
|
||||
"previouslyAttestedTargetEpoch": prevTarget,
|
||||
"previouslyAttestedSourceEpoch": prevSource,
|
||||
}).Warn("Attempted to submit a surrounding attestation, but blocked by slashing protection")
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the new attestation is being surrounded.
|
||||
for i := targetEpoch; i <= latestEpochWritten; i++ {
|
||||
h := safeTargetToSource(ctx, history, i)
|
||||
if h.IsEmpty() {
|
||||
historicalAtt, err := checkHistoryAtTargetEpoch(ctx, history, latestEpochWritten, i)
|
||||
if err != nil {
|
||||
return false, errors.Wrapf(err, "could not check historical attestation at target epoch: %d", i)
|
||||
}
|
||||
if historicalAtt.IsEmpty() {
|
||||
continue
|
||||
}
|
||||
if h.Source < sourceEpoch {
|
||||
return true
|
||||
prevTarget := i
|
||||
prevSource := historicalAtt.Source
|
||||
if surroundedByPrevAttestation(prevSource, prevTarget, sourceEpoch, targetEpoch) {
|
||||
// Surrounded attestation caught.
|
||||
log.WithFields(logrus.Fields{
|
||||
"targetEpoch": targetEpoch,
|
||||
"sourceEpoch": sourceEpoch,
|
||||
"previouslyAttestedTargetEpoch": prevTarget,
|
||||
"previouslyAttestedSourceEpoch": prevSource,
|
||||
}).Warn("Attempted to submit a surrounded attestation, but blocked by slashing protection")
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// markAttestationForTargetEpoch returns the modified attestation history with the passed-in epochs marked
|
||||
// as attested for. This is done to prevent the validator client from signing any slashable attestations.
|
||||
func markAttestationForTargetEpoch(ctx context.Context, history kv.EncHistoryData, sourceEpoch, targetEpoch uint64, signingRoot [32]byte) kv.EncHistoryData {
|
||||
if history == nil {
|
||||
return nil
|
||||
}
|
||||
func surroundedByPrevAttestation(prevSource, prevTarget, newSource, newTarget uint64) bool {
|
||||
return prevSource < newSource && newTarget < prevTarget
|
||||
}
|
||||
|
||||
func surroundingPrevAttestation(prevSource, prevTarget, newSource, newTarget uint64) bool {
|
||||
return newSource < prevSource && prevTarget < newTarget
|
||||
}
|
||||
|
||||
// Checks that the difference between the latest epoch written and
|
||||
// target epoch is greater than or equal to the weak subjectivity period.
|
||||
func differenceOutsideWeakSubjectivityBounds(latestEpochWritten, targetEpoch uint64) bool {
|
||||
wsPeriod := params.BeaconConfig().WeakSubjectivityPeriod
|
||||
latestEpochWritten, err := history.GetLatestEpochWritten(ctx)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not get latest epoch written from encapsulated data")
|
||||
return nil
|
||||
}
|
||||
if targetEpoch > latestEpochWritten {
|
||||
// If the target epoch to mark is ahead of latest written epoch, override the old targets and mark the requested epoch.
|
||||
// Limit the overwriting to one weak subjectivity period as further is not needed.
|
||||
maxToWrite := latestEpochWritten + wsPeriod
|
||||
for i := latestEpochWritten + 1; i < targetEpoch && i <= maxToWrite; i++ {
|
||||
history, err = history.SetTargetData(ctx, i%wsPeriod, &kv.HistoryData{Source: params.BeaconConfig().FarFutureEpoch})
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not set target to the encapsulated data")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
history, err = history.SetLatestEpochWritten(ctx, targetEpoch)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not set latest epoch written to the encapsulated data")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
history, err = history.SetTargetData(ctx, targetEpoch%wsPeriod, &kv.HistoryData{Source: sourceEpoch, SigningRoot: signingRoot[:]})
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not set target to the encapsulated data")
|
||||
return nil
|
||||
}
|
||||
return history
|
||||
return latestEpochWritten >= wsPeriod && targetEpoch <= latestEpochWritten-wsPeriod
|
||||
}
|
||||
|
||||
// safeTargetToSource makes sure the epoch accessed is within bounds, and if it's not it at
|
||||
// returns the "default" nil value.
|
||||
func safeTargetToSource(ctx context.Context, history kv.EncHistoryData, targetEpoch uint64) *kv.HistoryData {
|
||||
// Returns the actual attesting history at a specified target epoch.
|
||||
// The response is nil if there was no attesting history at that epoch.
|
||||
func checkHistoryAtTargetEpoch(
|
||||
ctx context.Context,
|
||||
history kv.EncHistoryData,
|
||||
latestEpochWritten,
|
||||
targetEpoch uint64,
|
||||
) (*kv.HistoryData, error) {
|
||||
wsPeriod := params.BeaconConfig().WeakSubjectivityPeriod
|
||||
latestEpochWritten, err := history.GetLatestEpochWritten(ctx)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not get latest epoch written from encapsulated data")
|
||||
return nil
|
||||
if differenceOutsideWeakSubjectivityBounds(latestEpochWritten, targetEpoch) {
|
||||
return nil, nil
|
||||
}
|
||||
// Ignore target epoch is > latest written.
|
||||
if targetEpoch > latestEpochWritten {
|
||||
return nil
|
||||
return nil, nil
|
||||
}
|
||||
if latestEpochWritten >= wsPeriod && targetEpoch < latestEpochWritten-wsPeriod { //Underflow protected older then weak subjectivity check.
|
||||
return nil
|
||||
}
|
||||
hd, err := history.GetTargetData(ctx, targetEpoch%wsPeriod)
|
||||
historicalAtt, err := history.GetTargetData(ctx, targetEpoch%wsPeriod)
|
||||
if err != nil {
|
||||
log.WithError(err).Errorf("Could not get target data for target epoch: %d", targetEpoch)
|
||||
return nil
|
||||
return nil, errors.Wrapf(err, "could not get target data for target epoch: %d", targetEpoch)
|
||||
}
|
||||
return hd
|
||||
return historicalAtt, nil
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
@@ -128,6 +129,13 @@ func TestPostSignatureUpdate(t *testing.T) {
|
||||
mockProtector.AllowAttestation = true
|
||||
err = validator.postAttSignUpdate(context.Background(), att, pubKey, sr)
|
||||
require.NoError(t, err, "Expected allowed attestation not to throw error")
|
||||
|
||||
e, err := validator.db.LowestSignedSourceEpoch(context.Background(), pubKey)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(4), e)
|
||||
e, err = validator.db.LowestSignedTargetEpoch(context.Background(), pubKey)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(10), e)
|
||||
}
|
||||
|
||||
func TestPostSignatureUpdate_NilLocal(t *testing.T) {
|
||||
@@ -168,7 +176,12 @@ func TestAttestationHistory_BlocksDoubleAttestation(t *testing.T) {
|
||||
newAttSource := uint64(0)
|
||||
newAttTarget := uint64(3)
|
||||
sr1 := [32]byte{1}
|
||||
history = markAttestationForTargetEpoch(ctx, history, newAttSource, newAttTarget, sr1)
|
||||
newHist, err := kv.MarkAllAsAttestedSinceLatestWrittenEpoch(ctx, history, newAttTarget, &kv.HistoryData{
|
||||
Source: newAttSource,
|
||||
SigningRoot: sr1[:],
|
||||
})
|
||||
require.NoError(t, err)
|
||||
history = newHist
|
||||
lew, err := history.GetLatestEpochWritten(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, newAttTarget, lew, "Unexpected latest epoch written")
|
||||
@@ -177,7 +190,9 @@ func TestAttestationHistory_BlocksDoubleAttestation(t *testing.T) {
|
||||
sr2 := [32]byte{2}
|
||||
newAttSource = uint64(1)
|
||||
newAttTarget = uint64(3)
|
||||
if !isNewAttSlashable(ctx, history, newAttSource, newAttTarget, sr2) {
|
||||
slashable, err := isNewAttSlashable(ctx, history, newAttSource, newAttTarget, sr2)
|
||||
require.NoError(t, err)
|
||||
if !slashable {
|
||||
t.Fatalf("Expected attestation of source %d and target %d to be considered slashable", newAttSource, newAttTarget)
|
||||
}
|
||||
}
|
||||
@@ -294,15 +309,27 @@ func TestAttestationHistory_Prunes(t *testing.T) {
|
||||
history := kv.NewAttestationHistoryArray(0)
|
||||
|
||||
// Try an attestation on totally unmarked history, should not be slashable.
|
||||
require.Equal(t, false, isNewAttSlashable(ctx, history, 0, wsPeriod+5, signingRoot), "Should not be slashable")
|
||||
slashable, err := isNewAttSlashable(ctx, history, 0, wsPeriod+5, signingRoot)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, false, slashable, "Should not be slashable")
|
||||
|
||||
// Mark attestations spanning epochs 0 to 3 and 6 to 9.
|
||||
prunedNewAttSource := uint64(0)
|
||||
prunedNewAttTarget := uint64(3)
|
||||
history = markAttestationForTargetEpoch(ctx, history, prunedNewAttSource, prunedNewAttTarget, signingRoot)
|
||||
newHist, err := kv.MarkAllAsAttestedSinceLatestWrittenEpoch(ctx, history, prunedNewAttTarget, &kv.HistoryData{
|
||||
Source: prunedNewAttSource,
|
||||
SigningRoot: signingRoot[:],
|
||||
})
|
||||
require.NoError(t, err)
|
||||
history = newHist
|
||||
newAttSource := prunedNewAttSource + 6
|
||||
newAttTarget := prunedNewAttTarget + 6
|
||||
history = markAttestationForTargetEpoch(ctx, history, newAttSource, newAttTarget, signingRoot2)
|
||||
newHist, err = kv.MarkAllAsAttestedSinceLatestWrittenEpoch(ctx, history, newAttTarget, &kv.HistoryData{
|
||||
Source: newAttSource,
|
||||
SigningRoot: signingRoot2[:],
|
||||
})
|
||||
require.NoError(t, err)
|
||||
history = newHist
|
||||
lte, err := history.GetLatestEpochWritten(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, newAttTarget, lte, "Unexpected latest epoch")
|
||||
@@ -310,24 +337,39 @@ func TestAttestationHistory_Prunes(t *testing.T) {
|
||||
// Mark an attestation spanning epochs 54000 to 54003.
|
||||
farNewAttSource := newAttSource + wsPeriod
|
||||
farNewAttTarget := newAttTarget + wsPeriod
|
||||
history = markAttestationForTargetEpoch(ctx, history, farNewAttSource, farNewAttTarget, signingRoot3)
|
||||
newHist, err = kv.MarkAllAsAttestedSinceLatestWrittenEpoch(ctx, history, farNewAttTarget, &kv.HistoryData{
|
||||
Source: farNewAttSource,
|
||||
SigningRoot: signingRoot3[:],
|
||||
})
|
||||
require.NoError(t, err)
|
||||
history = newHist
|
||||
lte, err = history.GetLatestEpochWritten(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, farNewAttTarget, lte, "Unexpected latest epoch")
|
||||
|
||||
require.Equal(t, (*kv.HistoryData)(nil), safeTargetToSource(ctx, history, prunedNewAttTarget), "Unexpectedly marked attestation")
|
||||
require.Equal(t, farNewAttSource, safeTargetToSource(ctx, history, farNewAttTarget).Source, "Unexpectedly marked attestation")
|
||||
histAtt, err := checkHistoryAtTargetEpoch(ctx, history, lte, prunedNewAttTarget)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, (*kv.HistoryData)(nil), histAtt, "Unexpectedly marked attestation")
|
||||
histAtt, err = checkHistoryAtTargetEpoch(ctx, history, lte, farNewAttTarget)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, farNewAttSource, histAtt.Source, "Unexpectedly marked attestation")
|
||||
|
||||
// Try an attestation from existing source to outside prune, should slash.
|
||||
if !isNewAttSlashable(ctx, history, newAttSource, farNewAttTarget, signingRoot4) {
|
||||
slashable, err = isNewAttSlashable(ctx, history, newAttSource, farNewAttTarget, signingRoot4)
|
||||
require.NoError(t, err)
|
||||
if !slashable {
|
||||
t.Fatalf("Expected attestation of source %d, target %d to be considered slashable", newAttSource, farNewAttTarget)
|
||||
}
|
||||
// Try an attestation from before existing target to outside prune, should slash.
|
||||
if !isNewAttSlashable(ctx, history, newAttTarget-1, farNewAttTarget, signingRoot4) {
|
||||
slashable, err = isNewAttSlashable(ctx, history, newAttTarget-1, farNewAttTarget, signingRoot4)
|
||||
require.NoError(t, err)
|
||||
if !slashable {
|
||||
t.Fatalf("Expected attestation of source %d, target %d to be considered slashable", newAttTarget-1, farNewAttTarget)
|
||||
}
|
||||
// Try an attestation larger than pruning amount, should slash.
|
||||
if !isNewAttSlashable(ctx, history, 0, farNewAttTarget+5, signingRoot4) {
|
||||
slashable, err = isNewAttSlashable(ctx, history, 0, farNewAttTarget+5, signingRoot4)
|
||||
require.NoError(t, err)
|
||||
if !slashable {
|
||||
t.Fatalf("Expected attestation of source 0, target %d to be considered slashable", farNewAttTarget+5)
|
||||
}
|
||||
}
|
||||
@@ -340,7 +382,12 @@ func TestAttestationHistory_BlocksSurroundedAttestation(t *testing.T) {
|
||||
signingRoot := [32]byte{1}
|
||||
newAttSource := uint64(0)
|
||||
newAttTarget := uint64(3)
|
||||
history = markAttestationForTargetEpoch(ctx, history, newAttSource, newAttTarget, signingRoot)
|
||||
newHist, err := kv.MarkAllAsAttestedSinceLatestWrittenEpoch(ctx, history, newAttTarget, &kv.HistoryData{
|
||||
Source: newAttSource,
|
||||
SigningRoot: signingRoot[:],
|
||||
})
|
||||
require.NoError(t, err)
|
||||
history = newHist
|
||||
lte, err := history.GetLatestEpochWritten(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, newAttTarget, lte)
|
||||
@@ -348,7 +395,9 @@ func TestAttestationHistory_BlocksSurroundedAttestation(t *testing.T) {
|
||||
// Try an attestation that should be slashable (being surrounded) spanning epochs 1 to 2.
|
||||
newAttSource = uint64(1)
|
||||
newAttTarget = uint64(2)
|
||||
require.Equal(t, true, isNewAttSlashable(ctx, history, newAttSource, newAttTarget, signingRoot), "Expected slashable attestation")
|
||||
slashable, err := isNewAttSlashable(ctx, history, newAttSource, newAttTarget, signingRoot)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, slashable, "Expected slashable attestation")
|
||||
}
|
||||
|
||||
func TestAttestationHistory_BlocksSurroundingAttestation(t *testing.T) {
|
||||
@@ -359,7 +408,12 @@ func TestAttestationHistory_BlocksSurroundingAttestation(t *testing.T) {
|
||||
// Mark an attestation spanning epochs 1 to 2.
|
||||
newAttSource := uint64(1)
|
||||
newAttTarget := uint64(2)
|
||||
history = markAttestationForTargetEpoch(ctx, history, newAttSource, newAttTarget, signingRoot)
|
||||
newHist, err := kv.MarkAllAsAttestedSinceLatestWrittenEpoch(ctx, history, newAttTarget, &kv.HistoryData{
|
||||
Source: newAttSource,
|
||||
SigningRoot: signingRoot[:],
|
||||
})
|
||||
require.NoError(t, err)
|
||||
history = newHist
|
||||
lte, err := history.GetLatestEpochWritten(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, newAttTarget, lte)
|
||||
@@ -370,5 +424,346 @@ func TestAttestationHistory_BlocksSurroundingAttestation(t *testing.T) {
|
||||
// Try an attestation that should be slashable (surrounding) spanning epochs 0 to 3.
|
||||
newAttSource = uint64(0)
|
||||
newAttTarget = uint64(3)
|
||||
require.Equal(t, true, isNewAttSlashable(ctx, history, newAttSource, newAttTarget, signingRoot))
|
||||
slashable, err := isNewAttSlashable(ctx, history, newAttSource, newAttTarget, signingRoot)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, slashable)
|
||||
}
|
||||
|
||||
func Test_isSurroundVote(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
source := uint64(1)
|
||||
target := uint64(4)
|
||||
history := kv.NewAttestationHistoryArray(0)
|
||||
signingRoot1 := bytesutil.PadTo([]byte{1}, 32)
|
||||
hist, err := history.SetTargetData(ctx, target, &kv.HistoryData{
|
||||
Source: source,
|
||||
SigningRoot: signingRoot1,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
history = hist
|
||||
tests := []struct {
|
||||
name string
|
||||
history kv.EncHistoryData
|
||||
latestEpochWritten uint64
|
||||
sourceEpoch uint64
|
||||
targetEpoch uint64
|
||||
want bool
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "ignores attestations outside of weak subjectivity bounds",
|
||||
history: kv.NewAttestationHistoryArray(0),
|
||||
latestEpochWritten: 2 * params.BeaconConfig().WeakSubjectivityPeriod,
|
||||
targetEpoch: params.BeaconConfig().WeakSubjectivityPeriod,
|
||||
sourceEpoch: params.BeaconConfig().WeakSubjectivityPeriod,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "detects surrounding attestations",
|
||||
history: history,
|
||||
latestEpochWritten: target,
|
||||
targetEpoch: target + 1,
|
||||
sourceEpoch: source - 1,
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "detects surrounded attestations",
|
||||
history: history,
|
||||
latestEpochWritten: target,
|
||||
targetEpoch: target - 1,
|
||||
sourceEpoch: source + 1,
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "new attestation source == old source, but new target < old target",
|
||||
history: history,
|
||||
latestEpochWritten: target,
|
||||
targetEpoch: target - 1,
|
||||
sourceEpoch: source,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "new attestation source > old source, but new target == old target",
|
||||
history: history,
|
||||
latestEpochWritten: target,
|
||||
targetEpoch: target,
|
||||
sourceEpoch: source + 1,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "new attestation source and targets equal to old one",
|
||||
history: history,
|
||||
latestEpochWritten: target,
|
||||
targetEpoch: target,
|
||||
sourceEpoch: source,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "new attestation source == old source, but new target > old target",
|
||||
history: history,
|
||||
latestEpochWritten: target,
|
||||
targetEpoch: target + 1,
|
||||
sourceEpoch: source,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "new attestation source < old source, but new target == old target",
|
||||
history: history,
|
||||
latestEpochWritten: target,
|
||||
targetEpoch: target,
|
||||
sourceEpoch: source - 1,
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := isSurroundVote(ctx, tt.history, tt.latestEpochWritten, tt.sourceEpoch, tt.targetEpoch)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("isSurroundVote() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if got != tt.want {
|
||||
t.Errorf("isSurroundVote() got = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_surroundedByPrevAttestation(t *testing.T) {
|
||||
type args struct {
|
||||
oldSource uint64
|
||||
oldTarget uint64
|
||||
newSource uint64
|
||||
newTarget uint64
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "0 values returns false",
|
||||
args: args{
|
||||
oldSource: 0,
|
||||
oldTarget: 0,
|
||||
newSource: 0,
|
||||
newTarget: 0,
|
||||
},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "new attestation is surrounded by an old one",
|
||||
args: args{
|
||||
oldSource: 2,
|
||||
oldTarget: 6,
|
||||
newSource: 3,
|
||||
newTarget: 5,
|
||||
},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "new attestation source and targets equal to old one",
|
||||
args: args{
|
||||
oldSource: 3,
|
||||
oldTarget: 5,
|
||||
newSource: 3,
|
||||
newTarget: 5,
|
||||
},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "new attestation source == old source, but new target < old target",
|
||||
args: args{
|
||||
oldSource: 3,
|
||||
oldTarget: 5,
|
||||
newSource: 3,
|
||||
newTarget: 4,
|
||||
},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "new attestation source > old source, but new target == old target",
|
||||
args: args{
|
||||
oldSource: 3,
|
||||
oldTarget: 5,
|
||||
newSource: 4,
|
||||
newTarget: 5,
|
||||
},
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := surroundedByPrevAttestation(tt.args.oldSource, tt.args.oldTarget, tt.args.newSource, tt.args.newTarget); got != tt.want {
|
||||
t.Errorf("surroundedByPrevAttestation() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_surroundingPrevAttestation(t *testing.T) {
|
||||
type args struct {
|
||||
oldSource uint64
|
||||
oldTarget uint64
|
||||
newSource uint64
|
||||
newTarget uint64
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "0 values returns false",
|
||||
args: args{
|
||||
oldSource: 0,
|
||||
oldTarget: 0,
|
||||
newSource: 0,
|
||||
newTarget: 0,
|
||||
},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "new attestation is surrounding an old one",
|
||||
args: args{
|
||||
oldSource: 3,
|
||||
oldTarget: 5,
|
||||
newSource: 2,
|
||||
newTarget: 6,
|
||||
},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "new attestation source and targets equal to old one",
|
||||
args: args{
|
||||
oldSource: 3,
|
||||
oldTarget: 5,
|
||||
newSource: 3,
|
||||
newTarget: 5,
|
||||
},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "new attestation source == old source, but new target > old target",
|
||||
args: args{
|
||||
oldSource: 3,
|
||||
oldTarget: 5,
|
||||
newSource: 3,
|
||||
newTarget: 6,
|
||||
},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "new attestation source < old source, but new target == old target",
|
||||
args: args{
|
||||
oldSource: 3,
|
||||
oldTarget: 5,
|
||||
newSource: 2,
|
||||
newTarget: 5,
|
||||
},
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := surroundingPrevAttestation(tt.args.oldSource, tt.args.oldTarget, tt.args.newSource, tt.args.newTarget); got != tt.want {
|
||||
t.Errorf("surroundingPrevAttestation() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_checkHistoryAtTargetEpoch(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
history := kv.NewAttestationHistoryArray(0)
|
||||
signingRoot1 := bytesutil.PadTo([]byte{1}, 32)
|
||||
hist, err := history.SetTargetData(ctx, 1, &kv.HistoryData{
|
||||
Source: 0,
|
||||
SigningRoot: signingRoot1,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
history = hist
|
||||
tests := []struct {
|
||||
name string
|
||||
history kv.EncHistoryData
|
||||
latestEpochWritten uint64
|
||||
targetEpoch uint64
|
||||
want *kv.HistoryData
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "ignores difference in epochs outside of weak subjectivity bounds",
|
||||
history: kv.NewAttestationHistoryArray(0),
|
||||
latestEpochWritten: 2 * params.BeaconConfig().WeakSubjectivityPeriod,
|
||||
targetEpoch: params.BeaconConfig().WeakSubjectivityPeriod,
|
||||
want: nil,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "ignores target epoch > latest written epoch",
|
||||
history: kv.NewAttestationHistoryArray(0),
|
||||
latestEpochWritten: params.BeaconConfig().WeakSubjectivityPeriod,
|
||||
targetEpoch: params.BeaconConfig().WeakSubjectivityPeriod + 1,
|
||||
want: nil,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "target epoch == latest written epoch should return correct results",
|
||||
history: history,
|
||||
latestEpochWritten: 1,
|
||||
targetEpoch: 1,
|
||||
want: &kv.HistoryData{
|
||||
Source: 0,
|
||||
SigningRoot: signingRoot1,
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := checkHistoryAtTargetEpoch(ctx, tt.history, tt.latestEpochWritten, tt.targetEpoch)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("checkHistoryAtTargetEpoch() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("checkHistoryAtTargetEpoch() got = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_differenceOutsideWeakSubjectivityBounds(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
want bool
|
||||
latestEpochWritten uint64
|
||||
targetEpoch uint64
|
||||
}{
|
||||
{
|
||||
name: "difference of weak subjectivity period - 1 returns false",
|
||||
latestEpochWritten: (2 * params.BeaconConfig().WeakSubjectivityPeriod) - 1,
|
||||
targetEpoch: params.BeaconConfig().WeakSubjectivityPeriod,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "difference of weak subjectivity period returns true",
|
||||
latestEpochWritten: 2 * params.BeaconConfig().WeakSubjectivityPeriod,
|
||||
targetEpoch: params.BeaconConfig().WeakSubjectivityPeriod,
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "difference > weak subjectivity period returns true",
|
||||
latestEpochWritten: (2 * params.BeaconConfig().WeakSubjectivityPeriod) + 1,
|
||||
targetEpoch: params.BeaconConfig().WeakSubjectivityPeriod,
|
||||
want: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := differenceOutsideWeakSubjectivityBounds(tt.latestEpochWritten, tt.targetEpoch); got != tt.want {
|
||||
t.Errorf("differenceOutsideWeakSubjectivityBounds() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,18 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
// AttestationMapMiss used to track the success rate of historical
|
||||
// attestation map for slashing detection flow.
|
||||
AttestationMapHit = promauto.NewCounter(prometheus.CounterOpts{
|
||||
Name: "attestation_history_map_hit",
|
||||
Help: "The number of attestation history calls that are present in the map.",
|
||||
})
|
||||
// AttestationMapMiss used to track the use of the fallback db read when
|
||||
// attestation map is being mutated while being used in the slashing detection flow.
|
||||
AttestationMapMiss = promauto.NewCounter(prometheus.CounterOpts{
|
||||
Name: "attestation_history_map_miss",
|
||||
Help: "The number of attestation history calls that are'nt present in the map.",
|
||||
})
|
||||
// ValidatorStatusesGaugeVec used to track validator statuses by public key.
|
||||
ValidatorStatusesGaugeVec = promauto.NewGaugeVec(
|
||||
prometheus.GaugeOpts{
|
||||
|
||||
@@ -119,12 +119,6 @@ func (fv *FakeValidator) LogValidatorGainsAndLosses(_ context.Context, _ uint64)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SaveProtections for mocking.
|
||||
func (fv *FakeValidator) SaveProtections(_ context.Context) error {
|
||||
fv.SaveProtectionsCalled = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// ResetAttesterProtectionData for mocking.
|
||||
func (fv *FakeValidator) ResetAttesterProtectionData() {
|
||||
fv.DeleteProtectionCalled = true
|
||||
|
||||
@@ -67,7 +67,9 @@ func (v *validator) ProposeBlock(ctx context.Context, slot uint64, pubKey [48]by
|
||||
}
|
||||
|
||||
if err := v.preBlockSignValidations(ctx, pubKey, b); err != nil {
|
||||
log.WithField("slot", b.Slot).WithError(err).Error("Failed block safety check")
|
||||
log.WithFields(
|
||||
blockLogFields(pubKey, b, nil),
|
||||
).WithError(err).Error("Failed block slashing protection check")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -86,7 +88,9 @@ func (v *validator) ProposeBlock(ctx context.Context, slot uint64, pubKey [48]by
|
||||
}
|
||||
|
||||
if err := v.postBlockSignUpdate(ctx, pubKey, blk, domain); err != nil {
|
||||
log.WithField("slot", blk.Block.Slot).WithError(err).Error("Failed post block signing validations")
|
||||
log.WithFields(
|
||||
blockLogFields(pubKey, b, sig),
|
||||
).WithError(err).Error("Failed block slashing protection check")
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
@@ -10,7 +9,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/shared/blockutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var failedPreBlockSignLocalErr = "attempted to sign a double proposal, block rejected by local protection"
|
||||
@@ -19,15 +18,17 @@ var failedPostBlockSignErr = "made a double proposal, considered slashable by re
|
||||
|
||||
func (v *validator) preBlockSignValidations(ctx context.Context, pubKey [48]byte, block *ethpb.BeaconBlock) error {
|
||||
fmtKey := fmt.Sprintf("%#x", pubKey[:])
|
||||
signingRoot, err := v.db.ProposalHistoryForSlot(ctx, pubKey[:], block.Slot)
|
||||
_, exists, err := v.db.ProposalHistoryForSlot(ctx, pubKey, block.Slot)
|
||||
if err != nil {
|
||||
if v.emitAccountMetrics {
|
||||
ValidatorProposeFailVec.WithLabelValues(fmtKey).Inc()
|
||||
}
|
||||
return errors.Wrap(err, "failed to get proposal history")
|
||||
}
|
||||
// If the bit for the current slot is marked, do not propose.
|
||||
if !bytes.Equal(signingRoot, params.BeaconConfig().ZeroHash[:]) {
|
||||
// If a proposal exists in our history for the slot, we assume it is slashable.
|
||||
// TODO(#7848): Add a more sophisticated strategy where if we indeed have the signing root,
|
||||
// only blocks that have a conflicting signing root with a historical proposal are slashable.
|
||||
if exists {
|
||||
if v.emitAccountMetrics {
|
||||
ValidatorProposeFailVec.WithLabelValues(fmtKey).Inc()
|
||||
}
|
||||
@@ -75,7 +76,7 @@ func (v *validator) postBlockSignUpdate(ctx context.Context, pubKey [48]byte, bl
|
||||
}
|
||||
return errors.Wrap(err, "failed to compute signing root for block")
|
||||
}
|
||||
if err := v.db.SaveProposalHistoryForSlot(ctx, pubKey[:], block.Block.Slot, signingRoot[:]); err != nil {
|
||||
if err := v.db.SaveProposalHistoryForSlot(ctx, pubKey, block.Block.Slot, signingRoot[:]); err != nil {
|
||||
if v.emitAccountMetrics {
|
||||
ValidatorProposeFailVec.WithLabelValues(fmtKey).Inc()
|
||||
}
|
||||
@@ -83,3 +84,15 @@ func (v *validator) postBlockSignUpdate(ctx context.Context, pubKey [48]byte, bl
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func blockLogFields(pubKey [48]byte, blk *ethpb.BeaconBlock, sig []byte) logrus.Fields {
|
||||
fields := logrus.Fields{
|
||||
"proposerPublicKey": fmt.Sprintf("%#x", pubKey),
|
||||
"proposerIndex": blk.ProposerIndex,
|
||||
"blockSlot": blk.Slot,
|
||||
}
|
||||
if sig != nil {
|
||||
fields["signature"] = fmt.Sprintf("%#x", sig)
|
||||
}
|
||||
return fields
|
||||
}
|
||||
|
||||
@@ -25,15 +25,34 @@ func TestPreBlockSignLocalValidation(t *testing.T) {
|
||||
Slot: 10,
|
||||
ProposerIndex: 0,
|
||||
}
|
||||
err := validator.db.SaveProposalHistoryForSlot(ctx, validatorKey.PublicKey().Marshal(), 10, []byte{1})
|
||||
pubKeyBytes := [48]byte{}
|
||||
copy(pubKeyBytes[:], validatorKey.PublicKey().Marshal())
|
||||
|
||||
// We save a proposal at slot 10 with a dummy signing root.
|
||||
err := validator.db.SaveProposalHistoryForSlot(ctx, pubKeyBytes, 10, []byte{1})
|
||||
require.NoError(t, err)
|
||||
pubKey := [48]byte{}
|
||||
copy(pubKey[:], validatorKey.PublicKey().Marshal())
|
||||
|
||||
// We expect the same block sent out should return slashable error.
|
||||
err = validator.preBlockSignValidations(context.Background(), pubKey, block)
|
||||
require.ErrorContains(t, failedPreBlockSignLocalErr, err)
|
||||
|
||||
// We save a proposal at slot 11 with a nil signing root.
|
||||
block.Slot = 11
|
||||
err = validator.db.SaveProposalHistoryForSlot(ctx, pubKeyBytes, block.Slot, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
// We expect the same block sent out should return slashable error even
|
||||
// if we had a nil signing root stored in the database.
|
||||
err = validator.preBlockSignValidations(context.Background(), pubKey, block)
|
||||
require.ErrorContains(t, failedPreBlockSignLocalErr, err)
|
||||
|
||||
// A block with a different slot for which we do not have a proposing history
|
||||
// should not be failing validation.
|
||||
block.Slot = 9
|
||||
err = validator.preBlockSignValidations(context.Background(), pubKey, block)
|
||||
require.NoError(t, err, "Expected allowed attestation not to throw error")
|
||||
require.NoError(t, err, "Expected allowed block not to throw error")
|
||||
}
|
||||
|
||||
func TestPreBlockSignValidation(t *testing.T) {
|
||||
|
||||
@@ -33,7 +33,6 @@ type Validator interface {
|
||||
ProposeBlock(ctx context.Context, slot uint64, pubKey [48]byte)
|
||||
SubmitAggregateAndProof(ctx context.Context, slot uint64, pubKey [48]byte)
|
||||
LogAttestationsSubmitted()
|
||||
SaveProtections(ctx context.Context) error
|
||||
ResetAttesterProtectionData()
|
||||
UpdateDomainDataCaches(ctx context.Context, slot uint64)
|
||||
WaitForWalletInitialization(ctx context.Context) error
|
||||
@@ -155,11 +154,11 @@ func run(ctx context.Context, v Validator) {
|
||||
}
|
||||
}
|
||||
// Wait for all processes to complete, then report span complete.
|
||||
|
||||
go func() {
|
||||
wg.Wait()
|
||||
v.ResetAttesterProtectionData()
|
||||
v.LogAttestationsSubmitted()
|
||||
// Log this client performance in the previous epoch
|
||||
v.LogAttestationsSubmitted()
|
||||
if err := v.LogValidatorGainsAndLosses(slotCtx, slot); err != nil {
|
||||
log.WithError(err).Error("Could not report validator's rewards/penalties")
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
"github.com/pkg/errors"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
pbrpc "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/event"
|
||||
"github.com/prysmaticlabs/prysm/shared/grpcutils"
|
||||
@@ -45,6 +46,12 @@ type GenesisFetcher interface {
|
||||
GenesisInfo(ctx context.Context) (*ethpb.Genesis, error)
|
||||
}
|
||||
|
||||
// BeaconNodeInfoFetcher can retrieve information such as the logs endpoint
|
||||
// from a beacon node via RPC.
|
||||
type BeaconNodeInfoFetcher interface {
|
||||
BeaconLogsEndpoint(ctx context.Context) (string, error)
|
||||
}
|
||||
|
||||
// ValidatorService represents a service to manage the validator client
|
||||
// routine.
|
||||
type ValidatorService struct {
|
||||
@@ -126,7 +133,6 @@ func (v *ValidatorService) Start() {
|
||||
dialOpts := ConstructDialOptions(
|
||||
v.maxCallRecvMsgSize,
|
||||
v.withCert,
|
||||
v.grpcHeaders,
|
||||
v.grpcRetries,
|
||||
v.grpcRetryDelay,
|
||||
streamInterceptor,
|
||||
@@ -134,6 +140,18 @@ func (v *ValidatorService) Start() {
|
||||
if dialOpts == nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, hdr := range v.grpcHeaders {
|
||||
if hdr != "" {
|
||||
ss := strings.Split(hdr, "=")
|
||||
if len(ss) != 2 {
|
||||
log.Warnf("Incorrect gRPC header flag format. Skipping %v", hdr)
|
||||
continue
|
||||
}
|
||||
v.ctx = metadata.AppendToOutgoingContext(v.ctx, ss[0], ss[1])
|
||||
}
|
||||
}
|
||||
|
||||
conn, err := grpc.DialContext(v.ctx, v.endpoint, dialOpts...)
|
||||
if err != nil {
|
||||
log.Errorf("Could not dial endpoint: %s, %v", v.endpoint, err)
|
||||
@@ -236,7 +254,6 @@ func (v *ValidatorService) recheckKeys(ctx context.Context) {
|
||||
func ConstructDialOptions(
|
||||
maxCallRecvMsgSize int,
|
||||
withCert string,
|
||||
grpcHeaders []string,
|
||||
grpcRetries uint,
|
||||
grpcRetryDelay time.Duration,
|
||||
extraOpts ...grpc.DialOption,
|
||||
@@ -260,25 +277,12 @@ func ConstructDialOptions(
|
||||
maxCallRecvMsgSize = 10 * 5 << 20 // Default 50Mb
|
||||
}
|
||||
|
||||
md := make(metadata.MD)
|
||||
for _, hdr := range grpcHeaders {
|
||||
if hdr != "" {
|
||||
ss := strings.Split(hdr, "=")
|
||||
if len(ss) != 2 {
|
||||
log.Warnf("Incorrect gRPC header flag format. Skipping %v", hdr)
|
||||
continue
|
||||
}
|
||||
md.Set(ss[0], ss[1])
|
||||
}
|
||||
}
|
||||
|
||||
dialOpts := []grpc.DialOption{
|
||||
transportSecurity,
|
||||
grpc.WithDefaultCallOptions(
|
||||
grpc.MaxCallRecvMsgSize(maxCallRecvMsgSize),
|
||||
grpc_retry.WithMax(grpcRetries),
|
||||
grpc_retry.WithBackoff(grpc_retry.BackoffLinear(grpcRetryDelay)),
|
||||
grpc.Header(&md),
|
||||
),
|
||||
grpc.WithStatsHandler(&ocgrpc.ClientHandler{}),
|
||||
grpc.WithUnaryInterceptor(middleware.ChainUnaryClient(
|
||||
@@ -317,6 +321,17 @@ func (v *ValidatorService) GenesisInfo(ctx context.Context) (*ethpb.Genesis, err
|
||||
return nc.GetGenesis(ctx, &ptypes.Empty{})
|
||||
}
|
||||
|
||||
// BeaconLogsEndpoint retrieves the websocket endpoint string at which
|
||||
// clients can subscribe to for beacon node logs.
|
||||
func (v *ValidatorService) BeaconLogsEndpoint(ctx context.Context) (string, error) {
|
||||
hc := pbrpc.NewHealthClient(v.conn)
|
||||
resp, err := hc.GetLogsEndpoint(ctx, &ptypes.Empty{})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return resp.BeaconLogsEndpoint, nil
|
||||
}
|
||||
|
||||
// to accounts changes in the keymanager, then updates those keys'
|
||||
// buckets in bolt DB if a bucket for a key does not exist.
|
||||
func recheckValidatingKeysBucket(ctx context.Context, valDB db.Database, km keymanager.IKeymanager) {
|
||||
|
||||
@@ -12,6 +12,9 @@ import (
|
||||
)
|
||||
|
||||
var _ shared.Service = (*ValidatorService)(nil)
|
||||
var _ BeaconNodeInfoFetcher = (*ValidatorService)(nil)
|
||||
var _ GenesisFetcher = (*ValidatorService)(nil)
|
||||
var _ SyncChecker = (*ValidatorService)(nil)
|
||||
|
||||
func TestStop_CancelsContext(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
@@ -525,20 +525,6 @@ func (v *validator) UpdateProtections(ctx context.Context, slot uint64) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SaveProtections saves the attestation information currently in validator state.
|
||||
func (v *validator) SaveProtections(ctx context.Context) error {
|
||||
v.attesterHistoryByPubKeyLock.RLock()
|
||||
if err := v.db.SaveAttestationHistoryForPubKeysV2(ctx, v.attesterHistoryByPubKey); err != nil {
|
||||
return errors.Wrap(err, "could not save attester history to DB")
|
||||
}
|
||||
v.attesterHistoryByPubKeyLock.RUnlock()
|
||||
v.attesterHistoryByPubKeyLock.Lock()
|
||||
v.attesterHistoryByPubKey = make(map[[48]byte]kv.EncHistoryData)
|
||||
v.attesterHistoryByPubKeyLock.Unlock()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ResetAttesterProtectionData reset validators protection data.
|
||||
func (v *validator) ResetAttesterProtectionData() {
|
||||
v.attesterHistoryByPubKeyLock.Lock()
|
||||
@@ -549,11 +535,11 @@ func (v *validator) ResetAttesterProtectionData() {
|
||||
// SaveProtection saves the attestation information currently in validator state.
|
||||
func (v *validator) SaveProtection(ctx context.Context, pubKey [48]byte) error {
|
||||
v.attesterHistoryByPubKeyLock.RLock()
|
||||
|
||||
defer v.attesterHistoryByPubKeyLock.RUnlock()
|
||||
if err := v.db.SaveAttestationHistoryForPubKeyV2(ctx, pubKey, v.attesterHistoryByPubKey[pubKey]); err != nil {
|
||||
return errors.Wrapf(err, "could not save attester with public key %#x history to DB", pubKey)
|
||||
}
|
||||
v.attesterHistoryByPubKeyLock.RUnlock()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -784,40 +784,6 @@ func TestUpdateProtections_OK(t *testing.T) {
|
||||
require.DeepEqual(t, history2, v.attesterHistoryByPubKey[pubKey2], "Unexpected retrieved history")
|
||||
}
|
||||
|
||||
func TestSaveProtections_OK(t *testing.T) {
|
||||
pubKey1 := [48]byte{1}
|
||||
pubKey2 := [48]byte{2}
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
client := mock.NewMockBeaconNodeValidatorClient(ctrl)
|
||||
db := dbTest.SetupDB(t, [][48]byte{pubKey1, pubKey2})
|
||||
ctx := context.Background()
|
||||
|
||||
cleanHistories, err := db.AttestationHistoryForPubKeysV2(context.Background(), [][48]byte{pubKey1, pubKey2})
|
||||
require.NoError(t, err)
|
||||
v := validator{
|
||||
db: db,
|
||||
validatorClient: client,
|
||||
attesterHistoryByPubKey: cleanHistories,
|
||||
}
|
||||
|
||||
history1 := cleanHistories[pubKey1]
|
||||
history1 = markAttestationForTargetEpoch(ctx, history1, 0, 1, [32]byte{1})
|
||||
|
||||
history2 := markAttestationForTargetEpoch(ctx, history1, 2, 3, [32]byte{2})
|
||||
|
||||
cleanHistories[pubKey1] = history1
|
||||
cleanHistories[pubKey2] = history2
|
||||
|
||||
v.attesterHistoryByPubKey = cleanHistories
|
||||
require.NoError(t, v.SaveProtections(context.Background()), "Could not update assignments")
|
||||
savedHistories, err := db.AttestationHistoryForPubKeysV2(context.Background(), [][48]byte{pubKey1, pubKey2})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.DeepEqual(t, history1, savedHistories[pubKey1], "Unexpected retrieved history")
|
||||
require.DeepEqual(t, history2, savedHistories[pubKey2], "Unexpected retrieved history")
|
||||
}
|
||||
|
||||
func TestSaveProtection_OK(t *testing.T) {
|
||||
pubKey1 := [48]byte{1}
|
||||
ctrl := gomock.NewController(t)
|
||||
@@ -835,7 +801,13 @@ func TestSaveProtection_OK(t *testing.T) {
|
||||
}
|
||||
|
||||
history1 := cleanHistories[pubKey1]
|
||||
history1 = markAttestationForTargetEpoch(ctx, history1, 0, 1, [32]byte{1})
|
||||
sr := [32]byte{1}
|
||||
newHist, err := kv.MarkAllAsAttestedSinceLatestWrittenEpoch(ctx, history1, 1, &kv.HistoryData{
|
||||
Source: 0,
|
||||
SigningRoot: sr[:],
|
||||
})
|
||||
require.NoError(t, err)
|
||||
history1 = newHist
|
||||
|
||||
cleanHistories[pubKey1] = history1
|
||||
|
||||
|
||||
@@ -6,9 +6,5 @@ go_library(
|
||||
importpath = "github.com/prysmaticlabs/prysm/validator/db/iface",
|
||||
# Other packages must use github.com/prysmaticlabs/prysm/validator/db.Database alias.
|
||||
visibility = ["//validator/db:__subpackages__"],
|
||||
deps = [
|
||||
"//proto/slashing:go_default_library",
|
||||
"//validator/db/kv:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
|
||||
],
|
||||
deps = ["//validator/db/kv:go_default_library"],
|
||||
)
|
||||
|
||||
@@ -5,8 +5,6 @@ import (
|
||||
"context"
|
||||
"io"
|
||||
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
slashpb "github.com/prysmaticlabs/prysm/proto/slashing"
|
||||
"github.com/prysmaticlabs/prysm/validator/db/kv"
|
||||
)
|
||||
|
||||
@@ -22,20 +20,19 @@ type ValidatorDB interface {
|
||||
SaveGenesisValidatorsRoot(ctx context.Context, genValRoot []byte) error
|
||||
|
||||
// Proposer protection related methods.
|
||||
ProposalHistoryForEpoch(ctx context.Context, publicKey []byte, epoch uint64) (bitfield.Bitlist, error)
|
||||
SaveProposalHistoryForEpoch(ctx context.Context, publicKey []byte, epoch uint64, history bitfield.Bitlist) error
|
||||
|
||||
// New data structure methods
|
||||
ProposalHistoryForSlot(ctx context.Context, publicKey []byte, slot uint64) ([]byte, error)
|
||||
SaveProposalHistoryForSlot(ctx context.Context, pubKey []byte, slot uint64, signingRoot []byte) error
|
||||
SaveProposalHistoryForPubKeysV2(ctx context.Context, proposals map[[48]byte]kv.ProposalHistoryForPubkey) error
|
||||
HighestSignedProposal(ctx context.Context, publicKey [48]byte) (uint64, error)
|
||||
LowestSignedProposal(ctx context.Context, publicKey [48]byte) (uint64, error)
|
||||
ProposalHistoryForSlot(ctx context.Context, publicKey [48]byte, slot uint64) ([32]byte, bool, error)
|
||||
SaveProposalHistoryForSlot(ctx context.Context, pubKey [48]byte, slot uint64, signingRoot []byte) error
|
||||
ProposedPublicKeys(ctx context.Context) ([][48]byte, error)
|
||||
|
||||
// Attester protection related methods.
|
||||
AttestationHistoryForPubKeys(ctx context.Context, publicKeys [][48]byte) (map[[48]byte]*slashpb.AttestationHistory, error)
|
||||
SaveAttestationHistoryForPubKeys(ctx context.Context, historyByPubKey map[[48]byte]*slashpb.AttestationHistory) error
|
||||
|
||||
// New attestation store methods.
|
||||
LowestSignedTargetEpoch(ctx context.Context, publicKey [48]byte) (uint64, error)
|
||||
LowestSignedSourceEpoch(ctx context.Context, publicKey [48]byte) (uint64, error)
|
||||
SaveLowestSignedTargetEpoch(ctx context.Context, publicKey [48]byte, epoch uint64) error
|
||||
SaveLowestSignedSourceEpoch(ctx context.Context, publicKey [48]byte, epoch uint64) error
|
||||
AttestationHistoryForPubKeysV2(ctx context.Context, publicKeys [][48]byte) (map[[48]byte]kv.EncHistoryData, error)
|
||||
SaveAttestationHistoryForPubKeysV2(ctx context.Context, historyByPubKeys map[[48]byte]kv.EncHistoryData) error
|
||||
SaveAttestationHistoryForPubKeyV2(ctx context.Context, pubKey [48]byte, history kv.EncHistoryData) error
|
||||
AttestedPublicKeys(ctx context.Context) ([][48]byte, error)
|
||||
}
|
||||
|
||||
@@ -4,12 +4,10 @@ load("@io_bazel_rules_go//go:def.bzl", "go_test")
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"attestation_history.go",
|
||||
"attestation_history_v2.go",
|
||||
"db.go",
|
||||
"genesis.go",
|
||||
"manage.go",
|
||||
"proposal_history.go",
|
||||
"historical_attestations.go",
|
||||
"proposal_history_v2.go",
|
||||
"schema.go",
|
||||
],
|
||||
@@ -17,15 +15,13 @@ go_library(
|
||||
visibility = ["//validator:__subpackages__"],
|
||||
deps = [
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//proto/slashing:go_default_library",
|
||||
"//shared/bytesutil:go_default_library",
|
||||
"//shared/fileutil:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"@com_github_gogo_protobuf//proto:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
|
||||
"@com_github_prometheus_client_golang//prometheus:go_default_library",
|
||||
"@com_github_prysmaticlabs_prombbolt//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@com_github_wealdtech_go_bytesutil//:go_default_library",
|
||||
"@io_etcd_go_bbolt//:go_default_library",
|
||||
"@io_opencensus_go//trace:go_default_library",
|
||||
],
|
||||
@@ -34,24 +30,17 @@ go_library(
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"attestation_history_test.go",
|
||||
"attestation_history_v2_test.go",
|
||||
"db_test.go",
|
||||
"genesis_test.go",
|
||||
"manage_test.go",
|
||||
"proposal_history_test.go",
|
||||
"historical_attestations_test.go",
|
||||
"proposal_history_v2_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//proto/slashing:go_default_library",
|
||||
"//shared/bytesutil:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"//shared/testutil/assert:go_default_library",
|
||||
"//shared/testutil/require:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
|
||||
"@io_etcd_go_bbolt//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
package kv
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/pkg/errors"
|
||||
slashpb "github.com/prysmaticlabs/prysm/proto/slashing"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
bolt "go.etcd.io/bbolt"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
func unmarshalAttestationHistory(ctx context.Context, enc []byte) (*slashpb.AttestationHistory, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "Validator.unmarshalAttestationHistory")
|
||||
defer span.End()
|
||||
|
||||
history := &slashpb.AttestationHistory{}
|
||||
if err := proto.Unmarshal(enc, history); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to unmarshal encoding")
|
||||
}
|
||||
return history, nil
|
||||
}
|
||||
|
||||
// AttestationHistoryForPubKeys accepts an array of validator public keys and returns a mapping of corresponding attestation history.
|
||||
func (store *Store) AttestationHistoryForPubKeys(ctx context.Context, publicKeys [][48]byte) (map[[48]byte]*slashpb.AttestationHistory, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "Validator.AttestationHistoryForPubKeys")
|
||||
defer span.End()
|
||||
|
||||
if len(publicKeys) == 0 {
|
||||
return make(map[[48]byte]*slashpb.AttestationHistory), nil
|
||||
}
|
||||
|
||||
var err error
|
||||
attestationHistoryForVals := make(map[[48]byte]*slashpb.AttestationHistory)
|
||||
err = store.view(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(historicAttestationsBucket)
|
||||
for _, key := range publicKeys {
|
||||
enc := bucket.Get(key[:])
|
||||
var attestationHistory *slashpb.AttestationHistory
|
||||
if len(enc) == 0 {
|
||||
newMap := make(map[uint64]uint64)
|
||||
newMap[0] = params.BeaconConfig().FarFutureEpoch
|
||||
attestationHistory = &slashpb.AttestationHistory{
|
||||
TargetToSource: newMap,
|
||||
}
|
||||
} else {
|
||||
attestationHistory, err = unmarshalAttestationHistory(ctx, enc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
attestationHistoryForVals[key] = attestationHistory
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return attestationHistoryForVals, err
|
||||
}
|
||||
|
||||
// SaveAttestationHistoryForPubKeys saves the attestation histories for the requested validator public keys.
|
||||
func (store *Store) SaveAttestationHistoryForPubKeys(ctx context.Context, historyByPubKeys map[[48]byte]*slashpb.AttestationHistory) error {
|
||||
ctx, span := trace.StartSpan(ctx, "Validator.SaveAttestationHistoryForPubKeys")
|
||||
defer span.End()
|
||||
|
||||
encoded := make(map[[48]byte][]byte)
|
||||
for pubKey, history := range historyByPubKeys {
|
||||
enc, err := proto.Marshal(history)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to encode attestation history")
|
||||
}
|
||||
encoded[pubKey] = enc
|
||||
}
|
||||
|
||||
err := store.update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(historicAttestationsBucket)
|
||||
for pubKey, encodedHistory := range encoded {
|
||||
if err := bucket.Put(pubKey[:], encodedHistory); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return err
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
package kv
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
slashpb "github.com/prysmaticlabs/prysm/proto/slashing"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
)
|
||||
|
||||
func TestAttestationHistoryForPubKeys_EmptyVals(t *testing.T) {
|
||||
pubkeys := [][48]byte{{30}, {25}, {20}}
|
||||
db := setupDB(t, pubkeys)
|
||||
|
||||
historyForPubKeys, err := db.AttestationHistoryForPubKeys(context.Background(), pubkeys)
|
||||
require.NoError(t, err)
|
||||
|
||||
newMap := make(map[uint64]uint64)
|
||||
newMap[0] = params.BeaconConfig().FarFutureEpoch
|
||||
clean := &slashpb.AttestationHistory{
|
||||
TargetToSource: newMap,
|
||||
}
|
||||
cleanAttHistoryForPubKeys := make(map[[48]byte]*slashpb.AttestationHistory)
|
||||
for _, pubKey := range pubkeys {
|
||||
cleanAttHistoryForPubKeys[pubKey] = clean
|
||||
}
|
||||
|
||||
require.DeepEqual(t, cleanAttHistoryForPubKeys, historyForPubKeys, "Expected attestation history epoch bits to be empty")
|
||||
}
|
||||
|
||||
func TestSaveAttestationHistory_OK(t *testing.T) {
|
||||
pubKeys := [][48]byte{{3}, {4}}
|
||||
db := setupDB(t, pubKeys)
|
||||
|
||||
farFuture := params.BeaconConfig().FarFutureEpoch
|
||||
newMap := make(map[uint64]uint64)
|
||||
// The validator attested at target epoch 2 but had no attestations for target epochs 0 and 1.
|
||||
newMap[0] = farFuture
|
||||
newMap[1] = farFuture
|
||||
newMap[2] = 1
|
||||
history := &slashpb.AttestationHistory{
|
||||
TargetToSource: newMap,
|
||||
LatestEpochWritten: 2,
|
||||
}
|
||||
|
||||
newMap2 := make(map[uint64]uint64)
|
||||
// The validator attested at target epoch 1 and 3 but had no attestations for target epochs 0 and 2.
|
||||
newMap2[0] = farFuture
|
||||
newMap2[1] = 0
|
||||
newMap2[2] = farFuture
|
||||
newMap2[3] = 2
|
||||
history2 := &slashpb.AttestationHistory{
|
||||
TargetToSource: newMap2,
|
||||
LatestEpochWritten: 3,
|
||||
}
|
||||
|
||||
attestationHistory := make(map[[48]byte]*slashpb.AttestationHistory)
|
||||
attestationHistory[pubKeys[0]] = history
|
||||
attestationHistory[pubKeys[1]] = history2
|
||||
|
||||
require.NoError(t, db.SaveAttestationHistoryForPubKeys(context.Background(), attestationHistory), "Saving attestation history failed")
|
||||
savedHistories, err := db.AttestationHistoryForPubKeys(context.Background(), pubKeys)
|
||||
require.NoError(t, err, "Failed to get attestation history")
|
||||
|
||||
require.NotNil(t, savedHistories)
|
||||
require.DeepEqual(t, attestationHistory, savedHistories, "Expected DB to keep object the same, received: %v", history)
|
||||
|
||||
savedHistory := savedHistories[pubKeys[0]]
|
||||
require.Equal(t, newMap[2], savedHistory.TargetToSource[2], "Expected target epoch %d to have the same marked source epoch", 2)
|
||||
require.Equal(t, newMap[1], savedHistory.TargetToSource[1], "Expected target epoch %d to have the same marked source epoch", 1)
|
||||
require.Equal(t, newMap[0], savedHistory.TargetToSource[0], "Expected target epoch %d to have the same marked source epoch", 0)
|
||||
|
||||
savedHistory = savedHistories[pubKeys[1]]
|
||||
require.Equal(t, newMap2[3], savedHistory.TargetToSource[3], "Expected target epoch %d to have the same marked source epoch", 3)
|
||||
require.Equal(t, newMap2[2], savedHistory.TargetToSource[2], "Expected target epoch %d to have the same marked source epoch", 2)
|
||||
require.Equal(t, newMap2[1], savedHistory.TargetToSource[1], "Expected target epoch %d to have the same marked source epoch", 1)
|
||||
}
|
||||
|
||||
func TestSaveAttestationHistory_Overwrites(t *testing.T) {
|
||||
db := setupDB(t, [][48]byte{})
|
||||
farFuture := params.BeaconConfig().FarFutureEpoch
|
||||
newMap1 := make(map[uint64]uint64)
|
||||
newMap1[0] = farFuture
|
||||
newMap1[1] = 0
|
||||
newMap2 := make(map[uint64]uint64)
|
||||
newMap2[0] = farFuture
|
||||
newMap2[1] = farFuture
|
||||
newMap2[2] = 1
|
||||
newMap3 := make(map[uint64]uint64)
|
||||
newMap3[0] = farFuture
|
||||
newMap3[1] = farFuture
|
||||
newMap3[2] = farFuture
|
||||
newMap3[3] = 2
|
||||
tests := []struct {
|
||||
pubkey [48]byte
|
||||
epoch uint64
|
||||
history *slashpb.AttestationHistory
|
||||
}{
|
||||
{
|
||||
pubkey: [48]byte{0},
|
||||
epoch: uint64(1),
|
||||
history: &slashpb.AttestationHistory{
|
||||
TargetToSource: newMap1,
|
||||
LatestEpochWritten: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
pubkey: [48]byte{0},
|
||||
epoch: uint64(2),
|
||||
history: &slashpb.AttestationHistory{
|
||||
TargetToSource: newMap2,
|
||||
LatestEpochWritten: 2,
|
||||
},
|
||||
},
|
||||
{
|
||||
pubkey: [48]byte{0},
|
||||
epoch: uint64(3),
|
||||
history: &slashpb.AttestationHistory{
|
||||
TargetToSource: newMap3,
|
||||
LatestEpochWritten: 3,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
attHistory := make(map[[48]byte]*slashpb.AttestationHistory)
|
||||
attHistory[tt.pubkey] = tt.history
|
||||
require.NoError(t, db.SaveAttestationHistoryForPubKeys(context.Background(), attHistory), "Saving attestation history failed")
|
||||
histories, err := db.AttestationHistoryForPubKeys(context.Background(), [][48]byte{tt.pubkey})
|
||||
require.NoError(t, err, "Failed to get attestation history")
|
||||
|
||||
history := histories[tt.pubkey]
|
||||
require.NotNil(t, history)
|
||||
require.DeepEqual(t, tt.history, history, "Expected DB to keep object the same")
|
||||
require.Equal(t, tt.epoch-1, history.TargetToSource[tt.epoch],
|
||||
"Expected target epoch %d to be marked with correct source epoch %d", tt.epoch, history.TargetToSource[tt.epoch])
|
||||
require.Equal(t, farFuture, history.TargetToSource[tt.epoch-1],
|
||||
"Expected target epoch %d to not be marked as attested for, received %d", tt.epoch-1, history.TargetToSource[tt.epoch-1])
|
||||
}
|
||||
}
|
||||
@@ -2,129 +2,28 @@ package kv
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
log "github.com/sirupsen/logrus"
|
||||
bolt "go.etcd.io/bbolt"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
const (
|
||||
// The size of each data entry in bytes for the source epoch (8 bytes) and signing root (32 bytes).
|
||||
uint64Size = 8
|
||||
latestEpochWrittenSize = uint64Size
|
||||
targetSize = uint64Size
|
||||
sourceSize = uint64Size
|
||||
signingRootSize = 32
|
||||
historySize = targetSize + sourceSize + signingRootSize
|
||||
minimalSize = latestEpochWrittenSize
|
||||
)
|
||||
|
||||
// HistoryData stores the needed data to confirm if an attestation is slashable
|
||||
// or repeated.
|
||||
type HistoryData struct {
|
||||
Source uint64
|
||||
SigningRoot []byte
|
||||
}
|
||||
|
||||
// EncHistoryData encapsulated history data.
|
||||
type EncHistoryData []byte
|
||||
|
||||
func (hd EncHistoryData) assertSize() error {
|
||||
if hd == nil || len(hd) < minimalSize {
|
||||
return fmt.Errorf("encapsulated data size: %d is smaller then minimal size: %d", len(hd), minimalSize)
|
||||
}
|
||||
if (len(hd)-minimalSize)%historySize != 0 {
|
||||
return fmt.Errorf("encapsulated data size: %d is not a multiple of entry size: %d", len(hd), historySize)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *HistoryData) IsEmpty() bool {
|
||||
if h == (*HistoryData)(nil) {
|
||||
return true
|
||||
}
|
||||
if h.Source == params.BeaconConfig().FarFutureEpoch {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func emptyHistoryData() *HistoryData {
|
||||
h := &HistoryData{Source: params.BeaconConfig().FarFutureEpoch, SigningRoot: bytesutil.PadTo([]byte{}, 32)}
|
||||
return h
|
||||
}
|
||||
|
||||
// NewAttestationHistoryArray creates a new encapsulated attestation history byte array
|
||||
// sized by the latest epoch written.
|
||||
func NewAttestationHistoryArray(target uint64) EncHistoryData {
|
||||
relativeTarget := target % params.BeaconConfig().WeakSubjectivityPeriod
|
||||
historyDataSize := (relativeTarget + 1) * historySize
|
||||
arraySize := latestEpochWrittenSize + historyDataSize
|
||||
en := make(EncHistoryData, arraySize)
|
||||
enc := en
|
||||
ctx := context.Background()
|
||||
// AttestedPublicKeys retrieves all public keys in our attestation history bucket.
|
||||
func (store *Store) AttestedPublicKeys(ctx context.Context) ([][48]byte, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "Validator.AttestedPublicKeys")
|
||||
defer span.End()
|
||||
var err error
|
||||
for i := uint64(0); i <= target%params.BeaconConfig().WeakSubjectivityPeriod; i++ {
|
||||
enc, err = enc.SetTargetData(ctx, i, emptyHistoryData())
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Failed to set empty target data")
|
||||
}
|
||||
}
|
||||
return enc
|
||||
}
|
||||
|
||||
func (hd EncHistoryData) GetLatestEpochWritten(ctx context.Context) (uint64, error) {
|
||||
if err := hd.assertSize(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return bytesutil.FromBytes8(hd[:latestEpochWrittenSize]), nil
|
||||
}
|
||||
|
||||
func (hd EncHistoryData) SetLatestEpochWritten(ctx context.Context, latestEpochWritten uint64) (EncHistoryData, error) {
|
||||
if err := hd.assertSize(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
copy(hd[:latestEpochWrittenSize], bytesutil.Uint64ToBytesLittleEndian(latestEpochWritten))
|
||||
return hd, nil
|
||||
}
|
||||
|
||||
func (hd EncHistoryData) GetTargetData(ctx context.Context, target uint64) (*HistoryData, error) {
|
||||
if err := hd.assertSize(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Cursor for the location to read target epoch from.
|
||||
// Modulus of target epoch X weak subjectivity period in order to have maximum size to the encapsulated data array.
|
||||
cursor := (target%params.BeaconConfig().WeakSubjectivityPeriod)*historySize + latestEpochWrittenSize
|
||||
if uint64(len(hd)) < cursor+historySize {
|
||||
return nil, nil
|
||||
}
|
||||
history := &HistoryData{}
|
||||
history.Source = bytesutil.FromBytes8(hd[cursor : cursor+sourceSize])
|
||||
sr := make([]byte, 32)
|
||||
copy(sr, hd[cursor+sourceSize:cursor+historySize])
|
||||
history.SigningRoot = sr
|
||||
return history, nil
|
||||
}
|
||||
|
||||
func (hd EncHistoryData) SetTargetData(ctx context.Context, target uint64, historyData *HistoryData) (EncHistoryData, error) {
|
||||
if err := hd.assertSize(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Cursor for the location to write target epoch to.
|
||||
// Modulus of target epoch X weak subjectivity period in order to have maximum size to the encapsulated data array.
|
||||
cursor := latestEpochWrittenSize + (target%params.BeaconConfig().WeakSubjectivityPeriod)*historySize
|
||||
|
||||
if uint64(len(hd)) < cursor+historySize {
|
||||
ext := make([]byte, cursor+historySize-uint64(len(hd)))
|
||||
hd = append(hd, ext...)
|
||||
}
|
||||
copy(hd[cursor:cursor+sourceSize], bytesutil.Uint64ToBytesLittleEndian(historyData.Source))
|
||||
copy(hd[cursor+sourceSize:cursor+sourceSize+signingRootSize], historyData.SigningRoot)
|
||||
return hd, nil
|
||||
attestedPublicKeys := make([][48]byte, 0)
|
||||
err = store.view(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(newHistoricAttestationsBucket)
|
||||
return bucket.ForEach(func(key []byte, _ []byte) error {
|
||||
pubKeyBytes := [48]byte{}
|
||||
copy(pubKeyBytes[:], key)
|
||||
attestedPublicKeys = append(attestedPublicKeys, pubKeyBytes)
|
||||
return nil
|
||||
})
|
||||
})
|
||||
return attestedPublicKeys, err
|
||||
}
|
||||
|
||||
// AttestationHistoryForPubKeysV2 accepts an array of validator public keys and returns a mapping of corresponding attestation history.
|
||||
@@ -146,7 +45,8 @@ func (store *Store) AttestationHistoryForPubKeysV2(ctx context.Context, publicKe
|
||||
if len(enc) == 0 {
|
||||
attestationHistory = NewAttestationHistoryArray(0)
|
||||
} else {
|
||||
attestationHistory = enc
|
||||
attestationHistory = make(EncHistoryData, len(enc))
|
||||
copy(attestationHistory, enc)
|
||||
}
|
||||
attestationHistoryForVals[key] = attestationHistory
|
||||
}
|
||||
@@ -185,96 +85,94 @@ func (store *Store) SaveAttestationHistoryForPubKeyV2(ctx context.Context, pubKe
|
||||
bucket := tx.Bucket(newHistoricAttestationsBucket)
|
||||
return bucket.Put(pubKey[:], history)
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// MigrateV2AttestationProtection import old attestation format data into the new attestation format
|
||||
func (store *Store) MigrateV2AttestationProtection(ctx context.Context) error {
|
||||
ctx, span := trace.StartSpan(ctx, "Validator.MigrateV2AttestationProtection")
|
||||
// LowestSignedSourceEpoch returns the lowest signed source epoch for a validator public key.
|
||||
// If no data exists, returning 0 is a sensible default.
|
||||
func (store *Store) LowestSignedSourceEpoch(ctx context.Context, publicKey [48]byte) (uint64, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "Validator.LowestSignedSourceEpoch")
|
||||
defer span.End()
|
||||
var allKeys [][48]byte
|
||||
|
||||
if err := store.db.View(func(tx *bolt.Tx) error {
|
||||
attestationsBucket := tx.Bucket(historicAttestationsBucket)
|
||||
if err := attestationsBucket.ForEach(func(pubKey, _ []byte) error {
|
||||
var pubKeyCopy [48]byte
|
||||
copy(pubKeyCopy[:], pubKey)
|
||||
allKeys = append(allKeys, pubKeyCopy)
|
||||
var err error
|
||||
var lowestSignedSourceEpoch uint64
|
||||
err = store.view(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(lowestSignedSourceBucket)
|
||||
lowestSignedSourceBytes := bucket.Get(publicKey[:])
|
||||
// 8 because bytesutil.BytesToUint64BigEndian will return 0 if input is less than 8 bytes.
|
||||
if len(lowestSignedSourceBytes) < 8 {
|
||||
return nil
|
||||
}); err != nil {
|
||||
return errors.Wrapf(err, "could not retrieve attestations for source in %s", store.databasePath)
|
||||
}
|
||||
|
||||
lowestSignedSourceEpoch = bytesutil.BytesToUint64BigEndian(lowestSignedSourceBytes)
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
allKeys = removeDuplicateKeys(allKeys)
|
||||
attMap, err := store.AttestationHistoryForPubKeys(ctx, allKeys)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not retrieve data for public keys %v", allKeys)
|
||||
}
|
||||
dataMap := make(map[[48]byte]EncHistoryData)
|
||||
for key, atts := range attMap {
|
||||
dataMap[key] = NewAttestationHistoryArray(atts.LatestEpochWritten)
|
||||
dataMap[key], err = dataMap[key].SetLatestEpochWritten(ctx, atts.LatestEpochWritten)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to set latest epoch while migrating attestations to v2")
|
||||
}
|
||||
for target, source := range atts.TargetToSource {
|
||||
dataMap[key], err = dataMap[key].SetTargetData(ctx, target, &HistoryData{
|
||||
Source: source,
|
||||
SigningRoot: []byte{1},
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to set target data while migrating attestations to v2")
|
||||
}
|
||||
}
|
||||
}
|
||||
err = store.SaveAttestationHistoryForPubKeysV2(ctx, dataMap)
|
||||
return err
|
||||
})
|
||||
return lowestSignedSourceEpoch, err
|
||||
}
|
||||
|
||||
// MigrateV2AttestationProtectionDb exports old attestation protection data
|
||||
// format to the new format and save the exported flag to database.
|
||||
func (store *Store) MigrateV2AttestationProtectionDb(ctx context.Context) error {
|
||||
ctx, span := trace.StartSpan(ctx, "Validator.MigrateV2AttestationProtectionDb")
|
||||
// LowestSignedTargetEpoch returns the lowest signed target epoch for a validator public key.
|
||||
// If no data exists, returning 0 is a sensible default.
|
||||
func (store *Store) LowestSignedTargetEpoch(ctx context.Context, publicKey [48]byte) (uint64, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "Validator.LowestSignedTargetEpoch")
|
||||
defer span.End()
|
||||
importAttestations, err := store.shouldMigrateAttestations()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to analyze whether attestations should be imported")
|
||||
}
|
||||
if !importAttestations {
|
||||
return nil
|
||||
}
|
||||
log.Info("Starting proposals protection db migration to v2...")
|
||||
err = store.MigrateV2AttestationProtection(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "filed to import attestations")
|
||||
}
|
||||
err = store.db.Update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(historicAttestationsBucket)
|
||||
if bucket != nil {
|
||||
if err := bucket.Put([]byte(attestationExported), []byte{1}); err != nil {
|
||||
return errors.Wrap(err, "failed to set migrated attestations flag in db")
|
||||
}
|
||||
|
||||
var err error
|
||||
var lowestSignedTargetEpoch uint64
|
||||
err = store.view(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(lowestSignedTargetBucket)
|
||||
lowestSignedTargetBytes := bucket.Get(publicKey[:])
|
||||
// 8 because bytesutil.BytesToUint64BigEndian will return 0 if input is less than 8 bytes.
|
||||
if len(lowestSignedTargetBytes) < 8 {
|
||||
return nil
|
||||
}
|
||||
lowestSignedTargetEpoch = bytesutil.BytesToUint64BigEndian(lowestSignedTargetBytes)
|
||||
return nil
|
||||
})
|
||||
log.Info("Finished proposals protection db migration to v2")
|
||||
return err
|
||||
return lowestSignedTargetEpoch, err
|
||||
}
|
||||
|
||||
func (store *Store) shouldMigrateAttestations() (bool, error) {
|
||||
var importAttestations bool
|
||||
err := store.db.View(func(tx *bolt.Tx) error {
|
||||
attestationBucket := tx.Bucket(historicAttestationsBucket)
|
||||
if attestationBucket != nil && attestationBucket.Stats().KeyN != 0 {
|
||||
if exported := attestationBucket.Get([]byte(attestationExported)); exported == nil {
|
||||
importAttestations = true
|
||||
// SaveLowestSignedSourceEpoch saves the lowest signed source epoch for a validator public key.
|
||||
func (store *Store) SaveLowestSignedSourceEpoch(ctx context.Context, publicKey [48]byte, epoch uint64) error {
|
||||
ctx, span := trace.StartSpan(ctx, "Validator.SaveLowestSignedSourceEpoch")
|
||||
defer span.End()
|
||||
|
||||
return store.update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(lowestSignedSourceBucket)
|
||||
|
||||
// If the incoming epoch is lower than the lowest signed epoch, override.
|
||||
lowestSignedSourceBytes := bucket.Get(publicKey[:])
|
||||
var lowestSignedSourceEpoch uint64
|
||||
if len(lowestSignedSourceBytes) >= 8 {
|
||||
lowestSignedSourceEpoch = bytesutil.BytesToUint64BigEndian(lowestSignedSourceBytes)
|
||||
}
|
||||
if len(lowestSignedSourceBytes) == 0 || epoch < lowestSignedSourceEpoch {
|
||||
if err := bucket.Put(publicKey[:], bytesutil.Uint64ToBytesBigEndian(epoch)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// SaveLowestSignedTargetEpoch saves the lowest signed target epoch for a validator public key.
|
||||
func (store *Store) SaveLowestSignedTargetEpoch(ctx context.Context, publicKey [48]byte, epoch uint64) error {
|
||||
ctx, span := trace.StartSpan(ctx, "Validator.SaveLowestSignedTargetEpoch")
|
||||
defer span.End()
|
||||
|
||||
return store.update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(lowestSignedTargetBucket)
|
||||
|
||||
// If the incoming epoch is lower than the lowest signed epoch, override.
|
||||
lowestSignedTargetBytes := bucket.Get(publicKey[:])
|
||||
var lowestSignedTargetEpoch uint64
|
||||
if len(lowestSignedTargetBytes) >= 8 {
|
||||
lowestSignedTargetEpoch = bytesutil.BytesToUint64BigEndian(lowestSignedTargetBytes)
|
||||
}
|
||||
if len(lowestSignedTargetBytes) == 0 || epoch < lowestSignedTargetEpoch {
|
||||
if err := bucket.Put(publicKey[:], bytesutil.Uint64ToBytesBigEndian(epoch)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return importAttestations, err
|
||||
}
|
||||
|
||||
@@ -4,131 +4,11 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
slashpb "github.com/prysmaticlabs/prysm/proto/slashing"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
bolt "go.etcd.io/bbolt"
|
||||
)
|
||||
|
||||
func TestNewAttestationHistoryArray(t *testing.T) {
|
||||
ba := NewAttestationHistoryArray(0)
|
||||
assert.Equal(t, latestEpochWrittenSize+historySize, len(ba))
|
||||
ba = NewAttestationHistoryArray(params.BeaconConfig().WeakSubjectivityPeriod - 1)
|
||||
assert.Equal(t, latestEpochWrittenSize+historySize*params.BeaconConfig().WeakSubjectivityPeriod, uint64(len(ba)))
|
||||
ba = NewAttestationHistoryArray(params.BeaconConfig().WeakSubjectivityPeriod)
|
||||
assert.Equal(t, latestEpochWrittenSize+historySize, len(ba))
|
||||
ba = NewAttestationHistoryArray(params.BeaconConfig().WeakSubjectivityPeriod + 1)
|
||||
assert.Equal(t, latestEpochWrittenSize+historySize+historySize, len(ba))
|
||||
|
||||
}
|
||||
|
||||
func TestSizeChecks(t *testing.T) {
|
||||
require.ErrorContains(t, "is smaller then minimal size", EncHistoryData{}.assertSize())
|
||||
require.NoError(t, EncHistoryData{0, 1, 2, 3, 4, 5, 6, 7}.assertSize())
|
||||
require.ErrorContains(t, "is not a multiple of entry size", EncHistoryData{0, 1, 2, 3, 4, 5, 6, 7, 8}.assertSize())
|
||||
require.NoError(t, NewAttestationHistoryArray(0).assertSize())
|
||||
require.NoError(t, NewAttestationHistoryArray(1).assertSize())
|
||||
require.NoError(t, NewAttestationHistoryArray(params.BeaconConfig().WeakSubjectivityPeriod).assertSize())
|
||||
require.NoError(t, NewAttestationHistoryArray(params.BeaconConfig().WeakSubjectivityPeriod-1).assertSize())
|
||||
}
|
||||
|
||||
func TestGetLatestEpochWritten(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ha := NewAttestationHistoryArray(0)
|
||||
ha[0] = 28
|
||||
lew, err := ha.GetLatestEpochWritten(ctx)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, uint64(28), lew)
|
||||
}
|
||||
|
||||
func TestSetLatestEpochWritten(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ha := NewAttestationHistoryArray(0)
|
||||
lew, err := ha.SetLatestEpochWritten(ctx, 2828282828)
|
||||
require.NoError(t, err)
|
||||
bytes := lew[:latestEpochWrittenSize]
|
||||
assert.Equal(t, uint64(2828282828), bytesutil.FromBytes8(bytes))
|
||||
}
|
||||
|
||||
func TestGetTargetData(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ha := NewAttestationHistoryArray(0)
|
||||
td, err := ha.GetTargetData(ctx, 0)
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, emptyHistoryData(), td)
|
||||
td, err = ha.GetTargetData(ctx, 1)
|
||||
require.NoError(t, err)
|
||||
var nilHist *HistoryData
|
||||
require.Equal(t, nilHist, td)
|
||||
}
|
||||
|
||||
func TestSetTargetData(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
type testStruct struct {
|
||||
name string
|
||||
enc EncHistoryData
|
||||
target uint64
|
||||
source uint64
|
||||
signingRoot []byte
|
||||
expected EncHistoryData
|
||||
error string
|
||||
}
|
||||
tests := []testStruct{
|
||||
{
|
||||
name: "empty enc",
|
||||
enc: EncHistoryData{},
|
||||
target: 0,
|
||||
source: 100,
|
||||
signingRoot: []byte{1, 2, 3},
|
||||
expected: (EncHistoryData)(nil),
|
||||
error: "encapsulated data size",
|
||||
},
|
||||
{
|
||||
name: "new enc",
|
||||
enc: NewAttestationHistoryArray(0),
|
||||
target: 0,
|
||||
source: 100,
|
||||
signingRoot: []byte{1, 2, 3},
|
||||
expected: EncHistoryData{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x64, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x2, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
|
||||
error: "",
|
||||
},
|
||||
{
|
||||
name: "higher target",
|
||||
enc: NewAttestationHistoryArray(0),
|
||||
target: 2,
|
||||
source: 100,
|
||||
signingRoot: []byte{1, 2, 3},
|
||||
expected: EncHistoryData{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x64, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x2, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
|
||||
error: "",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
enc, err := tt.enc.SetTargetData(ctx,
|
||||
tt.target,
|
||||
&HistoryData{
|
||||
Source: tt.source,
|
||||
SigningRoot: tt.signingRoot,
|
||||
})
|
||||
if tt.error == "" {
|
||||
require.NoError(t, err)
|
||||
td, err := enc.GetTargetData(ctx, tt.target)
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, bytesutil.PadTo(tt.signingRoot, 32), td.SigningRoot)
|
||||
require.Equal(t, tt.source, td.Source)
|
||||
return
|
||||
}
|
||||
assert.ErrorContains(t, tt.error, err)
|
||||
require.DeepEqual(t, tt.expected, enc)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestAttestationHistoryForPubKeysNew_EmptyVals(t *testing.T) {
|
||||
func TestAttestationHistoryForPubKeys_EmptyVals(t *testing.T) {
|
||||
pubkeys := [][48]byte{{30}, {25}, {20}}
|
||||
db := setupDB(t, pubkeys)
|
||||
historyForPubKeys, err := db.AttestationHistoryForPubKeysV2(context.Background(), pubkeys)
|
||||
@@ -141,7 +21,7 @@ func TestAttestationHistoryForPubKeysNew_EmptyVals(t *testing.T) {
|
||||
require.DeepEqual(t, cleanAttHistoryForPubKeys, historyForPubKeys, "Expected attestation history epoch bits to be empty")
|
||||
}
|
||||
|
||||
func TestAttestationHistoryForPubKeysNew_OK(t *testing.T) {
|
||||
func TestAttestationHistoryForPubKeys_OK(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
pubkeys := [][48]byte{{30}, {25}, {20}}
|
||||
db := setupDB(t, pubkeys)
|
||||
@@ -192,118 +72,106 @@ func TestAttestationHistoryForPubKey_OK(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, history, historyForPubKeys[pubkeys[0]], "Expected attestation history epoch bits to be empty")
|
||||
}
|
||||
|
||||
func TestStore_ImportOldAttestationFormatBadSourceFormat(t *testing.T) {
|
||||
func TestStore_AttestedPublicKeys(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
pubKeys := [][48]byte{{3}, {4}}
|
||||
db := setupDB(t, pubKeys)
|
||||
err := db.update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(historicAttestationsBucket)
|
||||
for _, pubKey := range pubKeys {
|
||||
if err := bucket.Put(pubKey[:], []byte{1}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
validatorDB, err := NewKVStore(t.TempDir(), nil)
|
||||
require.NoError(t, err, "Failed to instantiate DB")
|
||||
t.Cleanup(func() {
|
||||
require.NoError(t, validatorDB.Close(), "Failed to close database")
|
||||
require.NoError(t, validatorDB.ClearDB(), "Failed to clear database")
|
||||
})
|
||||
|
||||
keys, err := validatorDB.AttestedPublicKeys(ctx)
|
||||
require.NoError(t, err)
|
||||
require.ErrorContains(t, "could not retrieve data for public keys", db.MigrateV2AttestationProtection(ctx))
|
||||
assert.DeepEqual(t, make([][48]byte, 0), keys)
|
||||
|
||||
pubKey := [48]byte{1}
|
||||
err = validatorDB.SaveAttestationHistoryForPubKeyV2(ctx, pubKey, NewAttestationHistoryArray(0))
|
||||
require.NoError(t, err)
|
||||
|
||||
keys, err = validatorDB.AttestedPublicKeys(ctx)
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, [][48]byte{pubKey}, keys)
|
||||
}
|
||||
|
||||
func TestStore_ImportOldAttestationFormat(t *testing.T) {
|
||||
func TestLowestSignedSourceEpoch_SaveRetrieve(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
pubKeys := [][48]byte{{3}, {4}}
|
||||
db := setupDB(t, pubKeys)
|
||||
|
||||
farFuture := params.BeaconConfig().FarFutureEpoch
|
||||
newMap := make(map[uint64]uint64)
|
||||
// The validator attested at target epoch 2 but had no attestations for target epochs 0 and 1.
|
||||
newMap[0] = farFuture
|
||||
newMap[1] = farFuture
|
||||
newMap[2] = 1
|
||||
history := &slashpb.AttestationHistory{
|
||||
TargetToSource: newMap,
|
||||
LatestEpochWritten: 2,
|
||||
}
|
||||
|
||||
newMap2 := make(map[uint64]uint64)
|
||||
// The validator attested at target epoch 1 and 3 but had no attestations for target epochs 0 and 2.
|
||||
newMap2[0] = farFuture
|
||||
newMap2[1] = 0
|
||||
newMap2[2] = farFuture
|
||||
newMap2[3] = 2
|
||||
history2 := &slashpb.AttestationHistory{
|
||||
TargetToSource: newMap2,
|
||||
LatestEpochWritten: 3,
|
||||
}
|
||||
|
||||
attestationHistory := make(map[[48]byte]*slashpb.AttestationHistory)
|
||||
attestationHistory[pubKeys[0]] = history
|
||||
attestationHistory[pubKeys[1]] = history2
|
||||
|
||||
require.NoError(t, db.SaveAttestationHistoryForPubKeys(context.Background(), attestationHistory), "Saving attestation history failed")
|
||||
require.NoError(t, db.MigrateV2AttestationProtection(ctx), "Import attestation history failed")
|
||||
|
||||
attHis, err := db.AttestationHistoryForPubKeysV2(ctx, pubKeys)
|
||||
validatorDB, err := NewKVStore(t.TempDir(), nil)
|
||||
require.NoError(t, err, "Failed to instantiate DB")
|
||||
t.Cleanup(func() {
|
||||
require.NoError(t, validatorDB.Close(), "Failed to close database")
|
||||
require.NoError(t, validatorDB.ClearDB(), "Failed to clear database")
|
||||
})
|
||||
p0 := [48]byte{0}
|
||||
p1 := [48]byte{1}
|
||||
// Can save.
|
||||
require.NoError(t, validatorDB.SaveLowestSignedSourceEpoch(ctx, p0, 100))
|
||||
require.NoError(t, validatorDB.SaveLowestSignedSourceEpoch(ctx, p1, 200))
|
||||
got, err := validatorDB.LowestSignedSourceEpoch(ctx, p0)
|
||||
require.NoError(t, err)
|
||||
for pk, encHis := range attHis {
|
||||
his, ok := attestationHistory[pk]
|
||||
require.Equal(t, true, ok, "Missing public key in the original data")
|
||||
lew, err := encHis.GetLatestEpochWritten(ctx)
|
||||
require.NoError(t, err, "Failed to get latest epoch written")
|
||||
require.Equal(t, his.LatestEpochWritten, lew, "LatestEpochWritten is not equal to the source data value")
|
||||
for target, source := range his.TargetToSource {
|
||||
hd, err := encHis.GetTargetData(ctx, target)
|
||||
require.NoError(t, err, "Failed to get target data for epoch: %d", target)
|
||||
require.Equal(t, source, hd.Source, "Source epoch is different")
|
||||
require.DeepEqual(t, bytesutil.PadTo([]byte{1}, 32), hd.SigningRoot, "Signing root differs in imported data")
|
||||
}
|
||||
}
|
||||
require.Equal(t, uint64(100), got)
|
||||
got, err = validatorDB.LowestSignedSourceEpoch(ctx, p1)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(200), got)
|
||||
|
||||
// Can replace.
|
||||
require.NoError(t, validatorDB.SaveLowestSignedSourceEpoch(ctx, p0, 99))
|
||||
require.NoError(t, validatorDB.SaveLowestSignedSourceEpoch(ctx, p1, 199))
|
||||
got, err = validatorDB.LowestSignedSourceEpoch(ctx, p0)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(99), got)
|
||||
got, err = validatorDB.LowestSignedSourceEpoch(ctx, p1)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(199), got)
|
||||
|
||||
// Can not replace.
|
||||
require.NoError(t, validatorDB.SaveLowestSignedSourceEpoch(ctx, p0, 100))
|
||||
require.NoError(t, validatorDB.SaveLowestSignedSourceEpoch(ctx, p1, 200))
|
||||
got, err = validatorDB.LowestSignedSourceEpoch(ctx, p0)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(99), got)
|
||||
got, err = validatorDB.LowestSignedSourceEpoch(ctx, p1)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(199), got)
|
||||
}
|
||||
|
||||
func TestShouldImportAttestations(t *testing.T) {
|
||||
pubkey := [48]byte{3}
|
||||
db := setupDB(t, [][48]byte{pubkey})
|
||||
func TestLowestSignedTargetEpoch_SaveRetrieveReplace(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
validatorDB, err := NewKVStore(t.TempDir(), nil)
|
||||
require.NoError(t, err, "Failed to instantiate DB")
|
||||
t.Cleanup(func() {
|
||||
require.NoError(t, validatorDB.Close(), "Failed to close database")
|
||||
require.NoError(t, validatorDB.ClearDB(), "Failed to clear database")
|
||||
})
|
||||
p0 := [48]byte{0}
|
||||
p1 := [48]byte{1}
|
||||
// Can save.
|
||||
require.NoError(t, validatorDB.SaveLowestSignedTargetEpoch(ctx, p0, 100))
|
||||
require.NoError(t, validatorDB.SaveLowestSignedTargetEpoch(ctx, p1, 200))
|
||||
got, err := validatorDB.LowestSignedTargetEpoch(ctx, p0)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(100), got)
|
||||
got, err = validatorDB.LowestSignedTargetEpoch(ctx, p1)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(200), got)
|
||||
|
||||
shouldImport, err := db.shouldMigrateAttestations()
|
||||
// Can replace.
|
||||
require.NoError(t, validatorDB.SaveLowestSignedTargetEpoch(ctx, p0, 99))
|
||||
require.NoError(t, validatorDB.SaveLowestSignedTargetEpoch(ctx, p1, 199))
|
||||
got, err = validatorDB.LowestSignedTargetEpoch(ctx, p0)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, false, shouldImport, "Empty bucket should not be imported")
|
||||
newMap := make(map[uint64]uint64)
|
||||
newMap[2] = 1
|
||||
history := &slashpb.AttestationHistory{
|
||||
TargetToSource: newMap,
|
||||
LatestEpochWritten: 2,
|
||||
}
|
||||
attestationHistory := make(map[[48]byte]*slashpb.AttestationHistory)
|
||||
attestationHistory[pubkey] = history
|
||||
err = db.SaveAttestationHistoryForPubKeys(ctx, attestationHistory)
|
||||
require.Equal(t, uint64(99), got)
|
||||
got, err = validatorDB.LowestSignedTargetEpoch(ctx, p1)
|
||||
require.NoError(t, err)
|
||||
shouldImport, err = db.shouldMigrateAttestations()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, shouldImport, "Bucket with content should be imported")
|
||||
}
|
||||
require.Equal(t, uint64(199), got)
|
||||
|
||||
func TestStore_UpdateAttestationProtectionDb(t *testing.T) {
|
||||
pubkey := [48]byte{3}
|
||||
db := setupDB(t, [][48]byte{pubkey})
|
||||
ctx := context.Background()
|
||||
newMap := make(map[uint64]uint64)
|
||||
newMap[2] = 1
|
||||
history := &slashpb.AttestationHistory{
|
||||
TargetToSource: newMap,
|
||||
LatestEpochWritten: 2,
|
||||
}
|
||||
attestationHistory := make(map[[48]byte]*slashpb.AttestationHistory)
|
||||
attestationHistory[pubkey] = history
|
||||
err := db.SaveAttestationHistoryForPubKeys(ctx, attestationHistory)
|
||||
// Can not replace.
|
||||
require.NoError(t, validatorDB.SaveLowestSignedTargetEpoch(ctx, p0, 100))
|
||||
require.NoError(t, validatorDB.SaveLowestSignedTargetEpoch(ctx, p1, 200))
|
||||
got, err = validatorDB.LowestSignedTargetEpoch(ctx, p0)
|
||||
require.NoError(t, err)
|
||||
shouldImport, err := db.shouldMigrateAttestations()
|
||||
require.Equal(t, uint64(99), got)
|
||||
got, err = validatorDB.LowestSignedTargetEpoch(ctx, p1)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, shouldImport, "Bucket with content should be imported")
|
||||
err = db.MigrateV2AttestationProtectionDb(ctx)
|
||||
require.NoError(t, err)
|
||||
shouldImport, err = db.shouldMigrateAttestations()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, false, shouldImport, "Proposals should not be re-imported")
|
||||
require.Equal(t, uint64(199), got)
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
prombolt "github.com/prysmaticlabs/prombbolt"
|
||||
"github.com/prysmaticlabs/prysm/shared/fileutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
bolt "go.etcd.io/bbolt"
|
||||
@@ -14,9 +16,6 @@ import (
|
||||
// ProtectionDbFileName Validator slashing protection db file name.
|
||||
var ProtectionDbFileName = "validator.db"
|
||||
|
||||
const proposalExported = "PROPOSALS_IMPORTED"
|
||||
const attestationExported = "ATTESTATIONS_IMPORTED"
|
||||
|
||||
// Store defines an implementation of the Prysm Database interface
|
||||
// using BoltDB as the underlying persistent kv-store for eth2.
|
||||
type Store struct {
|
||||
@@ -26,6 +25,7 @@ type Store struct {
|
||||
|
||||
// Close closes the underlying boltdb database.
|
||||
func (store *Store) Close() error {
|
||||
prometheus.Unregister(createBoltCollector(store.db))
|
||||
return store.db.Close()
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ func (store *Store) ClearDB() error {
|
||||
if _, err := os.Stat(store.databasePath); os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
prometheus.Unregister(createBoltCollector(store.db))
|
||||
return os.Remove(filepath.Join(store.databasePath, ProtectionDbFileName))
|
||||
}
|
||||
|
||||
@@ -89,7 +90,11 @@ func NewKVStore(dirPath string, pubKeys [][48]byte) (*Store, error) {
|
||||
historicProposalsBucket,
|
||||
historicAttestationsBucket,
|
||||
newHistoricAttestationsBucket,
|
||||
newhistoricProposalsBucket,
|
||||
newHistoricProposalsBucket,
|
||||
lowestSignedSourceBucket,
|
||||
lowestSignedTargetBucket,
|
||||
lowestSignedProposalsBucket,
|
||||
highestSignedProposalsBucket,
|
||||
)
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
@@ -102,24 +107,22 @@ func NewKVStore(dirPath string, pubKeys [][48]byte) (*Store, error) {
|
||||
}
|
||||
}
|
||||
|
||||
err = prometheus.Register(createBoltCollector(kv.db))
|
||||
|
||||
return kv, err
|
||||
}
|
||||
|
||||
// GetKVStore returns the validator boltDB key-value store from directory. Returns nil if no such store exists.
|
||||
func GetKVStore(directory string) (*Store, error) {
|
||||
fileName := filepath.Join(directory, ProtectionDbFileName)
|
||||
if _, err := os.Stat(fileName); os.IsNotExist(err) {
|
||||
return nil, nil
|
||||
}
|
||||
boltDb, err := bolt.Open(fileName, params.BeaconIoConfig().ReadWritePermissions, &bolt.Options{Timeout: params.BeaconIoConfig().BoltTimeout})
|
||||
if err != nil {
|
||||
if errors.Is(err, bolt.ErrTimeout) {
|
||||
return nil, errors.New("cannot obtain database lock, database may be in use by another process")
|
||||
// UpdatePublicKeysBuckets for a specified list of keys.
|
||||
func (store *Store) UpdatePublicKeysBuckets(pubKeys [][48]byte) error {
|
||||
return store.update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(newHistoricProposalsBucket)
|
||||
for _, pubKey := range pubKeys {
|
||||
if _, err := bucket.CreateBucketIfNotExists(pubKey[:]); err != nil {
|
||||
return errors.Wrap(err, "failed to create proposal history bucket")
|
||||
}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Store{db: boltDb, databasePath: directory}, nil
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// Size returns the db size in bytes.
|
||||
@@ -131,3 +134,8 @@ func (store *Store) Size() (int64, error) {
|
||||
})
|
||||
return size, err
|
||||
}
|
||||
|
||||
// createBoltCollector returns a prometheus collector specifically configured for boltdb.
|
||||
func createBoltCollector(db *bolt.DB) prometheus.Collector {
|
||||
return prombolt.New("boltDB", db)
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
func setupDB(t testing.TB, pubkeys [][48]byte) *Store {
|
||||
db, err := NewKVStore(t.TempDir(), pubkeys)
|
||||
require.NoError(t, err, "Failed to instantiate DB")
|
||||
err = db.OldUpdatePublicKeysBuckets(pubkeys)
|
||||
err = db.UpdatePublicKeysBuckets(pubkeys)
|
||||
require.NoError(t, err, "Failed to create old buckets for public keys")
|
||||
t.Cleanup(func() {
|
||||
require.NoError(t, db.Close(), "Failed to close database")
|
||||
|
||||
170
validator/db/kv/historical_attestations.go
Normal file
170
validator/db/kv/historical_attestations.go
Normal file
@@ -0,0 +1,170 @@
|
||||
package kv
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const (
|
||||
// The size of each data entry in bytes for the source epoch (8 bytes) and signing root (32 bytes).
|
||||
uint64Size = 8
|
||||
latestEpochWrittenSize = uint64Size
|
||||
targetSize = uint64Size
|
||||
sourceSize = uint64Size
|
||||
signingRootSize = 32
|
||||
historySize = targetSize + sourceSize + signingRootSize
|
||||
minimalSize = latestEpochWrittenSize
|
||||
)
|
||||
|
||||
// HistoryData stores the needed data to confirm if an attestation is slashable
|
||||
// or repeated.
|
||||
type HistoryData struct {
|
||||
Source uint64
|
||||
SigningRoot []byte
|
||||
}
|
||||
|
||||
// EncHistoryData encapsulated history data.
|
||||
type EncHistoryData []byte
|
||||
|
||||
func (hd EncHistoryData) assertSize() error {
|
||||
if hd == nil || len(hd) < minimalSize {
|
||||
return fmt.Errorf("encapsulated data size: %d is smaller then minimal size: %d", len(hd), minimalSize)
|
||||
}
|
||||
if (len(hd)-minimalSize)%historySize != 0 {
|
||||
return fmt.Errorf("encapsulated data size: %d is not a multiple of entry size: %d", len(hd), historySize)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *HistoryData) IsEmpty() bool {
|
||||
if h == (*HistoryData)(nil) {
|
||||
return true
|
||||
}
|
||||
if h.Source == params.BeaconConfig().FarFutureEpoch {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func emptyHistoryData() *HistoryData {
|
||||
h := &HistoryData{Source: params.BeaconConfig().FarFutureEpoch, SigningRoot: bytesutil.PadTo([]byte{}, 32)}
|
||||
return h
|
||||
}
|
||||
|
||||
// NewAttestationHistoryArray creates a new encapsulated attestation history byte array
|
||||
// sized by the latest epoch written.
|
||||
func NewAttestationHistoryArray(target uint64) EncHistoryData {
|
||||
relativeTarget := target % params.BeaconConfig().WeakSubjectivityPeriod
|
||||
historyDataSize := (relativeTarget + 1) * historySize
|
||||
arraySize := latestEpochWrittenSize + historyDataSize
|
||||
en := make(EncHistoryData, arraySize)
|
||||
enc := en
|
||||
ctx := context.Background()
|
||||
var err error
|
||||
for i := uint64(0); i <= target%params.BeaconConfig().WeakSubjectivityPeriod; i++ {
|
||||
enc, err = enc.SetTargetData(ctx, i, emptyHistoryData())
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Failed to set empty target data")
|
||||
}
|
||||
}
|
||||
return enc
|
||||
}
|
||||
|
||||
func (hd EncHistoryData) GetLatestEpochWritten(ctx context.Context) (uint64, error) {
|
||||
if err := hd.assertSize(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return bytesutil.FromBytes8(hd[:latestEpochWrittenSize]), nil
|
||||
}
|
||||
|
||||
func (hd EncHistoryData) SetLatestEpochWritten(ctx context.Context, latestEpochWritten uint64) (EncHistoryData, error) {
|
||||
if err := hd.assertSize(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
copy(hd[:latestEpochWrittenSize], bytesutil.Uint64ToBytesLittleEndian(latestEpochWritten))
|
||||
return hd, nil
|
||||
}
|
||||
|
||||
func (hd EncHistoryData) GetTargetData(ctx context.Context, target uint64) (*HistoryData, error) {
|
||||
if err := hd.assertSize(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Cursor for the location to read target epoch from.
|
||||
// Modulus of target epoch X weak subjectivity period in order to have maximum size to the encapsulated data array.
|
||||
cursor := (target%params.BeaconConfig().WeakSubjectivityPeriod)*historySize + latestEpochWrittenSize
|
||||
if uint64(len(hd)) < cursor+historySize {
|
||||
return nil, nil
|
||||
}
|
||||
history := &HistoryData{}
|
||||
history.Source = bytesutil.FromBytes8(hd[cursor : cursor+sourceSize])
|
||||
sr := make([]byte, 32)
|
||||
copy(sr, hd[cursor+sourceSize:cursor+historySize])
|
||||
history.SigningRoot = sr
|
||||
return history, nil
|
||||
}
|
||||
|
||||
func (hd EncHistoryData) SetTargetData(ctx context.Context, target uint64, historyData *HistoryData) (EncHistoryData, error) {
|
||||
if err := hd.assertSize(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Cursor for the location to write target epoch to.
|
||||
// Modulus of target epoch X weak subjectivity period in order to have maximum size to the encapsulated data array.
|
||||
cursor := latestEpochWrittenSize + (target%params.BeaconConfig().WeakSubjectivityPeriod)*historySize
|
||||
|
||||
if uint64(len(hd)) < cursor+historySize {
|
||||
ext := make([]byte, cursor+historySize-uint64(len(hd)))
|
||||
hd = append(hd, ext...)
|
||||
}
|
||||
copy(hd[cursor:cursor+sourceSize], bytesutil.Uint64ToBytesLittleEndian(historyData.Source))
|
||||
copy(hd[cursor+sourceSize:cursor+sourceSize+signingRootSize], historyData.SigningRoot)
|
||||
|
||||
return hd, nil
|
||||
}
|
||||
|
||||
// MarkAllAsAttestedSinceLatestWrittenEpoch returns an attesting history with specified target+epoch pairs
|
||||
// since the latest written epoch up to the incoming attestation's target epoch as attested for.
|
||||
func MarkAllAsAttestedSinceLatestWrittenEpoch(
|
||||
ctx context.Context,
|
||||
hist EncHistoryData,
|
||||
incomingTarget uint64,
|
||||
incomingAtt *HistoryData,
|
||||
) (EncHistoryData, error) {
|
||||
wsPeriod := params.BeaconConfig().WeakSubjectivityPeriod
|
||||
latestEpochWritten, err := hist.GetLatestEpochWritten(ctx)
|
||||
if err != nil {
|
||||
return EncHistoryData{}, errors.Wrap(err, "could not get latest epoch written from history")
|
||||
}
|
||||
currentHD := hist
|
||||
if incomingTarget > latestEpochWritten {
|
||||
// If the target epoch to mark is ahead of latest written epoch, override the old targets and mark the requested epoch.
|
||||
// Limit the overwriting to one weak subjectivity period as further is not needed.
|
||||
maxToWrite := latestEpochWritten + wsPeriod
|
||||
for i := latestEpochWritten + 1; i < incomingTarget && i <= maxToWrite; i++ {
|
||||
newHD, err := hist.SetTargetData(ctx, i%wsPeriod, &HistoryData{
|
||||
Source: params.BeaconConfig().FarFutureEpoch,
|
||||
})
|
||||
if err != nil {
|
||||
return EncHistoryData{}, errors.Wrap(err, "could not set target data")
|
||||
}
|
||||
currentHD = newHD
|
||||
}
|
||||
newHD, err := currentHD.SetLatestEpochWritten(ctx, incomingTarget)
|
||||
if err != nil {
|
||||
return EncHistoryData{}, errors.Wrap(err, "could not set latest epoch written")
|
||||
}
|
||||
currentHD = newHD
|
||||
}
|
||||
newHD, err := currentHD.SetTargetData(ctx, incomingTarget%wsPeriod, &HistoryData{
|
||||
Source: incomingAtt.Source,
|
||||
SigningRoot: incomingAtt.SigningRoot,
|
||||
})
|
||||
if err != nil {
|
||||
return EncHistoryData{}, errors.Wrap(err, "could not set target data")
|
||||
}
|
||||
return newHD, nil
|
||||
}
|
||||
127
validator/db/kv/historical_attestations_test.go
Normal file
127
validator/db/kv/historical_attestations_test.go
Normal file
@@ -0,0 +1,127 @@
|
||||
package kv
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
)
|
||||
|
||||
func TestNewAttestationHistoryArray(t *testing.T) {
|
||||
ba := NewAttestationHistoryArray(0)
|
||||
assert.Equal(t, latestEpochWrittenSize+historySize, len(ba))
|
||||
ba = NewAttestationHistoryArray(params.BeaconConfig().WeakSubjectivityPeriod - 1)
|
||||
assert.Equal(t, latestEpochWrittenSize+historySize*params.BeaconConfig().WeakSubjectivityPeriod, uint64(len(ba)))
|
||||
ba = NewAttestationHistoryArray(params.BeaconConfig().WeakSubjectivityPeriod)
|
||||
assert.Equal(t, latestEpochWrittenSize+historySize, len(ba))
|
||||
ba = NewAttestationHistoryArray(params.BeaconConfig().WeakSubjectivityPeriod + 1)
|
||||
assert.Equal(t, latestEpochWrittenSize+historySize+historySize, len(ba))
|
||||
|
||||
}
|
||||
|
||||
func TestSizeChecks(t *testing.T) {
|
||||
require.ErrorContains(t, "is smaller then minimal size", EncHistoryData{}.assertSize())
|
||||
require.NoError(t, EncHistoryData{0, 1, 2, 3, 4, 5, 6, 7}.assertSize())
|
||||
require.ErrorContains(t, "is not a multiple of entry size", EncHistoryData{0, 1, 2, 3, 4, 5, 6, 7, 8}.assertSize())
|
||||
require.NoError(t, NewAttestationHistoryArray(0).assertSize())
|
||||
require.NoError(t, NewAttestationHistoryArray(1).assertSize())
|
||||
require.NoError(t, NewAttestationHistoryArray(params.BeaconConfig().WeakSubjectivityPeriod).assertSize())
|
||||
require.NoError(t, NewAttestationHistoryArray(params.BeaconConfig().WeakSubjectivityPeriod-1).assertSize())
|
||||
}
|
||||
|
||||
func TestGetLatestEpochWritten(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ha := NewAttestationHistoryArray(0)
|
||||
ha[0] = 28
|
||||
lew, err := ha.GetLatestEpochWritten(ctx)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, uint64(28), lew)
|
||||
}
|
||||
|
||||
func TestSetLatestEpochWritten(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ha := NewAttestationHistoryArray(0)
|
||||
lew, err := ha.SetLatestEpochWritten(ctx, 2828282828)
|
||||
require.NoError(t, err)
|
||||
bytes := lew[:latestEpochWrittenSize]
|
||||
assert.Equal(t, uint64(2828282828), bytesutil.FromBytes8(bytes))
|
||||
}
|
||||
|
||||
func TestGetTargetData(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ha := NewAttestationHistoryArray(0)
|
||||
td, err := ha.GetTargetData(ctx, 0)
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, emptyHistoryData(), td)
|
||||
td, err = ha.GetTargetData(ctx, 1)
|
||||
require.NoError(t, err)
|
||||
var nilHist *HistoryData
|
||||
require.Equal(t, nilHist, td)
|
||||
}
|
||||
|
||||
func TestSetTargetData(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
type testStruct struct {
|
||||
name string
|
||||
enc EncHistoryData
|
||||
target uint64
|
||||
source uint64
|
||||
signingRoot []byte
|
||||
expected EncHistoryData
|
||||
error string
|
||||
}
|
||||
tests := []testStruct{
|
||||
{
|
||||
name: "empty enc",
|
||||
enc: EncHistoryData{},
|
||||
target: 0,
|
||||
source: 100,
|
||||
signingRoot: []byte{1, 2, 3},
|
||||
expected: (EncHistoryData)(nil),
|
||||
error: "encapsulated data size",
|
||||
},
|
||||
{
|
||||
name: "new enc",
|
||||
enc: NewAttestationHistoryArray(0),
|
||||
target: 0,
|
||||
source: 100,
|
||||
signingRoot: []byte{1, 2, 3},
|
||||
expected: EncHistoryData{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x64, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x2, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
|
||||
error: "",
|
||||
},
|
||||
{
|
||||
name: "higher target",
|
||||
enc: NewAttestationHistoryArray(0),
|
||||
target: 2,
|
||||
source: 100,
|
||||
signingRoot: []byte{1, 2, 3},
|
||||
expected: EncHistoryData{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x64, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x2, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
|
||||
error: "",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
enc, err := tt.enc.SetTargetData(ctx,
|
||||
tt.target,
|
||||
&HistoryData{
|
||||
Source: tt.source,
|
||||
SigningRoot: tt.signingRoot,
|
||||
})
|
||||
if tt.error == "" {
|
||||
require.NoError(t, err)
|
||||
td, err := enc.GetTargetData(ctx, tt.target)
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, bytesutil.PadTo(tt.signingRoot, 32), td.SigningRoot)
|
||||
require.Equal(t, tt.source, td.Source)
|
||||
return
|
||||
}
|
||||
assert.ErrorContains(t, tt.error, err)
|
||||
require.DeepEqual(t, tt.expected, enc)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,322 +0,0 @@
|
||||
package kv
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
bolt "go.etcd.io/bbolt"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
var errFailedToCloseSource = errors.New("failed to close the source")
|
||||
var errFailedToCloseManySources = errors.New("failed to close one or more stores")
|
||||
|
||||
type epochProposals struct {
|
||||
Epoch []byte
|
||||
Proposals []byte
|
||||
}
|
||||
|
||||
type pubKeyProposals struct {
|
||||
PubKey [48]byte
|
||||
Proposals []epochProposals
|
||||
}
|
||||
|
||||
type pubKeyAttestations struct {
|
||||
PubKey [48]byte
|
||||
Attestations []byte
|
||||
}
|
||||
|
||||
// Merge merges data from sourceStores into a new store, which is created in targetDirectory.
|
||||
func Merge(ctx context.Context, sourceStores []*Store, targetDirectory string) error {
|
||||
ctx, span := trace.StartSpan(ctx, "Validator.Db.Merge")
|
||||
defer span.End()
|
||||
|
||||
allProposals, allAttestations, err := getAllProposalsAndAllAttestations(sourceStores)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return createMergeTargetStore(targetDirectory, allProposals, allAttestations)
|
||||
}
|
||||
|
||||
// Split splits data from sourceStore into several stores, one for each public key in sourceStore.
|
||||
// Each new store is created in its own subdirectory inside targetDirectory.
|
||||
func Split(ctx context.Context, sourceStore *Store, targetDirectory string) error {
|
||||
ctx, span := trace.StartSpan(ctx, "Validator.Db.Split")
|
||||
defer span.End()
|
||||
|
||||
allProposals, allAttestations, err := getAllProposalsAndAllAttestations([]*Store{sourceStore})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return createSplitTargetStores(targetDirectory, allProposals, allAttestations)
|
||||
}
|
||||
|
||||
func getPubKeyProposals(pubKey [48]byte, proposalsBucket *bolt.Bucket) (*pubKeyProposals, error) {
|
||||
pubKeyProposals := pubKeyProposals{
|
||||
PubKey: pubKey,
|
||||
Proposals: []epochProposals{},
|
||||
}
|
||||
|
||||
pubKeyBucket := proposalsBucket.Bucket(pubKey[:])
|
||||
if pubKeyBucket == nil {
|
||||
return &pubKeyProposals, nil
|
||||
}
|
||||
|
||||
if err := pubKeyBucket.ForEach(func(epoch, v []byte) error {
|
||||
epochProposals := epochProposals{
|
||||
Epoch: make([]byte, len(epoch)),
|
||||
Proposals: make([]byte, len(v)),
|
||||
}
|
||||
copy(epochProposals.Epoch, epoch)
|
||||
copy(epochProposals.Proposals, v)
|
||||
pubKeyProposals.Proposals = append(pubKeyProposals.Proposals, epochProposals)
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, errors.Wrapf(err, "could not retrieve proposals for public key %x", pubKey[:12])
|
||||
}
|
||||
|
||||
return &pubKeyProposals, nil
|
||||
}
|
||||
|
||||
func createMergeTargetStore(
|
||||
targetDirectory string,
|
||||
allProposals []pubKeyProposals,
|
||||
allAttestations []pubKeyAttestations) (err error) {
|
||||
|
||||
newStore, err := NewKVStore(targetDirectory, [][48]byte{})
|
||||
defer func() {
|
||||
if deferErr := newStore.Close(); deferErr != nil {
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, errFailedToCloseSource.Error())
|
||||
} else {
|
||||
err = errors.Wrap(deferErr, errFailedToCloseSource.Error())
|
||||
}
|
||||
|
||||
}
|
||||
}()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not initialize a new database in %s", targetDirectory)
|
||||
}
|
||||
|
||||
err = newStore.update(func(tx *bolt.Tx) error {
|
||||
allProposalsBucket := tx.Bucket(newhistoricProposalsBucket)
|
||||
for _, pubKeyProposals := range allProposals {
|
||||
proposalsBucket, err := createProposalsBucket(allProposalsBucket, pubKeyProposals.PubKey[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := addEpochProposals(proposalsBucket, pubKeyProposals.Proposals); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
attestationsBucket := tx.Bucket(historicAttestationsBucket)
|
||||
for _, attestations := range allAttestations {
|
||||
if err := addAttestations(attestationsBucket, attestations); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func createSplitTargetStores(
|
||||
targetDirectory string,
|
||||
allProposals []pubKeyProposals,
|
||||
allAttestations []pubKeyAttestations) (err error) {
|
||||
|
||||
var storesToClose []*Store
|
||||
defer func() {
|
||||
failedToClose := false
|
||||
for _, store := range storesToClose {
|
||||
if deferErr := store.Close(); deferErr != nil {
|
||||
failedToClose = true
|
||||
}
|
||||
}
|
||||
if failedToClose {
|
||||
if err != nil {
|
||||
err = errors.Wrapf(err, errFailedToCloseManySources.Error())
|
||||
} else {
|
||||
err = errFailedToCloseManySources
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
for _, pubKeyProposals := range allProposals {
|
||||
dirName := hex.EncodeToString(pubKeyProposals.PubKey[:])[:12]
|
||||
path := filepath.Join(targetDirectory, dirName)
|
||||
newStore, err := NewKVStore(path, [][48]byte{})
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not create a validator database in %s", path)
|
||||
}
|
||||
storesToClose = append(storesToClose, newStore)
|
||||
|
||||
if err := newStore.update(func(tx *bolt.Tx) error {
|
||||
allProposalsBucket := tx.Bucket(newhistoricProposalsBucket)
|
||||
proposalsBucket, err := createProposalsBucket(allProposalsBucket, pubKeyProposals.PubKey[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := addEpochProposals(proposalsBucket, pubKeyProposals.Proposals); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
attestationsBucket := tx.Bucket(historicAttestationsBucket)
|
||||
for _, pubKeyAttestations := range allAttestations {
|
||||
if string(pubKeyAttestations.PubKey[:]) == string(pubKeyProposals.PubKey[:]) {
|
||||
if err := addAttestations(attestationsBucket, pubKeyAttestations); err != nil {
|
||||
return err
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Create stores for attestations belonging to public keys that do not have proposals.
|
||||
for _, pubKeyAttestations := range allAttestations {
|
||||
var hasMatchingProposals = false
|
||||
for _, pubKeyProposals := range allProposals {
|
||||
if string(pubKeyAttestations.PubKey[:]) == string(pubKeyProposals.PubKey[:]) {
|
||||
hasMatchingProposals = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !hasMatchingProposals {
|
||||
dirName := hex.EncodeToString(pubKeyAttestations.PubKey[:])[:12]
|
||||
path := filepath.Join(targetDirectory, dirName)
|
||||
newStore, err := NewKVStore(path, [][48]byte{})
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not create a validator database in %s", path)
|
||||
}
|
||||
storesToClose = append(storesToClose, newStore)
|
||||
|
||||
if err := newStore.update(func(tx *bolt.Tx) error {
|
||||
attestationsBucket := tx.Bucket(historicAttestationsBucket)
|
||||
return addAttestations(attestationsBucket, pubKeyAttestations)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getAllProposalsAndAllAttestations(stores []*Store) ([]pubKeyProposals, []pubKeyAttestations, error) {
|
||||
var allProposals []pubKeyProposals
|
||||
var allAttestations []pubKeyAttestations
|
||||
|
||||
for _, store := range stores {
|
||||
// Storing keys upfront will allow using several short transactions (one for every key)
|
||||
// instead of one long-running transaction for all keys.
|
||||
var allKeys [][48]byte
|
||||
|
||||
if err := store.db.View(func(tx *bolt.Tx) error {
|
||||
proposalsBucket := tx.Bucket(newhistoricProposalsBucket)
|
||||
if err := proposalsBucket.ForEach(func(pubKey, _ []byte) error {
|
||||
var pubKeyCopy [48]byte
|
||||
copy(pubKeyCopy[:], pubKey)
|
||||
allKeys = append(allKeys, pubKeyCopy)
|
||||
return nil
|
||||
}); err != nil {
|
||||
return errors.Wrapf(err, "could not retrieve proposals for source in %s", store.databasePath)
|
||||
}
|
||||
|
||||
attestationsBucket := tx.Bucket(historicAttestationsBucket)
|
||||
if err := attestationsBucket.ForEach(func(pubKey, _ []byte) error {
|
||||
var pubKeyCopy [48]byte
|
||||
copy(pubKeyCopy[:], pubKey)
|
||||
allKeys = append(allKeys, pubKeyCopy)
|
||||
return nil
|
||||
}); err != nil {
|
||||
return errors.Wrapf(err, "could not retrieve attestations for source in %s", store.databasePath)
|
||||
}
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
allKeys = removeDuplicateKeys(allKeys)
|
||||
|
||||
for _, pubKey := range allKeys {
|
||||
if err := store.db.View(func(tx *bolt.Tx) error {
|
||||
proposalsBucket := tx.Bucket(newhistoricProposalsBucket)
|
||||
pubKeyProposals, err := getPubKeyProposals(pubKey, proposalsBucket)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
allProposals = append(allProposals, *pubKeyProposals)
|
||||
|
||||
attestationsBucket := tx.Bucket(historicAttestationsBucket)
|
||||
v := attestationsBucket.Get(pubKey[:])
|
||||
if v != nil {
|
||||
attestations := pubKeyAttestations{
|
||||
PubKey: pubKey,
|
||||
Attestations: make([]byte, len(v)),
|
||||
}
|
||||
copy(attestations.Attestations, v)
|
||||
allAttestations = append(allAttestations, attestations)
|
||||
}
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, nil, errors.Wrapf(err, "could not retrieve data for public key %x", pubKey[:12])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return allProposals, allAttestations, nil
|
||||
}
|
||||
|
||||
func createProposalsBucket(topLevelBucket *bolt.Bucket, pubKey []byte) (*bolt.Bucket, error) {
|
||||
var bucket, err = topLevelBucket.CreateBucket(pubKey)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not create proposals bucket for public key %x", pubKey[:12])
|
||||
}
|
||||
return bucket, nil
|
||||
}
|
||||
|
||||
func addEpochProposals(bucket *bolt.Bucket, proposals []epochProposals) error {
|
||||
for _, singleProposal := range proposals {
|
||||
if err := bucket.Put(singleProposal.Epoch, singleProposal.Proposals); err != nil {
|
||||
return errors.Wrapf(err, "could not add epoch proposals for epoch %v", singleProposal.Epoch)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func addAttestations(bucket *bolt.Bucket, attestations pubKeyAttestations) error {
|
||||
if err := bucket.Put(attestations.PubKey[:], attestations.Attestations); err != nil {
|
||||
return errors.Wrapf(
|
||||
err,
|
||||
"could not add public key attestations for public key %x",
|
||||
attestations.PubKey[:12])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func removeDuplicateKeys(keys [][48]byte) [][48]byte {
|
||||
last := 0
|
||||
|
||||
next:
|
||||
for _, k1 := range keys {
|
||||
for _, k2 := range keys[:last] {
|
||||
if k1 == k2 {
|
||||
continue next
|
||||
}
|
||||
}
|
||||
keys[last] = k1
|
||||
last++
|
||||
}
|
||||
|
||||
return keys[:last]
|
||||
}
|
||||
@@ -1,211 +0,0 @@
|
||||
package kv
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
slashpb "github.com/prysmaticlabs/prysm/proto/slashing"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
bolt "go.etcd.io/bbolt"
|
||||
)
|
||||
|
||||
type storeHistory struct {
|
||||
Proposals map[[48]byte][]byte
|
||||
Attestations map[[48]byte]map[uint64]uint64
|
||||
}
|
||||
|
||||
func TestMerge(t *testing.T) {
|
||||
firstStorePubKeys := [][48]byte{{1}, {2}}
|
||||
firstStore := setupDB(t, firstStorePubKeys)
|
||||
secondStorePubKeys := [][48]byte{{3}, {4}}
|
||||
secondStore := setupDB(t, secondStorePubKeys)
|
||||
|
||||
storeHistory1, err := prepareStore(firstStore, firstStorePubKeys)
|
||||
require.NoError(t, err)
|
||||
storeHistory2, err := prepareStore(secondStore, secondStorePubKeys)
|
||||
require.NoError(t, err)
|
||||
mergedProposals := make(map[[48]byte][]byte)
|
||||
for k, v := range storeHistory1.Proposals {
|
||||
mergedProposals[k] = v
|
||||
}
|
||||
for k, v := range storeHistory2.Proposals {
|
||||
mergedProposals[k] = v
|
||||
}
|
||||
mergedAttestations := make(map[[48]byte]map[uint64]uint64)
|
||||
for k, v := range storeHistory1.Attestations {
|
||||
mergedAttestations[k] = v
|
||||
}
|
||||
for k, v := range storeHistory2.Attestations {
|
||||
mergedAttestations[k] = v
|
||||
}
|
||||
mergedStoreHistory := storeHistory{
|
||||
Proposals: mergedProposals,
|
||||
Attestations: mergedAttestations,
|
||||
}
|
||||
|
||||
targetDirectory := t.TempDir() + "/target"
|
||||
|
||||
err = Merge(context.Background(), []*Store{firstStore, secondStore}, targetDirectory)
|
||||
require.NoError(t, err, "Merging failed")
|
||||
mergedStore, err := GetKVStore(targetDirectory)
|
||||
require.NoError(t, err, "Retrieving the merged store failed")
|
||||
|
||||
assertStore(
|
||||
t,
|
||||
mergedStore,
|
||||
append(firstStorePubKeys, secondStorePubKeys[0], secondStorePubKeys[1]),
|
||||
&mergedStoreHistory)
|
||||
}
|
||||
|
||||
func TestSplit(t *testing.T) {
|
||||
pubKey1 := [48]byte{1}
|
||||
pubKey2 := [48]byte{2}
|
||||
sourceStore := setupDB(t, [][48]byte{pubKey1, pubKey2})
|
||||
|
||||
storeHistory1, err := prepareStore(sourceStore, [][48]byte{pubKey1})
|
||||
require.NoError(t, err)
|
||||
storeHistory2, err := prepareStore(sourceStore, [][48]byte{pubKey2})
|
||||
require.NoError(t, err)
|
||||
|
||||
targetDirectory := t.TempDir() + "/target"
|
||||
|
||||
require.NoError(t, Split(context.Background(), sourceStore, targetDirectory), "Splitting failed")
|
||||
|
||||
encodedKey1 := hex.EncodeToString(pubKey1[:])[:12]
|
||||
keyStore1, err := GetKVStore(filepath.Join(targetDirectory, encodedKey1))
|
||||
require.NoError(t, err, "Retrieving the store for public key %v failed", encodedKey1)
|
||||
require.NotNil(t, keyStore1, "No store created for public key %v", encodedKey1)
|
||||
|
||||
encodedKey2 := hex.EncodeToString(pubKey2[:])[:12]
|
||||
keyStore2, err := GetKVStore(filepath.Join(targetDirectory, encodedKey2))
|
||||
require.NoError(t, err, "Retrieving the store for public key %v failed", encodedKey2)
|
||||
require.NotNil(t, keyStore2, "No store created for public key %v", encodedKey2)
|
||||
|
||||
err = keyStore1.view(func(tx *bolt.Tx) error {
|
||||
otherKeyProposalsBucket := tx.Bucket(newhistoricProposalsBucket).Bucket(pubKey2[:])
|
||||
require.Equal(t, (*bolt.Bucket)(nil), otherKeyProposalsBucket, "Store for public key %v contains proposals for another key", encodedKey2)
|
||||
otherKeyAttestationsBucket := tx.Bucket(historicAttestationsBucket).Bucket(pubKey2[:])
|
||||
require.Equal(t, (*bolt.Bucket)(nil), otherKeyAttestationsBucket, "Store for public key %v contains attestations for another key", encodedKey2)
|
||||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
err = keyStore2.view(func(tx *bolt.Tx) error {
|
||||
otherKeyProposalsBucket := tx.Bucket(newhistoricProposalsBucket).Bucket(pubKey1[:])
|
||||
require.Equal(t, (*bolt.Bucket)(nil), otherKeyProposalsBucket, "Store for public key %v contains proposals for another key", encodedKey1)
|
||||
otherKeyAttestationsBucket := tx.Bucket(historicAttestationsBucket).Bucket(pubKey1[:])
|
||||
require.Equal(t, (*bolt.Bucket)(nil), otherKeyAttestationsBucket, "Store for public key %v contains attestations for another key", encodedKey1)
|
||||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
assertStore(t, keyStore1, [][48]byte{pubKey1}, storeHistory1)
|
||||
assertStore(t, keyStore2, [][48]byte{pubKey2}, storeHistory2)
|
||||
}
|
||||
|
||||
func TestSplit_AttestationsWithoutMatchingProposalsAreSplit(t *testing.T) {
|
||||
pubKey1 := [48]byte{1}
|
||||
pubKey2 := [48]byte{2}
|
||||
sourceStore := setupDB(t, [][48]byte{pubKey1, pubKey2})
|
||||
|
||||
_, err := prepareStoreProposals(sourceStore, [][48]byte{pubKey1})
|
||||
require.NoError(t, err)
|
||||
attestationHistory, err := prepareStoreAttestations(sourceStore, [][48]byte{pubKey1, pubKey2})
|
||||
require.NoError(t, err)
|
||||
|
||||
targetDirectory := t.TempDir() + "/target"
|
||||
|
||||
require.NoError(t, Split(context.Background(), sourceStore, targetDirectory), "Splitting failed")
|
||||
|
||||
encodedKey1 := hex.EncodeToString(pubKey1[:])[:12]
|
||||
encodedKey2 := hex.EncodeToString(pubKey2[:])[:12]
|
||||
|
||||
attestationsOnlyKeyStore, err := GetKVStore(filepath.Join(targetDirectory, encodedKey2))
|
||||
require.NoError(t, err, "Retrieving the store failed")
|
||||
require.NotNil(t, attestationsOnlyKeyStore, "No store created for public key %v", encodedKey2)
|
||||
|
||||
err = attestationsOnlyKeyStore.view(func(tx *bolt.Tx) error {
|
||||
otherKeyProposalsBucket := tx.Bucket(newhistoricProposalsBucket).Bucket(pubKey1[:])
|
||||
require.Equal(t, (*bolt.Bucket)(nil), otherKeyProposalsBucket, "Store for public key %v contains proposals for another key", encodedKey1)
|
||||
otherKeyAttestationsBucket := tx.Bucket(historicAttestationsBucket).Bucket(pubKey1[:])
|
||||
require.Equal(t, (*bolt.Bucket)(nil), otherKeyAttestationsBucket, "Store for public key %v contains attestations for another key", encodedKey1)
|
||||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
splitAttestationsHistory, err :=
|
||||
attestationsOnlyKeyStore.AttestationHistoryForPubKeys(context.Background(), [][48]byte{pubKey2})
|
||||
require.NoError(t, err, "Retrieving attestation history failed for public key %v", encodedKey2)
|
||||
require.Equal(t, attestationHistory[pubKey2][0], splitAttestationsHistory[pubKey2].TargetToSource[0], "Attestations not merged correctly")
|
||||
}
|
||||
|
||||
func prepareStore(store *Store, pubKeys [][48]byte) (*storeHistory, error) {
|
||||
proposals, err := prepareStoreProposals(store, pubKeys)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
attestations, err := prepareStoreAttestations(store, pubKeys)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
history := storeHistory{
|
||||
Proposals: proposals,
|
||||
Attestations: attestations,
|
||||
}
|
||||
return &history, nil
|
||||
}
|
||||
|
||||
func prepareStoreProposals(store *Store, pubKeys [][48]byte) (map[[48]byte][]byte, error) {
|
||||
proposals := make(map[[48]byte][]byte)
|
||||
|
||||
for i, key := range pubKeys {
|
||||
signingRoot := bytesutil.PadTo([]byte{byte(i)}, 32)
|
||||
if err := store.SaveProposalHistoryForSlot(context.Background(), key[:], 0, signingRoot); err != nil {
|
||||
return nil, errors.Wrapf(err, "Saving proposal history failed")
|
||||
}
|
||||
proposals[key] = signingRoot
|
||||
}
|
||||
|
||||
return proposals, nil
|
||||
}
|
||||
|
||||
func prepareStoreAttestations(store *Store, pubKeys [][48]byte) (map[[48]byte]map[uint64]uint64, error) {
|
||||
storeAttestationHistory := make(map[[48]byte]*slashpb.AttestationHistory)
|
||||
attestations := make(map[[48]byte]map[uint64]uint64)
|
||||
|
||||
for i, key := range pubKeys {
|
||||
attestationHistoryMap := make(map[uint64]uint64)
|
||||
attestationHistoryMap[0] = uint64(i)
|
||||
attestationHistory := &slashpb.AttestationHistory{
|
||||
TargetToSource: attestationHistoryMap,
|
||||
LatestEpochWritten: 0,
|
||||
}
|
||||
storeAttestationHistory[key] = attestationHistory
|
||||
attestations[key] = attestationHistoryMap
|
||||
}
|
||||
if err := store.SaveAttestationHistoryForPubKeys(context.Background(), storeAttestationHistory); err != nil {
|
||||
return nil, errors.Wrapf(err, "Saving attestation history failed")
|
||||
}
|
||||
|
||||
return attestations, nil
|
||||
}
|
||||
|
||||
func assertStore(t *testing.T, store *Store, pubKeys [][48]byte, expectedHistory *storeHistory) {
|
||||
for _, key := range pubKeys {
|
||||
proposalHistory, err := store.ProposalHistoryForSlot(context.Background(), key[:], 0)
|
||||
require.NoError(t, err, "Retrieving proposal history failed for public key %v", key)
|
||||
expectedProposals := expectedHistory.Proposals[key]
|
||||
require.DeepEqual(t, expectedProposals, proposalHistory, "Proposals are incorrect")
|
||||
}
|
||||
|
||||
attestationHistory, err := store.AttestationHistoryForPubKeys(context.Background(), pubKeys)
|
||||
require.NoError(t, err, "Retrieving attestation history failed")
|
||||
for _, key := range pubKeys {
|
||||
expectedAttestations := expectedHistory.Attestations[key]
|
||||
require.Equal(t, expectedAttestations[0], attestationHistory[key].TargetToSource[0], "Attestations are incorrect")
|
||||
}
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
package kv
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/wealdtech/go-bytesutil"
|
||||
bolt "go.etcd.io/bbolt"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
// ProposalHistoryForPubkey for a validator public key.
|
||||
type ProposalHistoryForPubkey struct {
|
||||
Proposals []Proposal
|
||||
}
|
||||
|
||||
type Proposal struct {
|
||||
Slot uint64 `json:"slot"`
|
||||
SigningRoot []byte `json:"signing_root"`
|
||||
}
|
||||
|
||||
// ProposalHistoryForEpoch accepts a validator public key and returns the corresponding proposal history.
|
||||
// Returns nil if there is no proposal history for the validator.
|
||||
func (store *Store) ProposalHistoryForEpoch(ctx context.Context, publicKey []byte, epoch uint64) (bitfield.Bitlist, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "Validator.ProposalHistoryForEpoch")
|
||||
defer span.End()
|
||||
|
||||
var err error
|
||||
// Adding an extra byte for the bitlist length.
|
||||
slotBitlist := make(bitfield.Bitlist, params.BeaconConfig().SlotsPerEpoch/8+1)
|
||||
err = store.view(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(historicProposalsBucket)
|
||||
valBucket := bucket.Bucket(publicKey)
|
||||
if valBucket == nil {
|
||||
return fmt.Errorf("validator history empty for public key %#x", publicKey)
|
||||
}
|
||||
slotBits := valBucket.Get(bytesutil.Bytes8(epoch))
|
||||
if len(slotBits) == 0 {
|
||||
slotBitlist = bitfield.NewBitlist(params.BeaconConfig().SlotsPerEpoch)
|
||||
return nil
|
||||
}
|
||||
copy(slotBitlist, slotBits)
|
||||
return nil
|
||||
})
|
||||
return slotBitlist, err
|
||||
}
|
||||
|
||||
// SaveProposalHistoryForEpoch saves the proposal history for the requested validator public key.
|
||||
func (store *Store) SaveProposalHistoryForEpoch(ctx context.Context, pubKey []byte, epoch uint64, slotBits bitfield.Bitlist) error {
|
||||
ctx, span := trace.StartSpan(ctx, "Validator.SaveProposalHistoryForEpoch")
|
||||
defer span.End()
|
||||
|
||||
err := store.update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(historicProposalsBucket)
|
||||
valBucket := bucket.Bucket(pubKey)
|
||||
if valBucket == nil {
|
||||
return fmt.Errorf("validator history is empty for validator %#x", pubKey)
|
||||
}
|
||||
if err := valBucket.Put(bytesutil.Bytes8(epoch), slotBits); err != nil {
|
||||
return err
|
||||
}
|
||||
return pruneProposalHistory(valBucket, epoch)
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// UpdatePublicKeysBuckets for a specified list of keys.
|
||||
func (store *Store) OldUpdatePublicKeysBuckets(pubKeys [][48]byte) error {
|
||||
return store.update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(historicProposalsBucket)
|
||||
for _, pubKey := range pubKeys {
|
||||
if _, err := bucket.CreateBucketIfNotExists(pubKey[:]); err != nil {
|
||||
return errors.Wrap(err, "failed to create proposal history bucket")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func pruneProposalHistory(valBucket *bolt.Bucket, newestEpoch uint64) error {
|
||||
c := valBucket.Cursor()
|
||||
for k, _ := c.First(); k != nil; k, _ = c.First() {
|
||||
epoch := binary.LittleEndian.Uint64(k)
|
||||
// Only delete epochs that are older than the weak subjectivity period.
|
||||
if epoch+params.BeaconConfig().WeakSubjectivityPeriod <= newestEpoch {
|
||||
if err := c.Delete(); err != nil {
|
||||
return errors.Wrapf(err, "could not prune epoch %d in proposal history", epoch)
|
||||
}
|
||||
} else {
|
||||
// If starting from the oldest, we dont find anything prunable, stop pruning.
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,196 +0,0 @@
|
||||
package kv
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
)
|
||||
|
||||
func TestProposalHistoryForEpoch_InitializesNewPubKeys(t *testing.T) {
|
||||
pubkeys := [][48]byte{{30}, {25}, {20}}
|
||||
db := setupDB(t, pubkeys)
|
||||
|
||||
for _, pub := range pubkeys {
|
||||
slotBits, err := db.ProposalHistoryForEpoch(context.Background(), pub[:], 0)
|
||||
require.NoError(t, err)
|
||||
|
||||
cleanBits := bitfield.NewBitlist(params.BeaconConfig().SlotsPerEpoch)
|
||||
require.DeepEqual(t, cleanBits.Bytes(), slotBits.Bytes(), "Expected proposal history slot bits to be empty")
|
||||
}
|
||||
}
|
||||
|
||||
func TestProposalHistoryForEpoch_NilDB(t *testing.T) {
|
||||
valPubkey := [48]byte{1, 2, 3}
|
||||
db := setupDB(t, [][48]byte{})
|
||||
|
||||
_, err := db.ProposalHistoryForEpoch(context.Background(), valPubkey[:], 0)
|
||||
require.ErrorContains(t, "validator history empty for public key", err, "Unexpected error for nil DB")
|
||||
}
|
||||
|
||||
func TestSaveProposalHistoryForEpoch_OK(t *testing.T) {
|
||||
pubkey := [48]byte{3}
|
||||
db := setupDB(t, [][48]byte{pubkey})
|
||||
|
||||
epoch := uint64(2)
|
||||
slot := uint64(2)
|
||||
slotBits := bitfield.Bitlist{0x04, 0x00, 0x00, 0x00, 0x04}
|
||||
|
||||
err := db.SaveProposalHistoryForEpoch(context.Background(), pubkey[:], epoch, slotBits)
|
||||
require.NoError(t, err, "Saving proposal history failed: %v")
|
||||
savedBits, err := db.ProposalHistoryForEpoch(context.Background(), pubkey[:], epoch)
|
||||
require.NoError(t, err, "Failed to get proposal history")
|
||||
|
||||
require.NotNil(t, savedBits)
|
||||
require.DeepEqual(t, slotBits, savedBits, "Expected DB to keep object the same")
|
||||
require.Equal(t, true, savedBits.BitAt(slot), "Expected slot %d to be marked as proposed", slot)
|
||||
require.Equal(t, false, savedBits.BitAt(slot+1), "Expected slot %d to not be marked as proposed", slot+1)
|
||||
require.Equal(t, false, savedBits.BitAt(slot-1), "Expected slot %d to not be marked as proposed", slot-1)
|
||||
}
|
||||
|
||||
func TestSaveProposalHistoryForEpoch_Overwrites(t *testing.T) {
|
||||
pubkey := [48]byte{0}
|
||||
tests := []struct {
|
||||
slot uint64
|
||||
slotBits bitfield.Bitlist
|
||||
}{
|
||||
{
|
||||
slot: uint64(1),
|
||||
slotBits: bitfield.Bitlist{0x02, 0x00, 0x00, 0x00, 0x02},
|
||||
},
|
||||
{
|
||||
slot: uint64(2),
|
||||
slotBits: bitfield.Bitlist{0x04, 0x00, 0x00, 0x00, 0x04},
|
||||
},
|
||||
{
|
||||
slot: uint64(3),
|
||||
slotBits: bitfield.Bitlist{0x08, 0x00, 0x00, 0x00, 0x08},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
db := setupDB(t, [][48]byte{pubkey})
|
||||
err := db.SaveProposalHistoryForEpoch(context.Background(), pubkey[:], 0, tt.slotBits)
|
||||
require.NoError(t, err, "Saving proposal history failed")
|
||||
savedBits, err := db.ProposalHistoryForEpoch(context.Background(), pubkey[:], 0)
|
||||
require.NoError(t, err, "Failed to get proposal history")
|
||||
|
||||
require.NotNil(t, savedBits)
|
||||
require.DeepEqual(t, tt.slotBits, savedBits, "Expected DB to keep object the same")
|
||||
require.Equal(t, true, savedBits.BitAt(tt.slot), "Expected slot %d to be marked as proposed", tt.slot)
|
||||
require.Equal(t, false, savedBits.BitAt(tt.slot+1), "Expected slot %d to not be marked as proposed", tt.slot+1)
|
||||
require.Equal(t, false, savedBits.BitAt(tt.slot-1), "Expected slot %d to not be marked as proposed", tt.slot-1)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProposalHistoryForEpoch_MultipleEpochs(t *testing.T) {
|
||||
pubKey := [48]byte{0}
|
||||
tests := []struct {
|
||||
slots []uint64
|
||||
expectedBits []bitfield.Bitlist
|
||||
}{
|
||||
{
|
||||
slots: []uint64{1, 2, 8, 31},
|
||||
expectedBits: []bitfield.Bitlist{{0b00000110, 0b00000001, 0b00000000, 0b10000000, 0b00000001}},
|
||||
},
|
||||
{
|
||||
slots: []uint64{1, 33, 8},
|
||||
expectedBits: []bitfield.Bitlist{
|
||||
{0b00000010, 0b00000001, 0b00000000, 0b00000000, 0b00000001},
|
||||
{0b00000010, 0b00000000, 0b00000000, 0b00000000, 0b00000001},
|
||||
},
|
||||
},
|
||||
{
|
||||
slots: []uint64{2, 34, 36},
|
||||
expectedBits: []bitfield.Bitlist{
|
||||
{0b00000100, 0b00000000, 0b00000000, 0b00000000, 0b00000001},
|
||||
{0b00010100, 0b00000000, 0b00000000, 0b00000000, 0b00000001},
|
||||
},
|
||||
},
|
||||
{
|
||||
slots: []uint64{32, 33, 34},
|
||||
expectedBits: []bitfield.Bitlist{
|
||||
{0, 0, 0, 0, 1},
|
||||
{0b00000111, 0b00000000, 0b00000000, 0b00000000, 0b00000001},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
db := setupDB(t, [][48]byte{pubKey})
|
||||
for _, slot := range tt.slots {
|
||||
slotBits, err := db.ProposalHistoryForEpoch(context.Background(), pubKey[:], helpers.SlotToEpoch(slot))
|
||||
require.NoError(t, err, "Failed to get proposal history")
|
||||
slotBits.SetBitAt(slot%params.BeaconConfig().SlotsPerEpoch, true)
|
||||
err = db.SaveProposalHistoryForEpoch(context.Background(), pubKey[:], helpers.SlotToEpoch(slot), slotBits)
|
||||
require.NoError(t, err, "Saving proposal history failed")
|
||||
}
|
||||
|
||||
for i, slotBits := range tt.expectedBits {
|
||||
savedBits, err := db.ProposalHistoryForEpoch(context.Background(), pubKey[:], uint64(i))
|
||||
require.NoError(t, err, "Failed to get proposal history")
|
||||
require.DeepEqual(t, slotBits, savedBits, "Unexpected difference in bytes for slots %v", tt.slots)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPruneProposalHistory_OK(t *testing.T) {
|
||||
slotsPerEpoch := params.BeaconConfig().SlotsPerEpoch
|
||||
wsPeriod := params.BeaconConfig().WeakSubjectivityPeriod
|
||||
pubKey := [48]byte{0}
|
||||
tests := []struct {
|
||||
slots []uint64
|
||||
storedEpochs []uint64
|
||||
removedEpochs []uint64
|
||||
}{
|
||||
{
|
||||
// Go 2 epochs past pruning point.
|
||||
slots: []uint64{slotsPerEpoch / 2, slotsPerEpoch*5 + 6, (wsPeriod+3)*slotsPerEpoch + 8},
|
||||
storedEpochs: []uint64{5, 54003},
|
||||
removedEpochs: []uint64{0},
|
||||
},
|
||||
{
|
||||
// Go 10 epochs past pruning point.
|
||||
slots: []uint64{
|
||||
slotsPerEpoch + 4, slotsPerEpoch * 2,
|
||||
slotsPerEpoch * 3, slotsPerEpoch * 4,
|
||||
slotsPerEpoch * 5, (wsPeriod+10)*slotsPerEpoch + 8,
|
||||
},
|
||||
storedEpochs: []uint64{54010},
|
||||
removedEpochs: []uint64{1, 2, 3, 4},
|
||||
},
|
||||
{
|
||||
// Prune none.
|
||||
slots: []uint64{slotsPerEpoch + 4, slotsPerEpoch*2 + 3, slotsPerEpoch*3 + 4, slotsPerEpoch*4 + 3, slotsPerEpoch*5 + 3},
|
||||
storedEpochs: []uint64{1, 2, 3, 4, 5},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
db := setupDB(t, [][48]byte{pubKey})
|
||||
for _, slot := range tt.slots {
|
||||
slotBits, err := db.ProposalHistoryForEpoch(context.Background(), pubKey[:], helpers.SlotToEpoch(slot))
|
||||
require.NoError(t, err, "Failed to get proposal history")
|
||||
slotBits.SetBitAt(slot%params.BeaconConfig().SlotsPerEpoch, true)
|
||||
err = db.SaveProposalHistoryForEpoch(context.Background(), pubKey[:], helpers.SlotToEpoch(slot), slotBits)
|
||||
require.NoError(t, err, "Saving proposal history failed")
|
||||
}
|
||||
|
||||
for _, epoch := range tt.removedEpochs {
|
||||
savedBits, err := db.ProposalHistoryForEpoch(context.Background(), pubKey[:], epoch)
|
||||
require.NoError(t, err, "Failed to get proposal history")
|
||||
require.DeepEqual(t, bitfield.NewBitlist(slotsPerEpoch), savedBits, "Unexpected difference in bytes for epoch %d", epoch)
|
||||
}
|
||||
for _, epoch := range tt.storedEpochs {
|
||||
savedBits, err := db.ProposalHistoryForEpoch(context.Background(), pubKey[:], epoch)
|
||||
require.NoError(t, err, "Failed to get proposal history")
|
||||
if bytes.Equal(bitfield.NewBitlist(slotsPerEpoch), savedBits) {
|
||||
t.Fatalf("unexpected difference in bytes for epoch %d, expected %v vs received %v", epoch, bitfield.NewBitlist(slotsPerEpoch), savedBits)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,76 +5,109 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
log "github.com/sirupsen/logrus"
|
||||
bolt "go.etcd.io/bbolt"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
// ProposalHistoryForSlot accepts a validator public key and returns the corresponding signing root.
|
||||
// Returns nil if there is no proposal history for the validator at this slot.
|
||||
func (store *Store) ProposalHistoryForSlot(ctx context.Context, publicKey []byte, slot uint64) ([]byte, error) {
|
||||
// ProposalHistoryForPubkey for a validator public key.
|
||||
type ProposalHistoryForPubkey struct {
|
||||
Proposals []Proposal
|
||||
}
|
||||
|
||||
// Proposal representation for a validator public key.
|
||||
type Proposal struct {
|
||||
Slot uint64 `json:"slot"`
|
||||
SigningRoot []byte `json:"signing_root"`
|
||||
}
|
||||
|
||||
// ProposedPublicKeys retrieves all public keys in our proposals history bucket.
|
||||
func (store *Store) ProposedPublicKeys(ctx context.Context) ([][48]byte, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "Validator.ProposedPublicKeys")
|
||||
defer span.End()
|
||||
var err error
|
||||
proposedPublicKeys := make([][48]byte, 0)
|
||||
err = store.view(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(newHistoricProposalsBucket)
|
||||
return bucket.ForEach(func(key []byte, _ []byte) error {
|
||||
pubKeyBytes := [48]byte{}
|
||||
copy(pubKeyBytes[:], key)
|
||||
proposedPublicKeys = append(proposedPublicKeys, pubKeyBytes)
|
||||
return nil
|
||||
})
|
||||
})
|
||||
return proposedPublicKeys, err
|
||||
}
|
||||
|
||||
// ProposalHistoryForSlot accepts a validator public key and returns the corresponding signing root as well
|
||||
// as a boolean that tells us if we have a proposal history stored at the slot. It is possible we have proposed
|
||||
// a slot but stored a nil signing root, so the boolean helps give full information.
|
||||
func (store *Store) ProposalHistoryForSlot(ctx context.Context, publicKey [48]byte, slot uint64) ([32]byte, bool, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "Validator.ProposalHistoryForSlot")
|
||||
defer span.End()
|
||||
|
||||
var err error
|
||||
signingRoot := make([]byte, 32)
|
||||
err = store.view(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(newhistoricProposalsBucket)
|
||||
valBucket := bucket.Bucket(publicKey)
|
||||
if valBucket == nil {
|
||||
return fmt.Errorf("validator history empty for public key: %#x", publicKey)
|
||||
var proposalExists bool
|
||||
signingRoot := [32]byte{}
|
||||
err = store.update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(newHistoricProposalsBucket)
|
||||
valBucket, err := bucket.CreateBucketIfNotExists(publicKey[:])
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not create bucket for public key %#x", publicKey[:])
|
||||
}
|
||||
sr := valBucket.Get(bytesutil.Uint64ToBytesBigEndian(slot))
|
||||
if len(sr) == 0 {
|
||||
signingRootBytes := valBucket.Get(bytesutil.Uint64ToBytesBigEndian(slot))
|
||||
if signingRootBytes == nil {
|
||||
return nil
|
||||
}
|
||||
copy(signingRoot, sr)
|
||||
proposalExists = true
|
||||
copy(signingRoot[:], signingRootBytes)
|
||||
return nil
|
||||
})
|
||||
return signingRoot, err
|
||||
}
|
||||
|
||||
// SaveProposalHistoryForPubKeysV2 saves the proposal histories for the provided validator public keys.
|
||||
func (store *Store) SaveProposalHistoryForPubKeysV2(
|
||||
ctx context.Context,
|
||||
historyByPubKeys map[[48]byte]ProposalHistoryForPubkey,
|
||||
) error {
|
||||
ctx, span := trace.StartSpan(ctx, "Validator.SaveProposalHistoryForPubKeysV2")
|
||||
defer span.End()
|
||||
|
||||
err := store.update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(newhistoricProposalsBucket)
|
||||
for pubKey, history := range historyByPubKeys {
|
||||
valBucket, err := bucket.CreateBucketIfNotExists(pubKey[:])
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not create bucket for public key %#x", pubKey)
|
||||
}
|
||||
for _, proposal := range history.Proposals {
|
||||
if err := valBucket.Put(bytesutil.Uint64ToBytesBigEndian(proposal.Slot), proposal.SigningRoot); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return err
|
||||
return signingRoot, proposalExists, err
|
||||
}
|
||||
|
||||
// SaveProposalHistoryForSlot saves the proposal history for the requested validator public key.
|
||||
func (store *Store) SaveProposalHistoryForSlot(ctx context.Context, pubKey []byte, slot uint64, signingRoot []byte) error {
|
||||
// We also check if the incoming proposal slot is lower than the lowest signed proposal slot
|
||||
// for the validator and override its value on disk.
|
||||
func (store *Store) SaveProposalHistoryForSlot(ctx context.Context, pubKey [48]byte, slot uint64, signingRoot []byte) error {
|
||||
ctx, span := trace.StartSpan(ctx, "Validator.SaveProposalHistoryForEpoch")
|
||||
defer span.End()
|
||||
|
||||
err := store.update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(newhistoricProposalsBucket)
|
||||
valBucket, err := bucket.CreateBucketIfNotExists(pubKey)
|
||||
bucket := tx.Bucket(newHistoricProposalsBucket)
|
||||
valBucket, err := bucket.CreateBucketIfNotExists(pubKey[:])
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not create bucket for public key %#x", pubKey)
|
||||
}
|
||||
|
||||
// If the incoming slot is lower than the lowest signed proposal slot, override.
|
||||
lowestSignedBkt := tx.Bucket(lowestSignedProposalsBucket)
|
||||
lowestSignedProposalBytes := lowestSignedBkt.Get(pubKey[:])
|
||||
var lowestSignedProposalSlot uint64
|
||||
if len(lowestSignedProposalBytes) >= 8 {
|
||||
lowestSignedProposalSlot = bytesutil.BytesToUint64BigEndian(lowestSignedProposalBytes)
|
||||
}
|
||||
if len(lowestSignedProposalBytes) == 0 || slot < lowestSignedProposalSlot {
|
||||
if err := lowestSignedBkt.Put(pubKey[:], bytesutil.Uint64ToBytesBigEndian(slot)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// If the incoming slot is higher than the highest signed proposal slot, override.
|
||||
highestSignedBkt := tx.Bucket(highestSignedProposalsBucket)
|
||||
highestSignedProposalBytes := highestSignedBkt.Get(pubKey[:])
|
||||
var highestSignedProposalSlot uint64
|
||||
if len(highestSignedProposalBytes) >= 8 {
|
||||
highestSignedProposalSlot = bytesutil.BytesToUint64BigEndian(highestSignedProposalBytes)
|
||||
}
|
||||
if len(highestSignedProposalBytes) == 0 || slot > highestSignedProposalSlot {
|
||||
if err := highestSignedBkt.Put(pubKey[:], bytesutil.Uint64ToBytesBigEndian(slot)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := valBucket.Put(bytesutil.Uint64ToBytesBigEndian(slot), signingRoot); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -83,89 +116,46 @@ func (store *Store) SaveProposalHistoryForSlot(ctx context.Context, pubKey []byt
|
||||
return err
|
||||
}
|
||||
|
||||
// MigrateV2ProposalFormat accepts a validator public key and returns the corresponding signing root.
|
||||
// Returns nil if there is no proposal history for the validator at this slot.
|
||||
func (store *Store) MigrateV2ProposalFormat(ctx context.Context) error {
|
||||
ctx, span := trace.StartSpan(ctx, "Validator.MigrateV2ProposalFormat")
|
||||
// LowestSignedProposal returns the lowest signed proposal slot for a validator public key.
|
||||
// If no data exists, returning 0 is a sensible default.
|
||||
func (store *Store) LowestSignedProposal(ctx context.Context, publicKey [48]byte) (uint64, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "Validator.LowestSignedProposal")
|
||||
defer span.End()
|
||||
|
||||
var allKeys [][48]byte
|
||||
err := store.db.View(func(tx *bolt.Tx) error {
|
||||
proposalsBucket := tx.Bucket(historicProposalsBucket)
|
||||
if err := proposalsBucket.ForEach(func(pubKey, _ []byte) error {
|
||||
var pubKeyCopy [48]byte
|
||||
copy(pubKeyCopy[:], pubKey)
|
||||
allKeys = append(allKeys, pubKeyCopy)
|
||||
var err error
|
||||
var lowestSignedProposalSlot uint64
|
||||
err = store.view(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(lowestSignedProposalsBucket)
|
||||
lowestSignedProposalBytes := bucket.Get(publicKey[:])
|
||||
// 8 because bytesutil.BytesToUint64BigEndian will return 0 if input is less than 8 bytes.
|
||||
if len(lowestSignedProposalBytes) < 8 {
|
||||
return nil
|
||||
}); err != nil {
|
||||
return errors.Wrapf(err, "could not retrieve proposals for source in %s", store.databasePath)
|
||||
}
|
||||
lowestSignedProposalSlot = bytesutil.BytesToUint64BigEndian(lowestSignedProposalBytes)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
allKeys = removeDuplicateKeys(allKeys)
|
||||
var prs []*pubKeyProposals
|
||||
err = store.db.View(func(tx *bolt.Tx) error {
|
||||
proposalsBucket := tx.Bucket(historicProposalsBucket)
|
||||
for _, pk := range allKeys {
|
||||
pr, err := getPubKeyProposals(pk, proposalsBucket)
|
||||
prs = append(prs, pr)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not retrieve public key old proposals format")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = store.db.Update(func(tx *bolt.Tx) error {
|
||||
newProposalsBucket := tx.Bucket(newhistoricProposalsBucket)
|
||||
for _, pr := range prs {
|
||||
valBucket, err := newProposalsBucket.CreateBucketIfNotExists(pr.PubKey[:])
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not could not create bucket for public key")
|
||||
}
|
||||
for _, epochProposals := range pr.Proposals {
|
||||
// Adding an extra byte for the bitlist length.
|
||||
slotBitlist := make(bitfield.Bitlist, params.BeaconConfig().SlotsPerEpoch/8+1)
|
||||
slotBits := epochProposals.Proposals
|
||||
if len(slotBits) == 0 {
|
||||
continue
|
||||
}
|
||||
copy(slotBitlist, slotBits)
|
||||
for i := uint64(0); i < params.BeaconConfig().SlotsPerEpoch; i++ {
|
||||
if slotBitlist.BitAt(i) {
|
||||
ss, err := helpers.StartSlot(bytesutil.FromBytes8(epochProposals.Epoch))
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get start slot of epoch: %d", epochProposals.Epoch)
|
||||
}
|
||||
if err := valBucket.Put(bytesutil.Uint64ToBytesBigEndian(ss+i), []byte{1}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return err
|
||||
return lowestSignedProposalSlot, err
|
||||
}
|
||||
|
||||
// UpdatePublicKeysBuckets for a specified list of keys.
|
||||
func (store *Store) UpdatePublicKeysBuckets(pubKeys [][48]byte) error {
|
||||
return store.update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(newhistoricProposalsBucket)
|
||||
for _, pubKey := range pubKeys {
|
||||
if _, err := bucket.CreateBucketIfNotExists(pubKey[:]); err != nil {
|
||||
return errors.Wrap(err, "failed to create proposal history bucket")
|
||||
}
|
||||
// HighestSignedProposal returns the highest signed proposal slot for a validator public key.
|
||||
// If no data exists, returning 0 is a sensible default.
|
||||
func (store *Store) HighestSignedProposal(ctx context.Context, publicKey [48]byte) (uint64, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "Validator.HighestSignedProposal")
|
||||
defer span.End()
|
||||
|
||||
var err error
|
||||
var highestSignedProposalSlot uint64
|
||||
err = store.view(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(highestSignedProposalsBucket)
|
||||
highestSignedProposalBytes := bucket.Get(publicKey[:])
|
||||
// 8 because bytesutil.BytesToUint64BigEndian will return 0 if input is less than 8 bytes.
|
||||
if len(highestSignedProposalBytes) < 8 {
|
||||
return nil
|
||||
}
|
||||
highestSignedProposalSlot = bytesutil.BytesToUint64BigEndian(highestSignedProposalBytes)
|
||||
return nil
|
||||
})
|
||||
return highestSignedProposalSlot, err
|
||||
}
|
||||
|
||||
func pruneProposalHistoryBySlot(valBucket *bolt.Bucket, newestSlot uint64) error {
|
||||
@@ -186,45 +176,3 @@ func pruneProposalHistoryBySlot(valBucket *bolt.Bucket, newestSlot uint64) error
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MigrateV2ProposalsProtectionDb exports old proposal protection data format to the
|
||||
// new format and save the exported flag to database.
|
||||
func (store *Store) MigrateV2ProposalsProtectionDb(ctx context.Context) error {
|
||||
importProposals, err := store.shouldImportProposals()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !importProposals {
|
||||
return nil
|
||||
}
|
||||
log.Info("Starting proposals protection db migration to v2...")
|
||||
if err := store.MigrateV2ProposalFormat(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
err = store.db.Update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(historicProposalsBucket)
|
||||
if bucket != nil {
|
||||
if err := bucket.Put([]byte(proposalExported), []byte{1}); err != nil {
|
||||
return errors.Wrap(err, "failed to set exported proposals flag in db")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
log.Info("Finished proposals protection db migration to v2")
|
||||
return err
|
||||
}
|
||||
|
||||
func (store *Store) shouldImportProposals() (bool, error) {
|
||||
var importProposals bool
|
||||
err := store.db.View(func(tx *bolt.Tx) error {
|
||||
proposalBucket := tx.Bucket(historicProposalsBucket)
|
||||
if proposalBucket != nil && proposalBucket.Stats().KeyN != 0 {
|
||||
if exported := proposalBucket.Get([]byte(proposalExported)); exported == nil {
|
||||
importProposals = true
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return importProposals, err
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
)
|
||||
|
||||
@@ -15,19 +15,20 @@ func TestProposalHistoryForSlot_InitializesNewPubKeys(t *testing.T) {
|
||||
db := setupDB(t, pubkeys)
|
||||
|
||||
for _, pub := range pubkeys {
|
||||
signingRoot, err := db.ProposalHistoryForSlot(context.Background(), pub[:], 0)
|
||||
signingRoot, _, err := db.ProposalHistoryForSlot(context.Background(), pub, 0)
|
||||
require.NoError(t, err)
|
||||
expected := bytesutil.PadTo([]byte{}, 32)
|
||||
require.DeepEqual(t, expected, signingRoot, "Expected proposal history slot signing root to be empty")
|
||||
require.DeepEqual(t, expected, signingRoot[:], "Expected proposal history slot signing root to be empty")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewProposalHistoryForSlot_NilDB(t *testing.T) {
|
||||
func TestNewProposalHistoryForSlot_ReturnsNilIfNoHistory(t *testing.T) {
|
||||
valPubkey := [48]byte{1, 2, 3}
|
||||
db := setupDB(t, [][48]byte{})
|
||||
|
||||
_, err := db.ProposalHistoryForSlot(context.Background(), valPubkey[:], 0)
|
||||
require.ErrorContains(t, "validator history empty for public key", err, "Unexpected error for nil DB")
|
||||
_, proposalExists, err := db.ProposalHistoryForSlot(context.Background(), valPubkey, 0)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, false, proposalExists)
|
||||
}
|
||||
|
||||
func TestSaveProposalHistoryForSlot_OK(t *testing.T) {
|
||||
@@ -36,13 +37,13 @@ func TestSaveProposalHistoryForSlot_OK(t *testing.T) {
|
||||
|
||||
slot := uint64(2)
|
||||
|
||||
err := db.SaveProposalHistoryForSlot(context.Background(), pubkey[:], slot, []byte{1})
|
||||
err := db.SaveProposalHistoryForSlot(context.Background(), pubkey, slot, []byte{1})
|
||||
require.NoError(t, err, "Saving proposal history failed: %v")
|
||||
signingRoot, err := db.ProposalHistoryForSlot(context.Background(), pubkey[:], slot)
|
||||
signingRoot, _, err := db.ProposalHistoryForSlot(context.Background(), pubkey, slot)
|
||||
require.NoError(t, err, "Failed to get proposal history")
|
||||
|
||||
require.NotNil(t, signingRoot)
|
||||
require.DeepEqual(t, bytesutil.PadTo([]byte{1}, 32), signingRoot, "Expected DB to keep object the same")
|
||||
require.DeepEqual(t, bytesutil.PadTo([]byte{1}, 32), signingRoot[:], "Expected DB to keep object the same")
|
||||
}
|
||||
|
||||
func TestSaveProposalHistoryForSlot_Empty(t *testing.T) {
|
||||
@@ -51,13 +52,13 @@ func TestSaveProposalHistoryForSlot_Empty(t *testing.T) {
|
||||
|
||||
slot := uint64(2)
|
||||
emptySlot := uint64(120)
|
||||
err := db.SaveProposalHistoryForSlot(context.Background(), pubkey[:], slot, []byte{1})
|
||||
err := db.SaveProposalHistoryForSlot(context.Background(), pubkey, slot, []byte{1})
|
||||
require.NoError(t, err, "Saving proposal history failed: %v")
|
||||
signingRoot, err := db.ProposalHistoryForSlot(context.Background(), pubkey[:], emptySlot)
|
||||
signingRoot, _, err := db.ProposalHistoryForSlot(context.Background(), pubkey, emptySlot)
|
||||
require.NoError(t, err, "Failed to get proposal history")
|
||||
|
||||
require.NotNil(t, signingRoot)
|
||||
require.DeepEqual(t, bytesutil.PadTo([]byte{}, 32), signingRoot, "Expected DB to keep object the same")
|
||||
require.DeepEqual(t, bytesutil.PadTo([]byte{}, 32), signingRoot[:], "Expected DB to keep object the same")
|
||||
}
|
||||
|
||||
func TestSaveProposalHistoryForSlot_Overwrites(t *testing.T) {
|
||||
@@ -82,13 +83,14 @@ func TestSaveProposalHistoryForSlot_Overwrites(t *testing.T) {
|
||||
|
||||
for _, tt := range tests {
|
||||
db := setupDB(t, [][48]byte{pubkey})
|
||||
err := db.SaveProposalHistoryForSlot(context.Background(), pubkey[:], 0, tt.signingRoot)
|
||||
err := db.SaveProposalHistoryForSlot(context.Background(), pubkey, 0, tt.signingRoot)
|
||||
require.NoError(t, err, "Saving proposal history failed")
|
||||
signingRoot, err := db.ProposalHistoryForSlot(context.Background(), pubkey[:], 0)
|
||||
signingRoot, _, err := db.ProposalHistoryForSlot(context.Background(), pubkey, 0)
|
||||
require.NoError(t, err, "Failed to get proposal history")
|
||||
|
||||
require.NotNil(t, signingRoot)
|
||||
require.DeepEqual(t, tt.signingRoot, signingRoot, "Expected DB to keep object the same")
|
||||
require.DeepEqual(t, tt.signingRoot, signingRoot[:], "Expected DB to keep object the same")
|
||||
require.NoError(t, db.Close(), "Failed to close database")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,89 +139,119 @@ func TestPruneProposalHistoryBySlot_OK(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
db := setupDB(t, [][48]byte{pubKey})
|
||||
for _, slot := range tt.slots {
|
||||
err := db.SaveProposalHistoryForSlot(context.Background(), pubKey[:], slot, signedRoot)
|
||||
err := db.SaveProposalHistoryForSlot(context.Background(), pubKey, slot, signedRoot)
|
||||
require.NoError(t, err, "Saving proposal history failed")
|
||||
}
|
||||
|
||||
for _, slot := range tt.removedSlots {
|
||||
sr, err := db.ProposalHistoryForSlot(context.Background(), pubKey[:], slot)
|
||||
sr, _, err := db.ProposalHistoryForSlot(context.Background(), pubKey, slot)
|
||||
require.NoError(t, err, "Failed to get proposal history")
|
||||
require.DeepEqual(t, bytesutil.PadTo([]byte{}, 32), sr, "Unexpected difference in bytes for epoch %d", slot)
|
||||
require.DeepEqual(t, bytesutil.PadTo([]byte{}, 32), sr[:], "Unexpected difference in bytes for epoch %d", slot)
|
||||
}
|
||||
for _, slot := range tt.storedSlots {
|
||||
sr, err := db.ProposalHistoryForSlot(context.Background(), pubKey[:], slot)
|
||||
sr, _, err := db.ProposalHistoryForSlot(context.Background(), pubKey, slot)
|
||||
require.NoError(t, err, "Failed to get proposal history")
|
||||
require.DeepEqual(t, signedRoot, sr, "Unexpected difference in bytes for epoch %d", slot)
|
||||
require.DeepEqual(t, signedRoot, sr[:], "Unexpected difference in bytes for epoch %d", slot)
|
||||
}
|
||||
require.NoError(t, db.Close(), "Failed to close database")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStore_ImportProposalHistory(t *testing.T) {
|
||||
pubkey := [48]byte{3}
|
||||
func TestStore_ProposedPublicKeys(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
db := setupDB(t, [][48]byte{pubkey})
|
||||
proposedSlots := make(map[uint64]bool)
|
||||
proposedSlots[0] = true
|
||||
proposedSlots[1] = true
|
||||
proposedSlots[20] = true
|
||||
proposedSlots[31] = true
|
||||
proposedSlots[32] = true
|
||||
proposedSlots[33] = true
|
||||
proposedSlots[1023] = true
|
||||
proposedSlots[1024] = true
|
||||
proposedSlots[1025] = true
|
||||
lastIndex := 1025 + params.BeaconConfig().SlotsPerEpoch
|
||||
validatorDB, err := NewKVStore(t.TempDir(), nil)
|
||||
require.NoError(t, err, "Failed to instantiate DB")
|
||||
t.Cleanup(func() {
|
||||
require.NoError(t, validatorDB.Close(), "Failed to close database")
|
||||
require.NoError(t, validatorDB.ClearDB(), "Failed to clear database")
|
||||
})
|
||||
|
||||
for slot := range proposedSlots {
|
||||
slotBitlist, err := db.ProposalHistoryForEpoch(context.Background(), pubkey[:], helpers.SlotToEpoch(slot))
|
||||
require.NoError(t, err)
|
||||
slotBitlist.SetBitAt(slot%params.BeaconConfig().SlotsPerEpoch, true)
|
||||
err = db.SaveProposalHistoryForEpoch(context.Background(), pubkey[:], helpers.SlotToEpoch(slot), slotBitlist)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
err := db.MigrateV2ProposalFormat(ctx)
|
||||
keys, err := validatorDB.ProposedPublicKeys(ctx)
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, make([][48]byte, 0), keys)
|
||||
|
||||
pubKey := [48]byte{1}
|
||||
dummyRoot := [32]byte{}
|
||||
err = validatorDB.SaveProposalHistoryForSlot(ctx, pubKey, 1, dummyRoot[:])
|
||||
require.NoError(t, err)
|
||||
|
||||
for slot := uint64(0); slot <= lastIndex; slot++ {
|
||||
if _, ok := proposedSlots[slot]; ok {
|
||||
root, err := db.ProposalHistoryForSlot(ctx, pubkey[:], slot)
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, bytesutil.PadTo([]byte{1}, 32), root, "slot: %d", slot)
|
||||
continue
|
||||
}
|
||||
root, err := db.ProposalHistoryForSlot(ctx, pubkey[:], slot)
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, bytesutil.PadTo([]byte{}, 32), root)
|
||||
}
|
||||
keys, err = validatorDB.ProposedPublicKeys(ctx)
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, [][48]byte{pubKey}, keys)
|
||||
}
|
||||
|
||||
func TestShouldImportProposals(t *testing.T) {
|
||||
pubkey := [48]byte{3}
|
||||
db := setupDB(t, nil)
|
||||
//ctx := context.Background()
|
||||
|
||||
shouldImport, err := db.shouldImportProposals()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, false, shouldImport, "Empty bucket should not be imported")
|
||||
err = db.OldUpdatePublicKeysBuckets([][48]byte{pubkey})
|
||||
require.NoError(t, err)
|
||||
shouldImport, err = db.shouldImportProposals()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, shouldImport, "Bucket with content should be imported")
|
||||
}
|
||||
|
||||
func TestStore_UpdateProposalsProtectionDb(t *testing.T) {
|
||||
pubkey := [48]byte{3}
|
||||
db := setupDB(t, [][48]byte{pubkey})
|
||||
func TestStore_LowestSignedProposal(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
err := db.OldUpdatePublicKeysBuckets([][48]byte{pubkey})
|
||||
pubkey := [48]byte{3}
|
||||
dummySigningRoot := [32]byte{}
|
||||
validatorDB := setupDB(t, [][48]byte{pubkey})
|
||||
|
||||
slot, err := validatorDB.LowestSignedProposal(ctx, pubkey)
|
||||
require.NoError(t, err)
|
||||
shouldImport, err := db.shouldImportProposals()
|
||||
assert.Equal(t, uint64(0), slot)
|
||||
|
||||
// We save our first proposal history.
|
||||
err = validatorDB.SaveProposalHistoryForSlot(ctx, pubkey, 2 /* slot */, dummySigningRoot[:])
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, shouldImport, "Bucket with content should be imported")
|
||||
err = db.MigrateV2ProposalsProtectionDb(ctx)
|
||||
|
||||
// We expect the lowest signed slot is what we just saved.
|
||||
slot, err = validatorDB.LowestSignedProposal(ctx, pubkey)
|
||||
require.NoError(t, err)
|
||||
shouldImport, err = db.shouldImportProposals()
|
||||
assert.Equal(t, uint64(2), slot)
|
||||
|
||||
// We save a higher proposal history.
|
||||
err = validatorDB.SaveProposalHistoryForSlot(ctx, pubkey, 3 /* slot */, dummySigningRoot[:])
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, false, shouldImport, "Proposals should not be re-imported")
|
||||
|
||||
// We expect the lowest signed slot did not change.
|
||||
slot, err = validatorDB.LowestSignedProposal(ctx, pubkey)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, uint64(2), slot)
|
||||
|
||||
// We save a lower proposal history.
|
||||
err = validatorDB.SaveProposalHistoryForSlot(ctx, pubkey, 1 /* slot */, dummySigningRoot[:])
|
||||
require.NoError(t, err)
|
||||
|
||||
// We expect the lowest signed slot indeed changed.
|
||||
slot, err = validatorDB.LowestSignedProposal(ctx, pubkey)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, uint64(1), slot)
|
||||
}
|
||||
|
||||
func TestStore_HighestSignedProposal(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
pubkey := [48]byte{3}
|
||||
dummySigningRoot := [32]byte{}
|
||||
validatorDB := setupDB(t, [][48]byte{pubkey})
|
||||
|
||||
slot, err := validatorDB.HighestSignedProposal(ctx, pubkey)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, uint64(0), slot)
|
||||
|
||||
// We save our first proposal history.
|
||||
err = validatorDB.SaveProposalHistoryForSlot(ctx, pubkey, 2 /* slot */, dummySigningRoot[:])
|
||||
require.NoError(t, err)
|
||||
|
||||
// We expect the highest signed slot is what we just saved.
|
||||
slot, err = validatorDB.HighestSignedProposal(ctx, pubkey)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, uint64(2), slot)
|
||||
|
||||
// We save a lower proposal history.
|
||||
err = validatorDB.SaveProposalHistoryForSlot(ctx, pubkey, 1 /* slot */, dummySigningRoot[:])
|
||||
require.NoError(t, err)
|
||||
|
||||
// We expect the lowest signed slot did not change.
|
||||
slot, err = validatorDB.HighestSignedProposal(ctx, pubkey)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, uint64(2), slot)
|
||||
|
||||
// We save a higher proposal history.
|
||||
err = validatorDB.SaveProposalHistoryForSlot(ctx, pubkey, 3 /* slot */, dummySigningRoot[:])
|
||||
require.NoError(t, err)
|
||||
|
||||
// We expect the highest signed slot indeed changed.
|
||||
slot, err = validatorDB.HighestSignedProposal(ctx, pubkey)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, uint64(3), slot)
|
||||
}
|
||||
|
||||
@@ -3,15 +3,24 @@ package kv
|
||||
var (
|
||||
// Genesis information bucket key.
|
||||
genesisInfoBucket = []byte("genesis-info-bucket")
|
||||
// Genesis validators root key.
|
||||
genesisValidatorsRootKey = []byte("genesis-val-root")
|
||||
|
||||
// Validator slashing protection from double proposals.
|
||||
historicProposalsBucket = []byte("proposal-history-bucket")
|
||||
// Validator slashing protection from double proposals.
|
||||
newhistoricProposalsBucket = []byte("proposal-history-bucket-interchange")
|
||||
newHistoricProposalsBucket = []byte("proposal-history-bucket-interchange")
|
||||
// Validator slashing protection from slashable attestations.
|
||||
historicAttestationsBucket = []byte("attestation-history-bucket")
|
||||
// New Validator slashing protection from slashable attestations.
|
||||
newHistoricAttestationsBucket = []byte("attestation-history-bucket-interchange")
|
||||
|
||||
// Buckets for lowest signed source and target epoch for individual validator.
|
||||
lowestSignedSourceBucket = []byte("lowest-signed-source-bucket")
|
||||
lowestSignedTargetBucket = []byte("lowest-signed-target-bucket")
|
||||
|
||||
// Lowest and highest signed proposals.
|
||||
lowestSignedProposalsBucket = []byte("lowest-signed-proposals-bucket")
|
||||
highestSignedProposalsBucket = []byte("highest-signed-proposals-bucket")
|
||||
|
||||
// Genesis validators root bucket key.
|
||||
genesisValidatorsRootKey = []byte("genesis-val-root")
|
||||
)
|
||||
|
||||
@@ -101,12 +101,6 @@ func NewValidatorClient(cliCtx *cli.Context) (*ValidatorClient, error) {
|
||||
if err := ValidatorClient.initializeFromCLI(cliCtx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := ValidatorClient.db.MigrateV2ProposalsProtectionDb(cliCtx.Context); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := ValidatorClient.db.MigrateV2AttestationProtectionDb(cliCtx.Context); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ValidatorClient, nil
|
||||
}
|
||||
|
||||
@@ -247,6 +241,13 @@ func (s *ValidatorClient) initializeFromCLI(cliCtx *cli.Context) error {
|
||||
func (s *ValidatorClient) initializeForWeb(cliCtx *cli.Context) error {
|
||||
var keyManager keymanager.IKeymanager
|
||||
var err error
|
||||
walletDir := cliCtx.String(flags.WalletDirFlag.Name)
|
||||
defaultWalletPasswordFilePath := filepath.Join(walletDir, wallet.DefaultWalletPasswordFile)
|
||||
if fileutil.FileExists(defaultWalletPasswordFilePath) {
|
||||
if err := cliCtx.Set(flags.WalletPasswordFileFlag.Name, defaultWalletPasswordFilePath); err != nil {
|
||||
return errors.Wrap(err, "could not set default wallet password file path")
|
||||
}
|
||||
}
|
||||
// Read the wallet from the specified path.
|
||||
w, err := wallet.OpenWalletOrElseCli(cliCtx, func(cliCtx *cli.Context) (*wallet.Wallet, error) {
|
||||
return nil, nil
|
||||
@@ -404,24 +405,29 @@ func (s *ValidatorClient) registerRPCService(cliCtx *cli.Context, km keymanager.
|
||||
}
|
||||
validatorGatewayHost := cliCtx.String(flags.GRPCGatewayHost.Name)
|
||||
validatorGatewayPort := cliCtx.Int(flags.GRPCGatewayPort.Name)
|
||||
validatorMonitoringHost := cliCtx.String(cmd.MonitoringHostFlag.Name)
|
||||
validatorMonitoringPort := cliCtx.Int(flags.MonitoringPortFlag.Name)
|
||||
rpcHost := cliCtx.String(flags.RPCHost.Name)
|
||||
rpcPort := cliCtx.Int(flags.RPCPort.Name)
|
||||
nodeGatewayEndpoint := cliCtx.String(flags.BeaconRPCGatewayProviderFlag.Name)
|
||||
walletDir := cliCtx.String(flags.WalletDirFlag.Name)
|
||||
server := rpc.NewServer(cliCtx.Context, &rpc.Config{
|
||||
ValDB: s.db,
|
||||
Host: rpcHost,
|
||||
Port: fmt.Sprintf("%d", rpcPort),
|
||||
WalletInitializedFeed: s.walletInitialized,
|
||||
ValidatorService: vs,
|
||||
SyncChecker: vs,
|
||||
GenesisFetcher: vs,
|
||||
NodeGatewayEndpoint: nodeGatewayEndpoint,
|
||||
WalletDir: walletDir,
|
||||
Wallet: s.wallet,
|
||||
Keymanager: km,
|
||||
ValidatorGatewayHost: validatorGatewayHost,
|
||||
ValidatorGatewayPort: validatorGatewayPort,
|
||||
ValDB: s.db,
|
||||
Host: rpcHost,
|
||||
Port: fmt.Sprintf("%d", rpcPort),
|
||||
WalletInitializedFeed: s.walletInitialized,
|
||||
ValidatorService: vs,
|
||||
SyncChecker: vs,
|
||||
GenesisFetcher: vs,
|
||||
BeaconNodeInfoFetcher: vs,
|
||||
NodeGatewayEndpoint: nodeGatewayEndpoint,
|
||||
WalletDir: walletDir,
|
||||
Wallet: s.wallet,
|
||||
Keymanager: km,
|
||||
ValidatorGatewayHost: validatorGatewayHost,
|
||||
ValidatorGatewayPort: validatorGatewayPort,
|
||||
ValidatorMonitoringHost: validatorMonitoringHost,
|
||||
ValidatorMonitoringPort: validatorMonitoringPort,
|
||||
})
|
||||
return s.services.RegisterService(server)
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ go_library(
|
||||
"//proto/validator/accounts/v2:go_default_library",
|
||||
"//shared/cmd:go_default_library",
|
||||
"//shared/event:go_default_library",
|
||||
"//shared/featureconfig:go_default_library",
|
||||
"//shared/fileutil:go_default_library",
|
||||
"//shared/pagination:go_default_library",
|
||||
"//shared/petnames:go_default_library",
|
||||
@@ -66,6 +67,7 @@ go_test(
|
||||
"//proto/validator/accounts/v2:go_default_library",
|
||||
"//shared/bls:go_default_library",
|
||||
"//shared/event:go_default_library",
|
||||
"//shared/featureconfig:go_default_library",
|
||||
"//shared/fileutil:go_default_library",
|
||||
"//shared/testutil/assert:go_default_library",
|
||||
"//shared/testutil/require:go_default_library",
|
||||
|
||||
@@ -2,6 +2,7 @@ package rpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
ptypes "github.com/gogo/protobuf/types"
|
||||
@@ -32,3 +33,15 @@ func (s *Server) GetBeaconNodeConnection(ctx context.Context, _ *ptypes.Empty) (
|
||||
Syncing: syncStatus,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetLogsEndpoints for the beacon and validator client.
|
||||
func (s *Server) GetLogsEndpoints(ctx context.Context, _ *ptypes.Empty) (*pb.LogsEndpointResponse, error) {
|
||||
beaconLogsEndpoint, err := s.beaconNodeInfoFetcher.BeaconLogsEndpoint(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pb.LogsEndpointResponse{
|
||||
BeaconLogsEndpoint: beaconLogsEndpoint + "/logs",
|
||||
ValidatorLogsEndpoint: fmt.Sprintf("%s:%d/logs", s.validatorMonitoringHost, s.validatorMonitoringPort),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -33,6 +33,14 @@ func (m *mockGenesisFetcher) GenesisInfo(_ context.Context) (*ethpb.Genesis, err
|
||||
}, nil
|
||||
}
|
||||
|
||||
type mockBeaconInfoFetcher struct {
|
||||
endpoint string
|
||||
}
|
||||
|
||||
func (m *mockBeaconInfoFetcher) BeaconLogsEndpoint(_ context.Context) (string, error) {
|
||||
return m.endpoint, nil
|
||||
}
|
||||
|
||||
func TestServer_GetBeaconNodeConnection(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
endpoint := "localhost:90210"
|
||||
@@ -55,3 +63,19 @@ func TestServer_GetBeaconNodeConnection(t *testing.T) {
|
||||
}
|
||||
require.DeepEqual(t, want, got)
|
||||
}
|
||||
|
||||
func TestServer_GetLogsEndpoints(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
s := &Server{
|
||||
validatorMonitoringHost: "localhost",
|
||||
validatorMonitoringPort: 8081,
|
||||
beaconNodeInfoFetcher: &mockBeaconInfoFetcher{endpoint: "localhost:8080"},
|
||||
}
|
||||
got, err := s.GetLogsEndpoints(ctx, &ptypes.Empty{})
|
||||
require.NoError(t, err)
|
||||
want := &pb.LogsEndpointResponse{
|
||||
BeaconLogsEndpoint: "localhost:8080/logs",
|
||||
ValidatorLogsEndpoint: "localhost:8081/logs",
|
||||
}
|
||||
require.DeepEqual(t, want, got)
|
||||
}
|
||||
|
||||
@@ -33,71 +33,80 @@ func init() {
|
||||
|
||||
// Config options for the gRPC server.
|
||||
type Config struct {
|
||||
ValidatorGatewayHost string
|
||||
ValidatorGatewayPort int
|
||||
Host string
|
||||
Port string
|
||||
CertFlag string
|
||||
KeyFlag string
|
||||
ValDB db.Database
|
||||
WalletDir string
|
||||
ValidatorService *client.ValidatorService
|
||||
SyncChecker client.SyncChecker
|
||||
GenesisFetcher client.GenesisFetcher
|
||||
WalletInitializedFeed *event.Feed
|
||||
NodeGatewayEndpoint string
|
||||
Wallet *wallet.Wallet
|
||||
Keymanager keymanager.IKeymanager
|
||||
ValidatorGatewayHost string
|
||||
ValidatorGatewayPort int
|
||||
ValidatorMonitoringHost string
|
||||
ValidatorMonitoringPort int
|
||||
Host string
|
||||
Port string
|
||||
CertFlag string
|
||||
KeyFlag string
|
||||
ValDB db.Database
|
||||
WalletDir string
|
||||
ValidatorService *client.ValidatorService
|
||||
SyncChecker client.SyncChecker
|
||||
GenesisFetcher client.GenesisFetcher
|
||||
BeaconNodeInfoFetcher client.BeaconNodeInfoFetcher
|
||||
WalletInitializedFeed *event.Feed
|
||||
NodeGatewayEndpoint string
|
||||
Wallet *wallet.Wallet
|
||||
Keymanager keymanager.IKeymanager
|
||||
}
|
||||
|
||||
// Server defining a gRPC server for the remote signer API.
|
||||
type Server struct {
|
||||
valDB db.Database
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
host string
|
||||
port string
|
||||
listener net.Listener
|
||||
keymanager keymanager.IKeymanager
|
||||
withCert string
|
||||
withKey string
|
||||
credentialError error
|
||||
grpcServer *grpc.Server
|
||||
jwtKey []byte
|
||||
validatorService *client.ValidatorService
|
||||
syncChecker client.SyncChecker
|
||||
genesisFetcher client.GenesisFetcher
|
||||
walletDir string
|
||||
wallet *wallet.Wallet
|
||||
walletInitializedFeed *event.Feed
|
||||
walletInitialized bool
|
||||
nodeGatewayEndpoint string
|
||||
validatorGatewayHost string
|
||||
validatorGatewayPort int
|
||||
valDB db.Database
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
host string
|
||||
port string
|
||||
listener net.Listener
|
||||
keymanager keymanager.IKeymanager
|
||||
withCert string
|
||||
withKey string
|
||||
credentialError error
|
||||
grpcServer *grpc.Server
|
||||
jwtKey []byte
|
||||
validatorService *client.ValidatorService
|
||||
syncChecker client.SyncChecker
|
||||
genesisFetcher client.GenesisFetcher
|
||||
beaconNodeInfoFetcher client.BeaconNodeInfoFetcher
|
||||
walletDir string
|
||||
wallet *wallet.Wallet
|
||||
walletInitializedFeed *event.Feed
|
||||
walletInitialized bool
|
||||
nodeGatewayEndpoint string
|
||||
validatorMonitoringHost string
|
||||
validatorMonitoringPort int
|
||||
validatorGatewayHost string
|
||||
validatorGatewayPort int
|
||||
}
|
||||
|
||||
// NewServer instantiates a new gRPC server.
|
||||
func NewServer(ctx context.Context, cfg *Config) *Server {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
return &Server{
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
host: cfg.Host,
|
||||
port: cfg.Port,
|
||||
withCert: cfg.CertFlag,
|
||||
withKey: cfg.KeyFlag,
|
||||
valDB: cfg.ValDB,
|
||||
validatorService: cfg.ValidatorService,
|
||||
syncChecker: cfg.SyncChecker,
|
||||
genesisFetcher: cfg.GenesisFetcher,
|
||||
walletDir: cfg.WalletDir,
|
||||
walletInitializedFeed: cfg.WalletInitializedFeed,
|
||||
walletInitialized: cfg.Wallet != nil,
|
||||
wallet: cfg.Wallet,
|
||||
keymanager: cfg.Keymanager,
|
||||
nodeGatewayEndpoint: cfg.NodeGatewayEndpoint,
|
||||
validatorGatewayHost: cfg.ValidatorGatewayHost,
|
||||
validatorGatewayPort: cfg.ValidatorGatewayPort,
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
host: cfg.Host,
|
||||
port: cfg.Port,
|
||||
withCert: cfg.CertFlag,
|
||||
withKey: cfg.KeyFlag,
|
||||
valDB: cfg.ValDB,
|
||||
validatorService: cfg.ValidatorService,
|
||||
syncChecker: cfg.SyncChecker,
|
||||
beaconNodeInfoFetcher: cfg.BeaconNodeInfoFetcher,
|
||||
genesisFetcher: cfg.GenesisFetcher,
|
||||
walletDir: cfg.WalletDir,
|
||||
walletInitializedFeed: cfg.WalletInitializedFeed,
|
||||
walletInitialized: cfg.Wallet != nil,
|
||||
wallet: cfg.Wallet,
|
||||
keymanager: cfg.Keymanager,
|
||||
nodeGatewayEndpoint: cfg.NodeGatewayEndpoint,
|
||||
validatorMonitoringHost: cfg.ValidatorMonitoringHost,
|
||||
validatorMonitoringPort: cfg.ValidatorMonitoringPort,
|
||||
validatorGatewayHost: cfg.ValidatorGatewayHost,
|
||||
validatorGatewayPort: cfg.ValidatorGatewayPort,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,10 +4,14 @@ import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
ptypes "github.com/gogo/protobuf/types"
|
||||
"github.com/pkg/errors"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/validator/accounts/v2"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/fileutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/rand"
|
||||
"github.com/prysmaticlabs/prysm/validator/accounts"
|
||||
"github.com/prysmaticlabs/prysm/validator/accounts/wallet"
|
||||
@@ -73,6 +77,9 @@ func (s *Server) CreateWallet(ctx context.Context, req *pb.CreateWalletRequest)
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := writeWalletPasswordToDisk(walletDir, req.WalletPassword); err != nil {
|
||||
return nil, status.Error(codes.Internal, "Could not write wallet password to disk")
|
||||
}
|
||||
return &pb.CreateWalletResponse{
|
||||
Wallet: &pb.WalletResponse{
|
||||
WalletPath: walletDir,
|
||||
@@ -101,7 +108,9 @@ func (s *Server) CreateWallet(ctx context.Context, req *pb.CreateWalletRequest)
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := writeWalletPasswordToDisk(walletDir, req.WalletPassword); err != nil {
|
||||
return nil, status.Error(codes.Internal, "Could not write wallet password to disk")
|
||||
}
|
||||
return &pb.CreateWalletResponse{
|
||||
Wallet: &pb.WalletResponse{
|
||||
WalletPath: walletDir,
|
||||
@@ -272,3 +281,14 @@ func (s *Server) initializeWallet(ctx context.Context, cfg *wallet.Config) error
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeWalletPasswordToDisk(walletDir string, password string) error {
|
||||
if !featureconfig.Get().WriteWalletPasswordOnWebOnboarding {
|
||||
return nil
|
||||
}
|
||||
passwordFilePath := filepath.Join(walletDir, wallet.DefaultWalletPasswordFile)
|
||||
if fileutil.FileExists(passwordFilePath) {
|
||||
return fmt.Errorf("cannot write wallet password file as it already exists %s", passwordFilePath)
|
||||
}
|
||||
return fileutil.WriteFile(passwordFilePath, []byte(password))
|
||||
}
|
||||
|
||||
@@ -5,20 +5,24 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
ptypes "github.com/gogo/protobuf/types"
|
||||
"github.com/google/uuid"
|
||||
keystorev4 "github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4"
|
||||
|
||||
pb "github.com/prysmaticlabs/prysm/proto/validator/accounts/v2"
|
||||
"github.com/prysmaticlabs/prysm/shared/bls"
|
||||
"github.com/prysmaticlabs/prysm/shared/event"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/fileutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
"github.com/prysmaticlabs/prysm/validator/accounts"
|
||||
"github.com/prysmaticlabs/prysm/validator/accounts/wallet"
|
||||
"github.com/prysmaticlabs/prysm/validator/keymanager"
|
||||
"github.com/prysmaticlabs/prysm/validator/keymanager/imported"
|
||||
keystorev4 "github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4"
|
||||
)
|
||||
|
||||
func TestServer_CreateWallet_Imported(t *testing.T) {
|
||||
@@ -277,3 +281,30 @@ func TestServer_ImportKeystores_OK(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 3, len(keys))
|
||||
}
|
||||
|
||||
func Test_writeWalletPasswordToDisk(t *testing.T) {
|
||||
walletDir := setupWalletDir(t)
|
||||
resetCfg := featureconfig.InitWithReset(&featureconfig.Flags{
|
||||
WriteWalletPasswordOnWebOnboarding: false,
|
||||
})
|
||||
defer resetCfg()
|
||||
err := writeWalletPasswordToDisk(walletDir, "somepassword")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Expected a silent failure if the feature flag is not enabled.
|
||||
passwordFilePath := filepath.Join(walletDir, wallet.DefaultWalletPasswordFile)
|
||||
assert.Equal(t, false, fileutil.FileExists(passwordFilePath))
|
||||
resetCfg = featureconfig.InitWithReset(&featureconfig.Flags{
|
||||
WriteWalletPasswordOnWebOnboarding: true,
|
||||
})
|
||||
defer resetCfg()
|
||||
err = writeWalletPasswordToDisk(walletDir, "somepassword")
|
||||
require.NoError(t, err)
|
||||
|
||||
// File should have been written.
|
||||
assert.Equal(t, true, fileutil.FileExists(passwordFilePath))
|
||||
|
||||
// Attempting to write again should trigger an error.
|
||||
err = writeWalletPasswordToDisk(walletDir, "somepassword")
|
||||
require.NotNil(t, err)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ load("@prysm//tools/go:def.bzl", "go_library")
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"export.go",
|
||||
"format.go",
|
||||
"helpers.go",
|
||||
"import.go",
|
||||
@@ -11,10 +12,13 @@ go_library(
|
||||
importpath = "github.com/prysmaticlabs/prysm/validator/slashing-protection/local/standard-protection-format",
|
||||
visibility = ["//validator:__subpackages__"],
|
||||
deps = [
|
||||
"//shared/bytesutil:go_default_library",
|
||||
"//shared/hashutil:go_default_library",
|
||||
"//validator/db:go_default_library",
|
||||
"//validator/db/kv:go_default_library",
|
||||
"@com_github_k0kubun_go_ansi//:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_schollz_progressbar_v3//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
],
|
||||
)
|
||||
@@ -22,8 +26,10 @@ go_library(
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"export_test.go",
|
||||
"helpers_test.go",
|
||||
"import_test.go",
|
||||
"round_trip_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
package interchangeformat
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/validator/db"
|
||||
)
|
||||
|
||||
// ExportStandardProtectionJSON extracts all slashing protection data from a validator database
|
||||
// and packages it into an EIP-3076 compliant, standard
|
||||
func ExportStandardProtectionJSON(ctx context.Context, validatorDB db.Database) (*EIPSlashingProtectionFormat, error) {
|
||||
interchangeJSON := &EIPSlashingProtectionFormat{}
|
||||
genesisValidatorsRoot, err := validatorDB.GenesisValidatorsRoot(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
genesisRootHex, err := rootToHexString(genesisValidatorsRoot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
interchangeJSON.Metadata.GenesisValidatorsRoot = genesisRootHex
|
||||
interchangeJSON.Metadata.InterchangeFormatVersion = INTERCHANGE_FORMAT_VERSION
|
||||
|
||||
// Extract the existing public keys in our database.
|
||||
proposedPublicKeys, err := validatorDB.ProposedPublicKeys(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dataByPubKey := make(map[[48]byte]*ProtectionData)
|
||||
|
||||
// Extract the signed proposals by public keys.
|
||||
for _, pubKey := range proposedPublicKeys {
|
||||
pubKeyHex, err := pubKeyToHexString(pubKey[:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
signedBlocks, err := getSignedBlocksByPubKey(ctx, validatorDB, pubKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dataByPubKey[pubKey] = &ProtectionData{
|
||||
Pubkey: pubKeyHex,
|
||||
SignedBlocks: signedBlocks,
|
||||
SignedAttestations: nil,
|
||||
}
|
||||
}
|
||||
|
||||
// Next we turn our map into a slice as expected by the EIP-3076 JSON standard.
|
||||
dataList := make([]*ProtectionData, 0)
|
||||
for _, item := range dataByPubKey {
|
||||
dataList = append(dataList, item)
|
||||
}
|
||||
interchangeJSON.Data = dataList
|
||||
return interchangeJSON, nil
|
||||
}
|
||||
|
||||
func getSignedBlocksByPubKey(ctx context.Context, validatorDB db.Database, pubKey [48]byte) ([]*SignedBlock, error) {
|
||||
lowestSignedSlot, err := validatorDB.LowestSignedProposal(ctx, pubKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
highestSignedSlot, err := validatorDB.HighestSignedProposal(ctx, pubKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
signedBlocks := make([]*SignedBlock, 0)
|
||||
for i := lowestSignedSlot; i <= highestSignedSlot; i++ {
|
||||
if ctx.Err() != nil {
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
signingRoot, exists, err := validatorDB.ProposalHistoryForSlot(ctx, pubKey, i)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if exists {
|
||||
signingRootHex, err := rootToHexString(signingRoot[:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
signedBlocks = append(signedBlocks, &SignedBlock{
|
||||
Slot: fmt.Sprintf("%d", i),
|
||||
SigningRoot: signingRootHex,
|
||||
})
|
||||
}
|
||||
}
|
||||
return signedBlocks, nil
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package interchangeformat
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
dbtest "github.com/prysmaticlabs/prysm/validator/db/testing"
|
||||
)
|
||||
|
||||
func Test_getSignedBlocksByPubKey(t *testing.T) {
|
||||
pubKeys := [][48]byte{
|
||||
{1},
|
||||
}
|
||||
ctx := context.Background()
|
||||
validatorDB := dbtest.SetupDB(t, pubKeys)
|
||||
|
||||
// No highest and/or lowest signed blocks will return empty.
|
||||
signedBlocks, err := getSignedBlocksByPubKey(ctx, validatorDB, pubKeys[0])
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 0, len(signedBlocks))
|
||||
|
||||
// We mark slot 1 as proposed.
|
||||
dummyRoot1 := [32]byte{1}
|
||||
err = validatorDB.SaveProposalHistoryForSlot(ctx, pubKeys[0], 1, dummyRoot1[:])
|
||||
require.NoError(t, err)
|
||||
|
||||
// We mark slot 3 as proposed but with empty signing root.
|
||||
err = validatorDB.SaveProposalHistoryForSlot(ctx, pubKeys[0], 3, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
// We mark slot 5 as proposed.
|
||||
dummyRoot2 := [32]byte{2}
|
||||
err = validatorDB.SaveProposalHistoryForSlot(ctx, pubKeys[0], 5, dummyRoot2[:])
|
||||
require.NoError(t, err)
|
||||
|
||||
// We expect a valid proposal history containing slot 1 and slot 5 only
|
||||
// when we attempt to retrieve it from disk.
|
||||
signedBlocks, err = getSignedBlocksByPubKey(ctx, validatorDB, pubKeys[0])
|
||||
require.NoError(t, err)
|
||||
wanted := []*SignedBlock{
|
||||
{
|
||||
Slot: "1",
|
||||
SigningRoot: fmt.Sprintf("%#x", dummyRoot1),
|
||||
},
|
||||
{
|
||||
Slot: "3",
|
||||
SigningRoot: "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
},
|
||||
{
|
||||
Slot: "5",
|
||||
SigningRoot: fmt.Sprintf("%#x", dummyRoot2),
|
||||
},
|
||||
}
|
||||
for i, blk := range wanted {
|
||||
assert.DeepEqual(t, blk, signedBlocks[i])
|
||||
}
|
||||
}
|
||||
@@ -5,8 +5,29 @@ import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/k0kubun/go-ansi"
|
||||
"github.com/schollz/progressbar/v3"
|
||||
)
|
||||
|
||||
func initializeProgressBar(numItems int, msg string) *progressbar.ProgressBar {
|
||||
return progressbar.NewOptions(
|
||||
numItems,
|
||||
progressbar.OptionFullWidth(),
|
||||
progressbar.OptionSetWriter(ansi.NewAnsiStdout()),
|
||||
progressbar.OptionEnableColorCodes(true),
|
||||
progressbar.OptionSetTheme(progressbar.Theme{
|
||||
Saucer: "[green]=[reset]",
|
||||
SaucerHead: "[green]>[reset]",
|
||||
SaucerPadding: " ",
|
||||
BarStart: "[",
|
||||
BarEnd: "]",
|
||||
}),
|
||||
progressbar.OptionOnCompletion(func() { fmt.Println() }),
|
||||
progressbar.OptionSetDescription(msg),
|
||||
)
|
||||
}
|
||||
|
||||
func uint64FromString(str string) (uint64, error) {
|
||||
return strconv.ParseUint(str, 10, 64)
|
||||
}
|
||||
@@ -36,3 +57,21 @@ func rootFromHex(str string) ([32]byte, error) {
|
||||
copy(root[:], rootHexBytes[:32])
|
||||
return root, nil
|
||||
}
|
||||
|
||||
func rootToHexString(root []byte) (string, error) {
|
||||
// Nil signing roots are allowed in EIP-3076.
|
||||
if len(root) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
if len(root) != 32 {
|
||||
return "", fmt.Errorf("wanted length 32, received %d", len(root))
|
||||
}
|
||||
return fmt.Sprintf("%#x", root), nil
|
||||
}
|
||||
|
||||
func pubKeyToHexString(pubKey []byte) (string, error) {
|
||||
if len(pubKey) != 48 {
|
||||
return "", fmt.Errorf("wanted length 48, received %d", len(pubKey))
|
||||
}
|
||||
return fmt.Sprintf("%#x", pubKey), nil
|
||||
}
|
||||
|
||||
@@ -163,3 +163,97 @@ func Test_rootFromHex(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_rootToHexString(t *testing.T) {
|
||||
mockRoot := [32]byte{1}
|
||||
tests := []struct {
|
||||
name string
|
||||
root []byte
|
||||
want string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "nil roots return empty string",
|
||||
root: nil,
|
||||
want: "",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "len(root) == 0 returns empty string",
|
||||
root: make([]byte, 0),
|
||||
want: "",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "non-empty root with incorrect size returns error",
|
||||
root: make([]byte, 20),
|
||||
want: "",
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "non-empty root with correct size returns expected value",
|
||||
root: mockRoot[:],
|
||||
want: "0x0100000000000000000000000000000000000000000000000000000000000000",
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := rootToHexString(tt.root)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("rootToHexString() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if got != tt.want {
|
||||
t.Errorf("rootToHexString() got = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_pubKeyToHexString(t *testing.T) {
|
||||
mockPubKey := [48]byte{1}
|
||||
tests := []struct {
|
||||
name string
|
||||
pubKey []byte
|
||||
want string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "nil pubkey should return error",
|
||||
pubKey: nil,
|
||||
want: "",
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "empty pubkey should return error",
|
||||
pubKey: make([]byte, 0),
|
||||
want: "",
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "wrong length pubkey should return error",
|
||||
pubKey: make([]byte, 3),
|
||||
want: "",
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "non-empty pubkey with correct size returns expected value",
|
||||
pubKey: mockPubKey[:],
|
||||
want: "0x010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := pubKeyToHexString(tt.pubKey)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("pubKeyToHexString() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if got != tt.want {
|
||||
t.Errorf("pubKeyToHexString() got = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
||||
"github.com/prysmaticlabs/prysm/validator/db"
|
||||
"github.com/prysmaticlabs/prysm/validator/db/kv"
|
||||
@@ -73,13 +74,25 @@ func ImportStandardProtectionJSON(ctx context.Context, validatorDB db.Database,
|
||||
// We save the histories to disk as atomic operations, ensuring that this only occurs
|
||||
// until after we successfully parse all data from the JSON file. If there is any error
|
||||
// in parsing the JSON proposal and attesting histories, we will not reach this point.
|
||||
if err = validatorDB.SaveProposalHistoryForPubKeysV2(ctx, proposalHistoryByPubKey); err != nil {
|
||||
return errors.Wrap(err, "could not save proposal history from imported JSON to database")
|
||||
for pubKey, proposalHistory := range proposalHistoryByPubKey {
|
||||
bar := initializeProgressBar(
|
||||
len(proposalHistory.Proposals),
|
||||
fmt.Sprintf("Importing past proposals for validator public key %#x", bytesutil.Trunc(pubKey[:])),
|
||||
)
|
||||
for _, proposal := range proposalHistory.Proposals {
|
||||
if err := bar.Add(1); err != nil {
|
||||
log.WithError(err).Debug("Could not increase progress bar")
|
||||
}
|
||||
if err = validatorDB.SaveProposalHistoryForSlot(ctx, pubKey, proposal.Slot, proposal.SigningRoot); err != nil {
|
||||
return errors.Wrap(err, "could not save proposal history from imported JSON to database")
|
||||
}
|
||||
}
|
||||
}
|
||||
if err := validatorDB.SaveAttestationHistoryForPubKeysV2(ctx, attestingHistoryByPubKey); err != nil {
|
||||
return errors.Wrap(err, "could not save attesting history from imported JSON to database")
|
||||
}
|
||||
return nil
|
||||
|
||||
return saveLowestSourceTargetToDB(ctx, validatorDB, signedAttsByPubKey)
|
||||
}
|
||||
|
||||
func validateMetadata(ctx context.Context, validatorDB db.Database, interchangeJSON *EIPSlashingProtectionFormat) error {
|
||||
@@ -239,3 +252,51 @@ func transformSignedAttestations(ctx context.Context, atts []*SignedAttestation)
|
||||
}
|
||||
return &attestingHistory, nil
|
||||
}
|
||||
|
||||
// This saves the lowest source and target epoch from the individual validator to the DB.
|
||||
func saveLowestSourceTargetToDB(ctx context.Context, validatorDB db.Database, signedAttsByPubKey map[[48]byte][]*SignedAttestation) error {
|
||||
validatorLowestSourceEpoch := make(map[[48]byte]uint64) // Validator public key to lowest attested source epoch.
|
||||
validatorLowestTargetEpoch := make(map[[48]byte]uint64) // Validator public key to lowest attested target epoch.
|
||||
for pubKey, signedAtts := range signedAttsByPubKey {
|
||||
for _, att := range signedAtts {
|
||||
source, err := uint64FromString(att.SourceEpoch)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%d is not a valid source: %v", source, err)
|
||||
}
|
||||
target, err := uint64FromString(att.TargetEpoch)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%d is not a valid target: %v", target, err)
|
||||
}
|
||||
se, ok := validatorLowestSourceEpoch[pubKey]
|
||||
if !ok {
|
||||
validatorLowestSourceEpoch[pubKey] = source
|
||||
} else if source < se {
|
||||
validatorLowestSourceEpoch[pubKey] = source
|
||||
}
|
||||
te, ok := validatorLowestTargetEpoch[pubKey]
|
||||
if !ok {
|
||||
validatorLowestTargetEpoch[pubKey] = target
|
||||
} else if target < te {
|
||||
validatorLowestTargetEpoch[pubKey] = target
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This should not happen.
|
||||
if len(validatorLowestTargetEpoch) != len(validatorLowestSourceEpoch) {
|
||||
return errors.New("incorrect source and target map length")
|
||||
}
|
||||
|
||||
// Save lowest source and target epoch to DB for every validator in the map.
|
||||
for k, v := range validatorLowestSourceEpoch {
|
||||
if err := validatorDB.SaveLowestSignedSourceEpoch(ctx, k, v); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for k, v := range validatorLowestTargetEpoch {
|
||||
if err := validatorDB.SaveLowestSignedTargetEpoch(ctx, k, v); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/shared/bls"
|
||||
@@ -86,11 +85,11 @@ func TestStore_ImportInterchangeData_BadFormat_PreventsDBWrites(t *testing.T) {
|
||||
)
|
||||
proposals := proposalHistory[i].Proposals
|
||||
for _, proposal := range proposals {
|
||||
receivedProposalSigningRoot, err := validatorDB.ProposalHistoryForSlot(ctx, publicKeys[i][:], proposal.Slot)
|
||||
receivedProposalSigningRoot, _, err := validatorDB.ProposalHistoryForSlot(ctx, publicKeys[i], proposal.Slot)
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(
|
||||
t,
|
||||
params.BeaconConfig().ZeroHash[:],
|
||||
params.BeaconConfig().ZeroHash,
|
||||
receivedProposalSigningRoot,
|
||||
"Imported proposal signing root is different than the empty default",
|
||||
)
|
||||
@@ -131,11 +130,11 @@ func TestStore_ImportInterchangeData_OK(t *testing.T) {
|
||||
)
|
||||
proposals := proposalHistory[i].Proposals
|
||||
for _, proposal := range proposals {
|
||||
receivedProposalSigningRoot, err := validatorDB.ProposalHistoryForSlot(ctx, publicKeys[i][:], proposal.Slot)
|
||||
receivedProposalSigningRoot, _, err := validatorDB.ProposalHistoryForSlot(ctx, publicKeys[i], proposal.Slot)
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(
|
||||
t,
|
||||
receivedProposalSigningRoot,
|
||||
receivedProposalSigningRoot[:],
|
||||
proposal.SigningRoot,
|
||||
"Imported proposals are different then the generated ones",
|
||||
)
|
||||
@@ -745,6 +744,31 @@ func Test_parseUniqueSignedAttestationsByPubKey(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func Test_saveLowestSourceTargetToDBt_Ok(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
numValidators := 2
|
||||
publicKeys := createRandomPubKeys(t, numValidators)
|
||||
validatorDB := dbtest.SetupDB(t, publicKeys)
|
||||
|
||||
m := make(map[[48]byte][]*SignedAttestation)
|
||||
m[publicKeys[0]] = []*SignedAttestation{{SourceEpoch: "1", TargetEpoch: "2"}, {SourceEpoch: "3", TargetEpoch: "4"}}
|
||||
m[publicKeys[1]] = []*SignedAttestation{{SourceEpoch: "8", TargetEpoch: "7"}, {SourceEpoch: "6", TargetEpoch: "5"}}
|
||||
require.NoError(t, saveLowestSourceTargetToDB(ctx, validatorDB, m))
|
||||
|
||||
got, err := validatorDB.LowestSignedTargetEpoch(ctx, publicKeys[0])
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(2), got)
|
||||
got, err = validatorDB.LowestSignedTargetEpoch(ctx, publicKeys[1])
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(5), got)
|
||||
got, err = validatorDB.LowestSignedSourceEpoch(ctx, publicKeys[0])
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(1), got)
|
||||
got, err = validatorDB.LowestSignedSourceEpoch(ctx, publicKeys[1])
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(6), got)
|
||||
}
|
||||
|
||||
func mockSlashingProtectionJSON(
|
||||
t *testing.T,
|
||||
publicKeys [][48]byte,
|
||||
@@ -752,12 +776,12 @@ func mockSlashingProtectionJSON(
|
||||
proposalHistories []kv.ProposalHistoryForPubkey,
|
||||
) *EIPSlashingProtectionFormat {
|
||||
standardProtectionFormat := &EIPSlashingProtectionFormat{}
|
||||
standardProtectionFormat.Metadata.GenesisValidatorsRoot = hex.EncodeToString(bytesutil.PadTo([]byte{32}, 32))
|
||||
standardProtectionFormat.Metadata.InterchangeFormatVersion = "5"
|
||||
standardProtectionFormat.Metadata.GenesisValidatorsRoot = fmt.Sprintf("%#x", bytesutil.PadTo([]byte{32}, 32))
|
||||
standardProtectionFormat.Metadata.InterchangeFormatVersion = INTERCHANGE_FORMAT_VERSION
|
||||
ctx := context.Background()
|
||||
for i := 0; i < len(publicKeys); i++ {
|
||||
data := &ProtectionData{
|
||||
Pubkey: hex.EncodeToString(publicKeys[i][:]),
|
||||
Pubkey: fmt.Sprintf("%#x", publicKeys[i]),
|
||||
}
|
||||
highestEpochWritten, err := attestingHistories[i].GetLatestEpochWritten(ctx)
|
||||
require.NoError(t, err)
|
||||
@@ -765,16 +789,16 @@ func mockSlashingProtectionJSON(
|
||||
hd, err := attestingHistories[i].GetTargetData(ctx, target)
|
||||
require.NoError(t, err)
|
||||
data.SignedAttestations = append(data.SignedAttestations, &SignedAttestation{
|
||||
TargetEpoch: strconv.FormatUint(target, 10),
|
||||
SourceEpoch: strconv.FormatUint(hd.Source, 10),
|
||||
SigningRoot: hex.EncodeToString(hd.SigningRoot),
|
||||
TargetEpoch: fmt.Sprintf("%d", target),
|
||||
SourceEpoch: fmt.Sprintf("%d", hd.Source),
|
||||
SigningRoot: fmt.Sprintf("%#x", hd.SigningRoot),
|
||||
})
|
||||
}
|
||||
for target := uint64(0); target < highestEpochWritten; target++ {
|
||||
proposal := proposalHistories[i].Proposals[target]
|
||||
block := &SignedBlock{
|
||||
Slot: strconv.FormatUint(proposal.Slot, 10),
|
||||
SigningRoot: hex.EncodeToString(proposal.SigningRoot),
|
||||
Slot: fmt.Sprintf("%d", proposal.Slot),
|
||||
SigningRoot: fmt.Sprintf("%#x", proposal.SigningRoot),
|
||||
}
|
||||
data.SignedBlocks = append(data.SignedBlocks, block)
|
||||
|
||||
@@ -792,7 +816,7 @@ func mockAttestingAndProposalHistories(t *testing.T, numValidators int) ([]kv.En
|
||||
ctx := context.Background()
|
||||
for v := 0; v < numValidators; v++ {
|
||||
var err error
|
||||
latestTarget := gen.Intn(int(params.BeaconConfig().WeakSubjectivityPeriod) / 100)
|
||||
latestTarget := gen.Intn(int(params.BeaconConfig().WeakSubjectivityPeriod) / 1000)
|
||||
hd := kv.NewAttestationHistoryArray(uint64(latestTarget))
|
||||
proposals := make([]kv.Proposal, 0)
|
||||
for i := 1; i < latestTarget; i++ {
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
package interchangeformat
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
dbtest "github.com/prysmaticlabs/prysm/validator/db/testing"
|
||||
)
|
||||
|
||||
func TestImportExport_RoundTrip(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
numValidators := 5
|
||||
publicKeys := createRandomPubKeys(t, numValidators)
|
||||
validatorDB := dbtest.SetupDB(t, publicKeys)
|
||||
|
||||
// First we setup some mock attesting and proposal histories and create a mock
|
||||
// standard slashing protection format JSON struct.
|
||||
attestingHistory, proposalHistory := mockAttestingAndProposalHistories(t, numValidators)
|
||||
wanted := mockSlashingProtectionJSON(t, publicKeys, attestingHistory, proposalHistory)
|
||||
|
||||
// We encode the standard slashing protection struct into a JSON format.
|
||||
blob, err := json.Marshal(wanted)
|
||||
require.NoError(t, err)
|
||||
buf := bytes.NewBuffer(blob)
|
||||
|
||||
// Next, we attempt to import it into our validator database.
|
||||
err = ImportStandardProtectionJSON(ctx, validatorDB, buf)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Next up, we export our slashing protection database into the EIP standard file.
|
||||
// Next, we attempt to import it into our validator database.
|
||||
eipStandard, err := ExportStandardProtectionJSON(ctx, validatorDB)
|
||||
require.NoError(t, err)
|
||||
|
||||
// TODO(#7813): We have only implemented the export functionality
|
||||
// for proposals history at the moment, so we do not check attesting history.
|
||||
for i := range wanted.Data {
|
||||
wanted.Data[i].SignedAttestations = nil
|
||||
}
|
||||
|
||||
// We compare the metadata fields from import to export.
|
||||
require.Equal(t, wanted.Metadata, eipStandard.Metadata)
|
||||
|
||||
// The values in the data field of the EIP struct are not guaranteed to be sorted,
|
||||
// so we create a map to verify we have the data we expected.
|
||||
require.Equal(t, len(wanted.Data), len(eipStandard.Data))
|
||||
|
||||
dataByPubKey := make(map[string]*ProtectionData)
|
||||
for _, item := range wanted.Data {
|
||||
dataByPubKey[item.Pubkey] = item
|
||||
}
|
||||
for _, item := range eipStandard.Data {
|
||||
want, ok := dataByPubKey[item.Pubkey]
|
||||
require.Equal(t, true, ok)
|
||||
require.DeepEqual(t, want, item)
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user