mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-10 05:47:59 -05:00
Compare commits
117 Commits
v2.0.1
...
revamp-ser
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2361dff95e | ||
|
|
3d139d35f6 | ||
|
|
ea38969af2 | ||
|
|
2b81953117 | ||
|
|
f597366760 | ||
|
|
91d1bf0f0f | ||
|
|
40983b291a | ||
|
|
dd74e82e56 | ||
|
|
f753ce81cc | ||
|
|
9d678b0c47 | ||
|
|
4a4a7e97df | ||
|
|
652b1617ed | ||
|
|
42edc4f8dd | ||
|
|
70d5bc448f | ||
|
|
d1159308c8 | ||
|
|
e01298bd08 | ||
|
|
2bcb62db28 | ||
|
|
672fb72a7f | ||
|
|
7fbd5b06da | ||
|
|
0fb91437fc | ||
|
|
6e731bdedd | ||
|
|
40eb718ba2 | ||
|
|
e1840f7523 | ||
|
|
b07e1ba7a4 | ||
|
|
233171d17c | ||
|
|
2b0e132201 | ||
|
|
ad9e5331f5 | ||
|
|
341a2f1ea3 | ||
|
|
7974fe01cd | ||
|
|
ae56f643eb | ||
|
|
2ea09b621e | ||
|
|
40fedee137 | ||
|
|
7cdddcb015 | ||
|
|
4440ac199f | ||
|
|
d78428c49e | ||
|
|
2e45fada34 | ||
|
|
4c18d291f4 | ||
|
|
dfe33b0770 | ||
|
|
63308239d9 | ||
|
|
712cc18ee0 | ||
|
|
3d318cffa2 | ||
|
|
026207fc16 | ||
|
|
6b7b30ce47 | ||
|
|
105bb70b5e | ||
|
|
9564ab1f7f | ||
|
|
0b09e3e955 | ||
|
|
bb319e02e8 | ||
|
|
53c86429e4 | ||
|
|
61172d5007 | ||
|
|
1507719613 | ||
|
|
4c677e7b40 | ||
|
|
28f50862cb | ||
|
|
2dfb0696f7 | ||
|
|
ae2c883aaf | ||
|
|
ad9ef9d803 | ||
|
|
b837f90b35 | ||
|
|
7f3ec4221f | ||
|
|
5b3375638a | ||
|
|
3c721418db | ||
|
|
d7cad27cc3 | ||
|
|
290b4273dd | ||
|
|
a797a7aaac | ||
|
|
f7c34b0fd6 | ||
|
|
c6874e33f7 | ||
|
|
13ddc171eb | ||
|
|
acde184aa7 | ||
|
|
5fd6474e56 | ||
|
|
a7d7052d5d | ||
|
|
0c86e7bee5 | ||
|
|
a37eb3a00b | ||
|
|
34985f2d12 | ||
|
|
dc38ed5f5f | ||
|
|
f8bfe7c564 | ||
|
|
2bf9473005 | ||
|
|
be1780ebe9 | ||
|
|
b3a08148e0 | ||
|
|
5609c71e0d | ||
|
|
65db331eaf | ||
|
|
7b8aedbfe4 | ||
|
|
cf956c718d | ||
|
|
975f0ea1af | ||
|
|
a80b1c252a | ||
|
|
1f51e59bfd | ||
|
|
bfcb113f78 | ||
|
|
20c7efda2c | ||
|
|
f2990d8fdd | ||
|
|
d1f3050d20 | ||
|
|
4dbb5d6974 | ||
|
|
4134b55380 | ||
|
|
3884f85b20 | ||
|
|
1e8c7e7795 | ||
|
|
7ae997bfbc | ||
|
|
f8cddcd626 | ||
|
|
5b49e169d7 | ||
|
|
59547aea66 | ||
|
|
545424dd09 | ||
|
|
7d81c7515a | ||
|
|
508b18f1bd | ||
|
|
e644e6b626 | ||
|
|
280dc4ecf0 | ||
|
|
7a825a79ae | ||
|
|
b81f5fc7a5 | ||
|
|
06c084ff52 | ||
|
|
76e06438e9 | ||
|
|
f8f037b63d | ||
|
|
f114a47b5b | ||
|
|
65d2df4609 | ||
|
|
63349d863b | ||
|
|
e2a00d3e2e | ||
|
|
271ee2ed32 | ||
|
|
b5f0bd88b0 | ||
|
|
e7085897ad | ||
|
|
d9b98e9913 | ||
|
|
a9f9026c78 | ||
|
|
b128d446f2 | ||
|
|
9aa50352b6 | ||
|
|
362dfa691a |
3
.bazelrc
3
.bazelrc
@@ -36,6 +36,9 @@ run --define blst_disabled=false
|
||||
build:blst_disabled --define blst_disabled=true
|
||||
build:blst_disabled --define gotags=blst_disabled
|
||||
|
||||
build:minimal --//proto:network=minimal
|
||||
build:minimal --@io_bazel_rules_go//go/config:tags=minimal
|
||||
|
||||
# Release flags
|
||||
build:release --compilation_mode=opt
|
||||
build:release --config=llvm
|
||||
|
||||
@@ -1 +1 @@
|
||||
3.7.0
|
||||
4.2.1
|
||||
|
||||
4
.github/workflows/go.yml
vendored
4
.github/workflows/go.yml
vendored
@@ -34,12 +34,12 @@ jobs:
|
||||
- name: Gosec security scanner
|
||||
uses: securego/gosec@master
|
||||
with:
|
||||
args: '-exclude-dir=crypto/bls/herumi ./...'
|
||||
args: '-exclude=G307 -exclude-dir=crypto/bls/herumi ./...'
|
||||
|
||||
- name: Golangci-lint
|
||||
uses: golangci/golangci-lint-action@v2
|
||||
with:
|
||||
args: --print-issued-lines --sort-results --no-config --timeout=10m --disable-all -E deadcode --skip-files=validator/web/site_data.go
|
||||
args: --print-issued-lines --sort-results --no-config --timeout=10m --disable-all -E deadcode -E errcheck -E gosimple --skip-files=validator/web/site_data.go
|
||||
|
||||
build:
|
||||
name: Build
|
||||
|
||||
@@ -5,21 +5,22 @@ Contact: mailto:security@prysmaticlabs.com
|
||||
Encryption: openpgp4fpr:0AE0051D647BA3C1A917AF4072E33E4DF1A5036E
|
||||
Encryption: openpgp4fpr:CD08DE68C60B82D3EE2A3F7D95452A701810FEDB
|
||||
Encryption: openpgp4fpr:317D6E91058F8F3C2303BA7756313E44581297A6
|
||||
Encryption: openpgp4fpr:79C59A585E3FD3AFFA00F5C22940A6479DA7C9EC
|
||||
Preferred-Languages: en
|
||||
Canonical: https://github.com/prysmaticlabs/prysm/tree/master/.well-known/security.txt
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
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
|
||||
iQIzBAEBCgAdFiEECuAFHWR7o8GpF69AcuM+TfGlA24FAmGOfiYACgkQcuM+TfGl
|
||||
A24YwRAAiQk3w6yzqSEggrOlNoNn04iu/rWZdn5ihkQgzACXy8XH2D1gdKLChE/X
|
||||
7e5bUtgE2aCuHryQjwoKxqZakviBJFstVmHgF64rXv2zKhpqA30Mj4fI+T3zn8I+
|
||||
+FpFV0TTsxNLDx+AcR1eQ1nSayO7ImUDIfOQNDDnSZZy42Bc+F+QIGKB3aH/8bpG
|
||||
kT+bDTZrXvX+TE1gZTbAtZG8sH8g/zadoWEHIhfXUuYb0kTz+DRzAxoqU4j4Z4ee
|
||||
1zSfFAgfJwxJP4kWD7s4xkE1sBbCgGBeD6cW/C2lbcfIei+XSizLpHW3jD9dNqh4
|
||||
fLkmEspSa/LV/iXFq8nFzu/GLww4q+sQZDzzDKZyws54CrATinRitZMhzoIL0bTn
|
||||
yFZVOGHosFAMEVZ36dl1Aw2+B2W6tr2CVr9c5zfV+kup5/KZH1EmT5nYY/zFwfg2
|
||||
jYCFB5wmYeiyWZvuprgJXRArgVZLZaJxwWazlPVk4i/4vPvRgvfHqOwHCBe8DXy0
|
||||
VHPhpewwb/ECYek1KoaNQflgR8iH2GMHkC5RjhGDAt1S0AQDtite5m4ZYt1kvO9E
|
||||
k/znkv89dduhL9CKDvZvnI+DICwsTrf//4KJ8PM/qaPAJa4GvtiUU/eS/jKBivtv
|
||||
OP5dZQtX6KPc9ewqqZgn622uHSezoBidgeTkdZsJ6tw2eIu0lsY=
|
||||
=V7L0
|
||||
-----END PGP SIGNATURE-----
|
||||
|
||||
@@ -144,12 +144,6 @@ common_files = {
|
||||
"//:README.md": "README.md",
|
||||
}
|
||||
|
||||
toolchain(
|
||||
name = "built_cmake_toolchain",
|
||||
toolchain = "@rules_foreign_cc//tools/build_defs/native_tools:built_cmake",
|
||||
toolchain_type = "@rules_foreign_cc//tools/build_defs:cmake_toolchain",
|
||||
)
|
||||
|
||||
string_setting(
|
||||
name = "gotags",
|
||||
build_setting_default = "",
|
||||
|
||||
18
WORKSPACE
18
WORKSPACE
@@ -225,7 +225,7 @@ filegroup(
|
||||
url = "https://github.com/eth2-clients/slashing-protection-interchange-tests/archive/b8413ca42dc92308019d0d4db52c87e9e125c4e9.tar.gz",
|
||||
)
|
||||
|
||||
consensus_spec_version = "v1.1.0"
|
||||
consensus_spec_version = "v1.1.5"
|
||||
|
||||
bls_test_version = "v0.1.1"
|
||||
|
||||
@@ -241,7 +241,7 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "0f58ec1c8995ab2c0a3aada873e1a02f333c8659fdacaa1c76fbdce28b6177dc",
|
||||
sha256 = "a7d7173d953494c0dfde432c9fc064c25d46d666b024749b3474ae0cdfc50050",
|
||||
url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/general.tar.gz" % consensus_spec_version,
|
||||
)
|
||||
|
||||
@@ -257,7 +257,7 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "d2eeadef3f8885748f769a06eb916bea60fb00112a90cec3288ea78db5557df3",
|
||||
sha256 = "f86872061588c0197516b23025d39e9365b4716c112218a618739dc0d6f4666a",
|
||||
url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/minimal.tar.gz" % consensus_spec_version,
|
||||
)
|
||||
|
||||
@@ -273,7 +273,7 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "bbc345432f4eaa4babe2619e16fcf3f607113ede82d1bd0fff2633c1376419f7",
|
||||
sha256 = "7a06975360fd37fbb4694d0e06abb78d2a0835146c1d9b26d33569edff8b98f0",
|
||||
url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/mainnet.tar.gz" % consensus_spec_version,
|
||||
)
|
||||
|
||||
@@ -288,7 +288,7 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "787a50c2a03bebab92f089333f598780ca7b4849b36a4897e6603ddd3e86ec24",
|
||||
sha256 = "87d8089200163340484d61212fbdffbb5d9d03e1244622761dcb91e641a65761",
|
||||
strip_prefix = "consensus-specs-" + consensus_spec_version[1:],
|
||||
url = "https://github.com/ethereum/consensus-specs/archive/refs/tags/%s.tar.gz" % consensus_spec_version,
|
||||
)
|
||||
@@ -362,9 +362,9 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "54ce527b83d092da01127f2e3816f4d5cfbab69354caba8537f1ea55889b6d7c",
|
||||
sha256 = "0a3d94428ea28916276694c517b82b364122063fdbf924f54ee9ae0bc500289f",
|
||||
urls = [
|
||||
"https://github.com/prysmaticlabs/prysm-web-ui/releases/download/v1.0.0-beta.4/prysm-web-ui.tar.gz",
|
||||
"https://github.com/prysmaticlabs/prysm-web-ui/releases/download/v1.0.1/prysm-web-ui.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -395,10 +395,6 @@ load(
|
||||
|
||||
_cc_image_repos()
|
||||
|
||||
load("@com_github_ethereum_go_ethereum//:deps.bzl", "geth_dependencies")
|
||||
|
||||
geth_dependencies()
|
||||
|
||||
load("@io_bazel_rules_go//extras:embed_data_deps.bzl", "go_embed_data_dependencies")
|
||||
|
||||
go_embed_data_dependencies()
|
||||
|
||||
@@ -125,12 +125,12 @@ func (m *ApiProxyMiddleware) handleApiPath(gatewayRouter *mux.Router, path strin
|
||||
|
||||
var respJson []byte
|
||||
if !GrpcResponseIsEmpty(grpcRespBody) {
|
||||
if errJson := DeserializeGrpcResponseBodyIntoErrorJson(endpoint.Err, grpcRespBody); errJson != nil {
|
||||
respHasError, errJson := HandleGrpcResponseError(endpoint.Err, grpcResp, grpcRespBody, w)
|
||||
if errJson != nil {
|
||||
WriteError(w, errJson, nil)
|
||||
return
|
||||
}
|
||||
if endpoint.Err.Msg() != "" {
|
||||
HandleGrpcResponseError(endpoint.Err, grpcResp, w)
|
||||
if respHasError {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -97,26 +97,25 @@ func ReadGrpcResponseBody(r io.Reader) ([]byte, ErrorJson) {
|
||||
return body, nil
|
||||
}
|
||||
|
||||
// DeserializeGrpcResponseBodyIntoErrorJson deserializes the body from the grpc-gateway's response into an error struct.
|
||||
// The struct can be later examined to check if the request resulted in an error.
|
||||
func DeserializeGrpcResponseBodyIntoErrorJson(errJson ErrorJson, body []byte) ErrorJson {
|
||||
if err := json.Unmarshal(body, errJson); err != nil {
|
||||
return InternalServerErrorWithMessage(err, "could not unmarshal error")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// HandleGrpcResponseError acts on an error that resulted from a grpc-gateway's response.
|
||||
func HandleGrpcResponseError(errJson ErrorJson, resp *http.Response, w http.ResponseWriter) {
|
||||
// Something went wrong, but the request completed, meaning we can write headers and the error message.
|
||||
for h, vs := range resp.Header {
|
||||
for _, v := range vs {
|
||||
w.Header().Set(h, v)
|
||||
}
|
||||
func HandleGrpcResponseError(errJson ErrorJson, resp *http.Response, respBody []byte, w http.ResponseWriter) (bool, ErrorJson) {
|
||||
responseHasError := false
|
||||
if err := json.Unmarshal(respBody, errJson); err != nil {
|
||||
return false, InternalServerErrorWithMessage(err, "could not unmarshal error")
|
||||
}
|
||||
// Set code to HTTP code because unmarshalled body contained gRPC code.
|
||||
errJson.SetCode(resp.StatusCode)
|
||||
WriteError(w, errJson, resp.Header)
|
||||
if errJson.Msg() != "" {
|
||||
responseHasError = true
|
||||
// Something went wrong, but the request completed, meaning we can write headers and the error message.
|
||||
for h, vs := range resp.Header {
|
||||
for _, v := range vs {
|
||||
w.Header().Set(h, v)
|
||||
}
|
||||
}
|
||||
// Set code to HTTP code because unmarshalled body contained gRPC code.
|
||||
errJson.SetCode(resp.StatusCode)
|
||||
WriteError(w, errJson, resp.Header)
|
||||
}
|
||||
return responseHasError, nil
|
||||
}
|
||||
|
||||
// GrpcResponseIsEmpty determines whether the grpc-gateway's response body contains no data.
|
||||
@@ -201,9 +200,11 @@ func WriteMiddlewareResponseHeadersAndBody(grpcResp *http.Response, responseJson
|
||||
// WriteError writes the error by manipulating headers and the body of the final response.
|
||||
func WriteError(w http.ResponseWriter, errJson ErrorJson, responseHeader http.Header) {
|
||||
// Include custom error in the error JSON.
|
||||
hasCustomError := false
|
||||
if responseHeader != nil {
|
||||
customError, ok := responseHeader["Grpc-Metadata-"+grpc.CustomErrorMetadataKey]
|
||||
if ok {
|
||||
hasCustomError = true
|
||||
// Assume header has only one value and read the 0 index.
|
||||
if err := json.Unmarshal([]byte(customError[0]), errJson); err != nil {
|
||||
log.WithError(err).Error("Could not unmarshal custom error message")
|
||||
@@ -212,10 +213,29 @@ func WriteError(w http.ResponseWriter, errJson ErrorJson, responseHeader http.He
|
||||
}
|
||||
}
|
||||
|
||||
j, err := json.Marshal(errJson)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not marshal error message")
|
||||
return
|
||||
var j []byte
|
||||
if hasCustomError {
|
||||
var err error
|
||||
j, err = json.Marshal(errJson)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not marshal error message")
|
||||
return
|
||||
}
|
||||
} else {
|
||||
var err error
|
||||
// We marshal the response body into a DefaultErrorJson if the custom error is not present.
|
||||
// This is because the ErrorJson argument is the endpoint's error definition, which may contain custom fields.
|
||||
// In such a scenario marhaling the endpoint's error would populate the resulting JSON
|
||||
// with these fields even if they are not present in the gRPC header.
|
||||
d := &DefaultErrorJson{
|
||||
Message: errJson.Msg(),
|
||||
Code: errJson.StatusCode(),
|
||||
}
|
||||
j, err = json.Marshal(d)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not marshal error message")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Length", strconv.Itoa(len(j)))
|
||||
|
||||
@@ -63,6 +63,11 @@ func (e *testErrorJson) SetCode(code int) {
|
||||
e.Code = code
|
||||
}
|
||||
|
||||
// SetMsg sets the error's underlying message.
|
||||
func (e *testErrorJson) SetMsg(msg string) {
|
||||
e.Message = msg
|
||||
}
|
||||
|
||||
func TestDeserializeRequestBodyIntoContainer(t *testing.T) {
|
||||
t.Run("ok", func(t *testing.T) {
|
||||
var bodyJson bytes.Buffer
|
||||
@@ -156,29 +161,6 @@ func TestReadGrpcResponseBody(t *testing.T) {
|
||||
assert.Equal(t, "foo", string(body))
|
||||
}
|
||||
|
||||
func TestDeserializeGrpcResponseBodyIntoErrorJson(t *testing.T) {
|
||||
t.Run("ok", func(t *testing.T) {
|
||||
e := &testErrorJson{
|
||||
Message: "foo",
|
||||
Code: 500,
|
||||
}
|
||||
body, err := json.Marshal(e)
|
||||
require.NoError(t, err)
|
||||
|
||||
eToDeserialize := &testErrorJson{}
|
||||
errJson := DeserializeGrpcResponseBodyIntoErrorJson(eToDeserialize, body)
|
||||
require.Equal(t, true, errJson == nil)
|
||||
assert.Equal(t, "foo", eToDeserialize.Msg())
|
||||
assert.Equal(t, 500, eToDeserialize.StatusCode())
|
||||
})
|
||||
|
||||
t.Run("error", func(t *testing.T) {
|
||||
errJson := DeserializeGrpcResponseBodyIntoErrorJson(nil, nil)
|
||||
require.NotNil(t, errJson)
|
||||
assert.Equal(t, true, strings.Contains(errJson.Msg(), "could not unmarshal error"))
|
||||
})
|
||||
}
|
||||
|
||||
func TestHandleGrpcResponseError(t *testing.T) {
|
||||
response := &http.Response{
|
||||
StatusCode: 400,
|
||||
@@ -190,10 +172,14 @@ func TestHandleGrpcResponseError(t *testing.T) {
|
||||
writer := httptest.NewRecorder()
|
||||
errJson := &testErrorJson{
|
||||
Message: "foo",
|
||||
Code: 500,
|
||||
Code: 400,
|
||||
}
|
||||
b, err := json.Marshal(errJson)
|
||||
require.NoError(t, err)
|
||||
|
||||
HandleGrpcResponseError(errJson, response, writer)
|
||||
hasError, e := HandleGrpcResponseError(errJson, response, b, writer)
|
||||
require.Equal(t, true, e == nil)
|
||||
assert.Equal(t, true, hasError)
|
||||
v, ok := writer.Header()["Foo"]
|
||||
require.Equal(t, true, ok, "header not found")
|
||||
require.Equal(t, 1, len(v), "wrong number of header values")
|
||||
|
||||
@@ -15,6 +15,7 @@ type ErrorJson interface {
|
||||
StatusCode() int
|
||||
SetCode(code int)
|
||||
Msg() string
|
||||
SetMsg(msg string)
|
||||
}
|
||||
|
||||
// DefaultErrorJson is a JSON representation of a simple error value, containing only a message and an error code.
|
||||
@@ -54,3 +55,8 @@ func (e *DefaultErrorJson) Msg() string {
|
||||
func (e *DefaultErrorJson) SetCode(code int) {
|
||||
e.Code = code
|
||||
}
|
||||
|
||||
// SetMsg sets the error's underlying message.
|
||||
func (e *DefaultErrorJson) SetMsg(msg string) {
|
||||
e.Message = msg
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ go_library(
|
||||
"init_sync_process_block.go",
|
||||
"log.go",
|
||||
"metrics.go",
|
||||
"options.go",
|
||||
"process_attestation.go",
|
||||
"process_attestation_helpers.go",
|
||||
"process_block.go",
|
||||
@@ -22,6 +23,7 @@ go_library(
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/blockchain",
|
||||
visibility = [
|
||||
"//beacon-chain:__subpackages__",
|
||||
"//cmd/beacon-chain:__subpackages__",
|
||||
"//testing/fuzz:__pkg__",
|
||||
"//testing/slasher/simulator:__pkg__",
|
||||
],
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
func TestHeadSlot_DataRace(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
s := &Service{
|
||||
cfg: &Config{BeaconDB: beaconDB},
|
||||
cfg: &config{BeaconDB: beaconDB},
|
||||
}
|
||||
go func() {
|
||||
require.NoError(t, s.saveHead(context.Background(), [32]byte{}))
|
||||
@@ -25,7 +25,7 @@ func TestHeadSlot_DataRace(t *testing.T) {
|
||||
func TestHeadRoot_DataRace(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
s := &Service{
|
||||
cfg: &Config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB)},
|
||||
cfg: &config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB)},
|
||||
head: &head{root: [32]byte{'A'}},
|
||||
}
|
||||
go func() {
|
||||
@@ -38,7 +38,7 @@ func TestHeadRoot_DataRace(t *testing.T) {
|
||||
func TestHeadBlock_DataRace(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
s := &Service{
|
||||
cfg: &Config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB)},
|
||||
cfg: &config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB)},
|
||||
head: &head{block: wrapper.WrappedPhase0SignedBeaconBlock(ðpb.SignedBeaconBlock{})},
|
||||
}
|
||||
go func() {
|
||||
@@ -51,7 +51,7 @@ func TestHeadBlock_DataRace(t *testing.T) {
|
||||
func TestHeadState_DataRace(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
s := &Service{
|
||||
cfg: &Config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB)},
|
||||
cfg: &config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB)},
|
||||
}
|
||||
go func() {
|
||||
require.NoError(t, s.saveHead(context.Background(), [32]byte{}))
|
||||
|
||||
@@ -120,7 +120,7 @@ func TestHeadRoot_CanRetrieve(t *testing.T) {
|
||||
|
||||
func TestHeadRoot_UseDB(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
c := &Service{cfg: &Config{BeaconDB: beaconDB}}
|
||||
c := &Service{cfg: &config{BeaconDB: beaconDB}}
|
||||
c.head = &head{root: params.BeaconConfig().ZeroHash}
|
||||
b := util.NewBeaconBlock()
|
||||
br, err := b.Block.HashTreeRoot()
|
||||
@@ -278,14 +278,14 @@ func TestService_HeadGenesisValidatorRoot(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestService_ProtoArrayStore(t *testing.T) {
|
||||
c := &Service{cfg: &Config{ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}}
|
||||
c := &Service{cfg: &config{ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}}
|
||||
p := c.ProtoArrayStore()
|
||||
require.Equal(t, 0, int(p.FinalizedEpoch()))
|
||||
}
|
||||
|
||||
func TestService_ChainHeads(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
c := &Service{cfg: &Config{ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}}
|
||||
c := &Service{cfg: &config{ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}}
|
||||
require.NoError(t, c.cfg.ForkChoiceStore.ProcessBlock(ctx, 100, [32]byte{'a'}, [32]byte{}, [32]byte{}, 0, 0))
|
||||
require.NoError(t, c.cfg.ForkChoiceStore.ProcessBlock(ctx, 101, [32]byte{'b'}, [32]byte{'a'}, [32]byte{}, 0, 0))
|
||||
require.NoError(t, c.cfg.ForkChoiceStore.ProcessBlock(ctx, 102, [32]byte{'c'}, [32]byte{'b'}, [32]byte{}, 0, 0))
|
||||
|
||||
@@ -107,8 +107,8 @@ func (s *Service) saveHead(ctx context.Context, headRoot [32]byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if newHeadBlock == nil || newHeadBlock.IsNil() || newHeadBlock.Block().IsNil() {
|
||||
return errors.New("cannot save nil head block")
|
||||
if err := helpers.BeaconBlockIsNil(newHeadBlock); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Get the new head state from cached state or DB.
|
||||
@@ -175,7 +175,7 @@ func (s *Service) saveHead(ctx context.Context, headRoot [32]byte) error {
|
||||
// root in DB. With the inception of initial-sync-cache-state flag, it uses finalized
|
||||
// check point as anchors to resume sync therefore head is no longer needed to be saved on per slot basis.
|
||||
func (s *Service) saveHeadNoDB(ctx context.Context, b block.SignedBeaconBlock, r [32]byte, hs state.BeaconState) error {
|
||||
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
|
||||
if err := helpers.BeaconBlockIsNil(b); err != nil {
|
||||
return err
|
||||
}
|
||||
cachedHeadRoot, err := s.HeadRoot(ctx)
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
func TestService_headSyncCommitteeFetcher_Errors(t *testing.T) {
|
||||
beaconDB := dbtest.SetupDB(t)
|
||||
c := &Service{
|
||||
cfg: &Config{
|
||||
cfg: &config{
|
||||
StateGen: stategen.New(beaconDB),
|
||||
},
|
||||
}
|
||||
@@ -36,7 +36,7 @@ func TestService_headSyncCommitteeFetcher_Errors(t *testing.T) {
|
||||
func TestService_HeadDomainFetcher_Errors(t *testing.T) {
|
||||
beaconDB := dbtest.SetupDB(t)
|
||||
c := &Service{
|
||||
cfg: &Config{
|
||||
cfg: &config{
|
||||
StateGen: stategen.New(beaconDB),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -153,7 +153,7 @@ func Test_notifyNewHeadEvent(t *testing.T) {
|
||||
bState, _ := util.DeterministicGenesisState(t, 10)
|
||||
notifier := &mock.MockStateNotifier{RecordEvents: true}
|
||||
srv := &Service{
|
||||
cfg: &Config{
|
||||
cfg: &config{
|
||||
StateNotifier: notifier,
|
||||
},
|
||||
genesisRoot: [32]byte{1},
|
||||
@@ -182,7 +182,7 @@ func Test_notifyNewHeadEvent(t *testing.T) {
|
||||
notifier := &mock.MockStateNotifier{RecordEvents: true}
|
||||
genesisRoot := [32]byte{1}
|
||||
srv := &Service{
|
||||
cfg: &Config{
|
||||
cfg: &config{
|
||||
StateNotifier: notifier,
|
||||
},
|
||||
genesisRoot: genesisRoot,
|
||||
|
||||
@@ -25,7 +25,7 @@ func TestService_TreeHandler(t *testing.T) {
|
||||
headState, err := util.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, headState.SetBalances([]uint64{params.BeaconConfig().GweiPerEth}))
|
||||
cfg := &Config{
|
||||
cfg := &config{
|
||||
BeaconDB: beaconDB,
|
||||
ForkChoiceStore: protoarray.New(
|
||||
0, // justifiedEpoch
|
||||
@@ -34,8 +34,9 @@ func TestService_TreeHandler(t *testing.T) {
|
||||
),
|
||||
StateGen: stategen.New(beaconDB),
|
||||
}
|
||||
s, err := NewService(ctx, cfg)
|
||||
s, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
s.cfg = cfg
|
||||
require.NoError(t, s.cfg.ForkChoiceStore.ProcessBlock(ctx, 0, [32]byte{'a'}, [32]byte{'g'}, [32]byte{'c'}, 0, 0))
|
||||
require.NoError(t, s.cfg.ForkChoiceStore.ProcessBlock(ctx, 1, [32]byte{'b'}, [32]byte{'a'}, [32]byte{'c'}, 0, 0))
|
||||
s.setHead([32]byte{'a'}, wrapper.WrappedPhase0SignedBeaconBlock(util.NewBeaconBlock()), headState)
|
||||
|
||||
@@ -55,6 +55,8 @@ func logBlockSyncStatus(block block.BeaconBlock, blockRoot [32]byte, finalized *
|
||||
"epoch": slots.ToEpoch(block.Slot()),
|
||||
"finalizedEpoch": finalized.Epoch,
|
||||
"finalizedRoot": fmt.Sprintf("0x%s...", hex.EncodeToString(finalized.Root)[:8]),
|
||||
"parentRoot": fmt.Sprintf("0x%s...", hex.EncodeToString(block.ParentRoot())[:8]),
|
||||
"version": version.String(block.Version()),
|
||||
}).Info("Synced new block")
|
||||
log.WithFields(logrus.Fields{
|
||||
"slot": block.Slot,
|
||||
|
||||
139
beacon-chain/blockchain/options.go
Normal file
139
beacon-chain/blockchain/options.go
Normal file
@@ -0,0 +1,139 @@
|
||||
package blockchain
|
||||
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/async/event"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
|
||||
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/attestations"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/slashings"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
type Option func(s *Service) error
|
||||
|
||||
// WithMaxGoroutines to control resource use of the blockchain service.
|
||||
func WithMaxGoroutines(x int) Option {
|
||||
return func(s *Service) error {
|
||||
s.cfg.MaxRoutines = x
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithWeakSubjectivityCheckpoint for checkpoint sync.
|
||||
func WithWeakSubjectivityCheckpoint(c *ethpb.Checkpoint) Option {
|
||||
return func(s *Service) error {
|
||||
s.cfg.WeakSubjectivityCheckpt = c
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithDatabase for head access.
|
||||
func WithDatabase(beaconDB db.HeadAccessDatabase) Option {
|
||||
return func(s *Service) error {
|
||||
s.cfg.BeaconDB = beaconDB
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithChainStartFetcher to retrieve information about genesis.
|
||||
func WithChainStartFetcher(f powchain.ChainStartFetcher) Option {
|
||||
return func(s *Service) error {
|
||||
s.cfg.ChainStartFetcher = f
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithDepositCache for deposit lifecycle after chain inclusion.
|
||||
func WithDepositCache(c *depositcache.DepositCache) Option {
|
||||
return func(s *Service) error {
|
||||
s.cfg.DepositCache = c
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithAttestationPool for attestation lifecycle after chain inclusion.
|
||||
func WithAttestationPool(p attestations.Pool) Option {
|
||||
return func(s *Service) error {
|
||||
s.cfg.AttPool = p
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithExitPool for exits lifecycle after chain inclusion.
|
||||
func WithExitPool(p voluntaryexits.PoolManager) Option {
|
||||
return func(s *Service) error {
|
||||
s.cfg.ExitPool = p
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithSlashingPool for slashings lifecycle after chain inclusion.
|
||||
func WithSlashingPool(p slashings.PoolManager) Option {
|
||||
return func(s *Service) error {
|
||||
s.cfg.SlashingPool = p
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithP2PBroadcaster to broadcast messages after appropriate processing.
|
||||
func WithP2PBroadcaster(p p2p.Broadcaster) Option {
|
||||
return func(s *Service) error {
|
||||
s.cfg.P2p = p
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithStateNotifier to notify an event feed of state processing.
|
||||
func WithStateNotifier(n statefeed.Notifier) Option {
|
||||
return func(s *Service) error {
|
||||
s.cfg.StateNotifier = n
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithForkChoiceStore to update an optimized fork-choice representation.
|
||||
func WithForkChoiceStore(f forkchoice.ForkChoicer) Option {
|
||||
return func(s *Service) error {
|
||||
s.cfg.ForkChoiceStore = f
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithAttestationService for dealing with attestation lifecycles.
|
||||
func WithAttestationService(srv *attestations.Service) Option {
|
||||
return func(s *Service) error {
|
||||
s.cfg.AttService = srv
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithStateGen for managing state regeneration and replay.
|
||||
func WithStateGen(g *stategen.State) Option {
|
||||
return func(s *Service) error {
|
||||
s.cfg.StateGen = g
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithSlasherAttestationsFeed to forward attestations into slasher if enabled.
|
||||
func WithSlasherAttestationsFeed(f *event.Feed) Option {
|
||||
return func(s *Service) error {
|
||||
s.cfg.SlasherAttestationsFeed = f
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithFinalizedStateAtStartUp to store finalized state at start up.
|
||||
func WithFinalizedStateAtStartUp(st state.BeaconState) Option {
|
||||
return func(s *Service) error {
|
||||
s.cfg.FinalizedStateAtStartUp = st
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -87,7 +87,7 @@ func (s *Service) verifyBeaconBlock(ctx context.Context, data *ethpb.Attestation
|
||||
if (b == nil || b.IsNil()) && s.hasInitSyncBlock(r) {
|
||||
b = s.getInitSyncBlock(r)
|
||||
}
|
||||
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
|
||||
if err := helpers.BeaconBlockIsNil(b); err != nil {
|
||||
return err
|
||||
}
|
||||
if b.Block().Slot() > data.Slot {
|
||||
|
||||
@@ -24,13 +24,14 @@ func TestStore_OnAttestation_ErrorConditions(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{
|
||||
cfg := &config{
|
||||
BeaconDB: beaconDB,
|
||||
ForkChoiceStore: protoarray.New(0, 0, [32]byte{}),
|
||||
StateGen: stategen.New(beaconDB),
|
||||
}
|
||||
service, err := NewService(ctx, cfg)
|
||||
service, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
service.cfg = cfg
|
||||
|
||||
_, err = blockTree1(t, beaconDB, []byte{'g'})
|
||||
require.NoError(t, err)
|
||||
@@ -130,13 +131,14 @@ func TestStore_OnAttestation_Ok(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{
|
||||
cfg := &config{
|
||||
BeaconDB: beaconDB,
|
||||
ForkChoiceStore: protoarray.New(0, 0, [32]byte{}),
|
||||
StateGen: stategen.New(beaconDB),
|
||||
}
|
||||
service, err := NewService(ctx, cfg)
|
||||
service, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
service.cfg = cfg
|
||||
genesisState, pks := util.DeterministicGenesisState(t, 64)
|
||||
require.NoError(t, genesisState.SetGenesisTime(uint64(time.Now().Unix())-params.BeaconConfig().SecondsPerSlot))
|
||||
require.NoError(t, service.saveGenesisData(ctx, genesisState))
|
||||
@@ -155,12 +157,13 @@ func TestStore_SaveCheckpointState(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{
|
||||
cfg := &config{
|
||||
BeaconDB: beaconDB,
|
||||
StateGen: stategen.New(beaconDB),
|
||||
}
|
||||
service, err := NewService(ctx, cfg)
|
||||
service, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
service.cfg = cfg
|
||||
|
||||
s, err := util.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
@@ -227,12 +230,13 @@ func TestStore_UpdateCheckpointState(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{
|
||||
cfg := &config{
|
||||
BeaconDB: beaconDB,
|
||||
StateGen: stategen.New(beaconDB),
|
||||
}
|
||||
service, err := NewService(ctx, cfg)
|
||||
service, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
service.cfg = cfg
|
||||
|
||||
epoch := types.Epoch(1)
|
||||
baseState, _ := util.DeterministicGenesisState(t, 1)
|
||||
@@ -266,9 +270,10 @@ func TestAttEpoch_MatchPrevEpoch(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{BeaconDB: beaconDB}
|
||||
service, err := NewService(ctx, cfg)
|
||||
cfg := &config{BeaconDB: beaconDB}
|
||||
service, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
service.cfg = cfg
|
||||
|
||||
nowTime := uint64(params.BeaconConfig().SlotsPerEpoch) * params.BeaconConfig().SecondsPerSlot
|
||||
require.NoError(t, service.verifyAttTargetEpoch(ctx, 0, nowTime, ðpb.Checkpoint{Root: make([]byte, 32)}))
|
||||
@@ -278,9 +283,10 @@ func TestAttEpoch_MatchCurrentEpoch(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{BeaconDB: beaconDB}
|
||||
service, err := NewService(ctx, cfg)
|
||||
cfg := &config{BeaconDB: beaconDB}
|
||||
service, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
service.cfg = cfg
|
||||
|
||||
nowTime := uint64(params.BeaconConfig().SlotsPerEpoch) * params.BeaconConfig().SecondsPerSlot
|
||||
require.NoError(t, service.verifyAttTargetEpoch(ctx, 0, nowTime, ðpb.Checkpoint{Epoch: 1}))
|
||||
@@ -290,9 +296,10 @@ func TestAttEpoch_NotMatch(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{BeaconDB: beaconDB}
|
||||
service, err := NewService(ctx, cfg)
|
||||
cfg := &config{BeaconDB: beaconDB}
|
||||
service, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
service.cfg = cfg
|
||||
|
||||
nowTime := 2 * uint64(params.BeaconConfig().SlotsPerEpoch) * params.BeaconConfig().SecondsPerSlot
|
||||
err = service.verifyAttTargetEpoch(ctx, 0, nowTime, ðpb.Checkpoint{Root: make([]byte, 32)})
|
||||
@@ -303,9 +310,10 @@ func TestVerifyBeaconBlock_NoBlock(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{BeaconDB: beaconDB}
|
||||
service, err := NewService(ctx, cfg)
|
||||
cfg := &config{BeaconDB: beaconDB}
|
||||
service, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
service.cfg = cfg
|
||||
|
||||
d := util.HydrateAttestationData(ðpb.AttestationData{})
|
||||
assert.ErrorContains(t, "signed beacon block can't be nil", service.verifyBeaconBlock(ctx, d))
|
||||
@@ -315,9 +323,10 @@ func TestVerifyBeaconBlock_futureBlock(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{BeaconDB: beaconDB}
|
||||
service, err := NewService(ctx, cfg)
|
||||
cfg := &config{BeaconDB: beaconDB}
|
||||
service, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
service.cfg = cfg
|
||||
|
||||
b := util.NewBeaconBlock()
|
||||
b.Block.Slot = 2
|
||||
@@ -333,9 +342,10 @@ func TestVerifyBeaconBlock_OK(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{BeaconDB: beaconDB}
|
||||
service, err := NewService(ctx, cfg)
|
||||
cfg := &config{BeaconDB: beaconDB}
|
||||
service, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
service.cfg = cfg
|
||||
|
||||
b := util.NewBeaconBlock()
|
||||
b.Block.Slot = 2
|
||||
@@ -351,9 +361,10 @@ func TestVerifyFinalizedConsistency_InconsistentRoot(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{BeaconDB: beaconDB, ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}
|
||||
service, err := NewService(ctx, cfg)
|
||||
cfg := &config{BeaconDB: beaconDB, ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}
|
||||
service, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
service.cfg = cfg
|
||||
|
||||
b32 := util.NewBeaconBlock()
|
||||
b32.Block.Slot = 32
|
||||
@@ -378,9 +389,10 @@ func TestVerifyFinalizedConsistency_OK(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{BeaconDB: beaconDB, ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}
|
||||
service, err := NewService(ctx, cfg)
|
||||
cfg := &config{BeaconDB: beaconDB, ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}
|
||||
service, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
service.cfg = cfg
|
||||
|
||||
b32 := util.NewBeaconBlock()
|
||||
b32.Block.Slot = 32
|
||||
@@ -405,9 +417,10 @@ func TestVerifyFinalizedConsistency_IsCanonical(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{BeaconDB: beaconDB, ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}
|
||||
service, err := NewService(ctx, cfg)
|
||||
cfg := &config{BeaconDB: beaconDB, ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}
|
||||
service, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
service.cfg = cfg
|
||||
|
||||
b32 := util.NewBeaconBlock()
|
||||
b32.Block.Slot = 32
|
||||
|
||||
@@ -88,9 +88,8 @@ var initialSyncBlockCacheSize = uint64(2 * params.BeaconConfig().SlotsPerEpoch)
|
||||
func (s *Service) onBlock(ctx context.Context, signed block.SignedBeaconBlock, blockRoot [32]byte) error {
|
||||
ctx, span := trace.StartSpan(ctx, "blockChain.onBlock")
|
||||
defer span.End()
|
||||
|
||||
if signed == nil || signed.IsNil() || signed.Block().IsNil() {
|
||||
return errors.New("nil block")
|
||||
if err := helpers.BeaconBlockIsNil(signed); err != nil {
|
||||
return err
|
||||
}
|
||||
b := signed.Block()
|
||||
|
||||
@@ -237,8 +236,8 @@ func (s *Service) onBlockBatch(ctx context.Context, blks []block.SignedBeaconBlo
|
||||
if len(blks) == 0 || len(blockRoots) == 0 {
|
||||
return nil, nil, errors.New("no blocks provided")
|
||||
}
|
||||
if blks[0] == nil || blks[0].IsNil() || blks[0].Block().IsNil() {
|
||||
return nil, nil, errors.New("nil block")
|
||||
if err := helpers.BeaconBlockIsNil(blks[0]); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
b := blks[0].Block()
|
||||
|
||||
|
||||
@@ -135,7 +135,24 @@ func (s *Service) verifyBlkFinalizedSlot(b block.BeaconBlock) error {
|
||||
// shouldUpdateCurrentJustified prevents bouncing attack, by only update conflicting justified
|
||||
// checkpoints in the fork choice if in the early slots of the epoch.
|
||||
// Otherwise, delay incorporation of new justified checkpoint until next epoch boundary.
|
||||
// See https://ethresear.ch/t/prevention-of-bouncing-attack-on-ffg/6114 for more detailed analysis and discussion.
|
||||
//
|
||||
// Spec code:
|
||||
// def should_update_justified_checkpoint(store: Store, new_justified_checkpoint: Checkpoint) -> bool:
|
||||
// """
|
||||
// To address the bouncing attack, only update conflicting justified
|
||||
// checkpoints in the fork choice if in the early slots of the epoch.
|
||||
// Otherwise, delay incorporation of new justified checkpoint until next epoch boundary.
|
||||
//
|
||||
// See https://ethresear.ch/t/prevention-of-bouncing-attack-on-ffg/6114 for more detailed analysis and discussion.
|
||||
// """
|
||||
// if compute_slots_since_epoch_start(get_current_slot(store)) < SAFE_SLOTS_TO_UPDATE_JUSTIFIED:
|
||||
// return True
|
||||
//
|
||||
// justified_slot = compute_start_slot_at_epoch(store.justified_checkpoint.epoch)
|
||||
// if not get_ancestor(store, new_justified_checkpoint.root, justified_slot) == store.justified_checkpoint.root:
|
||||
// return False
|
||||
//
|
||||
// return True
|
||||
func (s *Service) shouldUpdateCurrentJustified(ctx context.Context, newJustifiedCheckpt *ethpb.Checkpoint) (bool, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "blockChain.shouldUpdateCurrentJustified")
|
||||
defer span.End()
|
||||
@@ -143,51 +160,20 @@ func (s *Service) shouldUpdateCurrentJustified(ctx context.Context, newJustified
|
||||
if slots.SinceEpochStarts(s.CurrentSlot()) < params.BeaconConfig().SafeSlotsToUpdateJustified {
|
||||
return true, nil
|
||||
}
|
||||
var newJustifiedBlockSigned block.SignedBeaconBlock
|
||||
justifiedRoot := s.ensureRootNotZeros(bytesutil.ToBytes32(newJustifiedCheckpt.Root))
|
||||
var err error
|
||||
if s.hasInitSyncBlock(justifiedRoot) {
|
||||
newJustifiedBlockSigned = s.getInitSyncBlock(justifiedRoot)
|
||||
} else {
|
||||
newJustifiedBlockSigned, err = s.cfg.BeaconDB.Block(ctx, justifiedRoot)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
if newJustifiedBlockSigned == nil || newJustifiedBlockSigned.IsNil() || newJustifiedBlockSigned.Block().IsNil() {
|
||||
return false, errors.New("nil new justified block")
|
||||
}
|
||||
|
||||
newJustifiedBlock := newJustifiedBlockSigned.Block()
|
||||
jSlot, err := slots.EpochStart(s.justifiedCheckpt.Epoch)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if newJustifiedBlock.Slot() <= jSlot {
|
||||
return false, nil
|
||||
}
|
||||
var justifiedBlockSigned block.SignedBeaconBlock
|
||||
cachedJustifiedRoot := s.ensureRootNotZeros(bytesutil.ToBytes32(s.justifiedCheckpt.Root))
|
||||
if s.hasInitSyncBlock(cachedJustifiedRoot) {
|
||||
justifiedBlockSigned = s.getInitSyncBlock(cachedJustifiedRoot)
|
||||
} else {
|
||||
justifiedBlockSigned, err = s.cfg.BeaconDB.Block(ctx, cachedJustifiedRoot)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
if justifiedBlockSigned == nil || justifiedBlockSigned.IsNil() || justifiedBlockSigned.Block().IsNil() {
|
||||
return false, errors.New("nil justified block")
|
||||
}
|
||||
justifiedBlock := justifiedBlockSigned.Block()
|
||||
b, err := s.ancestor(ctx, justifiedRoot[:], justifiedBlock.Slot())
|
||||
justifiedRoot := s.ensureRootNotZeros(bytesutil.ToBytes32(newJustifiedCheckpt.Root))
|
||||
b, err := s.ancestor(ctx, justifiedRoot[:], jSlot)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if !bytes.Equal(b, s.justifiedCheckpt.Root) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -37,13 +37,14 @@ func TestStore_OnBlock(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{
|
||||
cfg := &config{
|
||||
BeaconDB: beaconDB,
|
||||
StateGen: stategen.New(beaconDB),
|
||||
ForkChoiceStore: protoarray.New(0, 0, [32]byte{}),
|
||||
}
|
||||
service, err := NewService(ctx, cfg)
|
||||
service, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
service.cfg = cfg
|
||||
genesisStateRoot := [32]byte{}
|
||||
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
|
||||
assert.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(genesis)))
|
||||
@@ -133,12 +134,13 @@ func TestStore_OnBlockBatch(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{
|
||||
cfg := &config{
|
||||
BeaconDB: beaconDB,
|
||||
StateGen: stategen.New(beaconDB),
|
||||
}
|
||||
service, err := NewService(ctx, cfg)
|
||||
service, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
service.cfg = cfg
|
||||
|
||||
genesisStateRoot := [32]byte{}
|
||||
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
|
||||
@@ -188,9 +190,10 @@ func TestRemoveStateSinceLastFinalized_EmptyStartSlot(t *testing.T) {
|
||||
params.UseMinimalConfig()
|
||||
defer params.UseMainnetConfig()
|
||||
|
||||
cfg := &Config{BeaconDB: beaconDB, ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}
|
||||
service, err := NewService(ctx, cfg)
|
||||
cfg := &config{BeaconDB: beaconDB, ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}
|
||||
service, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
service.cfg = cfg
|
||||
service.genesisTime = time.Now()
|
||||
|
||||
update, err := service.shouldUpdateCurrentJustified(ctx, ðpb.Checkpoint{Root: make([]byte, 32)})
|
||||
@@ -222,9 +225,12 @@ func TestShouldUpdateJustified_ReturnFalse(t *testing.T) {
|
||||
params.UseMinimalConfig()
|
||||
defer params.UseMainnetConfig()
|
||||
|
||||
cfg := &Config{BeaconDB: beaconDB}
|
||||
service, err := NewService(ctx, cfg)
|
||||
cfg := &config{BeaconDB: beaconDB}
|
||||
service, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
service.cfg = cfg
|
||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{})
|
||||
|
||||
lastJustifiedBlk := util.NewBeaconBlock()
|
||||
lastJustifiedBlk.Block.ParentRoot = bytesutil.PadTo([]byte{'G'}, 32)
|
||||
lastJustifiedRoot, err := lastJustifiedBlk.Block.HashTreeRoot()
|
||||
@@ -249,12 +255,13 @@ func TestCachedPreState_CanGetFromStateSummary(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{
|
||||
cfg := &config{
|
||||
BeaconDB: beaconDB,
|
||||
StateGen: stategen.New(beaconDB),
|
||||
}
|
||||
service, err := NewService(ctx, cfg)
|
||||
service, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
service.cfg = cfg
|
||||
|
||||
s, err := v1.InitializeFromProto(ðpb.BeaconState{Slot: 1, GenesisValidatorsRoot: params.BeaconConfig().ZeroHash[:]})
|
||||
require.NoError(t, err)
|
||||
@@ -282,12 +289,13 @@ func TestCachedPreState_CanGetFromDB(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{
|
||||
cfg := &config{
|
||||
BeaconDB: beaconDB,
|
||||
StateGen: stategen.New(beaconDB),
|
||||
}
|
||||
service, err := NewService(ctx, cfg)
|
||||
service, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
service.cfg = cfg
|
||||
|
||||
genesisStateRoot := [32]byte{}
|
||||
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
|
||||
@@ -319,9 +327,10 @@ func TestUpdateJustified_CouldUpdateBest(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB)}
|
||||
service, err := NewService(ctx, cfg)
|
||||
cfg := &config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB), ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}
|
||||
service, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
service.cfg = cfg
|
||||
|
||||
signedBlock := util.NewBeaconBlock()
|
||||
require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(signedBlock)))
|
||||
@@ -352,9 +361,10 @@ func TestFillForkChoiceMissingBlocks_CanSave(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{BeaconDB: beaconDB}
|
||||
service, err := NewService(ctx, cfg)
|
||||
cfg := &config{BeaconDB: beaconDB}
|
||||
service, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
service.cfg = cfg
|
||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{'A'})
|
||||
service.finalizedCheckpt = ðpb.Checkpoint{Root: make([]byte, 32)}
|
||||
|
||||
@@ -390,9 +400,10 @@ func TestFillForkChoiceMissingBlocks_RootsMatch(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{BeaconDB: beaconDB}
|
||||
service, err := NewService(ctx, cfg)
|
||||
cfg := &config{BeaconDB: beaconDB}
|
||||
service, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
service.cfg = cfg
|
||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{'A'})
|
||||
service.finalizedCheckpt = ðpb.Checkpoint{Root: make([]byte, 32)}
|
||||
|
||||
@@ -431,9 +442,10 @@ func TestFillForkChoiceMissingBlocks_FilterFinalized(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{BeaconDB: beaconDB}
|
||||
service, err := NewService(ctx, cfg)
|
||||
cfg := &config{BeaconDB: beaconDB}
|
||||
service, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
service.cfg = cfg
|
||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{'A'})
|
||||
// Set finalized epoch to 1.
|
||||
service.finalizedCheckpt = ðpb.Checkpoint{Epoch: 1}
|
||||
@@ -574,7 +586,7 @@ func TestCurrentSlot_HandlesOverflow(t *testing.T) {
|
||||
}
|
||||
func TestAncestorByDB_CtxErr(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
service, err := NewService(ctx, &Config{})
|
||||
service, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
cancel()
|
||||
@@ -586,9 +598,10 @@ func TestAncestor_HandleSkipSlot(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{BeaconDB: beaconDB, ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}
|
||||
service, err := NewService(ctx, cfg)
|
||||
cfg := &config{BeaconDB: beaconDB, ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}
|
||||
service, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
service.cfg = cfg
|
||||
|
||||
b1 := util.NewBeaconBlock()
|
||||
b1.Block.Slot = 1
|
||||
@@ -629,9 +642,10 @@ func TestAncestor_HandleSkipSlot(t *testing.T) {
|
||||
|
||||
func TestAncestor_CanUseForkchoice(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
cfg := &Config{ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}
|
||||
service, err := NewService(ctx, cfg)
|
||||
cfg := &config{ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}
|
||||
service, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
service.cfg = cfg
|
||||
|
||||
b1 := util.NewBeaconBlock()
|
||||
b1.Block.Slot = 1
|
||||
@@ -668,9 +682,10 @@ func TestAncestor_CanUseDB(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{BeaconDB: beaconDB, ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}
|
||||
service, err := NewService(ctx, cfg)
|
||||
cfg := &config{BeaconDB: beaconDB, ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}
|
||||
service, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
service.cfg = cfg
|
||||
|
||||
b1 := util.NewBeaconBlock()
|
||||
b1.Block.Slot = 1
|
||||
@@ -705,9 +720,10 @@ func TestAncestor_CanUseDB(t *testing.T) {
|
||||
|
||||
func TestEnsureRootNotZeroHashes(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
cfg := &Config{}
|
||||
service, err := NewService(ctx, cfg)
|
||||
cfg := &config{}
|
||||
service, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
service.cfg = cfg
|
||||
service.genesisRoot = [32]byte{'a'}
|
||||
|
||||
r := service.ensureRootNotZeros(params.BeaconConfig().ZeroHash)
|
||||
@@ -760,8 +776,9 @@ func TestFinalizedImpliesNewJustified(t *testing.T) {
|
||||
beaconState, err := util.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(test.args.stateCheckPoint))
|
||||
service, err := NewService(ctx, &Config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB), ForkChoiceStore: protoarray.New(0, 0, [32]byte{})})
|
||||
service, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
service.cfg = &config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB), ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}
|
||||
service.justifiedCheckpt = test.args.cachedCheckPoint
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, ðpb.StateSummary{Root: bytesutil.PadTo(test.want.Root, 32)}))
|
||||
genesisState, err := util.NewBeaconState()
|
||||
@@ -852,8 +869,9 @@ func TestVerifyBlkDescendant(t *testing.T) {
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
service, err := NewService(ctx, &Config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB), ForkChoiceStore: protoarray.New(0, 0, [32]byte{})})
|
||||
service, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
service.cfg = &config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB), ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}
|
||||
service.finalizedCheckpt = ðpb.Checkpoint{
|
||||
Root: tt.args.finalizedRoot[:],
|
||||
}
|
||||
@@ -869,9 +887,10 @@ func TestVerifyBlkDescendant(t *testing.T) {
|
||||
func TestUpdateJustifiedInitSync(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
cfg := &Config{BeaconDB: beaconDB}
|
||||
service, err := NewService(ctx, cfg)
|
||||
cfg := &config{BeaconDB: beaconDB}
|
||||
service, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
service.cfg = cfg
|
||||
|
||||
gBlk := util.NewBeaconBlock()
|
||||
gRoot, err := gBlk.Block.HashTreeRoot()
|
||||
@@ -897,9 +916,10 @@ func TestUpdateJustifiedInitSync(t *testing.T) {
|
||||
|
||||
func TestHandleEpochBoundary_BadMetrics(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
cfg := &Config{}
|
||||
service, err := NewService(ctx, cfg)
|
||||
cfg := &config{}
|
||||
service, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
service.cfg = cfg
|
||||
|
||||
s, err := util.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
@@ -911,9 +931,10 @@ func TestHandleEpochBoundary_BadMetrics(t *testing.T) {
|
||||
|
||||
func TestHandleEpochBoundary_UpdateFirstSlot(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
cfg := &Config{}
|
||||
service, err := NewService(ctx, cfg)
|
||||
cfg := &config{}
|
||||
service, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
service.cfg = cfg
|
||||
|
||||
s, _ := util.DeterministicGenesisState(t, 1024)
|
||||
service.head = &head{state: s}
|
||||
@@ -927,15 +948,16 @@ func TestOnBlock_CanFinalize(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
cfg := &Config{
|
||||
cfg := &config{
|
||||
BeaconDB: beaconDB,
|
||||
StateGen: stategen.New(beaconDB),
|
||||
ForkChoiceStore: protoarray.New(0, 0, [32]byte{}),
|
||||
DepositCache: depositCache,
|
||||
StateNotifier: &mock.MockStateNotifier{},
|
||||
}
|
||||
service, err := NewService(ctx, cfg)
|
||||
service, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
service.cfg = cfg
|
||||
|
||||
gs, keys := util.DeterministicGenesisState(t, 32)
|
||||
require.NoError(t, service.saveGenesisData(ctx, gs))
|
||||
@@ -972,14 +994,15 @@ func TestInsertFinalizedDeposits(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
cfg := &Config{
|
||||
cfg := &config{
|
||||
BeaconDB: beaconDB,
|
||||
StateGen: stategen.New(beaconDB),
|
||||
ForkChoiceStore: protoarray.New(0, 0, [32]byte{}),
|
||||
DepositCache: depositCache,
|
||||
}
|
||||
service, err := NewService(ctx, cfg)
|
||||
service, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
service.cfg = cfg
|
||||
|
||||
gs, _ := util.DeterministicGenesisState(t, 32)
|
||||
require.NoError(t, service.saveGenesisData(ctx, gs))
|
||||
|
||||
@@ -44,9 +44,10 @@ func TestVerifyLMDFFGConsistent_NotOK(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{BeaconDB: beaconDB, ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}
|
||||
service, err := NewService(ctx, cfg)
|
||||
cfg := &config{BeaconDB: beaconDB, ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}
|
||||
service, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
service.cfg = cfg
|
||||
|
||||
b32 := util.NewBeaconBlock()
|
||||
b32.Block.Slot = 32
|
||||
@@ -72,9 +73,10 @@ func TestVerifyLMDFFGConsistent_OK(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{BeaconDB: beaconDB, ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}
|
||||
service, err := NewService(ctx, cfg)
|
||||
cfg := &config{BeaconDB: beaconDB, ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}
|
||||
service, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
service.cfg = cfg
|
||||
|
||||
b32 := util.NewBeaconBlock()
|
||||
b32.Block.Slot = 32
|
||||
@@ -101,15 +103,16 @@ func TestProcessAttestations_Ok(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{
|
||||
cfg := &config{
|
||||
BeaconDB: beaconDB,
|
||||
ForkChoiceStore: protoarray.New(0, 0, [32]byte{}),
|
||||
StateGen: stategen.New(beaconDB),
|
||||
AttPool: attestations.NewPool(),
|
||||
}
|
||||
service, err := NewService(ctx, cfg)
|
||||
service.genesisTime = prysmTime.Now().Add(-1 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second)
|
||||
service, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
service.genesisTime = prysmTime.Now().Add(-1 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second)
|
||||
service.cfg = cfg
|
||||
genesisState, pks := util.DeterministicGenesisState(t, 64)
|
||||
require.NoError(t, genesisState.SetGenesisTime(uint64(prysmTime.Now().Unix())-params.BeaconConfig().SecondsPerSlot))
|
||||
require.NoError(t, service.saveGenesisData(ctx, genesisState))
|
||||
|
||||
@@ -101,7 +101,10 @@ func (s *Service) ReceiveBlockBatch(ctx context.Context, blocks []block.SignedBe
|
||||
reportSlotMetrics(blockCopy.Block().Slot(), s.HeadSlot(), s.CurrentSlot(), s.finalizedCheckpt)
|
||||
}
|
||||
|
||||
if err := s.VerifyWeakSubjectivityRoot(s.ctx); err != nil {
|
||||
if err := s.cfg.BeaconDB.SaveBlocks(ctx, s.getInitSyncBlocks()); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.wsVerifier.VerifyWeakSubjectivity(s.ctx, s.finalizedCheckpt.Epoch); err != nil {
|
||||
// log.Fatalf will prevent defer from being called
|
||||
span.End()
|
||||
// Exit run time if the node failed to verify weak subjectivity checkpoint.
|
||||
|
||||
@@ -124,7 +124,7 @@ func TestService_ReceiveBlock(t *testing.T) {
|
||||
genesisBlockRoot := bytesutil.ToBytes32(nil)
|
||||
require.NoError(t, beaconDB.SaveState(ctx, genesis, genesisBlockRoot))
|
||||
|
||||
cfg := &Config{
|
||||
cfg := &config{
|
||||
BeaconDB: beaconDB,
|
||||
ForkChoiceStore: protoarray.New(
|
||||
0, // justifiedEpoch
|
||||
@@ -136,8 +136,9 @@ func TestService_ReceiveBlock(t *testing.T) {
|
||||
StateNotifier: &blockchainTesting.MockStateNotifier{RecordEvents: true},
|
||||
StateGen: stategen.New(beaconDB),
|
||||
}
|
||||
s, err := NewService(ctx, cfg)
|
||||
s, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
s.cfg = cfg
|
||||
require.NoError(t, s.saveGenesisData(ctx, genesis))
|
||||
gBlk, err := s.cfg.BeaconDB.GenesisBlock(ctx)
|
||||
require.NoError(t, err)
|
||||
@@ -165,7 +166,7 @@ func TestService_ReceiveBlockUpdateHead(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
genesisBlockRoot := bytesutil.ToBytes32(nil)
|
||||
require.NoError(t, beaconDB.SaveState(ctx, genesis, genesisBlockRoot))
|
||||
cfg := &Config{
|
||||
cfg := &config{
|
||||
BeaconDB: beaconDB,
|
||||
ForkChoiceStore: protoarray.New(
|
||||
0, // justifiedEpoch
|
||||
@@ -177,8 +178,9 @@ func TestService_ReceiveBlockUpdateHead(t *testing.T) {
|
||||
StateNotifier: &blockchainTesting.MockStateNotifier{RecordEvents: true},
|
||||
StateGen: stategen.New(beaconDB),
|
||||
}
|
||||
s, err := NewService(ctx, cfg)
|
||||
s, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
s.cfg = cfg
|
||||
require.NoError(t, s.saveGenesisData(ctx, genesis))
|
||||
gBlk, err := s.cfg.BeaconDB.GenesisBlock(ctx)
|
||||
require.NoError(t, err)
|
||||
@@ -248,7 +250,7 @@ func TestService_ReceiveBlockBatch(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
genesisBlockRoot, err := genesis.HashTreeRoot(ctx)
|
||||
require.NoError(t, err)
|
||||
cfg := &Config{
|
||||
cfg := &config{
|
||||
BeaconDB: beaconDB,
|
||||
ForkChoiceStore: protoarray.New(
|
||||
0, // justifiedEpoch
|
||||
@@ -258,8 +260,9 @@ func TestService_ReceiveBlockBatch(t *testing.T) {
|
||||
StateNotifier: &blockchainTesting.MockStateNotifier{RecordEvents: true},
|
||||
StateGen: stategen.New(beaconDB),
|
||||
}
|
||||
s, err := NewService(ctx, cfg)
|
||||
s, err := NewService(ctx)
|
||||
require.NoError(t, err)
|
||||
s.cfg = cfg
|
||||
err = s.saveGenesisData(ctx, genesis)
|
||||
require.NoError(t, err)
|
||||
gBlk, err := s.cfg.BeaconDB.GenesisBlock(ctx)
|
||||
@@ -284,8 +287,9 @@ func TestService_ReceiveBlockBatch(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestService_HasInitSyncBlock(t *testing.T) {
|
||||
s, err := NewService(context.Background(), &Config{StateNotifier: &blockchainTesting.MockStateNotifier{}})
|
||||
s, err := NewService(context.Background())
|
||||
require.NoError(t, err)
|
||||
s.cfg = &config{StateNotifier: &blockchainTesting.MockStateNotifier{}}
|
||||
r := [32]byte{'a'}
|
||||
if s.HasInitSyncBlock(r) {
|
||||
t.Error("Should not have block")
|
||||
@@ -299,8 +303,9 @@ func TestService_HasInitSyncBlock(t *testing.T) {
|
||||
func TestCheckSaveHotStateDB_Enabling(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
hook := logTest.NewGlobal()
|
||||
s, err := NewService(context.Background(), &Config{StateGen: stategen.New(beaconDB)})
|
||||
s, err := NewService(context.Background())
|
||||
require.NoError(t, err)
|
||||
s.cfg = &config{StateGen: stategen.New(beaconDB)}
|
||||
st := params.BeaconConfig().SlotsPerEpoch.Mul(uint64(epochsSinceFinalitySaveHotStateDB))
|
||||
s.genesisTime = time.Now().Add(time.Duration(-1*int64(st)*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second)
|
||||
s.finalizedCheckpt = ðpb.Checkpoint{}
|
||||
@@ -312,8 +317,9 @@ func TestCheckSaveHotStateDB_Enabling(t *testing.T) {
|
||||
func TestCheckSaveHotStateDB_Disabling(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
hook := logTest.NewGlobal()
|
||||
s, err := NewService(context.Background(), &Config{StateGen: stategen.New(beaconDB)})
|
||||
s, err := NewService(context.Background())
|
||||
require.NoError(t, err)
|
||||
s.cfg = &config{StateGen: stategen.New(beaconDB)}
|
||||
s.finalizedCheckpt = ðpb.Checkpoint{}
|
||||
require.NoError(t, s.checkSaveHotStateDB(context.Background()))
|
||||
s.genesisTime = time.Now()
|
||||
@@ -325,8 +331,9 @@ func TestCheckSaveHotStateDB_Disabling(t *testing.T) {
|
||||
func TestCheckSaveHotStateDB_Overflow(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
hook := logTest.NewGlobal()
|
||||
s, err := NewService(context.Background(), &Config{StateGen: stategen.New(beaconDB)})
|
||||
s, err := NewService(context.Background())
|
||||
require.NoError(t, err)
|
||||
s.cfg = &config{StateGen: stategen.New(beaconDB)}
|
||||
s.finalizedCheckpt = ðpb.Checkpoint{Epoch: 10000000}
|
||||
s.genesisTime = time.Now()
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ const headSyncMinEpochsAfterCheckpoint = 128
|
||||
// Service represents a service that handles the internal
|
||||
// logic of managing the full PoS beacon chain.
|
||||
type Service struct {
|
||||
cfg *Config
|
||||
cfg *config
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
genesisTime time.Time
|
||||
@@ -64,11 +64,11 @@ type Service struct {
|
||||
initSyncBlocksLock sync.RWMutex
|
||||
justifiedBalances []uint64
|
||||
justifiedBalancesLock sync.RWMutex
|
||||
wsVerified bool
|
||||
wsVerifier *WeakSubjectivityVerifier
|
||||
}
|
||||
|
||||
// Config options for the service.
|
||||
type Config struct {
|
||||
// config options for the service.
|
||||
type config struct {
|
||||
BeaconBlockBuf int
|
||||
ChainStartFetcher powchain.ChainStartFetcher
|
||||
BeaconDB db.HeadAccessDatabase
|
||||
@@ -84,53 +84,38 @@ type Config struct {
|
||||
StateGen *stategen.State
|
||||
SlasherAttestationsFeed *event.Feed
|
||||
WeakSubjectivityCheckpt *ethpb.Checkpoint
|
||||
FinalizedStateAtStartUp state.BeaconState
|
||||
}
|
||||
|
||||
// NewService instantiates a new block service instance that will
|
||||
// be registered into a running beacon node.
|
||||
func NewService(ctx context.Context, cfg *Config) (*Service, error) {
|
||||
func NewService(ctx context.Context, opts ...Option) (*Service, error) {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
return &Service{
|
||||
cfg: cfg,
|
||||
srv := &Service{
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
boundaryRoots: [][32]byte{},
|
||||
checkpointStateCache: cache.NewCheckpointStateCache(),
|
||||
initSyncBlocks: make(map[[32]byte]block.SignedBeaconBlock),
|
||||
justifiedBalances: make([]uint64, 0),
|
||||
}, nil
|
||||
cfg: &config{},
|
||||
}
|
||||
for _, opt := range opts {
|
||||
if err := opt(srv); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
var err error
|
||||
srv.wsVerifier, err = NewWeakSubjectivityVerifier(srv.cfg.WeakSubjectivityCheckpt, srv.cfg.BeaconDB)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return srv, nil
|
||||
}
|
||||
|
||||
// Start a blockchain service's main event loop.
|
||||
func (s *Service) Start() {
|
||||
// For running initial sync with state cache, in an event of restart, we use
|
||||
// last finalized check point as start point to sync instead of head
|
||||
// state. This is because we no longer save state every slot during sync.
|
||||
cp, err := s.cfg.BeaconDB.FinalizedCheckpoint(s.ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not fetch finalized cp: %v", err)
|
||||
}
|
||||
|
||||
r := bytesutil.ToBytes32(cp.Root)
|
||||
// Before the first finalized epoch, in the current epoch,
|
||||
// the finalized root is defined as zero hashes instead of genesis root hash.
|
||||
// We want to use genesis root to retrieve for state.
|
||||
if r == params.BeaconConfig().ZeroHash {
|
||||
genesisBlock, err := s.cfg.BeaconDB.GenesisBlock(s.ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not fetch finalized cp: %v", err)
|
||||
}
|
||||
if genesisBlock != nil && !genesisBlock.IsNil() {
|
||||
r, err = genesisBlock.Block().HashTreeRoot()
|
||||
if err != nil {
|
||||
log.Fatalf("Could not tree hash genesis block: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
beaconState, err := s.cfg.StateGen.StateByRoot(s.ctx, r)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not fetch beacon state by root: %v", err)
|
||||
}
|
||||
beaconState := s.cfg.FinalizedStateAtStartUp
|
||||
|
||||
// Make sure that attestation processor is subscribed and ready for state initializing event.
|
||||
attestationProcessorSubscribed := make(chan struct{}, 1)
|
||||
@@ -190,9 +175,11 @@ func (s *Service) Start() {
|
||||
}
|
||||
}
|
||||
|
||||
if err := s.VerifyWeakSubjectivityRoot(s.ctx); err != nil {
|
||||
// not attempting to save initial sync blocks here, because there shouldn't be until
|
||||
// after the statefeed.Initialized event is fired (below)
|
||||
if err := s.wsVerifier.VerifyWeakSubjectivity(s.ctx, s.finalizedCheckpt.Epoch); err != nil {
|
||||
// Exit run time if the node failed to verify weak subjectivity checkpoint.
|
||||
log.Fatalf("Could not verify weak subjectivity checkpoint: %v", err)
|
||||
log.Fatalf("could not verify initial checkpoint provided for chain sync, with err=: %v", err)
|
||||
}
|
||||
|
||||
s.cfg.StateNotifier.StateFeed().Send(&feed.Event{
|
||||
@@ -381,8 +368,8 @@ func (s *Service) initializeChainInfo(ctx context.Context) error {
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get genesis block from db")
|
||||
}
|
||||
if genesisBlock == nil || genesisBlock.IsNil() {
|
||||
return errors.New("no genesis block in db")
|
||||
if err := helpers.BeaconBlockIsNil(genesisBlock); err != nil {
|
||||
return err
|
||||
}
|
||||
genesisBlkRoot, err := genesisBlock.Block().HashTreeRoot()
|
||||
if err != nil {
|
||||
@@ -402,7 +389,7 @@ func (s *Service) initializeChainInfo(ctx context.Context) error {
|
||||
finalizedRoot := s.ensureRootNotZeros(bytesutil.ToBytes32(finalized.Root))
|
||||
var finalizedState state.BeaconState
|
||||
|
||||
finalizedState, err = s.cfg.StateGen.Resume(ctx)
|
||||
finalizedState, err = s.cfg.StateGen.Resume(ctx, s.cfg.FinalizedStateAtStartUp)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get finalized state from db")
|
||||
}
|
||||
@@ -424,7 +411,7 @@ func (s *Service) initializeChainInfo(ctx context.Context) error {
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not hash head block")
|
||||
}
|
||||
finalizedState, err := s.cfg.StateGen.Resume(ctx)
|
||||
finalizedState, err := s.cfg.StateGen.Resume(ctx, s.cfg.FinalizedStateAtStartUp)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get finalized state from db")
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ func init() {
|
||||
func TestChainService_SaveHead_DataRace(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
s := &Service{
|
||||
cfg: &Config{BeaconDB: beaconDB},
|
||||
cfg: &config{BeaconDB: beaconDB},
|
||||
}
|
||||
go func() {
|
||||
require.NoError(t, s.saveHead(context.Background(), [32]byte{}))
|
||||
|
||||
@@ -94,11 +94,12 @@ func setupBeaconChain(t *testing.T, beaconDB db.Database) *Service {
|
||||
DepositContainers: []*ethpb.DepositContainer{},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
web3Service, err = powchain.NewService(ctx, &powchain.Web3ServiceConfig{
|
||||
BeaconDB: beaconDB,
|
||||
HttpEndpoints: []string{endpoint},
|
||||
DepositContract: common.Address{},
|
||||
})
|
||||
web3Service, err = powchain.NewService(
|
||||
ctx,
|
||||
powchain.WithDatabase(beaconDB),
|
||||
powchain.WithHttpEndpoints([]string{endpoint}),
|
||||
powchain.WithDepositContractAddress(common.Address{}),
|
||||
)
|
||||
require.NoError(t, err, "Unable to set up web3 service")
|
||||
|
||||
attService, err := attestations.NewService(ctx, &attestations.Config{Pool: attestations.NewPool()})
|
||||
@@ -107,7 +108,7 @@ func setupBeaconChain(t *testing.T, beaconDB db.Database) *Service {
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
|
||||
cfg := &Config{
|
||||
cfg := &config{
|
||||
BeaconBlockBuf: 0,
|
||||
BeaconDB: beaconDB,
|
||||
DepositCache: depositCache,
|
||||
@@ -123,8 +124,9 @@ func setupBeaconChain(t *testing.T, beaconDB db.Database) *Service {
|
||||
// Safe a state in stategen to purposes of testing a service stop / shutdown.
|
||||
require.NoError(t, cfg.StateGen.SaveState(ctx, bytesutil.ToBytes32(bState.FinalizedCheckpoint().Root), bState))
|
||||
|
||||
chainService, err := NewService(ctx, cfg)
|
||||
chainService, err := NewService(ctx)
|
||||
require.NoError(t, err, "Unable to setup chain service")
|
||||
chainService.cfg = cfg
|
||||
chainService.genesisTime = time.Unix(1, 0) // non-zero time
|
||||
|
||||
return chainService
|
||||
@@ -149,7 +151,7 @@ func TestChainStartStop_Initialized(t *testing.T) {
|
||||
require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, blkRoot))
|
||||
require.NoError(t, beaconDB.SaveJustifiedCheckpoint(ctx, ðpb.Checkpoint{Root: blkRoot[:]}))
|
||||
require.NoError(t, beaconDB.SaveFinalizedCheckpoint(ctx, ðpb.Checkpoint{Root: blkRoot[:]}))
|
||||
|
||||
chainService.cfg.FinalizedStateAtStartUp = s
|
||||
// Test the start function.
|
||||
chainService.Start()
|
||||
|
||||
@@ -176,7 +178,7 @@ func TestChainStartStop_GenesisZeroHashes(t *testing.T) {
|
||||
require.NoError(t, beaconDB.SaveState(ctx, s, blkRoot))
|
||||
require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, blkRoot))
|
||||
require.NoError(t, beaconDB.SaveJustifiedCheckpoint(ctx, ðpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]}))
|
||||
|
||||
chainService.cfg.FinalizedStateAtStartUp = s
|
||||
// Test the start function.
|
||||
chainService.Start()
|
||||
|
||||
@@ -247,7 +249,7 @@ func TestChainService_CorrectGenesisRoots(t *testing.T) {
|
||||
require.NoError(t, beaconDB.SaveHeadBlockRoot(ctx, blkRoot))
|
||||
require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, blkRoot))
|
||||
require.NoError(t, beaconDB.SaveFinalizedCheckpoint(ctx, ðpb.Checkpoint{Root: blkRoot[:]}))
|
||||
|
||||
chainService.cfg.FinalizedStateAtStartUp = s
|
||||
// Test the start function.
|
||||
chainService.Start()
|
||||
|
||||
@@ -282,7 +284,8 @@ func TestChainService_InitializeChainInfo(t *testing.T) {
|
||||
require.NoError(t, beaconDB.SaveState(ctx, headState, genesisRoot))
|
||||
require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(headBlock)))
|
||||
require.NoError(t, beaconDB.SaveFinalizedCheckpoint(ctx, ðpb.Checkpoint{Epoch: slots.ToEpoch(finalizedSlot), Root: headRoot[:]}))
|
||||
c := &Service{cfg: &Config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB)}}
|
||||
c := &Service{cfg: &config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB)}}
|
||||
c.cfg.FinalizedStateAtStartUp = headState
|
||||
require.NoError(t, c.initializeChainInfo(ctx))
|
||||
headBlk, err := c.HeadBlock(ctx)
|
||||
require.NoError(t, err)
|
||||
@@ -322,7 +325,7 @@ func TestChainService_InitializeChainInfo_SetHeadAtGenesis(t *testing.T) {
|
||||
require.NoError(t, beaconDB.SaveState(ctx, headState, headRoot))
|
||||
require.NoError(t, beaconDB.SaveState(ctx, headState, genesisRoot))
|
||||
require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(headBlock)))
|
||||
c := &Service{cfg: &Config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB)}}
|
||||
c := &Service{cfg: &config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB)}}
|
||||
require.NoError(t, c.initializeChainInfo(ctx))
|
||||
s, err := c.HeadState(ctx)
|
||||
require.NoError(t, err)
|
||||
@@ -379,8 +382,8 @@ func TestChainService_InitializeChainInfo_HeadSync(t *testing.T) {
|
||||
Root: finalizedRoot[:],
|
||||
}))
|
||||
|
||||
c := &Service{cfg: &Config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB)}}
|
||||
|
||||
c := &Service{cfg: &config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB)}}
|
||||
c.cfg.FinalizedStateAtStartUp = headState
|
||||
require.NoError(t, c.initializeChainInfo(ctx))
|
||||
s, err := c.HeadState(ctx)
|
||||
require.NoError(t, err)
|
||||
@@ -417,7 +420,7 @@ func TestChainService_SaveHeadNoDB(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
s := &Service{
|
||||
cfg: &Config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB)},
|
||||
cfg: &config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB)},
|
||||
}
|
||||
blk := util.NewBeaconBlock()
|
||||
blk.Block.Slot = 1
|
||||
@@ -439,7 +442,7 @@ func TestHasBlock_ForkChoiceAndDB(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
s := &Service{
|
||||
cfg: &Config{ForkChoiceStore: protoarray.New(0, 0, [32]byte{}), BeaconDB: beaconDB},
|
||||
cfg: &config{ForkChoiceStore: protoarray.New(0, 0, [32]byte{}), BeaconDB: beaconDB},
|
||||
finalizedCheckpt: ðpb.Checkpoint{Root: make([]byte, 32)},
|
||||
}
|
||||
block := util.NewBeaconBlock()
|
||||
@@ -457,7 +460,7 @@ func TestServiceStop_SaveCachedBlocks(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
s := &Service{
|
||||
cfg: &Config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB)},
|
||||
cfg: &config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB)},
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
initSyncBlocks: make(map[[32]byte]block.SignedBeaconBlock),
|
||||
@@ -488,7 +491,7 @@ func BenchmarkHasBlockDB(b *testing.B) {
|
||||
beaconDB := testDB.SetupDB(b)
|
||||
ctx := context.Background()
|
||||
s := &Service{
|
||||
cfg: &Config{BeaconDB: beaconDB},
|
||||
cfg: &config{BeaconDB: beaconDB},
|
||||
}
|
||||
block := util.NewBeaconBlock()
|
||||
require.NoError(b, s.cfg.BeaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(block)))
|
||||
@@ -505,7 +508,7 @@ func BenchmarkHasBlockForkChoiceStore(b *testing.B) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(b)
|
||||
s := &Service{
|
||||
cfg: &Config{ForkChoiceStore: protoarray.New(0, 0, [32]byte{}), BeaconDB: beaconDB},
|
||||
cfg: &config{ForkChoiceStore: protoarray.New(0, 0, [32]byte{}), BeaconDB: beaconDB},
|
||||
finalizedCheckpt: ðpb.Checkpoint{Root: make([]byte, 32)},
|
||||
}
|
||||
block := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Body: ðpb.BeaconBlockBody{}}}
|
||||
|
||||
@@ -4,57 +4,94 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db/filters"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
)
|
||||
|
||||
// VerifyWeakSubjectivityRoot verifies the weak subjectivity root in the service struct.
|
||||
var errWSBlockNotFound = errors.New("weak subjectivity root not found in db")
|
||||
var errWSBlockNotFoundInEpoch = errors.New("weak subjectivity root not found in db within epoch")
|
||||
|
||||
type weakSubjectivityDB interface {
|
||||
HasBlock(ctx context.Context, blockRoot [32]byte) bool
|
||||
BlockRoots(ctx context.Context, f *filters.QueryFilter) ([][32]byte, error)
|
||||
}
|
||||
|
||||
type WeakSubjectivityVerifier struct {
|
||||
enabled bool
|
||||
verified bool
|
||||
root [32]byte
|
||||
epoch types.Epoch
|
||||
slot types.Slot
|
||||
db weakSubjectivityDB
|
||||
}
|
||||
|
||||
// NewWeakSubjectivityVerifier validates a checkpoint, and if valid, uses it to initialize a weak subjectivity verifier
|
||||
func NewWeakSubjectivityVerifier(wsc *ethpb.Checkpoint, db weakSubjectivityDB) (*WeakSubjectivityVerifier, error) {
|
||||
// TODO(7342): Weak subjectivity checks are currently optional. When we require the flag to be specified
|
||||
// per 7342, a nil checkpoint, zero-root or zero-epoch should all fail validation
|
||||
// and return an error instead of creating a WeakSubjectivityVerifier that permits any chain history.
|
||||
if wsc == nil || len(wsc.Root) == 0 || wsc.Epoch == 0 {
|
||||
return &WeakSubjectivityVerifier{
|
||||
enabled: false,
|
||||
}, nil
|
||||
}
|
||||
startSlot, err := slots.EpochStart(wsc.Epoch)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &WeakSubjectivityVerifier{
|
||||
enabled: true,
|
||||
verified: false,
|
||||
root: bytesutil.ToBytes32(wsc.Root),
|
||||
epoch: wsc.Epoch,
|
||||
db: db,
|
||||
slot: startSlot,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// VerifyWeakSubjectivity verifies the weak subjectivity root in the service struct.
|
||||
// Reference design: https://github.com/ethereum/consensus-specs/blob/master/specs/phase0/weak-subjectivity.md#weak-subjectivity-sync-procedure
|
||||
func (s *Service) VerifyWeakSubjectivityRoot(ctx context.Context) error {
|
||||
// TODO(7342): Remove the following to fully use weak subjectivity in production.
|
||||
if s.cfg.WeakSubjectivityCheckpt == nil || len(s.cfg.WeakSubjectivityCheckpt.Root) == 0 || s.cfg.WeakSubjectivityCheckpt.Epoch == 0 {
|
||||
func (v *WeakSubjectivityVerifier) VerifyWeakSubjectivity(ctx context.Context, finalizedEpoch types.Epoch) error {
|
||||
if v.verified || !v.enabled {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Do nothing if the weak subjectivity has previously been verified,
|
||||
// or weak subjectivity epoch is higher than last finalized epoch.
|
||||
if s.wsVerified {
|
||||
return nil
|
||||
}
|
||||
if s.cfg.WeakSubjectivityCheckpt.Epoch > s.finalizedCheckpt.Epoch {
|
||||
// Two conditions are described in the specs:
|
||||
// IF epoch_number > store.finalized_checkpoint.epoch,
|
||||
// then ASSERT during block sync that block with root block_root
|
||||
// is in the sync path at epoch epoch_number. Emit descriptive critical error if this assert fails,
|
||||
// then exit client process.
|
||||
// we do not handle this case ^, because we can only blocks that have been processed / are currently
|
||||
// in line for finalization, we don't have the ability to look ahead. so we only satisfy the following:
|
||||
// IF epoch_number <= store.finalized_checkpoint.epoch,
|
||||
// then ASSERT that the block in the canonical chain at epoch epoch_number has root block_root.
|
||||
// Emit descriptive critical error if this assert fails, then exit client process.
|
||||
if v.epoch > finalizedEpoch {
|
||||
return nil
|
||||
}
|
||||
log.Infof("Performing weak subjectivity check for root %#x in epoch %d", v.root, v.epoch)
|
||||
|
||||
r := bytesutil.ToBytes32(s.cfg.WeakSubjectivityCheckpt.Root)
|
||||
log.Infof("Performing weak subjectivity check for root %#x in epoch %d", r, s.cfg.WeakSubjectivityCheckpt.Epoch)
|
||||
// Save initial sync cached blocks to DB.
|
||||
if err := s.cfg.BeaconDB.SaveBlocks(ctx, s.getInitSyncBlocks()); err != nil {
|
||||
return err
|
||||
}
|
||||
// A node should have the weak subjectivity block in the DB.
|
||||
if !s.cfg.BeaconDB.HasBlock(ctx, r) {
|
||||
return fmt.Errorf("node does not have root in DB: %#x", r)
|
||||
}
|
||||
|
||||
startSlot, err := slots.EpochStart(s.cfg.WeakSubjectivityCheckpt.Epoch)
|
||||
if err != nil {
|
||||
return err
|
||||
if !v.db.HasBlock(ctx, v.root) {
|
||||
return errors.Wrap(errWSBlockNotFound, fmt.Sprintf("missing root %#x", v.root))
|
||||
}
|
||||
filter := filters.NewFilter().SetStartSlot(v.slot).SetEndSlot(v.slot + params.BeaconConfig().SlotsPerEpoch)
|
||||
// A node should have the weak subjectivity block corresponds to the correct epoch in the DB.
|
||||
filter := filters.NewFilter().SetStartSlot(startSlot).SetEndSlot(startSlot + params.BeaconConfig().SlotsPerEpoch)
|
||||
roots, err := s.cfg.BeaconDB.BlockRoots(ctx, filter)
|
||||
roots, err := v.db.BlockRoots(ctx, filter)
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "error while retrieving block roots to verify weak subjectivity")
|
||||
}
|
||||
for _, root := range roots {
|
||||
if r == root {
|
||||
if v.root == root {
|
||||
log.Info("Weak subjectivity check has passed")
|
||||
s.wsVerified = true
|
||||
v.verified = true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("node does not have root in db corresponding to epoch: %#x %d", r, s.cfg.WeakSubjectivityCheckpt.Epoch)
|
||||
return errors.Wrap(errWSBlockNotFoundInEpoch, fmt.Sprintf("root=%#x, epoch=%d", v.root, v.epoch))
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
@@ -23,59 +24,57 @@ func TestService_VerifyWeakSubjectivityRoot(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
tests := []struct {
|
||||
wsVerified bool
|
||||
wantErr bool
|
||||
wantErr error
|
||||
checkpt *ethpb.Checkpoint
|
||||
finalizedEpoch types.Epoch
|
||||
errString string
|
||||
name string
|
||||
}{
|
||||
{
|
||||
name: "nil root and epoch",
|
||||
wantErr: false,
|
||||
name: "nil root and epoch",
|
||||
},
|
||||
{
|
||||
name: "already verified",
|
||||
checkpt: ðpb.Checkpoint{Epoch: 2},
|
||||
finalizedEpoch: 2,
|
||||
wsVerified: true,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "not yet to verify, ws epoch higher than finalized epoch",
|
||||
checkpt: ðpb.Checkpoint{Epoch: 2},
|
||||
finalizedEpoch: 1,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "can't find the block in DB",
|
||||
checkpt: ðpb.Checkpoint{Root: bytesutil.PadTo([]byte{'a'}, 32), Epoch: 1},
|
||||
finalizedEpoch: 3,
|
||||
wantErr: true,
|
||||
errString: "node does not have root in DB",
|
||||
wantErr: errWSBlockNotFound,
|
||||
},
|
||||
{
|
||||
name: "can't find the block corresponds to ws epoch in DB",
|
||||
checkpt: ðpb.Checkpoint{Root: r[:], Epoch: 2}, // Root belongs in epoch 1.
|
||||
finalizedEpoch: 3,
|
||||
wantErr: true,
|
||||
errString: "node does not have root in db corresponding to epoch",
|
||||
wantErr: errWSBlockNotFoundInEpoch,
|
||||
},
|
||||
{
|
||||
name: "can verify and pass",
|
||||
checkpt: ðpb.Checkpoint{Root: r[:], Epoch: 1},
|
||||
finalizedEpoch: 3,
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
wv, err := NewWeakSubjectivityVerifier(tt.checkpt, beaconDB)
|
||||
require.NoError(t, err)
|
||||
s := &Service{
|
||||
cfg: &Config{BeaconDB: beaconDB, WeakSubjectivityCheckpt: tt.checkpt},
|
||||
wsVerified: tt.wsVerified,
|
||||
cfg: &config{BeaconDB: beaconDB, WeakSubjectivityCheckpt: tt.checkpt},
|
||||
finalizedCheckpt: ðpb.Checkpoint{Epoch: tt.finalizedEpoch},
|
||||
wsVerifier: wv,
|
||||
}
|
||||
if err := s.VerifyWeakSubjectivityRoot(context.Background()); (err != nil) != tt.wantErr {
|
||||
require.ErrorContains(t, tt.errString, err)
|
||||
err = s.wsVerifier.VerifyWeakSubjectivity(context.Background(), s.finalizedCheckpt.Epoch)
|
||||
if tt.wantErr == nil {
|
||||
require.NoError(t, err)
|
||||
} else {
|
||||
require.Equal(t, true, errors.Is(err, tt.wantErr))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -136,7 +136,10 @@ func (dc *DepositCache) InsertFinalizedDeposits(ctx context.Context, eth1Deposit
|
||||
log.WithError(err).Error("Could not hash deposit data. Finalized deposit cache not updated.")
|
||||
return
|
||||
}
|
||||
depositTrie.Insert(depHash[:], insertIndex)
|
||||
if err = depositTrie.Insert(depHash[:], insertIndex); err != nil {
|
||||
log.WithError(err).Error("Could not insert deposit hash")
|
||||
return
|
||||
}
|
||||
insertIndex++
|
||||
}
|
||||
|
||||
|
||||
12
beacon-chain/cache/skip_slot_cache.go
vendored
12
beacon-chain/cache/skip_slot_cache.go
vendored
@@ -120,26 +120,22 @@ func (c *SkipSlotCache) MarkInProgress(r [32]byte) error {
|
||||
|
||||
// MarkNotInProgress will release the lock on a given request. This should be
|
||||
// called after put.
|
||||
func (c *SkipSlotCache) MarkNotInProgress(r [32]byte) error {
|
||||
func (c *SkipSlotCache) MarkNotInProgress(r [32]byte) {
|
||||
if c.disabled {
|
||||
return nil
|
||||
return
|
||||
}
|
||||
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
|
||||
delete(c.inProgress, r)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Put the response in the cache.
|
||||
func (c *SkipSlotCache) Put(_ context.Context, r [32]byte, state state.BeaconState) error {
|
||||
func (c *SkipSlotCache) Put(_ context.Context, r [32]byte, state state.BeaconState) {
|
||||
if c.disabled {
|
||||
return nil
|
||||
return
|
||||
}
|
||||
|
||||
// Copy state so cached value is not mutated.
|
||||
c.cache.Add(r, state.Copy())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
4
beacon-chain/cache/skip_slot_cache_test.go
vendored
4
beacon-chain/cache/skip_slot_cache_test.go
vendored
@@ -28,8 +28,8 @@ func TestSkipSlotCache_RoundTrip(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, c.Put(ctx, r, s))
|
||||
require.NoError(t, c.MarkNotInProgress(r))
|
||||
c.Put(ctx, r, s)
|
||||
c.MarkNotInProgress(r)
|
||||
|
||||
res, err := c.Get(ctx, r)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -25,7 +25,7 @@ func ProcessAttestationsNoVerifySignature(
|
||||
beaconState state.BeaconState,
|
||||
b block.SignedBeaconBlock,
|
||||
) (state.BeaconState, error) {
|
||||
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
|
||||
if err := helpers.BeaconBlockIsNil(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
body := b.Block().Body()
|
||||
@@ -142,13 +142,19 @@ func SetParticipationAndRewardProposer(
|
||||
}
|
||||
|
||||
// HasValidatorFlag returns true if the flag at position has set.
|
||||
func HasValidatorFlag(flag, flagPosition uint8) bool {
|
||||
return ((flag >> flagPosition) & 1) == 1
|
||||
func HasValidatorFlag(flag, flagPosition uint8) (bool, error) {
|
||||
if flagPosition > 7 {
|
||||
return false, errors.New("flag position exceeds length")
|
||||
}
|
||||
return ((flag >> flagPosition) & 1) == 1, nil
|
||||
}
|
||||
|
||||
// AddValidatorFlag adds new validator flag to existing one.
|
||||
func AddValidatorFlag(flag, flagPosition uint8) uint8 {
|
||||
return flag | (1 << flagPosition)
|
||||
func AddValidatorFlag(flag, flagPosition uint8) (uint8, error) {
|
||||
if flagPosition > 7 {
|
||||
return flag, errors.New("flag position exceeds length")
|
||||
}
|
||||
return flag | (1 << flagPosition), nil
|
||||
}
|
||||
|
||||
// EpochParticipation sets and returns the proposer reward numerator and epoch participation.
|
||||
@@ -174,16 +180,37 @@ func EpochParticipation(beaconState state.BeaconState, indices []uint64, epochPa
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
if participatedFlags[sourceFlagIndex] && !HasValidatorFlag(epochParticipation[index], sourceFlagIndex) {
|
||||
epochParticipation[index] = AddValidatorFlag(epochParticipation[index], sourceFlagIndex)
|
||||
has, err := HasValidatorFlag(epochParticipation[index], sourceFlagIndex)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
if participatedFlags[sourceFlagIndex] && !has {
|
||||
epochParticipation[index], err = AddValidatorFlag(epochParticipation[index], sourceFlagIndex)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
proposerRewardNumerator += br * cfg.TimelySourceWeight
|
||||
}
|
||||
if participatedFlags[targetFlagIndex] && !HasValidatorFlag(epochParticipation[index], targetFlagIndex) {
|
||||
epochParticipation[index] = AddValidatorFlag(epochParticipation[index], targetFlagIndex)
|
||||
has, err = HasValidatorFlag(epochParticipation[index], targetFlagIndex)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
if participatedFlags[targetFlagIndex] && !has {
|
||||
epochParticipation[index], err = AddValidatorFlag(epochParticipation[index], targetFlagIndex)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
proposerRewardNumerator += br * cfg.TimelyTargetWeight
|
||||
}
|
||||
if participatedFlags[headFlagIndex] && !HasValidatorFlag(epochParticipation[index], headFlagIndex) {
|
||||
epochParticipation[index] = AddValidatorFlag(epochParticipation[index], headFlagIndex)
|
||||
has, err = HasValidatorFlag(epochParticipation[index], headFlagIndex)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
if participatedFlags[headFlagIndex] && !has {
|
||||
epochParticipation[index], err = AddValidatorFlag(epochParticipation[index], headFlagIndex)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
proposerRewardNumerator += br * cfg.TimelyHeadWeight
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,9 +275,15 @@ func TestProcessAttestationNoVerify_SourceTargetHead(t *testing.T) {
|
||||
indices, err := attestation.AttestingIndices(att.AggregationBits, committee)
|
||||
require.NoError(t, err)
|
||||
for _, index := range indices {
|
||||
require.Equal(t, true, altair.HasValidatorFlag(p[index], params.BeaconConfig().TimelyHeadFlagIndex))
|
||||
require.Equal(t, true, altair.HasValidatorFlag(p[index], params.BeaconConfig().TimelyTargetFlagIndex))
|
||||
require.Equal(t, true, altair.HasValidatorFlag(p[index], params.BeaconConfig().TimelySourceFlagIndex))
|
||||
has, err := altair.HasValidatorFlag(p[index], params.BeaconConfig().TimelyHeadFlagIndex)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, has)
|
||||
has, err = altair.HasValidatorFlag(p[index], params.BeaconConfig().TimelySourceFlagIndex)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, has)
|
||||
has, err = altair.HasValidatorFlag(p[index], params.BeaconConfig().TimelyTargetFlagIndex)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, has)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -331,12 +337,19 @@ func TestValidatorFlag_Has(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
for _, f := range tt.expected {
|
||||
require.Equal(t, true, altair.HasValidatorFlag(tt.set, f))
|
||||
has, err := altair.HasValidatorFlag(tt.set, f)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, has)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidatorFlag_Has_ExceedsLength(t *testing.T) {
|
||||
_, err := altair.HasValidatorFlag(0, 8)
|
||||
require.ErrorContains(t, "flag position exceeds length", err)
|
||||
}
|
||||
|
||||
func TestValidatorFlag_Add(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -368,23 +381,33 @@ func TestValidatorFlag_Add(t *testing.T) {
|
||||
expectedFalse: []uint8{},
|
||||
},
|
||||
}
|
||||
|
||||
var err error
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
b := uint8(0)
|
||||
for _, f := range tt.set {
|
||||
b = altair.AddValidatorFlag(b, f)
|
||||
b, err = altair.AddValidatorFlag(b, f)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
for _, f := range tt.expectedFalse {
|
||||
require.Equal(t, false, altair.HasValidatorFlag(b, f))
|
||||
has, err := altair.HasValidatorFlag(b, f)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, false, has)
|
||||
}
|
||||
for _, f := range tt.expectedTrue {
|
||||
require.Equal(t, true, altair.HasValidatorFlag(b, f))
|
||||
has, err := altair.HasValidatorFlag(b, f)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, has)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidatorFlag_Add_ExceedsLength(t *testing.T) {
|
||||
_, err := altair.AddValidatorFlag(0, 8)
|
||||
require.ErrorContains(t, "flag position exceeds length", err)
|
||||
}
|
||||
|
||||
func TestFuzzProcessAttestationsNoVerify_10000(t *testing.T) {
|
||||
fuzzer := fuzz.NewWithSeed(0)
|
||||
state := ðpb.BeaconStateAltair{}
|
||||
|
||||
@@ -42,12 +42,18 @@ func InitializePrecomputeValidators(ctx context.Context, beaconState state.Beaco
|
||||
// Set validator's active status for current epoch.
|
||||
if helpers.IsActiveValidatorUsingTrie(val, currentEpoch) {
|
||||
v.IsActiveCurrentEpoch = true
|
||||
bal.ActiveCurrentEpoch += val.EffectiveBalance()
|
||||
bal.ActiveCurrentEpoch, err = math.Add64(bal.ActiveCurrentEpoch, val.EffectiveBalance())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// Set validator's active status for preivous epoch.
|
||||
if helpers.IsActiveValidatorUsingTrie(val, prevEpoch) {
|
||||
v.IsActivePrevEpoch = true
|
||||
bal.ActivePrevEpoch += val.EffectiveBalance()
|
||||
bal.ActivePrevEpoch, err = math.Add64(bal.ActivePrevEpoch, val.EffectiveBalance())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
vals[idx] = v
|
||||
return nil
|
||||
@@ -150,7 +156,19 @@ func ProcessEpochParticipation(
|
||||
sourceIdx := cfg.TimelySourceFlagIndex
|
||||
headIdx := cfg.TimelyHeadFlagIndex
|
||||
for i, b := range cp {
|
||||
if HasValidatorFlag(b, targetIdx) && vals[i].IsActiveCurrentEpoch {
|
||||
has, err := HasValidatorFlag(b, sourceIdx)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if has && vals[i].IsActiveCurrentEpoch {
|
||||
vals[i].IsCurrentEpochAttester = true
|
||||
}
|
||||
has, err = HasValidatorFlag(b, targetIdx)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if has && vals[i].IsActiveCurrentEpoch {
|
||||
vals[i].IsCurrentEpochAttester = true
|
||||
vals[i].IsCurrentEpochTargetAttester = true
|
||||
}
|
||||
}
|
||||
@@ -159,17 +177,31 @@ func ProcessEpochParticipation(
|
||||
return nil, nil, err
|
||||
}
|
||||
for i, b := range pp {
|
||||
if HasValidatorFlag(b, sourceIdx) && vals[i].IsActivePrevEpoch {
|
||||
vals[i].IsPrevEpochAttester = true
|
||||
has, err := HasValidatorFlag(b, sourceIdx)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if HasValidatorFlag(b, targetIdx) && vals[i].IsActivePrevEpoch {
|
||||
if has && vals[i].IsActivePrevEpoch {
|
||||
vals[i].IsPrevEpochAttester = true
|
||||
vals[i].IsPrevEpochSourceAttester = true
|
||||
}
|
||||
has, err = HasValidatorFlag(b, targetIdx)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if has && vals[i].IsActivePrevEpoch {
|
||||
vals[i].IsPrevEpochAttester = true
|
||||
vals[i].IsPrevEpochTargetAttester = true
|
||||
}
|
||||
if HasValidatorFlag(b, headIdx) && vals[i].IsActivePrevEpoch {
|
||||
has, err = HasValidatorFlag(b, headIdx)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if has && vals[i].IsActivePrevEpoch {
|
||||
vals[i].IsPrevEpochHeadAttester = true
|
||||
}
|
||||
}
|
||||
bal = precompute.UpdateBalance(vals, bal)
|
||||
bal = precompute.UpdateBalance(vals, bal, beaconState.Version())
|
||||
return vals, bal, nil
|
||||
}
|
||||
|
||||
@@ -268,7 +300,7 @@ func attestationDelta(
|
||||
headWeight := cfg.TimelyHeadWeight
|
||||
reward, penalty = uint64(0), uint64(0)
|
||||
// Process source reward / penalty
|
||||
if val.IsPrevEpochAttester && !val.IsSlashed {
|
||||
if val.IsPrevEpochSourceAttester && !val.IsSlashed {
|
||||
if !inactivityLeak {
|
||||
n := baseReward * srcWeight * (bal.PrevEpochAttested / increment)
|
||||
reward += n / (activeIncrement * weightDenominator)
|
||||
|
||||
@@ -2,6 +2,7 @@ package altair
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math"
|
||||
"testing"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
@@ -62,6 +63,21 @@ func TestInitializeEpochValidators_Ok(t *testing.T) {
|
||||
assert.DeepEqual(t, wantedBalances, b, "Incorrect wanted balance")
|
||||
}
|
||||
|
||||
func TestInitializeEpochValidators_Overflow(t *testing.T) {
|
||||
ffe := params.BeaconConfig().FarFutureEpoch
|
||||
s, err := stateAltair.InitializeFromProto(ðpb.BeaconStateAltair{
|
||||
Slot: params.BeaconConfig().SlotsPerEpoch,
|
||||
Validators: []*ethpb.Validator{
|
||||
{WithdrawableEpoch: ffe, ExitEpoch: ffe, EffectiveBalance: math.MaxUint64},
|
||||
{WithdrawableEpoch: ffe, ExitEpoch: ffe, EffectiveBalance: math.MaxUint64},
|
||||
},
|
||||
InactivityScores: []uint64{0, 1},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
_, _, err = InitializePrecomputeValidators(context.Background(), s)
|
||||
require.ErrorContains(t, "could not read every validator: addition overflows", err)
|
||||
}
|
||||
|
||||
func TestInitializeEpochValidators_BadState(t *testing.T) {
|
||||
s, err := stateAltair.InitializeFromProto(ðpb.BeaconStateAltair{
|
||||
Validators: []*ethpb.Validator{{}},
|
||||
@@ -90,14 +106,18 @@ func TestProcessEpochParticipation(t *testing.T) {
|
||||
IsActivePrevEpoch: true,
|
||||
IsWithdrawableCurrentEpoch: true,
|
||||
CurrentEpochEffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
IsCurrentEpochAttester: true,
|
||||
IsPrevEpochAttester: true,
|
||||
IsPrevEpochSourceAttester: true,
|
||||
}, validators[1])
|
||||
require.DeepEqual(t, &precompute.Validator{
|
||||
IsActiveCurrentEpoch: true,
|
||||
IsActivePrevEpoch: true,
|
||||
IsWithdrawableCurrentEpoch: true,
|
||||
CurrentEpochEffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
IsCurrentEpochAttester: true,
|
||||
IsPrevEpochAttester: true,
|
||||
IsPrevEpochSourceAttester: true,
|
||||
IsCurrentEpochTargetAttester: true,
|
||||
IsPrevEpochTargetAttester: true,
|
||||
}, validators[2])
|
||||
@@ -106,7 +126,9 @@ func TestProcessEpochParticipation(t *testing.T) {
|
||||
IsActivePrevEpoch: true,
|
||||
IsWithdrawableCurrentEpoch: true,
|
||||
CurrentEpochEffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
IsCurrentEpochAttester: true,
|
||||
IsPrevEpochAttester: true,
|
||||
IsPrevEpochSourceAttester: true,
|
||||
IsCurrentEpochTargetAttester: true,
|
||||
IsPrevEpochTargetAttester: true,
|
||||
IsPrevEpochHeadAttester: true,
|
||||
@@ -120,8 +142,10 @@ func TestProcessEpochParticipation(t *testing.T) {
|
||||
func TestProcessEpochParticipation_InactiveValidator(t *testing.T) {
|
||||
generateParticipation := func(flags ...uint8) byte {
|
||||
b := byte(0)
|
||||
var err error
|
||||
for _, flag := range flags {
|
||||
b = AddValidatorFlag(b, flag)
|
||||
b, err = AddValidatorFlag(b, flag)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
return b
|
||||
}
|
||||
@@ -159,6 +183,7 @@ func TestProcessEpochParticipation_InactiveValidator(t *testing.T) {
|
||||
IsActiveCurrentEpoch: false,
|
||||
IsActivePrevEpoch: true,
|
||||
IsPrevEpochAttester: true,
|
||||
IsPrevEpochSourceAttester: true,
|
||||
IsPrevEpochTargetAttester: true,
|
||||
IsWithdrawableCurrentEpoch: true,
|
||||
CurrentEpochEffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
@@ -168,7 +193,9 @@ func TestProcessEpochParticipation_InactiveValidator(t *testing.T) {
|
||||
IsActivePrevEpoch: true,
|
||||
IsWithdrawableCurrentEpoch: true,
|
||||
CurrentEpochEffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
IsCurrentEpochAttester: true,
|
||||
IsPrevEpochAttester: true,
|
||||
IsPrevEpochSourceAttester: true,
|
||||
IsCurrentEpochTargetAttester: true,
|
||||
IsPrevEpochTargetAttester: true,
|
||||
IsPrevEpochHeadAttester: true,
|
||||
@@ -395,8 +422,12 @@ func TestProcessInactivityScores_NonEligibleValidator(t *testing.T) {
|
||||
func testState() (state.BeaconState, error) {
|
||||
generateParticipation := func(flags ...uint8) byte {
|
||||
b := byte(0)
|
||||
var err error
|
||||
for _, flag := range flags {
|
||||
b = AddValidatorFlag(b, flag)
|
||||
b, err = AddValidatorFlag(b, flag)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
@@ -161,14 +161,35 @@ func TranslateParticipation(ctx context.Context, state *statealtair.BeaconState,
|
||||
targetFlagIndex := cfg.TimelyTargetFlagIndex
|
||||
headFlagIndex := cfg.TimelyHeadFlagIndex
|
||||
for _, index := range indices {
|
||||
if participatedFlags[sourceFlagIndex] && !HasValidatorFlag(epochParticipation[index], sourceFlagIndex) {
|
||||
epochParticipation[index] = AddValidatorFlag(epochParticipation[index], sourceFlagIndex)
|
||||
has, err := HasValidatorFlag(epochParticipation[index], sourceFlagIndex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if participatedFlags[targetFlagIndex] && !HasValidatorFlag(epochParticipation[index], targetFlagIndex) {
|
||||
epochParticipation[index] = AddValidatorFlag(epochParticipation[index], targetFlagIndex)
|
||||
if participatedFlags[sourceFlagIndex] && !has {
|
||||
epochParticipation[index], err = AddValidatorFlag(epochParticipation[index], sourceFlagIndex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if participatedFlags[headFlagIndex] && !HasValidatorFlag(epochParticipation[index], headFlagIndex) {
|
||||
epochParticipation[index] = AddValidatorFlag(epochParticipation[index], headFlagIndex)
|
||||
has, err = HasValidatorFlag(epochParticipation[index], targetFlagIndex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if participatedFlags[targetFlagIndex] && !has {
|
||||
epochParticipation[index], err = AddValidatorFlag(epochParticipation[index], targetFlagIndex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
has, err = HasValidatorFlag(epochParticipation[index], headFlagIndex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if participatedFlags[headFlagIndex] && !has {
|
||||
epochParticipation[index], err = AddValidatorFlag(epochParticipation[index], headFlagIndex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/altair"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/time"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
stateAltair "github.com/prysmaticlabs/prysm/beacon-chain/state/v2"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
@@ -62,9 +61,15 @@ func TestTranslateParticipation(t *testing.T) {
|
||||
indices, err := attestation.AttestingIndices(pendingAtts[0].AggregationBits, committee)
|
||||
require.NoError(t, err)
|
||||
for _, index := range indices {
|
||||
require.Equal(t, true, altair.HasValidatorFlag(participation[index], params.BeaconConfig().TimelyHeadFlagIndex))
|
||||
require.Equal(t, true, altair.HasValidatorFlag(participation[index], params.BeaconConfig().TimelyTargetFlagIndex))
|
||||
require.Equal(t, true, altair.HasValidatorFlag(participation[index], params.BeaconConfig().TimelySourceFlagIndex))
|
||||
has, err := altair.HasValidatorFlag(participation[index], params.BeaconConfig().TimelySourceFlagIndex)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, has)
|
||||
has, err = altair.HasValidatorFlag(participation[index], params.BeaconConfig().TimelyTargetFlagIndex)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, has)
|
||||
has, err = altair.HasValidatorFlag(participation[index], params.BeaconConfig().TimelyHeadFlagIndex)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, has)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,8 +78,6 @@ func TestUpgradeToAltair(t *testing.T) {
|
||||
preForkState := st.Copy()
|
||||
aState, err := altair.UpgradeToAltair(context.Background(), st)
|
||||
require.NoError(t, err)
|
||||
_, ok := aState.(state.BeaconStateAltair)
|
||||
require.Equal(t, true, ok)
|
||||
|
||||
require.Equal(t, preForkState.GenesisTime(), aState.GenesisTime())
|
||||
require.DeepSSZEqual(t, preForkState.GenesisValidatorRoot(), aState.GenesisValidatorRoot())
|
||||
|
||||
@@ -25,7 +25,7 @@ func ProcessAttestationsNoVerifySignature(
|
||||
beaconState state.BeaconState,
|
||||
b block.SignedBeaconBlock,
|
||||
) (state.BeaconState, error) {
|
||||
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
|
||||
if err := helpers.BeaconBlockIsNil(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
body := b.Block().Body()
|
||||
|
||||
@@ -271,7 +271,7 @@ func TestVerifyIndexedAttestation_OK(t *testing.T) {
|
||||
Source: ðpb.Checkpoint{},
|
||||
}),
|
||||
AttestingIndices: []uint64{1},
|
||||
Signature: make([]byte, 96),
|
||||
Signature: make([]byte, params.BeaconConfig().BLSSignatureLength),
|
||||
}},
|
||||
{attestation: ðpb.IndexedAttestation{
|
||||
Data: util.HydrateAttestationData(ðpb.AttestationData{
|
||||
@@ -280,7 +280,7 @@ func TestVerifyIndexedAttestation_OK(t *testing.T) {
|
||||
},
|
||||
}),
|
||||
AttestingIndices: []uint64{47, 99, 101},
|
||||
Signature: make([]byte, 96),
|
||||
Signature: make([]byte, params.BeaconConfig().BLSSignatureLength),
|
||||
}},
|
||||
{attestation: ðpb.IndexedAttestation{
|
||||
Data: util.HydrateAttestationData(ðpb.AttestationData{
|
||||
@@ -289,7 +289,7 @@ func TestVerifyIndexedAttestation_OK(t *testing.T) {
|
||||
},
|
||||
}),
|
||||
AttestingIndices: []uint64{21, 72},
|
||||
Signature: make([]byte, 96),
|
||||
Signature: make([]byte, params.BeaconConfig().BLSSignatureLength),
|
||||
}},
|
||||
{attestation: ðpb.IndexedAttestation{
|
||||
Data: util.HydrateAttestationData(ðpb.AttestationData{
|
||||
@@ -298,7 +298,7 @@ func TestVerifyIndexedAttestation_OK(t *testing.T) {
|
||||
},
|
||||
}),
|
||||
AttestingIndices: []uint64{100, 121, 122},
|
||||
Signature: make([]byte, 96),
|
||||
Signature: make([]byte, params.BeaconConfig().BLSSignatureLength),
|
||||
}},
|
||||
}
|
||||
|
||||
|
||||
@@ -42,40 +42,60 @@ func ProcessAttesterSlashings(
|
||||
slashings []*ethpb.AttesterSlashing,
|
||||
slashFunc slashValidatorFunc,
|
||||
) (state.BeaconState, error) {
|
||||
for idx, slashing := range slashings {
|
||||
if err := VerifyAttesterSlashing(ctx, beaconState, slashing); err != nil {
|
||||
return nil, errors.Wrapf(err, "could not verify attester slashing %d", idx)
|
||||
var err error
|
||||
for _, slashing := range slashings {
|
||||
beaconState, err = ProcessAttesterSlashing(ctx, beaconState, slashing, slashFunc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
slashableIndices := slashableAttesterIndices(slashing)
|
||||
sort.SliceStable(slashableIndices, func(i, j int) bool {
|
||||
return slashableIndices[i] < slashableIndices[j]
|
||||
})
|
||||
currentEpoch := slots.ToEpoch(beaconState.Slot())
|
||||
var err error
|
||||
var slashedAny bool
|
||||
var val state.ReadOnlyValidator
|
||||
for _, validatorIndex := range slashableIndices {
|
||||
val, err = beaconState.ValidatorAtIndexReadOnly(types.ValidatorIndex(validatorIndex))
|
||||
}
|
||||
return beaconState, nil
|
||||
}
|
||||
|
||||
// ProcessAttesterSlashing processes individual attester slashing.
|
||||
func ProcessAttesterSlashing(
|
||||
ctx context.Context,
|
||||
beaconState state.BeaconState,
|
||||
slashing *ethpb.AttesterSlashing,
|
||||
slashFunc slashValidatorFunc,
|
||||
) (state.BeaconState, error) {
|
||||
if err := VerifyAttesterSlashing(ctx, beaconState, slashing); err != nil {
|
||||
return nil, errors.Wrap(err, "could not verify attester slashing")
|
||||
}
|
||||
slashableIndices := SlashableAttesterIndices(slashing)
|
||||
sort.SliceStable(slashableIndices, func(i, j int) bool {
|
||||
return slashableIndices[i] < slashableIndices[j]
|
||||
})
|
||||
currentEpoch := slots.ToEpoch(beaconState.Slot())
|
||||
var err error
|
||||
var slashedAny bool
|
||||
var val state.ReadOnlyValidator
|
||||
for _, validatorIndex := range slashableIndices {
|
||||
val, err = beaconState.ValidatorAtIndexReadOnly(types.ValidatorIndex(validatorIndex))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if helpers.IsSlashableValidator(val.ActivationEpoch(), val.WithdrawableEpoch(), val.Slashed(), currentEpoch) {
|
||||
cfg := params.BeaconConfig()
|
||||
var slashingQuotient uint64
|
||||
switch {
|
||||
case beaconState.Version() == version.Phase0:
|
||||
slashingQuotient = cfg.MinSlashingPenaltyQuotient
|
||||
case beaconState.Version() == version.Altair:
|
||||
slashingQuotient = cfg.MinSlashingPenaltyQuotientAltair
|
||||
default:
|
||||
return nil, errors.New("unknown state version")
|
||||
}
|
||||
beaconState, err = slashFunc(ctx, beaconState, types.ValidatorIndex(validatorIndex), slashingQuotient, cfg.ProposerRewardQuotient)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if helpers.IsSlashableValidator(val.ActivationEpoch(), val.WithdrawableEpoch(), val.Slashed(), currentEpoch) {
|
||||
cfg := params.BeaconConfig()
|
||||
slashingQuotient := cfg.MinSlashingPenaltyQuotient
|
||||
if beaconState.Version() == version.Altair {
|
||||
slashingQuotient = cfg.MinSlashingPenaltyQuotientAltair
|
||||
}
|
||||
beaconState, err = slashFunc(ctx, beaconState, types.ValidatorIndex(validatorIndex), slashingQuotient, cfg.ProposerRewardQuotient)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not slash validator index %d",
|
||||
validatorIndex)
|
||||
}
|
||||
slashedAny = true
|
||||
return nil, errors.Wrapf(err, "could not slash validator index %d",
|
||||
validatorIndex)
|
||||
}
|
||||
slashedAny = true
|
||||
}
|
||||
if !slashedAny {
|
||||
return nil, errors.New("unable to slash any validator despite confirmed attester slashing")
|
||||
}
|
||||
}
|
||||
if !slashedAny {
|
||||
return nil, errors.New("unable to slash any validator despite confirmed attester slashing")
|
||||
}
|
||||
return beaconState, nil
|
||||
}
|
||||
@@ -132,7 +152,8 @@ func IsSlashableAttestationData(data1, data2 *ethpb.AttestationData) bool {
|
||||
return isDoubleVote || isSurroundVote
|
||||
}
|
||||
|
||||
func slashableAttesterIndices(slashing *ethpb.AttesterSlashing) []uint64 {
|
||||
// SlashableAttesterIndices returns the intersection of attester indices from both attestations in this slashing.
|
||||
func SlashableAttesterIndices(slashing *ethpb.AttesterSlashing) []uint64 {
|
||||
if slashing == nil || slashing.Attestation_1 == nil || slashing.Attestation_2 == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -245,7 +245,7 @@ func TestFuzzslashableAttesterIndices_10000(t *testing.T) {
|
||||
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(attesterSlashing)
|
||||
slashableAttesterIndices(attesterSlashing)
|
||||
SlashableAttesterIndices(attesterSlashing)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ func TestProcessDeposits_MerkleBranchFailsVerification(t *testing.T) {
|
||||
Data: ðpb.Deposit_Data{
|
||||
PublicKey: bytesutil.PadTo([]byte{1, 2, 3}, 48),
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
Signature: make([]byte, 96),
|
||||
Signature: make([]byte, params.BeaconConfig().BLSSignatureLength),
|
||||
},
|
||||
}
|
||||
leaf, err := deposit.Data.HashTreeRoot()
|
||||
@@ -139,7 +139,7 @@ func TestProcessDeposits_RepeatedDeposit_IncreasesValidatorBalance(t *testing.T)
|
||||
PublicKey: sk.PublicKey().Marshal(),
|
||||
Amount: 1000,
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
Signature: make([]byte, 96),
|
||||
Signature: make([]byte, params.BeaconConfig().BLSSignatureLength),
|
||||
},
|
||||
}
|
||||
sr, err := signing.ComputeSigningRoot(deposit.Data, bytesutil.ToBytes(3, 32))
|
||||
|
||||
@@ -16,7 +16,7 @@ func NewGenesisBlock(stateRoot []byte) *ethpb.SignedBeaconBlock {
|
||||
ParentRoot: zeroHash,
|
||||
StateRoot: bytesutil.PadTo(stateRoot, 32),
|
||||
Body: ðpb.BeaconBlockBody{
|
||||
RandaoReveal: make([]byte, 96),
|
||||
RandaoReveal: make([]byte, params.BeaconConfig().BLSSignatureLength),
|
||||
Eth1Data: ðpb.Eth1Data{
|
||||
DepositRoot: make([]byte, 32),
|
||||
BlockHash: make([]byte, 32),
|
||||
|
||||
@@ -43,7 +43,7 @@ func ProcessBlockHeader(
|
||||
beaconState state.BeaconState,
|
||||
block block.SignedBeaconBlock,
|
||||
) (state.BeaconState, error) {
|
||||
if err := helpers.VerifyNilBeaconBlock(block); err != nil {
|
||||
if err := helpers.BeaconBlockIsNil(block); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bodyRoot, err := block.Block().Body().HashTreeRoot()
|
||||
|
||||
@@ -51,26 +51,46 @@ func ProcessProposerSlashings(
|
||||
slashFunc slashValidatorFunc,
|
||||
) (state.BeaconState, error) {
|
||||
var err error
|
||||
for idx, slashing := range slashings {
|
||||
if slashing == nil {
|
||||
return nil, errors.New("nil proposer slashings in block body")
|
||||
}
|
||||
if err = VerifyProposerSlashing(beaconState, slashing); err != nil {
|
||||
return nil, errors.Wrapf(err, "could not verify proposer slashing %d", idx)
|
||||
}
|
||||
cfg := params.BeaconConfig()
|
||||
slashingQuotient := cfg.MinSlashingPenaltyQuotient
|
||||
if beaconState.Version() == version.Altair {
|
||||
slashingQuotient = cfg.MinSlashingPenaltyQuotientAltair
|
||||
}
|
||||
beaconState, err = slashFunc(ctx, beaconState, slashing.Header_1.Header.ProposerIndex, slashingQuotient, cfg.ProposerRewardQuotient)
|
||||
for _, slashing := range slashings {
|
||||
beaconState, err = ProcessProposerSlashing(ctx, beaconState, slashing, slashFunc)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not slash proposer index %d", slashing.Header_1.Header.ProposerIndex)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return beaconState, nil
|
||||
}
|
||||
|
||||
// ProcessProposerSlashing processes individual proposer slashing.
|
||||
func ProcessProposerSlashing(
|
||||
ctx context.Context,
|
||||
beaconState state.BeaconState,
|
||||
slashing *ethpb.ProposerSlashing,
|
||||
slashFunc slashValidatorFunc,
|
||||
) (state.BeaconState, error) {
|
||||
var err error
|
||||
if slashing == nil {
|
||||
return nil, errors.New("nil proposer slashings in block body")
|
||||
}
|
||||
if err = VerifyProposerSlashing(beaconState, slashing); err != nil {
|
||||
return nil, errors.Wrap(err, "could not verify proposer slashing")
|
||||
}
|
||||
cfg := params.BeaconConfig()
|
||||
var slashingQuotient uint64
|
||||
switch {
|
||||
case beaconState.Version() == version.Phase0:
|
||||
slashingQuotient = cfg.MinSlashingPenaltyQuotient
|
||||
case beaconState.Version() == version.Altair:
|
||||
slashingQuotient = cfg.MinSlashingPenaltyQuotientAltair
|
||||
default:
|
||||
return nil, errors.New("unknown state version")
|
||||
}
|
||||
beaconState, err = slashFunc(ctx, beaconState, slashing.Header_1.Header.ProposerIndex, slashingQuotient, cfg.ProposerRewardQuotient)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not slash proposer index %d", slashing.Header_1.Header.ProposerIndex)
|
||||
}
|
||||
return beaconState, nil
|
||||
}
|
||||
|
||||
// VerifyProposerSlashing verifies that the data provided from slashing is valid.
|
||||
func VerifyProposerSlashing(
|
||||
beaconState state.ReadOnlyBeaconState,
|
||||
|
||||
@@ -105,7 +105,7 @@ func TestProcessProposerSlashings_ValidatorNotSlashable(t *testing.T) {
|
||||
Slot: 0,
|
||||
BodyRoot: []byte("foo"),
|
||||
},
|
||||
Signature: bytesutil.PadTo([]byte("A"), 96),
|
||||
Signature: bytesutil.PadTo([]byte("A"), params.BeaconConfig().BLSSignatureLength),
|
||||
},
|
||||
Header_2: ðpb.SignedBeaconBlockHeader{
|
||||
Header: ðpb.BeaconBlockHeader{
|
||||
@@ -113,7 +113,7 @@ func TestProcessProposerSlashings_ValidatorNotSlashable(t *testing.T) {
|
||||
Slot: 0,
|
||||
BodyRoot: []byte("bar"),
|
||||
},
|
||||
Signature: bytesutil.PadTo([]byte("B"), 96),
|
||||
Signature: bytesutil.PadTo([]byte("B"), params.BeaconConfig().BLSSignatureLength),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ func ProcessRandao(
|
||||
beaconState state.BeaconState,
|
||||
b block.SignedBeaconBlock,
|
||||
) (state.BeaconState, error) {
|
||||
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
|
||||
if err := helpers.BeaconBlockIsNil(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
body := b.Block().Body()
|
||||
|
||||
@@ -24,6 +24,7 @@ go_library(
|
||||
"//monitoring/tracing:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//proto/prysm/v1alpha1/attestation:go_default_library",
|
||||
"//runtime/version:go_default_library",
|
||||
"//time/slots:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
|
||||
@@ -51,6 +52,7 @@ go_test(
|
||||
"//math:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//proto/prysm/v1alpha1/attestation:go_default_library",
|
||||
"//runtime/version:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"//testing/util:go_default_library",
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/monitoring/tracing"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/attestation"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
@@ -64,7 +65,7 @@ func ProcessAttestations(
|
||||
vp = UpdateValidator(vp, v, indices, a, a.Data.Slot)
|
||||
}
|
||||
|
||||
pBal = UpdateBalance(vp, pBal)
|
||||
pBal = UpdateBalance(vp, pBal, state.Version())
|
||||
|
||||
return vp, pBal, nil
|
||||
}
|
||||
@@ -170,7 +171,7 @@ func UpdateValidator(vp []*Validator, record *Validator, indices []uint64, a *et
|
||||
}
|
||||
|
||||
// UpdateBalance updates pre computed balance store.
|
||||
func UpdateBalance(vp []*Validator, bBal *Balance) *Balance {
|
||||
func UpdateBalance(vp []*Validator, bBal *Balance, stateVersion int) *Balance {
|
||||
for _, v := range vp {
|
||||
if !v.IsSlashed {
|
||||
if v.IsCurrentEpochAttester {
|
||||
@@ -179,7 +180,10 @@ func UpdateBalance(vp []*Validator, bBal *Balance) *Balance {
|
||||
if v.IsCurrentEpochTargetAttester {
|
||||
bBal.CurrentEpochTargetAttested += v.CurrentEpochEffectiveBalance
|
||||
}
|
||||
if v.IsPrevEpochAttester {
|
||||
if stateVersion == version.Phase0 && v.IsPrevEpochAttester {
|
||||
bBal.PrevEpochAttested += v.CurrentEpochEffectiveBalance
|
||||
}
|
||||
if stateVersion == version.Altair && v.IsPrevEpochSourceAttester {
|
||||
bBal.PrevEpochAttested += v.CurrentEpochEffectiveBalance
|
||||
}
|
||||
if v.IsPrevEpochTargetAttester {
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/attestation"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/testing/util"
|
||||
@@ -65,7 +66,7 @@ func TestUpdateBalance(t *testing.T) {
|
||||
PrevEpochTargetAttested: 100 * params.BeaconConfig().EffectiveBalanceIncrement,
|
||||
PrevEpochHeadAttested: 200 * params.BeaconConfig().EffectiveBalanceIncrement,
|
||||
}
|
||||
pBal := precompute.UpdateBalance(vp, &precompute.Balance{})
|
||||
pBal := precompute.UpdateBalance(vp, &precompute.Balance{}, version.Phase0)
|
||||
assert.DeepEqual(t, wantedPBal, pBal, "Incorrect balance calculations")
|
||||
}
|
||||
|
||||
|
||||
@@ -20,12 +20,14 @@ type Validator struct {
|
||||
IsCurrentEpochTargetAttester bool
|
||||
// IsPrevEpochAttester is true if the validator attested previous epoch.
|
||||
IsPrevEpochAttester bool
|
||||
// IsPrevEpochSourceAttester is true if the validator attested to source previous epoch. [Only for Altair]
|
||||
IsPrevEpochSourceAttester bool
|
||||
// IsPrevEpochTargetAttester is true if the validator attested previous epoch target.
|
||||
IsPrevEpochTargetAttester bool
|
||||
// IsHeadAttester is true if the validator attested head.
|
||||
IsPrevEpochHeadAttester bool
|
||||
|
||||
// CurrentEpochEffectiveBalance is how much effective balance this validator validator has current epoch.
|
||||
// CurrentEpochEffectiveBalance is how much effective balance this validator has current epoch.
|
||||
CurrentEpochEffectiveBalance uint64
|
||||
// InclusionSlot is the slot of when the attestation gets included in the chain.
|
||||
InclusionSlot types.Slot
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
// Package operation contains types for block operation-specific events fired
|
||||
// during the runtime of a beacon node such as attestations, voluntary
|
||||
// exits, and slashings.
|
||||
// Package operation contains types for block operation-specific events fired during the runtime of a beacon node.
|
||||
package operation
|
||||
|
||||
import (
|
||||
@@ -18,6 +16,9 @@ const (
|
||||
|
||||
// ExitReceived is sent after an voluntary exit object has been received from the outside world (eg in RPC or sync)
|
||||
ExitReceived
|
||||
|
||||
// SyncCommitteeContributionReceived is sent after a sync committee contribution object has been received.
|
||||
SyncCommitteeContributionReceived
|
||||
)
|
||||
|
||||
// UnAggregatedAttReceivedData is the data sent with UnaggregatedAttReceived events.
|
||||
@@ -37,3 +38,9 @@ type ExitReceivedData struct {
|
||||
// Exit is the voluntary exit object.
|
||||
Exit *ethpb.SignedVoluntaryExit
|
||||
}
|
||||
|
||||
// SyncCommitteeContributionReceivedData is the data sent with SyncCommitteeContributionReceived objects.
|
||||
type SyncCommitteeContributionReceivedData struct {
|
||||
// Contribution is the sync committee contribution object.
|
||||
Contribution *ethpb.SignedContributionAndProof
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ go_library(
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers",
|
||||
visibility = [
|
||||
"//beacon-chain:__subpackages__",
|
||||
"//cmd/beacon-chain:__subpackages__",
|
||||
"//contracts/deposit:__pkg__",
|
||||
"//crypto/keystore:__pkg__",
|
||||
"//fuzz:__pkg__",
|
||||
|
||||
@@ -199,7 +199,7 @@ func CommitteeAssignments(
|
||||
// Each slot in an epoch has a different set of committees. This value is derived from the
|
||||
// active validator set, which does not change.
|
||||
numCommitteesPerSlot := SlotCommitteeCount(uint64(len(activeValidatorIndices)))
|
||||
validatorIndexToCommittee := make(map[types.ValidatorIndex]*CommitteeAssignmentContainer, params.BeaconConfig().SlotsPerEpoch.Mul(numCommitteesPerSlot))
|
||||
validatorIndexToCommittee := make(map[types.ValidatorIndex]*CommitteeAssignmentContainer, len(activeValidatorIndices))
|
||||
|
||||
// Compute all committees for all slots.
|
||||
for i := types.Slot(0); i < params.BeaconConfig().SlotsPerEpoch; i++ {
|
||||
|
||||
@@ -11,10 +11,10 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
)
|
||||
|
||||
// VerifyNilBeaconBlock checks if any composite field of input signed beacon block is nil.
|
||||
// BeaconBlockIsNil checks if any composite field of input signed beacon block is nil.
|
||||
// Access to these nil fields will result in run time panic,
|
||||
// it is recommended to run these checks as first line of defense.
|
||||
func VerifyNilBeaconBlock(b block.SignedBeaconBlock) error {
|
||||
func BeaconBlockIsNil(b block.SignedBeaconBlock) error {
|
||||
if b == nil || b.IsNil() {
|
||||
return errors.New("signed beacon block can't be nil")
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@ package signing
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/eth2-types"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
"github.com/prysmaticlabs/prysm/crypto/bls"
|
||||
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
eth "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
// Domain returns the domain version for BLS private key to sign and verify.
|
||||
|
||||
@@ -3,9 +3,9 @@ package signing
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/eth2-types"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
eth "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
)
|
||||
|
||||
@@ -24,7 +24,6 @@ go_test(
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"//time:go_default_library",
|
||||
"//time/slots:go_default_library",
|
||||
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
|
||||
],
|
||||
|
||||
@@ -59,3 +59,22 @@ func CanUpgradeToAltair(slot types.Slot) bool {
|
||||
altairEpoch := slots.ToEpoch(slot) == params.BeaconConfig().AltairForkEpoch
|
||||
return epochStart && altairEpoch
|
||||
}
|
||||
|
||||
// CanUpgradeToMerge returns true if the input `slot` can upgrade to Merge fork.
|
||||
//
|
||||
// Spec code:
|
||||
// If state.slot % SLOTS_PER_EPOCH == 0 and compute_epoch_at_slot(state.slot) == MERGE_FORK_EPOCH
|
||||
func CanUpgradeToMerge(slot types.Slot) bool {
|
||||
epochStart := slots.IsEpochStart(slot)
|
||||
mergeEpoch := slots.ToEpoch(slot) == params.BeaconConfig().MergeForkEpoch
|
||||
return epochStart && mergeEpoch
|
||||
}
|
||||
|
||||
// CanProcessEpoch checks the eligibility to process epoch.
|
||||
// The epoch can be processed at the end of the last slot of every epoch.
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
// If (state.slot + 1) % SLOTS_PER_EPOCH == 0:
|
||||
func CanProcessEpoch(state state.ReadOnlyBeaconState) bool {
|
||||
return (state.Slot()+1)%params.BeaconConfig().SlotsPerEpoch == 0
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
package time
|
||||
|
||||
import (
|
||||
"math"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
|
||||
@@ -11,7 +9,6 @@ import (
|
||||
eth "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
prysmTime "github.com/prysmaticlabs/prysm/time"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
)
|
||||
|
||||
@@ -83,338 +80,6 @@ func TestNextEpoch_OK(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestEpochStartSlot_OK(t *testing.T) {
|
||||
tests := []struct {
|
||||
epoch types.Epoch
|
||||
startSlot types.Slot
|
||||
error bool
|
||||
}{
|
||||
{epoch: 0, startSlot: 0 * params.BeaconConfig().SlotsPerEpoch, error: false},
|
||||
{epoch: 1, startSlot: 1 * params.BeaconConfig().SlotsPerEpoch, error: false},
|
||||
{epoch: 10, startSlot: 10 * params.BeaconConfig().SlotsPerEpoch, error: false},
|
||||
{epoch: 1 << 58, startSlot: 1 << 63, error: false},
|
||||
{epoch: 1 << 59, startSlot: 1 << 63, error: true},
|
||||
{epoch: 1 << 60, startSlot: 1 << 63, error: true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
ss, err := slots.EpochStart(tt.epoch)
|
||||
if !tt.error {
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, tt.startSlot, ss, "EpochStart(%d)", tt.epoch)
|
||||
} else {
|
||||
require.ErrorContains(t, "start slot calculation overflow", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEpochEndSlot_OK(t *testing.T) {
|
||||
tests := []struct {
|
||||
epoch types.Epoch
|
||||
startSlot types.Slot
|
||||
error bool
|
||||
}{
|
||||
{epoch: 0, startSlot: 1*params.BeaconConfig().SlotsPerEpoch - 1, error: false},
|
||||
{epoch: 1, startSlot: 2*params.BeaconConfig().SlotsPerEpoch - 1, error: false},
|
||||
{epoch: 10, startSlot: 11*params.BeaconConfig().SlotsPerEpoch - 1, error: false},
|
||||
{epoch: 1 << 59, startSlot: 1 << 63, error: true},
|
||||
{epoch: 1 << 60, startSlot: 1 << 63, error: true},
|
||||
{epoch: math.MaxUint64, startSlot: 0, error: true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
ss, err := slots.EpochEnd(tt.epoch)
|
||||
if !tt.error {
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, tt.startSlot, ss, "EpochStart(%d)", tt.epoch)
|
||||
} else {
|
||||
require.ErrorContains(t, "start slot calculation overflow", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsEpochStart(t *testing.T) {
|
||||
epochLength := params.BeaconConfig().SlotsPerEpoch
|
||||
|
||||
tests := []struct {
|
||||
slot types.Slot
|
||||
result bool
|
||||
}{
|
||||
{
|
||||
slot: epochLength + 1,
|
||||
result: false,
|
||||
},
|
||||
{
|
||||
slot: epochLength - 1,
|
||||
result: false,
|
||||
},
|
||||
{
|
||||
slot: epochLength,
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
slot: epochLength * 2,
|
||||
result: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
assert.Equal(t, tt.result, slots.IsEpochStart(tt.slot), "IsEpochStart(%d)", tt.slot)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsEpochEnd(t *testing.T) {
|
||||
epochLength := params.BeaconConfig().SlotsPerEpoch
|
||||
|
||||
tests := []struct {
|
||||
slot types.Slot
|
||||
result bool
|
||||
}{
|
||||
{
|
||||
slot: epochLength + 1,
|
||||
result: false,
|
||||
},
|
||||
{
|
||||
slot: epochLength,
|
||||
result: false,
|
||||
},
|
||||
{
|
||||
slot: epochLength - 1,
|
||||
result: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
assert.Equal(t, tt.result, slots.IsEpochEnd(tt.slot), "IsEpochEnd(%d)", tt.slot)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSlotsSinceEpochStarts(t *testing.T) {
|
||||
tests := []struct {
|
||||
slots types.Slot
|
||||
wantedSlots types.Slot
|
||||
}{
|
||||
{slots: 0, wantedSlots: 0},
|
||||
{slots: 1, wantedSlots: 1},
|
||||
{slots: params.BeaconConfig().SlotsPerEpoch - 1, wantedSlots: params.BeaconConfig().SlotsPerEpoch - 1},
|
||||
{slots: params.BeaconConfig().SlotsPerEpoch + 1, wantedSlots: 1},
|
||||
{slots: 10*params.BeaconConfig().SlotsPerEpoch + 2, wantedSlots: 2},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
assert.Equal(t, tt.wantedSlots, slots.SinceEpochStarts(tt.slots))
|
||||
}
|
||||
}
|
||||
|
||||
func TestRoundUpToNearestEpoch_OK(t *testing.T) {
|
||||
tests := []struct {
|
||||
startSlot types.Slot
|
||||
roundedUpSlot types.Slot
|
||||
}{
|
||||
{startSlot: 0 * params.BeaconConfig().SlotsPerEpoch, roundedUpSlot: 0},
|
||||
{startSlot: 1*params.BeaconConfig().SlotsPerEpoch - 10, roundedUpSlot: 1 * params.BeaconConfig().SlotsPerEpoch},
|
||||
{startSlot: 10*params.BeaconConfig().SlotsPerEpoch - (params.BeaconConfig().SlotsPerEpoch - 1), roundedUpSlot: 10 * params.BeaconConfig().SlotsPerEpoch},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
assert.Equal(t, tt.roundedUpSlot, slots.RoundUpToNearestEpoch(tt.startSlot), "RoundUpToNearestEpoch(%d)", tt.startSlot)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSlotToTime(t *testing.T) {
|
||||
type args struct {
|
||||
genesisTimeSec uint64
|
||||
slot types.Slot
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want time.Time
|
||||
wantedErr string
|
||||
}{
|
||||
{
|
||||
name: "slot_0",
|
||||
args: args{
|
||||
genesisTimeSec: 0,
|
||||
slot: 0,
|
||||
},
|
||||
want: time.Unix(0, 0),
|
||||
},
|
||||
{
|
||||
name: "slot_1",
|
||||
args: args{
|
||||
genesisTimeSec: 0,
|
||||
slot: 1,
|
||||
},
|
||||
want: time.Unix(int64(1*params.BeaconConfig().SecondsPerSlot), 0),
|
||||
},
|
||||
{
|
||||
name: "slot_12",
|
||||
args: args{
|
||||
genesisTimeSec: 500,
|
||||
slot: 12,
|
||||
},
|
||||
want: time.Unix(500+int64(12*params.BeaconConfig().SecondsPerSlot), 0),
|
||||
},
|
||||
{
|
||||
name: "overflow",
|
||||
args: args{
|
||||
genesisTimeSec: 500,
|
||||
slot: math.MaxUint64,
|
||||
},
|
||||
wantedErr: "is in the far distant future",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := slots.ToTime(tt.args.genesisTimeSec, tt.args.slot)
|
||||
if tt.wantedErr != "" {
|
||||
assert.ErrorContains(t, tt.wantedErr, err)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.DeepEqual(t, tt.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestVerifySlotTime(t *testing.T) {
|
||||
type args struct {
|
||||
genesisTime int64
|
||||
slot types.Slot
|
||||
timeTolerance time.Duration
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantedErr string
|
||||
}{
|
||||
{
|
||||
name: "Past slot",
|
||||
args: args{
|
||||
genesisTime: prysmTime.Now().Add(-1 * 5 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second).Unix(),
|
||||
slot: 3,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "within tolerance",
|
||||
args: args{
|
||||
genesisTime: prysmTime.Now().Add(-1 * 5 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second).Add(20 * time.Millisecond).Unix(),
|
||||
slot: 5,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "future slot",
|
||||
args: args{
|
||||
genesisTime: prysmTime.Now().Add(-1 * 5 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second).Unix(),
|
||||
slot: 6,
|
||||
},
|
||||
wantedErr: "could not process slot from the future",
|
||||
},
|
||||
{
|
||||
name: "max future slot",
|
||||
args: args{
|
||||
genesisTime: prysmTime.Now().Add(-1 * 5 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second).Unix(),
|
||||
slot: types.Slot(slots.MaxSlotBuffer + 6),
|
||||
},
|
||||
wantedErr: "exceeds max allowed value relative to the local clock",
|
||||
},
|
||||
{
|
||||
name: "evil future slot",
|
||||
args: args{
|
||||
genesisTime: prysmTime.Now().Add(-1 * 24 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second).Unix(), // 24 slots in the past
|
||||
// Gets multiplied with slot duration, and results in an overflow. Wraps around to a valid time.
|
||||
// Lower than max signed int. And chosen specifically to wrap to a valid slot 24
|
||||
slot: types.Slot((^uint64(0))/params.BeaconConfig().SecondsPerSlot) + 24,
|
||||
},
|
||||
wantedErr: "is in the far distant future",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := slots.VerifyTime(uint64(tt.args.genesisTime), tt.args.slot, tt.args.timeTolerance)
|
||||
if tt.wantedErr != "" {
|
||||
assert.ErrorContains(t, tt.wantedErr, err)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateSlotClock_HandlesBadSlot(t *testing.T) {
|
||||
genTime := prysmTime.Now().Add(-1 * time.Duration(slots.MaxSlotBuffer) * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second).Unix()
|
||||
|
||||
assert.NoError(t, slots.ValidateClock(types.Slot(slots.MaxSlotBuffer), uint64(genTime)), "unexpected error validating slot")
|
||||
assert.NoError(t, slots.ValidateClock(types.Slot(2*slots.MaxSlotBuffer), uint64(genTime)), "unexpected error validating slot")
|
||||
assert.ErrorContains(t, "which exceeds max allowed value relative to the local clock", slots.ValidateClock(types.Slot(2*slots.MaxSlotBuffer+1), uint64(genTime)), "no error from bad slot")
|
||||
assert.ErrorContains(t, "which exceeds max allowed value relative to the local clock", slots.ValidateClock(1<<63, uint64(genTime)), "no error from bad slot")
|
||||
}
|
||||
|
||||
func TestPrevSlot(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
slot types.Slot
|
||||
want types.Slot
|
||||
}{
|
||||
{
|
||||
name: "no underflow",
|
||||
slot: 0,
|
||||
want: 0,
|
||||
},
|
||||
{
|
||||
name: "slot 1",
|
||||
slot: 1,
|
||||
want: 0,
|
||||
},
|
||||
{
|
||||
name: "slot 2",
|
||||
slot: 2,
|
||||
want: 1,
|
||||
},
|
||||
{
|
||||
name: "max",
|
||||
slot: 1<<64 - 1,
|
||||
want: 1<<64 - 1 - 1,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := slots.PrevSlot(tt.slot); got != tt.want {
|
||||
t.Errorf("PrevSlot() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSyncCommitteePeriod(t *testing.T) {
|
||||
tests := []struct {
|
||||
epoch types.Epoch
|
||||
wanted uint64
|
||||
}{
|
||||
{epoch: 0, wanted: 0},
|
||||
{epoch: 0, wanted: 0 / uint64(params.BeaconConfig().EpochsPerSyncCommitteePeriod)},
|
||||
{epoch: 1, wanted: 1 / uint64(params.BeaconConfig().EpochsPerSyncCommitteePeriod)},
|
||||
{epoch: 1000, wanted: 1000 / uint64(params.BeaconConfig().EpochsPerSyncCommitteePeriod)},
|
||||
}
|
||||
for _, test := range tests {
|
||||
require.Equal(t, test.wanted, slots.SyncCommitteePeriod(test.epoch))
|
||||
}
|
||||
}
|
||||
|
||||
func TestSyncCommitteePeriodStartEpoch(t *testing.T) {
|
||||
tests := []struct {
|
||||
epoch types.Epoch
|
||||
wanted types.Epoch
|
||||
}{
|
||||
{epoch: 0, wanted: 0},
|
||||
{epoch: params.BeaconConfig().EpochsPerSyncCommitteePeriod + 1, wanted: params.BeaconConfig().EpochsPerSyncCommitteePeriod},
|
||||
{epoch: params.BeaconConfig().EpochsPerSyncCommitteePeriod*2 + 100, wanted: params.BeaconConfig().EpochsPerSyncCommitteePeriod * 2},
|
||||
{epoch: params.BeaconConfig().EpochsPerSyncCommitteePeriod*params.BeaconConfig().EpochsPerSyncCommitteePeriod + 1, wanted: params.BeaconConfig().EpochsPerSyncCommitteePeriod * params.BeaconConfig().EpochsPerSyncCommitteePeriod},
|
||||
}
|
||||
for _, test := range tests {
|
||||
e, err := slots.SyncCommitteePeriodStartEpoch(test.epoch)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, test.wanted, e)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCanUpgradeToAltair(t *testing.T) {
|
||||
bc := params.BeaconConfig()
|
||||
bc.AltairForkEpoch = 5
|
||||
@@ -448,3 +113,69 @@ func TestCanUpgradeToAltair(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCanUpgradeToMerge(t *testing.T) {
|
||||
bc := params.BeaconConfig()
|
||||
bc.MergeForkEpoch = 5
|
||||
params.OverrideBeaconConfig(bc)
|
||||
tests := []struct {
|
||||
name string
|
||||
slot types.Slot
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "not epoch start",
|
||||
slot: 1,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "not merge epoch",
|
||||
slot: params.BeaconConfig().SlotsPerEpoch,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "merge epoch",
|
||||
slot: types.Slot(params.BeaconConfig().MergeForkEpoch) * params.BeaconConfig().SlotsPerEpoch,
|
||||
want: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := CanUpgradeToMerge(tt.slot); got != tt.want {
|
||||
t.Errorf("CanUpgradeToMerge() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCanProcessEpoch_TrueOnEpochsLastSlot(t *testing.T) {
|
||||
tests := []struct {
|
||||
slot types.Slot
|
||||
canProcessEpoch bool
|
||||
}{
|
||||
{
|
||||
slot: 1,
|
||||
canProcessEpoch: false,
|
||||
}, {
|
||||
slot: 63,
|
||||
canProcessEpoch: true,
|
||||
},
|
||||
{
|
||||
slot: 64,
|
||||
canProcessEpoch: false,
|
||||
}, {
|
||||
slot: 127,
|
||||
canProcessEpoch: true,
|
||||
}, {
|
||||
slot: 1000000000,
|
||||
canProcessEpoch: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
b := ð.BeaconState{Slot: tt.slot}
|
||||
s, err := v1.InitializeFromProto(b)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, tt.canProcessEpoch, CanProcessEpoch(s), "CanProcessEpoch(%d)", tt.slot)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,6 @@ go_library(
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//proto/prysm/v1alpha1/block:go_default_library",
|
||||
"//runtime/version:go_default_library",
|
||||
"//time/slots:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_prometheus_client_golang//prometheus:go_default_library",
|
||||
"@com_github_prometheus_client_golang//prometheus/promauto:go_default_library",
|
||||
|
||||
@@ -213,9 +213,12 @@ func TestProcessEpoch_BadBalanceAltair(t *testing.T) {
|
||||
assert.NoError(t, s.SetSlot(63))
|
||||
assert.NoError(t, s.UpdateBalancesAtIndex(0, math.MaxUint64))
|
||||
participation := byte(0)
|
||||
participation = altair.AddValidatorFlag(participation, params.BeaconConfig().TimelyHeadFlagIndex)
|
||||
participation = altair.AddValidatorFlag(participation, params.BeaconConfig().TimelySourceFlagIndex)
|
||||
participation = altair.AddValidatorFlag(participation, params.BeaconConfig().TimelyTargetFlagIndex)
|
||||
participation, err := altair.AddValidatorFlag(participation, params.BeaconConfig().TimelyHeadFlagIndex)
|
||||
require.NoError(t, err)
|
||||
participation, err = altair.AddValidatorFlag(participation, params.BeaconConfig().TimelySourceFlagIndex)
|
||||
require.NoError(t, err)
|
||||
participation, err = altair.AddValidatorFlag(participation, params.BeaconConfig().TimelyTargetFlagIndex)
|
||||
require.NoError(t, err)
|
||||
|
||||
epochParticipation, err := s.CurrentEpochParticipation()
|
||||
assert.NoError(t, err)
|
||||
|
||||
@@ -22,7 +22,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/monitoring/tracing"
|
||||
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
@@ -52,8 +51,8 @@ func ExecuteStateTransition(
|
||||
if ctx.Err() != nil {
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
if signed == nil || signed.IsNil() || signed.Block().IsNil() {
|
||||
return nil, errors.New("nil block")
|
||||
if err := helpers.BeaconBlockIsNil(signed); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, span := trace.StartSpan(ctx, "core.state.ExecuteStateTransition")
|
||||
@@ -215,10 +214,7 @@ func ProcessSlots(ctx context.Context, state state.BeaconState, slot types.Slot)
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
if err := SkipSlotCache.MarkNotInProgress(key); err != nil {
|
||||
tracing.AnnotateError(span, err)
|
||||
log.WithError(err).Error("Failed to mark skip slot no longer in progress")
|
||||
}
|
||||
SkipSlotCache.MarkNotInProgress(key)
|
||||
}()
|
||||
|
||||
for state.Slot() < slot {
|
||||
@@ -226,7 +222,7 @@ func ProcessSlots(ctx context.Context, state state.BeaconState, slot types.Slot)
|
||||
tracing.AnnotateError(span, ctx.Err())
|
||||
// Cache last best value.
|
||||
if highestSlot < state.Slot() {
|
||||
if err := SkipSlotCache.Put(ctx, key, state); err != nil {
|
||||
if SkipSlotCache.Put(ctx, key, state); err != nil {
|
||||
log.WithError(err).Error("Failed to put skip slot cache value")
|
||||
}
|
||||
}
|
||||
@@ -237,7 +233,7 @@ func ProcessSlots(ctx context.Context, state state.BeaconState, slot types.Slot)
|
||||
tracing.AnnotateError(span, err)
|
||||
return nil, errors.Wrap(err, "could not process slot")
|
||||
}
|
||||
if CanProcessEpoch(state) {
|
||||
if time.CanProcessEpoch(state) {
|
||||
switch state.Version() {
|
||||
case version.Phase0:
|
||||
state, err = ProcessEpochPrecompute(ctx, state)
|
||||
@@ -260,7 +256,7 @@ func ProcessSlots(ctx context.Context, state state.BeaconState, slot types.Slot)
|
||||
return nil, errors.Wrap(err, "failed to increment state slot")
|
||||
}
|
||||
|
||||
if CanUpgradeToAltair(state.Slot()) {
|
||||
if time.CanUpgradeToAltair(state.Slot()) {
|
||||
state, err = altair.UpgradeToAltair(ctx, state)
|
||||
if err != nil {
|
||||
tracing.AnnotateError(span, err)
|
||||
@@ -270,27 +266,15 @@ func ProcessSlots(ctx context.Context, state state.BeaconState, slot types.Slot)
|
||||
}
|
||||
|
||||
if highestSlot < state.Slot() {
|
||||
if err := SkipSlotCache.Put(ctx, key, state); err != nil {
|
||||
log.WithError(err).Error("Failed to put skip slot cache value")
|
||||
tracing.AnnotateError(span, err)
|
||||
}
|
||||
SkipSlotCache.Put(ctx, key, state)
|
||||
}
|
||||
|
||||
return state, nil
|
||||
}
|
||||
|
||||
// CanUpgradeToAltair returns true if the input `slot` can upgrade to Altair.
|
||||
// Spec code:
|
||||
// If state.slot % SLOTS_PER_EPOCH == 0 and compute_epoch_at_slot(state.slot) == ALTAIR_FORK_EPOCH
|
||||
func CanUpgradeToAltair(slot types.Slot) bool {
|
||||
epochStart := slots.IsEpochStart(slot)
|
||||
altairEpoch := slots.ToEpoch(slot) == params.BeaconConfig().AltairForkEpoch
|
||||
return epochStart && altairEpoch
|
||||
}
|
||||
|
||||
// VerifyOperationLengths verifies that block operation lengths are valid.
|
||||
func VerifyOperationLengths(_ context.Context, state state.BeaconState, b block.SignedBeaconBlock) (state.BeaconState, error) {
|
||||
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
|
||||
if err := helpers.BeaconBlockIsNil(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
body := b.Block().Body()
|
||||
@@ -343,15 +327,6 @@ func VerifyOperationLengths(_ context.Context, state state.BeaconState, b block.
|
||||
return state, nil
|
||||
}
|
||||
|
||||
// CanProcessEpoch checks the eligibility to process epoch.
|
||||
// The epoch can be processed at the end of the last slot of every epoch
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
// If (state.slot + 1) % SLOTS_PER_EPOCH == 0:
|
||||
func CanProcessEpoch(state state.ReadOnlyBeaconState) bool {
|
||||
return (state.Slot()+1)%params.BeaconConfig().SlotsPerEpoch == 0
|
||||
}
|
||||
|
||||
// ProcessEpochPrecompute describes the per epoch operations that are performed on the beacon state.
|
||||
// It's optimized by pre computing validator attested info and epoch total/attested balances upfront.
|
||||
func ProcessEpochPrecompute(ctx context.Context, state state.BeaconState) (state.BeaconState, error) {
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
fuzz "github.com/google/gofuzz"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/time"
|
||||
v1 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
|
||||
@@ -122,7 +123,7 @@ func TestFuzzCanProcessEpoch_10000(_ *testing.T) {
|
||||
fuzzer.NilChance(0.1)
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
CanProcessEpoch(state)
|
||||
time.CanProcessEpoch(state)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -185,7 +185,7 @@ func ProcessBlockNoVerifyAnySig(
|
||||
) (*bls.SignatureSet, state.BeaconState, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "core.state.ProcessBlockNoVerifyAnySig")
|
||||
defer span.End()
|
||||
if err := helpers.VerifyNilBeaconBlock(signed); err != nil {
|
||||
if err := helpers.BeaconBlockIsNil(signed); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
@@ -258,7 +258,7 @@ func ProcessOperationsNoVerifyAttsSigs(
|
||||
signedBeaconBlock block.SignedBeaconBlock) (state.BeaconState, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "core.state.ProcessOperationsNoVerifyAttsSigs")
|
||||
defer span.End()
|
||||
if err := helpers.VerifyNilBeaconBlock(signedBeaconBlock); err != nil {
|
||||
if err := helpers.BeaconBlockIsNil(signedBeaconBlock); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -294,7 +294,7 @@ func ProcessBlockForStateRoot(
|
||||
) (state.BeaconState, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "core.state.ProcessBlockForStateRoot")
|
||||
defer span.End()
|
||||
if err := helpers.VerifyNilBeaconBlock(signed); err != nil {
|
||||
if err := helpers.BeaconBlockIsNil(signed); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
@@ -382,38 +382,6 @@ func TestProcessEpochPrecompute_CanProcess(t *testing.T) {
|
||||
assert.Equal(t, uint64(0), newState.Slashings()[2], "Unexpected slashed balance")
|
||||
}
|
||||
|
||||
func TestCanProcessEpoch_TrueOnEpochs(t *testing.T) {
|
||||
tests := []struct {
|
||||
slot types.Slot
|
||||
canProcessEpoch bool
|
||||
}{
|
||||
{
|
||||
slot: 1,
|
||||
canProcessEpoch: false,
|
||||
}, {
|
||||
slot: 63,
|
||||
canProcessEpoch: true,
|
||||
},
|
||||
{
|
||||
slot: 64,
|
||||
canProcessEpoch: false,
|
||||
}, {
|
||||
slot: 127,
|
||||
canProcessEpoch: true,
|
||||
}, {
|
||||
slot: 1000000000,
|
||||
canProcessEpoch: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
b := ðpb.BeaconState{Slot: tt.slot}
|
||||
s, err := v1.InitializeFromProto(b)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, tt.canProcessEpoch, transition.CanProcessEpoch(s), "CanProcessEpoch(%d)", tt.slot)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProcessBlock_OverMaxProposerSlashings(t *testing.T) {
|
||||
maxSlashings := params.BeaconConfig().MaxProposerSlashings
|
||||
b := ðpb.SignedBeaconBlock{
|
||||
@@ -589,37 +557,3 @@ func TestProcessSlotsUsingNextSlotCache(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, types.Slot(5), s.Slot())
|
||||
}
|
||||
|
||||
func TestCanUpgradeToAltair(t *testing.T) {
|
||||
bc := params.BeaconConfig()
|
||||
bc.AltairForkEpoch = 5
|
||||
params.OverrideBeaconConfig(bc)
|
||||
tests := []struct {
|
||||
name string
|
||||
slot types.Slot
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "not epoch start",
|
||||
slot: 1,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "not altair epoch",
|
||||
slot: params.BeaconConfig().SlotsPerEpoch,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "altair epoch",
|
||||
slot: types.Slot(params.BeaconConfig().AltairForkEpoch) * params.BeaconConfig().SlotsPerEpoch,
|
||||
want: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := transition.CanUpgradeToAltair(tt.slot); got != tt.want {
|
||||
t.Errorf("canUpgradeToAltair() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,14 +39,6 @@ type ReadOnlyDatabase interface {
|
||||
StateSummary(ctx context.Context, blockRoot [32]byte) (*ethpb.StateSummary, error)
|
||||
HasStateSummary(ctx context.Context, blockRoot [32]byte) bool
|
||||
HighestSlotStatesBelow(ctx context.Context, slot types.Slot) ([]state.ReadOnlyBeaconState, error)
|
||||
// Slashing operations.
|
||||
ProposerSlashing(ctx context.Context, slashingRoot [32]byte) (*eth.ProposerSlashing, error)
|
||||
AttesterSlashing(ctx context.Context, slashingRoot [32]byte) (*eth.AttesterSlashing, error)
|
||||
HasProposerSlashing(ctx context.Context, slashingRoot [32]byte) bool
|
||||
HasAttesterSlashing(ctx context.Context, slashingRoot [32]byte) bool
|
||||
// Block operations.
|
||||
VoluntaryExit(ctx context.Context, exitRoot [32]byte) (*eth.VoluntaryExit, error)
|
||||
HasVoluntaryExit(ctx context.Context, exitRoot [32]byte) bool
|
||||
// Checkpoint operations.
|
||||
JustifiedCheckpoint(ctx context.Context) (*eth.Checkpoint, error)
|
||||
FinalizedCheckpoint(ctx context.Context) (*eth.Checkpoint, error)
|
||||
@@ -75,11 +67,6 @@ type NoHeadAccessDatabase interface {
|
||||
DeleteStates(ctx context.Context, blockRoots [][32]byte) error
|
||||
SaveStateSummary(ctx context.Context, summary *ethpb.StateSummary) error
|
||||
SaveStateSummaries(ctx context.Context, summaries []*ethpb.StateSummary) error
|
||||
// Slashing operations.
|
||||
SaveProposerSlashing(ctx context.Context, slashing *eth.ProposerSlashing) error
|
||||
SaveAttesterSlashing(ctx context.Context, slashing *eth.AttesterSlashing) error
|
||||
// Block operations.
|
||||
SaveVoluntaryExit(ctx context.Context, exit *eth.VoluntaryExit) error
|
||||
// Checkpoint operations.
|
||||
SaveJustifiedCheckpoint(ctx context.Context, checkpoint *eth.Checkpoint) error
|
||||
SaveFinalizedCheckpoint(ctx context.Context, checkpoint *eth.Checkpoint) error
|
||||
|
||||
@@ -18,10 +18,8 @@ go_library(
|
||||
"migration_archived_index.go",
|
||||
"migration_block_slot_index.go",
|
||||
"migration_state_validators.go",
|
||||
"operations.go",
|
||||
"powchain.go",
|
||||
"schema.go",
|
||||
"slashings.go",
|
||||
"state.go",
|
||||
"state_summary.go",
|
||||
"state_summary_cache.go",
|
||||
@@ -88,9 +86,7 @@ go_test(
|
||||
"migration_archived_index_test.go",
|
||||
"migration_block_slot_index_test.go",
|
||||
"migration_state_validators_test.go",
|
||||
"operations_test.go",
|
||||
"powchain_test.go",
|
||||
"slashings_test.go",
|
||||
"state_summary_test.go",
|
||||
"state_test.go",
|
||||
"utils_test.go",
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"fmt"
|
||||
"path"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/io/file"
|
||||
bolt "go.etcd.io/bbolt"
|
||||
@@ -34,8 +34,8 @@ func (s *Store) Backup(ctx context.Context, outputDir string, permissionOverride
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if head == nil || head.IsNil() {
|
||||
return errors.New("no head block")
|
||||
if err := helpers.BeaconBlockIsNil(head); err != nil {
|
||||
return err
|
||||
}
|
||||
// Ensure the backups directory exists.
|
||||
if err := file.HandleBackupDir(backupsDir, permissionOverride); err != nil {
|
||||
|
||||
@@ -150,11 +150,7 @@ func (s *Store) BlocksBySlot(ctx context.Context, slot types.Slot) (bool, []bloc
|
||||
err := s.db.View(func(tx *bolt.Tx) error {
|
||||
bkt := tx.Bucket(blocksBucket)
|
||||
|
||||
keys, err := blockRootsBySlot(ctx, tx, slot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
keys := blockRootsBySlot(ctx, tx, slot)
|
||||
for i := 0; i < len(keys); i++ {
|
||||
encoded := bkt.Get(keys[i])
|
||||
blk, err := unmarshalBlock(ctx, encoded)
|
||||
@@ -174,11 +170,7 @@ func (s *Store) BlockRootsBySlot(ctx context.Context, slot types.Slot) (bool, []
|
||||
defer span.End()
|
||||
blockRoots := make([][32]byte, 0)
|
||||
err := s.db.View(func(tx *bolt.Tx) error {
|
||||
keys, err := blockRootsBySlot(ctx, tx, slot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
keys := blockRootsBySlot(ctx, tx, slot)
|
||||
for i := 0; i < len(keys); i++ {
|
||||
blockRoots = append(blockRoots, bytesutil.ToBytes32(keys[i]))
|
||||
}
|
||||
@@ -519,7 +511,7 @@ func blockRootsBySlotRange(
|
||||
}
|
||||
|
||||
// blockRootsBySlot retrieves the block roots by slot
|
||||
func blockRootsBySlot(ctx context.Context, tx *bolt.Tx, slot types.Slot) ([][]byte, error) {
|
||||
func blockRootsBySlot(ctx context.Context, tx *bolt.Tx, slot types.Slot) [][]byte {
|
||||
ctx, span := trace.StartSpan(ctx, "BeaconDB.blockRootsBySlot")
|
||||
defer span.End()
|
||||
|
||||
@@ -533,7 +525,7 @@ func blockRootsBySlot(ctx context.Context, tx *bolt.Tx, slot types.Slot) ([][]by
|
||||
roots = append(roots, v[i:i+32])
|
||||
}
|
||||
}
|
||||
return roots, nil
|
||||
return roots
|
||||
}
|
||||
|
||||
// createBlockIndicesFromBlock takes in a beacon block and returns
|
||||
|
||||
@@ -3,8 +3,8 @@ package kv
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db/filters"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/monitoring/tracing"
|
||||
@@ -84,8 +84,7 @@ func (s *Store) updateFinalizedBlockRoots(ctx context.Context, tx *bolt.Tx, chec
|
||||
tracing.AnnotateError(span, err)
|
||||
return err
|
||||
}
|
||||
if signedBlock == nil || signedBlock.IsNil() || signedBlock.Block().IsNil() {
|
||||
err := fmt.Errorf("missing block in database: block root=%#x", root)
|
||||
if err := helpers.BeaconBlockIsNil(signedBlock); err != nil {
|
||||
tracing.AnnotateError(span, err)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
package kv
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
bolt "go.etcd.io/bbolt"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
// VoluntaryExit retrieval by signing root.
|
||||
func (s *Store) VoluntaryExit(ctx context.Context, exitRoot [32]byte) (*ethpb.VoluntaryExit, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "BeaconDB.VoluntaryExit")
|
||||
defer span.End()
|
||||
enc, err := s.voluntaryExitBytes(ctx, exitRoot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(enc) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
exit := ðpb.VoluntaryExit{}
|
||||
if err := decode(ctx, enc, exit); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return exit, nil
|
||||
}
|
||||
|
||||
// HasVoluntaryExit verifies if a voluntary exit is stored in the db by its signing root.
|
||||
func (s *Store) HasVoluntaryExit(ctx context.Context, exitRoot [32]byte) bool {
|
||||
ctx, span := trace.StartSpan(ctx, "BeaconDB.HasVoluntaryExit")
|
||||
defer span.End()
|
||||
enc, err := s.voluntaryExitBytes(ctx, exitRoot)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return len(enc) > 0
|
||||
}
|
||||
|
||||
// SaveVoluntaryExit to the db by its signing root.
|
||||
func (s *Store) SaveVoluntaryExit(ctx context.Context, exit *ethpb.VoluntaryExit) error {
|
||||
ctx, span := trace.StartSpan(ctx, "BeaconDB.SaveVoluntaryExit")
|
||||
defer span.End()
|
||||
exitRoot, err := exit.HashTreeRoot()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
enc, err := encode(ctx, exit)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.db.Update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(voluntaryExitsBucket)
|
||||
return bucket.Put(exitRoot[:], enc)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Store) voluntaryExitBytes(ctx context.Context, exitRoot [32]byte) ([]byte, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "BeaconDB.voluntaryExitBytes")
|
||||
defer span.End()
|
||||
var dst []byte
|
||||
err := s.db.View(func(tx *bolt.Tx) error {
|
||||
bkt := tx.Bucket(voluntaryExitsBucket)
|
||||
dst = bkt.Get(exitRoot[:])
|
||||
return nil
|
||||
})
|
||||
return dst, err
|
||||
}
|
||||
|
||||
// deleteVoluntaryExit clears a voluntary exit from the db by its signing root.
|
||||
func (s *Store) deleteVoluntaryExit(ctx context.Context, exitRoot [32]byte) error {
|
||||
ctx, span := trace.StartSpan(ctx, "BeaconDB.deleteVoluntaryExit")
|
||||
defer span.End()
|
||||
return s.db.Update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(voluntaryExitsBucket)
|
||||
return bucket.Delete(exitRoot[:])
|
||||
})
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package kv
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
func TestStore_VoluntaryExits_CRUD(t *testing.T) {
|
||||
db := setupDB(t)
|
||||
ctx := context.Background()
|
||||
exit := ðpb.VoluntaryExit{
|
||||
Epoch: 5,
|
||||
}
|
||||
exitRoot, err := exit.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
retrieved, err := db.VoluntaryExit(ctx, exitRoot)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, (*ethpb.VoluntaryExit)(nil), retrieved, "Expected nil voluntary exit")
|
||||
require.NoError(t, db.SaveVoluntaryExit(ctx, exit))
|
||||
assert.Equal(t, true, db.HasVoluntaryExit(ctx, exitRoot), "Expected voluntary exit to exist in the db")
|
||||
retrieved, err = db.VoluntaryExit(ctx, exitRoot)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, true, proto.Equal(exit, retrieved), "Wanted %v, received %v", exit, retrieved)
|
||||
require.NoError(t, db.deleteVoluntaryExit(ctx, exitRoot))
|
||||
assert.Equal(t, false, db.HasVoluntaryExit(ctx, exitRoot), "Expected voluntary exit to have been deleted from the db")
|
||||
}
|
||||
@@ -1,147 +0,0 @@
|
||||
package kv
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
bolt "go.etcd.io/bbolt"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
// ProposerSlashing retrieval by slashing root.
|
||||
func (s *Store) ProposerSlashing(ctx context.Context, slashingRoot [32]byte) (*ethpb.ProposerSlashing, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "BeaconDB.ProposerSlashing")
|
||||
defer span.End()
|
||||
enc, err := s.proposerSlashingBytes(ctx, slashingRoot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(enc) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
proposerSlashing := ðpb.ProposerSlashing{}
|
||||
if err := decode(ctx, enc, proposerSlashing); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return proposerSlashing, nil
|
||||
}
|
||||
|
||||
// HasProposerSlashing verifies if a slashing is stored in the db.
|
||||
func (s *Store) HasProposerSlashing(ctx context.Context, slashingRoot [32]byte) bool {
|
||||
ctx, span := trace.StartSpan(ctx, "BeaconDB.HasProposerSlashing")
|
||||
defer span.End()
|
||||
enc, err := s.proposerSlashingBytes(ctx, slashingRoot)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return len(enc) > 0
|
||||
}
|
||||
|
||||
// SaveProposerSlashing to the db by its hash tree root.
|
||||
func (s *Store) SaveProposerSlashing(ctx context.Context, slashing *ethpb.ProposerSlashing) error {
|
||||
ctx, span := trace.StartSpan(ctx, "BeaconDB.SaveProposerSlashing")
|
||||
defer span.End()
|
||||
slashingRoot, err := slashing.HashTreeRoot()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
enc, err := encode(ctx, slashing)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.db.Update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(proposerSlashingsBucket)
|
||||
return bucket.Put(slashingRoot[:], enc)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Store) proposerSlashingBytes(ctx context.Context, slashingRoot [32]byte) ([]byte, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "BeaconDB.proposerSlashingBytes")
|
||||
defer span.End()
|
||||
var dst []byte
|
||||
err := s.db.View(func(tx *bolt.Tx) error {
|
||||
bkt := tx.Bucket(proposerSlashingsBucket)
|
||||
dst = bkt.Get(slashingRoot[:])
|
||||
return nil
|
||||
})
|
||||
return dst, err
|
||||
}
|
||||
|
||||
// deleteProposerSlashing clears a proposer slashing from the db by its hash tree root.
|
||||
func (s *Store) deleteProposerSlashing(ctx context.Context, slashingRoot [32]byte) error {
|
||||
ctx, span := trace.StartSpan(ctx, "BeaconDB.deleteProposerSlashing")
|
||||
defer span.End()
|
||||
return s.db.Update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(proposerSlashingsBucket)
|
||||
return bucket.Delete(slashingRoot[:])
|
||||
})
|
||||
}
|
||||
|
||||
// AttesterSlashing retrieval by hash tree root.
|
||||
func (s *Store) AttesterSlashing(ctx context.Context, slashingRoot [32]byte) (*ethpb.AttesterSlashing, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "BeaconDB.AttesterSlashing")
|
||||
defer span.End()
|
||||
enc, err := s.attesterSlashingBytes(ctx, slashingRoot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(enc) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
attSlashing := ðpb.AttesterSlashing{}
|
||||
if err := decode(ctx, enc, attSlashing); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return attSlashing, nil
|
||||
}
|
||||
|
||||
// HasAttesterSlashing verifies if a slashing is stored in the db.
|
||||
func (s *Store) HasAttesterSlashing(ctx context.Context, slashingRoot [32]byte) bool {
|
||||
ctx, span := trace.StartSpan(ctx, "BeaconDB.HasAttesterSlashing")
|
||||
defer span.End()
|
||||
enc, err := s.attesterSlashingBytes(ctx, slashingRoot)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return len(enc) > 0
|
||||
}
|
||||
|
||||
// SaveAttesterSlashing to the db by its hash tree root.
|
||||
func (s *Store) SaveAttesterSlashing(ctx context.Context, slashing *ethpb.AttesterSlashing) error {
|
||||
ctx, span := trace.StartSpan(ctx, "BeaconDB.SaveAttesterSlashing")
|
||||
defer span.End()
|
||||
slashingRoot, err := slashing.HashTreeRoot()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
enc, err := encode(ctx, slashing)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.db.Update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(attesterSlashingsBucket)
|
||||
return bucket.Put(slashingRoot[:], enc)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Store) attesterSlashingBytes(ctx context.Context, slashingRoot [32]byte) ([]byte, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "BeaconDB.attesterSlashingBytes")
|
||||
defer span.End()
|
||||
var dst []byte
|
||||
err := s.db.View(func(tx *bolt.Tx) error {
|
||||
bkt := tx.Bucket(attesterSlashingsBucket)
|
||||
dst = bkt.Get(slashingRoot[:])
|
||||
return nil
|
||||
})
|
||||
return dst, err
|
||||
}
|
||||
|
||||
// deleteAttesterSlashing clears an attester slashing from the db by its hash tree root.
|
||||
func (s *Store) deleteAttesterSlashing(ctx context.Context, slashingRoot [32]byte) error {
|
||||
ctx, span := trace.StartSpan(ctx, "BeaconDB.deleteAttesterSlashing")
|
||||
defer span.End()
|
||||
return s.db.Update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(attesterSlashingsBucket)
|
||||
return bucket.Delete(slashingRoot[:])
|
||||
})
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
package kv
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/testing/util"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
func TestStore_ProposerSlashing_CRUD(t *testing.T) {
|
||||
db := setupDB(t)
|
||||
ctx := context.Background()
|
||||
prop := ðpb.ProposerSlashing{
|
||||
Header_1: util.HydrateSignedBeaconHeader(ðpb.SignedBeaconBlockHeader{
|
||||
Header: ðpb.BeaconBlockHeader{
|
||||
ProposerIndex: 5,
|
||||
},
|
||||
}),
|
||||
Header_2: util.HydrateSignedBeaconHeader(ðpb.SignedBeaconBlockHeader{
|
||||
Header: ðpb.BeaconBlockHeader{
|
||||
ProposerIndex: 5,
|
||||
},
|
||||
}),
|
||||
}
|
||||
slashingRoot, err := prop.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
retrieved, err := db.ProposerSlashing(ctx, slashingRoot)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, (*ethpb.ProposerSlashing)(nil), retrieved, "Expected nil proposer slashing")
|
||||
require.NoError(t, db.SaveProposerSlashing(ctx, prop))
|
||||
assert.Equal(t, true, db.HasProposerSlashing(ctx, slashingRoot), "Expected proposer slashing to exist in the db")
|
||||
retrieved, err = db.ProposerSlashing(ctx, slashingRoot)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, true, proto.Equal(prop, retrieved), "Wanted %v, received %v", prop, retrieved)
|
||||
require.NoError(t, db.deleteProposerSlashing(ctx, slashingRoot))
|
||||
assert.Equal(t, false, db.HasProposerSlashing(ctx, slashingRoot), "Expected proposer slashing to have been deleted from the db")
|
||||
}
|
||||
|
||||
func TestStore_AttesterSlashing_CRUD(t *testing.T) {
|
||||
db := setupDB(t)
|
||||
ctx := context.Background()
|
||||
att := ðpb.AttesterSlashing{
|
||||
Attestation_1: util.HydrateIndexedAttestation(ðpb.IndexedAttestation{
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 5,
|
||||
}}),
|
||||
Attestation_2: util.HydrateIndexedAttestation(ðpb.IndexedAttestation{
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 7,
|
||||
}})}
|
||||
slashingRoot, err := att.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
retrieved, err := db.AttesterSlashing(ctx, slashingRoot)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, (*ethpb.AttesterSlashing)(nil), retrieved, "Expected nil attester slashing")
|
||||
require.NoError(t, db.SaveAttesterSlashing(ctx, att))
|
||||
assert.Equal(t, true, db.HasAttesterSlashing(ctx, slashingRoot), "Expected attester slashing to exist in the db")
|
||||
retrieved, err = db.AttesterSlashing(ctx, slashingRoot)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, true, proto.Equal(att, retrieved), "Wanted %v, received %v", att, retrieved)
|
||||
require.NoError(t, db.deleteAttesterSlashing(ctx, slashingRoot))
|
||||
assert.Equal(t, false, db.HasAttesterSlashing(ctx, slashingRoot), "Expected attester slashing to have been deleted from the db")
|
||||
}
|
||||
@@ -568,7 +568,7 @@ func (s *Store) slotByBlockRoot(ctx context.Context, tx *bolt.Tx, blockRoot []by
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if err := helpers.VerifyNilBeaconBlock(wrapper.WrappedPhase0SignedBeaconBlock(b)); err != nil {
|
||||
if err := helpers.BeaconBlockIsNil(wrapper.WrappedPhase0SignedBeaconBlock(b)); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return b.Block.Slot, nil
|
||||
|
||||
@@ -6,7 +6,7 @@ go_library(
|
||||
"log.go",
|
||||
"service.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/interop-cold-start",
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/deterministic-genesis",
|
||||
visibility = ["//beacon-chain:__subpackages__"],
|
||||
deps = [
|
||||
"//beacon-chain/cache/depositcache:go_default_library",
|
||||
@@ -4,4 +4,4 @@ import (
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var log = logrus.WithField("prefix", "interop-cold-start")
|
||||
var log = logrus.WithField("prefix", "deterministic-genesis")
|
||||
@@ -1,4 +1,4 @@
|
||||
// Package interopcoldstart allows for spinning up a deterministic
|
||||
// Package interopcoldstart allows for spinning up a deterministic-genesis
|
||||
// local chain without the need for eth1 deposits useful for
|
||||
// local client development and interoperability testing.
|
||||
package interopcoldstart
|
||||
@@ -11,26 +11,26 @@ import (
|
||||
|
||||
// MuxConfig contains configuration that should be used when registering the beacon node in the gateway.
|
||||
type MuxConfig struct {
|
||||
Handler gateway.MuxHandler
|
||||
EthPbMux *gateway.PbMux
|
||||
V1Alpha1PbMux *gateway.PbMux
|
||||
Handler gateway.MuxHandler
|
||||
EthPbMux *gateway.PbMux
|
||||
V1AlphaPbMux *gateway.PbMux
|
||||
}
|
||||
|
||||
// DefaultConfig returns a fully configured MuxConfig with standard gateway behavior.
|
||||
func DefaultConfig(enableDebugRPCEndpoints bool, httpModules string) MuxConfig {
|
||||
var v1Alpha1PbHandler, ethPbHandler *gateway.PbMux
|
||||
var v1AlphaPbHandler, ethPbHandler *gateway.PbMux
|
||||
if flags.EnableHTTPPrysmAPI(httpModules) {
|
||||
v1Alpha1Registrations := []gateway.PbHandlerRegistration{
|
||||
v1AlphaRegistrations := []gateway.PbHandlerRegistration{
|
||||
ethpbalpha.RegisterNodeHandler,
|
||||
ethpbalpha.RegisterBeaconChainHandler,
|
||||
ethpbalpha.RegisterBeaconNodeValidatorHandler,
|
||||
ethpbalpha.RegisterHealthHandler,
|
||||
}
|
||||
if enableDebugRPCEndpoints {
|
||||
v1Alpha1Registrations = append(v1Alpha1Registrations, ethpbalpha.RegisterDebugHandler)
|
||||
v1AlphaRegistrations = append(v1AlphaRegistrations, ethpbalpha.RegisterDebugHandler)
|
||||
|
||||
}
|
||||
v1Alpha1Mux := gwruntime.NewServeMux(
|
||||
v1AlphaMux := gwruntime.NewServeMux(
|
||||
gwruntime.WithMarshalerOption(gwruntime.MIMEWildcard, &gwruntime.HTTPBodyMarshaler{
|
||||
Marshaler: &gwruntime.JSONPb{
|
||||
MarshalOptions: protojson.MarshalOptions{
|
||||
@@ -45,10 +45,10 @@ func DefaultConfig(enableDebugRPCEndpoints bool, httpModules string) MuxConfig {
|
||||
"text/event-stream", &gwruntime.EventSourceJSONPb{},
|
||||
),
|
||||
)
|
||||
v1Alpha1PbHandler = &gateway.PbMux{
|
||||
Registrations: v1Alpha1Registrations,
|
||||
Patterns: []string{"/eth/v1alpha1/"},
|
||||
Mux: v1Alpha1Mux,
|
||||
v1AlphaPbHandler = &gateway.PbMux{
|
||||
Registrations: v1AlphaRegistrations,
|
||||
Patterns: []string{"/eth/v1alpha1/", "/eth/v1alpha2/"},
|
||||
Mux: v1AlphaMux,
|
||||
}
|
||||
}
|
||||
if flags.EnableHTTPEthAPI(httpModules) {
|
||||
@@ -83,7 +83,7 @@ func DefaultConfig(enableDebugRPCEndpoints bool, httpModules string) MuxConfig {
|
||||
}
|
||||
|
||||
return MuxConfig{
|
||||
EthPbMux: ethPbHandler,
|
||||
V1Alpha1PbMux: v1Alpha1PbHandler,
|
||||
EthPbMux: ethPbHandler,
|
||||
V1AlphaPbMux: v1AlphaPbHandler,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,10 +16,11 @@ func TestDefaultConfig(t *testing.T) {
|
||||
assert.Equal(t, "/internal/eth/v1/", cfg.EthPbMux.Patterns[0])
|
||||
assert.Equal(t, "/internal/eth/v2/", cfg.EthPbMux.Patterns[1])
|
||||
assert.Equal(t, 4, len(cfg.EthPbMux.Registrations))
|
||||
assert.NotNil(t, cfg.V1Alpha1PbMux.Mux)
|
||||
require.Equal(t, 1, len(cfg.V1Alpha1PbMux.Patterns))
|
||||
assert.Equal(t, "/eth/v1alpha1/", cfg.V1Alpha1PbMux.Patterns[0])
|
||||
assert.Equal(t, 4, len(cfg.V1Alpha1PbMux.Registrations))
|
||||
assert.NotNil(t, cfg.V1AlphaPbMux.Mux)
|
||||
require.Equal(t, 2, len(cfg.V1AlphaPbMux.Patterns))
|
||||
assert.Equal(t, "/eth/v1alpha1/", cfg.V1AlphaPbMux.Patterns[0])
|
||||
assert.Equal(t, "/eth/v1alpha2/", cfg.V1AlphaPbMux.Patterns[1])
|
||||
assert.Equal(t, 4, len(cfg.V1AlphaPbMux.Registrations))
|
||||
})
|
||||
|
||||
t.Run("With debug endpoints", func(t *testing.T) {
|
||||
@@ -29,10 +30,11 @@ func TestDefaultConfig(t *testing.T) {
|
||||
assert.Equal(t, "/internal/eth/v1/", cfg.EthPbMux.Patterns[0])
|
||||
assert.Equal(t, "/internal/eth/v2/", cfg.EthPbMux.Patterns[1])
|
||||
assert.Equal(t, 5, len(cfg.EthPbMux.Registrations))
|
||||
assert.NotNil(t, cfg.V1Alpha1PbMux.Mux)
|
||||
require.Equal(t, 1, len(cfg.V1Alpha1PbMux.Patterns))
|
||||
assert.Equal(t, "/eth/v1alpha1/", cfg.V1Alpha1PbMux.Patterns[0])
|
||||
assert.Equal(t, 5, len(cfg.V1Alpha1PbMux.Registrations))
|
||||
assert.NotNil(t, cfg.V1AlphaPbMux.Mux)
|
||||
require.Equal(t, 2, len(cfg.V1AlphaPbMux.Patterns))
|
||||
assert.Equal(t, "/eth/v1alpha1/", cfg.V1AlphaPbMux.Patterns[0])
|
||||
assert.Equal(t, "/eth/v1alpha2/", cfg.V1AlphaPbMux.Patterns[1])
|
||||
assert.Equal(t, 5, len(cfg.V1AlphaPbMux.Registrations))
|
||||
})
|
||||
t.Run("Without Prysm API", func(t *testing.T) {
|
||||
cfg := DefaultConfig(true, "eth")
|
||||
@@ -40,14 +42,15 @@ func TestDefaultConfig(t *testing.T) {
|
||||
require.Equal(t, 2, len(cfg.EthPbMux.Patterns))
|
||||
assert.Equal(t, "/internal/eth/v1/", cfg.EthPbMux.Patterns[0])
|
||||
assert.Equal(t, 5, len(cfg.EthPbMux.Registrations))
|
||||
assert.Equal(t, (*gateway.PbMux)(nil), cfg.V1Alpha1PbMux)
|
||||
assert.Equal(t, (*gateway.PbMux)(nil), cfg.V1AlphaPbMux)
|
||||
})
|
||||
t.Run("Without Eth API", func(t *testing.T) {
|
||||
cfg := DefaultConfig(true, "prysm")
|
||||
assert.Equal(t, (*gateway.PbMux)(nil), cfg.EthPbMux)
|
||||
assert.NotNil(t, cfg.V1Alpha1PbMux.Mux)
|
||||
require.Equal(t, 1, len(cfg.V1Alpha1PbMux.Patterns))
|
||||
assert.Equal(t, "/eth/v1alpha1/", cfg.V1Alpha1PbMux.Patterns[0])
|
||||
assert.Equal(t, 5, len(cfg.V1Alpha1PbMux.Registrations))
|
||||
assert.NotNil(t, cfg.V1AlphaPbMux.Mux)
|
||||
require.Equal(t, 2, len(cfg.V1AlphaPbMux.Patterns))
|
||||
assert.Equal(t, "/eth/v1alpha1/", cfg.V1AlphaPbMux.Patterns[0])
|
||||
assert.Equal(t, "/eth/v1alpha2/", cfg.V1AlphaPbMux.Patterns[1])
|
||||
assert.Equal(t, 5, len(cfg.V1AlphaPbMux.Registrations))
|
||||
})
|
||||
}
|
||||
|
||||
37
beacon-chain/monitor/BUILD.bazel
Normal file
37
beacon-chain/monitor/BUILD.bazel
Normal file
@@ -0,0 +1,37 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"doc.go",
|
||||
"process_block.go",
|
||||
"service.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/monitor",
|
||||
visibility = ["//beacon-chain:__subpackages__"],
|
||||
deps = [
|
||||
"//beacon-chain/core/blocks:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//proto/prysm/v1alpha1/block:go_default_library",
|
||||
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"process_block_test.go",
|
||||
"service_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//config/params:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//proto/prysm/v1alpha1/wrapper:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"//testing/util:go_default_library",
|
||||
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
|
||||
],
|
||||
)
|
||||
7
beacon-chain/monitor/doc.go
Normal file
7
beacon-chain/monitor/doc.go
Normal file
@@ -0,0 +1,7 @@
|
||||
/*
|
||||
Package monitor defines a runtime service which receives
|
||||
notifications triggered by events related to performance of tracked
|
||||
validating keys. It then logs and emits metrics for a user to keep finely
|
||||
detailed performance measures.
|
||||
*/
|
||||
package monitor
|
||||
47
beacon-chain/monitor/process_block.go
Normal file
47
beacon-chain/monitor/process_block.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package monitor
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// processSlashings logs the event of one of our tracked validators was slashed
|
||||
func (s *Service) processSlashings(blk block.BeaconBlock) {
|
||||
for _, slashing := range blk.Body().ProposerSlashings() {
|
||||
idx := slashing.Header_1.Header.ProposerIndex
|
||||
if s.TrackedIndex(idx) {
|
||||
log.WithFields(logrus.Fields{
|
||||
"ProposerIndex": idx,
|
||||
"Slot:": blk.Slot(),
|
||||
"SlashingSlot": slashing.Header_1.Header.Slot,
|
||||
"Root1": fmt.Sprintf("%#x", bytesutil.Trunc(slashing.Header_1.Header.BodyRoot)),
|
||||
"Root2": fmt.Sprintf("%#x", bytesutil.Trunc(slashing.Header_2.Header.BodyRoot)),
|
||||
}).Info("Proposer slashing was included")
|
||||
}
|
||||
}
|
||||
|
||||
for _, slashing := range blk.Body().AttesterSlashings() {
|
||||
for _, idx := range blocks.SlashableAttesterIndices(slashing) {
|
||||
if s.TrackedIndex(types.ValidatorIndex(idx)) {
|
||||
log.WithFields(logrus.Fields{
|
||||
"AttesterIndex": idx,
|
||||
"Slot:": blk.Slot(),
|
||||
"Slot1": slashing.Attestation_1.Data.Slot,
|
||||
"Root1": fmt.Sprintf("%#x", bytesutil.Trunc(slashing.Attestation_1.Data.BeaconBlockRoot)),
|
||||
"SourceEpoch1": slashing.Attestation_1.Data.Source.Epoch,
|
||||
"TargetEpoch1": slashing.Attestation_1.Data.Target.Epoch,
|
||||
"Slot2": slashing.Attestation_2.Data.Slot,
|
||||
"Root2": fmt.Sprintf("%#x", bytesutil.Trunc(slashing.Attestation_2.Data.BeaconBlockRoot)),
|
||||
"SourceEpoch2": slashing.Attestation_2.Data.Source.Epoch,
|
||||
"TargetEpoch2": slashing.Attestation_2.Data.Target.Epoch,
|
||||
}).Info("Attester slashing was included")
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
131
beacon-chain/monitor/process_block_test.go
Normal file
131
beacon-chain/monitor/process_block_test.go
Normal file
@@ -0,0 +1,131 @@
|
||||
package monitor
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/testing/util"
|
||||
logTest "github.com/sirupsen/logrus/hooks/test"
|
||||
)
|
||||
|
||||
func TestProcessSlashings(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
block *ethpb.BeaconBlock
|
||||
wantedErr string
|
||||
}{
|
||||
{
|
||||
name: "Proposer slashing a tracked index",
|
||||
block: ðpb.BeaconBlock{
|
||||
Body: ðpb.BeaconBlockBody{
|
||||
ProposerSlashings: []*ethpb.ProposerSlashing{
|
||||
{
|
||||
Header_1: ðpb.SignedBeaconBlockHeader{
|
||||
Header: ðpb.BeaconBlockHeader{
|
||||
ProposerIndex: 2,
|
||||
Slot: params.BeaconConfig().SlotsPerEpoch + 1,
|
||||
},
|
||||
},
|
||||
Header_2: ðpb.SignedBeaconBlockHeader{
|
||||
Header: ðpb.BeaconBlockHeader{
|
||||
ProposerIndex: 2,
|
||||
Slot: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantedErr: "\"Proposer slashing was included\" ProposerIndex=2",
|
||||
},
|
||||
{
|
||||
name: "Proposer slashing an untracked index",
|
||||
block: ðpb.BeaconBlock{
|
||||
Body: ðpb.BeaconBlockBody{
|
||||
ProposerSlashings: []*ethpb.ProposerSlashing{
|
||||
{
|
||||
Header_1: ðpb.SignedBeaconBlockHeader{
|
||||
Header: ðpb.BeaconBlockHeader{
|
||||
ProposerIndex: 3,
|
||||
Slot: params.BeaconConfig().SlotsPerEpoch + 4,
|
||||
},
|
||||
},
|
||||
Header_2: ðpb.SignedBeaconBlockHeader{
|
||||
Header: ðpb.BeaconBlockHeader{
|
||||
ProposerIndex: 3,
|
||||
Slot: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantedErr: "",
|
||||
},
|
||||
{
|
||||
name: "Attester slashing a tracked index",
|
||||
block: ðpb.BeaconBlock{
|
||||
Body: ðpb.BeaconBlockBody{
|
||||
AttesterSlashings: []*ethpb.AttesterSlashing{
|
||||
{
|
||||
Attestation_1: util.HydrateIndexedAttestation(ðpb.IndexedAttestation{
|
||||
Data: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 1},
|
||||
},
|
||||
AttestingIndices: []uint64{1, 3, 4},
|
||||
}),
|
||||
Attestation_2: util.HydrateIndexedAttestation(ðpb.IndexedAttestation{
|
||||
AttestingIndices: []uint64{1, 5, 6},
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantedErr: "\"Attester slashing was included\" AttesterIndex=1",
|
||||
},
|
||||
{
|
||||
name: "Attester slashing untracked index",
|
||||
block: ðpb.BeaconBlock{
|
||||
Body: ðpb.BeaconBlockBody{
|
||||
AttesterSlashings: []*ethpb.AttesterSlashing{
|
||||
{
|
||||
Attestation_1: util.HydrateIndexedAttestation(ðpb.IndexedAttestation{
|
||||
Data: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 1},
|
||||
},
|
||||
AttestingIndices: []uint64{1, 3, 4},
|
||||
}),
|
||||
Attestation_2: util.HydrateIndexedAttestation(ðpb.IndexedAttestation{
|
||||
AttestingIndices: []uint64{3, 5, 6},
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantedErr: "",
|
||||
}}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
s := &Service{
|
||||
config: &ValidatorMonitorConfig{
|
||||
TrackedValidators: map[types.ValidatorIndex]interface{}{
|
||||
1: nil,
|
||||
2: nil,
|
||||
},
|
||||
},
|
||||
}
|
||||
s.processSlashings(wrapper.WrappedPhase0BeaconBlock(tt.block))
|
||||
if tt.wantedErr != "" {
|
||||
require.LogsContain(t, hook, tt.wantedErr)
|
||||
} else {
|
||||
require.LogsDoNotContain(t, hook, "slashing")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
30
beacon-chain/monitor/service.go
Normal file
30
beacon-chain/monitor/service.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package monitor
|
||||
|
||||
import (
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var (
|
||||
log = logrus.WithField("prefix", "monitor")
|
||||
)
|
||||
|
||||
// ValidatorMonitorConfig contains the list of validator indices that the
|
||||
// monitor service tracks, as well as the event feed notifier that the
|
||||
// monitor needs to subscribe.
|
||||
type ValidatorMonitorConfig struct {
|
||||
TrackedValidators map[types.ValidatorIndex]interface{}
|
||||
}
|
||||
|
||||
// Service is the main structure that tracks validators and reports logs and
|
||||
// metrics of their performances throughout their lifetime.
|
||||
type Service struct {
|
||||
config *ValidatorMonitorConfig
|
||||
}
|
||||
|
||||
// TrackedIndex returns if the given validator index corresponds to one of the
|
||||
// validators we follow
|
||||
func (s *Service) TrackedIndex(idx types.ValidatorIndex) bool {
|
||||
_, ok := s.config.TrackedValidators[idx]
|
||||
return ok
|
||||
}
|
||||
21
beacon-chain/monitor/service_test.go
Normal file
21
beacon-chain/monitor/service_test.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package monitor
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
)
|
||||
|
||||
func TestTrackedIndex(t *testing.T) {
|
||||
s := &Service{
|
||||
config: &ValidatorMonitorConfig{
|
||||
TrackedValidators: map[types.ValidatorIndex]interface{}{
|
||||
1: nil,
|
||||
2: nil,
|
||||
},
|
||||
},
|
||||
}
|
||||
require.Equal(t, s.TrackedIndex(types.ValidatorIndex(1)), true)
|
||||
require.Equal(t, s.TrackedIndex(types.ValidatorIndex(3)), false)
|
||||
}
|
||||
@@ -6,6 +6,7 @@ go_library(
|
||||
"config.go",
|
||||
"log.go",
|
||||
"node.go",
|
||||
"options.go",
|
||||
"prometheus.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/node",
|
||||
@@ -18,15 +19,13 @@ go_library(
|
||||
"//async/event:go_default_library",
|
||||
"//beacon-chain/blockchain:go_default_library",
|
||||
"//beacon-chain/cache/depositcache:go_default_library",
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/db:go_default_library",
|
||||
"//beacon-chain/db/kv:go_default_library",
|
||||
"//beacon-chain/db/slasherkv:go_default_library",
|
||||
"//beacon-chain/deterministic-genesis:go_default_library",
|
||||
"//beacon-chain/forkchoice:go_default_library",
|
||||
"//beacon-chain/forkchoice/protoarray:go_default_library",
|
||||
"//beacon-chain/gateway:go_default_library",
|
||||
"//beacon-chain/interop-cold-start:go_default_library",
|
||||
"//beacon-chain/node/registration:go_default_library",
|
||||
"//beacon-chain/operations/attestations:go_default_library",
|
||||
"//beacon-chain/operations/slashings:go_default_library",
|
||||
"//beacon-chain/operations/synccommittee:go_default_library",
|
||||
@@ -36,14 +35,16 @@ go_library(
|
||||
"//beacon-chain/rpc:go_default_library",
|
||||
"//beacon-chain/rpc/apimiddleware:go_default_library",
|
||||
"//beacon-chain/slasher:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//beacon-chain/state/stategen:go_default_library",
|
||||
"//beacon-chain/sync:go_default_library",
|
||||
"//beacon-chain/sync/initial-sync:go_default_library",
|
||||
"//cmd:go_default_library",
|
||||
"//cmd/beacon-chain/flags:go_default_library",
|
||||
"//cmd/beacon-chain/p2p:go_default_library",
|
||||
"//config/features:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//container/slice:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//monitoring/backup:go_default_library",
|
||||
"//monitoring/prometheus:go_default_library",
|
||||
"//monitoring/tracing:go_default_library",
|
||||
@@ -72,9 +73,11 @@ go_test(
|
||||
"//beacon-chain/core/feed/state:go_default_library",
|
||||
"//cmd:go_default_library",
|
||||
"//cmd/beacon-chain/flags:go_default_library",
|
||||
"//cmd/beacon-chain/p2p:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common:go_default_library",
|
||||
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
|
||||
"@com_github_urfave_cli_v2//:go_default_library",
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
"github.com/prysmaticlabs/prysm/cmd"
|
||||
"github.com/prysmaticlabs/prysm/cmd/beacon-chain/flags"
|
||||
p2pcmd "github.com/prysmaticlabs/prysm/cmd/beacon-chain/p2p"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
tracing2 "github.com/prysmaticlabs/prysm/monitoring/tracing"
|
||||
"github.com/urfave/cli/v2"
|
||||
@@ -71,9 +73,9 @@ func configureEth1Config(cliCtx *cli.Context) {
|
||||
}
|
||||
|
||||
func configureNetwork(cliCtx *cli.Context) {
|
||||
if cliCtx.IsSet(cmd.BootstrapNode.Name) {
|
||||
if cliCtx.IsSet(p2pcmd.BootstrapNode.Name) {
|
||||
c := params.BeaconNetworkConfig()
|
||||
c.BootstrapNodes = cliCtx.StringSlice(cmd.BootstrapNode.Name)
|
||||
c.BootstrapNodes = cliCtx.StringSlice(p2pcmd.BootstrapNode.Name)
|
||||
params.OverrideBeaconNetworkConfig(c)
|
||||
}
|
||||
if cliCtx.IsSet(flags.ContractDeploymentBlock.Name) {
|
||||
@@ -95,3 +97,26 @@ func configureInteropConfig(cliCtx *cli.Context) {
|
||||
params.OverrideBeaconConfig(bCfg)
|
||||
}
|
||||
}
|
||||
|
||||
func configureExecutionSetting(cliCtx *cli.Context) {
|
||||
if cliCtx.IsSet(flags.TerminalTotalDifficultyOverride.Name) {
|
||||
c := params.BeaconConfig()
|
||||
c.TerminalTotalDifficulty = cliCtx.Uint64(flags.TerminalTotalDifficultyOverride.Name)
|
||||
params.OverrideBeaconConfig(c)
|
||||
}
|
||||
if cliCtx.IsSet(flags.TerminalBlockHashOverride.Name) {
|
||||
c := params.BeaconConfig()
|
||||
c.TerminalBlockHash = common.HexToHash(cliCtx.String(flags.TerminalBlockHashOverride.Name))
|
||||
params.OverrideBeaconConfig(c)
|
||||
}
|
||||
if cliCtx.IsSet(flags.TerminalBlockHashActivationEpochOverride.Name) {
|
||||
c := params.BeaconConfig()
|
||||
c.TerminalBlockHashActivationEpoch = types.Epoch(cliCtx.Uint64(flags.TerminalBlockHashActivationEpochOverride.Name))
|
||||
params.OverrideBeaconConfig(c)
|
||||
}
|
||||
if cliCtx.IsSet(flags.Coinbase.Name) {
|
||||
c := params.BeaconConfig()
|
||||
c.Coinbase = common.HexToAddress(cliCtx.String(flags.Coinbase.Name))
|
||||
params.OverrideBeaconConfig(c)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,9 +6,10 @@ import (
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
"github.com/prysmaticlabs/prysm/cmd"
|
||||
"github.com/prysmaticlabs/prysm/cmd/beacon-chain/flags"
|
||||
p2pcmd "github.com/prysmaticlabs/prysm/cmd/beacon-chain/p2p"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
@@ -70,16 +71,39 @@ func TestConfigureProofOfWork(t *testing.T) {
|
||||
assert.Equal(t, "deposit-contract", params.BeaconConfig().DepositContractAddress)
|
||||
}
|
||||
|
||||
func TestConfigureExecutionSetting(t *testing.T) {
|
||||
params.SetupTestConfigCleanup(t)
|
||||
|
||||
app := cli.App{}
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.Uint64(flags.TerminalTotalDifficultyOverride.Name, 0, "")
|
||||
set.String(flags.TerminalBlockHashOverride.Name, "", "")
|
||||
set.Uint64(flags.TerminalBlockHashActivationEpochOverride.Name, 0, "")
|
||||
set.String(flags.Coinbase.Name, "", "")
|
||||
require.NoError(t, set.Set(flags.TerminalTotalDifficultyOverride.Name, strconv.Itoa(100)))
|
||||
require.NoError(t, set.Set(flags.TerminalBlockHashOverride.Name, "0xA"))
|
||||
require.NoError(t, set.Set(flags.TerminalBlockHashActivationEpochOverride.Name, strconv.Itoa(200)))
|
||||
require.NoError(t, set.Set(flags.Coinbase.Name, "0xB"))
|
||||
cliCtx := cli.NewContext(&app, set, nil)
|
||||
|
||||
configureExecutionSetting(cliCtx)
|
||||
|
||||
assert.Equal(t, uint64(100), params.BeaconConfig().TerminalTotalDifficulty)
|
||||
assert.Equal(t, common.HexToHash("0xA"), params.BeaconConfig().TerminalBlockHash)
|
||||
assert.Equal(t, types.Epoch(200), params.BeaconConfig().TerminalBlockHashActivationEpoch)
|
||||
assert.Equal(t, common.HexToAddress("0xB"), params.BeaconConfig().Coinbase)
|
||||
}
|
||||
|
||||
func TestConfigureNetwork(t *testing.T) {
|
||||
params.SetupTestConfigCleanup(t)
|
||||
|
||||
app := cli.App{}
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
bootstrapNodes := cli.StringSlice{}
|
||||
set.Var(&bootstrapNodes, cmd.BootstrapNode.Name, "")
|
||||
set.Var(&bootstrapNodes, p2pcmd.BootstrapNode.Name, "")
|
||||
set.Int(flags.ContractDeploymentBlock.Name, 0, "")
|
||||
require.NoError(t, set.Set(cmd.BootstrapNode.Name, "node1"))
|
||||
require.NoError(t, set.Set(cmd.BootstrapNode.Name, "node2"))
|
||||
require.NoError(t, set.Set(p2pcmd.BootstrapNode.Name, "node1"))
|
||||
require.NoError(t, set.Set(p2pcmd.BootstrapNode.Name, "node2"))
|
||||
require.NoError(t, set.Set(flags.ContractDeploymentBlock.Name, strconv.Itoa(100)))
|
||||
cliCtx := cli.NewContext(&app, set, nil)
|
||||
|
||||
|
||||
@@ -21,15 +21,13 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/async/event"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db/kv"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db/slasherkv"
|
||||
interopcoldstart "github.com/prysmaticlabs/prysm/beacon-chain/deterministic-genesis"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/gateway"
|
||||
interopcoldstart "github.com/prysmaticlabs/prysm/beacon-chain/interop-cold-start"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/node/registration"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/attestations"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/slashings"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/synccommittee"
|
||||
@@ -39,6 +37,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/rpc"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/rpc/apimiddleware"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/slasher"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
||||
regularsync "github.com/prysmaticlabs/prysm/beacon-chain/sync"
|
||||
initialsync "github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync"
|
||||
@@ -46,7 +45,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/cmd/beacon-chain/flags"
|
||||
"github.com/prysmaticlabs/prysm/config/features"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/container/slice"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/monitoring/backup"
|
||||
"github.com/prysmaticlabs/prysm/monitoring/prometheus"
|
||||
"github.com/prysmaticlabs/prysm/runtime"
|
||||
@@ -62,6 +61,15 @@ const testSkipPowFlag = "test-skip-pow"
|
||||
// 128MB max message size when enabling debug endpoints.
|
||||
const debugGrpcMaxMsgSize = 1 << 27
|
||||
|
||||
// Used as a struct to keep cli flag options for configuring services
|
||||
// for the beacon node. We keep this as a separate struct to not pollute the actual BeaconNode
|
||||
// struct, as it is merely used to pass down configuration options into the appropriate services.
|
||||
type serviceFlagOpts struct {
|
||||
blockchainFlagOpts []blockchain.Option
|
||||
powchainFlagOpts []powchain.Option
|
||||
p2pFlagOpts []p2p.Option
|
||||
}
|
||||
|
||||
// BeaconNode defines a struct that handles the services running a random beacon chain
|
||||
// full PoS node. It handles the lifecycle of the entire system and registers
|
||||
// services to a service registry.
|
||||
@@ -87,11 +95,13 @@ type BeaconNode struct {
|
||||
collector *bcnodeCollector
|
||||
slasherBlockHeadersFeed *event.Feed
|
||||
slasherAttestationsFeed *event.Feed
|
||||
finalizedStateAtStartUp state.BeaconState
|
||||
serviceFlagOpts *serviceFlagOpts
|
||||
}
|
||||
|
||||
// New creates a new node instance, sets up configuration options, and registers
|
||||
// every required service to the node.
|
||||
func New(cliCtx *cli.Context) (*BeaconNode, error) {
|
||||
func New(cliCtx *cli.Context, opts ...Option) (*BeaconNode, error) {
|
||||
if err := configureTracing(cliCtx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -127,9 +137,16 @@ func New(cliCtx *cli.Context) (*BeaconNode, error) {
|
||||
syncCommitteePool: synccommittee.NewPool(),
|
||||
slasherBlockHeadersFeed: new(event.Feed),
|
||||
slasherAttestationsFeed: new(event.Feed),
|
||||
serviceFlagOpts: &serviceFlagOpts{},
|
||||
}
|
||||
|
||||
depositAddress, err := registration.DepositContractAddress()
|
||||
for _, opt := range opts {
|
||||
if err := opt(beacon); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
depositAddress, err := powchain.DepositContractAddress()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -141,9 +158,11 @@ func New(cliCtx *cli.Context) (*BeaconNode, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
beacon.startStateGen()
|
||||
if err := beacon.startStateGen(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := beacon.registerP2P(cliCtx); err != nil {
|
||||
if err := beacon.registerP2P(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -155,7 +174,7 @@ func New(cliCtx *cli.Context) (*BeaconNode, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := beacon.registerInteropServices(); err != nil {
|
||||
if err := beacon.registerDeterminsticGenesisService(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -414,37 +433,43 @@ func (b *BeaconNode) startSlasherDB(cliCtx *cli.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *BeaconNode) startStateGen() {
|
||||
func (b *BeaconNode) startStateGen() error {
|
||||
b.stateGen = stategen.New(b.db)
|
||||
}
|
||||
|
||||
func (b *BeaconNode) registerP2P(cliCtx *cli.Context) error {
|
||||
bootstrapNodeAddrs, dataDir, err := registration.P2PPreregistration(cliCtx)
|
||||
cp, err := b.db.FinalizedCheckpoint(b.ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
svc, err := p2p.NewService(b.ctx, &p2p.Config{
|
||||
NoDiscovery: cliCtx.Bool(cmd.NoDiscovery.Name),
|
||||
StaticPeers: slice.SplitCommaSeparated(cliCtx.StringSlice(cmd.StaticPeers.Name)),
|
||||
BootstrapNodeAddr: bootstrapNodeAddrs,
|
||||
RelayNodeAddr: cliCtx.String(cmd.RelayNode.Name),
|
||||
DataDir: dataDir,
|
||||
LocalIP: cliCtx.String(cmd.P2PIP.Name),
|
||||
HostAddress: cliCtx.String(cmd.P2PHost.Name),
|
||||
HostDNS: cliCtx.String(cmd.P2PHostDNS.Name),
|
||||
PrivateKey: cliCtx.String(cmd.P2PPrivKey.Name),
|
||||
MetaDataDir: cliCtx.String(cmd.P2PMetadata.Name),
|
||||
TCPPort: cliCtx.Uint(cmd.P2PTCPPort.Name),
|
||||
UDPPort: cliCtx.Uint(cmd.P2PUDPPort.Name),
|
||||
MaxPeers: cliCtx.Uint(cmd.P2PMaxPeers.Name),
|
||||
AllowListCIDR: cliCtx.String(cmd.P2PAllowList.Name),
|
||||
DenyListCIDR: slice.SplitCommaSeparated(cliCtx.StringSlice(cmd.P2PDenyList.Name)),
|
||||
EnableUPnP: cliCtx.Bool(cmd.EnableUPnPFlag.Name),
|
||||
DisableDiscv5: cliCtx.Bool(flags.DisableDiscv5.Name),
|
||||
StateNotifier: b,
|
||||
DB: b.db,
|
||||
})
|
||||
r := bytesutil.ToBytes32(cp.Root)
|
||||
// Consider edge case where finalized root are zeros instead of genesis root hash.
|
||||
if r == params.BeaconConfig().ZeroHash {
|
||||
genesisBlock, err := b.db.GenesisBlock(b.ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if genesisBlock != nil && !genesisBlock.IsNil() {
|
||||
r, err = genesisBlock.Block().HashTreeRoot()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
b.finalizedStateAtStartUp, err = b.stateGen.StateByRoot(b.ctx, r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *BeaconNode) registerP2P() error {
|
||||
opts := append(
|
||||
b.serviceFlagOpts.p2pFlagOpts,
|
||||
p2p.WithDatabase(b.db),
|
||||
p2p.WithStateNotifier(b),
|
||||
)
|
||||
svc, err := p2p.NewService(b.ctx, opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -480,29 +505,24 @@ func (b *BeaconNode) registerBlockchainService() error {
|
||||
return err
|
||||
}
|
||||
|
||||
wsp := b.cliCtx.String(flags.WeakSubjectivityCheckpt.Name)
|
||||
wsCheckpt, err := helpers.ParseWeakSubjectivityInputString(wsp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
maxRoutines := b.cliCtx.Int(cmd.MaxGoroutines.Name)
|
||||
blockchainService, err := blockchain.NewService(b.ctx, &blockchain.Config{
|
||||
BeaconDB: b.db,
|
||||
DepositCache: b.depositCache,
|
||||
ChainStartFetcher: web3Service,
|
||||
AttPool: b.attestationPool,
|
||||
ExitPool: b.exitPool,
|
||||
SlashingPool: b.slashingsPool,
|
||||
P2p: b.fetchP2P(),
|
||||
MaxRoutines: maxRoutines,
|
||||
StateNotifier: b,
|
||||
ForkChoiceStore: b.forkChoiceStore,
|
||||
AttService: attService,
|
||||
StateGen: b.stateGen,
|
||||
SlasherAttestationsFeed: b.slasherAttestationsFeed,
|
||||
WeakSubjectivityCheckpt: wsCheckpt,
|
||||
})
|
||||
// skipcq: CRT-D0001
|
||||
opts := append(
|
||||
b.serviceFlagOpts.blockchainFlagOpts,
|
||||
blockchain.WithDatabase(b.db),
|
||||
blockchain.WithDepositCache(b.depositCache),
|
||||
blockchain.WithChainStartFetcher(web3Service),
|
||||
blockchain.WithAttestationPool(b.attestationPool),
|
||||
blockchain.WithExitPool(b.exitPool),
|
||||
blockchain.WithSlashingPool(b.slashingsPool),
|
||||
blockchain.WithP2PBroadcaster(b.fetchP2P()),
|
||||
blockchain.WithStateNotifier(b),
|
||||
blockchain.WithForkChoiceStore(b.forkChoiceStore),
|
||||
blockchain.WithAttestationService(attService),
|
||||
blockchain.WithStateGen(b.stateGen),
|
||||
blockchain.WithSlasherAttestationsFeed(b.slasherAttestationsFeed),
|
||||
blockchain.WithFinalizedStateAtStartUp(b.finalizedStateAtStartUp),
|
||||
)
|
||||
blockchainService, err := blockchain.NewService(b.ctx, opts...)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not register blockchain service")
|
||||
}
|
||||
@@ -513,29 +533,27 @@ func (b *BeaconNode) registerPOWChainService() error {
|
||||
if b.cliCtx.Bool(testSkipPowFlag) {
|
||||
return b.services.RegisterService(&powchain.Service{})
|
||||
}
|
||||
|
||||
depAddress, endpoints, err := registration.PowchainPreregistration(b.cliCtx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bs, err := powchain.NewPowchainCollector(b.ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cfg := &powchain.Web3ServiceConfig{
|
||||
HttpEndpoints: endpoints,
|
||||
DepositContract: common.HexToAddress(depAddress),
|
||||
BeaconDB: b.db,
|
||||
DepositCache: b.depositCache,
|
||||
StateNotifier: b,
|
||||
StateGen: b.stateGen,
|
||||
Eth1HeaderReqLimit: b.cliCtx.Uint64(flags.Eth1HeaderReqLimit.Name),
|
||||
BeaconNodeStatsUpdater: bs,
|
||||
depositContractAddr, err := powchain.DepositContractAddress()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
web3Service, err := powchain.NewService(b.ctx, cfg)
|
||||
// skipcq: CRT-D0001
|
||||
opts := append(
|
||||
b.serviceFlagOpts.powchainFlagOpts,
|
||||
powchain.WithDepositContractAddress(common.HexToAddress(depositContractAddr)),
|
||||
powchain.WithDatabase(b.db),
|
||||
powchain.WithDepositCache(b.depositCache),
|
||||
powchain.WithStateNotifier(b),
|
||||
powchain.WithStateGen(b.stateGen),
|
||||
powchain.WithBeaconNodeStatsUpdater(bs),
|
||||
powchain.WithFinalizedStateAtStartup(b.finalizedStateAtStartUp),
|
||||
)
|
||||
web3Service, err := powchain.NewService(b.ctx, opts...)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not register proof-of-work chain web3Service")
|
||||
}
|
||||
@@ -559,24 +577,24 @@ func (b *BeaconNode) registerSyncService() error {
|
||||
return err
|
||||
}
|
||||
|
||||
rs := regularsync.NewService(b.ctx, ®ularsync.Config{
|
||||
DB: b.db,
|
||||
P2P: b.fetchP2P(),
|
||||
Chain: chainService,
|
||||
InitialSync: initSync,
|
||||
StateNotifier: b,
|
||||
BlockNotifier: b,
|
||||
AttestationNotifier: b,
|
||||
OperationNotifier: b,
|
||||
AttPool: b.attestationPool,
|
||||
ExitPool: b.exitPool,
|
||||
SlashingPool: b.slashingsPool,
|
||||
SyncCommsPool: b.syncCommitteePool,
|
||||
StateGen: b.stateGen,
|
||||
SlasherAttestationsFeed: b.slasherAttestationsFeed,
|
||||
SlasherBlockHeadersFeed: b.slasherBlockHeadersFeed,
|
||||
})
|
||||
|
||||
rs := regularsync.NewService(
|
||||
b.ctx,
|
||||
regularsync.WithDatabase(b.db),
|
||||
regularsync.WithP2P(b.fetchP2P()),
|
||||
regularsync.WithChainService(chainService),
|
||||
regularsync.WithInitialSync(initSync),
|
||||
regularsync.WithStateNotifier(b),
|
||||
regularsync.WithBlockNotifier(b),
|
||||
regularsync.WithAttestationNotifier(b),
|
||||
regularsync.WithOperationNotifier(b),
|
||||
regularsync.WithAttestationPool(b.attestationPool),
|
||||
regularsync.WithExitPool(b.exitPool),
|
||||
regularsync.WithSlashingPool(b.slashingsPool),
|
||||
regularsync.WithSyncCommsPool(b.syncCommitteePool),
|
||||
regularsync.WithStateGen(b.stateGen),
|
||||
regularsync.WithSlasherAttestationsFeed(b.slasherAttestationsFeed),
|
||||
regularsync.WithSlasherBlockHeadersFeed(b.slasherBlockHeadersFeed),
|
||||
)
|
||||
return b.services.RegisterService(rs)
|
||||
}
|
||||
|
||||
@@ -778,8 +796,8 @@ func (b *BeaconNode) registerGRPCGateway() error {
|
||||
|
||||
gatewayConfig := gateway.DefaultConfig(enableDebugRPCEndpoints, httpModules)
|
||||
muxs := make([]*apigateway.PbMux, 0)
|
||||
if gatewayConfig.V1Alpha1PbMux != nil {
|
||||
muxs = append(muxs, gatewayConfig.V1Alpha1PbMux)
|
||||
if gatewayConfig.V1AlphaPbMux != nil {
|
||||
muxs = append(muxs, gatewayConfig.V1AlphaPbMux)
|
||||
}
|
||||
if gatewayConfig.EthPbMux != nil {
|
||||
muxs = append(muxs, gatewayConfig.EthPbMux)
|
||||
@@ -801,7 +819,7 @@ func (b *BeaconNode) registerGRPCGateway() error {
|
||||
return b.services.RegisterService(g)
|
||||
}
|
||||
|
||||
func (b *BeaconNode) registerInteropServices() error {
|
||||
func (b *BeaconNode) registerDeterminsticGenesisService() error {
|
||||
genesisTime := b.cliCtx.Uint64(flags.InteropGenesisTimeFlag.Name)
|
||||
genesisValidators := b.cliCtx.Uint64(flags.InteropNumValidatorsFlag.Name)
|
||||
genesisStatePath := b.cliCtx.String(flags.InteropGenesisStateFlag.Name)
|
||||
@@ -815,6 +833,14 @@ func (b *BeaconNode) registerInteropServices() error {
|
||||
GenesisPath: genesisStatePath,
|
||||
})
|
||||
|
||||
// Register genesis state as start-up state when interop mode.
|
||||
// The start-up state gets reused across services.
|
||||
st, err := b.db.GenesisState(b.ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b.finalizedStateAtStartUp = st
|
||||
|
||||
return b.services.RegisterService(svc)
|
||||
}
|
||||
return nil
|
||||
|
||||
34
beacon-chain/node/options.go
Normal file
34
beacon-chain/node/options.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
|
||||
)
|
||||
|
||||
// Option for beacon node configuration.
|
||||
type Option func(bn *BeaconNode) error
|
||||
|
||||
// WithBlockchainFlagOptions includes functional options for the blockchain service related to CLI flags.
|
||||
func WithBlockchainFlagOptions(opts []blockchain.Option) Option {
|
||||
return func(bn *BeaconNode) error {
|
||||
bn.serviceFlagOpts.blockchainFlagOpts = opts
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithPowchainFlagOptions includes functional options for the powchain service related to CLI flags.
|
||||
func WithPowchainFlagOptions(opts []powchain.Option) Option {
|
||||
return func(bn *BeaconNode) error {
|
||||
bn.serviceFlagOpts.powchainFlagOpts = opts
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithP2PFlagOptions includes functional options for the p2p service related to CLI flags.
|
||||
func WithP2PFlagOptions(opts []p2p.Option) Option {
|
||||
return func(bn *BeaconNode) error {
|
||||
bn.serviceFlagOpts.p2pFlagOpts = opts
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -5,15 +5,15 @@ go_library(
|
||||
srcs = [
|
||||
"log.go",
|
||||
"p2p.go",
|
||||
"powchain.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/node/registration",
|
||||
visibility = ["//beacon-chain/node:__subpackages__"],
|
||||
visibility = [
|
||||
"//beacon-chain/node:__subpackages__",
|
||||
"//cmd/beacon-chain:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
"//cmd:go_default_library",
|
||||
"//cmd/beacon-chain/flags:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@com_github_urfave_cli_v2//:go_default_library",
|
||||
"@in_gopkg_yaml_v2//:go_default_library",
|
||||
@@ -22,18 +22,13 @@ go_library(
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"p2p_test.go",
|
||||
"powchain_test.go",
|
||||
],
|
||||
srcs = ["p2p_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//cmd:go_default_library",
|
||||
"//cmd/beacon-chain/flags:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
|
||||
"@com_github_urfave_cli_v2//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
package registration
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/prysmaticlabs/prysm/cmd/beacon-chain/flags"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// PowchainPreregistration prepares data for powchain.Service's registration.
|
||||
func PowchainPreregistration(cliCtx *cli.Context) (depositContractAddress string, endpoints []string, err error) {
|
||||
depositContractAddress, err = DepositContractAddress()
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
if cliCtx.String(flags.HTTPWeb3ProviderFlag.Name) == "" && len(cliCtx.StringSlice(flags.FallbackWeb3ProviderFlag.Name)) == 0 {
|
||||
log.Error(
|
||||
"No ETH1 node specified to run with the beacon node. Please consider running your own Ethereum proof-of-work node for better uptime, security, and decentralization of Ethereum. Visit https://docs.prylabs.network/docs/prysm-usage/setup-eth1 for more information.",
|
||||
)
|
||||
log.Error(
|
||||
"You will need to specify --http-web3provider and/or --fallback-web3provider to attach an eth1 node to the prysm node. Without an eth1 node block proposals for your validator will be affected and the beacon node will not be able to initialize the genesis state.",
|
||||
)
|
||||
}
|
||||
|
||||
endpoints = []string{cliCtx.String(flags.HTTPWeb3ProviderFlag.Name)}
|
||||
endpoints = append(endpoints, cliCtx.StringSlice(flags.FallbackWeb3ProviderFlag.Name)...)
|
||||
return
|
||||
}
|
||||
|
||||
// DepositContractAddress returns the address of the deposit contract.
|
||||
func DepositContractAddress() (string, error) {
|
||||
address := params.BeaconConfig().DepositContractAddress
|
||||
if address == "" {
|
||||
return "", errors.New("valid deposit contract is required")
|
||||
}
|
||||
|
||||
if !common.IsHexAddress(address) {
|
||||
return "", errors.New("invalid deposit contract address given: " + address)
|
||||
}
|
||||
|
||||
return address, nil
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
package registration
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/cmd/beacon-chain/flags"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
logTest "github.com/sirupsen/logrus/hooks/test"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func TestPowchainPreregistration(t *testing.T) {
|
||||
app := cli.App{}
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.String(flags.HTTPWeb3ProviderFlag.Name, "primary", "")
|
||||
fallback := cli.StringSlice{}
|
||||
err := fallback.Set("fallback1")
|
||||
require.NoError(t, err)
|
||||
err = fallback.Set("fallback2")
|
||||
require.NoError(t, err)
|
||||
set.Var(&fallback, flags.FallbackWeb3ProviderFlag.Name, "")
|
||||
ctx := cli.NewContext(&app, set, nil)
|
||||
|
||||
address, endpoints, err := PowchainPreregistration(ctx)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, params.BeaconConfig().DepositContractAddress, address)
|
||||
assert.DeepEqual(t, []string{"primary", "fallback1", "fallback2"}, endpoints)
|
||||
}
|
||||
|
||||
func TestPowchainPreregistration_EmptyWeb3Provider(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
app := cli.App{}
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.String(flags.HTTPWeb3ProviderFlag.Name, "", "")
|
||||
fallback := cli.StringSlice{}
|
||||
set.Var(&fallback, flags.FallbackWeb3ProviderFlag.Name, "")
|
||||
ctx := cli.NewContext(&app, set, nil)
|
||||
|
||||
_, _, err := PowchainPreregistration(ctx)
|
||||
require.NoError(t, err)
|
||||
assert.LogsContain(t, hook, "No ETH1 node specified to run with the beacon node")
|
||||
}
|
||||
|
||||
func TestDepositContractAddress_Ok(t *testing.T) {
|
||||
address, err := DepositContractAddress()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, params.BeaconConfig().DepositContractAddress, address)
|
||||
}
|
||||
|
||||
func TestDepositContractAddress_EmptyAddress(t *testing.T) {
|
||||
params.SetupTestConfigCleanup(t)
|
||||
config := params.BeaconConfig()
|
||||
config.DepositContractAddress = ""
|
||||
params.OverrideBeaconConfig(config)
|
||||
|
||||
_, err := DepositContractAddress()
|
||||
assert.ErrorContains(t, "valid deposit contract is required", err)
|
||||
}
|
||||
|
||||
func TestDepositContractAddress_NotHexAddress(t *testing.T) {
|
||||
params.SetupTestConfigCleanup(t)
|
||||
config := params.BeaconConfig()
|
||||
config.DepositContractAddress = "abc?!"
|
||||
params.OverrideBeaconConfig(config)
|
||||
|
||||
_, err := DepositContractAddress()
|
||||
assert.ErrorContains(t, "invalid deposit contract address given", err)
|
||||
}
|
||||
@@ -39,6 +39,7 @@ go_test(
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//config/params:go_default_library",
|
||||
"//crypto/bls:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user