mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-10 13:58:09 -05:00
Compare commits
217 Commits
v1.2.2
...
v1.3.8-hot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6c09424feb | ||
|
|
a45b04543a | ||
|
|
cff7dbd015 | ||
|
|
afc0ace624 | ||
|
|
400e42cc2d | ||
|
|
59ee339497 | ||
|
|
c53d0e1c5f | ||
|
|
02a8ae7f36 | ||
|
|
a4ff97d24b | ||
|
|
3d3b9d1217 | ||
|
|
169cd78bbd | ||
|
|
405e2a1a03 | ||
|
|
d77c298ec6 | ||
|
|
2c6549b431 | ||
|
|
aba2ec9aac | ||
|
|
a8716d2949 | ||
|
|
04bc8a85ca | ||
|
|
a9a0ecd76d | ||
|
|
902e3f4f53 | ||
|
|
228033f7a3 | ||
|
|
53ffc67850 | ||
|
|
59eb2e60d0 | ||
|
|
0ea11ac212 | ||
|
|
3e686a71e3 | ||
|
|
efbefaeb7c | ||
|
|
dd7481e99c | ||
|
|
fda003288d | ||
|
|
131a14ee2f | ||
|
|
45d2df1af7 | ||
|
|
5f3299e598 | ||
|
|
5217081567 | ||
|
|
389bad7d24 | ||
|
|
97b4b86ddf | ||
|
|
cc9bec7a19 | ||
|
|
8b494fb1bc | ||
|
|
6aa1297829 | ||
|
|
a91f2688f1 | ||
|
|
1c1bf37b33 | ||
|
|
76e36b95f7 | ||
|
|
74cf2320ad | ||
|
|
2a1c880673 | ||
|
|
c65c6ebc38 | ||
|
|
19a9b4b064 | ||
|
|
1af88b2c35 | ||
|
|
e3149c4f0b | ||
|
|
0808c02c65 | ||
|
|
76390c94af | ||
|
|
f0e2f561d5 | ||
|
|
74d0134ee3 | ||
|
|
91df0112c7 | ||
|
|
7998348bcb | ||
|
|
99bd988375 | ||
|
|
0a2f3e4d48 | ||
|
|
dfe5372db5 | ||
|
|
f2f509be0e | ||
|
|
01eb77c834 | ||
|
|
3cd95b4a6c | ||
|
|
80ab9201b3 | ||
|
|
1c6c058bba | ||
|
|
528cd89616 | ||
|
|
c179cfb93e | ||
|
|
f67228bacb | ||
|
|
af3d3e8cd3 | ||
|
|
878439065c | ||
|
|
acf17f9b82 | ||
|
|
9afa304817 | ||
|
|
847640333a | ||
|
|
28e4a3b7e8 | ||
|
|
d7103fdef3 | ||
|
|
f822f0436e | ||
|
|
0b06c48ed0 | ||
|
|
190d862552 | ||
|
|
a8ab279cb8 | ||
|
|
feeb59de23 | ||
|
|
2ec3f79146 | ||
|
|
e26dab84f6 | ||
|
|
4886a4e749 | ||
|
|
54cf5f3c7a | ||
|
|
5f2f53a0a6 | ||
|
|
7f0c92504f | ||
|
|
961a012502 | ||
|
|
139017546d | ||
|
|
5d12cc1ded | ||
|
|
e32c88e14c | ||
|
|
6a4d4d7028 | ||
|
|
e56ab297b1 | ||
|
|
ad303fb943 | ||
|
|
89da5d1ef5 | ||
|
|
82f25bacf2 | ||
|
|
b2d9f9a2d8 | ||
|
|
9cb4eafad4 | ||
|
|
ff40a68215 | ||
|
|
2fe50c5edd | ||
|
|
3e92ae0f48 | ||
|
|
c112d27ab5 | ||
|
|
a539e3d66e | ||
|
|
446029c1ba | ||
|
|
fba56df765 | ||
|
|
8281634131 | ||
|
|
b346cde919 | ||
|
|
eca67cec4c | ||
|
|
14439d2b12 | ||
|
|
4a64d4d133 | ||
|
|
9421ac13d8 | ||
|
|
d2b1115f46 | ||
|
|
9282a73663 | ||
|
|
799a4d80cd | ||
|
|
fe6e6909e6 | ||
|
|
e477fdfd6d | ||
|
|
a921455836 | ||
|
|
beadec32b8 | ||
|
|
693ce7b952 | ||
|
|
ce725ceec3 | ||
|
|
ecf25d1284 | ||
|
|
0a73be7389 | ||
|
|
034a28710e | ||
|
|
7b16601399 | ||
|
|
50e99fb6c1 | ||
|
|
ea4ea3d1c1 | ||
|
|
1f8171d069 | ||
|
|
9fea9816bd | ||
|
|
aa389c82a1 | ||
|
|
c577fbd772 | ||
|
|
dc6dee3f4e | ||
|
|
a3c96c2f44 | ||
|
|
3b6b3f6ef6 | ||
|
|
eb694ab5d5 | ||
|
|
fa2084330b | ||
|
|
286444a2ec | ||
|
|
55b6134be1 | ||
|
|
5374d07c4d | ||
|
|
b62619ae3a | ||
|
|
dc0fc94c13 | ||
|
|
548b471b8a | ||
|
|
fa92766095 | ||
|
|
9980ca3b7e | ||
|
|
72be10f9a5 | ||
|
|
ab301aa4fe | ||
|
|
2bb0a602e4 | ||
|
|
363771a5c7 | ||
|
|
bdf2b2019b | ||
|
|
f2125e5f64 | ||
|
|
294b031fa4 | ||
|
|
4a98300c59 | ||
|
|
0f1d14437c | ||
|
|
79754bded2 | ||
|
|
90da16432f | ||
|
|
f074c5ee89 | ||
|
|
edd86fd358 | ||
|
|
067a519b37 | ||
|
|
32f2f711db | ||
|
|
c1d4ff6239 | ||
|
|
e36c3dd668 | ||
|
|
1c7c62cf8a | ||
|
|
d215607e55 | ||
|
|
ff329df808 | ||
|
|
c9858b5e6b | ||
|
|
565d51009d | ||
|
|
c6b74b2ba7 | ||
|
|
090fbbf18c | ||
|
|
cdea2debc9 | ||
|
|
4c49d4af7e | ||
|
|
46f6bd6d08 | ||
|
|
b3dcbfe2a4 | ||
|
|
a92b20d2bb | ||
|
|
8a27449595 | ||
|
|
a3781e2ffc | ||
|
|
f973924fbf | ||
|
|
9547f53e88 | ||
|
|
c30ee6c166 | ||
|
|
29d1959b81 | ||
|
|
878bc15229 | ||
|
|
e39ce36f1c | ||
|
|
b4648f1df9 | ||
|
|
f4adc0ea86 | ||
|
|
658cbf5631 | ||
|
|
b400098296 | ||
|
|
c3f875bf65 | ||
|
|
5db5ca7056 | ||
|
|
f0eb843138 | ||
|
|
d44c27ec63 | ||
|
|
0625a6906c | ||
|
|
4d28d5e4d2 | ||
|
|
08b938982b | ||
|
|
6ee290a9af | ||
|
|
4da7a7797e | ||
|
|
6e831920bf | ||
|
|
eca8d85446 | ||
|
|
1db3c86b68 | ||
|
|
0c599521b1 | ||
|
|
e40fba7679 | ||
|
|
6b82873737 | ||
|
|
3edfa8cb88 | ||
|
|
b577869ed6 | ||
|
|
5c14b4c833 | ||
|
|
dd08305aa7 | ||
|
|
1395c11c29 | ||
|
|
ef48f6a061 | ||
|
|
09ddfae1d9 | ||
|
|
ad9cd1933a | ||
|
|
0f515784d8 | ||
|
|
7d3e53f3e4 | ||
|
|
dc1bec79ed | ||
|
|
d472380fef | ||
|
|
eea0160dd4 | ||
|
|
1ae429dc61 | ||
|
|
fc265055df | ||
|
|
917252d7d0 | ||
|
|
4f9752bb3e | ||
|
|
6391dec5de | ||
|
|
1ba414bd77 | ||
|
|
6f2438436c | ||
|
|
2515dc4c06 | ||
|
|
2c36e6534c | ||
|
|
fe27ca359c | ||
|
|
bf7425bae4 | ||
|
|
558b16275d |
13
.bazelrc
13
.bazelrc
@@ -39,16 +39,15 @@ build --define kafka_enabled=false
|
||||
test --define kafka_enabled=false
|
||||
run --define kafka_enabled=false
|
||||
|
||||
# Enable blst by default, we use a config so that our fuzzer stops complaining.
|
||||
build --config=blst_enabled
|
||||
test --config=blst_enabled
|
||||
run --config=blst_enabled
|
||||
build --define blst_disabled=false
|
||||
test --define blst_disabled=false
|
||||
run --define blst_disabled=false
|
||||
|
||||
build:kafka_enabled --define kafka_enabled=true
|
||||
build:kafka_enabled --define gotags=kafka_enabled
|
||||
|
||||
build:blst_enabled --define blst_enabled=true
|
||||
build:blst_enabled --define gotags=blst_enabled
|
||||
build:blst_disabled --define blst_disabled=true
|
||||
build:blst_disabled --define gotags=blst_disabled
|
||||
|
||||
# Release flags
|
||||
build:release --compilation_mode=opt
|
||||
@@ -84,7 +83,7 @@ build:fuzz --linkopt -Wl,--no-as-needed
|
||||
build:fuzz --define=gc_goopts=-d=libfuzzer,checkptr
|
||||
build:fuzz --run_under=//tools:fuzz_wrapper
|
||||
build:fuzz --compilation_mode=opt
|
||||
build:fuzz --define=blst_enabled=false
|
||||
build:fuzz --define=blst_disabled=true
|
||||
|
||||
test:fuzz --local_test_jobs="HOST_CPUS*.5"
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# across machines, developers, and workspaces.
|
||||
#
|
||||
# This config is loaded from https://github.com/bazelbuild/bazel-toolchains/blob/master/bazelrc/latest.bazelrc
|
||||
build:remote-cache --remote_timeout=3600
|
||||
#build:remote-cache --remote_timeout=3600
|
||||
#build:remote-cache --spawn_strategy=standalone
|
||||
#build:remote-cache --strategy=Javac=standalone
|
||||
#build:remote-cache --strategy=Closure=standalone
|
||||
@@ -11,6 +11,13 @@ build:remote-cache --remote_timeout=3600
|
||||
# Prysm specific remote-cache properties.
|
||||
#build:remote-cache --disk_cache=
|
||||
build:remote-cache --remote_download_minimal
|
||||
build:remote-cache --remote_cache=grpc://bazel-remote-cache:9092
|
||||
build:remote-cache --experimental_remote_downloader=grpc://bazel-remote-cache:9092
|
||||
build:remote-cache --remote_local_fallback
|
||||
# Enforce stricter environment rules, which eliminates some non-hermetic
|
||||
# behavior and therefore improves both the remote cache hit rate and the
|
||||
# correctness and repeatability of the build.
|
||||
build:remote-cache --incompatible_strict_action_env=true
|
||||
|
||||
# Import workspace options.
|
||||
import %workspace%/.bazelrc
|
||||
|
||||
@@ -30,4 +30,4 @@ comment:
|
||||
|
||||
ignore:
|
||||
- "**/*.pb.go"
|
||||
- "**/*_mock.go"
|
||||
- "**/testing/**/*"
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
version = 1
|
||||
|
||||
exclude_patterns = [
|
||||
"tools/analyzers/**",
|
||||
"validator/keymanager/remote/keymanager_test.go",
|
||||
"validator/web/site_data.go"
|
||||
]
|
||||
|
||||
[[analyzers]]
|
||||
name = "go"
|
||||
enabled = true
|
||||
|
||||
[analyzers.meta]
|
||||
import_paths = ["github.com/prysmaticlabs/prysm"]
|
||||
[analyzers.meta]
|
||||
import_paths = ["github.com/prysmaticlabs/prysm"]
|
||||
|
||||
[[analyzers]]
|
||||
name = "test-coverage"
|
||||
@@ -14,3 +20,7 @@ enabled = true
|
||||
[[analyzers]]
|
||||
name = "shell"
|
||||
enabled = true
|
||||
|
||||
[[analyzers]]
|
||||
name = "secrets"
|
||||
enabled = true
|
||||
|
||||
2
.github/workflows/go.yml
vendored
2
.github/workflows/go.yml
vendored
@@ -44,7 +44,7 @@ jobs:
|
||||
|
||||
- name: Build
|
||||
# Use blst tag to allow go and bazel builds for blst.
|
||||
run: go build -v --tags=blst_enabled ./...
|
||||
run: go build -v ./...
|
||||
|
||||
# Tests run via Bazel for now...
|
||||
# - name: Test
|
||||
|
||||
16
WORKSPACE
16
WORKSPACE
@@ -60,10 +60,10 @@ bazel_skylib_workspace()
|
||||
|
||||
http_archive(
|
||||
name = "bazel_gazelle",
|
||||
sha256 = "1f4fc1d91826ec436ae04833430626f4cc02c20bb0a813c0c2f3c4c421307b1d",
|
||||
strip_prefix = "bazel-gazelle-e368a11b76e92932122d824970dc0ce5feb9c349",
|
||||
sha256 = "62ca106be173579c0a167deb23358fdfe71ffa1e4cfdddf5582af26520f1c66f",
|
||||
urls = [
|
||||
"https://github.com/bazelbuild/bazel-gazelle/archive/e368a11b76e92932122d824970dc0ce5feb9c349.tar.gz",
|
||||
"https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.23.0/bazel-gazelle-v0.23.0.tar.gz",
|
||||
"https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.23.0/bazel-gazelle-v0.23.0.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -76,6 +76,8 @@ http_archive(
|
||||
|
||||
http_archive(
|
||||
name = "io_bazel_rules_docker",
|
||||
patch_args = ["-p1"],
|
||||
patches = ["//third_party:rules_docker_bad_checksum.patch"],
|
||||
sha256 = "1286175a94c0b1335efe1d75d22ea06e89742557d3fac2a0366f242a6eac6f5a",
|
||||
strip_prefix = "rules_docker-ba4310833230294fa69b7d6ea1787ac684631a7d",
|
||||
urls = ["https://github.com/bazelbuild/rules_docker/archive/ba4310833230294fa69b7d6ea1787ac684631a7d.tar.gz"],
|
||||
@@ -89,10 +91,10 @@ http_archive(
|
||||
# nogo check fails for certain third_party dependencies.
|
||||
"//third_party:io_bazel_rules_go.patch",
|
||||
],
|
||||
sha256 = "dbf5a9ef855684f84cac2e7ae7886c5a001d4f66ae23f6904da0faaaef0d61fc",
|
||||
sha256 = "7c10271940c6bce577d51a075ae77728964db285dac0a46614a7934dc34303e6",
|
||||
urls = [
|
||||
"https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.24.11/rules_go-v0.24.11.tar.gz",
|
||||
"https://github.com/bazelbuild/rules_go/releases/download/v0.24.11/rules_go-v0.24.11.tar.gz",
|
||||
"https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.26.0/rules_go-v0.26.0.tar.gz",
|
||||
"https://github.com/bazelbuild/rules_go/releases/download/v0.26.0/rules_go-v0.26.0.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -156,7 +158,7 @@ load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_depe
|
||||
go_rules_dependencies()
|
||||
|
||||
go_register_toolchains(
|
||||
go_version = "1.15.7",
|
||||
go_version = "1.16",
|
||||
nogo = "@//:nogo",
|
||||
)
|
||||
|
||||
|
||||
4
bazel.sh
4
bazel.sh
@@ -6,6 +6,6 @@
|
||||
|
||||
env -i \
|
||||
PATH=/usr/bin:/bin \
|
||||
HOME=$HOME \
|
||||
GOOGLE_APPLICATION_CREDENTIALS=$GOOGLE_APPLICATION_CREDENTIALS \
|
||||
HOME="$HOME" \
|
||||
GOOGLE_APPLICATION_CREDENTIALS="$GOOGLE_APPLICATION_CREDENTIALS" \
|
||||
bazel "$@"
|
||||
|
||||
@@ -1,138 +1,19 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_library")
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_test")
|
||||
load("@io_bazel_rules_docker//go:image.bzl", "go_image")
|
||||
load("@io_bazel_rules_docker//container:container.bzl", "container_bundle", "container_image")
|
||||
load("//tools:go_image.bzl", "go_image_alpine", "go_image_debug")
|
||||
load("@io_bazel_rules_docker//contrib:push-all.bzl", "docker_push")
|
||||
load("//tools:target_migration.bzl", "moved_targets")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"log.go",
|
||||
"main.go",
|
||||
"usage.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain",
|
||||
visibility = ["//beacon-chain:__subpackages__"],
|
||||
deps = [
|
||||
"//beacon-chain/db:go_default_library",
|
||||
"//beacon-chain/flags:go_default_library",
|
||||
"//beacon-chain/node:go_default_library",
|
||||
"//shared/cmd:go_default_library",
|
||||
"//shared/debug:go_default_library",
|
||||
"//shared/featureconfig:go_default_library",
|
||||
"//shared/fileutil:go_default_library",
|
||||
"//shared/journald:go_default_library",
|
||||
"//shared/logutil:go_default_library",
|
||||
"//shared/maxprocs:go_default_library",
|
||||
"//shared/tos:go_default_library",
|
||||
"//shared/version:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//log:go_default_library",
|
||||
"@com_github_ipfs_go_log_v2//:go_default_library",
|
||||
"@com_github_joonix_log//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@com_github_urfave_cli_v2//:go_default_library",
|
||||
"@com_github_x_cray_logrus_prefixed_formatter//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_image(
|
||||
name = "image",
|
||||
base = select({
|
||||
"//tools:base_image_alpine": "//tools:alpine_cc_image",
|
||||
"//tools:base_image_cc": "//tools:cc_image",
|
||||
"//conditions:default": "//tools:cc_image",
|
||||
}),
|
||||
binary = ":beacon-chain",
|
||||
tags = ["manual"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
container_image(
|
||||
name = "image_with_creation_time",
|
||||
base = "image",
|
||||
stamp = True,
|
||||
)
|
||||
|
||||
container_bundle(
|
||||
name = "image_bundle",
|
||||
images = {
|
||||
"gcr.io/prysmaticlabs/prysm/beacon-chain:latest": ":image_with_creation_time",
|
||||
"gcr.io/prysmaticlabs/prysm/beacon-chain:{DOCKER_TAG}": ":image_with_creation_time",
|
||||
"index.docker.io/prysmaticlabs/prysm-beacon-chain:latest": ":image_with_creation_time",
|
||||
"index.docker.io/prysmaticlabs/prysm-beacon-chain:{DOCKER_TAG}": ":image_with_creation_time",
|
||||
},
|
||||
tags = ["manual"],
|
||||
)
|
||||
|
||||
go_image_debug(
|
||||
name = "image_debug",
|
||||
image = ":image",
|
||||
tags = ["manual"],
|
||||
)
|
||||
|
||||
container_bundle(
|
||||
name = "image_bundle_debug",
|
||||
images = {
|
||||
"gcr.io/prysmaticlabs/prysm/beacon-chain:latest-debug": ":image_debug",
|
||||
"gcr.io/prysmaticlabs/prysm/beacon-chain:{DOCKER_TAG}-debug": ":image_debug",
|
||||
"index.docker.io/prysmaticlabs/prysm-beacon-chain:latest-debug": ":image_debug",
|
||||
"index.docker.io/prysmaticlabs/prysm-beacon-chain:{DOCKER_TAG}-debug": ":image_debug",
|
||||
},
|
||||
tags = ["manual"],
|
||||
)
|
||||
|
||||
go_image_alpine(
|
||||
name = "image_alpine",
|
||||
image = ":image",
|
||||
tags = ["manual"],
|
||||
)
|
||||
|
||||
container_bundle(
|
||||
name = "image_bundle_alpine",
|
||||
images = {
|
||||
"gcr.io/prysmaticlabs/prysm/beacon-chain:latest-alpine": ":image_alpine",
|
||||
"gcr.io/prysmaticlabs/prysm/beacon-chain:{DOCKER_TAG}-alpine": ":image_alpine",
|
||||
"index.docker.io/prysmaticlabs/prysm-beacon-chain:latest-alpine": ":image_alpine",
|
||||
"index.docker.io/prysmaticlabs/prysm-beacon-chain:{DOCKER_TAG}-alpine": ":image_alpine",
|
||||
},
|
||||
tags = ["manual"],
|
||||
)
|
||||
|
||||
docker_push(
|
||||
name = "push_images",
|
||||
bundle = ":image_bundle",
|
||||
tags = ["manual"],
|
||||
)
|
||||
|
||||
docker_push(
|
||||
name = "push_images_debug",
|
||||
bundle = ":image_bundle_debug",
|
||||
tags = ["manual"],
|
||||
)
|
||||
|
||||
docker_push(
|
||||
name = "push_images_alpine",
|
||||
bundle = ":image_bundle_alpine",
|
||||
tags = ["manual"],
|
||||
)
|
||||
|
||||
go_binary(
|
||||
name = "beacon-chain",
|
||||
embed = [":go_default_library"],
|
||||
visibility = [
|
||||
"//beacon-chain:__subpackages__",
|
||||
"//endtoend:__pkg__",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
size = "small",
|
||||
srcs = ["usage_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//shared/featureconfig:go_default_library",
|
||||
"@com_github_urfave_cli_v2//:go_default_library",
|
||||
moved_targets(
|
||||
[
|
||||
":push_images_debug",
|
||||
":push_images_alpine",
|
||||
":push_images",
|
||||
":image_bundle_debug",
|
||||
":image_debug",
|
||||
":image_bundle_alpine",
|
||||
":image_bundle",
|
||||
":image_with_creation_time",
|
||||
":image_alpine",
|
||||
":image",
|
||||
":go_default_test",
|
||||
":beacon-chain",
|
||||
],
|
||||
"//cmd/beacon-chain",
|
||||
)
|
||||
|
||||
@@ -27,7 +27,6 @@ go_library(
|
||||
deps = [
|
||||
"//beacon-chain/cache:go_default_library",
|
||||
"//beacon-chain/cache/depositcache:go_default_library",
|
||||
"//beacon-chain/core/blocks:go_default_library",
|
||||
"//beacon-chain/core/epoch/precompute:go_default_library",
|
||||
"//beacon-chain/core/feed:go_default_library",
|
||||
"//beacon-chain/core/feed/state:go_default_library",
|
||||
@@ -35,7 +34,6 @@ go_library(
|
||||
"//beacon-chain/core/state:go_default_library",
|
||||
"//beacon-chain/db:go_default_library",
|
||||
"//beacon-chain/db/filters:go_default_library",
|
||||
"//beacon-chain/flags:go_default_library",
|
||||
"//beacon-chain/forkchoice:go_default_library",
|
||||
"//beacon-chain/forkchoice/protoarray:go_default_library",
|
||||
"//beacon-chain/operations/attestations:go_default_library",
|
||||
@@ -43,8 +41,10 @@ go_library(
|
||||
"//beacon-chain/operations/voluntaryexits:go_default_library",
|
||||
"//beacon-chain/p2p:go_default_library",
|
||||
"//beacon-chain/powchain:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//beacon-chain/state/interface:go_default_library",
|
||||
"//beacon-chain/state/stateV0:go_default_library",
|
||||
"//beacon-chain/state/stategen:go_default_library",
|
||||
"//cmd/beacon-chain/flags:go_default_library",
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/attestationutil:go_default_library",
|
||||
"//shared/bls:go_default_library",
|
||||
@@ -83,6 +83,7 @@ go_test(
|
||||
"checktags_test.go",
|
||||
"head_test.go",
|
||||
"info_test.go",
|
||||
"init_test.go",
|
||||
"metrics_test.go",
|
||||
"process_attestation_test.go",
|
||||
"process_block_test.go",
|
||||
@@ -129,6 +130,7 @@ go_test(
|
||||
srcs = [
|
||||
"chain_info_norace_test.go",
|
||||
"checktags_test.go",
|
||||
"init_test.go",
|
||||
"receive_block_test.go",
|
||||
"service_norace_test.go",
|
||||
],
|
||||
|
||||
@@ -8,7 +8,8 @@ import (
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateV0"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
@@ -41,12 +42,13 @@ type HeadFetcher interface {
|
||||
HeadSlot() types.Slot
|
||||
HeadRoot(ctx context.Context) ([]byte, error)
|
||||
HeadBlock(ctx context.Context) (*ethpb.SignedBeaconBlock, error)
|
||||
HeadState(ctx context.Context) (*state.BeaconState, error)
|
||||
HeadValidatorsIndices(ctx context.Context, epoch types.Epoch) ([]uint64, error)
|
||||
HeadState(ctx context.Context) (iface.BeaconState, error)
|
||||
HeadValidatorsIndices(ctx context.Context, epoch types.Epoch) ([]types.ValidatorIndex, error)
|
||||
HeadSeed(ctx context.Context, epoch types.Epoch) ([32]byte, error)
|
||||
HeadGenesisValidatorRoot() [32]byte
|
||||
HeadETH1Data() *ethpb.Eth1Data
|
||||
ProtoArrayStore() *protoarray.Store
|
||||
ChainHeads() ([][32]byte, []types.Slot)
|
||||
}
|
||||
|
||||
// ForkFetcher retrieves the current fork information of the Ethereum beacon chain.
|
||||
@@ -74,7 +76,7 @@ func (s *Service) FinalizedCheckpt() *ethpb.Checkpoint {
|
||||
return ðpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]}
|
||||
}
|
||||
|
||||
return state.CopyCheckpoint(s.finalizedCheckpt)
|
||||
return stateV0.CopyCheckpoint(s.finalizedCheckpt)
|
||||
}
|
||||
|
||||
// CurrentJustifiedCheckpt returns the current justified checkpoint from head state.
|
||||
@@ -83,7 +85,7 @@ func (s *Service) CurrentJustifiedCheckpt() *ethpb.Checkpoint {
|
||||
return ðpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]}
|
||||
}
|
||||
|
||||
return state.CopyCheckpoint(s.justifiedCheckpt)
|
||||
return stateV0.CopyCheckpoint(s.justifiedCheckpt)
|
||||
}
|
||||
|
||||
// PreviousJustifiedCheckpt returns the previous justified checkpoint from head state.
|
||||
@@ -92,7 +94,7 @@ func (s *Service) PreviousJustifiedCheckpt() *ethpb.Checkpoint {
|
||||
return ðpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]}
|
||||
}
|
||||
|
||||
return state.CopyCheckpoint(s.prevJustifiedCheckpt)
|
||||
return stateV0.CopyCheckpoint(s.prevJustifiedCheckpt)
|
||||
}
|
||||
|
||||
// HeadSlot returns the slot of the head of the chain.
|
||||
@@ -117,7 +119,7 @@ func (s *Service) HeadRoot(ctx context.Context) ([]byte, error) {
|
||||
return r[:], nil
|
||||
}
|
||||
|
||||
b, err := s.beaconDB.HeadBlock(ctx)
|
||||
b, err := s.cfg.BeaconDB.HeadBlock(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -144,13 +146,13 @@ func (s *Service) HeadBlock(ctx context.Context) (*ethpb.SignedBeaconBlock, erro
|
||||
return s.headBlock(), nil
|
||||
}
|
||||
|
||||
return s.beaconDB.HeadBlock(ctx)
|
||||
return s.cfg.BeaconDB.HeadBlock(ctx)
|
||||
}
|
||||
|
||||
// HeadState returns the head state of the chain.
|
||||
// If the head is nil from service struct,
|
||||
// it will attempt to get the head state from DB.
|
||||
func (s *Service) HeadState(ctx context.Context) (*state.BeaconState, error) {
|
||||
func (s *Service) HeadState(ctx context.Context) (iface.BeaconState, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "blockChain.HeadState")
|
||||
defer span.End()
|
||||
s.headLock.RLock()
|
||||
@@ -163,16 +165,16 @@ func (s *Service) HeadState(ctx context.Context) (*state.BeaconState, error) {
|
||||
return s.headState(ctx), nil
|
||||
}
|
||||
|
||||
return s.stateGen.StateByRoot(ctx, s.headRoot())
|
||||
return s.cfg.StateGen.StateByRoot(ctx, s.headRoot())
|
||||
}
|
||||
|
||||
// HeadValidatorsIndices returns a list of active validator indices from the head view of a given epoch.
|
||||
func (s *Service) HeadValidatorsIndices(ctx context.Context, epoch types.Epoch) ([]uint64, error) {
|
||||
func (s *Service) HeadValidatorsIndices(ctx context.Context, epoch types.Epoch) ([]types.ValidatorIndex, error) {
|
||||
s.headLock.RLock()
|
||||
defer s.headLock.RUnlock()
|
||||
|
||||
if !s.hasHeadState() {
|
||||
return []uint64{}, nil
|
||||
return []types.ValidatorIndex{}, nil
|
||||
}
|
||||
return helpers.ActiveValidatorIndices(s.headState(ctx), epoch)
|
||||
}
|
||||
@@ -214,7 +216,7 @@ func (s *Service) HeadETH1Data() *ethpb.Eth1Data {
|
||||
|
||||
// ProtoArrayStore returns the proto array store object.
|
||||
func (s *Service) ProtoArrayStore() *protoarray.Store {
|
||||
return s.forkChoiceStore.Store()
|
||||
return s.cfg.ForkChoiceStore.Store()
|
||||
}
|
||||
|
||||
// GenesisTime returns the genesis time of beacon chain.
|
||||
@@ -251,10 +253,32 @@ func (s *Service) CurrentFork() *pb.Fork {
|
||||
// IsCanonical returns true if the input block root is part of the canonical chain.
|
||||
func (s *Service) IsCanonical(ctx context.Context, blockRoot [32]byte) (bool, error) {
|
||||
// If the block has been finalized, the block will always be part of the canonical chain.
|
||||
if s.beaconDB.IsFinalizedBlock(ctx, blockRoot) {
|
||||
if s.cfg.BeaconDB.IsFinalizedBlock(ctx, blockRoot) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// If the block has not been finalized, check fork choice store to see if the block is canonical
|
||||
return s.forkChoiceStore.IsCanonical(blockRoot), nil
|
||||
return s.cfg.ForkChoiceStore.IsCanonical(blockRoot), nil
|
||||
}
|
||||
|
||||
// ChainHeads returns all possible chain heads (leaves of fork choice tree).
|
||||
// Heads roots and heads slots are returned.
|
||||
func (s *Service) ChainHeads() ([][32]byte, []types.Slot) {
|
||||
nodes := s.ProtoArrayStore().Nodes()
|
||||
|
||||
// Deliberate choice to not preallocate space for below.
|
||||
// Heads cant be more than 2-3 in the worst case where pre-allocation will be 64 to begin with.
|
||||
headsRoots := make([][32]byte, 0)
|
||||
headsSlots := make([]types.Slot, 0)
|
||||
|
||||
nonExistentNode := ^uint64(0)
|
||||
for _, node := range nodes {
|
||||
// Possible heads have no children.
|
||||
if node.BestDescendant() == nonExistentNode && node.BestChild() == nonExistentNode {
|
||||
headsRoots = append(headsRoots, node.Root())
|
||||
headsSlots = append(headsSlots, node.Slot())
|
||||
}
|
||||
}
|
||||
|
||||
return headsRoots, headsSlots
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
func TestHeadSlot_DataRace(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
s := &Service{
|
||||
beaconDB: beaconDB,
|
||||
cfg: &Config{BeaconDB: beaconDB},
|
||||
}
|
||||
go func() {
|
||||
require.NoError(t, s.saveHead(context.Background(), [32]byte{}))
|
||||
@@ -24,9 +24,8 @@ func TestHeadSlot_DataRace(t *testing.T) {
|
||||
func TestHeadRoot_DataRace(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
s := &Service{
|
||||
beaconDB: beaconDB,
|
||||
head: &head{root: [32]byte{'A'}},
|
||||
stateGen: stategen.New(beaconDB),
|
||||
cfg: &Config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB)},
|
||||
head: &head{root: [32]byte{'A'}},
|
||||
}
|
||||
go func() {
|
||||
require.NoError(t, s.saveHead(context.Background(), [32]byte{}))
|
||||
@@ -38,9 +37,8 @@ func TestHeadRoot_DataRace(t *testing.T) {
|
||||
func TestHeadBlock_DataRace(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
s := &Service{
|
||||
beaconDB: beaconDB,
|
||||
head: &head{block: ðpb.SignedBeaconBlock{}},
|
||||
stateGen: stategen.New(beaconDB),
|
||||
cfg: &Config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB)},
|
||||
head: &head{block: ðpb.SignedBeaconBlock{}},
|
||||
}
|
||||
go func() {
|
||||
require.NoError(t, s.saveHead(context.Background(), [32]byte{}))
|
||||
@@ -52,8 +50,7 @@ func TestHeadBlock_DataRace(t *testing.T) {
|
||||
func TestHeadState_DataRace(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
s := &Service{
|
||||
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{}))
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateV0"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
@@ -104,7 +104,7 @@ func TestPrevJustifiedCheckpt_GenesisRootOk(t *testing.T) {
|
||||
|
||||
func TestHeadSlot_CanRetrieve(t *testing.T) {
|
||||
c := &Service{}
|
||||
s, err := state.InitializeFromProto(&pb.BeaconState{})
|
||||
s, err := stateV0.InitializeFromProto(&pb.BeaconState{})
|
||||
require.NoError(t, err)
|
||||
c.head = &head{slot: 100, state: s}
|
||||
assert.Equal(t, types.Slot(100), c.HeadSlot())
|
||||
@@ -120,7 +120,7 @@ func TestHeadRoot_CanRetrieve(t *testing.T) {
|
||||
|
||||
func TestHeadRoot_UseDB(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
c := &Service{beaconDB: beaconDB}
|
||||
c := &Service{cfg: &Config{BeaconDB: beaconDB}}
|
||||
c.head = &head{root: params.BeaconConfig().ZeroHash}
|
||||
b := testutil.NewBeaconBlock()
|
||||
br, err := b.Block.HashTreeRoot()
|
||||
@@ -136,7 +136,7 @@ func TestHeadRoot_UseDB(t *testing.T) {
|
||||
func TestHeadBlock_CanRetrieve(t *testing.T) {
|
||||
b := testutil.NewBeaconBlock()
|
||||
b.Block.Slot = 1
|
||||
s, err := state.InitializeFromProto(&pb.BeaconState{})
|
||||
s, err := stateV0.InitializeFromProto(&pb.BeaconState{})
|
||||
require.NoError(t, err)
|
||||
c := &Service{}
|
||||
c.head = &head{block: b, state: s}
|
||||
@@ -147,7 +147,7 @@ func TestHeadBlock_CanRetrieve(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestHeadState_CanRetrieve(t *testing.T) {
|
||||
s, err := state.InitializeFromProto(&pb.BeaconState{Slot: 2, GenesisValidatorsRoot: params.BeaconConfig().ZeroHash[:]})
|
||||
s, err := stateV0.InitializeFromProto(&pb.BeaconState{Slot: 2, GenesisValidatorsRoot: params.BeaconConfig().ZeroHash[:]})
|
||||
require.NoError(t, err)
|
||||
c := &Service{}
|
||||
c.head = &head{state: s}
|
||||
@@ -164,7 +164,7 @@ func TestGenesisTime_CanRetrieve(t *testing.T) {
|
||||
|
||||
func TestCurrentFork_CanRetrieve(t *testing.T) {
|
||||
f := &pb.Fork{Epoch: 999}
|
||||
s, err := state.InitializeFromProto(&pb.BeaconState{Fork: f})
|
||||
s, err := stateV0.InitializeFromProto(&pb.BeaconState{Fork: f})
|
||||
require.NoError(t, err)
|
||||
c := &Service{}
|
||||
c.head = &head{state: s}
|
||||
@@ -189,7 +189,7 @@ func TestGenesisValidatorRoot_CanRetrieve(t *testing.T) {
|
||||
c := &Service{}
|
||||
assert.Equal(t, [32]byte{}, c.GenesisValidatorRoot(), "Did not get correct genesis validator root")
|
||||
|
||||
s, err := state.InitializeFromProto(&pb.BeaconState{GenesisValidatorsRoot: []byte{'a'}})
|
||||
s, err := stateV0.InitializeFromProto(&pb.BeaconState{GenesisValidatorsRoot: []byte{'a'}})
|
||||
require.NoError(t, err)
|
||||
c.head = &head{state: s}
|
||||
assert.Equal(t, [32]byte{'a'}, c.GenesisValidatorRoot(), "Did not get correct genesis validator root")
|
||||
@@ -203,7 +203,7 @@ func TestHeadETH1Data_Nil(t *testing.T) {
|
||||
|
||||
func TestHeadETH1Data_CanRetrieve(t *testing.T) {
|
||||
d := ðpb.Eth1Data{DepositCount: 999}
|
||||
s, err := state.InitializeFromProto(&pb.BeaconState{Eth1Data: d})
|
||||
s, err := stateV0.InitializeFromProto(&pb.BeaconState{Eth1Data: d})
|
||||
require.NoError(t, err)
|
||||
c := &Service{}
|
||||
c.head = &head{state: s}
|
||||
@@ -278,7 +278,21 @@ func TestService_HeadGenesisValidatorRoot(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestService_ProtoArrayStore(t *testing.T) {
|
||||
c := &Service{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{})}}
|
||||
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))
|
||||
require.NoError(t, c.cfg.ForkChoiceStore.ProcessBlock(ctx, 103, [32]byte{'d'}, [32]byte{}, [32]byte{}, 0, 0))
|
||||
require.NoError(t, c.cfg.ForkChoiceStore.ProcessBlock(ctx, 104, [32]byte{'e'}, [32]byte{'b'}, [32]byte{}, 0, 0))
|
||||
|
||||
roots, slots := c.ChainHeads()
|
||||
require.DeepEqual(t, [][32]byte{{'c'}, {'d'}, {'e'}}, roots)
|
||||
require.DeepEqual(t, []types.Slot{102, 103, 104}, slots)
|
||||
}
|
||||
|
||||
@@ -12,7 +12,8 @@ import (
|
||||
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateV0"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/sirupsen/logrus"
|
||||
@@ -24,7 +25,7 @@ type head struct {
|
||||
slot types.Slot // current head slot.
|
||||
root [32]byte // current head root.
|
||||
block *ethpb.SignedBeaconBlock // current head block.
|
||||
state *stateTrie.BeaconState // current head state.
|
||||
state iface.BeaconState // current head state.
|
||||
}
|
||||
|
||||
// Determined the head from the fork choice service and saves its new data
|
||||
@@ -57,18 +58,18 @@ func (s *Service) updateHead(ctx context.Context, balances []uint64) error {
|
||||
// If the fork choice store is missing justified block info, a node should
|
||||
// re-initiate fork choice store using the latest justified info.
|
||||
// This recovers a fatal condition and should not happen in run time.
|
||||
if !s.forkChoiceStore.HasNode(headStartRoot) {
|
||||
jb, err := s.beaconDB.Block(ctx, headStartRoot)
|
||||
if !s.cfg.ForkChoiceStore.HasNode(headStartRoot) {
|
||||
jb, err := s.cfg.BeaconDB.Block(ctx, headStartRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.forkChoiceStore = protoarray.New(j.Epoch, f.Epoch, bytesutil.ToBytes32(f.Root))
|
||||
s.cfg.ForkChoiceStore = protoarray.New(j.Epoch, f.Epoch, bytesutil.ToBytes32(f.Root))
|
||||
if err := s.insertBlockToForkChoiceStore(ctx, jb.Block, headStartRoot, f, j); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
headRoot, err := s.forkChoiceStore.Head(ctx, j.Epoch, headStartRoot, balances, f.Epoch)
|
||||
headRoot, err := s.cfg.ForkChoiceStore.Head(ctx, j.Epoch, headStartRoot, balances, f.Epoch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -94,12 +95,12 @@ func (s *Service) saveHead(ctx context.Context, headRoot [32]byte) error {
|
||||
|
||||
// If the head state is not available, just return nil.
|
||||
// There's nothing to cache
|
||||
if !s.beaconDB.HasStateSummary(ctx, headRoot) {
|
||||
if !s.cfg.BeaconDB.HasStateSummary(ctx, headRoot) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get the new head block from DB.
|
||||
newHeadBlock, err := s.beaconDB.Block(ctx, headRoot)
|
||||
newHeadBlock, err := s.cfg.BeaconDB.Block(ctx, headRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -108,7 +109,7 @@ func (s *Service) saveHead(ctx context.Context, headRoot [32]byte) error {
|
||||
}
|
||||
|
||||
// Get the new head state from cached state or DB.
|
||||
newHeadState, err := s.stateGen.StateByRoot(ctx, headRoot)
|
||||
newHeadState, err := s.cfg.StateGen.StateByRoot(ctx, headRoot)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not retrieve head state in DB")
|
||||
}
|
||||
@@ -123,7 +124,7 @@ func (s *Service) saveHead(ctx context.Context, headRoot [32]byte) error {
|
||||
"newSlot": fmt.Sprintf("%d", newHeadBlock.Block.Slot),
|
||||
"oldSlot": fmt.Sprintf("%d", headSlot),
|
||||
}).Debug("Chain reorg occurred")
|
||||
s.stateNotifier.StateFeed().Send(&feed.Event{
|
||||
s.cfg.StateNotifier.StateFeed().Send(&feed.Event{
|
||||
Type: statefeed.Reorg,
|
||||
Data: &statefeed.ReorgData{
|
||||
NewSlot: newHeadBlock.Block.Slot,
|
||||
@@ -138,7 +139,7 @@ func (s *Service) saveHead(ctx context.Context, headRoot [32]byte) error {
|
||||
s.setHead(headRoot, newHeadBlock, newHeadState)
|
||||
|
||||
// Save the new head root to DB.
|
||||
if err := s.beaconDB.SaveHeadBlockRoot(ctx, headRoot); err != nil {
|
||||
if err := s.cfg.BeaconDB.SaveHeadBlockRoot(ctx, headRoot); err != nil {
|
||||
return errors.Wrap(err, "could not save head root in DB")
|
||||
}
|
||||
|
||||
@@ -148,7 +149,7 @@ func (s *Service) saveHead(ctx context.Context, headRoot [32]byte) error {
|
||||
// This gets called to update canonical root mapping. It does not save head block
|
||||
// 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 *ethpb.SignedBeaconBlock, r [32]byte, hs *stateTrie.BeaconState) error {
|
||||
func (s *Service) saveHeadNoDB(ctx context.Context, b *ethpb.SignedBeaconBlock, r [32]byte, hs iface.BeaconState) error {
|
||||
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -160,12 +161,12 @@ func (s *Service) saveHeadNoDB(ctx context.Context, b *ethpb.SignedBeaconBlock,
|
||||
return nil
|
||||
}
|
||||
|
||||
s.setHeadInitialSync(r, stateTrie.CopySignedBeaconBlock(b), hs)
|
||||
s.setHeadInitialSync(r, stateV0.CopySignedBeaconBlock(b), hs)
|
||||
return nil
|
||||
}
|
||||
|
||||
// This sets head view object which is used to track the head slot, root, block and state.
|
||||
func (s *Service) setHead(root [32]byte, block *ethpb.SignedBeaconBlock, state *stateTrie.BeaconState) {
|
||||
func (s *Service) setHead(root [32]byte, block *ethpb.SignedBeaconBlock, state iface.BeaconState) {
|
||||
s.headLock.Lock()
|
||||
defer s.headLock.Unlock()
|
||||
|
||||
@@ -173,7 +174,7 @@ func (s *Service) setHead(root [32]byte, block *ethpb.SignedBeaconBlock, state *
|
||||
s.head = &head{
|
||||
slot: block.Block.Slot,
|
||||
root: root,
|
||||
block: stateTrie.CopySignedBeaconBlock(block),
|
||||
block: stateV0.CopySignedBeaconBlock(block),
|
||||
state: state.Copy(),
|
||||
}
|
||||
}
|
||||
@@ -181,7 +182,7 @@ func (s *Service) setHead(root [32]byte, block *ethpb.SignedBeaconBlock, state *
|
||||
// This sets head view object which is used to track the head slot, root, block and state. The method
|
||||
// assumes that state being passed into the method will not be modified by any other alternate
|
||||
// caller which holds the state's reference.
|
||||
func (s *Service) setHeadInitialSync(root [32]byte, block *ethpb.SignedBeaconBlock, state *stateTrie.BeaconState) {
|
||||
func (s *Service) setHeadInitialSync(root [32]byte, block *ethpb.SignedBeaconBlock, state iface.BeaconState) {
|
||||
s.headLock.Lock()
|
||||
defer s.headLock.Unlock()
|
||||
|
||||
@@ -189,7 +190,7 @@ func (s *Service) setHeadInitialSync(root [32]byte, block *ethpb.SignedBeaconBlo
|
||||
s.head = &head{
|
||||
slot: block.Block.Slot,
|
||||
root: root,
|
||||
block: stateTrie.CopySignedBeaconBlock(block),
|
||||
block: stateV0.CopySignedBeaconBlock(block),
|
||||
state: state,
|
||||
}
|
||||
}
|
||||
@@ -215,13 +216,13 @@ func (s *Service) headRoot() [32]byte {
|
||||
// It does a full copy on head block for immutability.
|
||||
// This is a lock free version.
|
||||
func (s *Service) headBlock() *ethpb.SignedBeaconBlock {
|
||||
return stateTrie.CopySignedBeaconBlock(s.head.block)
|
||||
return stateV0.CopySignedBeaconBlock(s.head.block)
|
||||
}
|
||||
|
||||
// This returns the head state.
|
||||
// It does a full copy on head state for immutability.
|
||||
// This is a lock free version.
|
||||
func (s *Service) headState(ctx context.Context) *stateTrie.BeaconState {
|
||||
func (s *Service) headState(ctx context.Context) iface.BeaconState {
|
||||
ctx, span := trace.StartSpan(ctx, "blockChain.headState")
|
||||
defer span.End()
|
||||
|
||||
@@ -242,21 +243,21 @@ func (s *Service) hasHeadState() bool {
|
||||
|
||||
// This caches justified state balances to be used for fork choice.
|
||||
func (s *Service) cacheJustifiedStateBalances(ctx context.Context, justifiedRoot [32]byte) error {
|
||||
if err := s.beaconDB.SaveBlocks(ctx, s.getInitSyncBlocks()); err != nil {
|
||||
if err := s.cfg.BeaconDB.SaveBlocks(ctx, s.getInitSyncBlocks()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.clearInitSyncBlocks()
|
||||
|
||||
var justifiedState *stateTrie.BeaconState
|
||||
var justifiedState iface.BeaconState
|
||||
var err error
|
||||
if justifiedRoot == s.genesisRoot {
|
||||
justifiedState, err = s.beaconDB.GenesisState(ctx)
|
||||
justifiedState, err = s.cfg.BeaconDB.GenesisState(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
justifiedState, err = s.stateGen.StateByRoot(ctx, justifiedRoot)
|
||||
justifiedState, err = s.cfg.StateGen.StateByRoot(ctx, justifiedRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -268,7 +269,7 @@ func (s *Service) cacheJustifiedStateBalances(ctx context.Context, justifiedRoot
|
||||
epoch := helpers.CurrentEpoch(justifiedState)
|
||||
|
||||
justifiedBalances := make([]uint64, justifiedState.NumValidators())
|
||||
if err := justifiedState.ReadFromEveryValidator(func(idx int, val stateTrie.ReadOnlyValidator) error {
|
||||
if err := justifiedState.ReadFromEveryValidator(func(idx int, val iface.ReadOnlyValidator) error {
|
||||
if helpers.IsActiveValidatorUsingTrie(val, epoch) {
|
||||
justifiedBalances[idx] = val.EffectiveBalance()
|
||||
} else {
|
||||
|
||||
@@ -39,14 +39,14 @@ func TestSaveHead_Different(t *testing.T) {
|
||||
newHeadSignedBlock.Block.Slot = 1
|
||||
newHeadBlock := newHeadSignedBlock.Block
|
||||
|
||||
require.NoError(t, service.beaconDB.SaveBlock(context.Background(), newHeadSignedBlock))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveBlock(context.Background(), newHeadSignedBlock))
|
||||
newRoot, err := newHeadBlock.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
headState, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, headState.SetSlot(1))
|
||||
require.NoError(t, service.beaconDB.SaveStateSummary(context.Background(), &pb.StateSummary{Slot: 1, Root: newRoot[:]}))
|
||||
require.NoError(t, service.beaconDB.SaveState(context.Background(), headState, newRoot))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(context.Background(), &pb.StateSummary{Slot: 1, Root: newRoot[:]}))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveState(context.Background(), headState, newRoot))
|
||||
require.NoError(t, service.saveHead(context.Background(), newRoot))
|
||||
|
||||
assert.Equal(t, types.Slot(1), service.HeadSlot(), "Head did not change")
|
||||
@@ -55,7 +55,7 @@ func TestSaveHead_Different(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, cachedRoot, newRoot[:], "Head did not change")
|
||||
assert.DeepEqual(t, newHeadSignedBlock, service.headBlock(), "Head did not change")
|
||||
assert.DeepEqual(t, headState.CloneInnerState(), service.headState(ctx).CloneInnerState(), "Head did not change")
|
||||
assert.DeepSSZEqual(t, headState.CloneInnerState(), service.headState(ctx).CloneInnerState(), "Head did not change")
|
||||
}
|
||||
|
||||
func TestSaveHead_Different_Reorg(t *testing.T) {
|
||||
@@ -73,14 +73,14 @@ func TestSaveHead_Different_Reorg(t *testing.T) {
|
||||
newHeadSignedBlock.Block.ParentRoot = reorgChainParent[:]
|
||||
newHeadBlock := newHeadSignedBlock.Block
|
||||
|
||||
require.NoError(t, service.beaconDB.SaveBlock(context.Background(), newHeadSignedBlock))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveBlock(context.Background(), newHeadSignedBlock))
|
||||
newRoot, err := newHeadBlock.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
headState, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, headState.SetSlot(1))
|
||||
require.NoError(t, service.beaconDB.SaveStateSummary(context.Background(), &pb.StateSummary{Slot: 1, Root: newRoot[:]}))
|
||||
require.NoError(t, service.beaconDB.SaveState(context.Background(), headState, newRoot))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(context.Background(), &pb.StateSummary{Slot: 1, Root: newRoot[:]}))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveState(context.Background(), headState, newRoot))
|
||||
require.NoError(t, service.saveHead(context.Background(), newRoot))
|
||||
|
||||
assert.Equal(t, types.Slot(1), service.HeadSlot(), "Head did not change")
|
||||
@@ -91,7 +91,7 @@ func TestSaveHead_Different_Reorg(t *testing.T) {
|
||||
t.Error("Head did not change")
|
||||
}
|
||||
assert.DeepEqual(t, newHeadSignedBlock, service.headBlock(), "Head did not change")
|
||||
assert.DeepEqual(t, headState.CloneInnerState(), service.headState(ctx).CloneInnerState(), "Head did not change")
|
||||
assert.DeepSSZEqual(t, headState.CloneInnerState(), service.headState(ctx).CloneInnerState(), "Head did not change")
|
||||
require.LogsContain(t, hook, "Chain reorg occurred")
|
||||
}
|
||||
|
||||
@@ -101,8 +101,8 @@ func TestCacheJustifiedStateBalances_CanCache(t *testing.T) {
|
||||
|
||||
state, _ := testutil.DeterministicGenesisState(t, 100)
|
||||
r := [32]byte{'a'}
|
||||
require.NoError(t, service.beaconDB.SaveStateSummary(context.Background(), &pb.StateSummary{Root: r[:]}))
|
||||
require.NoError(t, service.beaconDB.SaveState(context.Background(), state, r))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(context.Background(), &pb.StateSummary{Root: r[:]}))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveState(context.Background(), state, r))
|
||||
require.NoError(t, service.cacheJustifiedStateBalances(context.Background(), r))
|
||||
require.DeepEqual(t, service.getJustifiedBalances(), state.Balances(), "Incorrect justified balances")
|
||||
}
|
||||
@@ -112,7 +112,7 @@ func TestUpdateHead_MissingJustifiedRoot(t *testing.T) {
|
||||
service := setupBeaconChain(t, beaconDB)
|
||||
|
||||
b := testutil.NewBeaconBlock()
|
||||
require.NoError(t, service.beaconDB.SaveBlock(context.Background(), b))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveBlock(context.Background(), b))
|
||||
r, err := b.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ func (s *Service) TreeHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
nodes := s.forkChoiceStore.Nodes()
|
||||
nodes := s.cfg.ForkChoiceStore.Nodes()
|
||||
|
||||
graph := dot.NewGraph(dot.Directed)
|
||||
graph.Attr("rankdir", "RL")
|
||||
|
||||
@@ -35,8 +35,8 @@ func TestService_TreeHandler(t *testing.T) {
|
||||
}
|
||||
s, err := NewService(ctx, cfg)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, s.forkChoiceStore.ProcessBlock(ctx, 0, [32]byte{'a'}, [32]byte{'g'}, [32]byte{'c'}, 0, 0))
|
||||
require.NoError(t, s.forkChoiceStore.ProcessBlock(ctx, 1, [32]byte{'b'}, [32]byte{'a'}, [32]byte{'c'}, 0, 0))
|
||||
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'}, testutil.NewBeaconBlock(), headState)
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
12
beacon-chain/blockchain/init_test.go
Normal file
12
beacon-chain/blockchain/init_test.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package blockchain
|
||||
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// Override network name so that hardcoded genesis files are not loaded.
|
||||
cfg := params.BeaconConfig()
|
||||
cfg.ConfigName = "test"
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
}
|
||||
@@ -16,13 +16,23 @@ var log = logrus.WithField("prefix", "blockchain")
|
||||
|
||||
// logs state transition related data every slot.
|
||||
func logStateTransitionData(b *ethpb.BeaconBlock) {
|
||||
log.WithFields(logrus.Fields{
|
||||
"attestations": len(b.Body.Attestations),
|
||||
"deposits": len(b.Body.Deposits),
|
||||
"attesterSlashings": len(b.Body.AttesterSlashings),
|
||||
"proposerSlashings": len(b.Body.ProposerSlashings),
|
||||
"voluntaryExits": len(b.Body.VoluntaryExits),
|
||||
}).Info("Finished applying state transition")
|
||||
log := log.WithField("slot", b.Slot)
|
||||
if len(b.Body.Attestations) > 0 {
|
||||
log = log.WithField("attestations", len(b.Body.Attestations))
|
||||
}
|
||||
if len(b.Body.Deposits) > 0 {
|
||||
log = log.WithField("deposits", len(b.Body.Deposits))
|
||||
}
|
||||
if len(b.Body.AttesterSlashings) > 0 {
|
||||
log = log.WithField("attesterSlashings", len(b.Body.AttesterSlashings))
|
||||
}
|
||||
if len(b.Body.ProposerSlashings) > 0 {
|
||||
log = log.WithField("proposerSlashings", len(b.Body.ProposerSlashings))
|
||||
}
|
||||
if len(b.Body.VoluntaryExits) > 0 {
|
||||
log = log.WithField("voluntaryExits", len(b.Body.VoluntaryExits))
|
||||
}
|
||||
log.Info("Finished applying state transition")
|
||||
}
|
||||
|
||||
func logBlockSyncStatus(block *ethpb.BeaconBlock, blockRoot [32]byte, finalized *ethpb.Checkpoint, receivedTime time.Time, genesisTime uint64) error {
|
||||
@@ -30,15 +40,18 @@ func logBlockSyncStatus(block *ethpb.BeaconBlock, blockRoot [32]byte, finalized
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.WithFields(logrus.Fields{
|
||||
"slot": block.Slot,
|
||||
"slotInEpoch": block.Slot % params.BeaconConfig().SlotsPerEpoch,
|
||||
"block": fmt.Sprintf("0x%s...", hex.EncodeToString(blockRoot[:])[:8]),
|
||||
"epoch": helpers.SlotToEpoch(block.Slot),
|
||||
"finalizedEpoch": finalized.Epoch,
|
||||
"finalizedRoot": fmt.Sprintf("0x%s...", hex.EncodeToString(finalized.Root)[:8]),
|
||||
}).Info("Synced new block")
|
||||
log.WithFields(logrus.Fields{
|
||||
"slot": block.Slot,
|
||||
"slotInEpoch": block.Slot % params.BeaconConfig().SlotsPerEpoch,
|
||||
"block": fmt.Sprintf("0x%s...", hex.EncodeToString(blockRoot[:])[:8]),
|
||||
"epoch": helpers.SlotToEpoch(block.Slot),
|
||||
"finalizedEpoch": finalized.Epoch,
|
||||
"finalizedRoot": fmt.Sprintf("0x%s...", hex.EncodeToString(finalized.Root)[:8]),
|
||||
"sinceSlotStartTime": timeutils.Now().Sub(startTime),
|
||||
"chainServiceProcessedTime": timeutils.Now().Sub(receivedTime),
|
||||
}).Info("Synced new block")
|
||||
}).Debug("Sync new block times")
|
||||
return nil
|
||||
}
|
||||
|
||||
63
beacon-chain/blockchain/log_test.go
Normal file
63
beacon-chain/blockchain/log_test.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package blockchain
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
logTest "github.com/sirupsen/logrus/hooks/test"
|
||||
)
|
||||
|
||||
func Test_logStateTransitionData(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
b *ethpb.BeaconBlock
|
||||
want string
|
||||
}{
|
||||
{name: "empty block body",
|
||||
b: ðpb.BeaconBlock{Body: ðpb.BeaconBlockBody{}},
|
||||
want: "\"Finished applying state transition\" prefix=blockchain slot=0",
|
||||
},
|
||||
{name: "has attestation",
|
||||
b: ðpb.BeaconBlock{Body: ðpb.BeaconBlockBody{Attestations: []*ethpb.Attestation{{}}}},
|
||||
want: "\"Finished applying state transition\" attestations=1 prefix=blockchain slot=0",
|
||||
},
|
||||
{name: "has deposit",
|
||||
b: ðpb.BeaconBlock{Body: ðpb.BeaconBlockBody{
|
||||
Attestations: []*ethpb.Attestation{{}},
|
||||
Deposits: []*ethpb.Deposit{{}}}},
|
||||
want: "\"Finished applying state transition\" attestations=1 deposits=1 prefix=blockchain slot=0",
|
||||
},
|
||||
{name: "has attester slashing",
|
||||
b: ðpb.BeaconBlock{Body: ðpb.BeaconBlockBody{
|
||||
AttesterSlashings: []*ethpb.AttesterSlashing{{}}}},
|
||||
want: "\"Finished applying state transition\" attesterSlashings=1 prefix=blockchain slot=0",
|
||||
},
|
||||
{name: "has proposer slashing",
|
||||
b: ðpb.BeaconBlock{Body: ðpb.BeaconBlockBody{
|
||||
ProposerSlashings: []*ethpb.ProposerSlashing{{}}}},
|
||||
want: "\"Finished applying state transition\" prefix=blockchain proposerSlashings=1 slot=0",
|
||||
},
|
||||
{name: "has exit",
|
||||
b: ðpb.BeaconBlock{Body: ðpb.BeaconBlockBody{
|
||||
VoluntaryExits: []*ethpb.SignedVoluntaryExit{{}}}},
|
||||
want: "\"Finished applying state transition\" prefix=blockchain slot=0 voluntaryExits=1",
|
||||
},
|
||||
{name: "has everything",
|
||||
b: ðpb.BeaconBlock{Body: ðpb.BeaconBlockBody{
|
||||
Attestations: []*ethpb.Attestation{{}},
|
||||
Deposits: []*ethpb.Deposit{{}},
|
||||
AttesterSlashings: []*ethpb.AttesterSlashing{{}},
|
||||
ProposerSlashings: []*ethpb.ProposerSlashing{{}},
|
||||
VoluntaryExits: []*ethpb.SignedVoluntaryExit{{}}}},
|
||||
want: "\"Finished applying state transition\" attestations=1 attesterSlashings=1 deposits=1 prefix=blockchain proposerSlashings=1 slot=0 voluntaryExits=1",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
hook := logTest.NewGlobal()
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
logStateTransitionData(tt.b)
|
||||
require.LogsContain(t, hook, tt.want)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
@@ -120,7 +120,7 @@ func reportSlotMetrics(stateSlot, headSlot, clockSlot types.Slot, finalizedCheck
|
||||
}
|
||||
|
||||
// reportEpochMetrics reports epoch related metrics.
|
||||
func reportEpochMetrics(ctx context.Context, postState, headState *stateTrie.BeaconState) error {
|
||||
func reportEpochMetrics(ctx context.Context, postState, headState iface.BeaconState) error {
|
||||
currentEpoch := types.Epoch(postState.Slot() / params.BeaconConfig().SlotsPerEpoch)
|
||||
|
||||
// Validator instances
|
||||
@@ -140,7 +140,7 @@ func reportEpochMetrics(ctx context.Context, postState, headState *stateTrie.Bea
|
||||
slashingEffectiveBalance := uint64(0)
|
||||
|
||||
for i, validator := range postState.Validators() {
|
||||
bal, err := postState.BalanceAtIndex(uint64(i))
|
||||
bal, err := postState.BalanceAtIndex(types.ValidatorIndex(i))
|
||||
if err != nil {
|
||||
log.Errorf("Could not load validator balance: %v", err)
|
||||
continue
|
||||
|
||||
@@ -25,7 +25,7 @@ func TestReportEpochMetrics_BadAttestation(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
h, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, h.SetCurrentEpochAttestations([]*pb.PendingAttestation{{InclusionDelay: 0}}))
|
||||
require.NoError(t, h.AppendCurrentEpochAttestations(&pb.PendingAttestation{InclusionDelay: 0}))
|
||||
err = reportEpochMetrics(context.Background(), s, h)
|
||||
require.ErrorContains(t, "attestation with inclusion delay of 0", err)
|
||||
}
|
||||
@@ -36,7 +36,7 @@ func TestReportEpochMetrics_SlashedValidatorOutOfBound(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
v.Slashed = true
|
||||
require.NoError(t, h.UpdateValidatorAtIndex(0, v))
|
||||
require.NoError(t, h.SetCurrentEpochAttestations([]*pb.PendingAttestation{{InclusionDelay: 1, Data: testutil.HydrateAttestationData(ð.AttestationData{})}}))
|
||||
require.NoError(t, h.AppendCurrentEpochAttestations(&pb.PendingAttestation{InclusionDelay: 1, Data: testutil.HydrateAttestationData(ð.AttestationData{})}))
|
||||
err = reportEpochMetrics(context.Background(), h, h)
|
||||
require.ErrorContains(t, "slot 0 out of bounds", err)
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateV0"
|
||||
"github.com/prysmaticlabs/prysm/shared/attestationutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
@@ -46,7 +46,7 @@ func (s *Service) onAttestation(ctx context.Context, a *ethpb.Attestation) error
|
||||
if err := helpers.ValidateSlotTargetEpoch(a.Data); err != nil {
|
||||
return err
|
||||
}
|
||||
tgt := stateTrie.CopyCheckpoint(a.Data.Target)
|
||||
tgt := stateV0.CopyCheckpoint(a.Data.Target)
|
||||
|
||||
// Note that target root check is ignored here because it was performed in sync's validation pipeline:
|
||||
// validate_aggregate_proof.go and validate_beacon_attestation.go
|
||||
@@ -97,7 +97,7 @@ func (s *Service) onAttestation(ctx context.Context, a *ethpb.Attestation) error
|
||||
// We assume trusted attestation in this function has verified signature.
|
||||
|
||||
// Update forkchoice store with the new attestation for updating weight.
|
||||
s.forkChoiceStore.ProcessAttestation(ctx, indexedAtt.AttestingIndices, bytesutil.ToBytes32(a.Data.BeaconBlockRoot), a.Data.Target.Epoch)
|
||||
s.cfg.ForkChoiceStore.ProcessAttestation(ctx, indexedAtt.AttestingIndices, bytesutil.ToBytes32(a.Data.BeaconBlockRoot), a.Data.Target.Epoch)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/mputil"
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
)
|
||||
|
||||
// getAttPreState retrieves the att pre state by either from the cache or the DB.
|
||||
func (s *Service) getAttPreState(ctx context.Context, c *ethpb.Checkpoint) (*stateTrie.BeaconState, error) {
|
||||
func (s *Service) getAttPreState(ctx context.Context, c *ethpb.Checkpoint) (iface.BeaconState, error) {
|
||||
// Use a multilock to allow scoped holding of a mutex by a checkpoint root + epoch
|
||||
// allowing us to behave smarter in terms of how this function is used concurrently.
|
||||
epochKey := strconv.FormatUint(uint64(c.Epoch), 10 /* base 10 */)
|
||||
@@ -33,7 +33,7 @@ func (s *Service) getAttPreState(ctx context.Context, c *ethpb.Checkpoint) (*sta
|
||||
return cachedState, nil
|
||||
}
|
||||
|
||||
baseState, err := s.stateGen.StateByRoot(ctx, bytesutil.ToBytes32(c.Root))
|
||||
baseState, err := s.cfg.StateGen.StateByRoot(ctx, bytesutil.ToBytes32(c.Root))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get pre state for epoch %d", c.Epoch)
|
||||
}
|
||||
@@ -62,7 +62,7 @@ func (s *Service) getAttPreState(ctx context.Context, c *ethpb.Checkpoint) (*sta
|
||||
|
||||
// To avoid sharing the same state across checkpoint state cache and hot state cache,
|
||||
// we don't add the state to check point cache.
|
||||
has, err := s.stateGen.HasStateInCache(ctx, bytesutil.ToBytes32(c.Root))
|
||||
has, err := s.cfg.StateGen.HasStateInCache(ctx, bytesutil.ToBytes32(c.Root))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -93,7 +93,7 @@ func (s *Service) verifyAttTargetEpoch(_ context.Context, genesisTime, nowTime u
|
||||
// verifyBeaconBlock verifies beacon head block is known and not from the future.
|
||||
func (s *Service) verifyBeaconBlock(ctx context.Context, data *ethpb.AttestationData) error {
|
||||
r := bytesutil.ToBytes32(data.BeaconBlockRoot)
|
||||
b, err := s.beaconDB.Block(ctx, r)
|
||||
b, err := s.cfg.BeaconDB.Block(ctx, r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
@@ -51,7 +50,7 @@ func TestStore_OnAttestation_ErrorConditions(t *testing.T) {
|
||||
s, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, s.SetSlot(100*params.BeaconConfig().SlotsPerEpoch))
|
||||
require.NoError(t, service.beaconDB.SaveState(ctx, s, BlkWithStateBadAttRoot))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, s, BlkWithStateBadAttRoot))
|
||||
|
||||
BlkWithValidState := testutil.NewBeaconBlock()
|
||||
BlkWithValidState.Block.Slot = 2
|
||||
@@ -67,7 +66,7 @@ func TestStore_OnAttestation_ErrorConditions(t *testing.T) {
|
||||
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, service.beaconDB.SaveState(ctx, s, BlkWithValidStateRoot))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, s, BlkWithValidStateRoot))
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -147,8 +146,8 @@ func TestStore_OnAttestation_Ok(t *testing.T) {
|
||||
copied := genesisState.Copy()
|
||||
copied, err = state.ProcessSlots(ctx, copied, 1)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, service.beaconDB.SaveState(ctx, copied, tRoot))
|
||||
require.NoError(t, service.forkChoiceStore.ProcessBlock(ctx, 0, tRoot, tRoot, tRoot, 1, 1))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, copied, tRoot))
|
||||
require.NoError(t, service.cfg.ForkChoiceStore.ProcessBlock(ctx, 0, tRoot, tRoot, tRoot, 1, 1))
|
||||
require.NoError(t, service.onAttestation(ctx, att[0]))
|
||||
}
|
||||
|
||||
@@ -176,7 +175,7 @@ func TestStore_SaveCheckpointState(t *testing.T) {
|
||||
err = s.SetBalances([]uint64{0})
|
||||
require.NoError(t, err)
|
||||
r := [32]byte{'g'}
|
||||
require.NoError(t, service.beaconDB.SaveState(ctx, s, r))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, s, r))
|
||||
|
||||
service.justifiedCheckpt = ðpb.Checkpoint{Root: r[:]}
|
||||
service.bestJustifiedCheckpt = ðpb.Checkpoint{Root: r[:]}
|
||||
@@ -185,16 +184,16 @@ func TestStore_SaveCheckpointState(t *testing.T) {
|
||||
|
||||
r = bytesutil.ToBytes32([]byte{'A'})
|
||||
cp1 := ðpb.Checkpoint{Epoch: 1, Root: bytesutil.PadTo([]byte{'A'}, 32)}
|
||||
require.NoError(t, service.beaconDB.SaveState(ctx, s, bytesutil.ToBytes32([]byte{'A'})))
|
||||
require.NoError(t, service.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{Root: bytesutil.PadTo([]byte{'A'}, 32)}))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, s, bytesutil.ToBytes32([]byte{'A'})))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &pb.StateSummary{Root: bytesutil.PadTo([]byte{'A'}, 32)}))
|
||||
|
||||
s1, err := service.getAttPreState(ctx, cp1)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1*params.BeaconConfig().SlotsPerEpoch, s1.Slot(), "Unexpected state slot")
|
||||
|
||||
cp2 := ðpb.Checkpoint{Epoch: 2, Root: bytesutil.PadTo([]byte{'B'}, 32)}
|
||||
require.NoError(t, service.beaconDB.SaveState(ctx, s, bytesutil.ToBytes32([]byte{'B'})))
|
||||
require.NoError(t, service.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{Root: bytesutil.PadTo([]byte{'B'}, 32)}))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, s, bytesutil.ToBytes32([]byte{'B'})))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &pb.StateSummary{Root: bytesutil.PadTo([]byte{'B'}, 32)}))
|
||||
s2, err := service.getAttPreState(ctx, cp2)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 2*params.BeaconConfig().SlotsPerEpoch, s2.Slot(), "Unexpected state slot")
|
||||
@@ -217,8 +216,8 @@ func TestStore_SaveCheckpointState(t *testing.T) {
|
||||
service.finalizedCheckpt = ðpb.Checkpoint{Root: r[:]}
|
||||
service.prevFinalizedCheckpt = ðpb.Checkpoint{Root: r[:]}
|
||||
cp3 := ðpb.Checkpoint{Epoch: 1, Root: bytesutil.PadTo([]byte{'C'}, 32)}
|
||||
require.NoError(t, service.beaconDB.SaveState(ctx, s, bytesutil.ToBytes32([]byte{'C'})))
|
||||
require.NoError(t, service.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{Root: bytesutil.PadTo([]byte{'C'}, 32)}))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, s, bytesutil.ToBytes32([]byte{'C'})))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &pb.StateSummary{Root: bytesutil.PadTo([]byte{'C'}, 32)}))
|
||||
s3, err := service.getAttPreState(ctx, cp3)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, s.Slot(), s3.Slot(), "Unexpected state slot")
|
||||
@@ -238,7 +237,7 @@ func TestStore_UpdateCheckpointState(t *testing.T) {
|
||||
epoch := types.Epoch(1)
|
||||
baseState, _ := testutil.DeterministicGenesisState(t, 1)
|
||||
checkpoint := ðpb.Checkpoint{Epoch: epoch, Root: bytesutil.PadTo([]byte("hi"), 32)}
|
||||
require.NoError(t, service.beaconDB.SaveState(ctx, baseState, bytesutil.ToBytes32(checkpoint.Root)))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, baseState, bytesutil.ToBytes32(checkpoint.Root)))
|
||||
returned, err := service.getAttPreState(ctx, checkpoint)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, params.BeaconConfig().SlotsPerEpoch.Mul(uint64(checkpoint.Epoch)), returned.Slot(), "Incorrectly returned base state")
|
||||
@@ -249,7 +248,7 @@ func TestStore_UpdateCheckpointState(t *testing.T) {
|
||||
|
||||
epoch = 2
|
||||
newCheckpoint := ðpb.Checkpoint{Epoch: epoch, Root: bytesutil.PadTo([]byte("bye"), 32)}
|
||||
require.NoError(t, service.beaconDB.SaveState(ctx, baseState, bytesutil.ToBytes32(newCheckpoint.Root)))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, baseState, bytesutil.ToBytes32(newCheckpoint.Root)))
|
||||
returned, err = service.getAttPreState(ctx, newCheckpoint)
|
||||
require.NoError(t, err)
|
||||
s, err := helpers.StartSlot(newCheckpoint.Epoch)
|
||||
@@ -260,9 +259,7 @@ func TestStore_UpdateCheckpointState(t *testing.T) {
|
||||
|
||||
cached, err = service.checkpointStateCache.StateByCheckpoint(newCheckpoint)
|
||||
require.NoError(t, err)
|
||||
if !proto.Equal(returned.InnerStateUnsafe(), cached.InnerStateUnsafe()) {
|
||||
t.Error("Incorrectly cached base state")
|
||||
}
|
||||
require.DeepSSZEqual(t, returned.InnerStateUnsafe(), cached.InnerStateUnsafe())
|
||||
}
|
||||
|
||||
func TestAttEpoch_MatchPrevEpoch(t *testing.T) {
|
||||
@@ -324,7 +321,7 @@ func TestVerifyBeaconBlock_futureBlock(t *testing.T) {
|
||||
|
||||
b := testutil.NewBeaconBlock()
|
||||
b.Block.Slot = 2
|
||||
require.NoError(t, service.beaconDB.SaveBlock(ctx, b))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, b))
|
||||
r, err := b.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
d := ðpb.AttestationData{Slot: 1, BeaconBlockRoot: r[:]}
|
||||
@@ -342,7 +339,7 @@ func TestVerifyBeaconBlock_OK(t *testing.T) {
|
||||
|
||||
b := testutil.NewBeaconBlock()
|
||||
b.Block.Slot = 2
|
||||
require.NoError(t, service.beaconDB.SaveBlock(ctx, b))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, b))
|
||||
r, err := b.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
d := ðpb.AttestationData{Slot: 2, BeaconBlockRoot: r[:]}
|
||||
@@ -360,7 +357,7 @@ func TestVerifyFinalizedConsistency_InconsistentRoot(t *testing.T) {
|
||||
|
||||
b32 := testutil.NewBeaconBlock()
|
||||
b32.Block.Slot = 32
|
||||
require.NoError(t, service.beaconDB.SaveBlock(ctx, b32))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, b32))
|
||||
r32, err := b32.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -369,7 +366,7 @@ func TestVerifyFinalizedConsistency_InconsistentRoot(t *testing.T) {
|
||||
b33 := testutil.NewBeaconBlock()
|
||||
b33.Block.Slot = 33
|
||||
b33.Block.ParentRoot = r32[:]
|
||||
require.NoError(t, service.beaconDB.SaveBlock(ctx, b33))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, b33))
|
||||
r33, err := b33.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -387,7 +384,7 @@ func TestVerifyFinalizedConsistency_OK(t *testing.T) {
|
||||
|
||||
b32 := testutil.NewBeaconBlock()
|
||||
b32.Block.Slot = 32
|
||||
require.NoError(t, service.beaconDB.SaveBlock(ctx, b32))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, b32))
|
||||
r32, err := b32.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -396,7 +393,7 @@ func TestVerifyFinalizedConsistency_OK(t *testing.T) {
|
||||
b33 := testutil.NewBeaconBlock()
|
||||
b33.Block.Slot = 33
|
||||
b33.Block.ParentRoot = r32[:]
|
||||
require.NoError(t, service.beaconDB.SaveBlock(ctx, b33))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, b33))
|
||||
r33, err := b33.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -425,10 +422,10 @@ func TestVerifyFinalizedConsistency_IsCanonical(t *testing.T) {
|
||||
r33, err := b33.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, service.forkChoiceStore.ProcessBlock(ctx, b32.Block.Slot, r32, [32]byte{}, [32]byte{}, 0, 0))
|
||||
require.NoError(t, service.forkChoiceStore.ProcessBlock(ctx, b33.Block.Slot, r33, r32, [32]byte{}, 0, 0))
|
||||
require.NoError(t, service.cfg.ForkChoiceStore.ProcessBlock(ctx, b32.Block.Slot, r32, [32]byte{}, [32]byte{}, 0, 0))
|
||||
require.NoError(t, service.cfg.ForkChoiceStore.ProcessBlock(ctx, b33.Block.Slot, r33, r32, [32]byte{}, 0, 0))
|
||||
|
||||
_, err = service.forkChoiceStore.Head(ctx, 0, r32, []uint64{}, 0)
|
||||
_, err = service.cfg.ForkChoiceStore.Head(ctx, 0, r32, []uint64{}, 0)
|
||||
require.NoError(t, err)
|
||||
err = service.VerifyFinalizedConsistency(context.Background(), r33[:])
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/attestationutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/bls"
|
||||
@@ -51,7 +51,8 @@ var initialSyncBlockCacheSize = uint64(2 * params.BeaconConfig().SlotsPerEpoch)
|
||||
// assert get_ancestor(store, block.parent_root, finalized_slot) == store.finalized_checkpoint.root
|
||||
//
|
||||
// # Check the block is valid and compute the post-state
|
||||
// state = state_transition(pre_state, signed_block, True)
|
||||
// state = pre_state.copy()
|
||||
// state_transition(state, signed_block, True)
|
||||
// # Add new block to the store
|
||||
// store.blocks[hash_tree_root(block)] = block
|
||||
// # Add new state for this block to the store
|
||||
@@ -146,7 +147,7 @@ func (s *Service) onBlock(ctx context.Context, signed *ethpb.SignedBeaconBlock,
|
||||
}
|
||||
|
||||
// Send notification of the processed block to the state feed.
|
||||
s.stateNotifier.StateFeed().Send(&feed.Event{
|
||||
s.cfg.StateNotifier.StateFeed().Send(&feed.Event{
|
||||
Type: statefeed.BlockProcessed,
|
||||
Data: &statefeed.BlockProcessedData{
|
||||
Slot: signed.Block.Slot,
|
||||
@@ -163,7 +164,7 @@ func (s *Service) onBlock(ctx context.Context, signed *ethpb.SignedBeaconBlock,
|
||||
return err
|
||||
}
|
||||
fRoot := bytesutil.ToBytes32(postState.FinalizedCheckpoint().Root)
|
||||
if err := s.forkChoiceStore.Prune(ctx, fRoot); err != nil {
|
||||
if err := s.cfg.ForkChoiceStore.Prune(ctx, fRoot); err != nil {
|
||||
return errors.Wrap(err, "could not prune proto array fork choice nodes")
|
||||
}
|
||||
if !featureconfig.Get().UpdateHeadTimely {
|
||||
@@ -188,75 +189,6 @@ func (s *Service) onBlock(ctx context.Context, signed *ethpb.SignedBeaconBlock,
|
||||
return s.handleEpochBoundary(ctx, postState)
|
||||
}
|
||||
|
||||
// onBlockInitialSyncStateTransition is called when an initial sync block is received.
|
||||
// It runs state transition on the block and without fork choice and post operation pool processes.
|
||||
// The block's signing root should be computed before calling this method to avoid redundant
|
||||
// computation in this method and methods it calls into.
|
||||
func (s *Service) onBlockInitialSyncStateTransition(ctx context.Context, signed *ethpb.SignedBeaconBlock, blockRoot [32]byte) error {
|
||||
ctx, span := trace.StartSpan(ctx, "blockChain.onBlockInitialSyncStateTransition")
|
||||
defer span.End()
|
||||
|
||||
if signed == nil || signed.Block == nil {
|
||||
return errors.New("nil block")
|
||||
}
|
||||
|
||||
b := signed.Block
|
||||
|
||||
// Retrieve incoming block's pre state.
|
||||
if err := s.verifyBlkPreState(ctx, b); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
preState, err := s.stateGen.StateByRootInitialSync(ctx, bytesutil.ToBytes32(signed.Block.ParentRoot))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if preState == nil {
|
||||
return fmt.Errorf("nil pre state for slot %d", b.Slot)
|
||||
}
|
||||
|
||||
// Exit early if the pre state slot is higher than incoming block's slot.
|
||||
if preState.Slot() >= signed.Block.Slot {
|
||||
return nil
|
||||
}
|
||||
|
||||
postState, err := state.ExecuteStateTransition(ctx, preState, signed)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not execute state transition")
|
||||
}
|
||||
|
||||
if err := s.savePostStateInfo(ctx, blockRoot, signed, postState, true /* init sync */); err != nil {
|
||||
return err
|
||||
}
|
||||
// Save the latest block as head in cache.
|
||||
if err := s.saveHeadNoDB(ctx, signed, blockRoot, postState); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Rate limit how many blocks (2 epochs worth of blocks) a node keeps in the memory.
|
||||
if uint64(len(s.getInitSyncBlocks())) > initialSyncBlockCacheSize {
|
||||
if err := s.beaconDB.SaveBlocks(ctx, s.getInitSyncBlocks()); err != nil {
|
||||
return err
|
||||
}
|
||||
s.clearInitSyncBlocks()
|
||||
}
|
||||
|
||||
if postState.CurrentJustifiedCheckpoint().Epoch > s.justifiedCheckpt.Epoch {
|
||||
if err := s.updateJustifiedInitSync(ctx, postState.CurrentJustifiedCheckpoint()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Update finalized check point. Prune the block cache and helper caches on every new finalized epoch.
|
||||
if postState.FinalizedCheckpointEpoch() > s.finalizedCheckpt.Epoch {
|
||||
if err := s.updateFinalized(ctx, postState.FinalizedCheckpoint()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return s.handleEpochBoundary(ctx, postState)
|
||||
}
|
||||
|
||||
func (s *Service) onBlockBatch(ctx context.Context, blks []*ethpb.SignedBeaconBlock,
|
||||
blockRoots [][32]byte) ([]*ethpb.Checkpoint, []*ethpb.Checkpoint, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "blockChain.onBlockBatch")
|
||||
@@ -274,7 +206,7 @@ func (s *Service) onBlockBatch(ctx context.Context, blks []*ethpb.SignedBeaconBl
|
||||
if err := s.verifyBlkPreState(ctx, b); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
preState, err := s.stateGen.StateByRootInitialSync(ctx, bytesutil.ToBytes32(b.ParentRoot))
|
||||
preState, err := s.cfg.StateGen.StateByRootInitialSync(ctx, bytesutil.ToBytes32(b.ParentRoot))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -290,7 +222,7 @@ func (s *Service) onBlockBatch(ctx context.Context, blks []*ethpb.SignedBeaconBl
|
||||
Messages: [][32]byte{},
|
||||
}
|
||||
var set *bls.SignatureSet
|
||||
boundaries := make(map[[32]byte]*stateTrie.BeaconState)
|
||||
boundaries := make(map[[32]byte]iface.BeaconState)
|
||||
for i, b := range blks {
|
||||
set, preState, err = state.ExecuteStateTransitionNoVerifyAnySig(ctx, preState, b)
|
||||
if err != nil {
|
||||
@@ -315,14 +247,14 @@ func (s *Service) onBlockBatch(ctx context.Context, blks []*ethpb.SignedBeaconBl
|
||||
return nil, nil, errors.New("batch block signature verification failed")
|
||||
}
|
||||
for r, st := range boundaries {
|
||||
if err := s.stateGen.SaveState(ctx, r, st); err != nil {
|
||||
if err := s.cfg.StateGen.SaveState(ctx, r, st); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
// Also saves the last post state which to be used as pre state for the next batch.
|
||||
lastB := blks[len(blks)-1]
|
||||
lastBR := blockRoots[len(blockRoots)-1]
|
||||
if err := s.stateGen.SaveState(ctx, lastBR, preState); err != nil {
|
||||
if err := s.cfg.StateGen.SaveState(ctx, lastBR, preState); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := s.saveHeadNoDB(ctx, lastB, lastBR, preState); err != nil {
|
||||
@@ -341,7 +273,7 @@ func (s *Service) handleBlockAfterBatchVerify(ctx context.Context, signed *ethpb
|
||||
if err := s.insertBlockToForkChoiceStore(ctx, b, blockRoot, fCheckpoint, jCheckpoint); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{
|
||||
if err := s.cfg.BeaconDB.SaveStateSummary(ctx, &pb.StateSummary{
|
||||
Slot: signed.Block.Slot,
|
||||
Root: blockRoot[:],
|
||||
}); err != nil {
|
||||
@@ -350,7 +282,7 @@ func (s *Service) handleBlockAfterBatchVerify(ctx context.Context, signed *ethpb
|
||||
|
||||
// Rate limit how many blocks (2 epochs worth of blocks) a node keeps in the memory.
|
||||
if uint64(len(s.getInitSyncBlocks())) > initialSyncBlockCacheSize {
|
||||
if err := s.beaconDB.SaveBlocks(ctx, s.getInitSyncBlocks()); err != nil {
|
||||
if err := s.cfg.BeaconDB.SaveBlocks(ctx, s.getInitSyncBlocks()); err != nil {
|
||||
return err
|
||||
}
|
||||
s.clearInitSyncBlocks()
|
||||
@@ -372,7 +304,7 @@ func (s *Service) handleBlockAfterBatchVerify(ctx context.Context, signed *ethpb
|
||||
}
|
||||
|
||||
// Epoch boundary bookkeeping such as logging epoch summaries.
|
||||
func (s *Service) handleEpochBoundary(ctx context.Context, postState *stateTrie.BeaconState) error {
|
||||
func (s *Service) handleEpochBoundary(ctx context.Context, postState iface.BeaconState) error {
|
||||
if postState.Slot()+1 == s.nextEpochBoundarySlot {
|
||||
// Update caches for the next epoch at epoch boundary slot - 1.
|
||||
if err := helpers.UpdateCommitteeCache(postState, helpers.NextEpoch(postState)); err != nil {
|
||||
@@ -412,7 +344,7 @@ func (s *Service) handleEpochBoundary(ctx context.Context, postState *stateTrie.
|
||||
// This feeds in the block and block's attestations to fork choice store. It's allows fork choice store
|
||||
// to gain information on the most current chain.
|
||||
func (s *Service) insertBlockAndAttestationsToForkChoiceStore(ctx context.Context, blk *ethpb.BeaconBlock, root [32]byte,
|
||||
st *stateTrie.BeaconState) error {
|
||||
st iface.BeaconState) error {
|
||||
fCheckpoint := st.FinalizedCheckpoint()
|
||||
jCheckpoint := st.CurrentJustifiedCheckpoint()
|
||||
if err := s.insertBlockToForkChoiceStore(ctx, blk, root, fCheckpoint, jCheckpoint); err != nil {
|
||||
@@ -428,7 +360,7 @@ func (s *Service) insertBlockAndAttestationsToForkChoiceStore(ctx context.Contex
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.forkChoiceStore.ProcessAttestation(ctx, indices, bytesutil.ToBytes32(a.Data.BeaconBlockRoot), a.Data.Target.Epoch)
|
||||
s.cfg.ForkChoiceStore.ProcessAttestation(ctx, indices, bytesutil.ToBytes32(a.Data.BeaconBlockRoot), a.Data.Target.Epoch)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -439,7 +371,7 @@ func (s *Service) insertBlockToForkChoiceStore(ctx context.Context, blk *ethpb.B
|
||||
return err
|
||||
}
|
||||
// Feed in block to fork choice store.
|
||||
if err := s.forkChoiceStore.ProcessBlock(ctx,
|
||||
if err := s.cfg.ForkChoiceStore.ProcessBlock(ctx,
|
||||
blk.Slot, root, bytesutil.ToBytes32(blk.ParentRoot), bytesutil.ToBytes32(blk.Body.Graffiti),
|
||||
jCheckpoint.Epoch,
|
||||
fCheckpoint.Epoch); err != nil {
|
||||
@@ -450,15 +382,15 @@ func (s *Service) insertBlockToForkChoiceStore(ctx context.Context, blk *ethpb.B
|
||||
|
||||
// This saves post state info to DB or cache. This also saves post state info to fork choice store.
|
||||
// Post state info consists of processed block and state. Do not call this method unless the block and state are verified.
|
||||
func (s *Service) savePostStateInfo(ctx context.Context, r [32]byte, b *ethpb.SignedBeaconBlock, st *stateTrie.BeaconState, initSync bool) error {
|
||||
func (s *Service) savePostStateInfo(ctx context.Context, r [32]byte, b *ethpb.SignedBeaconBlock, st iface.BeaconState, initSync bool) error {
|
||||
ctx, span := trace.StartSpan(ctx, "blockChain.savePostStateInfo")
|
||||
defer span.End()
|
||||
if initSync {
|
||||
s.saveInitSyncBlock(r, b)
|
||||
} else if err := s.beaconDB.SaveBlock(ctx, b); err != nil {
|
||||
} else if err := s.cfg.BeaconDB.SaveBlock(ctx, b); err != nil {
|
||||
return errors.Wrapf(err, "could not save block from slot %d", b.Block.Slot)
|
||||
}
|
||||
if err := s.stateGen.SaveState(ctx, r, st); err != nil {
|
||||
if err := s.cfg.StateGen.SaveState(ctx, r, st); err != nil {
|
||||
return errors.Wrap(err, "could not save state")
|
||||
}
|
||||
if err := s.insertBlockAndAttestationsToForkChoiceStore(ctx, b.Block, r, st); err != nil {
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
|
||||
"github.com/prysmaticlabs/prysm/shared/attestationutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
@@ -26,7 +26,7 @@ func (s *Service) CurrentSlot() types.Slot {
|
||||
// getBlockPreState returns the pre state of an incoming block. It uses the parent root of the block
|
||||
// to retrieve the state in DB. It verifies the pre state's validity and the incoming block
|
||||
// is in the correct time window.
|
||||
func (s *Service) getBlockPreState(ctx context.Context, b *ethpb.BeaconBlock) (*stateTrie.BeaconState, error) {
|
||||
func (s *Service) getBlockPreState(ctx context.Context, b *ethpb.BeaconBlock) (iface.BeaconState, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "blockChain.getBlockPreState")
|
||||
defer span.End()
|
||||
|
||||
@@ -35,7 +35,7 @@ func (s *Service) getBlockPreState(ctx context.Context, b *ethpb.BeaconBlock) (*
|
||||
return nil, err
|
||||
}
|
||||
|
||||
preState, err := s.stateGen.StateByRoot(ctx, bytesutil.ToBytes32(b.ParentRoot))
|
||||
preState, err := s.cfg.StateGen.StateByRoot(ctx, bytesutil.ToBytes32(b.ParentRoot))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get pre state for slot %d", b.Slot)
|
||||
}
|
||||
@@ -65,7 +65,7 @@ func (s *Service) verifyBlkPreState(ctx context.Context, b *ethpb.BeaconBlock) e
|
||||
// Loosen the check to HasBlock because state summary gets saved in batches
|
||||
// during initial syncing. There's no risk given a state summary object is just a
|
||||
// a subset of the block object.
|
||||
if !s.beaconDB.HasStateSummary(ctx, parentRoot) && !s.beaconDB.HasBlock(ctx, parentRoot) {
|
||||
if !s.cfg.BeaconDB.HasStateSummary(ctx, parentRoot) && !s.cfg.BeaconDB.HasBlock(ctx, parentRoot) {
|
||||
return errors.New("could not reconstruct parent state")
|
||||
}
|
||||
|
||||
@@ -73,12 +73,12 @@ func (s *Service) verifyBlkPreState(ctx context.Context, b *ethpb.BeaconBlock) e
|
||||
return err
|
||||
}
|
||||
|
||||
has, err := s.stateGen.HasState(ctx, parentRoot)
|
||||
has, err := s.cfg.StateGen.HasState(ctx, parentRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !has {
|
||||
if err := s.beaconDB.SaveBlocks(ctx, s.getInitSyncBlocks()); err != nil {
|
||||
if err := s.cfg.BeaconDB.SaveBlocks(ctx, s.getInitSyncBlocks()); err != nil {
|
||||
return errors.Wrap(err, "could not save initial sync blocks")
|
||||
}
|
||||
s.clearInitSyncBlocks()
|
||||
@@ -92,7 +92,7 @@ func (s *Service) VerifyBlkDescendant(ctx context.Context, root [32]byte) error
|
||||
ctx, span := trace.StartSpan(ctx, "blockChain.VerifyBlkDescendant")
|
||||
defer span.End()
|
||||
fRoot := s.ensureRootNotZeros(bytesutil.ToBytes32(s.finalizedCheckpt.Root))
|
||||
finalizedBlkSigned, err := s.beaconDB.Block(ctx, fRoot)
|
||||
finalizedBlkSigned, err := s.cfg.BeaconDB.Block(ctx, fRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -145,7 +145,7 @@ func (s *Service) shouldUpdateCurrentJustified(ctx context.Context, newJustified
|
||||
if s.hasInitSyncBlock(justifiedRoot) {
|
||||
newJustifiedBlockSigned = s.getInitSyncBlock(justifiedRoot)
|
||||
} else {
|
||||
newJustifiedBlockSigned, err = s.beaconDB.Block(ctx, justifiedRoot)
|
||||
newJustifiedBlockSigned, err = s.cfg.BeaconDB.Block(ctx, justifiedRoot)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -167,7 +167,7 @@ func (s *Service) shouldUpdateCurrentJustified(ctx context.Context, newJustified
|
||||
if s.hasInitSyncBlock(cachedJustifiedRoot) {
|
||||
justifiedBlockSigned = s.getInitSyncBlock(cachedJustifiedRoot)
|
||||
} else {
|
||||
justifiedBlockSigned, err = s.beaconDB.Block(ctx, cachedJustifiedRoot)
|
||||
justifiedBlockSigned, err = s.cfg.BeaconDB.Block(ctx, cachedJustifiedRoot)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -187,7 +187,7 @@ func (s *Service) shouldUpdateCurrentJustified(ctx context.Context, newJustified
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (s *Service) updateJustified(ctx context.Context, state *stateTrie.BeaconState) error {
|
||||
func (s *Service) updateJustified(ctx context.Context, state iface.ReadOnlyBeaconState) error {
|
||||
cpt := state.CurrentJustifiedCheckpoint()
|
||||
if cpt.Epoch > s.bestJustifiedCheckpt.Epoch {
|
||||
s.bestJustifiedCheckpt = cpt
|
||||
@@ -205,7 +205,7 @@ func (s *Service) updateJustified(ctx context.Context, state *stateTrie.BeaconSt
|
||||
}
|
||||
}
|
||||
|
||||
return s.beaconDB.SaveJustifiedCheckpoint(ctx, cpt)
|
||||
return s.cfg.BeaconDB.SaveJustifiedCheckpoint(ctx, cpt)
|
||||
}
|
||||
|
||||
// This caches input checkpoint as justified for the service struct. It rotates current justified to previous justified,
|
||||
@@ -218,18 +218,18 @@ func (s *Service) updateJustifiedInitSync(ctx context.Context, cp *ethpb.Checkpo
|
||||
return err
|
||||
}
|
||||
|
||||
return s.beaconDB.SaveJustifiedCheckpoint(ctx, cp)
|
||||
return s.cfg.BeaconDB.SaveJustifiedCheckpoint(ctx, cp)
|
||||
}
|
||||
|
||||
func (s *Service) updateFinalized(ctx context.Context, cp *ethpb.Checkpoint) error {
|
||||
// Blocks need to be saved so that we can retrieve finalized block from
|
||||
// DB when migrating states.
|
||||
if err := s.beaconDB.SaveBlocks(ctx, s.getInitSyncBlocks()); err != nil {
|
||||
if err := s.cfg.BeaconDB.SaveBlocks(ctx, s.getInitSyncBlocks()); err != nil {
|
||||
return err
|
||||
}
|
||||
s.clearInitSyncBlocks()
|
||||
|
||||
if err := s.beaconDB.SaveFinalizedCheckpoint(ctx, cp); err != nil {
|
||||
if err := s.cfg.BeaconDB.SaveFinalizedCheckpoint(ctx, cp); err != nil {
|
||||
return err
|
||||
}
|
||||
if !featureconfig.Get().UpdateHeadTimely {
|
||||
@@ -238,7 +238,7 @@ func (s *Service) updateFinalized(ctx context.Context, cp *ethpb.Checkpoint) err
|
||||
}
|
||||
|
||||
fRoot := bytesutil.ToBytes32(cp.Root)
|
||||
if err := s.stateGen.MigrateToCold(ctx, fRoot); err != nil {
|
||||
if err := s.cfg.StateGen.MigrateToCold(ctx, fRoot); err != nil {
|
||||
return errors.Wrap(err, "could not migrate to cold")
|
||||
}
|
||||
|
||||
@@ -282,10 +282,10 @@ func (s *Service) ancestorByForkChoiceStore(ctx context.Context, r [32]byte, slo
|
||||
ctx, span := trace.StartSpan(ctx, "blockChain.ancestorByForkChoiceStore")
|
||||
defer span.End()
|
||||
|
||||
if !s.forkChoiceStore.HasParent(r) {
|
||||
if !s.cfg.ForkChoiceStore.HasParent(r) {
|
||||
return nil, errors.New("could not find root in fork choice store")
|
||||
}
|
||||
return s.forkChoiceStore.AncestorRoot(ctx, r, slot)
|
||||
return s.cfg.ForkChoiceStore.AncestorRoot(ctx, r, slot)
|
||||
}
|
||||
|
||||
// This retrieves an ancestor root using DB. The look up is recursively looking up DB. Slower than `ancestorByForkChoiceStore`.
|
||||
@@ -298,7 +298,7 @@ func (s *Service) ancestorByDB(ctx context.Context, r [32]byte, slot types.Slot)
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
|
||||
signed, err := s.beaconDB.Block(ctx, r)
|
||||
signed, err := s.cfg.BeaconDB.Block(ctx, r)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get ancestor block")
|
||||
}
|
||||
@@ -333,7 +333,7 @@ func (s *Service) ancestorByDB(ctx context.Context, r [32]byte, slot types.Slot)
|
||||
// ancestor_at_finalized_slot = get_ancestor(store, store.justified_checkpoint.root, finalized_slot)
|
||||
// if ancestor_at_finalized_slot != store.finalized_checkpoint.root:
|
||||
// store.justified_checkpoint = state.current_justified_checkpoint
|
||||
func (s *Service) finalizedImpliesNewJustified(ctx context.Context, state *stateTrie.BeaconState) error {
|
||||
func (s *Service) finalizedImpliesNewJustified(ctx context.Context, state iface.BeaconState) error {
|
||||
// Update justified if it's different than the one cached in the store.
|
||||
if !attestationutil.CheckPointIsEqual(s.justifiedCheckpt, state.CurrentJustifiedCheckpoint()) {
|
||||
if state.CurrentJustifiedCheckpoint().Epoch > s.justifiedCheckpt.Epoch {
|
||||
@@ -377,8 +377,8 @@ func (s *Service) fillInForkChoiceMissingBlocks(ctx context.Context, blk *ethpb.
|
||||
}
|
||||
higherThanFinalized := slot > fSlot
|
||||
// As long as parent node is not in fork choice store, and parent node is in DB.
|
||||
for !s.forkChoiceStore.HasNode(parentRoot) && s.beaconDB.HasBlock(ctx, parentRoot) && higherThanFinalized {
|
||||
b, err := s.beaconDB.Block(ctx, parentRoot)
|
||||
for !s.cfg.ForkChoiceStore.HasNode(parentRoot) && s.cfg.BeaconDB.HasBlock(ctx, parentRoot) && higherThanFinalized {
|
||||
b, err := s.cfg.BeaconDB.Block(ctx, parentRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -396,7 +396,7 @@ func (s *Service) fillInForkChoiceMissingBlocks(ctx context.Context, blk *ethpb.
|
||||
for i := len(pendingNodes) - 1; i >= 0; i-- {
|
||||
b := pendingNodes[i]
|
||||
r := pendingRoots[i]
|
||||
if err := s.forkChoiceStore.ProcessBlock(ctx,
|
||||
if err := s.cfg.ForkChoiceStore.ProcessBlock(ctx,
|
||||
b.Slot, r, bytesutil.ToBytes32(b.ParentRoot), bytesutil.ToBytes32(b.Body.Graffiti),
|
||||
jCheckpoint.Epoch,
|
||||
fCheckpoint.Epoch); err != nil {
|
||||
@@ -413,7 +413,7 @@ func (s *Service) insertFinalizedDeposits(ctx context.Context, fRoot [32]byte) e
|
||||
defer span.End()
|
||||
|
||||
// Update deposit cache.
|
||||
finalizedState, err := s.stateGen.StateByRoot(ctx, fRoot)
|
||||
finalizedState, err := s.cfg.StateGen.StateByRoot(ctx, fRoot)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not fetch finalized state")
|
||||
}
|
||||
@@ -421,12 +421,10 @@ func (s *Service) insertFinalizedDeposits(ctx context.Context, fRoot [32]byte) e
|
||||
// We can be confident that these deposits will be included in some block
|
||||
// because the Eth1 follow distance makes such long-range reorgs extremely unlikely.
|
||||
eth1DepositIndex := int64(finalizedState.Eth1Data().DepositCount - 1)
|
||||
s.depositCache.InsertFinalizedDeposits(ctx, eth1DepositIndex)
|
||||
if featureconfig.Get().EnablePruningDepositProofs {
|
||||
// Deposit proofs are only used during state transition and can be safely removed to save space.
|
||||
if err = s.depositCache.PruneProofs(ctx, eth1DepositIndex); err != nil {
|
||||
return errors.Wrap(err, "could not prune deposit proofs")
|
||||
}
|
||||
s.cfg.DepositCache.InsertFinalizedDeposits(ctx, eth1DepositIndex)
|
||||
// Deposit proofs are only used during state transition and can be safely removed to save space.
|
||||
if err = s.cfg.DepositCache.PruneProofs(ctx, eth1DepositIndex); err != nil {
|
||||
return errors.Wrap(err, "could not prune deposit proofs")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -435,11 +433,11 @@ func (s *Service) insertFinalizedDeposits(ctx context.Context, fRoot [32]byte) e
|
||||
func (s *Service) deletePoolAtts(atts []*ethpb.Attestation) error {
|
||||
for _, att := range atts {
|
||||
if helpers.IsAggregated(att) {
|
||||
if err := s.attPool.DeleteAggregatedAttestation(att); err != nil {
|
||||
if err := s.cfg.AttPool.DeleteAggregatedAttestation(att); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := s.attPool.DeleteUnaggregatedAttestation(att); err != nil {
|
||||
if err := s.cfg.AttPool.DeleteUnaggregatedAttestation(att); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,12 +17,12 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db"
|
||||
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateV0"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/attestationutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
|
||||
@@ -48,7 +48,7 @@ func TestStore_OnBlock(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
st, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, service.beaconDB.SaveState(ctx, st.Copy(), validGenesisRoot))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, st.Copy(), validGenesisRoot))
|
||||
roots, err := blockTree1(t, beaconDB, validGenesisRoot[:])
|
||||
require.NoError(t, err)
|
||||
random := testutil.NewBeaconBlock()
|
||||
@@ -57,16 +57,16 @@ func TestStore_OnBlock(t *testing.T) {
|
||||
assert.NoError(t, beaconDB.SaveBlock(ctx, random))
|
||||
randomParentRoot, err := random.Block.HashTreeRoot()
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, service.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{Slot: st.Slot(), Root: randomParentRoot[:]}))
|
||||
require.NoError(t, service.beaconDB.SaveState(ctx, st.Copy(), randomParentRoot))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &pb.StateSummary{Slot: st.Slot(), Root: randomParentRoot[:]}))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, st.Copy(), randomParentRoot))
|
||||
randomParentRoot2 := roots[1]
|
||||
require.NoError(t, service.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{Slot: st.Slot(), Root: randomParentRoot2}))
|
||||
require.NoError(t, service.beaconDB.SaveState(ctx, st.Copy(), bytesutil.ToBytes32(randomParentRoot2)))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &pb.StateSummary{Slot: st.Slot(), Root: randomParentRoot2}))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, st.Copy(), bytesutil.ToBytes32(randomParentRoot2)))
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
blk *ethpb.SignedBeaconBlock
|
||||
s *stateTrie.BeaconState
|
||||
s iface.BeaconState
|
||||
time uint64
|
||||
wantErrString string
|
||||
}{
|
||||
@@ -145,7 +145,7 @@ func TestStore_OnBlockBatch(t *testing.T) {
|
||||
service.finalizedCheckpt = ðpb.Checkpoint{
|
||||
Root: gRoot[:],
|
||||
}
|
||||
service.forkChoiceStore = protoarray.New(0, 0, [32]byte{})
|
||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{})
|
||||
service.saveInitSyncBlock(gRoot, genesis)
|
||||
|
||||
st, keys := testutil.DeterministicGenesisState(t, 64)
|
||||
@@ -154,7 +154,7 @@ func TestStore_OnBlockBatch(t *testing.T) {
|
||||
|
||||
var blks []*ethpb.SignedBeaconBlock
|
||||
var blkRoots [][32]byte
|
||||
var firstState *stateTrie.BeaconState
|
||||
var firstState iface.BeaconState
|
||||
for i := 1; i < 10; i++ {
|
||||
b, err := testutil.GenerateFullBlock(bState, keys, testutil.DefaultBlockGenConfig(), types.Slot(i))
|
||||
require.NoError(t, err)
|
||||
@@ -172,7 +172,7 @@ func TestStore_OnBlockBatch(t *testing.T) {
|
||||
|
||||
blks[0].Block.ParentRoot = gRoot[:]
|
||||
require.NoError(t, beaconDB.SaveBlock(context.Background(), blks[0]))
|
||||
require.NoError(t, service.stateGen.SaveState(ctx, blkRoots[0], firstState))
|
||||
require.NoError(t, service.cfg.StateGen.SaveState(ctx, blkRoots[0], firstState))
|
||||
_, _, err = service.onBlockBatch(ctx, blks[1:], blkRoots[1:])
|
||||
require.NoError(t, err)
|
||||
}
|
||||
@@ -200,8 +200,8 @@ func TestRemoveStateSinceLastFinalized_EmptyStartSlot(t *testing.T) {
|
||||
newJustifiedBlk.Block.ParentRoot = bytesutil.PadTo(lastJustifiedRoot[:], 32)
|
||||
newJustifiedRoot, err := newJustifiedBlk.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, service.beaconDB.SaveBlock(ctx, newJustifiedBlk))
|
||||
require.NoError(t, service.beaconDB.SaveBlock(ctx, lastJustifiedBlk))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, newJustifiedBlk))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, lastJustifiedBlk))
|
||||
|
||||
diff := params.BeaconConfig().SlotsPerEpoch.Sub(1).Mul(params.BeaconConfig().SecondsPerSlot)
|
||||
service.genesisTime = time.Unix(time.Now().Unix()-int64(diff), 0)
|
||||
@@ -228,8 +228,8 @@ func TestShouldUpdateJustified_ReturnFalse(t *testing.T) {
|
||||
newJustifiedBlk.Block.ParentRoot = bytesutil.PadTo(lastJustifiedRoot[:], 32)
|
||||
newJustifiedRoot, err := newJustifiedBlk.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, service.beaconDB.SaveBlock(ctx, newJustifiedBlk))
|
||||
require.NoError(t, service.beaconDB.SaveBlock(ctx, lastJustifiedBlk))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, newJustifiedBlk))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, lastJustifiedBlk))
|
||||
|
||||
diff := params.BeaconConfig().SlotsPerEpoch.Sub(1).Mul(params.BeaconConfig().SecondsPerSlot)
|
||||
service.genesisTime = time.Unix(time.Now().Unix()-int64(diff), 0)
|
||||
@@ -251,7 +251,7 @@ func TestCachedPreState_CanGetFromStateSummary(t *testing.T) {
|
||||
service, err := NewService(ctx, cfg)
|
||||
require.NoError(t, err)
|
||||
|
||||
s, err := stateTrie.InitializeFromProto(&pb.BeaconState{Slot: 1, GenesisValidatorsRoot: params.BeaconConfig().ZeroHash[:]})
|
||||
s, err := stateV0.InitializeFromProto(&pb.BeaconState{Slot: 1, GenesisValidatorsRoot: params.BeaconConfig().ZeroHash[:]})
|
||||
require.NoError(t, err)
|
||||
|
||||
genesisStateRoot := [32]byte{}
|
||||
@@ -262,14 +262,14 @@ func TestCachedPreState_CanGetFromStateSummary(t *testing.T) {
|
||||
service.finalizedCheckpt = ðpb.Checkpoint{
|
||||
Root: gRoot[:],
|
||||
}
|
||||
service.forkChoiceStore = protoarray.New(0, 0, [32]byte{})
|
||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{})
|
||||
service.saveInitSyncBlock(gRoot, genesis)
|
||||
|
||||
b := testutil.NewBeaconBlock()
|
||||
b.Block.Slot = 1
|
||||
b.Block.ParentRoot = gRoot[:]
|
||||
require.NoError(t, service.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{Slot: 1, Root: gRoot[:]}))
|
||||
require.NoError(t, service.stateGen.SaveState(ctx, gRoot, s))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &pb.StateSummary{Slot: 1, Root: gRoot[:]}))
|
||||
require.NoError(t, service.cfg.StateGen.SaveState(ctx, gRoot, s))
|
||||
require.NoError(t, service.verifyBlkPreState(ctx, b.Block))
|
||||
}
|
||||
|
||||
@@ -292,7 +292,7 @@ func TestCachedPreState_CanGetFromDB(t *testing.T) {
|
||||
service.finalizedCheckpt = ðpb.Checkpoint{
|
||||
Root: gRoot[:],
|
||||
}
|
||||
service.forkChoiceStore = protoarray.New(0, 0, [32]byte{})
|
||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{})
|
||||
service.saveInitSyncBlock(gRoot, genesis)
|
||||
|
||||
b := testutil.NewBeaconBlock()
|
||||
@@ -303,10 +303,10 @@ func TestCachedPreState_CanGetFromDB(t *testing.T) {
|
||||
assert.ErrorContains(t, wanted, err)
|
||||
|
||||
b.Block.ParentRoot = gRoot[:]
|
||||
s, err := stateTrie.InitializeFromProto(&pb.BeaconState{Slot: 1})
|
||||
s, err := stateV0.InitializeFromProto(&pb.BeaconState{Slot: 1})
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, service.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{Slot: 1, Root: gRoot[:]}))
|
||||
require.NoError(t, service.stateGen.SaveState(ctx, gRoot, s))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &pb.StateSummary{Slot: 1, Root: gRoot[:]}))
|
||||
require.NoError(t, service.cfg.StateGen.SaveState(ctx, gRoot, s))
|
||||
require.NoError(t, service.verifyBlkPreState(ctx, b.Block))
|
||||
}
|
||||
|
||||
@@ -350,7 +350,7 @@ func TestFillForkChoiceMissingBlocks_CanSave(t *testing.T) {
|
||||
cfg := &Config{BeaconDB: beaconDB}
|
||||
service, err := NewService(ctx, cfg)
|
||||
require.NoError(t, err)
|
||||
service.forkChoiceStore = protoarray.New(0, 0, [32]byte{'A'})
|
||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{'A'})
|
||||
service.finalizedCheckpt = ðpb.Checkpoint{Root: make([]byte, 32)}
|
||||
|
||||
genesisStateRoot := [32]byte{}
|
||||
@@ -361,7 +361,7 @@ func TestFillForkChoiceMissingBlocks_CanSave(t *testing.T) {
|
||||
st, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, service.beaconDB.SaveState(ctx, st.Copy(), validGenesisRoot))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, st.Copy(), validGenesisRoot))
|
||||
roots, err := blockTree1(t, beaconDB, validGenesisRoot[:])
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -375,10 +375,10 @@ func TestFillForkChoiceMissingBlocks_CanSave(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
// 5 nodes from the block tree 1. B0 - B3 - B4 - B6 - B8
|
||||
assert.Equal(t, 5, len(service.forkChoiceStore.Nodes()), "Miss match nodes")
|
||||
assert.Equal(t, true, service.forkChoiceStore.HasNode(bytesutil.ToBytes32(roots[4])), "Didn't save node")
|
||||
assert.Equal(t, true, service.forkChoiceStore.HasNode(bytesutil.ToBytes32(roots[6])), "Didn't save node")
|
||||
assert.Equal(t, true, service.forkChoiceStore.HasNode(bytesutil.ToBytes32(roots[8])), "Didn't save node")
|
||||
assert.Equal(t, 5, len(service.cfg.ForkChoiceStore.Nodes()), "Miss match nodes")
|
||||
assert.Equal(t, true, service.cfg.ForkChoiceStore.HasNode(bytesutil.ToBytes32(roots[4])), "Didn't save node")
|
||||
assert.Equal(t, true, service.cfg.ForkChoiceStore.HasNode(bytesutil.ToBytes32(roots[6])), "Didn't save node")
|
||||
assert.Equal(t, true, service.cfg.ForkChoiceStore.HasNode(bytesutil.ToBytes32(roots[8])), "Didn't save node")
|
||||
}
|
||||
|
||||
func TestFillForkChoiceMissingBlocks_RootsMatch(t *testing.T) {
|
||||
@@ -388,7 +388,7 @@ func TestFillForkChoiceMissingBlocks_RootsMatch(t *testing.T) {
|
||||
cfg := &Config{BeaconDB: beaconDB}
|
||||
service, err := NewService(ctx, cfg)
|
||||
require.NoError(t, err)
|
||||
service.forkChoiceStore = protoarray.New(0, 0, [32]byte{'A'})
|
||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{'A'})
|
||||
service.finalizedCheckpt = ðpb.Checkpoint{Root: make([]byte, 32)}
|
||||
|
||||
genesisStateRoot := [32]byte{}
|
||||
@@ -399,7 +399,7 @@ func TestFillForkChoiceMissingBlocks_RootsMatch(t *testing.T) {
|
||||
st, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, service.beaconDB.SaveState(ctx, st.Copy(), validGenesisRoot))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, st.Copy(), validGenesisRoot))
|
||||
roots, err := blockTree1(t, beaconDB, validGenesisRoot[:])
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -413,12 +413,12 @@ func TestFillForkChoiceMissingBlocks_RootsMatch(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
// 5 nodes from the block tree 1. B0 - B3 - B4 - B6 - B8
|
||||
assert.Equal(t, 5, len(service.forkChoiceStore.Nodes()), "Miss match nodes")
|
||||
assert.Equal(t, 5, len(service.cfg.ForkChoiceStore.Nodes()), "Miss match nodes")
|
||||
// Ensure all roots and their respective blocks exist.
|
||||
wantedRoots := [][]byte{roots[0], roots[3], roots[4], roots[6], roots[8]}
|
||||
for i, rt := range wantedRoots {
|
||||
assert.Equal(t, true, service.forkChoiceStore.HasNode(bytesutil.ToBytes32(rt)), fmt.Sprintf("Didn't save node: %d", i))
|
||||
assert.Equal(t, true, service.beaconDB.HasBlock(context.Background(), bytesutil.ToBytes32(rt)))
|
||||
assert.Equal(t, true, service.cfg.ForkChoiceStore.HasNode(bytesutil.ToBytes32(rt)), fmt.Sprintf("Didn't save node: %d", i))
|
||||
assert.Equal(t, true, service.cfg.BeaconDB.HasBlock(context.Background(), bytesutil.ToBytes32(rt)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -429,7 +429,7 @@ func TestFillForkChoiceMissingBlocks_FilterFinalized(t *testing.T) {
|
||||
cfg := &Config{BeaconDB: beaconDB}
|
||||
service, err := NewService(ctx, cfg)
|
||||
require.NoError(t, err)
|
||||
service.forkChoiceStore = protoarray.New(0, 0, [32]byte{'A'})
|
||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0, [32]byte{'A'})
|
||||
// Set finalized epoch to 1.
|
||||
service.finalizedCheckpt = ðpb.Checkpoint{Epoch: 1}
|
||||
|
||||
@@ -441,24 +441,24 @@ func TestFillForkChoiceMissingBlocks_FilterFinalized(t *testing.T) {
|
||||
st, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, service.beaconDB.SaveState(ctx, st.Copy(), validGenesisRoot))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, st.Copy(), validGenesisRoot))
|
||||
|
||||
// Define a tree branch, slot 63 <- 64 <- 65
|
||||
b63 := testutil.NewBeaconBlock()
|
||||
b63.Block.Slot = 63
|
||||
require.NoError(t, service.beaconDB.SaveBlock(ctx, b63))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, b63))
|
||||
r63, err := b63.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
b64 := testutil.NewBeaconBlock()
|
||||
b64.Block.Slot = 64
|
||||
b64.Block.ParentRoot = r63[:]
|
||||
require.NoError(t, service.beaconDB.SaveBlock(ctx, b64))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, b64))
|
||||
r64, err := b64.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
b65 := testutil.NewBeaconBlock()
|
||||
b65.Block.Slot = 65
|
||||
b65.Block.ParentRoot = r64[:]
|
||||
require.NoError(t, service.beaconDB.SaveBlock(ctx, b65))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, b65))
|
||||
|
||||
beaconState, _ := testutil.DeterministicGenesisState(t, 32)
|
||||
err = service.fillInForkChoiceMissingBlocks(
|
||||
@@ -466,10 +466,10 @@ func TestFillForkChoiceMissingBlocks_FilterFinalized(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
// There should be 2 nodes, block 65 and block 64.
|
||||
assert.Equal(t, 2, len(service.forkChoiceStore.Nodes()), "Miss match nodes")
|
||||
assert.Equal(t, 2, len(service.cfg.ForkChoiceStore.Nodes()), "Miss match nodes")
|
||||
|
||||
// Block with slot 63 should be in fork choice because it's less than finalized epoch 1.
|
||||
assert.Equal(t, true, service.forkChoiceStore.HasNode(r63), "Didn't save node")
|
||||
assert.Equal(t, true, service.cfg.ForkChoiceStore.HasNode(r63), "Didn't save node")
|
||||
}
|
||||
|
||||
// blockTree1 constructs the following tree:
|
||||
@@ -649,7 +649,7 @@ func TestAncestor_CanUseForkchoice(t *testing.T) {
|
||||
beaconBlock.Block.ParentRoot = bytesutil.PadTo(b.Block.ParentRoot, 32)
|
||||
r, err := b.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, service.forkChoiceStore.ProcessBlock(context.Background(), b.Block.Slot, r, bytesutil.ToBytes32(b.Block.ParentRoot), [32]byte{}, 0, 0)) // Saves blocks to fork choice store.
|
||||
require.NoError(t, service.cfg.ForkChoiceStore.ProcessBlock(context.Background(), b.Block.Slot, r, bytesutil.ToBytes32(b.Block.ParentRoot), [32]byte{}, 0, 0)) // Saves blocks to fork choice store.
|
||||
}
|
||||
|
||||
r, err := service.ancestor(context.Background(), r200[:], 150)
|
||||
@@ -689,7 +689,7 @@ func TestAncestor_CanUseDB(t *testing.T) {
|
||||
require.NoError(t, beaconDB.SaveBlock(context.Background(), beaconBlock)) // Saves blocks to DB.
|
||||
}
|
||||
|
||||
require.NoError(t, service.forkChoiceStore.ProcessBlock(context.Background(), 200, r200, r200, [32]byte{}, 0, 0))
|
||||
require.NoError(t, service.cfg.ForkChoiceStore.ProcessBlock(context.Background(), 200, r200, r200, [32]byte{}, 0, 0))
|
||||
|
||||
r, err := service.ancestor(context.Background(), r200[:], 150)
|
||||
require.NoError(t, err)
|
||||
@@ -758,10 +758,10 @@ func TestFinalizedImpliesNewJustified(t *testing.T) {
|
||||
service, err := NewService(ctx, &Config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB), ForkChoiceStore: protoarray.New(0, 0, [32]byte{})})
|
||||
require.NoError(t, err)
|
||||
service.justifiedCheckpt = test.args.cachedCheckPoint
|
||||
require.NoError(t, service.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{Root: bytesutil.PadTo(test.want.Root, 32)}))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &pb.StateSummary{Root: bytesutil.PadTo(test.want.Root, 32)}))
|
||||
genesisState, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, service.beaconDB.SaveState(ctx, genesisState, bytesutil.ToBytes32(test.want.Root)))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, genesisState, bytesutil.ToBytes32(test.want.Root)))
|
||||
|
||||
if test.args.diffFinalizedCheckPoint {
|
||||
b1 := testutil.NewBeaconBlock()
|
||||
@@ -778,7 +778,7 @@ func TestFinalizedImpliesNewJustified(t *testing.T) {
|
||||
beaconBlock := testutil.NewBeaconBlock()
|
||||
beaconBlock.Block.Slot = b.Block.Slot
|
||||
beaconBlock.Block.ParentRoot = bytesutil.PadTo(b.Block.ParentRoot, 32)
|
||||
require.NoError(t, service.beaconDB.SaveBlock(context.Background(), beaconBlock))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveBlock(context.Background(), beaconBlock))
|
||||
}
|
||||
service.finalizedCheckpt = ðpb.Checkpoint{Root: []byte{'c'}, Epoch: 1}
|
||||
service.justifiedCheckpt.Root = r100[:]
|
||||
@@ -871,11 +871,11 @@ func TestUpdateJustifiedInitSync(t *testing.T) {
|
||||
gBlk := testutil.NewBeaconBlock()
|
||||
gRoot, err := gBlk.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, service.beaconDB.SaveBlock(ctx, gBlk))
|
||||
require.NoError(t, service.beaconDB.SaveGenesisBlockRoot(ctx, gRoot))
|
||||
require.NoError(t, service.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{Root: gRoot[:]}))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, gBlk))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveGenesisBlockRoot(ctx, gRoot))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, &pb.StateSummary{Root: gRoot[:]}))
|
||||
beaconState, _ := testutil.DeterministicGenesisState(t, 32)
|
||||
require.NoError(t, service.beaconDB.SaveState(ctx, beaconState, gRoot))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, beaconState, gRoot))
|
||||
service.genesisRoot = gRoot
|
||||
currentCp := ðpb.Checkpoint{Epoch: 1}
|
||||
service.justifiedCheckpt = currentCp
|
||||
@@ -885,7 +885,7 @@ func TestUpdateJustifiedInitSync(t *testing.T) {
|
||||
|
||||
assert.DeepSSZEqual(t, currentCp, service.prevJustifiedCheckpt, "Incorrect previous justified checkpoint")
|
||||
assert.DeepSSZEqual(t, newCp, service.CurrentJustifiedCheckpt(), "Incorrect current justified checkpoint in cache")
|
||||
cp, err := service.beaconDB.JustifiedCheckpoint(ctx)
|
||||
cp, err := service.cfg.BeaconDB.JustifiedCheckpoint(ctx)
|
||||
require.NoError(t, err)
|
||||
assert.DeepSSZEqual(t, newCp, cp, "Incorrect current justified checkpoint in db")
|
||||
}
|
||||
@@ -899,7 +899,8 @@ func TestHandleEpochBoundary_BadMetrics(t *testing.T) {
|
||||
s, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, s.SetSlot(1))
|
||||
service.head = &head{}
|
||||
service.head = &head{state: (*stateV0.BeaconState)(nil)}
|
||||
|
||||
require.ErrorContains(t, "failed to initialize precompute: nil inner state", service.handleEpochBoundary(ctx, s))
|
||||
}
|
||||
|
||||
@@ -932,7 +933,7 @@ func TestOnBlock_CanFinalize(t *testing.T) {
|
||||
|
||||
gs, keys := testutil.DeterministicGenesisState(t, 32)
|
||||
require.NoError(t, service.saveGenesisData(ctx, gs))
|
||||
gBlk, err := service.beaconDB.GenesisBlock(ctx)
|
||||
gBlk, err := service.cfg.BeaconDB.GenesisBlock(ctx)
|
||||
require.NoError(t, err)
|
||||
gRoot, err := gBlk.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
@@ -945,7 +946,7 @@ func TestOnBlock_CanFinalize(t *testing.T) {
|
||||
r, err := blk.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, service.onBlock(ctx, blk, r))
|
||||
testState, err = service.stateGen.StateByRoot(ctx, r)
|
||||
testState, err = service.cfg.StateGen.StateByRoot(ctx, r)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
require.Equal(t, types.Epoch(3), service.CurrentJustifiedCheckpt().Epoch)
|
||||
@@ -953,11 +954,6 @@ func TestOnBlock_CanFinalize(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestInsertFinalizedDeposits(t *testing.T) {
|
||||
flags := featureconfig.Get()
|
||||
flags.EnablePruningDepositProofs = true
|
||||
reset := featureconfig.InitWithReset(flags)
|
||||
defer reset()
|
||||
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
depositCache, err := depositcache.New()
|
||||
@@ -973,14 +969,14 @@ func TestInsertFinalizedDeposits(t *testing.T) {
|
||||
|
||||
gs, _ := testutil.DeterministicGenesisState(t, 32)
|
||||
require.NoError(t, service.saveGenesisData(ctx, gs))
|
||||
gBlk, err := service.beaconDB.GenesisBlock(ctx)
|
||||
gBlk, err := service.cfg.BeaconDB.GenesisBlock(ctx)
|
||||
require.NoError(t, err)
|
||||
gRoot, err := gBlk.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
service.finalizedCheckpt = ðpb.Checkpoint{Root: gRoot[:]}
|
||||
gs = gs.Copy()
|
||||
assert.NoError(t, gs.SetEth1Data(ðpb.Eth1Data{DepositCount: 10}))
|
||||
assert.NoError(t, service.stateGen.SaveState(ctx, [32]byte{'m', 'o', 'c', 'k'}, gs))
|
||||
assert.NoError(t, service.cfg.StateGen.SaveState(ctx, [32]byte{'m', 'o', 'c', 'k'}, gs))
|
||||
zeroSig := [96]byte{}
|
||||
for i := uint64(0); i < uint64(4*params.BeaconConfig().SlotsPerEpoch); i++ {
|
||||
root := []byte(strconv.Itoa(int(i)))
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/slotutil"
|
||||
@@ -21,7 +21,7 @@ import (
|
||||
// AttestationReceiver interface defines the methods of chain service receive and processing new attestations.
|
||||
type AttestationReceiver interface {
|
||||
ReceiveAttestationNoPubsub(ctx context.Context, att *ethpb.Attestation) error
|
||||
AttestationPreState(ctx context.Context, att *ethpb.Attestation) (*state.BeaconState, error)
|
||||
AttestationPreState(ctx context.Context, att *ethpb.Attestation) (iface.BeaconState, error)
|
||||
VerifyLmdFfgConsistency(ctx context.Context, att *ethpb.Attestation) error
|
||||
VerifyFinalizedConsistency(ctx context.Context, root []byte) error
|
||||
}
|
||||
@@ -43,7 +43,7 @@ func (s *Service) ReceiveAttestationNoPubsub(ctx context.Context, att *ethpb.Att
|
||||
}
|
||||
|
||||
// AttestationPreState returns the pre state of attestation.
|
||||
func (s *Service) AttestationPreState(ctx context.Context, att *ethpb.Attestation) (*state.BeaconState, error) {
|
||||
func (s *Service) AttestationPreState(ctx context.Context, att *ethpb.Attestation) (iface.BeaconState, error) {
|
||||
ss, err := helpers.StartSlot(att.Data.Target.Epoch)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -76,7 +76,7 @@ func (s *Service) VerifyLmdFfgConsistency(ctx context.Context, a *ethpb.Attestat
|
||||
func (s *Service) VerifyFinalizedConsistency(ctx context.Context, root []byte) error {
|
||||
// A canonical root implies the root to has an ancestor that aligns with finalized check point.
|
||||
// In this case, we could exit early to save on additional computation.
|
||||
if s.forkChoiceStore.IsCanonical(bytesutil.ToBytes32(root)) {
|
||||
if s.cfg.ForkChoiceStore.IsCanonical(bytesutil.ToBytes32(root)) {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -97,10 +97,10 @@ func (s *Service) VerifyFinalizedConsistency(ctx context.Context, root []byte) e
|
||||
}
|
||||
|
||||
// This routine processes fork choice attestations from the pool to account for validator votes and fork choice.
|
||||
func (s *Service) processAttestationsRoutine(subscribedToStateEvents chan struct{}) {
|
||||
func (s *Service) processAttestationsRoutine(subscribedToStateEvents chan<- struct{}) {
|
||||
// Wait for state to be initialized.
|
||||
stateChannel := make(chan *feed.Event, 1)
|
||||
stateSub := s.stateNotifier.StateFeed().Subscribe(stateChannel)
|
||||
stateSub := s.cfg.StateNotifier.StateFeed().Subscribe(stateChannel)
|
||||
subscribedToStateEvents <- struct{}{}
|
||||
<-stateChannel
|
||||
stateSub.Unsubscribe()
|
||||
@@ -121,7 +121,7 @@ func (s *Service) processAttestationsRoutine(subscribedToStateEvents chan struct
|
||||
case <-st.C():
|
||||
// Continue when there's no fork choice attestation, there's nothing to process and update head.
|
||||
// This covers the condition when the node is still initial syncing to the head of the chain.
|
||||
if s.attPool.ForkchoiceAttestationCount() == 0 {
|
||||
if s.cfg.AttPool.ForkchoiceAttestationCount() == 0 {
|
||||
continue
|
||||
}
|
||||
s.processAttestations(s.ctx)
|
||||
@@ -134,7 +134,7 @@ func (s *Service) processAttestationsRoutine(subscribedToStateEvents chan struct
|
||||
|
||||
// This processes fork choice attestations from the pool to account for validator votes and fork choice.
|
||||
func (s *Service) processAttestations(ctx context.Context) {
|
||||
atts := s.attPool.ForkchoiceAttestations()
|
||||
atts := s.cfg.AttPool.ForkchoiceAttestations()
|
||||
for _, a := range atts {
|
||||
// Based on the spec, don't process the attestation until the subsequent slot.
|
||||
// This delays consideration in the fork choice until their slot is in the past.
|
||||
@@ -144,13 +144,13 @@ func (s *Service) processAttestations(ctx context.Context) {
|
||||
continue
|
||||
}
|
||||
|
||||
hasState := s.beaconDB.HasStateSummary(ctx, bytesutil.ToBytes32(a.Data.BeaconBlockRoot))
|
||||
hasState := s.cfg.BeaconDB.HasStateSummary(ctx, bytesutil.ToBytes32(a.Data.BeaconBlockRoot))
|
||||
hasBlock := s.hasBlock(ctx, bytesutil.ToBytes32(a.Data.BeaconBlockRoot))
|
||||
if !(hasState && hasBlock) {
|
||||
continue
|
||||
}
|
||||
|
||||
if err := s.attPool.DeleteForkchoiceAttestation(a); err != nil {
|
||||
if err := s.cfg.AttPool.DeleteForkchoiceAttestation(a); err != nil {
|
||||
log.WithError(err).Error("Could not delete fork choice attestation in pool")
|
||||
}
|
||||
|
||||
|
||||
@@ -43,13 +43,13 @@ func TestVerifyLMDFFGConsistent_NotOK(t *testing.T) {
|
||||
|
||||
b32 := testutil.NewBeaconBlock()
|
||||
b32.Block.Slot = 32
|
||||
require.NoError(t, service.beaconDB.SaveBlock(ctx, b32))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, b32))
|
||||
r32, err := b32.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
b33 := testutil.NewBeaconBlock()
|
||||
b33.Block.Slot = 33
|
||||
b33.Block.ParentRoot = r32[:]
|
||||
require.NoError(t, service.beaconDB.SaveBlock(ctx, b33))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, b33))
|
||||
r33, err := b33.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -71,13 +71,13 @@ func TestVerifyLMDFFGConsistent_OK(t *testing.T) {
|
||||
|
||||
b32 := testutil.NewBeaconBlock()
|
||||
b32.Block.Slot = 32
|
||||
require.NoError(t, service.beaconDB.SaveBlock(ctx, b32))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, b32))
|
||||
r32, err := b32.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
b33 := testutil.NewBeaconBlock()
|
||||
b33.Block.Slot = 33
|
||||
b33.Block.ParentRoot = r32[:]
|
||||
require.NoError(t, service.beaconDB.SaveBlock(ctx, b33))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, b33))
|
||||
r33, err := b33.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -112,10 +112,10 @@ func TestProcessAttestations_Ok(t *testing.T) {
|
||||
copied := genesisState.Copy()
|
||||
copied, err = state.ProcessSlots(ctx, copied, 1)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, service.beaconDB.SaveState(ctx, copied, tRoot))
|
||||
require.NoError(t, service.forkChoiceStore.ProcessBlock(ctx, 0, tRoot, tRoot, tRoot, 1, 1))
|
||||
require.NoError(t, service.attPool.SaveForkchoiceAttestations(atts))
|
||||
require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, copied, tRoot))
|
||||
require.NoError(t, service.cfg.ForkChoiceStore.ProcessBlock(ctx, 0, tRoot, tRoot, tRoot, 1, 1))
|
||||
require.NoError(t, service.cfg.AttPool.SaveForkchoiceAttestations(atts))
|
||||
service.processAttestations(ctx)
|
||||
require.Equal(t, 0, len(service.attPool.ForkchoiceAttestations()))
|
||||
require.Equal(t, 0, len(service.cfg.AttPool.ForkchoiceAttestations()))
|
||||
require.LogsDoNotContain(t, hook, "Could not process attestation for fork choice")
|
||||
}
|
||||
|
||||
@@ -9,11 +9,10 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
|
||||
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateV0"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/timeutils"
|
||||
"github.com/prysmaticlabs/prysm/shared/traceutil"
|
||||
"github.com/sirupsen/logrus"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
@@ -23,7 +22,6 @@ var epochsSinceFinalitySaveHotStateDB = types.Epoch(100)
|
||||
// BlockReceiver interface defines the methods of chain service receive and processing new blocks.
|
||||
type BlockReceiver interface {
|
||||
ReceiveBlock(ctx context.Context, block *ethpb.SignedBeaconBlock, blockRoot [32]byte) error
|
||||
ReceiveBlockInitialSync(ctx context.Context, block *ethpb.SignedBeaconBlock, blockRoot [32]byte) error
|
||||
ReceiveBlockBatch(ctx context.Context, blocks []*ethpb.SignedBeaconBlock, blkRoots [][32]byte) error
|
||||
HasInitSyncBlock(root [32]byte) bool
|
||||
}
|
||||
@@ -37,7 +35,7 @@ func (s *Service) ReceiveBlock(ctx context.Context, block *ethpb.SignedBeaconBlo
|
||||
ctx, span := trace.StartSpan(ctx, "blockChain.ReceiveBlock")
|
||||
defer span.End()
|
||||
receivedTime := timeutils.Now()
|
||||
blockCopy := stateTrie.CopySignedBeaconBlock(block)
|
||||
blockCopy := stateV0.CopySignedBeaconBlock(block)
|
||||
|
||||
// Apply state transition on the new block.
|
||||
if err := s.onBlock(ctx, blockCopy, blockRoot); err != nil {
|
||||
@@ -52,7 +50,7 @@ func (s *Service) ReceiveBlock(ctx context.Context, block *ethpb.SignedBeaconBlo
|
||||
log.WithError(err).Warn("Could not update head")
|
||||
}
|
||||
// Send notification of the processed block to the state feed.
|
||||
s.stateNotifier.StateFeed().Send(&feed.Event{
|
||||
s.cfg.StateNotifier.StateFeed().Send(&feed.Event{
|
||||
Type: statefeed.BlockProcessed,
|
||||
Data: &statefeed.BlockProcessedData{
|
||||
Slot: blockCopy.Block.Slot,
|
||||
@@ -86,44 +84,6 @@ func (s *Service) ReceiveBlock(ctx context.Context, block *ethpb.SignedBeaconBlo
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReceiveBlockInitialSync processes the input block for the purpose of initial syncing.
|
||||
// This method should only be used on blocks during initial syncing phase.
|
||||
func (s *Service) ReceiveBlockInitialSync(ctx context.Context, block *ethpb.SignedBeaconBlock, blockRoot [32]byte) error {
|
||||
ctx, span := trace.StartSpan(ctx, "blockChain.ReceiveBlockNoVerify")
|
||||
defer span.End()
|
||||
blockCopy := stateTrie.CopySignedBeaconBlock(block)
|
||||
|
||||
// Apply state transition on the new block.
|
||||
if err := s.onBlockInitialSyncStateTransition(ctx, blockCopy, blockRoot); err != nil {
|
||||
err := errors.Wrap(err, "could not process block")
|
||||
traceutil.AnnotateError(span, err)
|
||||
return err
|
||||
}
|
||||
|
||||
// Send notification of the processed block to the state feed.
|
||||
s.stateNotifier.StateFeed().Send(&feed.Event{
|
||||
Type: statefeed.BlockProcessed,
|
||||
Data: &statefeed.BlockProcessedData{
|
||||
Slot: blockCopy.Block.Slot,
|
||||
BlockRoot: blockRoot,
|
||||
SignedBlock: blockCopy,
|
||||
Verified: true,
|
||||
},
|
||||
})
|
||||
|
||||
// Reports on blockCopy and fork choice metrics.
|
||||
reportSlotMetrics(blockCopy.Block.Slot, s.HeadSlot(), s.CurrentSlot(), s.finalizedCheckpt)
|
||||
|
||||
// Log state transition data.
|
||||
log.WithFields(logrus.Fields{
|
||||
"slot": blockCopy.Block.Slot,
|
||||
"attestations": len(blockCopy.Block.Body.Attestations),
|
||||
"deposits": len(blockCopy.Block.Body.Deposits),
|
||||
}).Debug("Finished applying state transition")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReceiveBlockBatch processes the whole block batch at once, assuming the block batch is linear ,transitioning
|
||||
// the state, performing batch verification of all collected signatures and then performing the appropriate
|
||||
// actions for a block post-transition.
|
||||
@@ -140,13 +100,13 @@ func (s *Service) ReceiveBlockBatch(ctx context.Context, blocks []*ethpb.SignedB
|
||||
}
|
||||
|
||||
for i, b := range blocks {
|
||||
blockCopy := stateTrie.CopySignedBeaconBlock(b)
|
||||
blockCopy := stateV0.CopySignedBeaconBlock(b)
|
||||
if err = s.handleBlockAfterBatchVerify(ctx, blockCopy, blkRoots[i], fCheckpoints[i], jCheckpoints[i]); err != nil {
|
||||
traceutil.AnnotateError(span, err)
|
||||
return err
|
||||
}
|
||||
// Send notification of the processed block to the state feed.
|
||||
s.stateNotifier.StateFeed().Send(&feed.Event{
|
||||
s.cfg.StateNotifier.StateFeed().Send(&feed.Event{
|
||||
Type: statefeed.BlockProcessed,
|
||||
Data: &statefeed.BlockProcessedData{
|
||||
Slot: blockCopy.Block.Slot,
|
||||
@@ -182,18 +142,18 @@ func (s *Service) handlePostBlockOperations(b *ethpb.BeaconBlock) error {
|
||||
}
|
||||
|
||||
// Add block attestations to the fork choice pool to compute head.
|
||||
if err := s.attPool.SaveBlockAttestations(b.Body.Attestations); err != nil {
|
||||
if err := s.cfg.AttPool.SaveBlockAttestations(b.Body.Attestations); err != nil {
|
||||
log.Errorf("Could not save block attestations for fork choice: %v", err)
|
||||
return nil
|
||||
}
|
||||
// Mark block exits as seen so we don't include same ones in future blocks.
|
||||
for _, e := range b.Body.VoluntaryExits {
|
||||
s.exitPool.MarkIncluded(e)
|
||||
s.cfg.ExitPool.MarkIncluded(e)
|
||||
}
|
||||
|
||||
// Mark attester slashings as seen so we don't include same ones in future blocks.
|
||||
for _, as := range b.Body.AttesterSlashings {
|
||||
s.slashingPool.MarkIncludedAttesterSlashing(as)
|
||||
s.cfg.SlashingPool.MarkIncludedAttesterSlashing(as)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -209,9 +169,9 @@ func (s *Service) checkSaveHotStateDB(ctx context.Context) error {
|
||||
}
|
||||
|
||||
if sinceFinality >= epochsSinceFinalitySaveHotStateDB {
|
||||
s.stateGen.EnableSaveHotStateToDB(ctx)
|
||||
s.cfg.StateGen.EnableSaveHotStateToDB(ctx)
|
||||
return nil
|
||||
}
|
||||
|
||||
return s.stateGen.DisableSaveHotStateToDB(ctx)
|
||||
return s.cfg.StateGen.DisableSaveHotStateToDB(ctx)
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ func TestService_ReceiveBlock(t *testing.T) {
|
||||
),
|
||||
},
|
||||
check: func(t *testing.T, s *Service) {
|
||||
if baCount := len(s.attPool.BlockAttestations()); baCount != 2 {
|
||||
if baCount := len(s.cfg.AttPool.BlockAttestations()); baCount != 2 {
|
||||
t.Errorf("Did not get the correct number of block attestations saved to the pool. "+
|
||||
"Got %d but wanted %d", baCount, 2)
|
||||
}
|
||||
@@ -93,7 +93,7 @@ func TestService_ReceiveBlock(t *testing.T) {
|
||||
),
|
||||
},
|
||||
check: func(t *testing.T, s *Service) {
|
||||
pending := s.exitPool.PendingExits(genesis, 1, true /* no limit */)
|
||||
pending := s.cfg.ExitPool.PendingExits(genesis, 1, true /* no limit */)
|
||||
if len(pending) != 0 {
|
||||
t.Errorf(
|
||||
"Did not mark the correct number of exits. Got %d pending but wanted %d",
|
||||
@@ -109,7 +109,7 @@ func TestService_ReceiveBlock(t *testing.T) {
|
||||
block: genFullBlock(t, testutil.DefaultBlockGenConfig(), 1 /*slot*/),
|
||||
},
|
||||
check: func(t *testing.T, s *Service) {
|
||||
if recvd := len(s.stateNotifier.(*blockchainTesting.MockStateNotifier).ReceivedEvents()); recvd < 1 {
|
||||
if recvd := len(s.cfg.StateNotifier.(*blockchainTesting.MockStateNotifier).ReceivedEvents()); recvd < 1 {
|
||||
t.Errorf("Received %d state notifications, expected at least 1", recvd)
|
||||
}
|
||||
},
|
||||
@@ -137,7 +137,7 @@ func TestService_ReceiveBlock(t *testing.T) {
|
||||
s, err := NewService(ctx, cfg)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, s.saveGenesisData(ctx, genesis))
|
||||
gBlk, err := s.beaconDB.GenesisBlock(ctx)
|
||||
gBlk, err := s.cfg.BeaconDB.GenesisBlock(ctx)
|
||||
require.NoError(t, err)
|
||||
gRoot, err := gBlk.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
@@ -178,7 +178,7 @@ func TestService_ReceiveBlockUpdateHead(t *testing.T) {
|
||||
s, err := NewService(ctx, cfg)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, s.saveGenesisData(ctx, genesis))
|
||||
gBlk, err := s.beaconDB.GenesisBlock(ctx)
|
||||
gBlk, err := s.cfg.BeaconDB.GenesisBlock(ctx)
|
||||
require.NoError(t, err)
|
||||
gRoot, err := gBlk.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
@@ -192,92 +192,11 @@ func TestService_ReceiveBlockUpdateHead(t *testing.T) {
|
||||
wg.Done()
|
||||
}()
|
||||
wg.Wait()
|
||||
if recvd := len(s.stateNotifier.(*blockchainTesting.MockStateNotifier).ReceivedEvents()); recvd < 1 {
|
||||
if recvd := len(s.cfg.StateNotifier.(*blockchainTesting.MockStateNotifier).ReceivedEvents()); recvd < 1 {
|
||||
t.Errorf("Received %d state notifications, expected at least 1", recvd)
|
||||
}
|
||||
// Verify fork choice has processed the block. (Genesis block and the new block)
|
||||
assert.Equal(t, 2, len(s.forkChoiceStore.Nodes()))
|
||||
}
|
||||
|
||||
func TestService_ReceiveBlockInitialSync(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
genesis, keys := testutil.DeterministicGenesisState(t, 64)
|
||||
genFullBlock := func(t *testing.T, conf *testutil.BlockGenConfig, slot types.Slot) *ethpb.SignedBeaconBlock {
|
||||
blk, err := testutil.GenerateFullBlock(genesis, keys, conf, slot)
|
||||
assert.NoError(t, err)
|
||||
return blk
|
||||
}
|
||||
|
||||
type args struct {
|
||||
block *ethpb.SignedBeaconBlock
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantedErr string
|
||||
check func(*testing.T, *Service)
|
||||
}{
|
||||
{
|
||||
name: "applies block with state transition",
|
||||
args: args{
|
||||
block: genFullBlock(t, testutil.DefaultBlockGenConfig(), 2 /*slot*/),
|
||||
},
|
||||
check: func(t *testing.T, s *Service) {
|
||||
assert.Equal(t, types.Slot(2), s.head.state.Slot(), "Incorrect head state slot")
|
||||
assert.Equal(t, types.Slot(2), s.head.block.Block.Slot, "Incorrect head block slot")
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "notifies block processed on state feed",
|
||||
args: args{
|
||||
block: genFullBlock(t, testutil.DefaultBlockGenConfig(), 1 /*slot*/),
|
||||
},
|
||||
check: func(t *testing.T, s *Service) {
|
||||
if recvd := len(s.stateNotifier.(*blockchainTesting.MockStateNotifier).ReceivedEvents()); recvd < 1 {
|
||||
t.Errorf("Received %d state notifications, expected at least 1", recvd)
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
genesisBlockRoot := bytesutil.ToBytes32(nil)
|
||||
|
||||
cfg := &Config{
|
||||
BeaconDB: beaconDB,
|
||||
ForkChoiceStore: protoarray.New(
|
||||
0, // justifiedEpoch
|
||||
0, // finalizedEpoch
|
||||
genesisBlockRoot,
|
||||
),
|
||||
StateNotifier: &blockchainTesting.MockStateNotifier{RecordEvents: true},
|
||||
StateGen: stategen.New(beaconDB),
|
||||
}
|
||||
s, err := NewService(ctx, cfg)
|
||||
require.NoError(t, err)
|
||||
err = s.saveGenesisData(ctx, genesis)
|
||||
require.NoError(t, err)
|
||||
gBlk, err := s.beaconDB.GenesisBlock(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
gRoot, err := gBlk.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
s.finalizedCheckpt = ðpb.Checkpoint{Root: gRoot[:]}
|
||||
root, err := tt.args.block.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
err = s.ReceiveBlockInitialSync(ctx, tt.args.block, root)
|
||||
if tt.wantedErr != "" {
|
||||
assert.ErrorContains(t, tt.wantedErr, err)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
tt.check(t, s)
|
||||
}
|
||||
})
|
||||
}
|
||||
assert.Equal(t, 2, len(s.cfg.ForkChoiceStore.Nodes()))
|
||||
}
|
||||
|
||||
func TestService_ReceiveBlockBatch(t *testing.T) {
|
||||
@@ -315,7 +234,7 @@ func TestService_ReceiveBlockBatch(t *testing.T) {
|
||||
block: genFullBlock(t, testutil.DefaultBlockGenConfig(), 1 /*slot*/),
|
||||
},
|
||||
check: func(t *testing.T, s *Service) {
|
||||
if recvd := len(s.stateNotifier.(*blockchainTesting.MockStateNotifier).ReceivedEvents()); recvd < 1 {
|
||||
if recvd := len(s.cfg.StateNotifier.(*blockchainTesting.MockStateNotifier).ReceivedEvents()); recvd < 1 {
|
||||
t.Errorf("Received %d state notifications, expected at least 1", recvd)
|
||||
}
|
||||
},
|
||||
@@ -341,7 +260,7 @@ func TestService_ReceiveBlockBatch(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
err = s.saveGenesisData(ctx, genesis)
|
||||
require.NoError(t, err)
|
||||
gBlk, err := s.beaconDB.GenesisBlock(ctx)
|
||||
gBlk, err := s.cfg.BeaconDB.GenesisBlock(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
gRoot, err := gBlk.Block.HashTreeRoot()
|
||||
|
||||
@@ -15,13 +15,11 @@ import (
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
|
||||
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/flags"
|
||||
f "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/attestations"
|
||||
@@ -29,9 +27,10 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateV0"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/cmd/beacon-chain/flags"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/slotutil"
|
||||
@@ -46,22 +45,13 @@ const headSyncMinEpochsAfterCheckpoint = 128
|
||||
// Service represents a service that handles the internal
|
||||
// logic of managing the full PoS beacon chain.
|
||||
type Service struct {
|
||||
cfg *Config
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
beaconDB db.HeadAccessDatabase
|
||||
depositCache *depositcache.DepositCache
|
||||
chainStartFetcher powchain.ChainStartFetcher
|
||||
attPool attestations.Pool
|
||||
slashingPool *slashings.Pool
|
||||
exitPool *voluntaryexits.Pool
|
||||
genesisTime time.Time
|
||||
p2p p2p.Broadcaster
|
||||
maxRoutines int
|
||||
head *head
|
||||
headLock sync.RWMutex
|
||||
stateNotifier statefeed.Notifier
|
||||
genesisRoot [32]byte
|
||||
forkChoiceStore f.ForkChoicer
|
||||
justifiedCheckpt *ethpb.Checkpoint
|
||||
prevJustifiedCheckpt *ethpb.Checkpoint
|
||||
bestJustifiedCheckpt *ethpb.Checkpoint
|
||||
@@ -70,34 +60,29 @@ type Service struct {
|
||||
nextEpochBoundarySlot types.Slot
|
||||
boundaryRoots [][32]byte
|
||||
checkpointStateCache *cache.CheckpointStateCache
|
||||
stateGen *stategen.State
|
||||
opsService *attestations.Service
|
||||
initSyncBlocks map[[32]byte]*ethpb.SignedBeaconBlock
|
||||
initSyncBlocksLock sync.RWMutex
|
||||
justifiedBalances []uint64
|
||||
justifiedBalancesLock sync.RWMutex
|
||||
wsEpoch types.Epoch
|
||||
wsRoot []byte
|
||||
wsVerified bool
|
||||
}
|
||||
|
||||
// Config options for the service.
|
||||
type Config struct {
|
||||
BeaconBlockBuf int
|
||||
ChainStartFetcher powchain.ChainStartFetcher
|
||||
BeaconDB db.HeadAccessDatabase
|
||||
DepositCache *depositcache.DepositCache
|
||||
AttPool attestations.Pool
|
||||
ExitPool *voluntaryexits.Pool
|
||||
SlashingPool *slashings.Pool
|
||||
P2p p2p.Broadcaster
|
||||
MaxRoutines int
|
||||
StateNotifier statefeed.Notifier
|
||||
ForkChoiceStore f.ForkChoicer
|
||||
OpsService *attestations.Service
|
||||
StateGen *stategen.State
|
||||
WspBlockRoot []byte
|
||||
WspEpoch types.Epoch
|
||||
BeaconBlockBuf int
|
||||
ChainStartFetcher powchain.ChainStartFetcher
|
||||
BeaconDB db.HeadAccessDatabase
|
||||
DepositCache *depositcache.DepositCache
|
||||
AttPool attestations.Pool
|
||||
ExitPool voluntaryexits.PoolManager
|
||||
SlashingPool slashings.PoolManager
|
||||
P2p p2p.Broadcaster
|
||||
MaxRoutines int
|
||||
StateNotifier statefeed.Notifier
|
||||
ForkChoiceStore f.ForkChoicer
|
||||
OpsService *attestations.Service
|
||||
StateGen *stategen.State
|
||||
WeakSubjectivityCheckpt *ethpb.Checkpoint
|
||||
}
|
||||
|
||||
// NewService instantiates a new block service instance that will
|
||||
@@ -105,26 +90,13 @@ type Config struct {
|
||||
func NewService(ctx context.Context, cfg *Config) (*Service, error) {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
return &Service{
|
||||
cfg: cfg,
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
beaconDB: cfg.BeaconDB,
|
||||
depositCache: cfg.DepositCache,
|
||||
chainStartFetcher: cfg.ChainStartFetcher,
|
||||
attPool: cfg.AttPool,
|
||||
exitPool: cfg.ExitPool,
|
||||
slashingPool: cfg.SlashingPool,
|
||||
p2p: cfg.P2p,
|
||||
maxRoutines: cfg.MaxRoutines,
|
||||
stateNotifier: cfg.StateNotifier,
|
||||
forkChoiceStore: cfg.ForkChoiceStore,
|
||||
boundaryRoots: [][32]byte{},
|
||||
checkpointStateCache: cache.NewCheckpointStateCache(),
|
||||
opsService: cfg.OpsService,
|
||||
stateGen: cfg.StateGen,
|
||||
initSyncBlocks: make(map[[32]byte]*ethpb.SignedBeaconBlock),
|
||||
justifiedBalances: make([]uint64, 0),
|
||||
wsEpoch: cfg.WspEpoch,
|
||||
wsRoot: cfg.WspBlockRoot,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -133,7 +105,7 @@ 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.beaconDB.FinalizedCheckpoint(s.ctx)
|
||||
cp, err := s.cfg.BeaconDB.FinalizedCheckpoint(s.ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not fetch finalized cp: %v", err)
|
||||
}
|
||||
@@ -143,7 +115,7 @@ func (s *Service) Start() {
|
||||
// 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.beaconDB.GenesisBlock(s.ctx)
|
||||
genesisBlock, err := s.cfg.BeaconDB.GenesisBlock(s.ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not fetch finalized cp: %v", err)
|
||||
}
|
||||
@@ -154,7 +126,7 @@ func (s *Service) Start() {
|
||||
}
|
||||
}
|
||||
}
|
||||
beaconState, err := s.stateGen.StateByRoot(s.ctx, r)
|
||||
beaconState, err := s.cfg.StateGen.StateByRoot(s.ctx, r)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not fetch beacon state by root: %v", err)
|
||||
}
|
||||
@@ -166,13 +138,13 @@ func (s *Service) Start() {
|
||||
if beaconState != nil {
|
||||
log.Info("Blockchain data already exists in DB, initializing...")
|
||||
s.genesisTime = time.Unix(int64(beaconState.GenesisTime()), 0)
|
||||
s.opsService.SetGenesisTime(beaconState.GenesisTime())
|
||||
s.cfg.OpsService.SetGenesisTime(beaconState.GenesisTime())
|
||||
if err := s.initializeChainInfo(s.ctx); err != nil {
|
||||
log.Fatalf("Could not set up chain info: %v", err)
|
||||
}
|
||||
|
||||
// We start a counter to genesis, if needed.
|
||||
gState, err := s.beaconDB.GenesisState(s.ctx)
|
||||
gState, err := s.cfg.BeaconDB.GenesisState(s.ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not retrieve genesis state: %v", err)
|
||||
}
|
||||
@@ -182,24 +154,24 @@ func (s *Service) Start() {
|
||||
}
|
||||
go slotutil.CountdownToGenesis(s.ctx, s.genesisTime, uint64(gState.NumValidators()), gRoot)
|
||||
|
||||
justifiedCheckpoint, err := s.beaconDB.JustifiedCheckpoint(s.ctx)
|
||||
justifiedCheckpoint, err := s.cfg.BeaconDB.JustifiedCheckpoint(s.ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not get justified checkpoint: %v", err)
|
||||
}
|
||||
finalizedCheckpoint, err := s.beaconDB.FinalizedCheckpoint(s.ctx)
|
||||
finalizedCheckpoint, err := s.cfg.BeaconDB.FinalizedCheckpoint(s.ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not get finalized checkpoint: %v", err)
|
||||
}
|
||||
|
||||
// Resume fork choice.
|
||||
s.justifiedCheckpt = stateTrie.CopyCheckpoint(justifiedCheckpoint)
|
||||
s.justifiedCheckpt = stateV0.CopyCheckpoint(justifiedCheckpoint)
|
||||
if err := s.cacheJustifiedStateBalances(s.ctx, s.ensureRootNotZeros(bytesutil.ToBytes32(s.justifiedCheckpt.Root))); err != nil {
|
||||
log.Fatalf("Could not cache justified state balances: %v", err)
|
||||
}
|
||||
s.prevJustifiedCheckpt = stateTrie.CopyCheckpoint(justifiedCheckpoint)
|
||||
s.bestJustifiedCheckpt = stateTrie.CopyCheckpoint(justifiedCheckpoint)
|
||||
s.finalizedCheckpt = stateTrie.CopyCheckpoint(finalizedCheckpoint)
|
||||
s.prevFinalizedCheckpt = stateTrie.CopyCheckpoint(finalizedCheckpoint)
|
||||
s.prevJustifiedCheckpt = stateV0.CopyCheckpoint(justifiedCheckpoint)
|
||||
s.bestJustifiedCheckpt = stateV0.CopyCheckpoint(justifiedCheckpoint)
|
||||
s.finalizedCheckpt = stateV0.CopyCheckpoint(finalizedCheckpoint)
|
||||
s.prevFinalizedCheckpt = stateV0.CopyCheckpoint(finalizedCheckpoint)
|
||||
s.resumeForkChoice(justifiedCheckpoint, finalizedCheckpoint)
|
||||
|
||||
ss, err := helpers.StartSlot(s.finalizedCheckpt.Epoch)
|
||||
@@ -222,7 +194,7 @@ func (s *Service) Start() {
|
||||
log.Fatalf("Could not verify weak subjectivity checkpoint: %v", err)
|
||||
}
|
||||
|
||||
s.stateNotifier.StateFeed().Send(&feed.Event{
|
||||
s.cfg.StateNotifier.StateFeed().Send(&feed.Event{
|
||||
Type: statefeed.Initialized,
|
||||
Data: &statefeed.InitializedData{
|
||||
StartTime: s.genesisTime,
|
||||
@@ -231,13 +203,13 @@ func (s *Service) Start() {
|
||||
})
|
||||
} else {
|
||||
log.Info("Waiting to reach the validator deposit threshold to start the beacon chain...")
|
||||
if s.chainStartFetcher == nil {
|
||||
if s.cfg.ChainStartFetcher == nil {
|
||||
log.Fatal("Not configured web3Service for POW chain")
|
||||
return // return need for TestStartUninitializedChainWithoutConfigPOWChain.
|
||||
}
|
||||
go func() {
|
||||
stateChannel := make(chan *feed.Event, 1)
|
||||
stateSub := s.stateNotifier.StateFeed().Subscribe(stateChannel)
|
||||
stateSub := s.cfg.StateNotifier.StateFeed().Subscribe(stateChannel)
|
||||
defer stateSub.Unsubscribe()
|
||||
<-attestationProcessorSubscribed
|
||||
for {
|
||||
@@ -270,8 +242,8 @@ func (s *Service) Start() {
|
||||
// processChainStartTime initializes a series of deposits from the ChainStart deposits in the eth1
|
||||
// deposit contract, initializes the beacon chain's state, and kicks off the beacon chain.
|
||||
func (s *Service) processChainStartTime(ctx context.Context, genesisTime time.Time) {
|
||||
preGenesisState := s.chainStartFetcher.PreGenesisState()
|
||||
initializedState, err := s.initializeBeaconChain(ctx, genesisTime, preGenesisState, s.chainStartFetcher.ChainStartEth1Data())
|
||||
preGenesisState := s.cfg.ChainStartFetcher.PreGenesisState()
|
||||
initializedState, err := s.initializeBeaconChain(ctx, genesisTime, preGenesisState, s.cfg.ChainStartFetcher.ChainStartEth1Data())
|
||||
if err != nil {
|
||||
log.Fatalf("Could not initialize beacon chain: %v", err)
|
||||
}
|
||||
@@ -284,7 +256,7 @@ func (s *Service) processChainStartTime(ctx context.Context, genesisTime time.Ti
|
||||
|
||||
// We send out a state initialized event to the rest of the services
|
||||
// running in the beacon node.
|
||||
s.stateNotifier.StateFeed().Send(&feed.Event{
|
||||
s.cfg.StateNotifier.StateFeed().Send(&feed.Event{
|
||||
Type: statefeed.Initialized,
|
||||
Data: &statefeed.InitializedData{
|
||||
StartTime: genesisTime,
|
||||
@@ -299,8 +271,8 @@ func (s *Service) processChainStartTime(ctx context.Context, genesisTime time.Ti
|
||||
func (s *Service) initializeBeaconChain(
|
||||
ctx context.Context,
|
||||
genesisTime time.Time,
|
||||
preGenesisState *stateTrie.BeaconState,
|
||||
eth1data *ethpb.Eth1Data) (*stateTrie.BeaconState, error) {
|
||||
preGenesisState iface.BeaconState,
|
||||
eth1data *ethpb.Eth1Data) (iface.BeaconState, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "beacon-chain.Service.initializeBeaconChain")
|
||||
defer span.End()
|
||||
s.genesisTime = genesisTime
|
||||
@@ -318,7 +290,7 @@ func (s *Service) initializeBeaconChain(
|
||||
log.Info("Initialized beacon chain genesis state")
|
||||
|
||||
// Clear out all pre-genesis data now that the state is initialized.
|
||||
s.chainStartFetcher.ClearPreGenesisData()
|
||||
s.cfg.ChainStartFetcher.ClearPreGenesisData()
|
||||
|
||||
// Update committee shuffled indices for genesis epoch.
|
||||
if err := helpers.UpdateCommitteeCache(genesisState, 0 /* genesis epoch */); err != nil {
|
||||
@@ -328,7 +300,7 @@ func (s *Service) initializeBeaconChain(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.opsService.SetGenesisTime(genesisState.GenesisTime())
|
||||
s.cfg.OpsService.SetGenesisTime(genesisState.GenesisTime())
|
||||
|
||||
return genesisState, nil
|
||||
}
|
||||
@@ -337,14 +309,14 @@ func (s *Service) initializeBeaconChain(
|
||||
func (s *Service) Stop() error {
|
||||
defer s.cancel()
|
||||
|
||||
if s.stateGen != nil && s.head != nil && s.head.state != nil {
|
||||
if err := s.stateGen.ForceCheckpoint(s.ctx, s.head.state.FinalizedCheckpoint().Root); err != nil {
|
||||
if s.cfg.StateGen != nil && s.head != nil && s.head.state != nil {
|
||||
if err := s.cfg.StateGen.ForceCheckpoint(s.ctx, s.head.state.FinalizedCheckpoint().Root); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Save initial sync cached blocks to the DB before stop.
|
||||
return s.beaconDB.SaveBlocks(s.ctx, s.getInitSyncBlocks())
|
||||
return s.cfg.BeaconDB.SaveBlocks(s.ctx, s.getInitSyncBlocks())
|
||||
}
|
||||
|
||||
// Status always returns nil unless there is an error condition that causes
|
||||
@@ -353,60 +325,42 @@ func (s *Service) Status() error {
|
||||
if s.genesisRoot == params.BeaconConfig().ZeroHash {
|
||||
return errors.New("genesis state has not been created")
|
||||
}
|
||||
if runtime.NumGoroutine() > s.maxRoutines {
|
||||
if runtime.NumGoroutine() > s.cfg.MaxRoutines {
|
||||
return fmt.Errorf("too many goroutines %d", runtime.NumGoroutine())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// This gets called when beacon chain is first initialized to save genesis data (state, block, and more) in db.
|
||||
func (s *Service) saveGenesisData(ctx context.Context, genesisState *stateTrie.BeaconState) error {
|
||||
stateRoot, err := genesisState.HashTreeRoot(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
func (s *Service) saveGenesisData(ctx context.Context, genesisState iface.BeaconState) error {
|
||||
if err := s.cfg.BeaconDB.SaveGenesisData(ctx, genesisState); err != nil {
|
||||
return errors.Wrap(err, "could not save genesis data")
|
||||
}
|
||||
genesisBlk, err := s.cfg.BeaconDB.GenesisBlock(ctx)
|
||||
if err != nil || genesisBlk == nil {
|
||||
return fmt.Errorf("could not load genesis block: %v", err)
|
||||
}
|
||||
genesisBlk := blocks.NewGenesisBlock(stateRoot[:])
|
||||
genesisBlkRoot, err := genesisBlk.Block.HashTreeRoot()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get genesis block root")
|
||||
}
|
||||
|
||||
s.genesisRoot = genesisBlkRoot
|
||||
|
||||
if err := s.beaconDB.SaveBlock(ctx, genesisBlk); err != nil {
|
||||
return errors.Wrap(err, "could not save genesis block")
|
||||
}
|
||||
if err := s.beaconDB.SaveState(ctx, genesisState, genesisBlkRoot); err != nil {
|
||||
return errors.Wrap(err, "could not save genesis state")
|
||||
}
|
||||
if err := s.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{
|
||||
Slot: 0,
|
||||
Root: genesisBlkRoot[:],
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.stateGen.SaveFinalizedState(0, genesisBlkRoot, genesisState)
|
||||
|
||||
if err := s.beaconDB.SaveHeadBlockRoot(ctx, genesisBlkRoot); err != nil {
|
||||
return errors.Wrap(err, "could not save head block root")
|
||||
}
|
||||
if err := s.beaconDB.SaveGenesisBlockRoot(ctx, genesisBlkRoot); err != nil {
|
||||
return errors.Wrap(err, "could not save genesis block root")
|
||||
}
|
||||
s.cfg.StateGen.SaveFinalizedState(0 /*slot*/, genesisBlkRoot, genesisState)
|
||||
|
||||
// Finalized checkpoint at genesis is a zero hash.
|
||||
genesisCheckpoint := genesisState.FinalizedCheckpoint()
|
||||
|
||||
s.justifiedCheckpt = stateTrie.CopyCheckpoint(genesisCheckpoint)
|
||||
s.justifiedCheckpt = stateV0.CopyCheckpoint(genesisCheckpoint)
|
||||
if err := s.cacheJustifiedStateBalances(ctx, genesisBlkRoot); err != nil {
|
||||
return err
|
||||
}
|
||||
s.prevJustifiedCheckpt = stateTrie.CopyCheckpoint(genesisCheckpoint)
|
||||
s.bestJustifiedCheckpt = stateTrie.CopyCheckpoint(genesisCheckpoint)
|
||||
s.finalizedCheckpt = stateTrie.CopyCheckpoint(genesisCheckpoint)
|
||||
s.prevFinalizedCheckpt = stateTrie.CopyCheckpoint(genesisCheckpoint)
|
||||
s.prevJustifiedCheckpt = stateV0.CopyCheckpoint(genesisCheckpoint)
|
||||
s.bestJustifiedCheckpt = stateV0.CopyCheckpoint(genesisCheckpoint)
|
||||
s.finalizedCheckpt = stateV0.CopyCheckpoint(genesisCheckpoint)
|
||||
s.prevFinalizedCheckpt = stateV0.CopyCheckpoint(genesisCheckpoint)
|
||||
|
||||
if err := s.forkChoiceStore.ProcessBlock(ctx,
|
||||
if err := s.cfg.ForkChoiceStore.ProcessBlock(ctx,
|
||||
genesisBlk.Block.Slot,
|
||||
genesisBlkRoot,
|
||||
params.BeaconConfig().ZeroHash,
|
||||
@@ -417,13 +371,12 @@ func (s *Service) saveGenesisData(ctx context.Context, genesisState *stateTrie.B
|
||||
}
|
||||
|
||||
s.setHead(genesisBlkRoot, genesisBlk, genesisState)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// This gets called to initialize chain info variables using the finalized checkpoint stored in DB
|
||||
func (s *Service) initializeChainInfo(ctx context.Context) error {
|
||||
genesisBlock, err := s.beaconDB.GenesisBlock(ctx)
|
||||
genesisBlock, err := s.cfg.BeaconDB.GenesisBlock(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get genesis block from db")
|
||||
}
|
||||
@@ -436,7 +389,7 @@ func (s *Service) initializeChainInfo(ctx context.Context) error {
|
||||
}
|
||||
s.genesisRoot = genesisBlkRoot
|
||||
|
||||
finalized, err := s.beaconDB.FinalizedCheckpoint(ctx)
|
||||
finalized, err := s.cfg.BeaconDB.FinalizedCheckpoint(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get finalized checkpoint from db")
|
||||
}
|
||||
@@ -446,15 +399,15 @@ func (s *Service) initializeChainInfo(ctx context.Context) error {
|
||||
return errors.New("no finalized epoch in the database")
|
||||
}
|
||||
finalizedRoot := s.ensureRootNotZeros(bytesutil.ToBytes32(finalized.Root))
|
||||
var finalizedState *stateTrie.BeaconState
|
||||
var finalizedState iface.BeaconState
|
||||
|
||||
finalizedState, err = s.stateGen.Resume(ctx)
|
||||
finalizedState, err = s.cfg.StateGen.Resume(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get finalized state from db")
|
||||
}
|
||||
|
||||
if flags.Get().HeadSync {
|
||||
headBlock, err := s.beaconDB.HeadBlock(ctx)
|
||||
headBlock, err := s.cfg.BeaconDB.HeadBlock(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not retrieve head block")
|
||||
}
|
||||
@@ -470,13 +423,13 @@ func (s *Service) initializeChainInfo(ctx context.Context) error {
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not hash head block")
|
||||
}
|
||||
finalizedState, err := s.stateGen.Resume(ctx)
|
||||
finalizedState, err := s.cfg.StateGen.Resume(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get finalized state from db")
|
||||
}
|
||||
log.Infof("Regenerating state from the last checkpoint at slot %d to current head slot of %d."+
|
||||
"This process may take a while, please wait.", finalizedState.Slot(), headBlock.Block.Slot)
|
||||
headState, err := s.stateGen.StateByRoot(ctx, headRoot)
|
||||
headState, err := s.cfg.StateGen.StateByRoot(ctx, headRoot)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not retrieve head state")
|
||||
}
|
||||
@@ -489,7 +442,7 @@ func (s *Service) initializeChainInfo(ctx context.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
finalizedBlock, err := s.beaconDB.Block(ctx, finalizedRoot)
|
||||
finalizedBlock, err := s.cfg.BeaconDB.Block(ctx, finalizedRoot)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get finalized block from db")
|
||||
}
|
||||
@@ -506,7 +459,7 @@ func (s *Service) initializeChainInfo(ctx context.Context) error {
|
||||
// information to fork choice service to initializes fork choice store.
|
||||
func (s *Service) resumeForkChoice(justifiedCheckpoint, finalizedCheckpoint *ethpb.Checkpoint) {
|
||||
store := protoarray.New(justifiedCheckpoint.Epoch, finalizedCheckpoint.Epoch, bytesutil.ToBytes32(finalizedCheckpoint.Root))
|
||||
s.forkChoiceStore = store
|
||||
s.cfg.ForkChoiceStore = store
|
||||
}
|
||||
|
||||
// This returns true if block has been processed before. Two ways to verify the block has been processed:
|
||||
@@ -514,9 +467,9 @@ func (s *Service) resumeForkChoice(justifiedCheckpoint, finalizedCheckpoint *eth
|
||||
// 2.) Check DB.
|
||||
// Checking 1.) is ten times faster than checking 2.)
|
||||
func (s *Service) hasBlock(ctx context.Context, root [32]byte) bool {
|
||||
if s.forkChoiceStore.HasNode(root) {
|
||||
if s.cfg.ForkChoiceStore.HasNode(root) {
|
||||
return true
|
||||
}
|
||||
|
||||
return s.beaconDB.HasBlock(ctx, root)
|
||||
return s.cfg.BeaconDB.HasBlock(ctx, root)
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ func init() {
|
||||
func TestChainService_SaveHead_DataRace(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
s := &Service{
|
||||
beaconDB: beaconDB,
|
||||
cfg: &Config{BeaconDB: beaconDB},
|
||||
}
|
||||
go func() {
|
||||
require.NoError(t, s.saveHead(context.Background(), [32]byte{}))
|
||||
|
||||
@@ -18,13 +18,13 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db"
|
||||
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/flags"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/attestations"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
|
||||
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateV0"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
||||
"github.com/prysmaticlabs/prysm/cmd/beacon-chain/flags"
|
||||
protodb "github.com/prysmaticlabs/prysm/proto/beacon/db"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
@@ -70,8 +70,10 @@ func setupBeaconChain(t *testing.T, beaconDB db.Database) *Service {
|
||||
var web3Service *powchain.Service
|
||||
var err error
|
||||
bState, _ := testutil.DeterministicGenesisState(t, 10)
|
||||
pbState, err := stateV0.ProtobufBeaconState(bState.InnerStateUnsafe())
|
||||
require.NoError(t, err)
|
||||
err = beaconDB.SavePowchainData(ctx, &protodb.ETH1ChainData{
|
||||
BeaconState: bState.InnerStateUnsafe(),
|
||||
BeaconState: pbState,
|
||||
Trie: &protodb.SparseMerkleTrie{},
|
||||
CurrentEth1Data: &protodb.LatestETH1Data{
|
||||
BlockHash: make([]byte, 32),
|
||||
@@ -88,7 +90,7 @@ func setupBeaconChain(t *testing.T, beaconDB db.Database) *Service {
|
||||
require.NoError(t, err)
|
||||
web3Service, err = powchain.NewService(ctx, &powchain.Web3ServiceConfig{
|
||||
BeaconDB: beaconDB,
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
HttpEndpoints: []string{endpoint},
|
||||
DepositContract: common.Address{},
|
||||
})
|
||||
require.NoError(t, err, "Unable to set up web3 service")
|
||||
@@ -274,14 +276,14 @@ func TestChainService_InitializeChainInfo(t *testing.T) {
|
||||
require.NoError(t, beaconDB.SaveState(ctx, headState, genesisRoot))
|
||||
require.NoError(t, beaconDB.SaveBlock(ctx, headBlock))
|
||||
require.NoError(t, beaconDB.SaveFinalizedCheckpoint(ctx, ðpb.Checkpoint{Epoch: helpers.SlotToEpoch(finalizedSlot), Root: headRoot[:]}))
|
||||
c := &Service{beaconDB: beaconDB, stateGen: stategen.New(beaconDB)}
|
||||
c := &Service{cfg: &Config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB)}}
|
||||
require.NoError(t, c.initializeChainInfo(ctx))
|
||||
headBlk, err := c.HeadBlock(ctx)
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, headBlock, headBlk, "Head block incorrect")
|
||||
s, err := c.HeadState(ctx)
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, headState.InnerStateUnsafe(), s.InnerStateUnsafe(), "Head state incorrect")
|
||||
assert.DeepSSZEqual(t, headState.InnerStateUnsafe(), s.InnerStateUnsafe(), "Head state incorrect")
|
||||
assert.Equal(t, c.HeadSlot(), headBlock.Block.Slot, "Head slot incorrect")
|
||||
r, err := c.HeadRoot(context.Background())
|
||||
require.NoError(t, err)
|
||||
@@ -314,11 +316,11 @@ 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, headBlock))
|
||||
c := &Service{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)
|
||||
assert.DeepEqual(t, headState.InnerStateUnsafe(), s.InnerStateUnsafe(), "Head state incorrect")
|
||||
assert.DeepSSZEqual(t, headState.InnerStateUnsafe(), s.InnerStateUnsafe(), "Head state incorrect")
|
||||
assert.Equal(t, genesisRoot, c.genesisRoot, "Genesis block root incorrect")
|
||||
assert.DeepEqual(t, genesis, c.head.block)
|
||||
}
|
||||
@@ -371,12 +373,12 @@ func TestChainService_InitializeChainInfo_HeadSync(t *testing.T) {
|
||||
Root: finalizedRoot[:],
|
||||
}))
|
||||
|
||||
c := &Service{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)
|
||||
assert.DeepEqual(t, headState.InnerStateUnsafe(), s.InnerStateUnsafe(), "Head state incorrect")
|
||||
assert.DeepSSZEqual(t, headState.InnerStateUnsafe(), s.InnerStateUnsafe(), "Head state incorrect")
|
||||
assert.Equal(t, genesisRoot, c.genesisRoot, "Genesis block root incorrect")
|
||||
// Since head sync is not triggered, chain is initialized to the last finalization checkpoint.
|
||||
assert.DeepEqual(t, finalizedBlock, c.head.block)
|
||||
@@ -397,7 +399,7 @@ func TestChainService_InitializeChainInfo_HeadSync(t *testing.T) {
|
||||
require.NoError(t, c.initializeChainInfo(ctx))
|
||||
s, err = c.HeadState(ctx)
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, headState.InnerStateUnsafe(), s.InnerStateUnsafe(), "Head state incorrect")
|
||||
assert.DeepSSZEqual(t, headState.InnerStateUnsafe(), s.InnerStateUnsafe(), "Head state incorrect")
|
||||
assert.Equal(t, genesisRoot, c.genesisRoot, "Genesis block root incorrect")
|
||||
// Head slot is far beyond the latest finalized checkpoint, head sync is triggered.
|
||||
assert.DeepEqual(t, headBlock, c.head.block)
|
||||
@@ -409,8 +411,7 @@ func TestChainService_SaveHeadNoDB(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
s := &Service{
|
||||
beaconDB: beaconDB,
|
||||
stateGen: stategen.New(beaconDB),
|
||||
cfg: &Config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB)},
|
||||
}
|
||||
blk := testutil.NewBeaconBlock()
|
||||
blk.Block.Slot = 1
|
||||
@@ -418,10 +419,10 @@ func TestChainService_SaveHeadNoDB(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
newState, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, s.stateGen.SaveState(ctx, r, newState))
|
||||
require.NoError(t, s.cfg.StateGen.SaveState(ctx, r, newState))
|
||||
require.NoError(t, s.saveHeadNoDB(ctx, blk, r, newState))
|
||||
|
||||
newB, err := s.beaconDB.HeadBlock(ctx)
|
||||
newB, err := s.cfg.BeaconDB.HeadBlock(ctx)
|
||||
require.NoError(t, err)
|
||||
if reflect.DeepEqual(newB, blk) {
|
||||
t.Error("head block should not be equal")
|
||||
@@ -432,9 +433,8 @@ func TestHasBlock_ForkChoiceAndDB(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
s := &Service{
|
||||
forkChoiceStore: protoarray.New(0, 0, [32]byte{}),
|
||||
cfg: &Config{ForkChoiceStore: protoarray.New(0, 0, [32]byte{}), BeaconDB: beaconDB},
|
||||
finalizedCheckpt: ðpb.Checkpoint{Root: make([]byte, 32)},
|
||||
beaconDB: beaconDB,
|
||||
}
|
||||
block := testutil.NewBeaconBlock()
|
||||
r, err := block.Block.HashTreeRoot()
|
||||
@@ -451,25 +451,24 @@ 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)},
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
beaconDB: beaconDB,
|
||||
initSyncBlocks: make(map[[32]byte]*ethpb.SignedBeaconBlock),
|
||||
stateGen: stategen.New(beaconDB),
|
||||
}
|
||||
b := testutil.NewBeaconBlock()
|
||||
r, err := b.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
s.saveInitSyncBlock(r, b)
|
||||
require.NoError(t, s.Stop())
|
||||
require.Equal(t, true, s.beaconDB.HasBlock(ctx, r))
|
||||
require.Equal(t, true, s.cfg.BeaconDB.HasBlock(ctx, r))
|
||||
}
|
||||
|
||||
func TestProcessChainStartTime_ReceivedFeed(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
service := setupBeaconChain(t, beaconDB)
|
||||
stateChannel := make(chan *feed.Event, 1)
|
||||
stateSub := service.stateNotifier.StateFeed().Subscribe(stateChannel)
|
||||
stateSub := service.cfg.StateNotifier.StateFeed().Subscribe(stateChannel)
|
||||
defer stateSub.Unsubscribe()
|
||||
service.processChainStartTime(context.Background(), time.Now())
|
||||
|
||||
@@ -483,16 +482,16 @@ func BenchmarkHasBlockDB(b *testing.B) {
|
||||
beaconDB := testDB.SetupDB(b)
|
||||
ctx := context.Background()
|
||||
s := &Service{
|
||||
beaconDB: beaconDB,
|
||||
cfg: &Config{BeaconDB: beaconDB},
|
||||
}
|
||||
block := testutil.NewBeaconBlock()
|
||||
require.NoError(b, s.beaconDB.SaveBlock(ctx, block))
|
||||
require.NoError(b, s.cfg.BeaconDB.SaveBlock(ctx, block))
|
||||
r, err := block.Block.HashTreeRoot()
|
||||
require.NoError(b, err)
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
require.Equal(b, true, s.beaconDB.HasBlock(ctx, r), "Block is not in DB")
|
||||
require.Equal(b, true, s.cfg.BeaconDB.HasBlock(ctx, r), "Block is not in DB")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -500,20 +499,19 @@ func BenchmarkHasBlockForkChoiceStore(b *testing.B) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(b)
|
||||
s := &Service{
|
||||
forkChoiceStore: protoarray.New(0, 0, [32]byte{}),
|
||||
cfg: &Config{ForkChoiceStore: protoarray.New(0, 0, [32]byte{}), BeaconDB: beaconDB},
|
||||
finalizedCheckpt: ðpb.Checkpoint{Root: make([]byte, 32)},
|
||||
beaconDB: beaconDB,
|
||||
}
|
||||
block := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Body: ðpb.BeaconBlockBody{}}}
|
||||
r, err := block.Block.HashTreeRoot()
|
||||
require.NoError(b, err)
|
||||
bs := &pb.BeaconState{FinalizedCheckpoint: ðpb.Checkpoint{Root: make([]byte, 32)}, CurrentJustifiedCheckpoint: ðpb.Checkpoint{Root: make([]byte, 32)}}
|
||||
beaconState, err := beaconstate.InitializeFromProto(bs)
|
||||
beaconState, err := stateV0.InitializeFromProto(bs)
|
||||
require.NoError(b, err)
|
||||
require.NoError(b, s.insertBlockAndAttestationsToForkChoiceStore(ctx, block.Block, r, beaconState))
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
require.Equal(b, true, s.forkChoiceStore.HasNode(r), "Block is not in fork choice store")
|
||||
require.Equal(b, true, s.cfg.ForkChoiceStore.HasNode(r), "Block is not in fork choice store")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,8 +18,10 @@ go_library(
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/db:go_default_library",
|
||||
"//beacon-chain/forkchoice/protoarray:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//beacon-chain/state/interface:go_default_library",
|
||||
"//beacon-chain/state/stateV0:go_default_library",
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/bytesutil:go_default_library",
|
||||
"//shared/event:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
|
||||
@@ -19,8 +19,10 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateV0"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/event"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/sirupsen/logrus"
|
||||
@@ -28,7 +30,7 @@ import (
|
||||
|
||||
// ChainService defines the mock interface for testing
|
||||
type ChainService struct {
|
||||
State *stateTrie.BeaconState
|
||||
State iface.BeaconState
|
||||
Root []byte
|
||||
Block *ethpb.SignedBeaconBlock
|
||||
FinalizedCheckPoint *ethpb.Checkpoint
|
||||
@@ -149,7 +151,7 @@ func (mon *MockOperationNotifier) OperationFeed() *event.Feed {
|
||||
// ReceiveBlockInitialSync mocks ReceiveBlockInitialSync method in chain service.
|
||||
func (s *ChainService) ReceiveBlockInitialSync(ctx context.Context, block *ethpb.SignedBeaconBlock, _ [32]byte) error {
|
||||
if s.State == nil {
|
||||
s.State = &stateTrie.BeaconState{}
|
||||
s.State = &stateV0.BeaconState{}
|
||||
}
|
||||
if !bytes.Equal(s.Root, block.Block.ParentRoot) {
|
||||
return errors.Errorf("wanted %#x but got %#x", s.Root, block.Block.ParentRoot)
|
||||
@@ -176,7 +178,7 @@ func (s *ChainService) ReceiveBlockInitialSync(ctx context.Context, block *ethpb
|
||||
// ReceiveBlockBatch processes blocks in batches from initial-sync.
|
||||
func (s *ChainService) ReceiveBlockBatch(ctx context.Context, blks []*ethpb.SignedBeaconBlock, _ [][32]byte) error {
|
||||
if s.State == nil {
|
||||
s.State = &stateTrie.BeaconState{}
|
||||
s.State = &stateV0.BeaconState{}
|
||||
}
|
||||
for _, block := range blks {
|
||||
if !bytes.Equal(s.Root, block.Block.ParentRoot) {
|
||||
@@ -205,7 +207,7 @@ func (s *ChainService) ReceiveBlockBatch(ctx context.Context, blks []*ethpb.Sign
|
||||
// ReceiveBlock mocks ReceiveBlock method in chain service.
|
||||
func (s *ChainService) ReceiveBlock(ctx context.Context, block *ethpb.SignedBeaconBlock, _ [32]byte) error {
|
||||
if s.State == nil {
|
||||
s.State = &stateTrie.BeaconState{}
|
||||
s.State = &stateV0.BeaconState{}
|
||||
}
|
||||
if !bytes.Equal(s.Root, block.Block.ParentRoot) {
|
||||
return errors.Errorf("wanted %#x but got %#x", s.Root, block.Block.ParentRoot)
|
||||
@@ -251,7 +253,7 @@ func (s *ChainService) HeadBlock(context.Context) (*ethpb.SignedBeaconBlock, err
|
||||
}
|
||||
|
||||
// HeadState mocks HeadState method in chain service.
|
||||
func (s *ChainService) HeadState(context.Context) (*stateTrie.BeaconState, error) {
|
||||
func (s *ChainService) HeadState(context.Context) (iface.BeaconState, error) {
|
||||
return s.State, nil
|
||||
}
|
||||
|
||||
@@ -286,14 +288,14 @@ func (s *ChainService) ReceiveAttestationNoPubsub(context.Context, *ethpb.Attest
|
||||
}
|
||||
|
||||
// AttestationPreState mocks AttestationPreState method in chain service.
|
||||
func (s *ChainService) AttestationPreState(_ context.Context, _ *ethpb.Attestation) (*stateTrie.BeaconState, error) {
|
||||
func (s *ChainService) AttestationPreState(_ context.Context, _ *ethpb.Attestation) (iface.BeaconState, error) {
|
||||
return s.State, nil
|
||||
}
|
||||
|
||||
// HeadValidatorsIndices mocks the same method in the chain service.
|
||||
func (s *ChainService) HeadValidatorsIndices(_ context.Context, epoch types.Epoch) ([]uint64, error) {
|
||||
func (s *ChainService) HeadValidatorsIndices(_ context.Context, epoch types.Epoch) ([]types.ValidatorIndex, error) {
|
||||
if s.State == nil {
|
||||
return []uint64{}, nil
|
||||
return []types.ValidatorIndex{}, nil
|
||||
}
|
||||
return helpers.ActiveValidatorIndices(s.State, epoch)
|
||||
}
|
||||
@@ -381,3 +383,12 @@ func (s *ChainService) VerifyFinalizedConsistency(_ context.Context, r []byte) e
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ChainHeads mocks ChainHeads and always return nil.
|
||||
func (s *ChainService) ChainHeads() ([][32]byte, []types.Slot) {
|
||||
return [][32]byte{
|
||||
bytesutil.ToBytes32(bytesutil.PadTo([]byte("foo"), 32)),
|
||||
bytesutil.ToBytes32(bytesutil.PadTo([]byte("bar"), 32)),
|
||||
},
|
||||
[]types.Slot{0, 1}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
// Reference design: https://github.com/ethereum/eth2.0-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 len(s.wsRoot) == 0 || s.wsEpoch == 0 {
|
||||
if s.cfg.WeakSubjectivityCheckpt == nil || len(s.cfg.WeakSubjectivityCheckpt.Root) == 0 || s.cfg.WeakSubjectivityCheckpt.Epoch == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -23,28 +23,28 @@ func (s *Service) VerifyWeakSubjectivityRoot(ctx context.Context) error {
|
||||
if s.wsVerified {
|
||||
return nil
|
||||
}
|
||||
if s.wsEpoch > s.finalizedCheckpt.Epoch {
|
||||
if s.cfg.WeakSubjectivityCheckpt.Epoch > s.finalizedCheckpt.Epoch {
|
||||
return nil
|
||||
}
|
||||
|
||||
r := bytesutil.ToBytes32(s.wsRoot)
|
||||
log.Infof("Performing weak subjectivity check for root %#x in epoch %d", r, s.wsEpoch)
|
||||
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.beaconDB.SaveBlocks(ctx, s.getInitSyncBlocks()); err != nil {
|
||||
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.beaconDB.HasBlock(ctx, r) {
|
||||
if !s.cfg.BeaconDB.HasBlock(ctx, r) {
|
||||
return fmt.Errorf("node does not have root in DB: %#x", r)
|
||||
}
|
||||
|
||||
startSlot, err := helpers.StartSlot(s.wsEpoch)
|
||||
startSlot, err := helpers.StartSlot(s.cfg.WeakSubjectivityCheckpt.Epoch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 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.beaconDB.BlockRoots(ctx, filter)
|
||||
roots, err := s.cfg.BeaconDB.BlockRoots(ctx, filter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -56,5 +56,5 @@ func (s *Service) VerifyWeakSubjectivityRoot(ctx context.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("node does not have root in db corresponding to epoch: %#x %d", r, s.wsEpoch)
|
||||
return fmt.Errorf("node does not have root in db corresponding to epoch: %#x %d", r, s.cfg.WeakSubjectivityCheckpt.Epoch)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
)
|
||||
@@ -22,8 +23,7 @@ func TestService_VerifyWeakSubjectivityRoot(t *testing.T) {
|
||||
tests := []struct {
|
||||
wsVerified bool
|
||||
wantErr bool
|
||||
wsRoot [32]byte
|
||||
wsEpoch types.Epoch
|
||||
checkpt *ethpb.Checkpoint
|
||||
finalizedEpoch types.Epoch
|
||||
errString string
|
||||
name string
|
||||
@@ -34,37 +34,34 @@ func TestService_VerifyWeakSubjectivityRoot(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "already verified",
|
||||
wsEpoch: 2,
|
||||
checkpt: ðpb.Checkpoint{Epoch: 2},
|
||||
finalizedEpoch: 2,
|
||||
wsVerified: true,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "not yet to verify, ws epoch higher than finalized epoch",
|
||||
wsEpoch: 2,
|
||||
checkpt: ðpb.Checkpoint{Epoch: 2},
|
||||
finalizedEpoch: 1,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "can't find the block in DB",
|
||||
wsEpoch: 1,
|
||||
wsRoot: [32]byte{'a'},
|
||||
checkpt: ðpb.Checkpoint{Root: bytesutil.PadTo([]byte{'a'}, 32), Epoch: 1},
|
||||
finalizedEpoch: 3,
|
||||
wantErr: true,
|
||||
errString: "node does not have root in DB",
|
||||
},
|
||||
{
|
||||
name: "can't find the block corresponds to ws epoch in DB",
|
||||
wsEpoch: 2,
|
||||
wsRoot: r, // Root belongs in epoch 1.
|
||||
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",
|
||||
},
|
||||
{
|
||||
name: "can verify and pass",
|
||||
wsEpoch: 1,
|
||||
wsRoot: r,
|
||||
checkpt: ðpb.Checkpoint{Root: r[:], Epoch: 1},
|
||||
finalizedEpoch: 3,
|
||||
wantErr: false,
|
||||
},
|
||||
@@ -72,9 +69,7 @@ func TestService_VerifyWeakSubjectivityRoot(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s := &Service{
|
||||
beaconDB: beaconDB,
|
||||
wsRoot: tt.wsRoot[:],
|
||||
wsEpoch: tt.wsEpoch,
|
||||
cfg: &Config{BeaconDB: beaconDB, WeakSubjectivityCheckpt: tt.checkpt},
|
||||
wsVerified: tt.wsVerified,
|
||||
finalizedCheckpt: ðpb.Checkpoint{Epoch: tt.finalizedEpoch},
|
||||
}
|
||||
|
||||
21
beacon-chain/cache/BUILD.bazel
vendored
21
beacon-chain/cache/BUILD.bazel
vendored
@@ -1,8 +1,8 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_library")
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_test")
|
||||
|
||||
# gazelle:ignore committee_disabled.go
|
||||
# gazelle:ignore proposer_indices_disabled.go
|
||||
# gazelle:exclude committee_disabled.go
|
||||
# gazelle:exclude proposer_indices_disabled.go
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
@@ -11,13 +11,13 @@ go_library(
|
||||
"committees.go",
|
||||
"common.go",
|
||||
"doc.go",
|
||||
"proposer_indices_type.go",
|
||||
"skip_slot_cache.go",
|
||||
"subnet_ids.go",
|
||||
"proposer_indices_type.go",
|
||||
] + select({
|
||||
"//fuzz:fuzzing_enabled": [
|
||||
"committee_disabled.go",
|
||||
"proposer_indices_disabled.go"
|
||||
"proposer_indices_disabled.go",
|
||||
],
|
||||
"//conditions:default": [
|
||||
"committee.go",
|
||||
@@ -31,9 +31,8 @@ go_library(
|
||||
"//tools:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/featureconfig:go_default_library",
|
||||
"//beacon-chain/state/interface:go_default_library",
|
||||
"//beacon-chain/state/stateV0:go_default_library",
|
||||
"//shared/hashutil:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"//shared/sliceutil:go_default_library",
|
||||
@@ -53,20 +52,20 @@ go_test(
|
||||
size = "small",
|
||||
srcs = [
|
||||
"attestation_data_test.go",
|
||||
"cache_test.go",
|
||||
"checkpoint_state_test.go",
|
||||
"committee_fuzz_test.go",
|
||||
"committee_test.go",
|
||||
"cache_test.go",
|
||||
"proposer_indices_test.go",
|
||||
"skip_slot_cache_test.go",
|
||||
"subnet_ids_test.go",
|
||||
"proposer_indices_test.go"
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//beacon-chain/state/interface:go_default_library",
|
||||
"//beacon-chain/state/stateV0:go_default_library",
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/bytesutil:go_default_library",
|
||||
"//shared/featureconfig:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"//shared/testutil/assert:go_default_library",
|
||||
"//shared/testutil/require:go_default_library",
|
||||
|
||||
4
beacon-chain/cache/attestation_data.go
vendored
4
beacon-chain/cache/attestation_data.go
vendored
@@ -11,7 +11,7 @@ import (
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateV0"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
@@ -98,7 +98,7 @@ func (c *AttestationCache) Get(ctx context.Context, req *ethpb.AttestationDataRe
|
||||
|
||||
if exists && item != nil && item.(*attestationReqResWrapper).res != nil {
|
||||
attestationCacheHit.Inc()
|
||||
return state.CopyAttestationData(item.(*attestationReqResWrapper).res), nil
|
||||
return stateV0.CopyAttestationData(item.(*attestationReqResWrapper).res), nil
|
||||
}
|
||||
attestationCacheMiss.Inc()
|
||||
return nil, nil
|
||||
|
||||
4
beacon-chain/cache/cache_test.go
vendored
4
beacon-chain/cache/cache_test.go
vendored
@@ -2,12 +2,8 @@ package cache
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
resetCfg := featureconfig.InitWithReset(&featureconfig.Flags{EnableEth1DataVoteCache: true})
|
||||
defer resetCfg()
|
||||
m.Run()
|
||||
}
|
||||
|
||||
8
beacon-chain/cache/checkpoint_state.go
vendored
8
beacon-chain/cache/checkpoint_state.go
vendored
@@ -7,7 +7,7 @@ import (
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
|
||||
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
||||
)
|
||||
|
||||
@@ -47,7 +47,7 @@ func NewCheckpointStateCache() *CheckpointStateCache {
|
||||
|
||||
// StateByCheckpoint fetches state by checkpoint. Returns true with a
|
||||
// reference to the CheckpointState info, if exists. Otherwise returns false, nil.
|
||||
func (c *CheckpointStateCache) StateByCheckpoint(cp *ethpb.Checkpoint) (*stateTrie.BeaconState, error) {
|
||||
func (c *CheckpointStateCache) StateByCheckpoint(cp *ethpb.Checkpoint) (iface.BeaconState, error) {
|
||||
c.lock.RLock()
|
||||
defer c.lock.RUnlock()
|
||||
h, err := hashutil.HashProto(cp)
|
||||
@@ -60,7 +60,7 @@ func (c *CheckpointStateCache) StateByCheckpoint(cp *ethpb.Checkpoint) (*stateTr
|
||||
if exists && item != nil {
|
||||
checkpointStateHit.Inc()
|
||||
// Copy here is unnecessary since the return will only be used to verify attestation signature.
|
||||
return item.(*stateTrie.BeaconState), nil
|
||||
return item.(iface.BeaconState), nil
|
||||
}
|
||||
|
||||
checkpointStateMiss.Inc()
|
||||
@@ -69,7 +69,7 @@ func (c *CheckpointStateCache) StateByCheckpoint(cp *ethpb.Checkpoint) (*stateTr
|
||||
|
||||
// AddCheckpointState adds CheckpointState object to the cache. This method also trims the least
|
||||
// recently added CheckpointState object if the cache size has ready the max cache size limit.
|
||||
func (c *CheckpointStateCache) AddCheckpointState(cp *ethpb.Checkpoint, s *stateTrie.BeaconState) error {
|
||||
func (c *CheckpointStateCache) AddCheckpointState(cp *ethpb.Checkpoint, s iface.ReadOnlyBeaconState) error {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
h, err := hashutil.HashProto(cp)
|
||||
|
||||
17
beacon-chain/cache/checkpoint_state_test.go
vendored
17
beacon-chain/cache/checkpoint_state_test.go
vendored
@@ -6,7 +6,8 @@ import (
|
||||
"github.com/gogo/protobuf/proto"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateV0"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
@@ -18,7 +19,7 @@ func TestCheckpointStateCache_StateByCheckpoint(t *testing.T) {
|
||||
cache := NewCheckpointStateCache()
|
||||
|
||||
cp1 := ðpb.Checkpoint{Epoch: 1, Root: bytesutil.PadTo([]byte{'A'}, 32)}
|
||||
st, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
||||
st, err := stateV0.InitializeFromProto(&pb.BeaconState{
|
||||
GenesisValidatorsRoot: params.BeaconConfig().ZeroHash[:],
|
||||
Slot: 64,
|
||||
})
|
||||
@@ -26,19 +27,23 @@ func TestCheckpointStateCache_StateByCheckpoint(t *testing.T) {
|
||||
|
||||
state, err := cache.StateByCheckpoint(cp1)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, (*stateTrie.BeaconState)(nil), state, "Expected state not to exist in empty cache")
|
||||
assert.Equal(t, iface.BeaconState(nil), state, "Expected state not to exist in empty cache")
|
||||
|
||||
require.NoError(t, cache.AddCheckpointState(cp1, st))
|
||||
|
||||
state, err = cache.StateByCheckpoint(cp1)
|
||||
require.NoError(t, err)
|
||||
|
||||
if !proto.Equal(state.InnerStateUnsafe(), st.InnerStateUnsafe()) {
|
||||
pbState1, err := stateV0.ProtobufBeaconState(state.InnerStateUnsafe())
|
||||
require.NoError(t, err)
|
||||
pbState2, err := stateV0.ProtobufBeaconState(st.InnerStateUnsafe())
|
||||
require.NoError(t, err)
|
||||
if !proto.Equal(pbState1, pbState2) {
|
||||
t.Error("incorrectly cached state")
|
||||
}
|
||||
|
||||
cp2 := ðpb.Checkpoint{Epoch: 2, Root: bytesutil.PadTo([]byte{'B'}, 32)}
|
||||
st2, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
||||
st2, err := stateV0.InitializeFromProto(&pb.BeaconState{
|
||||
Slot: 128,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@@ -55,7 +60,7 @@ func TestCheckpointStateCache_StateByCheckpoint(t *testing.T) {
|
||||
|
||||
func TestCheckpointStateCache_MaxSize(t *testing.T) {
|
||||
c := NewCheckpointStateCache()
|
||||
st, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
||||
st, err := stateV0.InitializeFromProto(&pb.BeaconState{
|
||||
Slot: 0,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
6
beacon-chain/cache/committee.go
vendored
6
beacon-chain/cache/committee.go
vendored
@@ -56,7 +56,7 @@ func NewCommitteesCache() *CommitteeCache {
|
||||
|
||||
// Committee fetches the shuffled indices by slot and committee index. Every list of indices
|
||||
// represent one committee. Returns true if the list exists with slot and committee index. Otherwise returns false, nil.
|
||||
func (c *CommitteeCache) Committee(slot types.Slot, seed [32]byte, index uint64) ([]uint64, error) {
|
||||
func (c *CommitteeCache) Committee(slot types.Slot, seed [32]byte, index types.CommitteeIndex) ([]types.ValidatorIndex, error) {
|
||||
c.lock.RLock()
|
||||
defer c.lock.RUnlock()
|
||||
|
||||
@@ -82,7 +82,7 @@ func (c *CommitteeCache) Committee(slot types.Slot, seed [32]byte, index uint64)
|
||||
committeeCountPerSlot = item.CommitteeCount / uint64(params.BeaconConfig().SlotsPerEpoch)
|
||||
}
|
||||
|
||||
indexOffSet := index + uint64(slot.ModSlot(params.BeaconConfig().SlotsPerEpoch).Mul(committeeCountPerSlot))
|
||||
indexOffSet := uint64(index) + uint64(slot.ModSlot(params.BeaconConfig().SlotsPerEpoch).Mul(committeeCountPerSlot))
|
||||
start, end := startEndIndices(item, indexOffSet)
|
||||
|
||||
if end > uint64(len(item.ShuffledIndices)) || end < start {
|
||||
@@ -106,7 +106,7 @@ func (c *CommitteeCache) AddCommitteeShuffledList(committees *Committees) error
|
||||
}
|
||||
|
||||
// ActiveIndices returns the active indices of a given seed stored in cache.
|
||||
func (c *CommitteeCache) ActiveIndices(seed [32]byte) ([]uint64, error) {
|
||||
func (c *CommitteeCache) ActiveIndices(seed [32]byte) ([]types.ValidatorIndex, error) {
|
||||
c.lock.RLock()
|
||||
defer c.lock.RUnlock()
|
||||
obj, exists, err := c.CommitteeCache.GetByKey(key(seed))
|
||||
|
||||
8
beacon-chain/cache/committee_disabled.go
vendored
8
beacon-chain/cache/committee_disabled.go
vendored
@@ -16,7 +16,7 @@ func NewCommitteesCache() *FakeCommitteeCache {
|
||||
|
||||
// Committee fetches the shuffled indices by slot and committee index. Every list of indices
|
||||
// represent one committee. Returns true if the list exists with slot and committee index. Otherwise returns false, nil.
|
||||
func (c *FakeCommitteeCache) Committee(slot types.Slot, seed [32]byte, index uint64) ([]uint64, error) {
|
||||
func (c *FakeCommitteeCache) Committee(slot types.Slot, seed [32]byte, index types.CommitteeIndex) ([]types.ValidatorIndex, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -27,12 +27,12 @@ func (c *FakeCommitteeCache) AddCommitteeShuffledList(committees *Committees) er
|
||||
}
|
||||
|
||||
// AddProposerIndicesList updates the committee shuffled list with proposer indices.
|
||||
func (c *FakeCommitteeCache) AddProposerIndicesList(seed [32]byte, indices []uint64) error {
|
||||
func (c *FakeCommitteeCache) AddProposerIndicesList(seed [32]byte, indices []types.ValidatorIndex) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ActiveIndices returns the active indices of a given seed stored in cache.
|
||||
func (c *FakeCommitteeCache) ActiveIndices(seed [32]byte) ([]uint64, error) {
|
||||
func (c *FakeCommitteeCache) ActiveIndices(seed [32]byte) ([]types.ValidatorIndex, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ func (c *FakeCommitteeCache) ActiveIndicesCount(seed [32]byte) (int, error) {
|
||||
}
|
||||
|
||||
// ProposerIndices returns the proposer indices of a given seed.
|
||||
func (c *FakeCommitteeCache) ProposerIndices(seed [32]byte) ([]uint64, error) {
|
||||
func (c *FakeCommitteeCache) ProposerIndices(seed [32]byte) ([]types.ValidatorIndex, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
||||
19
beacon-chain/cache/committee_test.go
vendored
19
beacon-chain/cache/committee_test.go
vendored
@@ -6,6 +6,7 @@ import (
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
|
||||
@@ -16,7 +17,7 @@ func TestCommitteeKeyFn_OK(t *testing.T) {
|
||||
item := &Committees{
|
||||
CommitteeCount: 1,
|
||||
Seed: [32]byte{'A'},
|
||||
ShuffledIndices: []uint64{1, 2, 3, 4, 5},
|
||||
ShuffledIndices: []types.ValidatorIndex{1, 2, 3, 4, 5},
|
||||
}
|
||||
|
||||
k, err := committeeKeyFn(item)
|
||||
@@ -33,13 +34,13 @@ func TestCommitteeCache_CommitteesByEpoch(t *testing.T) {
|
||||
cache := NewCommitteesCache()
|
||||
|
||||
item := &Committees{
|
||||
ShuffledIndices: []uint64{1, 2, 3, 4, 5, 6},
|
||||
ShuffledIndices: []types.ValidatorIndex{1, 2, 3, 4, 5, 6},
|
||||
Seed: [32]byte{'A'},
|
||||
CommitteeCount: 3,
|
||||
}
|
||||
|
||||
slot := params.BeaconConfig().SlotsPerEpoch
|
||||
committeeIndex := uint64(1)
|
||||
committeeIndex := types.CommitteeIndex(1)
|
||||
indices, err := cache.Committee(slot, item.Seed, committeeIndex)
|
||||
require.NoError(t, err)
|
||||
if indices != nil {
|
||||
@@ -47,18 +48,18 @@ func TestCommitteeCache_CommitteesByEpoch(t *testing.T) {
|
||||
}
|
||||
require.NoError(t, cache.AddCommitteeShuffledList(item))
|
||||
|
||||
wantedIndex := uint64(0)
|
||||
wantedIndex := types.CommitteeIndex(0)
|
||||
indices, err = cache.Committee(slot, item.Seed, wantedIndex)
|
||||
require.NoError(t, err)
|
||||
|
||||
start, end := startEndIndices(item, wantedIndex)
|
||||
start, end := startEndIndices(item, uint64(wantedIndex))
|
||||
assert.DeepEqual(t, item.ShuffledIndices[start:end], indices)
|
||||
}
|
||||
|
||||
func TestCommitteeCache_ActiveIndices(t *testing.T) {
|
||||
cache := NewCommitteesCache()
|
||||
|
||||
item := &Committees{Seed: [32]byte{'A'}, SortedIndices: []uint64{1, 2, 3, 4, 5, 6}}
|
||||
item := &Committees{Seed: [32]byte{'A'}, SortedIndices: []types.ValidatorIndex{1, 2, 3, 4, 5, 6}}
|
||||
indices, err := cache.ActiveIndices(item.Seed)
|
||||
require.NoError(t, err)
|
||||
if indices != nil {
|
||||
@@ -75,7 +76,7 @@ func TestCommitteeCache_ActiveIndices(t *testing.T) {
|
||||
func TestCommitteeCache_ActiveCount(t *testing.T) {
|
||||
cache := NewCommitteesCache()
|
||||
|
||||
item := &Committees{Seed: [32]byte{'A'}, SortedIndices: []uint64{1, 2, 3, 4, 5, 6}}
|
||||
item := &Committees{Seed: [32]byte{'A'}, SortedIndices: []types.ValidatorIndex{1, 2, 3, 4, 5, 6}}
|
||||
count, err := cache.ActiveIndicesCount(item.Seed)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 0, count, "Expected active count not to exist in empty cache")
|
||||
@@ -119,8 +120,8 @@ func TestCommitteeCacheOutOfRange(t *testing.T) {
|
||||
err := cache.CommitteeCache.Add(&Committees{
|
||||
CommitteeCount: 1,
|
||||
Seed: seed,
|
||||
ShuffledIndices: []uint64{0},
|
||||
SortedIndices: []uint64{},
|
||||
ShuffledIndices: []types.ValidatorIndex{0},
|
||||
SortedIndices: []types.ValidatorIndex{},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
|
||||
10
beacon-chain/cache/committees.go
vendored
10
beacon-chain/cache/committees.go
vendored
@@ -1,6 +1,10 @@
|
||||
package cache
|
||||
|
||||
import "errors"
|
||||
import (
|
||||
"errors"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
)
|
||||
|
||||
// ErrNotCommittee will be returned when a cache object is not a pointer to
|
||||
// a Committee struct.
|
||||
@@ -10,6 +14,6 @@ var ErrNotCommittee = errors.New("object is not a committee struct")
|
||||
type Committees struct {
|
||||
CommitteeCount uint64
|
||||
Seed [32]byte
|
||||
ShuffledIndices []uint64
|
||||
SortedIndices []uint64
|
||||
ShuffledIndices []types.ValidatorIndex
|
||||
SortedIndices []types.ValidatorIndex
|
||||
}
|
||||
|
||||
@@ -90,7 +90,9 @@ func (dc *DepositCache) InsertDeposit(ctx context.Context, d *ethpb.Deposit, blo
|
||||
defer dc.depositsLock.Unlock()
|
||||
// Keep the slice sorted on insertion in order to avoid costly sorting on retrieval.
|
||||
heightIdx := sort.Search(len(dc.deposits), func(i int) bool { return dc.deposits[i].Index >= index })
|
||||
newDeposits := append([]*dbpb.DepositContainer{{Deposit: d, Eth1BlockHeight: blockNum, DepositRoot: depositRoot[:], Index: index}}, dc.deposits[heightIdx:]...)
|
||||
newDeposits := append(
|
||||
[]*dbpb.DepositContainer{{Deposit: d, Eth1BlockHeight: blockNum, DepositRoot: depositRoot[:], Index: index}},
|
||||
dc.deposits[heightIdx:]...)
|
||||
dc.deposits = append(dc.deposits[:heightIdx], newDeposits...)
|
||||
historicalDepositsCount.Inc()
|
||||
}
|
||||
|
||||
3
beacon-chain/cache/proposer_indices.go
vendored
3
beacon-chain/cache/proposer_indices.go
vendored
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
@@ -75,7 +76,7 @@ func (c *ProposerIndicesCache) HasProposerIndices(r [32]byte) (bool, error) {
|
||||
}
|
||||
|
||||
// ProposerIndices returns the proposer indices of a block root seed.
|
||||
func (c *ProposerIndicesCache) ProposerIndices(r [32]byte) ([]uint64, error) {
|
||||
func (c *ProposerIndicesCache) ProposerIndices(r [32]byte) ([]types.ValidatorIndex, error) {
|
||||
c.lock.RLock()
|
||||
defer c.lock.RUnlock()
|
||||
obj, exists, err := c.ProposerIndicesCache.GetByKey(key(r))
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
// This file is used in fuzzer builds to bypass proposer indices caches.
|
||||
package cache
|
||||
|
||||
import types "github.com/prysmaticlabs/eth2-types"
|
||||
|
||||
// FakeProposerIndicesCache is a struct with 1 queue for looking up proposer indices by root.
|
||||
type FakeProposerIndicesCache struct {
|
||||
}
|
||||
@@ -19,7 +21,7 @@ func (c *FakeProposerIndicesCache) AddProposerIndices(p *ProposerIndices) error
|
||||
}
|
||||
|
||||
// ProposerIndices returns the proposer indices of a block root seed.
|
||||
func (c *FakeProposerIndicesCache) ProposerIndices(r [32]byte) ([]uint64, error) {
|
||||
func (c *FakeProposerIndicesCache) ProposerIndices(r [32]byte) ([]types.ValidatorIndex, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
||||
5
beacon-chain/cache/proposer_indices_test.go
vendored
5
beacon-chain/cache/proposer_indices_test.go
vendored
@@ -4,6 +4,7 @@ import (
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
@@ -12,7 +13,7 @@ import (
|
||||
func TestProposerKeyFn_OK(t *testing.T) {
|
||||
item := &ProposerIndices{
|
||||
BlockRoot: [32]byte{'A'},
|
||||
ProposerIndices: []uint64{1, 2, 3, 4, 5},
|
||||
ProposerIndices: []types.ValidatorIndex{1, 2, 3, 4, 5},
|
||||
}
|
||||
|
||||
k, err := proposerIndicesKeyFn(item)
|
||||
@@ -48,7 +49,7 @@ func TestProposerCache_AddProposerIndicesList(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, true, has)
|
||||
|
||||
item := &ProposerIndices{BlockRoot: [32]byte{'B'}, ProposerIndices: []uint64{1, 2, 3, 4, 5, 6}}
|
||||
item := &ProposerIndices{BlockRoot: [32]byte{'B'}, ProposerIndices: []types.ValidatorIndex{1, 2, 3, 4, 5, 6}}
|
||||
require.NoError(t, cache.AddProposerIndices(item))
|
||||
|
||||
received, err = cache.ProposerIndices(item.BlockRoot)
|
||||
|
||||
8
beacon-chain/cache/proposer_indices_type.go
vendored
8
beacon-chain/cache/proposer_indices_type.go
vendored
@@ -1,6 +1,10 @@
|
||||
package cache
|
||||
|
||||
import "errors"
|
||||
import (
|
||||
"errors"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
)
|
||||
|
||||
// ErrNotProposerIndices will be returned when a cache object is not a pointer to
|
||||
// a ProposerIndices struct.
|
||||
@@ -9,5 +13,5 @@ var ErrNotProposerIndices = errors.New("object is not a proposer indices struct"
|
||||
// ProposerIndices defines the cached struct for proposer indices.
|
||||
type ProposerIndices struct {
|
||||
BlockRoot [32]byte
|
||||
ProposerIndices []uint64
|
||||
ProposerIndices []types.ValidatorIndex
|
||||
}
|
||||
|
||||
8
beacon-chain/cache/skip_slot_cache.go
vendored
8
beacon-chain/cache/skip_slot_cache.go
vendored
@@ -9,7 +9,7 @@ import (
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
@@ -57,7 +57,7 @@ func (c *SkipSlotCache) Disable() {
|
||||
|
||||
// Get waits for any in progress calculation to complete before returning a
|
||||
// cached response, if any.
|
||||
func (c *SkipSlotCache) Get(ctx context.Context, r [32]byte) (*stateTrie.BeaconState, error) {
|
||||
func (c *SkipSlotCache) Get(ctx context.Context, r [32]byte) (iface.BeaconState, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "skipSlotCache.Get")
|
||||
defer span.End()
|
||||
if c.disabled {
|
||||
@@ -97,7 +97,7 @@ func (c *SkipSlotCache) Get(ctx context.Context, r [32]byte) (*stateTrie.BeaconS
|
||||
if exists && item != nil {
|
||||
skipSlotCacheHit.Inc()
|
||||
span.AddAttributes(trace.BoolAttribute("hit", true))
|
||||
return item.(*stateTrie.BeaconState).Copy(), nil
|
||||
return item.(iface.BeaconState).Copy(), nil
|
||||
}
|
||||
skipSlotCacheMiss.Inc()
|
||||
span.AddAttributes(trace.BoolAttribute("hit", false))
|
||||
@@ -136,7 +136,7 @@ func (c *SkipSlotCache) MarkNotInProgress(r [32]byte) error {
|
||||
}
|
||||
|
||||
// Put the response in the cache.
|
||||
func (c *SkipSlotCache) Put(_ context.Context, r [32]byte, state *stateTrie.BeaconState) error {
|
||||
func (c *SkipSlotCache) Put(_ context.Context, r [32]byte, state iface.BeaconState) error {
|
||||
if c.disabled {
|
||||
return nil
|
||||
}
|
||||
|
||||
7
beacon-chain/cache/skip_slot_cache_test.go
vendored
7
beacon-chain/cache/skip_slot_cache_test.go
vendored
@@ -5,7 +5,8 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateV0"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
@@ -18,11 +19,11 @@ func TestSkipSlotCache_RoundTrip(t *testing.T) {
|
||||
r := [32]byte{'a'}
|
||||
state, err := c.Get(ctx, r)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, (*stateTrie.BeaconState)(nil), state, "Empty cache returned an object")
|
||||
assert.Equal(t, iface.BeaconState(nil), state, "Empty cache returned an object")
|
||||
|
||||
require.NoError(t, c.MarkInProgress(r))
|
||||
|
||||
state, err = stateTrie.InitializeFromProto(&pb.BeaconState{
|
||||
state, err = stateV0.InitializeFromProto(&pb.BeaconState{
|
||||
Slot: 10,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
19
beacon-chain/cache/subnet_ids.go
vendored
19
beacon-chain/cache/subnet_ids.go
vendored
@@ -133,3 +133,22 @@ func (s *subnetIDs) AddPersistentCommittee(pubkey []byte, comIndex []uint64, dur
|
||||
|
||||
s.persistentSubnets.Set(string(pubkey), comIndex, duration)
|
||||
}
|
||||
|
||||
// EmptyAllCaches empties out all the related caches and flushes any stored
|
||||
// entries on them. This should only ever be used for testing, in normal
|
||||
// production, handling of the relevant subnets for each role is done
|
||||
// separately.
|
||||
func (s *subnetIDs) EmptyAllCaches() {
|
||||
// Clear the caches.
|
||||
s.attesterLock.Lock()
|
||||
s.attester.Purge()
|
||||
s.attesterLock.Unlock()
|
||||
|
||||
s.aggregatorLock.Lock()
|
||||
s.aggregator.Purge()
|
||||
s.aggregatorLock.Unlock()
|
||||
|
||||
s.subnetsLock.Lock()
|
||||
s.persistentSubnets.Flush()
|
||||
s.subnetsLock.Unlock()
|
||||
}
|
||||
|
||||
@@ -26,7 +26,8 @@ go_library(
|
||||
deps = [
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/core/validators:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//beacon-chain/state/interface:go_default_library",
|
||||
"//beacon-chain/state/stateV0:go_default_library",
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/attestationutil:go_default_library",
|
||||
"//shared/bls:go_default_library",
|
||||
@@ -70,8 +71,10 @@ go_test(
|
||||
shard_count = 2,
|
||||
deps = [
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/core/validators:go_default_library",
|
||||
"//beacon-chain/p2p/types:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//beacon-chain/state/interface:go_default_library",
|
||||
"//beacon-chain/state/stateV0:go_default_library",
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/aggregation:go_default_library",
|
||||
"//shared/aggregation/attestations:go_default_library",
|
||||
|
||||
@@ -5,9 +5,10 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/attestationutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/bls"
|
||||
@@ -19,9 +20,9 @@ import (
|
||||
// records.
|
||||
func ProcessAttestations(
|
||||
ctx context.Context,
|
||||
beaconState *stateTrie.BeaconState,
|
||||
beaconState iface.BeaconState,
|
||||
b *ethpb.SignedBeaconBlock,
|
||||
) (*stateTrie.BeaconState, error) {
|
||||
) (iface.BeaconState, error) {
|
||||
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -63,13 +64,13 @@ func ProcessAttestations(
|
||||
// assert data.source == state.previous_justified_checkpoint
|
||||
// state.previous_epoch_attestations.append(pending_attestation)
|
||||
//
|
||||
// # Check signature
|
||||
// # Verify signature
|
||||
// assert is_valid_indexed_attestation(state, get_indexed_attestation(state, attestation))
|
||||
func ProcessAttestation(
|
||||
ctx context.Context,
|
||||
beaconState *stateTrie.BeaconState,
|
||||
beaconState iface.BeaconState,
|
||||
att *ethpb.Attestation,
|
||||
) (*stateTrie.BeaconState, error) {
|
||||
) (iface.BeaconState, error) {
|
||||
beaconState, err := ProcessAttestationNoVerifySignature(ctx, beaconState, att)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -81,9 +82,9 @@ func ProcessAttestation(
|
||||
// records. The only difference would be that the attestation signature would not be verified.
|
||||
func ProcessAttestationsNoVerifySignature(
|
||||
ctx context.Context,
|
||||
beaconState *stateTrie.BeaconState,
|
||||
beaconState iface.BeaconState,
|
||||
b *ethpb.SignedBeaconBlock,
|
||||
) (*stateTrie.BeaconState, error) {
|
||||
) (iface.BeaconState, error) {
|
||||
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -98,39 +99,50 @@ func ProcessAttestationsNoVerifySignature(
|
||||
return beaconState, nil
|
||||
}
|
||||
|
||||
// ProcessAttestationNoVerifySignature processes the attestation without verifying the attestation signature. This
|
||||
// method is used to validate attestations whose signatures have already been verified.
|
||||
func ProcessAttestationNoVerifySignature(
|
||||
// VerifyAttestationNoVerifySignature verifies the attestation without verifying the attestation signature. This is
|
||||
// used before processing attestation with the beacon state.
|
||||
func VerifyAttestationNoVerifySignature(
|
||||
ctx context.Context,
|
||||
beaconState *stateTrie.BeaconState,
|
||||
beaconState iface.ReadOnlyBeaconState,
|
||||
att *ethpb.Attestation,
|
||||
) (*stateTrie.BeaconState, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "core.ProcessAttestationNoVerifySignature")
|
||||
) error {
|
||||
ctx, span := trace.StartSpan(ctx, "core.VerifyAttestationNoVerifySignature")
|
||||
defer span.End()
|
||||
|
||||
if err := helpers.ValidateNilAttestation(att); err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
currEpoch := helpers.CurrentEpoch(beaconState)
|
||||
prevEpoch := helpers.PrevEpoch(beaconState)
|
||||
data := att.Data
|
||||
if data.Target.Epoch != prevEpoch && data.Target.Epoch != currEpoch {
|
||||
return nil, fmt.Errorf(
|
||||
return fmt.Errorf(
|
||||
"expected target epoch (%d) to be the previous epoch (%d) or the current epoch (%d)",
|
||||
data.Target.Epoch,
|
||||
prevEpoch,
|
||||
currEpoch,
|
||||
)
|
||||
}
|
||||
|
||||
if data.Target.Epoch == currEpoch {
|
||||
if !beaconState.MatchCurrentJustifiedCheckpoint(data.Source) {
|
||||
return errors.New("source check point not equal to current justified checkpoint")
|
||||
}
|
||||
} else {
|
||||
if !beaconState.MatchPreviousJustifiedCheckpoint(data.Source) {
|
||||
return errors.New("source check point not equal to previous justified checkpoint")
|
||||
}
|
||||
}
|
||||
|
||||
if err := helpers.ValidateSlotTargetEpoch(att.Data); err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
s := att.Data.Slot
|
||||
minInclusionCheck := s+params.BeaconConfig().MinAttestationInclusionDelay <= beaconState.Slot()
|
||||
epochInclusionCheck := beaconState.Slot() <= s+params.BeaconConfig().SlotsPerEpoch
|
||||
if !minInclusionCheck {
|
||||
return nil, fmt.Errorf(
|
||||
return fmt.Errorf(
|
||||
"attestation slot %d + inclusion delay %d > state slot %d",
|
||||
s,
|
||||
params.BeaconConfig().MinAttestationInclusionDelay,
|
||||
@@ -138,7 +150,7 @@ func ProcessAttestationNoVerifySignature(
|
||||
)
|
||||
}
|
||||
if !epochInclusionCheck {
|
||||
return nil, fmt.Errorf(
|
||||
return fmt.Errorf(
|
||||
"state slot %d > attestation slot %d + SLOTS_PER_EPOCH %d",
|
||||
beaconState.Slot(),
|
||||
s,
|
||||
@@ -147,17 +159,47 @@ func ProcessAttestationNoVerifySignature(
|
||||
}
|
||||
activeValidatorCount, err := helpers.ActiveValidatorCount(beaconState, att.Data.Target.Epoch)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
c := helpers.SlotCommitteeCount(activeValidatorCount)
|
||||
if att.Data.CommitteeIndex >= c {
|
||||
return nil, fmt.Errorf("committee index %d >= committee count %d", att.Data.CommitteeIndex, c)
|
||||
if uint64(att.Data.CommitteeIndex) >= c {
|
||||
return fmt.Errorf("committee index %d >= committee count %d", att.Data.CommitteeIndex, c)
|
||||
}
|
||||
|
||||
if err := helpers.VerifyAttestationBitfieldLengths(beaconState, att); err != nil {
|
||||
return nil, errors.Wrap(err, "could not verify attestation bitfields")
|
||||
return errors.Wrap(err, "could not verify attestation bitfields")
|
||||
}
|
||||
|
||||
// Verify attesting indices are correct.
|
||||
committee, err := helpers.BeaconCommitteeFromState(beaconState, att.Data.Slot, att.Data.CommitteeIndex)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
indexedAtt, err := attestationutil.ConvertToIndexed(ctx, att, committee)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return attestationutil.IsValidAttestationIndices(ctx, indexedAtt)
|
||||
}
|
||||
|
||||
// ProcessAttestationNoVerifySignature processes the attestation without verifying the attestation signature. This
|
||||
// method is used to validate attestations whose signatures have already been verified.
|
||||
func ProcessAttestationNoVerifySignature(
|
||||
ctx context.Context,
|
||||
beaconState iface.BeaconState,
|
||||
att *ethpb.Attestation,
|
||||
) (iface.BeaconState, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "core.ProcessAttestationNoVerifySignature")
|
||||
defer span.End()
|
||||
|
||||
if err := VerifyAttestationNoVerifySignature(ctx, beaconState, att); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
currEpoch := helpers.CurrentEpoch(beaconState)
|
||||
data := att.Data
|
||||
s := att.Data.Slot
|
||||
proposerIndex, err := helpers.BeaconProposerIndex(beaconState)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -170,40 +212,21 @@ func ProcessAttestationNoVerifySignature(
|
||||
}
|
||||
|
||||
if data.Target.Epoch == currEpoch {
|
||||
if !beaconState.MatchCurrentJustifiedCheckpoint(data.Source) {
|
||||
return nil, errors.New("source check point not equal to current justified checkpoint")
|
||||
}
|
||||
if err := beaconState.AppendCurrentEpochAttestations(pendingAtt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
if !beaconState.MatchPreviousJustifiedCheckpoint(data.Source) {
|
||||
return nil, errors.New("source check point not equal to previous justified checkpoint")
|
||||
}
|
||||
if err := beaconState.AppendPreviousEpochAttestations(pendingAtt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Verify attesting indices are correct.
|
||||
committee, err := helpers.BeaconCommitteeFromState(beaconState, att.Data.Slot, att.Data.CommitteeIndex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
indexedAtt, err := attestationutil.ConvertToIndexed(ctx, att, committee)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := attestationutil.IsValidAttestationIndices(ctx, indexedAtt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return beaconState, nil
|
||||
}
|
||||
|
||||
// VerifyAttestationSignature converts and attestation into an indexed attestation and verifies
|
||||
// the signature in that attestation.
|
||||
func VerifyAttestationSignature(ctx context.Context, beaconState *stateTrie.BeaconState, att *ethpb.Attestation) error {
|
||||
func VerifyAttestationSignature(ctx context.Context, beaconState iface.ReadOnlyBeaconState, att *ethpb.Attestation) error {
|
||||
if err := helpers.ValidateNilAttestation(att); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -234,21 +257,26 @@ func VerifyAttestationSignature(ctx context.Context, beaconState *stateTrie.Beac
|
||||
// domain = get_domain(state, DOMAIN_BEACON_ATTESTER, indexed_attestation.data.target.epoch)
|
||||
// signing_root = compute_signing_root(indexed_attestation.data, domain)
|
||||
// return bls.FastAggregateVerify(pubkeys, signing_root, indexed_attestation.signature)
|
||||
func VerifyIndexedAttestation(ctx context.Context, beaconState *stateTrie.BeaconState, indexedAtt *ethpb.IndexedAttestation) error {
|
||||
func VerifyIndexedAttestation(ctx context.Context, beaconState iface.ReadOnlyBeaconState, indexedAtt *ethpb.IndexedAttestation) error {
|
||||
ctx, span := trace.StartSpan(ctx, "core.VerifyIndexedAttestation")
|
||||
defer span.End()
|
||||
|
||||
if err := attestationutil.IsValidAttestationIndices(ctx, indexedAtt); err != nil {
|
||||
return err
|
||||
}
|
||||
domain, err := helpers.Domain(beaconState.Fork(), indexedAtt.Data.Target.Epoch, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorRoot())
|
||||
domain, err := helpers.Domain(
|
||||
beaconState.Fork(),
|
||||
indexedAtt.Data.Target.Epoch,
|
||||
params.BeaconConfig().DomainBeaconAttester,
|
||||
beaconState.GenesisValidatorRoot(),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
indices := indexedAtt.AttestingIndices
|
||||
var pubkeys []bls.PublicKey
|
||||
for i := 0; i < len(indices); i++ {
|
||||
pubkeyAtIdx := beaconState.PubkeyAtIndex(indices[i])
|
||||
pubkeyAtIdx := beaconState.PubkeyAtIndex(types.ValidatorIndex(indices[i]))
|
||||
pk, err := bls.PublicKeyFromBytes(pubkeyAtIdx[:])
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not deserialize validator public key")
|
||||
|
||||
@@ -6,9 +6,13 @@ import (
|
||||
"testing"
|
||||
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateV0"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
)
|
||||
|
||||
@@ -33,7 +37,7 @@ func TestProcessAttestationNoVerifySignature_BeaconFuzzIssue78(t *testing.T) {
|
||||
if err := spb.UnmarshalSSZ(stateData); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
st, err := state.InitializeFromProtoUnsafe(spb)
|
||||
st, err := stateV0.InitializeFromProtoUnsafe(spb)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -42,3 +46,35 @@ func TestProcessAttestationNoVerifySignature_BeaconFuzzIssue78(t *testing.T) {
|
||||
_, err = blocks.ProcessAttestationNoVerifySignature(ctx, st, att)
|
||||
require.ErrorContains(t, "committee index 1 >= committee count 1", err)
|
||||
}
|
||||
|
||||
// Regression introduced in https://github.com/prysmaticlabs/prysm/pull/8566.
|
||||
func TestVerifyAttestationNoVerifySignature_IncorrectSourceEpoch(t *testing.T) {
|
||||
// Attestation with an empty signature
|
||||
|
||||
beaconState, _ := testutil.DeterministicGenesisState(t, 100)
|
||||
|
||||
aggBits := bitfield.NewBitlist(3)
|
||||
aggBits.SetBitAt(1, true)
|
||||
var mockRoot [32]byte
|
||||
copy(mockRoot[:], "hello-world")
|
||||
att := ðpb.Attestation{
|
||||
Data: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 99, Root: mockRoot[:]},
|
||||
Target: ðpb.Checkpoint{Epoch: 0, Root: make([]byte, 32)},
|
||||
},
|
||||
AggregationBits: aggBits,
|
||||
}
|
||||
|
||||
zeroSig := [96]byte{}
|
||||
att.Signature = zeroSig[:]
|
||||
|
||||
err := beaconState.SetSlot(beaconState.Slot() + params.BeaconConfig().MinAttestationInclusionDelay)
|
||||
require.NoError(t, err)
|
||||
ckp := beaconState.CurrentJustifiedCheckpoint()
|
||||
copy(ckp.Root, "hello-world")
|
||||
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(ckp))
|
||||
require.NoError(t, beaconState.AppendCurrentEpochAttestations(&pb.PendingAttestation{}))
|
||||
|
||||
err = blocks.VerifyAttestationNoVerifySignature(context.TODO(), beaconState, att)
|
||||
assert.NotEqual(t, nil, err)
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateV0"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/aggregation"
|
||||
attaggregation "github.com/prysmaticlabs/prysm/shared/aggregation/attestations"
|
||||
@@ -68,7 +68,7 @@ func TestProcessAttestations_NeitherCurrentNorPrevEpoch(t *testing.T) {
|
||||
pfc := beaconState.PreviousJustifiedCheckpoint()
|
||||
pfc.Root = []byte("hello-world")
|
||||
require.NoError(t, beaconState.SetPreviousJustifiedCheckpoint(pfc))
|
||||
require.NoError(t, beaconState.SetPreviousEpochAttestations([]*pb.PendingAttestation{}))
|
||||
require.NoError(t, beaconState.AppendPreviousEpochAttestations(&pb.PendingAttestation{}))
|
||||
|
||||
want := fmt.Sprintf(
|
||||
"expected target epoch (%d) to be the previous epoch (%d) or the current epoch (%d)",
|
||||
@@ -81,14 +81,13 @@ func TestProcessAttestations_NeitherCurrentNorPrevEpoch(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestProcessAttestations_CurrentEpochFFGDataMismatches(t *testing.T) {
|
||||
aggBits := bitfield.NewBitlist(3)
|
||||
attestations := []*ethpb.Attestation{
|
||||
{
|
||||
Data: ðpb.AttestationData{
|
||||
Target: ðpb.Checkpoint{Epoch: 0, Root: make([]byte, 32)},
|
||||
Source: ðpb.Checkpoint{Epoch: 1, Root: make([]byte, 32)},
|
||||
},
|
||||
AggregationBits: aggBits,
|
||||
AggregationBits: bitfield.Bitlist{0x09},
|
||||
},
|
||||
}
|
||||
b := testutil.NewBeaconBlock()
|
||||
@@ -102,7 +101,7 @@ func TestProcessAttestations_CurrentEpochFFGDataMismatches(t *testing.T) {
|
||||
cfc := beaconState.CurrentJustifiedCheckpoint()
|
||||
cfc.Root = []byte("hello-world")
|
||||
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(cfc))
|
||||
require.NoError(t, beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{}))
|
||||
require.NoError(t, beaconState.AppendCurrentEpochAttestations(&pb.PendingAttestation{}))
|
||||
|
||||
want := "source check point not equal to current justified checkpoint"
|
||||
_, err := blocks.ProcessAttestations(context.Background(), beaconState, b)
|
||||
@@ -140,7 +139,7 @@ func TestProcessAttestations_PrevEpochFFGDataMismatches(t *testing.T) {
|
||||
pfc := beaconState.PreviousJustifiedCheckpoint()
|
||||
pfc.Root = []byte("hello-world")
|
||||
require.NoError(t, beaconState.SetPreviousJustifiedCheckpoint(pfc))
|
||||
require.NoError(t, beaconState.SetPreviousEpochAttestations([]*pb.PendingAttestation{}))
|
||||
require.NoError(t, beaconState.AppendPreviousEpochAttestations(&pb.PendingAttestation{}))
|
||||
|
||||
want := "source check point not equal to previous justified checkpoint"
|
||||
_, err = blocks.ProcessAttestations(context.Background(), beaconState, b)
|
||||
@@ -176,7 +175,7 @@ func TestProcessAttestations_InvalidAggregationBitsLength(t *testing.T) {
|
||||
cfc := beaconState.CurrentJustifiedCheckpoint()
|
||||
cfc.Root = []byte("hello-world")
|
||||
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(cfc))
|
||||
require.NoError(t, beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{}))
|
||||
require.NoError(t, beaconState.AppendCurrentEpochAttestations(&pb.PendingAttestation{}))
|
||||
|
||||
expected := "failed to verify aggregation bitfield: wanted participants bitfield length 3, got: 4"
|
||||
_, err = blocks.ProcessAttestations(context.Background(), beaconState, b)
|
||||
@@ -201,7 +200,7 @@ func TestProcessAttestations_OK(t *testing.T) {
|
||||
cfc := beaconState.CurrentJustifiedCheckpoint()
|
||||
cfc.Root = mockRoot[:]
|
||||
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(cfc))
|
||||
require.NoError(t, beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{}))
|
||||
require.NoError(t, beaconState.AppendCurrentEpochAttestations(&pb.PendingAttestation{}))
|
||||
|
||||
committee, err := helpers.BeaconCommitteeFromState(beaconState, att.Data.Slot, att.Data.CommitteeIndex)
|
||||
require.NoError(t, err)
|
||||
@@ -243,7 +242,7 @@ func TestProcessAggregatedAttestation_OverlappingBits(t *testing.T) {
|
||||
cfc := beaconState.CurrentJustifiedCheckpoint()
|
||||
cfc.Root = bytesutil.PadTo([]byte("hello-world"), 32)
|
||||
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(cfc))
|
||||
require.NoError(t, beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{}))
|
||||
require.NoError(t, beaconState.AppendCurrentEpochAttestations(&pb.PendingAttestation{}))
|
||||
|
||||
committee, err := helpers.BeaconCommitteeFromState(beaconState, att1.Data.Slot, att1.Data.CommitteeIndex)
|
||||
require.NoError(t, err)
|
||||
@@ -306,7 +305,7 @@ func TestProcessAggregatedAttestation_NoOverlappingBits(t *testing.T) {
|
||||
cfc := beaconState.CurrentJustifiedCheckpoint()
|
||||
cfc.Root = mockRoot[:]
|
||||
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(cfc))
|
||||
require.NoError(t, beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{}))
|
||||
require.NoError(t, beaconState.AppendCurrentEpochAttestations(&pb.PendingAttestation{}))
|
||||
|
||||
committee, err := helpers.BeaconCommitteeFromState(beaconState, att1.Data.Slot, att1.Data.CommitteeIndex)
|
||||
require.NoError(t, err)
|
||||
@@ -357,7 +356,7 @@ func TestProcessAggregatedAttestation_NoOverlappingBits(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestProcessAttestationsNoVerify_IncorrectSlotTargetEpoch(t *testing.T) {
|
||||
func TestVerifyAttestationNoVerifySignature_IncorrectSlotTargetEpoch(t *testing.T) {
|
||||
beaconState, _ := testutil.DeterministicGenesisState(t, 1)
|
||||
|
||||
att := testutil.HydrateAttestation(ðpb.Attestation{
|
||||
@@ -367,7 +366,7 @@ func TestProcessAttestationsNoVerify_IncorrectSlotTargetEpoch(t *testing.T) {
|
||||
},
|
||||
})
|
||||
wanted := "slot 32 does not match target epoch 0"
|
||||
_, err := blocks.ProcessAttestationNoVerifySignature(context.TODO(), beaconState, att)
|
||||
err := blocks.VerifyAttestationNoVerifySignature(context.TODO(), beaconState, att)
|
||||
assert.ErrorContains(t, wanted, err)
|
||||
}
|
||||
|
||||
@@ -396,13 +395,44 @@ func TestProcessAttestationsNoVerify_OK(t *testing.T) {
|
||||
ckp := beaconState.CurrentJustifiedCheckpoint()
|
||||
copy(ckp.Root, "hello-world")
|
||||
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(ckp))
|
||||
require.NoError(t, beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{}))
|
||||
require.NoError(t, beaconState.AppendCurrentEpochAttestations(&pb.PendingAttestation{}))
|
||||
|
||||
_, err = blocks.ProcessAttestationNoVerifySignature(context.TODO(), beaconState, att)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestProcessAttestationsNoVerify_BadAttIdx(t *testing.T) {
|
||||
func TestVerifyAttestationNoVerifySignature_OK(t *testing.T) {
|
||||
// Attestation with an empty signature
|
||||
|
||||
beaconState, _ := testutil.DeterministicGenesisState(t, 100)
|
||||
|
||||
aggBits := bitfield.NewBitlist(3)
|
||||
aggBits.SetBitAt(1, true)
|
||||
var mockRoot [32]byte
|
||||
copy(mockRoot[:], "hello-world")
|
||||
att := ðpb.Attestation{
|
||||
Data: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 0, Root: mockRoot[:]},
|
||||
Target: ðpb.Checkpoint{Epoch: 0, Root: make([]byte, 32)},
|
||||
},
|
||||
AggregationBits: aggBits,
|
||||
}
|
||||
|
||||
zeroSig := [96]byte{}
|
||||
att.Signature = zeroSig[:]
|
||||
|
||||
err := beaconState.SetSlot(beaconState.Slot() + params.BeaconConfig().MinAttestationInclusionDelay)
|
||||
require.NoError(t, err)
|
||||
ckp := beaconState.CurrentJustifiedCheckpoint()
|
||||
copy(ckp.Root, "hello-world")
|
||||
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(ckp))
|
||||
require.NoError(t, beaconState.AppendCurrentEpochAttestations(&pb.PendingAttestation{}))
|
||||
|
||||
err = blocks.VerifyAttestationNoVerifySignature(context.TODO(), beaconState, att)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestVerifyAttestationNoVerifySignature_BadAttIdx(t *testing.T) {
|
||||
beaconState, _ := testutil.DeterministicGenesisState(t, 100)
|
||||
aggBits := bitfield.NewBitlist(3)
|
||||
aggBits.SetBitAt(1, true)
|
||||
@@ -422,8 +452,8 @@ func TestProcessAttestationsNoVerify_BadAttIdx(t *testing.T) {
|
||||
ckp := beaconState.CurrentJustifiedCheckpoint()
|
||||
copy(ckp.Root, "hello-world")
|
||||
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(ckp))
|
||||
require.NoError(t, beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{}))
|
||||
_, err := blocks.ProcessAttestationNoVerifySignature(context.TODO(), beaconState, att)
|
||||
require.NoError(t, beaconState.AppendCurrentEpochAttestations(&pb.PendingAttestation{}))
|
||||
err := blocks.VerifyAttestationNoVerifySignature(context.TODO(), beaconState, att)
|
||||
require.ErrorContains(t, "committee index 100 >= committee count 1", err)
|
||||
}
|
||||
|
||||
@@ -436,7 +466,7 @@ func TestConvertToIndexed_OK(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
state, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
||||
state, err := stateV0.InitializeFromProto(&pb.BeaconState{
|
||||
Slot: 5,
|
||||
Validators: validators,
|
||||
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
|
||||
@@ -494,7 +524,7 @@ func TestVerifyIndexedAttestation_OK(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
state, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
||||
state, err := stateV0.InitializeFromProto(&pb.BeaconState{
|
||||
Slot: 5,
|
||||
Validators: validators,
|
||||
Fork: &pb.Fork{
|
||||
@@ -581,7 +611,7 @@ func TestValidateIndexedAttestation_AboveMaxLength(t *testing.T) {
|
||||
}
|
||||
|
||||
want := "validator indices count exceeds MAX_VALIDATORS_PER_COMMITTEE"
|
||||
err := blocks.VerifyIndexedAttestation(context.Background(), &stateTrie.BeaconState{}, indexedAtt1)
|
||||
err := blocks.VerifyIndexedAttestation(context.Background(), &stateV0.BeaconState{}, indexedAtt1)
|
||||
assert.ErrorContains(t, want, err)
|
||||
}
|
||||
|
||||
|
||||
@@ -5,10 +5,10 @@ import (
|
||||
"sort"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
v "github.com/prysmaticlabs/prysm/beacon-chain/core/validators"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
|
||||
"github.com/prysmaticlabs/prysm/shared/attestationutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/slashutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/sliceutil"
|
||||
@@ -35,15 +35,11 @@ import (
|
||||
// assert slashed_any
|
||||
func ProcessAttesterSlashings(
|
||||
ctx context.Context,
|
||||
beaconState *stateTrie.BeaconState,
|
||||
b *ethpb.SignedBeaconBlock,
|
||||
) (*stateTrie.BeaconState, error) {
|
||||
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
body := b.Block.Body
|
||||
for idx, slashing := range body.AttesterSlashings {
|
||||
beaconState iface.BeaconState,
|
||||
slashings []*ethpb.AttesterSlashing,
|
||||
slashFunc slashValidatorFunc,
|
||||
) (iface.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)
|
||||
}
|
||||
@@ -54,14 +50,14 @@ func ProcessAttesterSlashings(
|
||||
currentEpoch := helpers.SlotToEpoch(beaconState.Slot())
|
||||
var err error
|
||||
var slashedAny bool
|
||||
var val stateTrie.ReadOnlyValidator
|
||||
var val iface.ReadOnlyValidator
|
||||
for _, validatorIndex := range slashableIndices {
|
||||
val, err = beaconState.ValidatorAtIndexReadOnly(validatorIndex)
|
||||
val, err = beaconState.ValidatorAtIndexReadOnly(types.ValidatorIndex(validatorIndex))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if helpers.IsSlashableValidator(val.ActivationEpoch(), val.WithdrawableEpoch(), val.Slashed(), currentEpoch) {
|
||||
beaconState, err = v.SlashValidator(beaconState, validatorIndex)
|
||||
beaconState, err = slashFunc(beaconState, types.ValidatorIndex(validatorIndex))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not slash validator index %d",
|
||||
validatorIndex)
|
||||
@@ -77,7 +73,7 @@ func ProcessAttesterSlashings(
|
||||
}
|
||||
|
||||
// VerifyAttesterSlashing validates the attestation data in both attestations in the slashing object.
|
||||
func VerifyAttesterSlashing(ctx context.Context, beaconState *stateTrie.BeaconState, slashing *ethpb.AttesterSlashing) error {
|
||||
func VerifyAttesterSlashing(ctx context.Context, beaconState iface.ReadOnlyBeaconState, slashing *ethpb.AttesterSlashing) error {
|
||||
if slashing == nil {
|
||||
return errors.New("nil slashing")
|
||||
}
|
||||
|
||||
@@ -8,7 +8,8 @@ import (
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
v "github.com/prysmaticlabs/prysm/beacon-chain/core/validators"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateV0"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bls"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
@@ -46,7 +47,7 @@ func TestProcessAttesterSlashings_DataNotSlashable(t *testing.T) {
|
||||
var registry []*ethpb.Validator
|
||||
currentSlot := types.Slot(0)
|
||||
|
||||
beaconState, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
||||
beaconState, err := stateV0.InitializeFromProto(&pb.BeaconState{
|
||||
Validators: registry,
|
||||
Slot: currentSlot,
|
||||
})
|
||||
@@ -57,7 +58,7 @@ func TestProcessAttesterSlashings_DataNotSlashable(t *testing.T) {
|
||||
AttesterSlashings: slashings,
|
||||
},
|
||||
}
|
||||
_, err = blocks.ProcessAttesterSlashings(context.Background(), beaconState, b)
|
||||
_, err = blocks.ProcessAttesterSlashings(context.Background(), beaconState, b.Block.Body.AttesterSlashings, v.SlashValidator)
|
||||
assert.ErrorContains(t, "attestations are not slashable", err)
|
||||
}
|
||||
|
||||
@@ -65,7 +66,7 @@ func TestProcessAttesterSlashings_IndexedAttestationFailedToVerify(t *testing.T)
|
||||
var registry []*ethpb.Validator
|
||||
currentSlot := types.Slot(0)
|
||||
|
||||
beaconState, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
||||
beaconState, err := stateV0.InitializeFromProto(&pb.BeaconState{
|
||||
Validators: registry,
|
||||
Slot: currentSlot,
|
||||
})
|
||||
@@ -92,7 +93,7 @@ func TestProcessAttesterSlashings_IndexedAttestationFailedToVerify(t *testing.T)
|
||||
},
|
||||
}
|
||||
|
||||
_, err = blocks.ProcessAttesterSlashings(context.Background(), beaconState, b)
|
||||
_, err = blocks.ProcessAttesterSlashings(context.Background(), beaconState, b.Block.Body.AttesterSlashings, v.SlashValidator)
|
||||
assert.ErrorContains(t, "validator indices count exceeds MAX_VALIDATORS_PER_COMMITTEE", err)
|
||||
}
|
||||
|
||||
@@ -144,7 +145,7 @@ func TestProcessAttesterSlashings_AppliesCorrectStatus(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
newState, err := blocks.ProcessAttesterSlashings(context.Background(), beaconState, b)
|
||||
newState, err := blocks.ProcessAttesterSlashings(context.Background(), beaconState, b.Block.Body.AttesterSlashings, v.SlashValidator)
|
||||
require.NoError(t, err)
|
||||
newRegistry := newState.Validators()
|
||||
|
||||
|
||||
@@ -7,7 +7,8 @@ import (
|
||||
fuzz "github.com/google/gofuzz"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
eth "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
v "github.com/prysmaticlabs/prysm/beacon-chain/core/validators"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateV0"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
@@ -22,7 +23,7 @@ func TestFuzzProcessAttestationNoVerify_10000(t *testing.T) {
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(att)
|
||||
s, err := stateTrie.InitializeFromProtoUnsafe(state)
|
||||
s, err := stateV0.InitializeFromProtoUnsafe(state)
|
||||
require.NoError(t, err)
|
||||
_, err = ProcessAttestationNoVerifySignature(ctx, s, att)
|
||||
_ = err
|
||||
@@ -38,7 +39,7 @@ func TestFuzzProcessBlockHeader_10000(t *testing.T) {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(block)
|
||||
|
||||
s, err := stateTrie.InitializeFromProtoUnsafe(state)
|
||||
s, err := stateV0.InitializeFromProtoUnsafe(state)
|
||||
require.NoError(t, err)
|
||||
_, err = ProcessBlockHeader(context.Background(), s, block)
|
||||
_ = err
|
||||
@@ -71,14 +72,14 @@ func TestFuzzverifyDepositDataSigningRoot_10000(t *testing.T) {
|
||||
|
||||
func TestFuzzProcessEth1DataInBlock_10000(t *testing.T) {
|
||||
fuzzer := fuzz.NewWithSeed(0)
|
||||
b := ð.SignedBeaconBlock{}
|
||||
state := &stateTrie.BeaconState{}
|
||||
e := ð.Eth1Data{}
|
||||
state := &stateV0.BeaconState{}
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(b)
|
||||
s, err := ProcessEth1DataInBlock(context.Background(), state, b)
|
||||
fuzzer.Fuzz(e)
|
||||
s, err := ProcessEth1DataInBlock(context.Background(), state, e)
|
||||
if err != nil && s != nil {
|
||||
t.Fatalf("state should be nil on err. found: %v on error: %v for state: %v and block: %v", s, err, state, b)
|
||||
t.Fatalf("state should be nil on err. found: %v on error: %v for state: %v and eth1data: %v", s, err, state, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -103,7 +104,7 @@ func TestFuzzEth1DataHasEnoughSupport_10000(t *testing.T) {
|
||||
for i := 0; i < 100000; i++ {
|
||||
fuzzer.Fuzz(eth1data)
|
||||
fuzzer.Fuzz(&stateVotes)
|
||||
s, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
||||
s, err := stateV0.InitializeFromProto(&pb.BeaconState{
|
||||
Eth1DataVotes: stateVotes,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@@ -121,9 +122,9 @@ func TestFuzzProcessBlockHeaderNoVerify_10000(t *testing.T) {
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(block)
|
||||
s, err := stateTrie.InitializeFromProtoUnsafe(state)
|
||||
s, err := stateV0.InitializeFromProtoUnsafe(state)
|
||||
require.NoError(t, err)
|
||||
_, err = ProcessBlockHeaderNoVerify(s, block)
|
||||
_, err = ProcessBlockHeaderNoVerify(s, block.Slot, block.ProposerIndex, block.ParentRoot, []byte{})
|
||||
_ = err
|
||||
}
|
||||
}
|
||||
@@ -136,7 +137,7 @@ func TestFuzzProcessRandao_10000(t *testing.T) {
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(b)
|
||||
s, err := stateTrie.InitializeFromProtoUnsafe(state)
|
||||
s, err := stateV0.InitializeFromProtoUnsafe(state)
|
||||
require.NoError(t, err)
|
||||
r, err := ProcessRandao(context.Background(), s, b)
|
||||
if err != nil && r != nil {
|
||||
@@ -153,9 +154,9 @@ func TestFuzzProcessRandaoNoVerify_10000(t *testing.T) {
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(blockBody)
|
||||
s, err := stateTrie.InitializeFromProtoUnsafe(state)
|
||||
s, err := stateV0.InitializeFromProtoUnsafe(state)
|
||||
require.NoError(t, err)
|
||||
r, err := ProcessRandaoNoVerify(s, blockBody)
|
||||
r, err := ProcessRandaoNoVerify(s, blockBody.RandaoReveal)
|
||||
if err != nil && r != nil {
|
||||
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, blockBody)
|
||||
}
|
||||
@@ -165,16 +166,16 @@ func TestFuzzProcessRandaoNoVerify_10000(t *testing.T) {
|
||||
func TestFuzzProcessProposerSlashings_10000(t *testing.T) {
|
||||
fuzzer := fuzz.NewWithSeed(0)
|
||||
state := &pb.BeaconState{}
|
||||
b := ð.SignedBeaconBlock{}
|
||||
p := ð.ProposerSlashing{}
|
||||
ctx := context.Background()
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(b)
|
||||
s, err := stateTrie.InitializeFromProtoUnsafe(state)
|
||||
fuzzer.Fuzz(p)
|
||||
s, err := stateV0.InitializeFromProtoUnsafe(state)
|
||||
require.NoError(t, err)
|
||||
r, err := ProcessProposerSlashings(ctx, s, b)
|
||||
r, err := ProcessProposerSlashings(ctx, s, []*eth.ProposerSlashing{p}, v.SlashValidator)
|
||||
if err != nil && r != nil {
|
||||
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, b)
|
||||
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and slashing: %v", r, err, state, p)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -186,7 +187,7 @@ func TestFuzzVerifyProposerSlashing_10000(t *testing.T) {
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(proposerSlashing)
|
||||
s, err := stateTrie.InitializeFromProtoUnsafe(state)
|
||||
s, err := stateV0.InitializeFromProtoUnsafe(state)
|
||||
require.NoError(t, err)
|
||||
err = VerifyProposerSlashing(s, proposerSlashing)
|
||||
_ = err
|
||||
@@ -196,16 +197,16 @@ func TestFuzzVerifyProposerSlashing_10000(t *testing.T) {
|
||||
func TestFuzzProcessAttesterSlashings_10000(t *testing.T) {
|
||||
fuzzer := fuzz.NewWithSeed(0)
|
||||
state := &pb.BeaconState{}
|
||||
b := ð.SignedBeaconBlock{}
|
||||
a := ð.AttesterSlashing{}
|
||||
ctx := context.Background()
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(b)
|
||||
s, err := stateTrie.InitializeFromProtoUnsafe(state)
|
||||
fuzzer.Fuzz(a)
|
||||
s, err := stateV0.InitializeFromProtoUnsafe(state)
|
||||
require.NoError(t, err)
|
||||
r, err := ProcessAttesterSlashings(ctx, s, b)
|
||||
r, err := ProcessAttesterSlashings(ctx, s, []*eth.AttesterSlashing{a}, v.SlashValidator)
|
||||
if err != nil && r != nil {
|
||||
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, b)
|
||||
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and slashing: %v", r, err, state, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -218,7 +219,7 @@ func TestFuzzVerifyAttesterSlashing_10000(t *testing.T) {
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(attesterSlashing)
|
||||
s, err := stateTrie.InitializeFromProtoUnsafe(state)
|
||||
s, err := stateV0.InitializeFromProtoUnsafe(state)
|
||||
require.NoError(t, err)
|
||||
err = VerifyAttesterSlashing(ctx, s, attesterSlashing)
|
||||
_ = err
|
||||
@@ -255,7 +256,7 @@ func TestFuzzProcessAttestations_10000(t *testing.T) {
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(b)
|
||||
s, err := stateTrie.InitializeFromProtoUnsafe(state)
|
||||
s, err := stateV0.InitializeFromProtoUnsafe(state)
|
||||
require.NoError(t, err)
|
||||
r, err := ProcessAttestations(ctx, s, b)
|
||||
if err != nil && r != nil {
|
||||
@@ -272,7 +273,7 @@ func TestFuzzProcessAttestationsNoVerify_10000(t *testing.T) {
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(b)
|
||||
s, err := stateTrie.InitializeFromProtoUnsafe(state)
|
||||
s, err := stateV0.InitializeFromProtoUnsafe(state)
|
||||
require.NoError(t, err)
|
||||
r, err := ProcessAttestationsNoVerifySignature(ctx, s, b)
|
||||
if err != nil && r != nil {
|
||||
@@ -289,7 +290,7 @@ func TestFuzzProcessAttestation_10000(t *testing.T) {
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(attestation)
|
||||
s, err := stateTrie.InitializeFromProtoUnsafe(state)
|
||||
s, err := stateV0.InitializeFromProtoUnsafe(state)
|
||||
require.NoError(t, err)
|
||||
r, err := ProcessAttestation(ctx, s, attestation)
|
||||
if err != nil && r != nil {
|
||||
@@ -306,7 +307,7 @@ func TestFuzzVerifyIndexedAttestationn_10000(t *testing.T) {
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(idxAttestation)
|
||||
s, err := stateTrie.InitializeFromProtoUnsafe(state)
|
||||
s, err := stateV0.InitializeFromProtoUnsafe(state)
|
||||
require.NoError(t, err)
|
||||
err = VerifyIndexedAttestation(ctx, s, idxAttestation)
|
||||
_ = err
|
||||
@@ -321,7 +322,7 @@ func TestFuzzVerifyAttestation_10000(t *testing.T) {
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(attestation)
|
||||
s, err := stateTrie.InitializeFromProtoUnsafe(state)
|
||||
s, err := stateV0.InitializeFromProtoUnsafe(state)
|
||||
require.NoError(t, err)
|
||||
err = VerifyAttestationSignature(ctx, s, attestation)
|
||||
_ = err
|
||||
@@ -331,16 +332,18 @@ func TestFuzzVerifyAttestation_10000(t *testing.T) {
|
||||
func TestFuzzProcessDeposits_10000(t *testing.T) {
|
||||
fuzzer := fuzz.NewWithSeed(0)
|
||||
state := &pb.BeaconState{}
|
||||
b := ð.SignedBeaconBlock{}
|
||||
deposits := make([]*eth.Deposit, 100)
|
||||
ctx := context.Background()
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(b)
|
||||
s, err := stateTrie.InitializeFromProtoUnsafe(state)
|
||||
for i := range deposits {
|
||||
fuzzer.Fuzz(deposits[i])
|
||||
}
|
||||
s, err := stateV0.InitializeFromProtoUnsafe(state)
|
||||
require.NoError(t, err)
|
||||
r, err := ProcessDeposits(ctx, s, b)
|
||||
r, err := ProcessDeposits(ctx, s, deposits)
|
||||
if err != nil && r != nil {
|
||||
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, b)
|
||||
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, deposits)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -354,7 +357,7 @@ func TestFuzzProcessPreGenesisDeposit_10000(t *testing.T) {
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(deposit)
|
||||
s, err := stateTrie.InitializeFromProtoUnsafe(state)
|
||||
s, err := stateV0.InitializeFromProtoUnsafe(state)
|
||||
require.NoError(t, err)
|
||||
r, err := ProcessPreGenesisDeposits(ctx, s, []*eth.Deposit{deposit})
|
||||
if err != nil && r != nil {
|
||||
@@ -371,7 +374,7 @@ func TestFuzzProcessDeposit_10000(t *testing.T) {
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(deposit)
|
||||
s, err := stateTrie.InitializeFromProtoUnsafe(state)
|
||||
s, err := stateV0.InitializeFromProtoUnsafe(state)
|
||||
require.NoError(t, err)
|
||||
r, err := ProcessDeposit(s, deposit, true)
|
||||
if err != nil && r != nil {
|
||||
@@ -387,7 +390,7 @@ func TestFuzzverifyDeposit_10000(t *testing.T) {
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(deposit)
|
||||
s, err := stateTrie.InitializeFromProtoUnsafe(state)
|
||||
s, err := stateV0.InitializeFromProtoUnsafe(state)
|
||||
require.NoError(t, err)
|
||||
err = verifyDeposit(s, deposit)
|
||||
_ = err
|
||||
@@ -397,16 +400,16 @@ func TestFuzzverifyDeposit_10000(t *testing.T) {
|
||||
func TestFuzzProcessVoluntaryExits_10000(t *testing.T) {
|
||||
fuzzer := fuzz.NewWithSeed(0)
|
||||
state := &pb.BeaconState{}
|
||||
b := ð.SignedBeaconBlock{}
|
||||
e := ð.SignedVoluntaryExit{}
|
||||
ctx := context.Background()
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(b)
|
||||
s, err := stateTrie.InitializeFromProtoUnsafe(state)
|
||||
fuzzer.Fuzz(e)
|
||||
s, err := stateV0.InitializeFromProtoUnsafe(state)
|
||||
require.NoError(t, err)
|
||||
r, err := ProcessVoluntaryExits(ctx, s, b)
|
||||
r, err := ProcessVoluntaryExits(ctx, s, []*eth.SignedVoluntaryExit{e})
|
||||
if err != nil && r != nil {
|
||||
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, b)
|
||||
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and exit: %v", r, err, state, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -414,15 +417,15 @@ func TestFuzzProcessVoluntaryExits_10000(t *testing.T) {
|
||||
func TestFuzzProcessVoluntaryExitsNoVerify_10000(t *testing.T) {
|
||||
fuzzer := fuzz.NewWithSeed(0)
|
||||
state := &pb.BeaconState{}
|
||||
b := ð.SignedBeaconBlock{}
|
||||
e := ð.SignedVoluntaryExit{}
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(b)
|
||||
s, err := stateTrie.InitializeFromProtoUnsafe(state)
|
||||
fuzzer.Fuzz(e)
|
||||
s, err := stateV0.InitializeFromProtoUnsafe(state)
|
||||
require.NoError(t, err)
|
||||
r, err := ProcessVoluntaryExits(context.Background(), s, b)
|
||||
r, err := ProcessVoluntaryExits(context.Background(), s, []*eth.SignedVoluntaryExit{e})
|
||||
if err != nil && r != nil {
|
||||
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, b)
|
||||
t.Fatalf("return value should be nil on err. found: %v on error: %v for state: %v and block: %v", r, err, state, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -430,7 +433,7 @@ func TestFuzzProcessVoluntaryExitsNoVerify_10000(t *testing.T) {
|
||||
func TestFuzzVerifyExit_10000(t *testing.T) {
|
||||
fuzzer := fuzz.NewWithSeed(0)
|
||||
ve := ð.SignedVoluntaryExit{}
|
||||
val := stateTrie.ReadOnlyValidator{}
|
||||
val := stateV0.ReadOnlyValidator{}
|
||||
fork := &pb.Fork{}
|
||||
var slot types.Slot
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
v "github.com/prysmaticlabs/prysm/beacon-chain/core/validators"
|
||||
"github.com/prysmaticlabs/prysm/shared/bls"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
@@ -90,7 +91,7 @@ func TestProcessAttesterSlashings_RegressionSlashableIndices(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
newState, err := blocks.ProcessAttesterSlashings(context.Background(), beaconState, b)
|
||||
newState, err := blocks.ProcessAttesterSlashings(context.Background(), beaconState, b.Block.Body.AttesterSlashings, v.SlashValidator)
|
||||
require.NoError(t, err)
|
||||
newRegistry := newState.Validators()
|
||||
if !newRegistry[expectedSlashedVal].Slashed {
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bls"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
@@ -20,15 +20,23 @@ import (
|
||||
// ProcessPreGenesisDeposits processes a deposit for the beacon state before chainstart.
|
||||
func ProcessPreGenesisDeposits(
|
||||
ctx context.Context,
|
||||
beaconState *stateTrie.BeaconState,
|
||||
beaconState iface.BeaconState,
|
||||
deposits []*ethpb.Deposit,
|
||||
) (*stateTrie.BeaconState, error) {
|
||||
) (iface.BeaconState, error) {
|
||||
var err error
|
||||
beaconState, err = ProcessDeposits(ctx, beaconState, ðpb.SignedBeaconBlock{
|
||||
Block: ðpb.BeaconBlock{Body: ðpb.BeaconBlockBody{Deposits: deposits}}})
|
||||
beaconState, err = ProcessDeposits(ctx, beaconState, deposits)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not process deposit")
|
||||
}
|
||||
beaconState, err = activateValidatorWithEffectiveBalance(beaconState, deposits)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return beaconState, nil
|
||||
}
|
||||
|
||||
// This updates validator's effective balance, and if it's above MaxEffectiveBalance, validator becomes active in genesis.
|
||||
func activateValidatorWithEffectiveBalance(beaconState iface.BeaconState, deposits []*ethpb.Deposit) (iface.BeaconState, error) {
|
||||
for _, deposit := range deposits {
|
||||
pubkey := deposit.Data.PublicKey
|
||||
index, ok := beaconState.ValidatorIndexByPubkey(bytesutil.ToBytes48(pubkey))
|
||||
@@ -67,33 +75,21 @@ func ProcessPreGenesisDeposits(
|
||||
// process_deposit(state, deposit)
|
||||
func ProcessDeposits(
|
||||
ctx context.Context,
|
||||
beaconState *stateTrie.BeaconState,
|
||||
b *ethpb.SignedBeaconBlock,
|
||||
) (*stateTrie.BeaconState, error) {
|
||||
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
deposits := b.Block.Body.Deposits
|
||||
var err error
|
||||
domain, err := helpers.ComputeDomain(params.BeaconConfig().DomainDeposit, nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
beaconState iface.BeaconState,
|
||||
deposits []*ethpb.Deposit,
|
||||
) (iface.BeaconState, error) {
|
||||
// Attempt to verify all deposit signatures at once, if this fails then fall back to processing
|
||||
// individual deposits with signature verification enabled.
|
||||
var verifySignature bool
|
||||
if err := verifyDepositDataWithDomain(ctx, deposits, domain); err != nil {
|
||||
log.WithError(err).Debug("Failed to verify deposit data, verifying signatures individually")
|
||||
verifySignature = true
|
||||
batchVerified, err := batchVerifyDepositsSignatures(ctx, deposits)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, deposit := range deposits {
|
||||
if deposit == nil || deposit.Data == nil {
|
||||
return nil, errors.New("got a nil deposit in block")
|
||||
}
|
||||
beaconState, err = ProcessDeposit(beaconState, deposit, verifySignature)
|
||||
beaconState, err = ProcessDeposit(beaconState, deposit, batchVerified)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not process deposit from %#x", bytesutil.Trunc(deposit.Data.PublicKey))
|
||||
}
|
||||
@@ -101,6 +97,21 @@ func ProcessDeposits(
|
||||
return beaconState, nil
|
||||
}
|
||||
|
||||
func batchVerifyDepositsSignatures(ctx context.Context, deposits []*ethpb.Deposit) (bool, error) {
|
||||
var err error
|
||||
domain, err := helpers.ComputeDomain(params.BeaconConfig().DomainDeposit, nil, nil)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
verified := false
|
||||
if err := verifyDepositDataWithDomain(ctx, deposits, domain); err != nil {
|
||||
log.WithError(err).Debug("Failed to batch verify deposits signatures, will try individual verify")
|
||||
verified = true
|
||||
}
|
||||
return verified, nil
|
||||
}
|
||||
|
||||
// ProcessDeposit takes in a deposit object and inserts it
|
||||
// into the registry as a new validator or balance change.
|
||||
//
|
||||
@@ -140,7 +151,7 @@ func ProcessDeposits(
|
||||
// # Increase balance by deposit amount
|
||||
// index = ValidatorIndex(validator_pubkeys.index(pubkey))
|
||||
// increase_balance(state, index, amount)
|
||||
func ProcessDeposit(beaconState *stateTrie.BeaconState, deposit *ethpb.Deposit, verifySignature bool) (*stateTrie.BeaconState, error) {
|
||||
func ProcessDeposit(beaconState iface.BeaconState, deposit *ethpb.Deposit, verifySignature bool) (iface.BeaconState, error) {
|
||||
if err := verifyDeposit(beaconState, deposit); err != nil {
|
||||
if deposit == nil || deposit.Data == nil {
|
||||
return nil, err
|
||||
@@ -191,7 +202,7 @@ func ProcessDeposit(beaconState *stateTrie.BeaconState, deposit *ethpb.Deposit,
|
||||
return beaconState, nil
|
||||
}
|
||||
|
||||
func verifyDeposit(beaconState *stateTrie.BeaconState, deposit *ethpb.Deposit) error {
|
||||
func verifyDeposit(beaconState iface.ReadOnlyBeaconState, deposit *ethpb.Deposit) error {
|
||||
// Verify Merkle proof of deposit and deposit trie root.
|
||||
if deposit == nil || deposit.Data == nil {
|
||||
return errors.New("received nil deposit or nil deposit data")
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateV0"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bls"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
@@ -40,7 +40,7 @@ func TestProcessDeposits_SameValidatorMultipleDepositsSameBlock(t *testing.T) {
|
||||
},
|
||||
}
|
||||
balances := []uint64{0}
|
||||
beaconState, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
||||
beaconState, err := stateV0.InitializeFromProto(&pb.BeaconState{
|
||||
Validators: registry,
|
||||
Balances: balances,
|
||||
Eth1Data: eth1Data,
|
||||
@@ -50,7 +50,7 @@ func TestProcessDeposits_SameValidatorMultipleDepositsSameBlock(t *testing.T) {
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
newState, err := blocks.ProcessDeposits(context.Background(), beaconState, b)
|
||||
newState, err := blocks.ProcessDeposits(context.Background(), beaconState, b.Block.Body.Deposits)
|
||||
require.NoError(t, err, "Expected block deposits to process correctly")
|
||||
|
||||
assert.Equal(t, 2, len(newState.Validators()), "Incorrect validator count")
|
||||
@@ -80,7 +80,7 @@ func TestProcessDeposits_MerkleBranchFailsVerification(t *testing.T) {
|
||||
Deposits: []*ethpb.Deposit{deposit},
|
||||
},
|
||||
}
|
||||
beaconState, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
||||
beaconState, err := stateV0.InitializeFromProto(&pb.BeaconState{
|
||||
Eth1Data: ðpb.Eth1Data{
|
||||
DepositRoot: []byte{0},
|
||||
BlockHash: []byte{1},
|
||||
@@ -88,7 +88,7 @@ func TestProcessDeposits_MerkleBranchFailsVerification(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
want := "deposit root did not verify"
|
||||
_, err = blocks.ProcessDeposits(context.Background(), beaconState, b)
|
||||
_, err = blocks.ProcessDeposits(context.Background(), beaconState, b.Block.Body.Deposits)
|
||||
assert.ErrorContains(t, want, err)
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ func TestProcessDeposits_AddsNewValidatorDeposit(t *testing.T) {
|
||||
},
|
||||
}
|
||||
balances := []uint64{0}
|
||||
beaconState, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
||||
beaconState, err := stateV0.InitializeFromProto(&pb.BeaconState{
|
||||
Validators: registry,
|
||||
Balances: balances,
|
||||
Eth1Data: eth1Data,
|
||||
@@ -121,7 +121,7 @@ func TestProcessDeposits_AddsNewValidatorDeposit(t *testing.T) {
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
newState, err := blocks.ProcessDeposits(context.Background(), beaconState, b)
|
||||
newState, err := blocks.ProcessDeposits(context.Background(), beaconState, b.Block.Body.Deposits)
|
||||
require.NoError(t, err, "Expected block deposits to process correctly")
|
||||
if newState.Balances()[1] != dep[0].Data.Amount {
|
||||
t.Errorf(
|
||||
@@ -174,7 +174,7 @@ func TestProcessDeposits_RepeatedDeposit_IncreasesValidatorBalance(t *testing.T)
|
||||
}
|
||||
balances := []uint64{0, 50}
|
||||
root := depositTrie.Root()
|
||||
beaconState, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
||||
beaconState, err := stateV0.InitializeFromProto(&pb.BeaconState{
|
||||
Validators: registry,
|
||||
Balances: balances,
|
||||
Eth1Data: ðpb.Eth1Data{
|
||||
@@ -183,7 +183,7 @@ func TestProcessDeposits_RepeatedDeposit_IncreasesValidatorBalance(t *testing.T)
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
newState, err := blocks.ProcessDeposits(context.Background(), beaconState, b)
|
||||
newState, err := blocks.ProcessDeposits(context.Background(), beaconState, b.Block.Body.Deposits)
|
||||
require.NoError(t, err, "Process deposit failed")
|
||||
assert.Equal(t, uint64(1000+50), newState.Balances()[1], "Expected balance at index 1 to be 1050")
|
||||
}
|
||||
@@ -202,7 +202,7 @@ func TestProcessDeposit_AddsNewValidatorDeposit(t *testing.T) {
|
||||
},
|
||||
}
|
||||
balances := []uint64{0}
|
||||
beaconState, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
||||
beaconState, err := stateV0.InitializeFromProto(&pb.BeaconState{
|
||||
Validators: registry,
|
||||
Balances: balances,
|
||||
Eth1Data: eth1Data,
|
||||
@@ -244,7 +244,7 @@ func TestProcessDeposit_SkipsInvalidDeposit(t *testing.T) {
|
||||
},
|
||||
}
|
||||
balances := []uint64{0}
|
||||
beaconState, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
||||
beaconState, err := stateV0.InitializeFromProto(&pb.BeaconState{
|
||||
Validators: registry,
|
||||
Balances: balances,
|
||||
Eth1Data: eth1Data,
|
||||
@@ -300,7 +300,7 @@ func TestPreGenesisDeposits_SkipInvalidDeposit(t *testing.T) {
|
||||
},
|
||||
}
|
||||
balances := []uint64{0}
|
||||
beaconState, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
||||
beaconState, err := stateV0.InitializeFromProto(&pb.BeaconState{
|
||||
Validators: registry,
|
||||
Balances: balances,
|
||||
Eth1Data: eth1Data,
|
||||
@@ -317,7 +317,7 @@ func TestPreGenesisDeposits_SkipInvalidDeposit(t *testing.T) {
|
||||
require.Equal(t, false, ok, "bad pubkey should not exist in state")
|
||||
|
||||
for i := 1; i < newState.NumValidators(); i++ {
|
||||
val, err := newState.ValidatorAtIndex(uint64(i))
|
||||
val, err := newState.ValidatorAtIndex(types.ValidatorIndex(i))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, params.BeaconConfig().MaxEffectiveBalance, val.EffectiveBalance, "unequal effective balance")
|
||||
require.Equal(t, types.Epoch(0), val.ActivationEpoch)
|
||||
|
||||
@@ -6,7 +6,8 @@ import (
|
||||
"errors"
|
||||
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateV0"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
|
||||
@@ -18,24 +19,20 @@ import (
|
||||
// def process_eth1_data(state: BeaconState, body: BeaconBlockBody) -> None:
|
||||
// state.eth1_data_votes.append(body.eth1_data)
|
||||
// if state.eth1_data_votes.count(body.eth1_data) * 2 > EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH:
|
||||
// state.latest_eth1_data = body.eth1_data
|
||||
func ProcessEth1DataInBlock(_ context.Context, beaconState *stateTrie.BeaconState, b *ethpb.SignedBeaconBlock) (*stateTrie.BeaconState, error) {
|
||||
block := b.Block
|
||||
// state.eth1_data = body.eth1_data
|
||||
func ProcessEth1DataInBlock(_ context.Context, beaconState iface.BeaconState, eth1Data *ethpb.Eth1Data) (iface.BeaconState, error) {
|
||||
if beaconState == nil {
|
||||
return nil, errors.New("nil state")
|
||||
}
|
||||
if block == nil || block.Body == nil {
|
||||
return nil, errors.New("nil block or block withought body")
|
||||
}
|
||||
if err := beaconState.AppendEth1DataVotes(block.Body.Eth1Data); err != nil {
|
||||
if err := beaconState.AppendEth1DataVotes(eth1Data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hasSupport, err := Eth1DataHasEnoughSupport(beaconState, block.Body.Eth1Data)
|
||||
hasSupport, err := Eth1DataHasEnoughSupport(beaconState, eth1Data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if hasSupport {
|
||||
if err := beaconState.SetEth1Data(block.Body.Eth1Data); err != nil {
|
||||
if err := beaconState.SetEth1Data(eth1Data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@@ -59,9 +56,9 @@ func AreEth1DataEqual(a, b *ethpb.Eth1Data) bool {
|
||||
// eth1 voting period. A vote is cast by including eth1data in a block and part of state processing
|
||||
// appends eth1data to the state in the Eth1DataVotes list. Iterating through this list checks the
|
||||
// votes to see if they match the eth1data.
|
||||
func Eth1DataHasEnoughSupport(beaconState *stateTrie.BeaconState, data *ethpb.Eth1Data) (bool, error) {
|
||||
func Eth1DataHasEnoughSupport(beaconState iface.ReadOnlyBeaconState, data *ethpb.Eth1Data) (bool, error) {
|
||||
voteCount := uint64(0)
|
||||
data = stateTrie.CopyETH1Data(data)
|
||||
data = stateV0.CopyETH1Data(data)
|
||||
|
||||
for _, vote := range beaconState.Eth1DataVotes() {
|
||||
if AreEth1DataEqual(vote, data) {
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateV0"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
@@ -70,7 +70,7 @@ func TestEth1DataHasEnoughSupport(t *testing.T) {
|
||||
c.EpochsPerEth1VotingPeriod = tt.votingPeriodLength
|
||||
params.OverrideBeaconConfig(c)
|
||||
|
||||
s, err := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
s, err := stateV0.InitializeFromProto(&pb.BeaconState{
|
||||
Eth1DataVotes: tt.stateVotes,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@@ -160,7 +160,7 @@ func TestAreEth1DataEqual(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestProcessEth1Data_SetsCorrectly(t *testing.T) {
|
||||
beaconState, err := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
beaconState, err := stateV0.InitializeFromProto(&pb.BeaconState{
|
||||
Eth1DataVotes: []*ethpb.Eth1Data{},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@@ -176,16 +176,19 @@ func TestProcessEth1Data_SetsCorrectly(t *testing.T) {
|
||||
}
|
||||
|
||||
period := uint64(params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().EpochsPerEth1VotingPeriod)))
|
||||
var ok bool
|
||||
for i := uint64(0); i < period; i++ {
|
||||
beaconState, err = blocks.ProcessEth1DataInBlock(context.Background(), beaconState, b)
|
||||
processedState, err := blocks.ProcessEth1DataInBlock(context.Background(), beaconState, b.Block.Body.Eth1Data)
|
||||
require.NoError(t, err)
|
||||
beaconState, ok = processedState.(*stateV0.BeaconState)
|
||||
require.Equal(t, true, ok)
|
||||
}
|
||||
|
||||
newETH1DataVotes := beaconState.Eth1DataVotes()
|
||||
if len(newETH1DataVotes) <= 1 {
|
||||
t.Error("Expected new ETH1 data votes to have length > 1")
|
||||
}
|
||||
if !proto.Equal(beaconState.Eth1Data(), beaconstate.CopyETH1Data(b.Block.Body.Eth1Data)) {
|
||||
if !proto.Equal(beaconState.Eth1Data(), stateV0.CopyETH1Data(b.Block.Body.Eth1Data)) {
|
||||
t.Errorf(
|
||||
"Expected latest eth1 data to have been set to %v, received %v",
|
||||
b.Block.Body.Eth1Data,
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
v "github.com/prysmaticlabs/prysm/beacon-chain/core/validators"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
@@ -26,35 +26,28 @@ var ValidatorCannotExitYetMsg = "validator has not been active long enough to ex
|
||||
// should exit the state's validator registry.
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
// def process_voluntary_exit(state: BeaconState, exit: VoluntaryExit) -> None:
|
||||
// """
|
||||
// Process ``VoluntaryExit`` operation.
|
||||
// """
|
||||
// validator = state.validator_registry[exit.validator_index]
|
||||
// def process_voluntary_exit(state: BeaconState, signed_voluntary_exit: SignedVoluntaryExit) -> None:
|
||||
// voluntary_exit = signed_voluntary_exit.message
|
||||
// validator = state.validators[voluntary_exit.validator_index]
|
||||
// # Verify the validator is active
|
||||
// assert is_active_validator(validator, get_current_epoch(state))
|
||||
// # Verify the validator has not yet exited
|
||||
// # Verify exit has not been initiated
|
||||
// assert validator.exit_epoch == FAR_FUTURE_EPOCH
|
||||
// # Exits must specify an epoch when they become valid; they are not valid before then
|
||||
// assert get_current_epoch(state) >= exit.epoch
|
||||
// assert get_current_epoch(state) >= voluntary_exit.epoch
|
||||
// # Verify the validator has been active long enough
|
||||
// assert get_current_epoch(state) >= validator.activation_epoch + PERSISTENT_COMMITTEE_PERIOD
|
||||
// assert get_current_epoch(state) >= validator.activation_epoch + SHARD_COMMITTEE_PERIOD
|
||||
// # Verify signature
|
||||
// domain = get_domain(state, DOMAIN_VOLUNTARY_EXIT, exit.epoch)
|
||||
// assert bls_verify(validator.pubkey, signing_root(exit), exit.signature, domain)
|
||||
// domain = get_domain(state, DOMAIN_VOLUNTARY_EXIT, voluntary_exit.epoch)
|
||||
// signing_root = compute_signing_root(voluntary_exit, domain)
|
||||
// assert bls.Verify(validator.pubkey, signing_root, signed_voluntary_exit.signature)
|
||||
// # Initiate exit
|
||||
// initiate_validator_exit(state, exit.validator_index)
|
||||
// initiate_validator_exit(state, voluntary_exit.validator_index)
|
||||
func ProcessVoluntaryExits(
|
||||
_ context.Context,
|
||||
beaconState *stateTrie.BeaconState,
|
||||
b *ethpb.SignedBeaconBlock,
|
||||
) (*stateTrie.BeaconState, error) {
|
||||
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
body := b.Block.Body
|
||||
exits := body.VoluntaryExits
|
||||
beaconState iface.BeaconState,
|
||||
exits []*ethpb.SignedVoluntaryExit,
|
||||
) (iface.BeaconState, error) {
|
||||
for idx, exit := range exits {
|
||||
if exit == nil || exit.Exit == nil {
|
||||
return nil, errors.New("nil voluntary exit in block body")
|
||||
@@ -77,23 +70,30 @@ func ProcessVoluntaryExits(
|
||||
// VerifyExitAndSignature implements the spec defined validation for voluntary exits.
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
// def process_voluntary_exit(state: BeaconState, exit: VoluntaryExit) -> None:
|
||||
// """
|
||||
// Process ``VoluntaryExit`` operation.
|
||||
// """
|
||||
// validator = state.validator_registry[exit.validator_index]
|
||||
// def process_voluntary_exit(state: BeaconState, signed_voluntary_exit: SignedVoluntaryExit) -> None:
|
||||
// voluntary_exit = signed_voluntary_exit.message
|
||||
// validator = state.validators[voluntary_exit.validator_index]
|
||||
// # Verify the validator is active
|
||||
// assert is_active_validator(validator, get_current_epoch(state))
|
||||
// # Verify the validator has not yet exited
|
||||
// # Verify exit has not been initiated
|
||||
// assert validator.exit_epoch == FAR_FUTURE_EPOCH
|
||||
// # Exits must specify an epoch when they become valid; they are not valid before then
|
||||
// assert get_current_epoch(state) >= exit.epoch
|
||||
// assert get_current_epoch(state) >= voluntary_exit.epoch
|
||||
// # Verify the validator has been active long enough
|
||||
// assert get_current_epoch(state) >= validator.activation_epoch + PERSISTENT_COMMITTEE_PERIOD
|
||||
// assert get_current_epoch(state) >= validator.activation_epoch + SHARD_COMMITTEE_PERIOD
|
||||
// # Verify signature
|
||||
// domain = get_domain(state, DOMAIN_VOLUNTARY_EXIT, exit.epoch)
|
||||
// assert bls_verify(validator.pubkey, signing_root(exit), exit.signature, domain)
|
||||
func VerifyExitAndSignature(validator stateTrie.ReadOnlyValidator, currentSlot types.Slot, fork *pb.Fork, signed *ethpb.SignedVoluntaryExit, genesisRoot []byte) error {
|
||||
// domain = get_domain(state, DOMAIN_VOLUNTARY_EXIT, voluntary_exit.epoch)
|
||||
// signing_root = compute_signing_root(voluntary_exit, domain)
|
||||
// assert bls.Verify(validator.pubkey, signing_root, signed_voluntary_exit.signature)
|
||||
// # Initiate exit
|
||||
// initiate_validator_exit(state, voluntary_exit.validator_index)
|
||||
func VerifyExitAndSignature(
|
||||
validator iface.ReadOnlyValidator,
|
||||
currentSlot types.Slot,
|
||||
fork *pb.Fork,
|
||||
signed *ethpb.SignedVoluntaryExit,
|
||||
genesisRoot []byte,
|
||||
) error {
|
||||
if signed == nil || signed.Exit == nil {
|
||||
return errors.New("nil exit")
|
||||
}
|
||||
@@ -116,20 +116,24 @@ func VerifyExitAndSignature(validator stateTrie.ReadOnlyValidator, currentSlot t
|
||||
// verifyExitConditions implements the spec defined validation for voluntary exits(excluding signatures).
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
// def process_voluntary_exit(state: BeaconState, exit: VoluntaryExit) -> None:
|
||||
// """
|
||||
// Process ``VoluntaryExit`` operation.
|
||||
// """
|
||||
// validator = state.validator_registry[exit.validator_index]
|
||||
// def process_voluntary_exit(state: BeaconState, signed_voluntary_exit: SignedVoluntaryExit) -> None:
|
||||
// voluntary_exit = signed_voluntary_exit.message
|
||||
// validator = state.validators[voluntary_exit.validator_index]
|
||||
// # Verify the validator is active
|
||||
// assert is_active_validator(validator, get_current_epoch(state))
|
||||
// # Verify the validator has not yet exited
|
||||
// # Verify exit has not been initiated
|
||||
// assert validator.exit_epoch == FAR_FUTURE_EPOCH
|
||||
// # Exits must specify an epoch when they become valid; they are not valid before then
|
||||
// assert get_current_epoch(state) >= exit.epoch
|
||||
// assert get_current_epoch(state) >= voluntary_exit.epoch
|
||||
// # Verify the validator has been active long enough
|
||||
// assert get_current_epoch(state) >= validator.activation_epoch + SHARD_COMMITTEE_PERIOD
|
||||
func verifyExitConditions(validator stateTrie.ReadOnlyValidator, currentSlot types.Slot, exit *ethpb.VoluntaryExit) error {
|
||||
// # Verify signature
|
||||
// domain = get_domain(state, DOMAIN_VOLUNTARY_EXIT, voluntary_exit.epoch)
|
||||
// signing_root = compute_signing_root(voluntary_exit, domain)
|
||||
// assert bls.Verify(validator.pubkey, signing_root, signed_voluntary_exit.signature)
|
||||
// # Initiate exit
|
||||
// initiate_validator_exit(state, voluntary_exit.validator_index)
|
||||
func verifyExitConditions(validator iface.ReadOnlyValidator, currentSlot types.Slot, exit *ethpb.VoluntaryExit) error {
|
||||
currentEpoch := helpers.SlotToEpoch(currentSlot)
|
||||
// Verify the validator is active.
|
||||
if !helpers.IsActiveValidatorUsingTrie(validator, currentEpoch) {
|
||||
@@ -146,9 +150,10 @@ func verifyExitConditions(validator stateTrie.ReadOnlyValidator, currentSlot typ
|
||||
// Verify the validator has been active long enough.
|
||||
if currentEpoch < validator.ActivationEpoch()+params.BeaconConfig().ShardCommitteePeriod {
|
||||
return fmt.Errorf(
|
||||
"%s: %d epochs vs required %d epochs",
|
||||
"%s: %d of %d epochs. Validator will be eligible for exit at epoch %d",
|
||||
ValidatorCannotExitYetMsg,
|
||||
currentEpoch,
|
||||
currentEpoch-validator.ActivationEpoch(),
|
||||
params.BeaconConfig().ShardCommitteePeriod,
|
||||
validator.ActivationEpoch()+params.BeaconConfig().ShardCommitteePeriod,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateV0"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bls"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
@@ -31,7 +31,7 @@ func TestProcessVoluntaryExits_NotActiveLongEnoughToExit(t *testing.T) {
|
||||
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
|
||||
},
|
||||
}
|
||||
state, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
||||
state, err := stateV0.InitializeFromProto(&pb.BeaconState{
|
||||
Validators: registry,
|
||||
Slot: 10,
|
||||
})
|
||||
@@ -44,7 +44,7 @@ func TestProcessVoluntaryExits_NotActiveLongEnoughToExit(t *testing.T) {
|
||||
}
|
||||
|
||||
want := "validator has not been active long enough to exit"
|
||||
_, err = blocks.ProcessVoluntaryExits(context.Background(), state, b)
|
||||
_, err = blocks.ProcessVoluntaryExits(context.Background(), state, b.Block.Body.VoluntaryExits)
|
||||
assert.ErrorContains(t, want, err)
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ func TestProcessVoluntaryExits_ExitAlreadySubmitted(t *testing.T) {
|
||||
ExitEpoch: 10,
|
||||
},
|
||||
}
|
||||
state, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
||||
state, err := stateV0.InitializeFromProto(&pb.BeaconState{
|
||||
Validators: registry,
|
||||
Slot: 0,
|
||||
})
|
||||
@@ -74,7 +74,7 @@ func TestProcessVoluntaryExits_ExitAlreadySubmitted(t *testing.T) {
|
||||
}
|
||||
|
||||
want := "validator with index 0 has already submitted an exit, which will take place at epoch: 10"
|
||||
_, err = blocks.ProcessVoluntaryExits(context.Background(), state, b)
|
||||
_, err = blocks.ProcessVoluntaryExits(context.Background(), state, b.Block.Body.VoluntaryExits)
|
||||
assert.ErrorContains(t, want, err)
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ func TestProcessVoluntaryExits_AppliesCorrectStatus(t *testing.T) {
|
||||
ActivationEpoch: 0,
|
||||
},
|
||||
}
|
||||
state, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
||||
state, err := stateV0.InitializeFromProto(&pb.BeaconState{
|
||||
Validators: registry,
|
||||
Fork: &pb.Fork{
|
||||
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
|
||||
@@ -122,7 +122,7 @@ func TestProcessVoluntaryExits_AppliesCorrectStatus(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
newState, err := blocks.ProcessVoluntaryExits(context.Background(), state, b)
|
||||
newState, err := blocks.ProcessVoluntaryExits(context.Background(), state, b.Block.Body.VoluntaryExits)
|
||||
require.NoError(t, err, "Could not process exits")
|
||||
newRegistry := newState.Validators()
|
||||
if newRegistry[0].ExitEpoch != helpers.ActivationExitEpoch(types.Epoch(state.Slot()/params.BeaconConfig().SlotsPerEpoch)) {
|
||||
|
||||
@@ -5,10 +5,10 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
|
||||
@@ -19,35 +19,43 @@ import (
|
||||
// def process_block_header(state: BeaconState, block: BeaconBlock) -> None:
|
||||
// # Verify that the slots match
|
||||
// assert block.slot == state.slot
|
||||
// # Verify that proposer index is the correct index
|
||||
// # Verify that the block is newer than latest block header
|
||||
// assert block.slot > state.latest_block_header.slot
|
||||
// # Verify that proposer index is the correct index
|
||||
// assert block.proposer_index == get_beacon_proposer_index(state)
|
||||
// # Verify that the parent matches
|
||||
// assert block.parent_root == hash_tree_root(state.latest_block_header)
|
||||
// # Save current block as the new latest block
|
||||
// # Cache current block as the new latest block
|
||||
// state.latest_block_header = BeaconBlockHeader(
|
||||
// slot=block.slot,
|
||||
// proposer_index=block.proposer_index,
|
||||
// parent_root=block.parent_root,
|
||||
// # state_root: zeroed, overwritten in the next `process_slot` call
|
||||
// state_root=Bytes32(), # Overwritten in the next process_slot call
|
||||
// body_root=hash_tree_root(block.body),
|
||||
// # signature is always zeroed
|
||||
// )
|
||||
//
|
||||
// # Verify proposer is not slashed
|
||||
// proposer = state.validators[get_beacon_proposer_index(state)]
|
||||
// proposer = state.validators[block.proposer_index]
|
||||
// assert not proposer.slashed
|
||||
// # Verify proposer signature
|
||||
// assert bls_verify(proposer.pubkey, signing_root(block), block.signature, get_domain(state, DOMAIN_BEACON_PROPOSER))
|
||||
func ProcessBlockHeader(
|
||||
_ context.Context,
|
||||
beaconState *stateTrie.BeaconState,
|
||||
beaconState iface.BeaconState,
|
||||
block *ethpb.SignedBeaconBlock,
|
||||
) (*stateTrie.BeaconState, error) {
|
||||
beaconState, err := ProcessBlockHeaderNoVerify(beaconState, block.Block)
|
||||
) (iface.BeaconState, error) {
|
||||
if err := helpers.VerifyNilBeaconBlock(block); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bodyRoot, err := block.Block.Body.HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
beaconState, err = ProcessBlockHeaderNoVerify(beaconState, block.Block.Slot, block.Block.ProposerIndex, block.Block.ParentRoot, bodyRoot[:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Verify proposer signature.
|
||||
if err := VerifyBlockSignature(beaconState, block); err != nil {
|
||||
if err := VerifyBlockSignature(beaconState, block.Block.ProposerIndex, block.Signature, block.Block.HashTreeRoot); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -64,51 +72,52 @@ func ProcessBlockHeader(
|
||||
// def process_block_header(state: BeaconState, block: BeaconBlock) -> None:
|
||||
// # Verify that the slots match
|
||||
// assert block.slot == state.slot
|
||||
// # Verify that proposer index is the correct index
|
||||
// # Verify that the block is newer than latest block header
|
||||
// assert block.slot > state.latest_block_header.slot
|
||||
// # Verify that proposer index is the correct index
|
||||
// assert block.proposer_index == get_beacon_proposer_index(state)
|
||||
// # Verify that the parent matches
|
||||
// assert block.parent_root == hash_tree_root(state.latest_block_header)
|
||||
// # Save current block as the new latest block
|
||||
// # Cache current block as the new latest block
|
||||
// state.latest_block_header = BeaconBlockHeader(
|
||||
// slot=block.slot,
|
||||
// proposer_index=block.proposer_index,
|
||||
// parent_root=block.parent_root,
|
||||
// # state_root: zeroed, overwritten in the next `process_slot` call
|
||||
// state_root=Bytes32(), # Overwritten in the next process_slot call
|
||||
// body_root=hash_tree_root(block.body),
|
||||
// # signature is always zeroed
|
||||
// )
|
||||
//
|
||||
// # Verify proposer is not slashed
|
||||
// proposer = state.validators[get_beacon_proposer_index(state)]
|
||||
// proposer = state.validators[block.proposer_index]
|
||||
// assert not proposer.slashed
|
||||
func ProcessBlockHeaderNoVerify(
|
||||
beaconState *stateTrie.BeaconState,
|
||||
block *ethpb.BeaconBlock,
|
||||
) (*stateTrie.BeaconState, error) {
|
||||
if block == nil {
|
||||
return nil, errors.New("nil block")
|
||||
}
|
||||
if beaconState.Slot() != block.Slot {
|
||||
return nil, fmt.Errorf("state slot: %d is different than block slot: %d", beaconState.Slot(), block.Slot)
|
||||
beaconState iface.BeaconState,
|
||||
slot types.Slot, proposerIndex types.ValidatorIndex,
|
||||
parentRoot, bodyRoot []byte,
|
||||
) (iface.BeaconState, error) {
|
||||
if beaconState.Slot() != slot {
|
||||
return nil, fmt.Errorf("state slot: %d is different than block slot: %d", beaconState.Slot(), slot)
|
||||
}
|
||||
idx, err := helpers.BeaconProposerIndex(beaconState)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if block.ProposerIndex != idx {
|
||||
return nil, fmt.Errorf("proposer index: %d is different than calculated: %d", block.ProposerIndex, idx)
|
||||
if proposerIndex != idx {
|
||||
return nil, fmt.Errorf("proposer index: %d is different than calculated: %d", proposerIndex, idx)
|
||||
}
|
||||
parentHeader := beaconState.LatestBlockHeader()
|
||||
if parentHeader.Slot >= block.Slot {
|
||||
return nil, fmt.Errorf("block.Slot %d must be greater than state.LatestBlockHeader.Slot %d", block.Slot, parentHeader.Slot)
|
||||
if parentHeader.Slot >= slot {
|
||||
return nil, fmt.Errorf("block.Slot %d must be greater than state.LatestBlockHeader.Slot %d", slot, parentHeader.Slot)
|
||||
}
|
||||
parentRoot, err := parentHeader.HashTreeRoot()
|
||||
parentHeaderRoot, err := parentHeader.HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !bytes.Equal(block.ParentRoot, parentRoot[:]) {
|
||||
if !bytes.Equal(parentRoot, parentHeaderRoot[:]) {
|
||||
return nil, fmt.Errorf(
|
||||
"parent root %#x does not match the latest block header signing root in state %#x",
|
||||
block.ParentRoot, parentRoot)
|
||||
parentRoot, parentHeaderRoot[:])
|
||||
}
|
||||
|
||||
proposer, err := beaconState.ValidatorAtIndexReadOnly(idx)
|
||||
@@ -119,16 +128,12 @@ func ProcessBlockHeaderNoVerify(
|
||||
return nil, fmt.Errorf("proposer at index %d was previously slashed", idx)
|
||||
}
|
||||
|
||||
bodyRoot, err := block.Body.HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := beaconState.SetLatestBlockHeader(ðpb.BeaconBlockHeader{
|
||||
Slot: block.Slot,
|
||||
ProposerIndex: block.ProposerIndex,
|
||||
ParentRoot: block.ParentRoot,
|
||||
Slot: slot,
|
||||
ProposerIndex: proposerIndex,
|
||||
ParentRoot: parentRoot,
|
||||
StateRoot: params.BeaconConfig().ZeroHash[:],
|
||||
BodyRoot: bodyRoot[:],
|
||||
BodyRoot: bodyRoot,
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -125,16 +125,13 @@ func TestProcessBlockHeader_DifferentSlots(t *testing.T) {
|
||||
blockSig, err := helpers.ComputeDomainAndSign(state, currentEpoch, &sszBytes, params.BeaconConfig().DomainBeaconProposer, priv)
|
||||
require.NoError(t, err)
|
||||
validators[5896].PublicKey = priv.PublicKey().Marshal()
|
||||
block := ðpb.SignedBeaconBlock{
|
||||
block := testutil.HydrateSignedBeaconBlock(ðpb.SignedBeaconBlock{
|
||||
Block: ðpb.BeaconBlock{
|
||||
Slot: 1,
|
||||
Body: ðpb.BeaconBlockBody{
|
||||
RandaoReveal: []byte{'A', 'B', 'C'},
|
||||
},
|
||||
Slot: 1,
|
||||
ParentRoot: lbhsr[:],
|
||||
},
|
||||
Signature: blockSig,
|
||||
}
|
||||
})
|
||||
|
||||
_, err = blocks.ProcessBlockHeader(context.Background(), state, block)
|
||||
want := "is different than block slot"
|
||||
@@ -321,7 +318,7 @@ func TestBlockSignatureSet_OK(t *testing.T) {
|
||||
validators[proposerIdx].PublicKey = priv.PublicKey().Marshal()
|
||||
err = state.UpdateValidatorAtIndex(proposerIdx, validators[proposerIdx])
|
||||
require.NoError(t, err)
|
||||
set, err := blocks.BlockSignatureSet(state, block)
|
||||
set, err := blocks.BlockSignatureSet(state, block.Block.ProposerIndex, block.Signature, block.Block.HashTreeRoot)
|
||||
require.NoError(t, err)
|
||||
|
||||
verified, err := set.Verify()
|
||||
|
||||
@@ -4,59 +4,57 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/pkg/errors"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
v "github.com/prysmaticlabs/prysm/beacon-chain/core/validators"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
|
||||
type slashValidatorFunc func(iface.BeaconState, types.ValidatorIndex) (iface.BeaconState, error)
|
||||
|
||||
// ProcessProposerSlashings is one of the operations performed
|
||||
// on each processed beacon block to slash proposers based on
|
||||
// slashing conditions if any slashable events occurred.
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
// def process_proposer_slashing(state: BeaconState, proposer_slashing: ProposerSlashing) -> None:
|
||||
// """
|
||||
// Process ``ProposerSlashing`` operation.
|
||||
// """
|
||||
// proposer = state.validator_registry[proposer_slashing.proposer_index]
|
||||
// # Verify slots match
|
||||
// assert proposer_slashing.header_1.slot == proposer_slashing.header_2.slot
|
||||
// # But the headers are different
|
||||
// assert proposer_slashing.header_1 != proposer_slashing.header_2
|
||||
// # Check proposer is slashable
|
||||
// assert is_slashable_validator(proposer, get_current_epoch(state))
|
||||
// # Signatures are valid
|
||||
// for header in (proposer_slashing.header_1, proposer_slashing.header_2):
|
||||
// domain = get_domain(state, DOMAIN_BEACON_PROPOSER, slot_to_epoch(header.slot))
|
||||
// assert bls_verify(proposer.pubkey, signing_root(header), header.signature, domain)
|
||||
// header_1 = proposer_slashing.signed_header_1.message
|
||||
// header_2 = proposer_slashing.signed_header_2.message
|
||||
//
|
||||
// slash_validator(state, proposer_slashing.proposer_index)
|
||||
// # Verify header slots match
|
||||
// assert header_1.slot == header_2.slot
|
||||
// # Verify header proposer indices match
|
||||
// assert header_1.proposer_index == header_2.proposer_index
|
||||
// # Verify the headers are different
|
||||
// assert header_1 != header_2
|
||||
// # Verify the proposer is slashable
|
||||
// proposer = state.validators[header_1.proposer_index]
|
||||
// assert is_slashable_validator(proposer, get_current_epoch(state))
|
||||
// # Verify signatures
|
||||
// for signed_header in (proposer_slashing.signed_header_1, proposer_slashing.signed_header_2):
|
||||
// domain = get_domain(state, DOMAIN_BEACON_PROPOSER, compute_epoch_at_slot(signed_header.message.slot))
|
||||
// signing_root = compute_signing_root(signed_header.message, domain)
|
||||
// assert bls.Verify(proposer.pubkey, signing_root, signed_header.signature)
|
||||
//
|
||||
// slash_validator(state, header_1.proposer_index)
|
||||
func ProcessProposerSlashings(
|
||||
_ context.Context,
|
||||
beaconState *stateTrie.BeaconState,
|
||||
b *ethpb.SignedBeaconBlock,
|
||||
) (*stateTrie.BeaconState, error) {
|
||||
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
body := b.Block.Body
|
||||
beaconState iface.BeaconState,
|
||||
slashings []*ethpb.ProposerSlashing,
|
||||
slashFunc slashValidatorFunc,
|
||||
) (iface.BeaconState, error) {
|
||||
var err error
|
||||
for idx, slashing := range body.ProposerSlashings {
|
||||
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)
|
||||
}
|
||||
beaconState, err = v.SlashValidator(
|
||||
beaconState, slashing.Header_1.Header.ProposerIndex,
|
||||
)
|
||||
beaconState, err = slashFunc(beaconState, slashing.Header_1.Header.ProposerIndex)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not slash proposer index %d", slashing.Header_1.Header.ProposerIndex)
|
||||
}
|
||||
@@ -66,7 +64,7 @@ func ProcessProposerSlashings(
|
||||
|
||||
// VerifyProposerSlashing verifies that the data provided from slashing is valid.
|
||||
func VerifyProposerSlashing(
|
||||
beaconState *stateTrie.BeaconState,
|
||||
beaconState iface.BeaconState,
|
||||
slashing *ethpb.ProposerSlashing,
|
||||
) error {
|
||||
if slashing.Header_1 == nil || slashing.Header_1.Header == nil || slashing.Header_2 == nil || slashing.Header_2.Header == nil {
|
||||
|
||||
@@ -5,9 +5,9 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateV0"
|
||||
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
)
|
||||
@@ -24,7 +24,7 @@ func TestVerifyProposerSlashing_BeaconFuzzIssue91(t *testing.T) {
|
||||
err = rawState.UnmarshalSSZ(file)
|
||||
require.NoError(t, err)
|
||||
|
||||
st, err := stateTrie.InitializeFromProtoUnsafe(rawState)
|
||||
st, err := stateV0.InitializeFromProtoUnsafe(rawState)
|
||||
require.NoError(t, err)
|
||||
|
||||
file, err = ioutil.ReadFile("testdata/beaconfuzz_91_proposer_slashing.ssz")
|
||||
|
||||
@@ -9,7 +9,9 @@ import (
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
v "github.com/prysmaticlabs/prysm/beacon-chain/core/validators"
|
||||
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateV0"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bls"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
@@ -48,7 +50,7 @@ func TestProcessProposerSlashings_UnmatchedHeaderSlots(t *testing.T) {
|
||||
},
|
||||
}
|
||||
want := "mismatched header slots"
|
||||
_, err := blocks.ProcessProposerSlashings(context.Background(), beaconState, b)
|
||||
_, err := blocks.ProcessProposerSlashings(context.Background(), beaconState, b.Block.Body.ProposerSlashings, v.SlashValidator)
|
||||
assert.ErrorContains(t, want, err)
|
||||
}
|
||||
|
||||
@@ -81,7 +83,7 @@ func TestProcessProposerSlashings_SameHeaders(t *testing.T) {
|
||||
},
|
||||
}
|
||||
want := "expected slashing headers to differ"
|
||||
_, err := blocks.ProcessProposerSlashings(context.Background(), beaconState, b)
|
||||
_, err := blocks.ProcessProposerSlashings(context.Background(), beaconState, b.Block.Body.ProposerSlashings, v.SlashValidator)
|
||||
assert.ErrorContains(t, want, err)
|
||||
}
|
||||
|
||||
@@ -116,7 +118,7 @@ func TestProcessProposerSlashings_ValidatorNotSlashable(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
beaconState, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
||||
beaconState, err := stateV0.InitializeFromProto(&pb.BeaconState{
|
||||
Validators: registry,
|
||||
Slot: currentSlot,
|
||||
})
|
||||
@@ -131,7 +133,7 @@ func TestProcessProposerSlashings_ValidatorNotSlashable(t *testing.T) {
|
||||
"validator with key %#x is not slashable",
|
||||
bytesutil.ToBytes48(beaconState.Validators()[0].PublicKey),
|
||||
)
|
||||
_, err = blocks.ProcessProposerSlashings(context.Background(), beaconState, b)
|
||||
_, err = blocks.ProcessProposerSlashings(context.Background(), beaconState, b.Block.Body.ProposerSlashings, v.SlashValidator)
|
||||
assert.ErrorContains(t, want, err)
|
||||
}
|
||||
|
||||
@@ -139,7 +141,7 @@ func TestProcessProposerSlashings_AppliesCorrectStatus(t *testing.T) {
|
||||
// We test the case when data is correct and verify the validator
|
||||
// registry has been updated.
|
||||
beaconState, privKeys := testutil.DeterministicGenesisState(t, 100)
|
||||
proposerIdx := uint64(1)
|
||||
proposerIdx := types.ValidatorIndex(1)
|
||||
|
||||
header1 := ðpb.SignedBeaconBlockHeader{
|
||||
Header: testutil.HydrateBeaconHeader(ðpb.BeaconBlockHeader{
|
||||
@@ -170,7 +172,7 @@ func TestProcessProposerSlashings_AppliesCorrectStatus(t *testing.T) {
|
||||
block := testutil.NewBeaconBlock()
|
||||
block.Block.Body.ProposerSlashings = slashings
|
||||
|
||||
newState, err := blocks.ProcessProposerSlashings(context.Background(), beaconState, block)
|
||||
newState, err := blocks.ProcessProposerSlashings(context.Background(), beaconState, block.Block.Body.ProposerSlashings, v.SlashValidator)
|
||||
require.NoError(t, err)
|
||||
|
||||
newStateVals := newState.Validators()
|
||||
@@ -182,7 +184,7 @@ func TestProcessProposerSlashings_AppliesCorrectStatus(t *testing.T) {
|
||||
|
||||
func TestVerifyProposerSlashing(t *testing.T) {
|
||||
type args struct {
|
||||
beaconState *stateTrie.BeaconState
|
||||
beaconState iface.BeaconState
|
||||
slashing *ethpb.ProposerSlashing
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
|
||||
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
@@ -27,9 +27,9 @@ import (
|
||||
// state.randao_mixes[epoch % EPOCHS_PER_HISTORICAL_VECTOR] = mix
|
||||
func ProcessRandao(
|
||||
_ context.Context,
|
||||
beaconState *stateTrie.BeaconState,
|
||||
beaconState iface.BeaconState,
|
||||
b *ethpb.SignedBeaconBlock,
|
||||
) (*stateTrie.BeaconState, error) {
|
||||
) (iface.BeaconState, error) {
|
||||
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -42,7 +42,7 @@ func ProcessRandao(
|
||||
return nil, errors.Wrap(err, "could not verify block randao")
|
||||
}
|
||||
|
||||
beaconState, err = ProcessRandaoNoVerify(beaconState, body)
|
||||
beaconState, err = ProcessRandaoNoVerify(beaconState, body.RandaoReveal)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not process randao")
|
||||
}
|
||||
@@ -59,9 +59,9 @@ func ProcessRandao(
|
||||
// hash(body.randao_reveal))
|
||||
// )
|
||||
func ProcessRandaoNoVerify(
|
||||
beaconState *stateTrie.BeaconState,
|
||||
body *ethpb.BeaconBlockBody,
|
||||
) (*stateTrie.BeaconState, error) {
|
||||
beaconState iface.BeaconState,
|
||||
randaoReveal []byte,
|
||||
) (iface.BeaconState, error) {
|
||||
currentEpoch := helpers.SlotToEpoch(beaconState.Slot())
|
||||
// If block randao passed verification, we XOR the state's latest randao mix with the block's
|
||||
// randao and update the state's corresponding latest randao mix value.
|
||||
@@ -70,7 +70,7 @@ func ProcessRandaoNoVerify(
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
blockRandaoReveal := hashutil.Hash(body.RandaoReveal)
|
||||
blockRandaoReveal := hashutil.Hash(randaoReveal)
|
||||
if len(blockRandaoReveal) != len(latestMixSlice) {
|
||||
return nil, errors.New("blockRandaoReveal length doesnt match latestMixSlice length")
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ func TestRandaoSignatureSet_OK(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
set, err := blocks.RandaoSignatureSet(beaconState, block.Body)
|
||||
set, err := blocks.RandaoSignatureSet(beaconState, block.Body.RandaoReveal)
|
||||
require.NoError(t, err)
|
||||
verified, err := set.Verify()
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -5,9 +5,10 @@ import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/attestationutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/bls"
|
||||
@@ -59,45 +60,51 @@ func verifySignature(signedData, pub, signature, domain []byte) error {
|
||||
}
|
||||
|
||||
// VerifyBlockSignature verifies the proposer signature of a beacon block.
|
||||
func VerifyBlockSignature(beaconState *stateTrie.BeaconState, block *ethpb.SignedBeaconBlock) error {
|
||||
func VerifyBlockSignature(beaconState iface.ReadOnlyBeaconState,
|
||||
proposerIndex types.ValidatorIndex,
|
||||
sig []byte,
|
||||
rootFunc func() ([32]byte, error)) error {
|
||||
currentEpoch := helpers.SlotToEpoch(beaconState.Slot())
|
||||
domain, err := helpers.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainBeaconProposer, beaconState.GenesisValidatorRoot())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
proposer, err := beaconState.ValidatorAtIndex(block.Block.ProposerIndex)
|
||||
proposer, err := beaconState.ValidatorAtIndex(proposerIndex)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
proposerPubKey := proposer.PublicKey
|
||||
return helpers.VerifyBlockSigningRoot(block.Block, proposerPubKey, block.Signature, domain)
|
||||
return helpers.VerifyBlockSigningRoot(proposerPubKey, sig, domain, rootFunc)
|
||||
}
|
||||
|
||||
// BlockSignatureSet retrieves the block signature set from the provided block and its corresponding state.
|
||||
func BlockSignatureSet(beaconState *stateTrie.BeaconState, block *ethpb.SignedBeaconBlock) (*bls.SignatureSet, error) {
|
||||
func BlockSignatureSet(beaconState iface.ReadOnlyBeaconState,
|
||||
proposerIndex types.ValidatorIndex,
|
||||
sig []byte,
|
||||
rootFunc func() ([32]byte, error)) (*bls.SignatureSet, error) {
|
||||
currentEpoch := helpers.SlotToEpoch(beaconState.Slot())
|
||||
domain, err := helpers.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainBeaconProposer, beaconState.GenesisValidatorRoot())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
proposer, err := beaconState.ValidatorAtIndex(block.Block.ProposerIndex)
|
||||
proposer, err := beaconState.ValidatorAtIndex(proposerIndex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
proposerPubKey := proposer.PublicKey
|
||||
return helpers.BlockSignatureSet(block.Block, proposerPubKey, block.Signature, domain)
|
||||
return helpers.BlockSignatureSet(proposerPubKey, sig, domain, rootFunc)
|
||||
}
|
||||
|
||||
// RandaoSignatureSet retrieves the relevant randao specific signature set object
|
||||
// from a block and its corresponding state.
|
||||
func RandaoSignatureSet(beaconState *stateTrie.BeaconState,
|
||||
body *ethpb.BeaconBlockBody,
|
||||
func RandaoSignatureSet(beaconState iface.ReadOnlyBeaconState,
|
||||
reveal []byte,
|
||||
) (*bls.SignatureSet, error) {
|
||||
buf, proposerPub, domain, err := randaoSigningData(beaconState)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
set, err := signatureSet(buf, proposerPub, body.RandaoReveal, domain)
|
||||
set, err := signatureSet(buf, proposerPub, reveal, domain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -105,7 +112,7 @@ func RandaoSignatureSet(beaconState *stateTrie.BeaconState,
|
||||
}
|
||||
|
||||
// retrieves the randao related signing data from the state.
|
||||
func randaoSigningData(beaconState *stateTrie.BeaconState) ([]byte, []byte, []byte, error) {
|
||||
func randaoSigningData(beaconState iface.ReadOnlyBeaconState) ([]byte, []byte, []byte, error) {
|
||||
proposerIdx, err := helpers.BeaconProposerIndex(beaconState)
|
||||
if err != nil {
|
||||
return nil, nil, nil, errors.Wrap(err, "could not get beacon proposer index")
|
||||
@@ -124,7 +131,12 @@ func randaoSigningData(beaconState *stateTrie.BeaconState) ([]byte, []byte, []by
|
||||
}
|
||||
|
||||
// Method to break down attestations of the same domain and collect them into a single signature set.
|
||||
func createAttestationSignatureSet(ctx context.Context, beaconState *stateTrie.BeaconState, atts []*ethpb.Attestation, domain []byte) (*bls.SignatureSet, error) {
|
||||
func createAttestationSignatureSet(
|
||||
ctx context.Context,
|
||||
beaconState iface.ReadOnlyBeaconState,
|
||||
atts []*ethpb.Attestation,
|
||||
domain []byte,
|
||||
) (*bls.SignatureSet, error) {
|
||||
if len(atts) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -148,7 +160,7 @@ func createAttestationSignatureSet(ctx context.Context, beaconState *stateTrie.B
|
||||
indices := ia.AttestingIndices
|
||||
pubkeys := make([][]byte, len(indices))
|
||||
for i := 0; i < len(indices); i++ {
|
||||
pubkeyAtIdx := beaconState.PubkeyAtIndex(indices[i])
|
||||
pubkeyAtIdx := beaconState.PubkeyAtIndex(types.ValidatorIndex(indices[i]))
|
||||
pubkeys[i] = pubkeyAtIdx[:]
|
||||
}
|
||||
aggP, err := bls.AggregatePublicKeys(pubkeys)
|
||||
@@ -172,7 +184,7 @@ func createAttestationSignatureSet(ctx context.Context, beaconState *stateTrie.B
|
||||
|
||||
// AttestationSignatureSet retrieves all the related attestation signature data such as the relevant public keys,
|
||||
// signatures and attestation signing data and collate it into a signature set object.
|
||||
func AttestationSignatureSet(ctx context.Context, beaconState *stateTrie.BeaconState, atts []*ethpb.Attestation) (*bls.SignatureSet, error) {
|
||||
func AttestationSignatureSet(ctx context.Context, beaconState iface.ReadOnlyBeaconState, atts []*ethpb.Attestation) (*bls.SignatureSet, error) {
|
||||
if len(atts) == 0 {
|
||||
return bls.NewSet(), nil
|
||||
}
|
||||
|
||||
@@ -36,7 +36,9 @@ go_test(
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/core/state:go_default_library",
|
||||
"//beacon-chain/core/state/stateutils:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//beacon-chain/core/validators:go_default_library",
|
||||
"//beacon-chain/state/interface:go_default_library",
|
||||
"//beacon-chain/state/stateV0:go_default_library",
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"//shared/params/spectest:go_default_library",
|
||||
@@ -71,7 +73,9 @@ go_test(
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/core/state:go_default_library",
|
||||
"//beacon-chain/core/state/stateutils:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//beacon-chain/core/validators:go_default_library",
|
||||
"//beacon-chain/state/interface:go_default_library",
|
||||
"//beacon-chain/state/stateV0:go_default_library",
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"//shared/params/spectest:go_default_library",
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
package spectest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
v "github.com/prysmaticlabs/prysm/beacon-chain/core/validators"
|
||||
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
|
||||
"github.com/prysmaticlabs/prysm/shared/params/spectest"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
@@ -24,7 +27,9 @@ func runAttesterSlashingTest(t *testing.T, config string) {
|
||||
require.NoError(t, attSlashing.UnmarshalSSZ(attSlashingFile), "Failed to unmarshal")
|
||||
|
||||
body := ðpb.BeaconBlockBody{AttesterSlashings: []*ethpb.AttesterSlashing{attSlashing}}
|
||||
testutil.RunBlockOperationTest(t, folderPath, body, blocks.ProcessAttesterSlashings)
|
||||
testutil.RunBlockOperationTest(t, folderPath, body, func(ctx context.Context, s iface.BeaconState, b *ethpb.SignedBeaconBlock) (iface.BeaconState, error) {
|
||||
return blocks.ProcessAttesterSlashings(ctx, s, b.Block.Body.AttesterSlashings, v.SlashValidator)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"github.com/gogo/protobuf/proto"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateV0"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/params/spectest"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
@@ -33,7 +33,7 @@ func runBlockHeaderTest(t *testing.T, config string) {
|
||||
require.NoError(t, err)
|
||||
preBeaconStateBase := &pb.BeaconState{}
|
||||
require.NoError(t, preBeaconStateBase.UnmarshalSSZ(preBeaconStateFile), "Failed to unmarshal")
|
||||
preBeaconState, err := stateTrie.InitializeFromProto(preBeaconStateBase)
|
||||
preBeaconState, err := stateV0.InitializeFromProto(preBeaconStateBase)
|
||||
require.NoError(t, err)
|
||||
|
||||
// If the post.ssz is not present, it means the test should fail on our end.
|
||||
@@ -46,7 +46,9 @@ func runBlockHeaderTest(t *testing.T, config string) {
|
||||
}
|
||||
|
||||
// Spectest blocks are not signed, so we'll call NoVerify to skip sig verification.
|
||||
beaconState, err := blocks.ProcessBlockHeaderNoVerify(preBeaconState, block)
|
||||
bodyRoot, err := block.Body.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
beaconState, err := blocks.ProcessBlockHeaderNoVerify(preBeaconState, block.Slot, block.ProposerIndex, block.ParentRoot, bodyRoot[:])
|
||||
if postSSZExists {
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -55,7 +57,9 @@ func runBlockHeaderTest(t *testing.T, config string) {
|
||||
|
||||
postBeaconState := &pb.BeaconState{}
|
||||
require.NoError(t, postBeaconState.UnmarshalSSZ(postBeaconStateFile), "Failed to unmarshal")
|
||||
if !proto.Equal(beaconState.CloneInnerState(), postBeaconState) {
|
||||
pbState, err := stateV0.ProtobufBeaconState(beaconState.CloneInnerState())
|
||||
require.NoError(t, err)
|
||||
if !proto.Equal(pbState, postBeaconState) {
|
||||
diff, _ := messagediff.PrettyDiff(beaconState.CloneInnerState(), postBeaconState)
|
||||
t.Log(diff)
|
||||
t.Fatal("Post state does not match expected")
|
||||
|
||||
@@ -15,7 +15,8 @@ import (
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateV0"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/params/spectest"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
@@ -38,7 +39,7 @@ func runBlockProcessingTest(t *testing.T, config string) {
|
||||
require.NoError(t, err)
|
||||
beaconStateBase := &pb.BeaconState{}
|
||||
require.NoError(t, beaconStateBase.UnmarshalSSZ(preBeaconStateFile), "Failed to unmarshal")
|
||||
beaconState, err := stateTrie.InitializeFromProto(beaconStateBase)
|
||||
beaconState, err := stateV0.InitializeFromProto(beaconStateBase)
|
||||
require.NoError(t, err)
|
||||
|
||||
file, err := testutil.BazelFileBytes(testsFolderPath, folder.Name(), "meta.yaml")
|
||||
@@ -48,16 +49,20 @@ func runBlockProcessingTest(t *testing.T, config string) {
|
||||
require.NoError(t, testutil.UnmarshalYaml(file, metaYaml), "Failed to Unmarshal")
|
||||
|
||||
var transitionError error
|
||||
var processedState iface.BeaconState
|
||||
var ok bool
|
||||
for i := 0; i < metaYaml.BlocksCount; i++ {
|
||||
filename := fmt.Sprintf("blocks_%d.ssz", i)
|
||||
blockFile, err := testutil.BazelFileBytes(testsFolderPath, folder.Name(), filename)
|
||||
require.NoError(t, err)
|
||||
block := ðpb.SignedBeaconBlock{}
|
||||
require.NoError(t, block.UnmarshalSSZ(blockFile), "Failed to unmarshal")
|
||||
beaconState, transitionError = state.ExecuteStateTransition(context.Background(), beaconState, block)
|
||||
processedState, transitionError = state.ExecuteStateTransition(context.Background(), beaconState, block)
|
||||
if transitionError != nil {
|
||||
break
|
||||
}
|
||||
beaconState, ok = processedState.(*stateV0.BeaconState)
|
||||
require.Equal(t, true, ok)
|
||||
}
|
||||
|
||||
// If the post.ssz is not present, it means the test should fail on our end.
|
||||
@@ -79,8 +84,9 @@ func runBlockProcessingTest(t *testing.T, config string) {
|
||||
|
||||
postBeaconState := &pb.BeaconState{}
|
||||
require.NoError(t, postBeaconState.UnmarshalSSZ(postBeaconStateFile), "Failed to unmarshal")
|
||||
|
||||
if !proto.Equal(beaconState.InnerStateUnsafe(), postBeaconState) {
|
||||
pbState, err := stateV0.ProtobufBeaconState(beaconState.InnerStateUnsafe())
|
||||
require.NoError(t, err)
|
||||
if !proto.Equal(pbState, postBeaconState) {
|
||||
diff, _ := messagediff.PrettyDiff(beaconState.InnerStateUnsafe(), postBeaconState)
|
||||
t.Log(diff)
|
||||
t.Fatal("Post state does not match expected")
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package spectest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
|
||||
"github.com/prysmaticlabs/prysm/shared/params/spectest"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
@@ -24,7 +26,10 @@ func runDepositTest(t *testing.T, config string) {
|
||||
require.NoError(t, deposit.UnmarshalSSZ(depositFile), "Failed to unmarshal")
|
||||
|
||||
body := ðpb.BeaconBlockBody{Deposits: []*ethpb.Deposit{deposit}}
|
||||
testutil.RunBlockOperationTest(t, folderPath, body, blocks.ProcessDeposits)
|
||||
processDepositsFunc := func(ctx context.Context, s iface.BeaconState, b *ethpb.SignedBeaconBlock) (iface.BeaconState, error) {
|
||||
return blocks.ProcessDeposits(ctx, s, b.Block.Body.Deposits)
|
||||
}
|
||||
testutil.RunBlockOperationTest(t, folderPath, body, processDepositsFunc)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
package spectest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
v "github.com/prysmaticlabs/prysm/beacon-chain/core/validators"
|
||||
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
|
||||
"github.com/prysmaticlabs/prysm/shared/params/spectest"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
@@ -24,7 +27,9 @@ func runProposerSlashingTest(t *testing.T, config string) {
|
||||
require.NoError(t, proposerSlashing.UnmarshalSSZ(proposerSlashingFile), "Failed to unmarshal")
|
||||
|
||||
body := ðpb.BeaconBlockBody{ProposerSlashings: []*ethpb.ProposerSlashing{proposerSlashing}}
|
||||
testutil.RunBlockOperationTest(t, folderPath, body, blocks.ProcessProposerSlashings)
|
||||
testutil.RunBlockOperationTest(t, folderPath, body, func(ctx context.Context, s iface.BeaconState, b *ethpb.SignedBeaconBlock) (iface.BeaconState, error) {
|
||||
return blocks.ProcessProposerSlashings(ctx, s, b.Block.Body.ProposerSlashings, v.SlashValidator)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package spectest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
|
||||
"github.com/prysmaticlabs/prysm/shared/params/spectest"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
@@ -24,7 +26,9 @@ func runVoluntaryExitTest(t *testing.T, config string) {
|
||||
require.NoError(t, voluntaryExit.UnmarshalSSZ(exitFile), "Failed to unmarshal")
|
||||
|
||||
body := ðpb.BeaconBlockBody{VoluntaryExits: []*ethpb.SignedVoluntaryExit{voluntaryExit}}
|
||||
testutil.RunBlockOperationTest(t, folderPath, body, blocks.ProcessVoluntaryExits)
|
||||
testutil.RunBlockOperationTest(t, folderPath, body, func(ctx context.Context, s iface.BeaconState, b *ethpb.SignedBeaconBlock) (iface.BeaconState, error) {
|
||||
return blocks.ProcessVoluntaryExits(ctx, s, b.Block.Body.VoluntaryExits)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,12 +9,14 @@ go_library(
|
||||
deps = [
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/core/validators:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//beacon-chain/state/interface:go_default_library",
|
||||
"//beacon-chain/state/stateV0:go_default_library",
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/attestationutil:go_default_library",
|
||||
"//shared/mathutil:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
|
||||
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
|
||||
],
|
||||
)
|
||||
@@ -29,7 +31,8 @@ go_test(
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//beacon-chain/state/interface:go_default_library",
|
||||
"//beacon-chain/state/stateV0:go_default_library",
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"//shared/testutil:go_default_library",
|
||||
|
||||
@@ -9,10 +9,12 @@ import (
|
||||
"sort"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/validators"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateV0"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/attestationutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/mathutil"
|
||||
@@ -22,7 +24,7 @@ import (
|
||||
// sortableIndices implements the Sort interface to sort newly activated validator indices
|
||||
// by activation epoch and by index number.
|
||||
type sortableIndices struct {
|
||||
indices []uint64
|
||||
indices []types.ValidatorIndex
|
||||
validators []*ethpb.Validator
|
||||
}
|
||||
|
||||
@@ -42,9 +44,13 @@ func (s sortableIndices) Less(i, j int) bool {
|
||||
// need to get attesting balance from attestations.
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
// def get_attesting_balance(state: BeaconState, attestations: List[PendingAttestation]) -> Gwei:
|
||||
// def get_attesting_balance(state: BeaconState, attestations: Sequence[PendingAttestation]) -> Gwei:
|
||||
// """
|
||||
// Return the combined effective balance of the set of unslashed validators participating in ``attestations``.
|
||||
// Note: ``get_total_balance`` returns ``EFFECTIVE_BALANCE_INCREMENT`` Gwei minimum to avoid divisions by zero.
|
||||
// """
|
||||
// return get_total_balance(state, get_unslashed_attesting_indices(state, attestations))
|
||||
func AttestingBalance(state *stateTrie.BeaconState, atts []*pb.PendingAttestation) (uint64, error) {
|
||||
func AttestingBalance(state iface.ReadOnlyBeaconState, atts []*pb.PendingAttestation) (uint64, error) {
|
||||
indices, err := UnslashedAttestingIndices(state, atts)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "could not get attesting indices")
|
||||
@@ -75,7 +81,7 @@ func AttestingBalance(state *stateTrie.BeaconState, atts []*pb.PendingAttestatio
|
||||
// for index in activation_queue[:get_validator_churn_limit(state)]:
|
||||
// validator = state.validators[index]
|
||||
// validator.activation_epoch = compute_activation_exit_epoch(get_current_epoch(state))
|
||||
func ProcessRegistryUpdates(state *stateTrie.BeaconState) (*stateTrie.BeaconState, error) {
|
||||
func ProcessRegistryUpdates(state iface.BeaconState) (iface.BeaconState, error) {
|
||||
currentEpoch := helpers.CurrentEpoch(state)
|
||||
vals := state.Validators()
|
||||
var err error
|
||||
@@ -85,7 +91,7 @@ func ProcessRegistryUpdates(state *stateTrie.BeaconState) (*stateTrie.BeaconStat
|
||||
// Process the validators for activation eligibility.
|
||||
if helpers.IsEligibleForActivationQueue(validator) {
|
||||
validator.ActivationEligibilityEpoch = activationEligibilityEpoch
|
||||
if err := state.UpdateValidatorAtIndex(uint64(idx), validator); err != nil {
|
||||
if err := state.UpdateValidatorAtIndex(types.ValidatorIndex(idx), validator); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@@ -94,7 +100,7 @@ func ProcessRegistryUpdates(state *stateTrie.BeaconState) (*stateTrie.BeaconStat
|
||||
isActive := helpers.IsActiveValidator(validator, currentEpoch)
|
||||
belowEjectionBalance := validator.EffectiveBalance <= ejectionBal
|
||||
if isActive && belowEjectionBalance {
|
||||
state, err = validators.InitiateValidatorExit(state, uint64(idx))
|
||||
state, err = validators.InitiateValidatorExit(state, types.ValidatorIndex(idx))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not initiate exit for validator %d", idx)
|
||||
}
|
||||
@@ -102,10 +108,10 @@ func ProcessRegistryUpdates(state *stateTrie.BeaconState) (*stateTrie.BeaconStat
|
||||
}
|
||||
|
||||
// Queue validators eligible for activation and not yet dequeued for activation.
|
||||
var activationQ []uint64
|
||||
var activationQ []types.ValidatorIndex
|
||||
for idx, validator := range vals {
|
||||
if helpers.IsEligibleForActivation(state, validator) {
|
||||
activationQ = append(activationQ, uint64(idx))
|
||||
activationQ = append(activationQ, types.ValidatorIndex(idx))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,10 +157,10 @@ func ProcessRegistryUpdates(state *stateTrie.BeaconState) (*stateTrie.BeaconStat
|
||||
// for index, validator in enumerate(state.validators):
|
||||
// if validator.slashed and epoch + EPOCHS_PER_SLASHINGS_VECTOR // 2 == validator.withdrawable_epoch:
|
||||
// increment = EFFECTIVE_BALANCE_INCREMENT # Factored out from penalty numerator to avoid uint64 overflow
|
||||
// penalty_numerator = validator.effective_balance // increment * adjusted_total_slashing_balance
|
||||
// penalty_numerator = validator.effective_balance // increment * adjusted_total_slashing_balance
|
||||
// penalty = penalty_numerator // total_balance * increment
|
||||
// decrease_balance(state, ValidatorIndex(index), penalty)
|
||||
func ProcessSlashings(state *stateTrie.BeaconState) (*stateTrie.BeaconState, error) {
|
||||
func ProcessSlashings(state iface.BeaconState) (iface.BeaconState, error) {
|
||||
currentEpoch := helpers.CurrentEpoch(state)
|
||||
totalBalance, err := helpers.TotalActiveBalance(state)
|
||||
if err != nil {
|
||||
@@ -180,7 +186,7 @@ func ProcessSlashings(state *stateTrie.BeaconState) (*stateTrie.BeaconState, err
|
||||
if val.Slashed && correctEpoch {
|
||||
penaltyNumerator := val.EffectiveBalance / increment * minSlashing
|
||||
penalty := penaltyNumerator / totalBalance * increment
|
||||
if err := helpers.DecreaseBalance(state, uint64(idx), penalty); err != nil {
|
||||
if err := helpers.DecreaseBalance(state, types.ValidatorIndex(idx), penalty); err != nil {
|
||||
return false, val, err
|
||||
}
|
||||
return true, val, nil
|
||||
@@ -190,47 +196,15 @@ func ProcessSlashings(state *stateTrie.BeaconState) (*stateTrie.BeaconState, err
|
||||
return state, err
|
||||
}
|
||||
|
||||
// ProcessFinalUpdates processes the final updates during epoch processing.
|
||||
// ProcessEth1DataReset processes updates to ETH1 data votes during epoch processing.
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
// def process_final_updates(state: BeaconState) -> None:
|
||||
// current_epoch = get_current_epoch(state)
|
||||
// next_epoch = Epoch(current_epoch + 1)
|
||||
// def process_eth1_data_reset(state: BeaconState) -> None:
|
||||
// next_epoch = Epoch(get_current_epoch(state) + 1)
|
||||
// # Reset eth1 data votes
|
||||
// if next_epoch % EPOCHS_PER_ETH1_VOTING_PERIOD == 0:
|
||||
// state.eth1_data_votes = []
|
||||
// # Update effective balances with hysteresis
|
||||
// for index, validator in enumerate(state.validators):
|
||||
// balance = state.balances[index]
|
||||
// HYSTERESIS_INCREMENT = EFFECTIVE_BALANCE_INCREMENT // HYSTERESIS_QUOTIENT
|
||||
// DOWNWARD_THRESHOLD = HYSTERESIS_INCREMENT * HYSTERESIS_DOWNWARD_MULTIPLIER
|
||||
// UPWARD_THRESHOLD = HYSTERESIS_INCREMENT * HYSTERESIS_UPWARD_MULTIPLIER
|
||||
// if (
|
||||
// balance + DOWNWARD_THRESHOLD < validator.effective_balance
|
||||
// or validator.effective_balance + UPWARD_THRESHOLD < balance
|
||||
// ):
|
||||
// validator.effective_balance = min(balance - balance % EFFECTIVE_BALANCE_INCREMENT, MAX_EFFECTIVE_BALANCE)
|
||||
// index_epoch = Epoch(next_epoch + ACTIVATION_EXIT_DELAY)
|
||||
// index_root_position = index_epoch % EPOCHS_PER_HISTORICAL_VECTOR
|
||||
// indices_list = List[ValidatorIndex, VALIDATOR_REGISTRY_LIMIT](get_active_validator_indices(state, index_epoch))
|
||||
// state.active_index_roots[index_root_position] = hash_tree_root(indices_list)
|
||||
// # Set committees root
|
||||
// committee_root_position = next_epoch % EPOCHS_PER_HISTORICAL_VECTOR
|
||||
// state.compact_committees_roots[committee_root_position] = get_compact_committees_root(state, next_epoch)
|
||||
// # Reset slashings
|
||||
// state.slashings[next_epoch % EPOCHS_PER_SLASHINGS_VECTOR] = Gwei(0)
|
||||
// # Set randao mix
|
||||
// state.randao_mixes[next_epoch % EPOCHS_PER_HISTORICAL_VECTOR] = get_randao_mix(state, current_epoch)
|
||||
// # Set historical root accumulator
|
||||
// if next_epoch % (SLOTS_PER_HISTORICAL_ROOT // SLOTS_PER_EPOCH) == 0:
|
||||
// historical_batch = HistoricalBatch(block_roots=state.block_roots, state_roots=state.state_roots)
|
||||
// state.historical_roots.append(hash_tree_root(historical_batch))
|
||||
// # Update start shard
|
||||
// state.start_shard = Shard((state.start_shard + get_shard_delta(state, current_epoch)) % SHARD_COUNT)
|
||||
// # Rotate current/previous epoch attestations
|
||||
// state.previous_epoch_attestations = state.current_epoch_attestations
|
||||
// state.current_epoch_attestations = []
|
||||
func ProcessFinalUpdates(state *stateTrie.BeaconState) (*stateTrie.BeaconState, error) {
|
||||
func ProcessEth1DataReset(state iface.BeaconState) (iface.BeaconState, error) {
|
||||
currentEpoch := helpers.CurrentEpoch(state)
|
||||
nextEpoch := currentEpoch + 1
|
||||
|
||||
@@ -241,6 +215,25 @@ func ProcessFinalUpdates(state *stateTrie.BeaconState) (*stateTrie.BeaconState,
|
||||
}
|
||||
}
|
||||
|
||||
return state, nil
|
||||
}
|
||||
|
||||
// ProcessEffectiveBalanceUpdates processes effective balance updates during epoch processing.
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
// def process_effective_balance_updates(state: BeaconState) -> None:
|
||||
// # Update effective balances with hysteresis
|
||||
// for index, validator in enumerate(state.validators):
|
||||
// balance = state.balances[index]
|
||||
// HYSTERESIS_INCREMENT = uint64(EFFECTIVE_BALANCE_INCREMENT // HYSTERESIS_QUOTIENT)
|
||||
// DOWNWARD_THRESHOLD = HYSTERESIS_INCREMENT * HYSTERESIS_DOWNWARD_MULTIPLIER
|
||||
// UPWARD_THRESHOLD = HYSTERESIS_INCREMENT * HYSTERESIS_UPWARD_MULTIPLIER
|
||||
// if (
|
||||
// balance + DOWNWARD_THRESHOLD < validator.effective_balance
|
||||
// or validator.effective_balance + UPWARD_THRESHOLD < balance
|
||||
// ):
|
||||
// validator.effective_balance = min(balance - balance % EFFECTIVE_BALANCE_INCREMENT, MAX_EFFECTIVE_BALANCE)
|
||||
func ProcessEffectiveBalanceUpdates(state iface.BeaconState) (iface.BeaconState, error) {
|
||||
effBalanceInc := params.BeaconConfig().EffectiveBalanceIncrement
|
||||
maxEffBalance := params.BeaconConfig().MaxEffectiveBalance
|
||||
hysteresisInc := effBalanceInc / params.BeaconConfig().HysteresisQuotient
|
||||
@@ -259,12 +252,16 @@ func ProcessFinalUpdates(state *stateTrie.BeaconState) (*stateTrie.BeaconState,
|
||||
balance := bals[idx]
|
||||
|
||||
if balance+downwardThreshold < val.EffectiveBalance || val.EffectiveBalance+upwardThreshold < balance {
|
||||
newVal := stateTrie.CopyValidator(val)
|
||||
newVal.EffectiveBalance = maxEffBalance
|
||||
if newVal.EffectiveBalance > balance-balance%effBalanceInc {
|
||||
newVal.EffectiveBalance = balance - balance%effBalanceInc
|
||||
effectiveBal := maxEffBalance
|
||||
if effectiveBal > balance-balance%effBalanceInc {
|
||||
effectiveBal = balance - balance%effBalanceInc
|
||||
}
|
||||
return true, newVal, nil
|
||||
if effectiveBal != val.EffectiveBalance {
|
||||
newVal := stateV0.CopyValidator(val)
|
||||
newVal.EffectiveBalance = effectiveBal
|
||||
return true, newVal, nil
|
||||
}
|
||||
return false, val, nil
|
||||
}
|
||||
return false, val, nil
|
||||
}
|
||||
@@ -273,6 +270,20 @@ func ProcessFinalUpdates(state *stateTrie.BeaconState) (*stateTrie.BeaconState,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return state, nil
|
||||
}
|
||||
|
||||
// ProcessSlashingsReset processes the total slashing balances updates during epoch processing.
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
// def process_slashings_reset(state: BeaconState) -> None:
|
||||
// next_epoch = Epoch(get_current_epoch(state) + 1)
|
||||
// # Reset slashings
|
||||
// state.slashings[next_epoch % EPOCHS_PER_SLASHINGS_VECTOR] = Gwei(0)
|
||||
func ProcessSlashingsReset(state iface.BeaconState) (iface.BeaconState, error) {
|
||||
currentEpoch := helpers.CurrentEpoch(state)
|
||||
nextEpoch := currentEpoch + 1
|
||||
|
||||
// Set total slashed balances.
|
||||
slashedExitLength := params.BeaconConfig().EpochsPerSlashingsVector
|
||||
slashedEpoch := nextEpoch % slashedExitLength
|
||||
@@ -288,6 +299,21 @@ func ProcessFinalUpdates(state *stateTrie.BeaconState) (*stateTrie.BeaconState,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return state, nil
|
||||
}
|
||||
|
||||
// ProcessRandaoMixesReset processes the final updates to RANDAO mix during epoch processing.
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
// def process_randao_mixes_reset(state: BeaconState) -> None:
|
||||
// current_epoch = get_current_epoch(state)
|
||||
// next_epoch = Epoch(current_epoch + 1)
|
||||
// # Set randao mix
|
||||
// state.randao_mixes[next_epoch % EPOCHS_PER_HISTORICAL_VECTOR] = get_randao_mix(state, current_epoch)
|
||||
func ProcessRandaoMixesReset(state iface.BeaconState) (iface.BeaconState, error) {
|
||||
currentEpoch := helpers.CurrentEpoch(state)
|
||||
nextEpoch := currentEpoch + 1
|
||||
|
||||
// Set RANDAO mix.
|
||||
randaoMixLength := params.BeaconConfig().EpochsPerHistoricalVector
|
||||
if uint64(state.RandaoMixesLength()) != uint64(randaoMixLength) {
|
||||
@@ -305,6 +331,22 @@ func ProcessFinalUpdates(state *stateTrie.BeaconState) (*stateTrie.BeaconState,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return state, nil
|
||||
}
|
||||
|
||||
// ProcessHistoricalRootsUpdate processes the updates to historical root accumulator during epoch processing.
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
// def process_historical_roots_update(state: BeaconState) -> None:
|
||||
// # Set historical root accumulator
|
||||
// next_epoch = Epoch(get_current_epoch(state) + 1)
|
||||
// if next_epoch % (SLOTS_PER_HISTORICAL_ROOT // SLOTS_PER_EPOCH) == 0:
|
||||
// historical_batch = HistoricalBatch(block_roots=state.block_roots, state_roots=state.state_roots)
|
||||
// state.historical_roots.append(hash_tree_root(historical_batch))
|
||||
func ProcessHistoricalRootsUpdate(state iface.BeaconState) (iface.BeaconState, error) {
|
||||
currentEpoch := helpers.CurrentEpoch(state)
|
||||
nextEpoch := currentEpoch + 1
|
||||
|
||||
// Set historical root accumulator.
|
||||
epochsPerHistoricalRoot := params.BeaconConfig().SlotsPerHistoricalRoot.DivSlot(params.BeaconConfig().SlotsPerEpoch)
|
||||
if nextEpoch.Mod(uint64(epochsPerHistoricalRoot)) == 0 {
|
||||
@@ -321,13 +363,63 @@ func ProcessFinalUpdates(state *stateTrie.BeaconState) (*stateTrie.BeaconState,
|
||||
}
|
||||
}
|
||||
|
||||
return state, nil
|
||||
}
|
||||
|
||||
// ProcessParticipationRecordUpdates rotates current/previous epoch attestations during epoch processing.
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
// def process_participation_record_updates(state: BeaconState) -> None:
|
||||
// # Rotate current/previous epoch attestations
|
||||
// state.previous_epoch_attestations = state.current_epoch_attestations
|
||||
// state.current_epoch_attestations = []
|
||||
func ProcessParticipationRecordUpdates(state iface.BeaconState) (iface.BeaconState, error) {
|
||||
if err := state.RotateAttestations(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return state, nil
|
||||
}
|
||||
|
||||
// ProcessFinalUpdates processes the final updates during epoch processing.
|
||||
func ProcessFinalUpdates(state iface.BeaconState) (iface.BeaconState, error) {
|
||||
var err error
|
||||
|
||||
// Reset ETH1 data votes.
|
||||
state, err = ProcessEth1DataReset(state)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Update effective balances with hysteresis.
|
||||
state, err = ProcessEffectiveBalanceUpdates(state)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Set total slashed balances.
|
||||
state, err = ProcessSlashingsReset(state)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Set RANDAO mix.
|
||||
state, err = ProcessRandaoMixesReset(state)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Set historical root accumulator.
|
||||
state, err = ProcessHistoricalRootsUpdate(state)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Rotate current and previous epoch attestations.
|
||||
if err := state.SetPreviousEpochAttestations(state.CurrentEpochAttestations()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := state.SetCurrentEpochAttestations([]*pb.PendingAttestation{}); err != nil {
|
||||
state, err = ProcessParticipationRecordUpdates(state)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return state, nil
|
||||
}
|
||||
|
||||
@@ -341,8 +433,8 @@ func ProcessFinalUpdates(state *stateTrie.BeaconState) (*stateTrie.BeaconState,
|
||||
// for a in attestations:
|
||||
// output = output.union(get_attesting_indices(state, a.data, a.aggregation_bits))
|
||||
// return set(filter(lambda index: not state.validators[index].slashed, output))
|
||||
func UnslashedAttestingIndices(state *stateTrie.BeaconState, atts []*pb.PendingAttestation) ([]uint64, error) {
|
||||
var setIndices []uint64
|
||||
func UnslashedAttestingIndices(state iface.ReadOnlyBeaconState, atts []*pb.PendingAttestation) ([]types.ValidatorIndex, error) {
|
||||
var setIndices []types.ValidatorIndex
|
||||
seen := make(map[uint64]bool)
|
||||
|
||||
for _, att := range atts {
|
||||
@@ -357,7 +449,7 @@ func UnslashedAttestingIndices(state *stateTrie.BeaconState, atts []*pb.PendingA
|
||||
// Create a set for attesting indices
|
||||
for _, index := range attestingIndices {
|
||||
if !seen[index] {
|
||||
setIndices = append(setIndices, index)
|
||||
setIndices = append(setIndices, types.ValidatorIndex(index))
|
||||
}
|
||||
seen[index] = true
|
||||
}
|
||||
@@ -386,10 +478,10 @@ func UnslashedAttestingIndices(state *stateTrie.BeaconState, atts []*pb.PendingA
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
// def get_base_reward(state: BeaconState, index: ValidatorIndex) -> Gwei:
|
||||
// total_balance = get_total_active_balance(state)
|
||||
// effective_balance = state.validator_registry[index].effective_balance
|
||||
// return effective_balance * BASE_REWARD_FACTOR // integer_squareroot(total_balance) // BASE_REWARDS_PER_EPOCH
|
||||
func BaseReward(state *stateTrie.BeaconState, index uint64) (uint64, error) {
|
||||
// total_balance = get_total_active_balance(state)
|
||||
// effective_balance = state.validators[index].effective_balance
|
||||
// return Gwei(effective_balance * BASE_REWARD_FACTOR // integer_squareroot(total_balance) // BASE_REWARDS_PER_EPOCH)
|
||||
func BaseReward(state iface.ReadOnlyBeaconState, index types.ValidatorIndex) (uint64, error) {
|
||||
totalBalance, err := helpers.TotalActiveBalance(state)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "could not calculate active balance")
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"testing"
|
||||
|
||||
fuzz "github.com/google/gofuzz"
|
||||
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateV0"
|
||||
ethereum_beacon_p2p_v1 "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
)
|
||||
@@ -15,7 +15,7 @@ func TestFuzzFinalUpdates_10000(t *testing.T) {
|
||||
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(base)
|
||||
s, err := beaconstate.InitializeFromProtoUnsafe(base)
|
||||
s, err := stateV0.InitializeFromProtoUnsafe(base)
|
||||
require.NoError(t, err)
|
||||
_, err = ProcessFinalUpdates(s)
|
||||
_ = err
|
||||
|
||||
@@ -10,7 +10,8 @@ import (
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateV0"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
@@ -42,7 +43,7 @@ func TestUnslashedAttestingIndices_CanSortAndFilter(t *testing.T) {
|
||||
Validators: validators,
|
||||
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
|
||||
}
|
||||
beaconState, err := state.InitializeFromProto(base)
|
||||
beaconState, err := stateV0.InitializeFromProto(base)
|
||||
require.NoError(t, err)
|
||||
|
||||
indices, err := epoch.UnslashedAttestingIndices(beaconState, atts)
|
||||
@@ -88,7 +89,7 @@ func TestUnslashedAttestingIndices_DuplicatedAttestations(t *testing.T) {
|
||||
Validators: validators,
|
||||
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
|
||||
}
|
||||
beaconState, err := state.InitializeFromProto(base)
|
||||
beaconState, err := stateV0.InitializeFromProto(base)
|
||||
require.NoError(t, err)
|
||||
|
||||
indices, err := epoch.UnslashedAttestingIndices(beaconState, atts)
|
||||
@@ -134,7 +135,7 @@ func TestAttestingBalance_CorrectBalance(t *testing.T) {
|
||||
Validators: validators,
|
||||
Balances: balances,
|
||||
}
|
||||
beaconState, err := state.InitializeFromProto(base)
|
||||
beaconState, err := stateV0.InitializeFromProto(base)
|
||||
require.NoError(t, err)
|
||||
|
||||
balance, err := epoch.AttestingBalance(beaconState, atts)
|
||||
@@ -160,7 +161,7 @@ func TestBaseReward_AccurateRewards(t *testing.T) {
|
||||
{ExitEpoch: params.BeaconConfig().FarFutureEpoch, EffectiveBalance: tt.b}},
|
||||
Balances: []uint64{tt.a},
|
||||
}
|
||||
beaconState, err := state.InitializeFromProto(base)
|
||||
beaconState, err := stateV0.InitializeFromProto(base)
|
||||
require.NoError(t, err)
|
||||
c, err := epoch.BaseReward(beaconState, 0)
|
||||
require.NoError(t, err)
|
||||
@@ -175,7 +176,7 @@ func TestProcessSlashings_NotSlashed(t *testing.T) {
|
||||
Balances: []uint64{params.BeaconConfig().MaxEffectiveBalance},
|
||||
Slashings: []uint64{0, 1e9},
|
||||
}
|
||||
s, err := state.InitializeFromProto(base)
|
||||
s, err := stateV0.InitializeFromProto(base)
|
||||
require.NoError(t, err)
|
||||
newState, err := epoch.ProcessSlashings(s)
|
||||
require.NoError(t, err)
|
||||
@@ -253,7 +254,7 @@ func TestProcessSlashings_SlashedLess(t *testing.T) {
|
||||
for i, tt := range tests {
|
||||
t.Run(fmt.Sprint(i), func(t *testing.T) {
|
||||
original := proto.Clone(tt.state)
|
||||
s, err := state.InitializeFromProto(tt.state)
|
||||
s, err := stateV0.InitializeFromProto(tt.state)
|
||||
require.NoError(t, err)
|
||||
newState, err := epoch.ProcessSlashings(s)
|
||||
require.NoError(t, err)
|
||||
@@ -295,7 +296,9 @@ func TestProcessFinalUpdates_CanProcess(t *testing.T) {
|
||||
|
||||
// Verify historical root accumulator was appended.
|
||||
assert.Equal(t, 1, len(newS.HistoricalRoots()), "Unexpected slashed balance")
|
||||
assert.NotNil(t, newS.CurrentEpochAttestations(), "Nil value stored in current epoch attestations instead of empty slice")
|
||||
currAtt, err := newS.CurrentEpochAttestations()
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, currAtt, "Nil value stored in current epoch attestations instead of empty slice")
|
||||
}
|
||||
|
||||
func TestProcessRegistryUpdates_NoRotation(t *testing.T) {
|
||||
@@ -311,7 +314,7 @@ func TestProcessRegistryUpdates_NoRotation(t *testing.T) {
|
||||
},
|
||||
FinalizedCheckpoint: ðpb.Checkpoint{Root: make([]byte, 32)},
|
||||
}
|
||||
beaconState, err := state.InitializeFromProto(base)
|
||||
beaconState, err := stateV0.InitializeFromProto(base)
|
||||
require.NoError(t, err)
|
||||
newState, err := epoch.ProcessRegistryUpdates(beaconState)
|
||||
require.NoError(t, err)
|
||||
@@ -334,7 +337,7 @@ func TestProcessRegistryUpdates_EligibleToActivate(t *testing.T) {
|
||||
ActivationEpoch: params.BeaconConfig().FarFutureEpoch,
|
||||
})
|
||||
}
|
||||
beaconState, err := state.InitializeFromProto(base)
|
||||
beaconState, err := stateV0.InitializeFromProto(base)
|
||||
require.NoError(t, err)
|
||||
currentEpoch := helpers.CurrentEpoch(beaconState)
|
||||
newState, err := epoch.ProcessRegistryUpdates(beaconState)
|
||||
@@ -363,7 +366,7 @@ func TestProcessRegistryUpdates_ActivationCompletes(t *testing.T) {
|
||||
},
|
||||
FinalizedCheckpoint: ðpb.Checkpoint{Root: make([]byte, 32)},
|
||||
}
|
||||
beaconState, err := state.InitializeFromProto(base)
|
||||
beaconState, err := stateV0.InitializeFromProto(base)
|
||||
require.NoError(t, err)
|
||||
newState, err := epoch.ProcessRegistryUpdates(beaconState)
|
||||
require.NoError(t, err)
|
||||
@@ -387,7 +390,7 @@ func TestProcessRegistryUpdates_ValidatorsEjected(t *testing.T) {
|
||||
},
|
||||
FinalizedCheckpoint: ðpb.Checkpoint{Root: make([]byte, 32)},
|
||||
}
|
||||
beaconState, err := state.InitializeFromProto(base)
|
||||
beaconState, err := stateV0.InitializeFromProto(base)
|
||||
require.NoError(t, err)
|
||||
newState, err := epoch.ProcessRegistryUpdates(beaconState)
|
||||
require.NoError(t, err)
|
||||
@@ -412,7 +415,7 @@ func TestProcessRegistryUpdates_CanExits(t *testing.T) {
|
||||
},
|
||||
FinalizedCheckpoint: ðpb.Checkpoint{Root: make([]byte, 32)},
|
||||
}
|
||||
beaconState, err := state.InitializeFromProto(base)
|
||||
beaconState, err := stateV0.InitializeFromProto(base)
|
||||
require.NoError(t, err)
|
||||
newState, err := epoch.ProcessRegistryUpdates(beaconState)
|
||||
require.NoError(t, err)
|
||||
@@ -421,7 +424,7 @@ func TestProcessRegistryUpdates_CanExits(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func buildState(t testing.TB, slot types.Slot, validatorCount uint64) *state.BeaconState {
|
||||
func buildState(t testing.TB, slot types.Slot, validatorCount uint64) iface.BeaconState {
|
||||
validators := make([]*ethpb.Validator, validatorCount)
|
||||
for i := 0; i < len(validators); i++ {
|
||||
validators[i] = ðpb.Validator{
|
||||
|
||||
@@ -15,7 +15,7 @@ go_library(
|
||||
visibility = ["//beacon-chain:__subpackages__"],
|
||||
deps = [
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//beacon-chain/state/interface:go_default_library",
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/attestationutil:go_default_library",
|
||||
"//shared/mathutil:go_default_library",
|
||||
@@ -41,7 +41,7 @@ go_test(
|
||||
deps = [
|
||||
"//beacon-chain/core/epoch:go_default_library",
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//beacon-chain/state/stateV0:go_default_library",
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/attestationutil:go_default_library",
|
||||
"//shared/mathutil:go_default_library",
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/attestationutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
@@ -19,7 +19,7 @@ import (
|
||||
// it also tracks and updates epoch attesting balances.
|
||||
func ProcessAttestations(
|
||||
ctx context.Context,
|
||||
state *stateTrie.BeaconState,
|
||||
state iface.ReadOnlyBeaconState,
|
||||
vp []*Validator,
|
||||
pBal *Balance,
|
||||
) ([]*Validator, *Balance, error) {
|
||||
@@ -29,7 +29,15 @@ func ProcessAttestations(
|
||||
v := &Validator{}
|
||||
var err error
|
||||
|
||||
for _, a := range append(state.PreviousEpochAttestations(), state.CurrentEpochAttestations()...) {
|
||||
prevAtt, err := state.PreviousEpochAttestations()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
curAtt, err := state.CurrentEpochAttestations()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
for _, a := range append(prevAtt, curAtt...) {
|
||||
if a.InclusionDelay == 0 {
|
||||
return nil, nil, errors.New("attestation with inclusion delay of 0")
|
||||
}
|
||||
@@ -61,7 +69,7 @@ func ProcessAttestations(
|
||||
}
|
||||
|
||||
// AttestedCurrentEpoch returns true if attestation `a` attested once in current epoch and/or epoch boundary block.
|
||||
func AttestedCurrentEpoch(s *stateTrie.BeaconState, a *pb.PendingAttestation) (bool, bool, error) {
|
||||
func AttestedCurrentEpoch(s iface.ReadOnlyBeaconState, a *pb.PendingAttestation) (bool, bool, error) {
|
||||
currentEpoch := helpers.CurrentEpoch(s)
|
||||
var votedCurrentEpoch, votedTarget bool
|
||||
// Did validator vote current epoch.
|
||||
@@ -79,7 +87,7 @@ func AttestedCurrentEpoch(s *stateTrie.BeaconState, a *pb.PendingAttestation) (b
|
||||
}
|
||||
|
||||
// AttestedPrevEpoch returns true if attestation `a` attested once in previous epoch and epoch boundary block and/or the same head.
|
||||
func AttestedPrevEpoch(s *stateTrie.BeaconState, a *pb.PendingAttestation) (bool, bool, bool, error) {
|
||||
func AttestedPrevEpoch(s iface.ReadOnlyBeaconState, a *pb.PendingAttestation) (bool, bool, bool, error) {
|
||||
prevEpoch := helpers.PrevEpoch(s)
|
||||
var votedPrevEpoch, votedTarget, votedHead bool
|
||||
// Did validator vote previous epoch.
|
||||
@@ -107,7 +115,7 @@ func AttestedPrevEpoch(s *stateTrie.BeaconState, a *pb.PendingAttestation) (bool
|
||||
}
|
||||
|
||||
// SameTarget returns true if attestation `a` attested to the same target block in state.
|
||||
func SameTarget(state *stateTrie.BeaconState, a *pb.PendingAttestation, e types.Epoch) (bool, error) {
|
||||
func SameTarget(state iface.ReadOnlyBeaconState, a *pb.PendingAttestation, e types.Epoch) (bool, error) {
|
||||
r, err := helpers.BlockRoot(state, e)
|
||||
if err != nil {
|
||||
return false, err
|
||||
@@ -119,7 +127,7 @@ func SameTarget(state *stateTrie.BeaconState, a *pb.PendingAttestation, e types.
|
||||
}
|
||||
|
||||
// SameHead returns true if attestation `a` attested to the same block by attestation slot in state.
|
||||
func SameHead(state *stateTrie.BeaconState, a *pb.PendingAttestation) (bool, error) {
|
||||
func SameHead(state iface.ReadOnlyBeaconState, a *pb.PendingAttestation) (bool, error) {
|
||||
r, err := helpers.BlockRootAtSlot(state, a.Data.Slot)
|
||||
if err != nil {
|
||||
return false, err
|
||||
|
||||
@@ -170,9 +170,9 @@ func TestProcessAttestations(t *testing.T) {
|
||||
require.NoError(t, beaconState.SetBlockRoots(br))
|
||||
att2.Data.Target.Root = newRt[:]
|
||||
att2.Data.BeaconBlockRoot = newRt[:]
|
||||
err := beaconState.SetPreviousEpochAttestations([]*pb.PendingAttestation{{Data: att1.Data, AggregationBits: bf, InclusionDelay: 1}})
|
||||
err := beaconState.AppendPreviousEpochAttestations(&pb.PendingAttestation{Data: att1.Data, AggregationBits: bf, InclusionDelay: 1})
|
||||
require.NoError(t, err)
|
||||
err = beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{{Data: att2.Data, AggregationBits: bf, InclusionDelay: 1}})
|
||||
err = beaconState.AppendCurrentEpochAttestations(&pb.PendingAttestation{Data: att2.Data, AggregationBits: bf, InclusionDelay: 1})
|
||||
require.NoError(t, err)
|
||||
|
||||
pVals := make([]*precompute.Validator, validators)
|
||||
|
||||
@@ -4,16 +4,45 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
|
||||
)
|
||||
|
||||
// ProcessJustificationAndFinalizationPreCompute processes justification and finalization during
|
||||
// epoch processing. This is where a beacon node can justify and finalize a new epoch.
|
||||
// Note: this is an optimized version by passing in precomputed total and attesting balances.
|
||||
// def process_justification_and_finalization(state: BeaconState) -> None:
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
// def process_justification_and_finalization(state: BeaconState) -> None:
|
||||
// # Initial FFG checkpoint values have a `0x00` stub for `root`.
|
||||
// # Skip FFG updates in the first two epochs to avoid corner cases that might result in modifying this stub.
|
||||
// if get_current_epoch(state) <= GENESIS_EPOCH + 1:
|
||||
// return
|
||||
// previous_attestations = get_matching_target_attestations(state, get_previous_epoch(state))
|
||||
// current_attestations = get_matching_target_attestations(state, get_current_epoch(state))
|
||||
// total_active_balance = get_total_active_balance(state)
|
||||
// previous_target_balance = get_attesting_balance(state, previous_attestations)
|
||||
// current_target_balance = get_attesting_balance(state, current_attestations)
|
||||
// weigh_justification_and_finalization(state, total_active_balance, previous_target_balance, current_target_balance)
|
||||
func ProcessJustificationAndFinalizationPreCompute(state iface.BeaconState, pBal *Balance) (iface.BeaconState, error) {
|
||||
canProcessSlot, err := helpers.StartSlot(2 /*epoch*/)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if state.Slot() <= canProcessSlot {
|
||||
return state, nil
|
||||
}
|
||||
|
||||
return weighJustificationAndFinalization(state, pBal.ActiveCurrentEpoch, pBal.PrevEpochTargetAttested, pBal.CurrentEpochTargetAttested)
|
||||
}
|
||||
|
||||
// weighJustificationAndFinalization processes justification and finalization during
|
||||
// epoch processing. This is where a beacon node can justify and finalize a new epoch.
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
// def weigh_justification_and_finalization(state: BeaconState,
|
||||
// total_active_balance: Gwei,
|
||||
// previous_epoch_target_balance: Gwei,
|
||||
// current_epoch_target_balance: Gwei) -> None:
|
||||
// previous_epoch = get_previous_epoch(state)
|
||||
// current_epoch = get_current_epoch(state)
|
||||
// old_previous_justified_checkpoint = state.previous_justified_checkpoint
|
||||
@@ -21,15 +50,13 @@ import (
|
||||
//
|
||||
// # Process justifications
|
||||
// state.previous_justified_checkpoint = state.current_justified_checkpoint
|
||||
// state.justification_bits[1:] = state.justification_bits[:-1]
|
||||
// state.justification_bits[1:] = state.justification_bits[:JUSTIFICATION_BITS_LENGTH - 1]
|
||||
// state.justification_bits[0] = 0b0
|
||||
// matching_target_attestations = get_matching_target_attestations(state, previous_epoch) # Previous epoch
|
||||
// if get_attesting_balance(state, matching_target_attestations) * 3 >= get_total_active_balance(state) * 2:
|
||||
// if previous_epoch_target_balance * 3 >= total_active_balance * 2:
|
||||
// state.current_justified_checkpoint = Checkpoint(epoch=previous_epoch,
|
||||
// root=get_block_root(state, previous_epoch))
|
||||
// state.justification_bits[1] = 0b1
|
||||
// matching_target_attestations = get_matching_target_attestations(state, current_epoch) # Current epoch
|
||||
// if get_attesting_balance(state, matching_target_attestations) * 3 >= get_total_active_balance(state) * 2:
|
||||
// if current_epoch_target_balance * 3 >= total_active_balance * 2:
|
||||
// state.current_justified_checkpoint = Checkpoint(epoch=current_epoch,
|
||||
// root=get_block_root(state, current_epoch))
|
||||
// state.justification_bits[0] = 0b1
|
||||
@@ -48,15 +75,8 @@ import (
|
||||
// # The 1st/2nd most recent epochs are justified, the 1st using the 2nd as source
|
||||
// if all(bits[0:2]) and old_current_justified_checkpoint.epoch + 1 == current_epoch:
|
||||
// state.finalized_checkpoint = old_current_justified_checkpoint
|
||||
func ProcessJustificationAndFinalizationPreCompute(state *stateTrie.BeaconState, pBal *Balance) (*stateTrie.BeaconState, error) {
|
||||
canProcessSlot, err := helpers.StartSlot(2 /*epoch*/)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if state.Slot() <= canProcessSlot {
|
||||
return state, nil
|
||||
}
|
||||
|
||||
func weighJustificationAndFinalization(state iface.BeaconState,
|
||||
totalActiveBalance, prevEpochTargetBalance, currEpochTargetBalance uint64) (iface.BeaconState, error) {
|
||||
prevEpoch := helpers.PrevEpoch(state)
|
||||
currentEpoch := helpers.CurrentEpoch(state)
|
||||
oldPrevJustifiedCheckpoint := state.PreviousJustifiedCheckpoint()
|
||||
@@ -76,7 +96,7 @@ func ProcessJustificationAndFinalizationPreCompute(state *stateTrie.BeaconState,
|
||||
// We will use that paradigm here for consistency with the godoc spec definition.
|
||||
|
||||
// If 2/3 or more of total balance attested in the previous epoch.
|
||||
if 3*pBal.PrevEpochTargetAttested >= 2*pBal.ActiveCurrentEpoch {
|
||||
if 3*prevEpochTargetBalance >= 2*totalActiveBalance {
|
||||
blockRoot, err := helpers.BlockRoot(state, prevEpoch)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get block root for previous epoch %d", prevEpoch)
|
||||
@@ -92,7 +112,7 @@ func ProcessJustificationAndFinalizationPreCompute(state *stateTrie.BeaconState,
|
||||
}
|
||||
|
||||
// If 2/3 or more of the total balance attested in the current epoch.
|
||||
if 3*pBal.CurrentEpochTargetAttested >= 2*pBal.ActiveCurrentEpoch {
|
||||
if 3*currEpochTargetBalance >= 2*totalActiveBalance {
|
||||
blockRoot, err := helpers.BlockRoot(state, currentEpoch)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get block root for current epoch %d", prevEpoch)
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute"
|
||||
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateV0"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
|
||||
@@ -37,7 +37,7 @@ func TestProcessJustificationAndFinalizationPreCompute_ConsecutiveEpochs(t *test
|
||||
Balances: []uint64{a, a, a, a}, // validator total balance should be 128000000000
|
||||
BlockRoots: blockRoots,
|
||||
}
|
||||
state, err := beaconstate.InitializeFromProto(base)
|
||||
state, err := stateV0.InitializeFromProto(base)
|
||||
require.NoError(t, err)
|
||||
attestedBalance := 4 * uint64(e) * 3 / 2
|
||||
b := &precompute.Balance{PrevEpochTargetAttested: attestedBalance}
|
||||
@@ -74,7 +74,7 @@ func TestProcessJustificationAndFinalizationPreCompute_JustifyCurrentEpoch(t *te
|
||||
Balances: []uint64{a, a, a, a}, // validator total balance should be 128000000000
|
||||
BlockRoots: blockRoots,
|
||||
}
|
||||
state, err := beaconstate.InitializeFromProto(base)
|
||||
state, err := stateV0.InitializeFromProto(base)
|
||||
require.NoError(t, err)
|
||||
attestedBalance := 4 * uint64(e) * 3 / 2
|
||||
b := &precompute.Balance{PrevEpochTargetAttested: attestedBalance}
|
||||
@@ -110,7 +110,7 @@ func TestProcessJustificationAndFinalizationPreCompute_JustifyPrevEpoch(t *testi
|
||||
Balances: []uint64{a, a, a, a}, // validator total balance should be 128000000000
|
||||
BlockRoots: blockRoots, FinalizedCheckpoint: ðpb.Checkpoint{Root: make([]byte, 32)},
|
||||
}
|
||||
state, err := beaconstate.InitializeFromProto(base)
|
||||
state, err := stateV0.InitializeFromProto(base)
|
||||
require.NoError(t, err)
|
||||
attestedBalance := 4 * uint64(e) * 3 / 2
|
||||
b := &precompute.Balance{PrevEpochTargetAttested: attestedBalance}
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
@@ -16,16 +16,17 @@ import (
|
||||
// New gets called at the beginning of process epoch cycle to return
|
||||
// pre computed instances of validators attesting records and total
|
||||
// balances attested in an epoch.
|
||||
func New(ctx context.Context, state *stateTrie.BeaconState) ([]*Validator, *Balance, error) {
|
||||
func New(ctx context.Context, state iface.BeaconState) ([]*Validator, *Balance, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "precomputeEpoch.New")
|
||||
defer span.End()
|
||||
|
||||
pValidators := make([]*Validator, state.NumValidators())
|
||||
pBal := &Balance{}
|
||||
|
||||
currentEpoch := helpers.CurrentEpoch(state)
|
||||
prevEpoch := helpers.PrevEpoch(state)
|
||||
|
||||
if err := state.ReadFromEveryValidator(func(idx int, val stateTrie.ReadOnlyValidator) error {
|
||||
if err := state.ReadFromEveryValidator(func(idx int, val iface.ReadOnlyValidator) error {
|
||||
// Was validator withdrawable or slashed
|
||||
withdrawable := prevEpoch+1 >= val.WithdrawableEpoch()
|
||||
pVal := &Validator{
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute"
|
||||
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateV0"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
|
||||
func TestNew(t *testing.T) {
|
||||
ffe := params.BeaconConfig().FarFutureEpoch
|
||||
s, err := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
s, err := stateV0.InitializeFromProto(&pb.BeaconState{
|
||||
Slot: params.BeaconConfig().SlotsPerEpoch,
|
||||
// Validator 0 is slashed
|
||||
// Validator 1 is withdrawable
|
||||
|
||||
@@ -4,18 +4,23 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
|
||||
"github.com/prysmaticlabs/prysm/shared/mathutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
|
||||
type attesterRewardsFunc func(iface.ReadOnlyBeaconState, *Balance, []*Validator) ([]uint64, []uint64, error)
|
||||
type proposerRewardsFunc func(iface.ReadOnlyBeaconState, *Balance, []*Validator) ([]uint64, error)
|
||||
|
||||
// ProcessRewardsAndPenaltiesPrecompute processes the rewards and penalties of individual validator.
|
||||
// This is an optimized version by passing in precomputed validator attesting records and and total epoch balances.
|
||||
func ProcessRewardsAndPenaltiesPrecompute(
|
||||
state *stateTrie.BeaconState,
|
||||
state iface.BeaconState,
|
||||
pBal *Balance,
|
||||
vp []*Validator,
|
||||
) (*stateTrie.BeaconState, error) {
|
||||
attRewardsFunc attesterRewardsFunc,
|
||||
proRewardsFunc proposerRewardsFunc,
|
||||
) (iface.BeaconState, error) {
|
||||
// Can't process rewards and penalties in genesis epoch.
|
||||
if helpers.CurrentEpoch(state) == 0 {
|
||||
return state, nil
|
||||
@@ -27,13 +32,13 @@ func ProcessRewardsAndPenaltiesPrecompute(
|
||||
return state, errors.New("precomputed registries not the same length as state registries")
|
||||
}
|
||||
|
||||
attsRewards, attsPenalties, err := AttestationsDelta(state, pBal, vp)
|
||||
attsRewards, attsPenalties, err := attRewardsFunc(state, pBal, vp)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get attestation delta")
|
||||
return nil, errors.Wrap(err, "could not get attester attestation delta")
|
||||
}
|
||||
proposerRewards, err := ProposersDelta(state, pBal, vp)
|
||||
proposerRewards, err := proRewardsFunc(state, pBal, vp)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get attestation delta")
|
||||
return nil, errors.Wrap(err, "could not get proposer attestation delta")
|
||||
}
|
||||
validatorBals := state.Balances()
|
||||
for i := 0; i < numOfVals; i++ {
|
||||
@@ -56,7 +61,7 @@ func ProcessRewardsAndPenaltiesPrecompute(
|
||||
|
||||
// AttestationsDelta computes and returns the rewards and penalties differences for individual validators based on the
|
||||
// voting records.
|
||||
func AttestationsDelta(state *stateTrie.BeaconState, pBal *Balance, vp []*Validator) ([]uint64, []uint64, error) {
|
||||
func AttestationsDelta(state iface.ReadOnlyBeaconState, pBal *Balance, vp []*Validator) ([]uint64, []uint64, error) {
|
||||
numOfVals := state.NumValidators()
|
||||
rewards := make([]uint64, numOfVals)
|
||||
penalties := make([]uint64, numOfVals)
|
||||
@@ -70,8 +75,7 @@ func AttestationsDelta(state *stateTrie.BeaconState, pBal *Balance, vp []*Valida
|
||||
}
|
||||
|
||||
func attestationDelta(pBal *Balance, v *Validator, prevEpoch, finalizedEpoch types.Epoch) (uint64, uint64) {
|
||||
eligible := v.IsActivePrevEpoch || (v.IsSlashed && !v.IsWithdrawableCurrentEpoch)
|
||||
if !eligible || pBal.ActiveCurrentEpoch == 0 {
|
||||
if !EligibleForRewards(v) || pBal.ActiveCurrentEpoch == 0 {
|
||||
return 0, 0
|
||||
}
|
||||
|
||||
@@ -88,7 +92,7 @@ func attestationDelta(pBal *Balance, v *Validator, prevEpoch, finalizedEpoch typ
|
||||
maxAttesterReward := br - proposerReward
|
||||
r += maxAttesterReward / uint64(v.InclusionDistance)
|
||||
|
||||
if isInInactivityLeak(prevEpoch, finalizedEpoch) {
|
||||
if helpers.IsInInactivityLeak(prevEpoch, finalizedEpoch) {
|
||||
// Since full base reward will be canceled out by inactivity penalty deltas,
|
||||
// optimal participation receives full base reward compensation here.
|
||||
r += br
|
||||
@@ -103,7 +107,7 @@ func attestationDelta(pBal *Balance, v *Validator, prevEpoch, finalizedEpoch typ
|
||||
|
||||
// Process target reward / penalty
|
||||
if v.IsPrevEpochTargetAttester && !v.IsSlashed {
|
||||
if isInInactivityLeak(prevEpoch, finalizedEpoch) {
|
||||
if helpers.IsInInactivityLeak(prevEpoch, finalizedEpoch) {
|
||||
// Since full base reward will be canceled out by inactivity penalty deltas,
|
||||
// optimal participation receives full base reward compensation here.
|
||||
r += br
|
||||
@@ -117,7 +121,7 @@ func attestationDelta(pBal *Balance, v *Validator, prevEpoch, finalizedEpoch typ
|
||||
|
||||
// Process head reward / penalty
|
||||
if v.IsPrevEpochHeadAttester && !v.IsSlashed {
|
||||
if isInInactivityLeak(prevEpoch, finalizedEpoch) {
|
||||
if helpers.IsInInactivityLeak(prevEpoch, finalizedEpoch) {
|
||||
// Since full base reward will be canceled out by inactivity penalty deltas,
|
||||
// optimal participation receives full base reward compensation here.
|
||||
r += br
|
||||
@@ -130,9 +134,7 @@ func attestationDelta(pBal *Balance, v *Validator, prevEpoch, finalizedEpoch typ
|
||||
}
|
||||
|
||||
// Process finality delay penalty
|
||||
finalityDelay := finalityDelay(prevEpoch, finalizedEpoch)
|
||||
|
||||
if isInInactivityLeak(prevEpoch, finalizedEpoch) {
|
||||
if helpers.IsInInactivityLeak(prevEpoch, finalizedEpoch) {
|
||||
// If validator is performing optimally, this cancels all rewards for a neutral balance.
|
||||
proposerReward := br / params.BeaconConfig().ProposerRewardQuotient
|
||||
p += baseRewardsPerEpoch*br - proposerReward
|
||||
@@ -140,6 +142,7 @@ func attestationDelta(pBal *Balance, v *Validator, prevEpoch, finalizedEpoch typ
|
||||
// Equivalent to the following condition from the spec:
|
||||
// `index not in get_unslashed_attesting_indices(state, matching_target_attestations)`
|
||||
if !v.IsPrevEpochTargetAttester || v.IsSlashed {
|
||||
finalityDelay := helpers.FinalityDelay(prevEpoch, finalizedEpoch)
|
||||
p += vb * uint64(finalityDelay) / params.BeaconConfig().InactivityPenaltyQuotient
|
||||
}
|
||||
}
|
||||
@@ -148,7 +151,7 @@ func attestationDelta(pBal *Balance, v *Validator, prevEpoch, finalizedEpoch typ
|
||||
|
||||
// ProposersDelta computes and returns the rewards and penalties differences for individual validators based on the
|
||||
// proposer inclusion records.
|
||||
func ProposersDelta(state *stateTrie.BeaconState, pBal *Balance, vp []*Validator) ([]uint64, error) {
|
||||
func ProposersDelta(state iface.ReadOnlyBeaconState, pBal *Balance, vp []*Validator) ([]uint64, error) {
|
||||
numofVals := state.NumValidators()
|
||||
rewards := make([]uint64, numofVals)
|
||||
|
||||
@@ -163,7 +166,7 @@ func ProposersDelta(state *stateTrie.BeaconState, pBal *Balance, vp []*Validator
|
||||
baseRewardsPerEpoch := params.BeaconConfig().BaseRewardsPerEpoch
|
||||
proposerRewardQuotient := params.BeaconConfig().ProposerRewardQuotient
|
||||
for _, v := range vp {
|
||||
if v.ProposerIndex >= uint64(len(rewards)) {
|
||||
if uint64(v.ProposerIndex) >= uint64(len(rewards)) {
|
||||
// This should never happen with a valid state / validator.
|
||||
return nil, errors.New("proposer index out of range")
|
||||
}
|
||||
@@ -178,20 +181,10 @@ func ProposersDelta(state *stateTrie.BeaconState, pBal *Balance, vp []*Validator
|
||||
return rewards, nil
|
||||
}
|
||||
|
||||
// isInInactivityLeak returns true if the state is experiencing inactivity leak.
|
||||
// EligibleForRewards for validator.
|
||||
//
|
||||
// Spec code:
|
||||
// def is_in_inactivity_leak(state: BeaconState) -> bool:
|
||||
// return get_finality_delay(state) > MIN_EPOCHS_TO_INACTIVITY_PENALTY
|
||||
func isInInactivityLeak(prevEpoch, finalizedEpoch types.Epoch) bool {
|
||||
return finalityDelay(prevEpoch, finalizedEpoch) > params.BeaconConfig().MinEpochsToInactivityPenalty
|
||||
}
|
||||
|
||||
// finalityDelay returns the finality delay using the beacon state.
|
||||
//
|
||||
// Spec code:
|
||||
// def get_finality_delay(state: BeaconState) -> uint64:
|
||||
// return get_previous_epoch(state) - state.finalized_checkpoint.epoch
|
||||
func finalityDelay(prevEpoch, finalizedEpoch types.Epoch) types.Epoch {
|
||||
return prevEpoch - finalizedEpoch
|
||||
// if is_active_validator(v, previous_epoch) or (v.slashed and previous_epoch + 1 < v.withdrawable_epoch)
|
||||
func EligibleForRewards(v *Validator) bool {
|
||||
return v.IsActivePrevEpoch || (v.IsSlashed && !v.IsWithdrawableCurrentEpoch)
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateV0"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/mathutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
@@ -34,7 +34,7 @@ func TestProcessRewardsAndPenaltiesPrecompute(t *testing.T) {
|
||||
}
|
||||
base.PreviousEpochAttestations = atts
|
||||
|
||||
beaconState, err := state.InitializeFromProto(base)
|
||||
beaconState, err := stateV0.InitializeFromProto(base)
|
||||
require.NoError(t, err)
|
||||
|
||||
vp, bp, err := New(context.Background(), beaconState)
|
||||
@@ -42,8 +42,10 @@ func TestProcessRewardsAndPenaltiesPrecompute(t *testing.T) {
|
||||
vp, bp, err = ProcessAttestations(context.Background(), beaconState, vp, bp)
|
||||
require.NoError(t, err)
|
||||
|
||||
beaconState, err = ProcessRewardsAndPenaltiesPrecompute(beaconState, bp, vp)
|
||||
processedState, err := ProcessRewardsAndPenaltiesPrecompute(beaconState, bp, vp, AttestationsDelta, ProposersDelta)
|
||||
require.NoError(t, err)
|
||||
beaconState, ok := processedState.(*stateV0.BeaconState)
|
||||
require.Equal(t, true, ok)
|
||||
|
||||
// Indices that voted everything except for head, lost a bit money
|
||||
wanted := uint64(31999810265)
|
||||
@@ -76,9 +78,9 @@ func TestAttestationDeltaPrecompute(t *testing.T) {
|
||||
}
|
||||
}
|
||||
base.PreviousEpochAttestations = atts
|
||||
beaconState, err := state.InitializeFromProto(base)
|
||||
beaconState, err := stateV0.InitializeFromProto(base)
|
||||
require.NoError(t, err)
|
||||
slashedAttestedIndices := []uint64{1413}
|
||||
slashedAttestedIndices := []types.ValidatorIndex{1413}
|
||||
for _, i := range slashedAttestedIndices {
|
||||
vs := beaconState.Validators()
|
||||
vs[i].Slashed = true
|
||||
@@ -101,7 +103,7 @@ func TestAttestationDeltaPrecompute(t *testing.T) {
|
||||
totalBalance, err := helpers.TotalActiveBalance(beaconState)
|
||||
require.NoError(t, err)
|
||||
|
||||
attestedIndices := []uint64{55, 1339, 1746, 1811, 1569}
|
||||
attestedIndices := []types.ValidatorIndex{55, 1339, 1746, 1811, 1569}
|
||||
for _, i := range attestedIndices {
|
||||
base, err := epoch.BaseReward(beaconState, i)
|
||||
require.NoError(t, err, "Could not get base reward")
|
||||
@@ -126,7 +128,7 @@ func TestAttestationDeltaPrecompute(t *testing.T) {
|
||||
assert.Equal(t, 3*base, penalties[i], "Unexpected slashed indices penalty balance")
|
||||
}
|
||||
|
||||
nonAttestedIndices := []uint64{434, 677, 872, 791}
|
||||
nonAttestedIndices := []types.ValidatorIndex{434, 677, 872, 791}
|
||||
for _, i := range nonAttestedIndices {
|
||||
base, err := epoch.BaseReward(beaconState, i)
|
||||
assert.NoError(t, err, "Could not get base reward")
|
||||
@@ -160,7 +162,7 @@ func TestAttestationDeltas_ZeroEpoch(t *testing.T) {
|
||||
}
|
||||
}
|
||||
base.PreviousEpochAttestations = atts
|
||||
beaconState, err := state.InitializeFromProto(base)
|
||||
beaconState, err := stateV0.InitializeFromProto(base)
|
||||
require.NoError(t, err)
|
||||
|
||||
pVals, pBal, err := New(context.Background(), beaconState)
|
||||
@@ -198,7 +200,7 @@ func TestAttestationDeltas_ZeroInclusionDelay(t *testing.T) {
|
||||
}
|
||||
}
|
||||
base.PreviousEpochAttestations = atts
|
||||
beaconState, err := state.InitializeFromProto(base)
|
||||
beaconState, err := stateV0.InitializeFromProto(base)
|
||||
require.NoError(t, err)
|
||||
|
||||
pVals, pBal, err := New(context.Background(), beaconState)
|
||||
@@ -224,11 +226,11 @@ func TestProcessRewardsAndPenaltiesPrecompute_SlashedInactivePenalty(t *testing.
|
||||
}
|
||||
base.PreviousEpochAttestations = atts
|
||||
|
||||
beaconState, err := state.InitializeFromProto(base)
|
||||
beaconState, err := stateV0.InitializeFromProto(base)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch*10))
|
||||
|
||||
slashedAttestedIndices := []uint64{14, 37, 68, 77, 139}
|
||||
slashedAttestedIndices := []types.ValidatorIndex{14, 37, 68, 77, 139}
|
||||
for _, i := range slashedAttestedIndices {
|
||||
vs := beaconState.Validators()
|
||||
vs[i].Slashed = true
|
||||
@@ -298,10 +300,10 @@ func TestProposerDeltaPrecompute_HappyCase(t *testing.T) {
|
||||
e := params.BeaconConfig().SlotsPerEpoch
|
||||
validatorCount := uint64(10)
|
||||
base := buildState(e, validatorCount)
|
||||
beaconState, err := state.InitializeFromProto(base)
|
||||
beaconState, err := stateV0.InitializeFromProto(base)
|
||||
require.NoError(t, err)
|
||||
|
||||
proposerIndex := uint64(1)
|
||||
proposerIndex := types.ValidatorIndex(1)
|
||||
b := &Balance{ActiveCurrentEpoch: 1000}
|
||||
v := []*Validator{
|
||||
{IsPrevEpochAttester: true, CurrentEpochEffectiveBalance: 32, ProposerIndex: proposerIndex},
|
||||
@@ -320,10 +322,10 @@ func TestProposerDeltaPrecompute_ValidatorIndexOutOfRange(t *testing.T) {
|
||||
e := params.BeaconConfig().SlotsPerEpoch
|
||||
validatorCount := uint64(10)
|
||||
base := buildState(e, validatorCount)
|
||||
beaconState, err := state.InitializeFromProto(base)
|
||||
beaconState, err := stateV0.InitializeFromProto(base)
|
||||
require.NoError(t, err)
|
||||
|
||||
proposerIndex := validatorCount
|
||||
proposerIndex := types.ValidatorIndex(validatorCount)
|
||||
b := &Balance{ActiveCurrentEpoch: 1000}
|
||||
v := []*Validator{
|
||||
{IsPrevEpochAttester: true, CurrentEpochEffectiveBalance: 32, ProposerIndex: proposerIndex},
|
||||
@@ -336,10 +338,10 @@ func TestProposerDeltaPrecompute_SlashedCase(t *testing.T) {
|
||||
e := params.BeaconConfig().SlotsPerEpoch
|
||||
validatorCount := uint64(10)
|
||||
base := buildState(e, validatorCount)
|
||||
beaconState, err := state.InitializeFromProto(base)
|
||||
beaconState, err := stateV0.InitializeFromProto(base)
|
||||
require.NoError(t, err)
|
||||
|
||||
proposerIndex := uint64(1)
|
||||
proposerIndex := types.ValidatorIndex(1)
|
||||
b := &Balance{ActiveCurrentEpoch: 1000}
|
||||
v := []*Validator{
|
||||
{IsPrevEpochAttester: true, CurrentEpochEffectiveBalance: 32, ProposerIndex: proposerIndex, IsSlashed: true},
|
||||
@@ -348,55 +350,3 @@ func TestProposerDeltaPrecompute_SlashedCase(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, uint64(0), r[proposerIndex], "Unexpected proposer reward for slashed")
|
||||
}
|
||||
|
||||
func TestFinalityDelay(t *testing.T) {
|
||||
base := buildState(params.BeaconConfig().SlotsPerEpoch*10, 1)
|
||||
base.FinalizedCheckpoint = ðpb.Checkpoint{Epoch: 3}
|
||||
beaconState, err := state.InitializeFromProto(base)
|
||||
require.NoError(t, err)
|
||||
prevEpoch := types.Epoch(0)
|
||||
finalizedEpoch := types.Epoch(0)
|
||||
// Set values for each test case
|
||||
setVal := func() {
|
||||
prevEpoch = helpers.PrevEpoch(beaconState)
|
||||
finalizedEpoch = beaconState.FinalizedCheckpointEpoch()
|
||||
}
|
||||
setVal()
|
||||
d := finalityDelay(prevEpoch, finalizedEpoch)
|
||||
w := helpers.PrevEpoch(beaconState) - beaconState.FinalizedCheckpointEpoch()
|
||||
assert.Equal(t, w, d, "Did not get wanted finality delay")
|
||||
|
||||
require.NoError(t, beaconState.SetFinalizedCheckpoint(ðpb.Checkpoint{Epoch: 4}))
|
||||
setVal()
|
||||
d = finalityDelay(prevEpoch, finalizedEpoch)
|
||||
w = helpers.PrevEpoch(beaconState) - beaconState.FinalizedCheckpointEpoch()
|
||||
assert.Equal(t, w, d, "Did not get wanted finality delay")
|
||||
|
||||
require.NoError(t, beaconState.SetFinalizedCheckpoint(ðpb.Checkpoint{Epoch: 5}))
|
||||
setVal()
|
||||
d = finalityDelay(prevEpoch, finalizedEpoch)
|
||||
w = helpers.PrevEpoch(beaconState) - beaconState.FinalizedCheckpointEpoch()
|
||||
assert.Equal(t, w, d, "Did not get wanted finality delay")
|
||||
}
|
||||
|
||||
func TestIsInInactivityLeak(t *testing.T) {
|
||||
base := buildState(params.BeaconConfig().SlotsPerEpoch*10, 1)
|
||||
base.FinalizedCheckpoint = ðpb.Checkpoint{Epoch: 3}
|
||||
beaconState, err := state.InitializeFromProto(base)
|
||||
require.NoError(t, err)
|
||||
prevEpoch := types.Epoch(0)
|
||||
finalizedEpoch := types.Epoch(0)
|
||||
// Set values for each test case
|
||||
setVal := func() {
|
||||
prevEpoch = helpers.PrevEpoch(beaconState)
|
||||
finalizedEpoch = beaconState.FinalizedCheckpointEpoch()
|
||||
}
|
||||
setVal()
|
||||
assert.Equal(t, true, isInInactivityLeak(prevEpoch, finalizedEpoch), "Wanted inactivity leak true")
|
||||
require.NoError(t, beaconState.SetFinalizedCheckpoint(ðpb.Checkpoint{Epoch: 4}))
|
||||
setVal()
|
||||
assert.Equal(t, true, isInInactivityLeak(prevEpoch, finalizedEpoch), "Wanted inactivity leak true")
|
||||
require.NoError(t, beaconState.SetFinalizedCheckpoint(ðpb.Checkpoint{Epoch: 5}))
|
||||
setVal()
|
||||
assert.Equal(t, false, isInInactivityLeak(prevEpoch, finalizedEpoch), "Wanted inactivity leak false")
|
||||
}
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
package precompute
|
||||
|
||||
import (
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
|
||||
"github.com/prysmaticlabs/prysm/shared/mathutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
|
||||
// ProcessSlashingsPrecompute processes the slashed validators during epoch processing.
|
||||
// This is an optimized version by passing in precomputed total epoch balances.
|
||||
func ProcessSlashingsPrecompute(state *stateTrie.BeaconState, pBal *Balance) error {
|
||||
func ProcessSlashingsPrecompute(state iface.BeaconState, pBal *Balance) error {
|
||||
currentEpoch := helpers.CurrentEpoch(state)
|
||||
exitLength := params.BeaconConfig().EpochsPerSlashingsVector
|
||||
|
||||
@@ -26,7 +27,7 @@ func ProcessSlashingsPrecompute(state *stateTrie.BeaconState, pBal *Balance) err
|
||||
|
||||
var hasSlashing bool
|
||||
// Iterate through validator list in state, stop until a validator satisfies slashing condition of current epoch.
|
||||
err := state.ReadFromEveryValidator(func(idx int, val stateTrie.ReadOnlyValidator) error {
|
||||
err := state.ReadFromEveryValidator(func(idx int, val iface.ReadOnlyValidator) error {
|
||||
correctEpoch := epochToWithdraw == val.WithdrawableEpoch()
|
||||
if val.Slashed() && correctEpoch {
|
||||
hasSlashing = true
|
||||
@@ -47,7 +48,7 @@ func ProcessSlashingsPrecompute(state *stateTrie.BeaconState, pBal *Balance) err
|
||||
if val.Slashed && correctEpoch {
|
||||
penaltyNumerator := val.EffectiveBalance / increment * minSlashing
|
||||
penalty := penaltyNumerator / pBal.ActiveCurrentEpoch * increment
|
||||
if err := helpers.DecreaseBalance(state, uint64(idx), penalty); err != nil {
|
||||
if err := helpers.DecreaseBalance(state, types.ValidatorIndex(idx), penalty); err != nil {
|
||||
return false, val, err
|
||||
}
|
||||
return true, val, nil
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"github.com/gogo/protobuf/proto"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute"
|
||||
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateV0"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
)
|
||||
|
||||
func TestProcessSlashingsPrecompute_NotSlashedWithSlashedTrue(t *testing.T) {
|
||||
s, err := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
s, err := stateV0.InitializeFromProto(&pb.BeaconState{
|
||||
Slot: 0,
|
||||
Validators: []*ethpb.Validator{{Slashed: true}},
|
||||
Balances: []uint64{params.BeaconConfig().MaxEffectiveBalance},
|
||||
@@ -30,7 +30,7 @@ func TestProcessSlashingsPrecompute_NotSlashedWithSlashedTrue(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestProcessSlashingsPrecompute_NotSlashedWithSlashedFalse(t *testing.T) {
|
||||
s, err := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
s, err := stateV0.InitializeFromProto(&pb.BeaconState{
|
||||
Slot: 0,
|
||||
Validators: []*ethpb.Validator{{}},
|
||||
Balances: []uint64{params.BeaconConfig().MaxEffectiveBalance},
|
||||
@@ -124,7 +124,7 @@ func TestProcessSlashingsPrecompute_SlashedLess(t *testing.T) {
|
||||
pBal := &precompute.Balance{ActiveCurrentEpoch: ab}
|
||||
|
||||
original := proto.Clone(tt.state)
|
||||
state, err := beaconstate.InitializeFromProto(tt.state)
|
||||
state, err := stateV0.InitializeFromProto(tt.state)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, precompute.ProcessSlashingsPrecompute(state, pBal))
|
||||
assert.Equal(t, tt.want, state.Balances()[0], "ProcessSlashings({%v}) = newState; newState.Balances[0] = %d; wanted %d", original, state.Balances()[0])
|
||||
|
||||
@@ -29,7 +29,7 @@ go_test(
|
||||
"//beacon-chain/core/epoch:go_default_library",
|
||||
"//beacon-chain/core/epoch/precompute:go_default_library",
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//beacon-chain/state/stateV0:go_default_library",
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"//shared/params/spectest:go_default_library",
|
||||
@@ -62,7 +62,7 @@ go_test(
|
||||
"//beacon-chain/core/epoch:go_default_library",
|
||||
"//beacon-chain/core/epoch/precompute:go_default_library",
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//beacon-chain/state/stateV0:go_default_library",
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"//shared/params/spectest: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