mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-10 05:47:59 -05:00
Compare commits
218 Commits
v0.3.2
...
v1.0.0-alp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
475d428fce | ||
|
|
2f15f16650 | ||
|
|
46b19072f4 | ||
|
|
50d67f52bb | ||
|
|
62c25eaedb | ||
|
|
28733f2c9e | ||
|
|
0803f0f0ff | ||
|
|
52b46d4570 | ||
|
|
8a3ea1e936 | ||
|
|
17c1fc3250 | ||
|
|
3763a8ce5d | ||
|
|
075d29f5b4 | ||
|
|
c70103bdb3 | ||
|
|
0ecd2a6dc2 | ||
|
|
4fbcedf541 | ||
|
|
5a1a768135 | ||
|
|
21f51993c5 | ||
|
|
5eb6485e14 | ||
|
|
ea84f44307 | ||
|
|
144f37e994 | ||
|
|
046a00aa87 | ||
|
|
497fa6ed50 | ||
|
|
899670e1e9 | ||
|
|
ef21456c8a | ||
|
|
92131695b1 | ||
|
|
24fc67a6dd | ||
|
|
dc5ed7a80e | ||
|
|
cb045dd0e3 | ||
|
|
748d513c62 | ||
|
|
3b9a03d517 | ||
|
|
d5ddd012bc | ||
|
|
a85bf9305d | ||
|
|
c76034147e | ||
|
|
d8c57541e4 | ||
|
|
28a9adc49b | ||
|
|
e59721f264 | ||
|
|
40f7b258eb | ||
|
|
8c9ae8e3bf | ||
|
|
29f43190fc | ||
|
|
b69c76c879 | ||
|
|
ca0912e5d8 | ||
|
|
2e570d7427 | ||
|
|
973a0a89b5 | ||
|
|
1d8b207d7c | ||
|
|
7a5010ecea | ||
|
|
7b8bad35e7 | ||
|
|
fa435d39bb | ||
|
|
159ef3d702 | ||
|
|
06db5f6471 | ||
|
|
a7bee79988 | ||
|
|
0fff07a93b | ||
|
|
70e64be8d6 | ||
|
|
33ffa34ea7 | ||
|
|
bcebf63cab | ||
|
|
d6f7d67ee9 | ||
|
|
b7afc90266 | ||
|
|
4b64a75c77 | ||
|
|
fcf131412f | ||
|
|
279dd5ac8d | ||
|
|
c7a4fcd098 | ||
|
|
07753189fd | ||
|
|
e162d27634 | ||
|
|
f440c815f9 | ||
|
|
9aac572c21 | ||
|
|
7bdd1355b8 | ||
|
|
477b014bd1 | ||
|
|
ec7f7aebdc | ||
|
|
3544ed2818 | ||
|
|
b43e43b4a9 | ||
|
|
c26a492225 | ||
|
|
0df12261a1 | ||
|
|
f385a1dea6 | ||
|
|
8376fb36ca | ||
|
|
02b238bda2 | ||
|
|
3dd5576e33 | ||
|
|
df9a534826 | ||
|
|
7e50c36725 | ||
|
|
e22365c4a8 | ||
|
|
c8f8e3f1e0 | ||
|
|
3e81afd7ab | ||
|
|
404a0f6bda | ||
|
|
00ef08b3dc | ||
|
|
6edb3018f9 | ||
|
|
17516b625e | ||
|
|
7f7866ff2a | ||
|
|
c5f186d56f | ||
|
|
0982ff124e | ||
|
|
63df1d0b8d | ||
|
|
cb9ac6282f | ||
|
|
c67b01e5d3 | ||
|
|
b40e6db1e5 | ||
|
|
f89d753275 | ||
|
|
a24546152b | ||
|
|
6bc70e228f | ||
|
|
f2a3fadda7 | ||
|
|
6a4b17f237 | ||
|
|
7ebb3c1784 | ||
|
|
33f6c22607 | ||
|
|
1a0a399bed | ||
|
|
c4c9a8465a | ||
|
|
5e2faf1a9d | ||
|
|
93e68db5e6 | ||
|
|
cdac3d61ea | ||
|
|
4118fa5242 | ||
|
|
2df76798bc | ||
|
|
3792bf67b6 | ||
|
|
e077d3ddc9 | ||
|
|
2ad5cec56c | ||
|
|
6b1e60c404 | ||
|
|
48e984f526 | ||
|
|
fbee94a0e9 | ||
|
|
9740245ca5 | ||
|
|
48d4a8655a | ||
|
|
e15d92df06 | ||
|
|
729bd83734 | ||
|
|
c63fb2cd44 | ||
|
|
78a865eb0b | ||
|
|
6e516dabf9 | ||
|
|
454e02ac4f | ||
|
|
35d74981a0 | ||
|
|
d8bcd891c4 | ||
|
|
2e0158d7c5 | ||
|
|
bdb80f4639 | ||
|
|
0043fb0441 | ||
|
|
f520472fc6 | ||
|
|
5241582ece | ||
|
|
b0128ad894 | ||
|
|
5d1c3da85c | ||
|
|
301c2a1448 | ||
|
|
bc3d673ea4 | ||
|
|
3d092d3eed | ||
|
|
4df5c042d9 | ||
|
|
d06b0e8a86 | ||
|
|
4f8d9c59dd | ||
|
|
021d777b5e | ||
|
|
dc3fb018fe | ||
|
|
2ab4b86f9b | ||
|
|
b30a089548 | ||
|
|
271938202e | ||
|
|
6fe814c5aa | ||
|
|
a9f4d1d02d | ||
|
|
7c110e54f0 | ||
|
|
3043d4722f | ||
|
|
c96c8b4aa3 | ||
|
|
9f46000dba | ||
|
|
5450b3155e | ||
|
|
1bb12c3568 | ||
|
|
1be8b3aa5e | ||
|
|
431762164e | ||
|
|
3ec2a0f9e0 | ||
|
|
e96b45b29c | ||
|
|
e529f5b1d6 | ||
|
|
f18bada8c9 | ||
|
|
5657535c52 | ||
|
|
9da9fbdfba | ||
|
|
de2ec8e575 | ||
|
|
3660732f44 | ||
|
|
8e6c16d416 | ||
|
|
8143cc36bc | ||
|
|
eeffa4fb30 | ||
|
|
1137403e4b | ||
|
|
f17818b1c0 | ||
|
|
691f0bba70 | ||
|
|
b024191887 | ||
|
|
1f87cb11fc | ||
|
|
a0b142a26c | ||
|
|
035eaffd9d | ||
|
|
c41244ad34 | ||
|
|
c20d9ccbb3 | ||
|
|
3380d14475 | ||
|
|
4f031d1988 | ||
|
|
02afb53ea4 | ||
|
|
0974c02a00 | ||
|
|
c6acf0a28c | ||
|
|
ed7ad4525e | ||
|
|
7fcc07fb45 | ||
|
|
f937713fe9 | ||
|
|
359e0abe1d | ||
|
|
0704ba685a | ||
|
|
0f95b797af | ||
|
|
43722e45f4 | ||
|
|
ff4ed413a3 | ||
|
|
f1a42eb589 | ||
|
|
a90ffaba49 | ||
|
|
663d919b6f | ||
|
|
7b30845c01 | ||
|
|
46eb228379 | ||
|
|
8d3fc1ad3e | ||
|
|
93195b762b | ||
|
|
f0abf0d7d5 | ||
|
|
9d27449212 | ||
|
|
edb6590764 | ||
|
|
e77cf724b8 | ||
|
|
b633dfe880 | ||
|
|
8334aac111 | ||
|
|
4c1e2ba196 | ||
|
|
25c13663d2 | ||
|
|
0c3af32274 | ||
|
|
01cb01a8f2 | ||
|
|
0c9e99e04a | ||
|
|
d4cd51f23e | ||
|
|
962fe8552d | ||
|
|
eddaea869b | ||
|
|
300d072456 | ||
|
|
ac1c92e241 | ||
|
|
2452c7403b | ||
|
|
b97e22107c | ||
|
|
98faf95943 | ||
|
|
af28862e94 | ||
|
|
b133eb6c4a | ||
|
|
345ec1bf8c | ||
|
|
d1fea430d6 | ||
|
|
054b15bc45 | ||
|
|
6a2955d43c | ||
|
|
0ecd83afbb | ||
|
|
069f2c5fb6 | ||
|
|
acb15a1f04 | ||
|
|
e2af70f692 |
16
.bazelrc
16
.bazelrc
@@ -15,7 +15,7 @@ run --host_force_python=PY2
|
||||
# Network sandboxing only works on linux.
|
||||
--experimental_sandbox_default_allow_network=false
|
||||
|
||||
# Use minimal protobufs at runtime
|
||||
# Use mainnet protobufs at runtime
|
||||
run --define ssz=mainnet
|
||||
test --define ssz=mainnet
|
||||
build --define ssz=mainnet
|
||||
@@ -30,6 +30,20 @@ build --define kafka_enabled=false
|
||||
test --define kafka_enabled=false
|
||||
run --define kafka_enabled=false
|
||||
|
||||
# Release flags
|
||||
build:release --workspace_status_command=./scripts/workspace_status.sh
|
||||
build:release --stamp
|
||||
build:release --compilation_mode=opt
|
||||
|
||||
# LLVM compiler for building C/C++ dependencies.
|
||||
build:llvm --crosstool_top=@llvm_toolchain//:toolchain
|
||||
build:llvm --define compiler=llvm
|
||||
|
||||
# Build binary with cgo symbolizer for debugging / profiling.
|
||||
build:cgo_symbolizer --config=llvm
|
||||
build:cgo_symbolizer --copt=-g
|
||||
build:cgo_symbolizer --define=USE_CGO_SYMBOLIZER=true
|
||||
build:cgo_symbolizer -c dbg
|
||||
|
||||
# multi-arch cross-compiling toolchain configs:
|
||||
-----------------------------------------------
|
||||
|
||||
@@ -1 +1 @@
|
||||
2.1.1
|
||||
3.0.0
|
||||
|
||||
@@ -20,15 +20,16 @@ build:remote-cache --strategy=Genrule=standalone
|
||||
build:remote-cache --disk_cache=
|
||||
build:remote-cache --host_platform_remote_properties_override='properties:{name:\"cache-silo-key\" value:\"prysm\"}'
|
||||
build:remote-cache --remote_instance_name=projects/prysmaticlabs/instances/default_instance
|
||||
|
||||
build:remote-cache --experimental_remote_download_outputs=minimal
|
||||
build:remote-cache --experimental_inmemory_jdeps_files
|
||||
build:remote-cache --experimental_inmemory_dotd_files
|
||||
build:remote-cache --remote_download_minimal
|
||||
|
||||
# Import workspace options.
|
||||
import %workspace%/.bazelrc
|
||||
|
||||
startup --host_jvm_args=-Xmx1000m --host_jvm_args=-Xms1000m
|
||||
query --repository_cache=/tmp/repositorycache
|
||||
query --experimental_repository_cache_hardlinks
|
||||
build --repository_cache=/tmp/repositorycache
|
||||
build --experimental_repository_cache_hardlinks
|
||||
build --experimental_strict_action_env
|
||||
build --disk_cache=/tmp/bazelbuilds
|
||||
build --experimental_multi_threaded_digest
|
||||
@@ -36,17 +37,15 @@ build --sandbox_tmpfs_path=/tmp
|
||||
build --verbose_failures
|
||||
build --announce_rc
|
||||
build --show_progress_rate_limit=5
|
||||
build --curses=yes --color=yes
|
||||
build --curses=yes --color=no
|
||||
build --keep_going
|
||||
build --test_output=errors
|
||||
build --flaky_test_attempts=5
|
||||
build --jobs=50
|
||||
build --stamp
|
||||
test --local_test_jobs=2
|
||||
# Disabled race detection due to unstable test results under constrained environment build kite
|
||||
# build --features=race
|
||||
|
||||
# Enable kafka for CI and docker images
|
||||
build --define kafka_enabled=true
|
||||
# Enable kafka for CI tests only.
|
||||
test --define kafka_enabled=true
|
||||
run --define kafka_enabled=true
|
||||
|
||||
build --bes_backend=grpcs://builds.prylabs.net:1985
|
||||
build --bes_results_url=https://builds.prylabs.net/invocation/
|
||||
|
||||
5
.github/CODEOWNERS
vendored
Normal file
5
.github/CODEOWNERS
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
# Automatically require code review from core-team.
|
||||
* @prysmaticlabs/core-team
|
||||
|
||||
# Starlark code owners
|
||||
*.bzl @prestonvanloon
|
||||
13
.github/no-response.yml
vendored
Normal file
13
.github/no-response.yml
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
# Configuration for probot-no-response - https://github.com/probot/no-response
|
||||
|
||||
# Number of days of inactivity before an Issue is closed for lack of response
|
||||
daysUntilClose: 14
|
||||
# Label requiring a response
|
||||
responseRequiredLabel: Need-Info
|
||||
# Comment to post when closing an Issue for lack of response. Set to `false` to disable
|
||||
closeComment: >
|
||||
This issue has been automatically closed because there has been no response
|
||||
to our request for more information from the original author. With only the
|
||||
information that is currently in the issue, we don't have enough information
|
||||
to take action. Please reach out if you have or find the answers we need so
|
||||
that we can investigate further.
|
||||
41
.github/workflows/dappnode-release-trigger.yml
vendored
Normal file
41
.github/workflows/dappnode-release-trigger.yml
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
name: Update DAppNodePackages
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*'
|
||||
|
||||
jobs:
|
||||
dappnode-update-beacon-chain:
|
||||
name: Trigger a beacon-chain release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Get latest tag
|
||||
id: get_tag
|
||||
run: echo ::set-output name=TAG::${GITHUB_REF/refs\/tags\//}
|
||||
- name: Send dispatch event to DAppNodePackage-prysm-beacon-chain
|
||||
env:
|
||||
DISPATCH_REPO: dappnode/DAppNodePackage-prysm-beacon-chain
|
||||
run: |
|
||||
curl -v -X POST -u "${{ secrets.PAT_GITHUB }}" \
|
||||
-H "Accept: application/vnd.github.everest-preview+json" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data '{"event_type":"new_release", "client_payload": { "tag":"${{ steps.get_tag.outputs.TAG }}"}}' \
|
||||
https://api.github.com/repos/$DISPATCH_REPO/dispatches
|
||||
|
||||
dappnode-update-validator:
|
||||
name: Trigger a validator release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Get latest tag
|
||||
id: get_tag
|
||||
run: echo ::set-output name=TAG::${GITHUB_REF/refs\/tags\//}
|
||||
- name: Send dispatch event to DAppNodePackage validator repository
|
||||
env:
|
||||
DISPATCH_REPO: dappnode/DAppNodePackage-prysm-validator
|
||||
run: |
|
||||
curl -v -X POST -u "${{ secrets.PAT_GITHUB }}" \
|
||||
-H "Accept: application/vnd.github.everest-preview+json" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data '{"event_type":"new_release", "client_payload": { "tag":"${{ steps.get_tag.outputs.TAG }}"}}' \
|
||||
https://api.github.com/repos/$DISPATCH_REPO/dispatches
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -17,6 +17,7 @@ bazel-*
|
||||
# Coverage outputs
|
||||
coverage.txt
|
||||
profile.out
|
||||
profile.grind
|
||||
|
||||
# Nodejs
|
||||
node_modules
|
||||
@@ -29,3 +30,6 @@ password.txt
|
||||
# go dependancy
|
||||
/go.mod
|
||||
/go.sum
|
||||
|
||||
# Dist files
|
||||
dist
|
||||
|
||||
@@ -4,23 +4,23 @@ Hash: SHA512
|
||||
Contact: mailto:security@prysmaticlabs.com
|
||||
Encryption: openpgp4fpr:0AE0051D647BA3C1A917AF4072E33E4DF1A5036E
|
||||
Encryption: openpgp4fpr:341396BAFACC28C5082327F889725027FC8EC0D4
|
||||
Encryption: openpgp4fpr:8B7814F1B221A8E8AA465FC7BDBF744ADE1A0033
|
||||
Encryption: openpgp4fpr:FEE44615A19049DF0CA0C2735E2B7E5734DFADCB
|
||||
Preferred-Languages: en
|
||||
Canonical: https://github.com/prysmaticlabs/prysm/tree/master/.well-known/security.txt
|
||||
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQIzBAEBCgAdFiEECuAFHWR7o8GpF69AcuM+TfGlA24FAlzi0WgACgkQcuM+TfGl
|
||||
A241pw/+Ks3Hxx8eGbjRIeuncuK811FkCiofNJS+MY2p4W2/tIrk48DtLRx8/k5L
|
||||
Dh1QyypZsqUgofrK7PbGVdEin6oEb2jYbTWUarAVTbhlsUdM4YcxwpgmGVslW7+C
|
||||
Hm8wMasQZhCkFfakzhfKX5hIQoFaFI/OvtVKIQsodP8dAieCDaGmtfq1Bs1LgFqi
|
||||
KrpeEdC2XbBQs33ADheC5SdGT1mnatP3VX8cOhLsfoPksYgTSpwK0clkoWs1eZOQ
|
||||
l1ImfW/FJCpSndBWgBR503ZgaU3Ic+5qxmAIuUP4chl0DFRMlPFEM5OWC6JkkCOd
|
||||
5kKrXGRmrhgtQg+pA3zqJnFItRj7gxPBA/ypxCkKPrLEkRvbdpdZEl5vAlYkeBL6
|
||||
iKSLHnMswGKldiYxy7ofam5bM3myhYYNFb25boV5pRptrnoUmWOACHioBGQHwWNt
|
||||
B0XktD0j7+pCCiJyyYxmOnElsk/Y/u4Tv5pYWvfFuxTF2XOg+P/EH64AIFLWgB1U
|
||||
VnITxhakxqejCBxZkuVCFNSzt+TXG0NS9EIj/UOYBY+wxrBZ62ITjdA16RS/3n3z
|
||||
DuIDtxOOwUumbOO32+a5zIb+ARmnocYJviI7FuENb01/U6qb+nm9hQI6oIpSCNsv
|
||||
Pb4O/ZlOx70U/7mt4Xn/dTKH9bnKOOVhOw00KJWFfAce73AVnLA=
|
||||
=Uhqg
|
||||
iQIzBAEBCgAdFiEECuAFHWR7o8GpF69AcuM+TfGlA24FAl6HrcwACgkQcuM+TfGl
|
||||
A26voQ/8DFB5wUHP0uyY8k7FGbxhLzSeImxomnUHJaUGfdczbCdYPMEHc9zI1iZP
|
||||
6LRiy9wS6qhqj/GSKVwvDPr+ZymXuV3L22GOP2lRhl7Z9Mm21ZJNOcoQBFOZnyHu
|
||||
DAy9HeTmeuJxYkf8weqZYXyzEoKJBDmfuWmEFjrtMcFXUfT3aJn1E2A/AQdcVQIC
|
||||
9L+iGWwFwjsPhcfaMuwcB7QMheDO6KSB7XPPCbrZ036Np8UTZ4qbZ5y73tlfkcOc
|
||||
tYTrMSPtS4eNutiDOP5Np36cLzRtNpm/BziAK+7ZKiYY0HI5h9IkCTLO4x2UmAMX
|
||||
sPoeaAB5z2QLIwmU9J2NhJrwiNMGTpJ+0bowy8U4cgzAX20CXVjRqGhy+cir8Ewg
|
||||
DjEGjWINUw6W0yzJp0mKSKzuOhdTTmzIYBeMBsyce+pgN1KGFCxeIwxGxyJzADdw
|
||||
mYQdljRXn4yEYP/KEpu/F2o8L4ptRO2jZWKvTvdzSSGGSyKyF4HsIRJ7m98DaB6S
|
||||
0oGq1KpbKKTbQi5g8UShGV2gPeMCs5ZIIqK2b/cRzUet18aUuofLmR4lkKZa9yEG
|
||||
rbzuJq/gB2vgQwExUEgVQ3/DfVc+y80e3YZ5s+rzV0vbLxl4Gh4yExpLo7hRf9iY
|
||||
EFvMzH+BEEb5VfCwByZyV1BmesZVIosr7K6UmVtPe0bZGvv3uIg=
|
||||
=5qpD
|
||||
-----END PGP SIGNATURE-----
|
||||
|
||||
30
BUILD.bazel
30
BUILD.bazel
@@ -4,7 +4,6 @@ load("@com_github_atlassian_bazel_tools//goimports:def.bzl", "goimports")
|
||||
load("@io_kubernetes_build//defs:run_in_workspace.bzl", "workspace_binary")
|
||||
load("@io_bazel_rules_go//go:def.bzl", "nogo")
|
||||
load("@graknlabs_bazel_distribution//common:rules.bzl", "assemble_targz", "assemble_versioned")
|
||||
load("//tools:binary_targets.bzl", "binary_targets", "determine_targets")
|
||||
|
||||
prefix = "github.com/prysmaticlabs/prysm"
|
||||
|
||||
@@ -104,40 +103,17 @@ nogo(
|
||||
"@org_golang_x_tools//go/analysis/passes/assign:go_tool_library",
|
||||
"@org_golang_x_tools//go/analysis/passes/inspect:go_tool_library",
|
||||
"@org_golang_x_tools//go/analysis/passes/asmdecl:go_tool_library",
|
||||
"//tools/analyzers/maligned:go_tool_library",
|
||||
"//tools/analyzers/roughtime:go_tool_library",
|
||||
"//tools/analyzers/errcheck:go_tool_library",
|
||||
],
|
||||
)
|
||||
|
||||
assemble_versioned(
|
||||
name = "assemble-versioned-all",
|
||||
tags = ["manual"],
|
||||
targets = [
|
||||
":assemble-{}-{}-targz".format(
|
||||
pair[0],
|
||||
pair[1],
|
||||
)
|
||||
for pair in binary_targets
|
||||
],
|
||||
version_file = "//:VERSION",
|
||||
)
|
||||
|
||||
common_files = {
|
||||
"//:LICENSE.md": "LICENSE.md",
|
||||
"//:README.md": "README.md",
|
||||
}
|
||||
|
||||
[assemble_targz(
|
||||
name = "assemble-{}-{}-targz".format(
|
||||
pair[0],
|
||||
pair[1],
|
||||
),
|
||||
additional_files = determine_targets(pair, common_files),
|
||||
output_filename = "prysm-{}-{}".format(
|
||||
pair[0],
|
||||
pair[1],
|
||||
),
|
||||
tags = ["manual"],
|
||||
) for pair in binary_targets]
|
||||
|
||||
toolchain(
|
||||
name = "built_cmake_toolchain",
|
||||
toolchain = "@rules_foreign_cc//tools/build_defs/native_tools:built_cmake",
|
||||
|
||||
223
README.md
223
README.md
@@ -1,232 +1,17 @@
|
||||
# Prysm: An Ethereum 2.0 Client Written in Go
|
||||
|
||||
[](https://buildkite.com/prysmatic-labs/prysm)
|
||||
[](https://github.com/ethereum/eth2.0-specs/tree/v0.9.3)
|
||||
[](https://github.com/ethereum/eth2.0-specs/tree/v0.11.1)
|
||||
[](https://discord.gg/KSA7rPr)
|
||||
[](https://gitter.im/prysmaticlabs/geth-sharding?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||
|
||||
This is the core repository for Prysm, a [Golang](https://golang.org/) implementation of the Ethereum 2.0 client specifications developed by [Prysmatic Labs](https://prysmaticlabs.com).
|
||||
|
||||
### Need assistance?
|
||||
A more detailed set of installation and usage instructions as well as breakdowns of each individual component are available in the [official documentation portal](https://docs.prylabs.network). If you still have questions, feel free to stop by either our [Discord](https://discord.gg/KSA7rPr) or [Gitter](https://gitter.im/prysmaticlabs/geth-sharding?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) and a member of the team or our community will be happy to assist you.
|
||||
### Getting Started
|
||||
A detailed set of installation and usage instructions as well as breakdowns of each individual component are available in the [official documentation portal](https://docs.prylabs.network). If you still have questions, feel free to stop by either our [Discord](https://discord.gg/KSA7rPr) or [Gitter](https://gitter.im/prysmaticlabs/geth-sharding?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) and a member of the team or our community will be happy to assist you.
|
||||
|
||||
### Come join the testnet!
|
||||
Participation is now open to the public for our Ethereum 2.0 phase 0 testnet release. Visit [prylabs.net](https://prylabs.net) for more information on the project or to sign up as a validator on the network.
|
||||
|
||||
# Table of Contents
|
||||
|
||||
- [Dependencies](#dependencies)
|
||||
- [Installation](#installing-prysm)
|
||||
- [Build via Docker](#build-via-docker)
|
||||
- [Build via Bazel](#build-via-bazel)
|
||||
- [Connecting to the public testnet: running a beacon node](#connecting-to-the-testnet-running-a-beacon-node)
|
||||
- [Running via Docker](#running-via-docker)
|
||||
- [Running via Bazel](#running-via-bazel)
|
||||
- [Staking ETH: running a validator client](#staking-eth-running-a-validator-client)
|
||||
- [Activating your validator: depositing 3.2 Goerli ETH](#activating-your-validator-depositing-32-gerli-eth)
|
||||
- [Starting the validator with Bazel](#starting-the-validator-with-bazel)
|
||||
- [Setting up a local ETH2 development chain](#setting-up-a-local-eth2-development-chain)
|
||||
- [Installation and dependencies](#installation-and-dependencies)
|
||||
- [Running a local beacon node and validator client](#running-a-local-beacon-node-and-validator-client)
|
||||
- [Testing Prysm](#testing-prysm)
|
||||
- [Contributing](#contributing)
|
||||
- [License](#license)
|
||||
|
||||
## Dependencies
|
||||
|
||||
Prysm can be installed either with Docker **\(recommended\)** or using our build tool, Bazel. The below instructions include sections for performing both.
|
||||
|
||||
#### **For Docker installations:**
|
||||
|
||||
* The latest release of [Docker](https://docs.docker.com/install/)
|
||||
|
||||
#### **For Bazel installations:**
|
||||
|
||||
* The latest release of [Bazel](https://docs.bazel.build/versions/master/install.html)
|
||||
* The latest release of `cmake`
|
||||
* The latest release of `git`
|
||||
* A modern UNIX operating system \(macOS included\)
|
||||
|
||||
## Installing Prysm
|
||||
|
||||
### Build via Docker
|
||||
|
||||
1. Ensure you are running the most recent version of Docker by issuing the command:
|
||||
|
||||
```text
|
||||
docker -v
|
||||
```
|
||||
|
||||
2. To pull the Prysm images, issue the following commands:
|
||||
|
||||
```text
|
||||
docker pull gcr.io/prysmaticlabs/prysm/validator:latest
|
||||
docker pull gcr.io/prysmaticlabs/prysm/beacon-chain:latest
|
||||
```
|
||||
|
||||
This process will also install any related dependencies.
|
||||
|
||||
### Build via Bazel
|
||||
|
||||
1. Open a terminal window. Ensure you are running the most recent version of Bazel by issuing the command:
|
||||
|
||||
```text
|
||||
bazel version
|
||||
```
|
||||
|
||||
2. Clone Prysm's [main repository](https://github.com/prysmaticlabs/prysm) and enter the directory:
|
||||
|
||||
```text
|
||||
git clone https://github.com/prysmaticlabs/prysm
|
||||
cd prysm
|
||||
```
|
||||
|
||||
3. Build both the beacon chain node and the validator client:
|
||||
|
||||
```text
|
||||
bazel build //beacon-chain:beacon-chain
|
||||
bazel build //validator:validator
|
||||
```
|
||||
|
||||
Bazel will automatically pull and install any dependencies as well, including Go and necessary compilers.
|
||||
|
||||
## Connecting to the testnet: running a beacon node
|
||||
|
||||
Below are instructions for initialising a beacon node and connecting to the public testnet. To further understand the role that the beacon node plays in Prysm, see [this section of the documentation.](https://docs.prylabs.network/docs/how-prysm-works/architecture-overview/)
|
||||
|
||||
|
||||
**NOTE:** It is recommended to open up port 13000 on your local router to improve connectivity and receive more peers from the network. To do so, navigate to `192.168.0.1` in your browser and login if required. Follow along with the interface to modify your routers firewall settings. When this task is completed, append the parameter`--p2p-host-ip=$(curl -s ident.me)` to your selected beacon startup command presented in this section to use the newly opened port.
|
||||
|
||||
### Running via Docker
|
||||
|
||||
#### **Docker on Linux/macOS:**
|
||||
|
||||
To start your beacon node, issue the following command:
|
||||
|
||||
```text
|
||||
docker run -it -v $HOME/prysm:/data -p 4000:4000 -p 13000:13000 --name beacon-node \
|
||||
gcr.io/prysmaticlabs/prysm/beacon-chain:latest \
|
||||
--datadir=/data
|
||||
```
|
||||
|
||||
The beacon node can be halted by either using `Ctrl+c` or with the command:
|
||||
|
||||
```text
|
||||
docker stop beacon-node
|
||||
```
|
||||
|
||||
To restart the beacon node, issue the following command:
|
||||
|
||||
```text
|
||||
docker start -ai beacon-node
|
||||
```
|
||||
|
||||
To delete a corrupted container, issue the following command:
|
||||
|
||||
```text
|
||||
docker rm beacon-node
|
||||
```
|
||||
|
||||
To recreate a deleted container and refresh the chain database, issue the start command with an additional `--clear-db` parameter:
|
||||
|
||||
```text
|
||||
docker run -it -v $HOME/prysm:/data -p 4000:4000 -p 13000:13000 --name beacon-node \
|
||||
gcr.io/prysmaticlabs/prysm/beacon-chain:latest \
|
||||
--datadir=/data \
|
||||
--clear-db
|
||||
```
|
||||
|
||||
#### **Docker on Windows:**
|
||||
|
||||
1. You will need to 'share' the local drive you wish to mount to \(e.g. C:\).
|
||||
1. Enter Docker settings \(right click the tray icon\)
|
||||
2. Click 'Shared Drives'
|
||||
3. Select a drive to share
|
||||
4. Click 'Apply'
|
||||
|
||||
2. You will next need to create a directory named `/prysm/` within your selected shared Drive. This folder will be used as a local data directory for Beacon Node chain data as well as account and keystore information required by the validator. Docker will **not** create this directory if it does not exist already. For the purposes of these instructions, it is assumed that `C:` is your prior-selected shared Drive.
|
||||
3. To run the beacon node, issue the following command:
|
||||
|
||||
```text
|
||||
docker run -it -v c:/prysm/:/data -p 4000:4000 -p 13000:13000 --name beacon-node gcr.io/prysmaticlabs/prysm/beacon-chain:latest --datadir=/data --clear-db
|
||||
```
|
||||
|
||||
### Running via Bazel
|
||||
|
||||
To start your Beacon Node with Bazel, issue the following command:
|
||||
|
||||
```text
|
||||
bazel run //beacon-chain -- --clear-db --datadir=$HOME/prysm
|
||||
```
|
||||
|
||||
This will sync up the beacon node with the latest head block in the network.
|
||||
|
||||
|
||||
**NOTE:** The beacon node must be **completely synced** before attempting to initialise a validator client, otherwise the validator will not be able to complete the deposit and **funds will lost**.
|
||||
|
||||
|
||||
## Staking ETH: Running a validator client
|
||||
|
||||
Once your beacon node is up, the chain will be waiting for you to deposit 3.2 Goerli ETH into a [validator deposit contract](https://docs.prylabs.network/docs/how-prysm-works/validator-deposit-contract) in order to activate your validator \(discussed in the section below\). First though, you will need to create this validator and connect to this node to participate in consensus.
|
||||
|
||||
Each validator represents 3.2 Goerli ETH being staked in the system, and it is possible to spin up as many as you desire in order to have more stake in the network.
|
||||
|
||||
### Activating your validator: depositing 3.2 Göerli ETH
|
||||
|
||||
To begin setting up a validator, follow the instructions found on [prylabs.net](https://prylabs.net) to use the Göerli ETH faucet and make a deposit. For step-by-step assistance with the deposit page, see the [Activating a Validator ](https://docs.prylabs.network/docs/activating-a-validator)section of this documentation.
|
||||
|
||||
It will take a while for the nodes in the network to process a deposit. Once the node is active, the validator will immediately begin performing its responsibilities.
|
||||
|
||||
In your validator client, you will be able to frequently see your validator balance as it goes up over time. Note that, should your node ever go offline for a long period, a validator will start gradually losing its deposit until it is removed from the network entirely.
|
||||
|
||||
**Congratulations, you are now running Ethereum 2.0 Phase 0!**
|
||||
|
||||
## Setting up a local ETH2 development chain
|
||||
|
||||
This section outlines the process of setting up Prysm for local testing with other Ethereum 2.0 client implementations. See the [INTEROP.md](https://github.com/prysmaticlabs/prysm/blob/master/INTEROP.md) file for advanced configuration options. For more background information on interoperability development, see [this blog post](https://blog.ethereum.org/2019/09/19/eth2-interop-in-review/).
|
||||
|
||||
### Installation and dependencies
|
||||
|
||||
To begin setting up a local ETH2 development chain, follow the **Bazel** instructions found in the [dependencies](https://github.com/prysmaticlabs/prysm#dependencies) and [installation](https://github.com/prysmaticlabs/prysm#installation) sections respectively.
|
||||
|
||||
### Running a local beacon node and validator client
|
||||
|
||||
The example below will generate a beacon genesis state and initiate Prysm with 64 validators with the genesis time set to your machines UNIX time.
|
||||
|
||||
Open up two terminal windows. In the first, issue the command:
|
||||
|
||||
```text
|
||||
bazel run //beacon-chain -- \
|
||||
--custom-genesis-delay=0 \
|
||||
--bootstrap-node= \
|
||||
--deposit-contract $(curl https://prylabs.net/contract) \
|
||||
--clear-db \
|
||||
--interop-num-validators 64 \
|
||||
--interop-eth1data-votes
|
||||
```
|
||||
|
||||
Wait a moment for the beacon chain to start. In the other terminal, issue the command:
|
||||
|
||||
```text
|
||||
bazel run //validator -- --keymanager=interop --keymanageropts='{"keys":64}'
|
||||
```
|
||||
|
||||
This command will kickstart the system with your 64 validators performing their duties accordingly.
|
||||
|
||||
## Testing Prysm
|
||||
|
||||
To run the unit tests of our system, issue the command:
|
||||
|
||||
```text
|
||||
bazel test //...
|
||||
```
|
||||
|
||||
To run our linter, make sure you have [golangci-lint](https://github.com/golangci/golangci-lint) installed and then issue the command:
|
||||
|
||||
```text
|
||||
golangci-lint run
|
||||
```
|
||||
|
||||
Participation is now open to the public for our Ethereum 2.0 phase 0 testnet release. Visit [prylabs.net](https://prylabs.net) for more information on the project or to sign up as a validator on the network. You can visualize the nodes in the network on [eth2stats.io](https://eth2stats.io), explore validator rewards/penalties via Bitfly's block explorer: [beaconcha.in](https://beaconcha.in), and follow the latest blocks added to the chain on [Etherscan](https://beacon.etherscan.io).
|
||||
|
||||
## Contributing
|
||||
Want to get involved? Check out our [Contribution Guide](https://docs.prylabs.network/docs/contribute/contribution-guidelines/) to learn more!
|
||||
|
||||
305
WORKSPACE
305
WORKSPACE
@@ -13,6 +13,28 @@ http_archive(
|
||||
],
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "com_grail_bazel_toolchain",
|
||||
sha256 = "0bec89e35d8a141c87f28cfc506d6d344785c8eb2ff3a453140a1fe972ada79d",
|
||||
strip_prefix = "bazel-toolchain-77a87103145f86f03f90475d19c2c8854398a444",
|
||||
urls = ["https://github.com/grailbio/bazel-toolchain/archive/77a87103145f86f03f90475d19c2c8854398a444.tar.gz"],
|
||||
)
|
||||
|
||||
load("@com_grail_bazel_toolchain//toolchain:deps.bzl", "bazel_toolchain_dependencies")
|
||||
|
||||
bazel_toolchain_dependencies()
|
||||
|
||||
load("@com_grail_bazel_toolchain//toolchain:rules.bzl", "llvm_toolchain")
|
||||
|
||||
llvm_toolchain(
|
||||
name = "llvm_toolchain",
|
||||
llvm_version = "9.0.0",
|
||||
)
|
||||
|
||||
load("@llvm_toolchain//:toolchains.bzl", "llvm_register_toolchains")
|
||||
|
||||
llvm_register_toolchains()
|
||||
|
||||
load("@prysm//tools/cross-toolchain:prysm_toolchains.bzl", "configure_prysm_toolchains")
|
||||
|
||||
configure_prysm_toolchains()
|
||||
@@ -30,10 +52,10 @@ http_archive(
|
||||
|
||||
http_archive(
|
||||
name = "bazel_gazelle",
|
||||
sha256 = "86c6d481b3f7aedc1d60c1c211c6f76da282ae197c3b3160f54bd3a8f847896f",
|
||||
sha256 = "d8c45ee70ec39a57e7a05e5027c32b1576cc7f16d9dd37135b0eddde45cf1b10",
|
||||
urls = [
|
||||
"https://storage.googleapis.com/bazel-mirror/github.com/bazelbuild/bazel-gazelle/releases/download/v0.19.1/bazel-gazelle-v0.19.1.tar.gz",
|
||||
"https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.19.1/bazel-gazelle-v0.19.1.tar.gz",
|
||||
"https://storage.googleapis.com/bazel-mirror/github.com/bazelbuild/bazel-gazelle/releases/download/v0.20.0/bazel-gazelle-v0.20.0.tar.gz",
|
||||
"https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.20.0/bazel-gazelle-v0.20.0.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -53,10 +75,10 @@ http_archive(
|
||||
|
||||
http_archive(
|
||||
name = "io_bazel_rules_go",
|
||||
sha256 = "e88471aea3a3a4f19ec1310a55ba94772d087e9ce46e41ae38ecebe17935de7b",
|
||||
sha256 = "e6a6c016b0663e06fa5fccf1cd8152eab8aa8180c583ec20c872f4f9953a7ac5",
|
||||
urls = [
|
||||
"https://storage.googleapis.com/bazel-mirror/github.com/bazelbuild/rules_go/releases/download/v0.20.3/rules_go-v0.20.3.tar.gz",
|
||||
"https://github.com/bazelbuild/rules_go/releases/download/v0.20.3/rules_go-v0.20.3.tar.gz",
|
||||
"https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.22.1/rules_go-v0.22.1.tar.gz",
|
||||
"https://github.com/bazelbuild/rules_go/releases/download/v0.22.1/rules_go-v0.22.1.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -70,7 +92,7 @@ git_repository(
|
||||
name = "graknlabs_bazel_distribution",
|
||||
commit = "962f3a7e56942430c0ec120c24f9e9f2a9c2ce1a",
|
||||
remote = "https://github.com/graknlabs/bazel-distribution",
|
||||
shallow_since = "1563544980 +0300",
|
||||
shallow_since = "1569509514 +0300",
|
||||
)
|
||||
|
||||
# Override default import in rules_go with special patch until
|
||||
@@ -84,7 +106,7 @@ git_repository(
|
||||
"//third_party:com_github_gogo_protobuf-equal.patch",
|
||||
],
|
||||
remote = "https://github.com/gogo/protobuf",
|
||||
shallow_since = "1567336231 +0200",
|
||||
shallow_since = "1571033717 +0200",
|
||||
# gazelle args: -go_prefix github.com/gogo/protobuf -proto legacy
|
||||
)
|
||||
|
||||
@@ -95,6 +117,22 @@ load(
|
||||
|
||||
container_repositories()
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_docker//container:container.bzl",
|
||||
"container_pull",
|
||||
)
|
||||
|
||||
container_pull(
|
||||
name = "alpine_cc_linux_amd64",
|
||||
digest = "sha256:d5cee45549351be7a03a96c7b319b9c1808979b10888b79acca4435cc068005e",
|
||||
registry = "index.docker.io",
|
||||
repository = "frolvlad/alpine-glibc",
|
||||
)
|
||||
|
||||
load("@prysm//third_party/herumi:herumi.bzl", "bls_dependencies")
|
||||
|
||||
bls_dependencies()
|
||||
|
||||
load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies")
|
||||
|
||||
go_rules_dependencies()
|
||||
@@ -114,15 +152,8 @@ load(
|
||||
_go_image_repos = "repositories",
|
||||
)
|
||||
|
||||
_go_image_repos()
|
||||
|
||||
# Golang images
|
||||
# This is using gcr.io/distroless/base
|
||||
load(
|
||||
"@io_bazel_rules_docker//go:image.bzl",
|
||||
_go_image_repos = "repositories",
|
||||
)
|
||||
|
||||
_go_image_repos()
|
||||
|
||||
# CC images
|
||||
@@ -166,8 +197,8 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "72c6ee3c20d19736b1203f364a6eb0ddee2c173073e20bee2beccd288fdc42be",
|
||||
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.9.4/general.tar.gz",
|
||||
sha256 = "b90221d87b3b4cb17d7f195f8852f5dd8fec1cf623d42443b97bdb5a216ae61d",
|
||||
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.11.1/general.tar.gz",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
@@ -182,8 +213,8 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "a3cc860a3679f6f62ee57b65677a9b48a65fdebb151cdcbf50f23852632845ef",
|
||||
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.9.4/minimal.tar.gz",
|
||||
sha256 = "316b227c0198f55872e46d601a578afeac88aab36ed38e3f01af753e98db156f",
|
||||
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.11.1/minimal.tar.gz",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
@@ -198,8 +229,8 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "8fc1b6220973ca30fa4ddc4ed24d66b1719abadca8bedb5e06c3bd9bc0df28e9",
|
||||
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.9.4/mainnet.tar.gz",
|
||||
sha256 = "b9c52f60293bcc1acfd4f8ab7ddf8bf8222ddd6a105e93d384542d1396e1b07a",
|
||||
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.11.1/mainnet.tar.gz",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
@@ -209,13 +240,6 @@ http_archive(
|
||||
url = "https://github.com/bazelbuild/buildtools/archive/bf564b4925ab5876a3f64d8b90fab7f769013d42.zip",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "com_github_herumi_bls_eth_go_binary",
|
||||
sha256 = "b5628a95bd1e6ff84f73d87c134bb1e7e9c1a5a2a10b831867d9dad7d8defc3e",
|
||||
strip_prefix = "bls-go-binary-8ee33d1a2e8ba8dcf0c3d0b459d75d42d163339d",
|
||||
url = "https://github.com/nisdas/bls-go-binary/archive/8ee33d1a2e8ba8dcf0c3d0b459d75d42d163339d.zip",
|
||||
)
|
||||
|
||||
load("@com_github_bazelbuild_buildtools//buildifier:deps.bzl", "buildifier_dependencies")
|
||||
|
||||
buildifier_dependencies()
|
||||
@@ -242,9 +266,9 @@ all_content = """filegroup(name = "all", srcs = glob(["**"]), visibility = ["//v
|
||||
|
||||
http_archive(
|
||||
name = "rules_foreign_cc",
|
||||
sha256 = "450563dc2938f38566a59596bb30a3e905fbbcc35b3fff5a1791b122bc140465",
|
||||
strip_prefix = "rules_foreign_cc-456425521973736ef346d93d3d6ba07d807047df",
|
||||
url = "https://github.com/bazelbuild/rules_foreign_cc/archive/456425521973736ef346d93d3d6ba07d807047df.zip",
|
||||
sha256 = "450563dc2938f38566a59596bb30a3e905fbbcc35b3fff5a1791b122bc140465",
|
||||
)
|
||||
|
||||
load("@rules_foreign_cc//:workspace_definitions.bzl", "rules_foreign_cc_dependencies")
|
||||
@@ -256,6 +280,7 @@ rules_foreign_cc_dependencies([
|
||||
http_archive(
|
||||
name = "librdkafka",
|
||||
build_file_content = all_content,
|
||||
sha256 = "f6be27772babfdacbbf2e4c5432ea46c57ef5b7d82e52a81b885e7b804781fd6",
|
||||
strip_prefix = "librdkafka-1.2.1",
|
||||
urls = ["https://github.com/edenhill/librdkafka/archive/v1.2.1.tar.gz"],
|
||||
)
|
||||
@@ -264,7 +289,7 @@ http_archive(
|
||||
|
||||
go_repository(
|
||||
name = "com_github_ethereum_go_ethereum",
|
||||
commit = "40beaeef26d5a2a0918dec2b960c2556c71a90a0",
|
||||
commit = "861ae1b1875c17d86a6a5d68118708ab2b099658",
|
||||
importpath = "github.com/ethereum/go-ethereum",
|
||||
# Note: go-ethereum is not bazel-friendly with regards to cgo. We have a
|
||||
# a fork that has resolved these issues by disabling HID/USB support and
|
||||
@@ -279,12 +304,10 @@ go_repository(
|
||||
name = "com_github_prysmaticlabs_go_ssz",
|
||||
commit = "e24db4d9e9637cf88ee9e4a779e339a1686a84ee",
|
||||
importpath = "github.com/prysmaticlabs/go-ssz",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_urfave_cli",
|
||||
commit = "e6cf83ec39f6e1158ced1927d4ed14578fda8edb", # v1.21.0
|
||||
importpath = "github.com/urfave/cli",
|
||||
patch_args = ["-p1"],
|
||||
patches = [
|
||||
"//third_party:com_github_prysmaticlabs_go_ssz.patch",
|
||||
],
|
||||
)
|
||||
|
||||
go_repository(
|
||||
@@ -615,8 +638,9 @@ go_repository(
|
||||
|
||||
go_repository(
|
||||
name = "org_golang_x_crypto",
|
||||
commit = "4def268fd1a49955bfb3dda92fe3db4f924f2285",
|
||||
importpath = "golang.org/x/crypto",
|
||||
sum = "h1:1ZiEyfaQIg3Qh0EoqpwAakHVhecoE5wlSg5GjnafJGw=",
|
||||
version = "v0.0.0-20200221231518-2aa609cf4a9d",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
@@ -742,12 +766,6 @@ go_repository(
|
||||
importpath = "github.com/matttproud/golang_protobuf_extensions",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_boltdb_bolt",
|
||||
commit = "2f1ce7a837dcb8da3ec595b1dac9d0632f0f99e8", # v1.3.1
|
||||
importpath = "github.com/boltdb/bolt",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_pborman_uuid",
|
||||
commit = "8b1b92947f46224e3b97bb1a3a5b0382be00d31e", # v1.2.0
|
||||
@@ -892,6 +910,13 @@ go_repository(
|
||||
importpath = "k8s.io/client-go",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "io_etcd_go_bbolt",
|
||||
importpath = "go.etcd.io/bbolt",
|
||||
sum = "h1:hi1bXHMVrlQh6WwxAy+qZCV/SYIlqo+Ushwdpa4tAKg=",
|
||||
version = "v1.3.4",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "io_k8s_apimachinery",
|
||||
build_file_proto_mode = "disable_global",
|
||||
@@ -908,8 +933,8 @@ go_repository(
|
||||
go_repository(
|
||||
name = "com_github_google_gofuzz",
|
||||
importpath = "github.com/google/gofuzz",
|
||||
sum = "h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=",
|
||||
version = "v1.0.0",
|
||||
sum = "h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=",
|
||||
version = "v1.1.0",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
@@ -1176,7 +1201,7 @@ go_repository(
|
||||
|
||||
go_repository(
|
||||
name = "com_github_prysmaticlabs_go_bitfield",
|
||||
commit = "dbb55b15e92f897ee230360c8d9695e2f224b117",
|
||||
commit = "62c2aee7166951c456888f92237aee4303ba1b9d",
|
||||
importpath = "github.com/prysmaticlabs/go-bitfield",
|
||||
)
|
||||
|
||||
@@ -1187,8 +1212,9 @@ go_ssz_dependencies()
|
||||
go_repository(
|
||||
name = "org_golang_google_grpc",
|
||||
build_file_proto_mode = "disable",
|
||||
commit = "1d89a3c832915b2314551c1d2a506874d62e53f7", # v1.22.0
|
||||
importpath = "google.golang.org/grpc",
|
||||
sum = "h1:zvIju4sqAGvwKspUQOhwnpcqSbzi7/H6QomNNjTL4sk=",
|
||||
version = "v1.27.1",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
@@ -1215,12 +1241,6 @@ go_repository(
|
||||
importpath = "golang.org/x/time",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "in_gopkg_natefinch_npipe_v2",
|
||||
commit = "c1b8fa8bdccecb0b8db834ee0b92fdbcfa606dd6",
|
||||
importpath = "gopkg.in/natefinch/npipe.v2",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_googleapis_gnostic",
|
||||
commit = "896953e6749863beec38e27029c804e88c3144b8", # v0.4.1
|
||||
@@ -1277,12 +1297,6 @@ go_repository(
|
||||
importpath = "k8s.io/utils",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_googleapis_gnostic",
|
||||
commit = "25d8b0b6698593f520d9d8dc5a88e6b16ca9ecc0",
|
||||
importpath = "github.com/googleapis/gnostic",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_patrickmn_go_cache",
|
||||
commit = "46f407853014144407b6c2ec7ccc76bf67958d93",
|
||||
@@ -1291,7 +1305,7 @@ go_repository(
|
||||
|
||||
go_repository(
|
||||
name = "com_github_prysmaticlabs_ethereumapis",
|
||||
commit = "fca4d6f69bedb8615c2fc916d1a68f2692285caa",
|
||||
commit = "6607cc86ddb7c78acfe3b1f0dfb115489a96d46d",
|
||||
importpath = "github.com/prysmaticlabs/ethereumapis",
|
||||
patch_args = ["-p1"],
|
||||
patches = [
|
||||
@@ -1301,8 +1315,9 @@ go_repository(
|
||||
|
||||
go_repository(
|
||||
name = "com_github_cloudflare_roughtime",
|
||||
commit = "d41fdcee702eb3e5c3296288a453b9340184d37e",
|
||||
importpath = "github.com/cloudflare/roughtime",
|
||||
sum = "h1:jeSxE3fepJdhASERvBHI6RFkMhISv6Ir2JUybYLIVXs=",
|
||||
version = "v0.0.0-20200205191924-a69ef1dab727",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
@@ -1325,13 +1340,6 @@ go_repository(
|
||||
version = "v0.0.4",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_mdlayher_prombolt",
|
||||
importpath = "github.com/mdlayher/prombolt",
|
||||
sum = "h1:N257g6TTx0LxYoskSDFxvkSJ3NOZpy9IF1xQ7Gu+K8I=",
|
||||
version = "v0.0.0-20161005185022-dfcf01d20ee9",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_minio_highwayhash",
|
||||
importpath = "github.com/minio/highwayhash",
|
||||
@@ -1369,13 +1377,6 @@ go_repository(
|
||||
version = "v0.10.5",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "in_gopkg_urfave_cli_v1",
|
||||
importpath = "gopkg.in/urfave/cli.v1",
|
||||
sum = "h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0=",
|
||||
version = "v1.20.0",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_naoina_go_stringutil",
|
||||
importpath = "github.com/naoina/go-stringutil",
|
||||
@@ -1453,9 +1454,9 @@ go_repository(
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_emicklei_dot",
|
||||
commit = "f4a04130244d60cef56086d2f649b4b55e9624aa",
|
||||
importpath = "github.com/emicklei/dot",
|
||||
name = "com_github_googleapis_gnostic",
|
||||
commit = "25d8b0b6698593f520d9d8dc5a88e6b16ca9ecc0",
|
||||
importpath = "github.com/googleapis/gnostic",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
@@ -1498,18 +1499,6 @@ go_repository(
|
||||
version = "v0.0.1",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_dgraph_io_ristretto",
|
||||
commit = "99d1bbbf28e64530eb246be0568fc7709a35ebdd",
|
||||
importpath = "github.com/dgraph-io/ristretto",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_cespare_xxhash",
|
||||
commit = "d7df74196a9e781ede915320c11c378c1b2f3a1f",
|
||||
importpath = "github.com/cespare/xxhash",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_kevinms_leakybucket_go",
|
||||
importpath = "github.com/kevinms/leakybucket-go",
|
||||
@@ -1519,74 +1508,89 @@ go_repository(
|
||||
|
||||
go_repository(
|
||||
name = "com_github_wealdtech_go_eth2_wallet",
|
||||
commit = "6970d62e60d86fdae3c3e510e800e8a60d755a7d",
|
||||
importpath = "github.com/wealdtech/go-eth2-wallet",
|
||||
sum = "h1:Hna/w4EKBJIs86VprIq7ez063A6kwk31d/O3Gs+MpYc=",
|
||||
version = "v1.9.3",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_wealdtech_go_eth2_wallet_hd",
|
||||
commit = "ce0a252a01c621687e9786a64899cfbfe802ba73",
|
||||
importpath = "github.com/wealdtech/go-eth2-wallet-hd",
|
||||
name = "com_github_wealdtech_go_eth2_wallet_hd_v2",
|
||||
importpath = "github.com/wealdtech/go-eth2-wallet-hd/v2",
|
||||
sum = "h1:kiCvdexK3zRC2GwZHSHq+hS+irVNtMs5pNADyumeeRM=",
|
||||
version = "v2.0.1",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_wealdtech_go_eth2_wallet_nd",
|
||||
commit = "12c8c41cdbd16797ff292e27f58e126bb89e9706",
|
||||
importpath = "github.com/wealdtech/go-eth2-wallet-nd",
|
||||
name = "com_github_wealdtech_go_eth2_wallet_nd_v2",
|
||||
importpath = "github.com/wealdtech/go-eth2-wallet-nd/v2",
|
||||
sum = "h1:4lB6GY5oHQn5xwn/Sxm1e9SeVCaxa7q/0hqXUQYUNwU=",
|
||||
version = "v2.0.1",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_wealdtech_go_eth2_wallet_store_filesystem",
|
||||
commit = "1eea6a48d75380047d2ebe7c8c4bd8985bcfdeca",
|
||||
importpath = "github.com/wealdtech/go-eth2-wallet-store-filesystem",
|
||||
sum = "h1:Lc6wVTjIYeD+2hLAIzq1SugTWR527vEX4tEr5v3zxJc=",
|
||||
version = "v1.7.2",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_wealdtech_go_eth2_wallet_store_s3",
|
||||
commit = "1c821b5161f7bb0b3efa2030eff687eea5e70e53",
|
||||
importpath = "github.com/wealdtech/go-eth2-wallet-store-s3",
|
||||
sum = "h1:xzyQDxbe5nr7xG0ByevTV2S8qkeOZvvjp+leBJcpxXQ=",
|
||||
version = "v1.6.2",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_wealdtech_go_eth2_wallet_encryptor_keystorev4",
|
||||
commit = "0c11c07b9544eb662210fadded94f40f309d8c8f",
|
||||
importpath = "github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4",
|
||||
sum = "h1:IcpS4VpXhYz+TVupB5n6C6IQzaKwG+Rc8nvgCa/da4c=",
|
||||
version = "v1.0.0",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_wealdtech_go_eth2_wallet_types",
|
||||
commit = "af67d8101be61e7c4dd8126d2b3eba20cff5dab2",
|
||||
importpath = "github.com/wealdtech/go-eth2-wallet-types",
|
||||
name = "com_github_wealdtech_go_eth2_wallet_types_v2",
|
||||
importpath = "github.com/wealdtech/go-eth2-wallet-types/v2",
|
||||
sum = "h1:Ct3RrNJTapBiG2GxVl53Kfgy96f0GEUV7bediTu91u8=",
|
||||
version = "v2.0.1",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_wealdtech_go_eth2_types",
|
||||
commit = "f9c31ddf180537dd5712d5998a3d56c45864d71f",
|
||||
importpath = "github.com/wealdtech/go-eth2-types",
|
||||
name = "com_github_wealdtech_go_eth2_types_v2",
|
||||
importpath = "github.com/wealdtech/go-eth2-types/v2",
|
||||
sum = "h1:qfmgaCBkH2N11LHCXsRWYz7OOxc+1QXrKHlS9yDnFsw=",
|
||||
version = "v2.3.0",
|
||||
build_directives = [
|
||||
"gazelle:resolve go github.com/herumi/bls-eth-go-binary/bls @herumi_bls_eth_go_binary//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_wealdtech_go_eth2_util",
|
||||
commit = "326ebb1755651131bb8f4506ea9a23be6d9ad1dd",
|
||||
importpath = "github.com/wealdtech/go-eth2-util",
|
||||
sum = "h1:MyM16V7Qhd9q2ZaRa0WteBg2bWb8UplIKjZr8aeBZP0=",
|
||||
version = "v1.1.4",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_wealdtech_go_ecodec",
|
||||
commit = "7473d835445a3490e61a5fcf48fe4e9755a37957",
|
||||
importpath = "github.com/wealdtech/go-ecodec",
|
||||
sum = "h1:yggrTSckcPJRaxxOxQF7FPm21kgE8WA6+f5jdq5Kr8o=",
|
||||
version = "v1.1.0",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_wealdtech_go_bytesutil",
|
||||
commit = "e564d0ade555b9f97494f0f669196ddcc6bc531d",
|
||||
importpath = "github.com/wealdtech/go-bytesutil",
|
||||
sum = "h1:ocEg3Ke2GkZ4vQw5lp46rmO+pfqCCTgq35gqOy8JKVc=",
|
||||
version = "v1.1.1",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_wealdtech_go_indexer",
|
||||
commit = "334862c32b1e3a5c6738a2618f5c0a8ebeb8cd51",
|
||||
importpath = "github.com/wealdtech/go-indexer",
|
||||
sum = "h1:/S4rfWQbSOnnYmwnvuTVatDibZ8o1s9bmTCHO16XINg=",
|
||||
version = "v1.0.0",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
@@ -1601,3 +1605,84 @@ go_repository(
|
||||
sum = "h1:J1gHJRNFEk7NdiaPQQqAvxEy+7hhCsVv3uzduWybmqY=",
|
||||
version = "v0.0.0-20200302201340-8c54356e12c9",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_ferranbt_fastssz",
|
||||
commit = "06015a5d84f9e4eefe2c21377ca678fa8f1a1b09",
|
||||
importpath = "github.com/ferranbt/fastssz",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_burntsushi_toml",
|
||||
importpath = "github.com/BurntSushi/toml",
|
||||
sum = "h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=",
|
||||
version = "v0.3.1",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_cpuguy83_go_md2man_v2",
|
||||
importpath = "github.com/cpuguy83/go-md2man/v2",
|
||||
sum = "h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=",
|
||||
version = "v2.0.0",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_russross_blackfriday_v2",
|
||||
importpath = "github.com/russross/blackfriday/v2",
|
||||
sum = "h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=",
|
||||
version = "v2.0.1",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_shurcool_sanitized_anchor_name",
|
||||
importpath = "github.com/shurcooL/sanitized_anchor_name",
|
||||
sum = "h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=",
|
||||
version = "v1.0.0",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "in_gopkg_urfave_cli_v2",
|
||||
importpath = "gopkg.in/urfave/cli.v2",
|
||||
sum = "h1:OvXt/p4cdwNl+mwcWMq/AxaKFkhdxcjx+tx+qf4EOvY=",
|
||||
version = "v2.0.0-20190806201727-b62605953717",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "in_gopkg_urfave_cli_v1",
|
||||
importpath = "gopkg.in/urfave/cli.v1",
|
||||
sum = "h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0=",
|
||||
version = "v1.20.0",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_wealdtech_eth2_signer_api",
|
||||
build_file_proto_mode = "disable_global",
|
||||
importpath = "github.com/wealdtech/eth2-signer-api",
|
||||
sum = "h1:fqJYjKwG/FeUAJYYiZblIP6agiz3WWB+Hxpw85Fnr5I=",
|
||||
version = "v1.0.1",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_prysmaticlabs_prombbolt",
|
||||
importpath = "github.com/prysmaticlabs/prombbolt",
|
||||
sum = "h1:bVD46NhbqEE6bsIqj42TCS3ELUdumti3WfAw9DXNtkg=",
|
||||
version = "v0.0.0-20200324184628-09789ef63796",
|
||||
)
|
||||
|
||||
load("@com_github_prysmaticlabs_prombbolt//:repositories.bzl", "prombbolt_dependencies")
|
||||
|
||||
prombbolt_dependencies()
|
||||
|
||||
go_repository(
|
||||
name = "com_github_ianlancetaylor_cgosymbolizer",
|
||||
importpath = "github.com/ianlancetaylor/cgosymbolizer",
|
||||
sum = "h1:GWsU1WjSE2rtvyTYGcndqmPPkQkBNV7pEuZdnGtwtu4=",
|
||||
version = "v0.0.0-20200321040036-d43e30eacb43",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "org_golang_x_mod",
|
||||
importpath = "golang.org/x/mod",
|
||||
sum = "h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=",
|
||||
version = "v0.2.0",
|
||||
)
|
||||
|
||||
11
bazel.sh
Executable file
11
bazel.sh
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This script serves as a wrapper around bazel to limit the scope of environment variables that
|
||||
# may change the action output. Using this script should result in a higher cache hit ratio for
|
||||
# cached actions with a more heremtic build.
|
||||
|
||||
env -i \
|
||||
PATH=/usr/bin:/bin \
|
||||
HOME=$HOME \
|
||||
GOOGLE_APPLICATION_CREDENTIALS=$GOOGLE_APPLICATION_CREDENTIALS \
|
||||
bazel "$@"
|
||||
@@ -1,7 +1,7 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library", "go_test")
|
||||
load("@io_bazel_rules_docker//go:image.bzl", "go_image")
|
||||
load("@io_bazel_rules_docker//container:container.bzl", "container_bundle")
|
||||
load("//tools:binary_targets.bzl", "binary_targets", "go_image_debug")
|
||||
load("//tools:go_image.bzl", "go_image_alpine", "go_image_debug")
|
||||
load("@io_bazel_rules_docker//contrib:push-all.bzl", "docker_push")
|
||||
|
||||
go_library(
|
||||
@@ -23,9 +23,10 @@ go_library(
|
||||
"@com_github_ipfs_go_log//:go_default_library",
|
||||
"@com_github_joonix_log//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@com_github_urfave_cli//:go_default_library",
|
||||
"@com_github_whyrusleeping_go_logging//:go_default_library",
|
||||
"@com_github_x_cray_logrus_prefixed_formatter//:go_default_library",
|
||||
"@in_gopkg_urfave_cli_v2//:go_default_library",
|
||||
"@in_gopkg_urfave_cli_v2//altsrc:go_default_library",
|
||||
"@org_uber_go_automaxprocs//:go_default_library",
|
||||
],
|
||||
)
|
||||
@@ -36,7 +37,11 @@ go_image(
|
||||
"main.go",
|
||||
"usage.go",
|
||||
],
|
||||
base = "//tools:cc_image",
|
||||
base = select({
|
||||
"//tools:base_image_alpine": "//tools:alpine_cc_image",
|
||||
"//tools:base_image_cc": "//tools:cc_image",
|
||||
"//conditions:default": "//tools:cc_image",
|
||||
}),
|
||||
goarch = "amd64",
|
||||
goos = "linux",
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain",
|
||||
@@ -55,9 +60,10 @@ go_image(
|
||||
"@com_github_ipfs_go_log//:go_default_library",
|
||||
"@com_github_joonix_log//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@com_github_urfave_cli//:go_default_library",
|
||||
"@com_github_whyrusleeping_go_logging//:go_default_library",
|
||||
"@com_github_x_cray_logrus_prefixed_formatter//:go_default_library",
|
||||
"@in_gopkg_urfave_cli_v2//:go_default_library",
|
||||
"@in_gopkg_urfave_cli_v2//altsrc:go_default_library",
|
||||
"@org_uber_go_automaxprocs//:go_default_library",
|
||||
],
|
||||
)
|
||||
@@ -74,6 +80,7 @@ container_bundle(
|
||||
go_image_debug(
|
||||
name = "image_debug",
|
||||
image = ":image",
|
||||
tags = ["manual"],
|
||||
)
|
||||
|
||||
container_bundle(
|
||||
@@ -85,6 +92,21 @@ container_bundle(
|
||||
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",
|
||||
},
|
||||
tags = ["manual"],
|
||||
)
|
||||
|
||||
docker_push(
|
||||
name = "push_images",
|
||||
bundle = ":image_bundle",
|
||||
@@ -97,6 +119,12 @@ docker_push(
|
||||
tags = ["manual"],
|
||||
)
|
||||
|
||||
docker_push(
|
||||
name = "push_images_alpine",
|
||||
bundle = ":image_bundle_alpine",
|
||||
tags = ["manual"],
|
||||
)
|
||||
|
||||
go_binary(
|
||||
name = "beacon-chain",
|
||||
embed = [":go_default_library"],
|
||||
@@ -111,17 +139,8 @@ go_test(
|
||||
size = "small",
|
||||
srcs = ["usage_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = ["@com_github_urfave_cli//:go_default_library"],
|
||||
deps = [
|
||||
"//shared/featureconfig:go_default_library",
|
||||
"@in_gopkg_urfave_cli_v2//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
[go_binary(
|
||||
name = "beacon-chain-{}-{}".format(
|
||||
pair[0],
|
||||
pair[1],
|
||||
),
|
||||
embed = [":go_default_library"],
|
||||
goarch = pair[1],
|
||||
goos = pair[0],
|
||||
tags = ["manual"],
|
||||
visibility = ["//visibility:public"],
|
||||
) for pair in binary_targets]
|
||||
|
||||
@@ -39,7 +39,6 @@ go_test(
|
||||
"//shared/testutil:go_default_library",
|
||||
"@com_github_gogo_protobuf//proto:go_default_library",
|
||||
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
|
||||
],
|
||||
|
||||
@@ -147,7 +147,11 @@ func (s *Service) run(ctx context.Context) {
|
||||
select {
|
||||
case event := <-stateChannel:
|
||||
if event.Type == statefeed.BlockProcessed {
|
||||
data := event.Data.(*statefeed.BlockProcessedData)
|
||||
data, ok := event.Data.(*statefeed.BlockProcessedData)
|
||||
if !ok {
|
||||
log.Error("Event feed data is not type *statefeed.BlockProcessedData")
|
||||
continue
|
||||
}
|
||||
log.WithField("headRoot", fmt.Sprintf("%#x", data.BlockRoot)).Debug("Received block processed event")
|
||||
headState, err := s.headFetcher.HeadState(ctx)
|
||||
if err != nil {
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
mock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
|
||||
@@ -34,10 +33,8 @@ func TestArchiverService_ReceivesBlockProcessedEvent(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
svc, beaconDB := setupService(t)
|
||||
defer dbutil.TeardownDB(t, beaconDB)
|
||||
st, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
||||
Slot: 1,
|
||||
})
|
||||
if err != nil {
|
||||
st := testutil.NewBeaconState()
|
||||
if err := st.SetSlot(1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
svc.headFetcher = &mock.ChainService{
|
||||
@@ -61,10 +58,8 @@ func TestArchiverService_OnlyArchiveAtEpochEnd(t *testing.T) {
|
||||
svc, beaconDB := setupService(t)
|
||||
defer dbutil.TeardownDB(t, beaconDB)
|
||||
// The head state is NOT an epoch end.
|
||||
st, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
||||
Slot: params.BeaconConfig().SlotsPerEpoch - 2,
|
||||
})
|
||||
if err != nil {
|
||||
st := testutil.NewBeaconState()
|
||||
if err := st.SetSlot(params.BeaconConfig().SlotsPerEpoch - 2); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
svc.headFetcher = &mock.ChainService{
|
||||
@@ -317,8 +312,8 @@ func TestArchiverService_SavesActivatedValidatorChanges(t *testing.T) {
|
||||
if retrieved == nil {
|
||||
t.Fatal("Retrieved indices are nil")
|
||||
}
|
||||
if !reflect.DeepEqual(retrieved.Activated, []uint64{4, 5}) {
|
||||
t.Errorf("Wanted indices 4 5 activated, received %v", retrieved.Activated)
|
||||
if len(retrieved.Activated) != 98 {
|
||||
t.Error("Did not get wanted active length")
|
||||
}
|
||||
testutil.AssertLogsContain(t, hook, "Successfully archived")
|
||||
}
|
||||
@@ -433,18 +428,20 @@ func setupState(validatorCount uint64) (*stateTrie.BeaconState, error) {
|
||||
|
||||
// We initialize a head state that has attestations from participated
|
||||
// validators in a simulated fashion.
|
||||
return stateTrie.InitializeFromProto(&pb.BeaconState{
|
||||
Slot: (2 * params.BeaconConfig().SlotsPerEpoch) - 1,
|
||||
Validators: validators,
|
||||
Balances: balances,
|
||||
BlockRoots: make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot),
|
||||
Slashings: []uint64{0, 1e9, 1e9},
|
||||
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
|
||||
CurrentEpochAttestations: atts,
|
||||
FinalizedCheckpoint: ðpb.Checkpoint{},
|
||||
JustificationBits: bitfield.Bitvector4{0x00},
|
||||
CurrentJustifiedCheckpoint: ðpb.Checkpoint{},
|
||||
})
|
||||
st := testutil.NewBeaconState()
|
||||
if err := st.SetSlot((2 * params.BeaconConfig().SlotsPerEpoch) - 1); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := st.SetValidators(validators); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := st.SetBalances(balances); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := st.SetCurrentEpochAttestations(atts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return st, nil
|
||||
}
|
||||
|
||||
func setupService(t *testing.T) (*Service, db.Database) {
|
||||
|
||||
@@ -40,11 +40,13 @@ go_library(
|
||||
"//beacon-chain/powchain:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//beacon-chain/state/stategen:go_default_library",
|
||||
"//beacon-chain/state/stateutil:go_default_library",
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/attestationutil:go_default_library",
|
||||
"//shared/bytesutil:go_default_library",
|
||||
"//shared/featureconfig:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"//shared/roughtime:go_default_library",
|
||||
"//shared/slotutil:go_default_library",
|
||||
"//shared/traceutil:go_default_library",
|
||||
"@com_github_emicklei_dot//:go_default_library",
|
||||
@@ -115,6 +117,13 @@ go_test(
|
||||
"service_norace_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
gc_goopts = [
|
||||
# Go 1.14 enables checkptr by default when building with -race or -msan. There is a pointer
|
||||
# issue in boltdb, so must disable checkptr at compile time. This flag can be removed once
|
||||
# the project is migrated to etcd's version of boltdb and the issue has been fixed.
|
||||
# See: https://github.com/etcd-io/bbolt/issues/187.
|
||||
"-d=checkptr=0",
|
||||
],
|
||||
race = "on",
|
||||
tags = ["race_on"],
|
||||
deps = [
|
||||
|
||||
@@ -186,7 +186,7 @@ func (s *Service) CurrentFork() *pb.Fork {
|
||||
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
|
||||
}
|
||||
}
|
||||
return s.headState().Fork()
|
||||
return s.head.state.Fork()
|
||||
}
|
||||
|
||||
// Participation returns the participation stats of a given epoch.
|
||||
|
||||
@@ -5,7 +5,9 @@ import (
|
||||
"testing"
|
||||
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
||||
)
|
||||
|
||||
func TestHeadSlot_DataRace(t *testing.T) {
|
||||
@@ -15,10 +17,9 @@ func TestHeadSlot_DataRace(t *testing.T) {
|
||||
beaconDB: db,
|
||||
}
|
||||
go func() {
|
||||
s.saveHead(
|
||||
context.Background(),
|
||||
[32]byte{},
|
||||
)
|
||||
if err := s.saveHead(context.Background(), [32]byte{}, ); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}()
|
||||
s.HeadSlot()
|
||||
}
|
||||
@@ -29,12 +30,12 @@ func TestHeadRoot_DataRace(t *testing.T) {
|
||||
s := &Service{
|
||||
beaconDB: db,
|
||||
head: &head{root: [32]byte{'A'}},
|
||||
stateGen: stategen.New(db, cache.NewStateSummaryCache()),
|
||||
}
|
||||
go func() {
|
||||
s.saveHead(
|
||||
context.Background(),
|
||||
[32]byte{},
|
||||
)
|
||||
if err := s.saveHead(context.Background(), [32]byte{}, ); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}()
|
||||
if _, err := s.HeadRoot(context.Background()); err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -47,14 +48,16 @@ func TestHeadBlock_DataRace(t *testing.T) {
|
||||
s := &Service{
|
||||
beaconDB: db,
|
||||
head: &head{block: ðpb.SignedBeaconBlock{}},
|
||||
stateGen: stategen.New(db, cache.NewStateSummaryCache()),
|
||||
}
|
||||
go func() {
|
||||
s.saveHead(
|
||||
context.Background(),
|
||||
[32]byte{},
|
||||
)
|
||||
if err := s.saveHead(context.Background(), [32]byte{}, ); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}()
|
||||
s.HeadBlock(context.Background())
|
||||
if _, err := s.HeadBlock(context.Background()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHeadState_DataRace(t *testing.T) {
|
||||
@@ -62,12 +65,14 @@ func TestHeadState_DataRace(t *testing.T) {
|
||||
defer testDB.TeardownDB(t, db)
|
||||
s := &Service{
|
||||
beaconDB: db,
|
||||
stateGen: stategen.New(db, cache.NewStateSummaryCache()),
|
||||
}
|
||||
go func() {
|
||||
s.saveHead(
|
||||
context.Background(),
|
||||
[32]byte{},
|
||||
)
|
||||
if err := s.saveHead(context.Background(), [32]byte{}, ); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}()
|
||||
s.HeadState(context.Background())
|
||||
if _, err := s.HeadState(context.Background()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,7 +128,10 @@ func TestPrevJustifiedCheckpt_GenesisRootOk(t *testing.T) {
|
||||
|
||||
func TestHeadSlot_CanRetrieve(t *testing.T) {
|
||||
c := &Service{}
|
||||
s, _ := state.InitializeFromProto(&pb.BeaconState{})
|
||||
s, err := state.InitializeFromProto(&pb.BeaconState{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
c.head = &head{slot: 100, state: s}
|
||||
if c.HeadSlot() != 100 {
|
||||
t.Errorf("Wanted head slot: %d, got: %d", 100, c.HeadSlot())
|
||||
@@ -145,7 +148,10 @@ func TestHeadRoot_CanRetrieve(t *testing.T) {
|
||||
|
||||
func TestHeadBlock_CanRetrieve(t *testing.T) {
|
||||
b := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 1}}
|
||||
s, _ := state.InitializeFromProto(&pb.BeaconState{})
|
||||
s, err := state.InitializeFromProto(&pb.BeaconState{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
c := &Service{}
|
||||
c.head = &head{block: b, state: s}
|
||||
|
||||
@@ -160,7 +166,7 @@ func TestHeadBlock_CanRetrieve(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestHeadState_CanRetrieve(t *testing.T) {
|
||||
s, err := state.InitializeFromProto(&pb.BeaconState{Slot: 2})
|
||||
s, err := state.InitializeFromProto(&pb.BeaconState{Slot: 2, GenesisValidatorsRoot: params.BeaconConfig().ZeroHash[:]})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -170,7 +176,7 @@ func TestHeadState_CanRetrieve(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(s.InnerStateUnsafe(), headState.InnerStateUnsafe()) {
|
||||
if !proto.Equal(s.InnerStateUnsafe(), headState.InnerStateUnsafe()) {
|
||||
t.Error("incorrect head state received")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
@@ -58,9 +59,15 @@ 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
|
||||
_, cached := s.initSyncState[headRoot]
|
||||
if !cached && !s.beaconDB.HasState(ctx, headRoot) {
|
||||
return nil
|
||||
if !featureconfig.Get().DisableNewStateMgmt {
|
||||
if !s.stateGen.StateSummaryExists(ctx, headRoot) {
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
_, cached := s.initSyncState[headRoot]
|
||||
if !cached && !s.beaconDB.HasState(ctx, headRoot) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Get the new head block from DB.
|
||||
@@ -74,15 +81,19 @@ func (s *Service) saveHead(ctx context.Context, headRoot [32]byte) error {
|
||||
|
||||
// Get the new head state from cached state or DB.
|
||||
var newHeadState *state.BeaconState
|
||||
var exists bool
|
||||
newHeadState, exists = s.initSyncState[headRoot]
|
||||
if !exists {
|
||||
newHeadState, err = s.beaconDB.State(ctx, headRoot)
|
||||
if !featureconfig.Get().DisableNewStateMgmt {
|
||||
newHeadState, err = s.stateGen.StateByRoot(ctx, headRoot)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not retrieve head state in DB")
|
||||
}
|
||||
if newHeadState == nil {
|
||||
return errors.New("cannot save nil head state")
|
||||
} else {
|
||||
var exists bool
|
||||
newHeadState, exists = s.initSyncState[headRoot]
|
||||
if !exists {
|
||||
newHeadState, err = s.beaconDB.State(ctx, headRoot)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not retrieve head state in DB")
|
||||
}
|
||||
}
|
||||
}
|
||||
if newHeadState == nil {
|
||||
@@ -108,19 +119,27 @@ func (s *Service) saveHeadNoDB(ctx context.Context, b *ethpb.SignedBeaconBlock,
|
||||
return errors.New("cannot save nil head block")
|
||||
}
|
||||
|
||||
headState, err := s.beaconDB.State(ctx, r)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not retrieve head state in DB")
|
||||
}
|
||||
if headState == nil {
|
||||
s.initSyncStateLock.RLock()
|
||||
cachedHeadState, ok := s.initSyncState[r]
|
||||
if ok {
|
||||
headState = cachedHeadState
|
||||
var headState *state.BeaconState
|
||||
var err error
|
||||
if !featureconfig.Get().DisableNewStateMgmt {
|
||||
headState, err = s.stateGen.StateByRoot(ctx, r)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not retrieve head state in DB")
|
||||
}
|
||||
} else {
|
||||
headState, err = s.beaconDB.State(ctx, r)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not retrieve head state in DB")
|
||||
}
|
||||
if headState == nil {
|
||||
s.initSyncStateLock.RLock()
|
||||
cachedHeadState, ok := s.initSyncState[r]
|
||||
if ok {
|
||||
headState = cachedHeadState
|
||||
}
|
||||
s.initSyncStateLock.RUnlock()
|
||||
}
|
||||
s.initSyncStateLock.RUnlock()
|
||||
}
|
||||
|
||||
if headState == nil {
|
||||
return errors.New("nil head state")
|
||||
}
|
||||
|
||||
@@ -9,8 +9,8 @@ import (
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/go-ssz"
|
||||
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
)
|
||||
|
||||
func TestSaveHead_Same(t *testing.T) {
|
||||
@@ -44,10 +44,24 @@ func TestSaveHead_Different(t *testing.T) {
|
||||
|
||||
newHeadBlock := ðpb.BeaconBlock{Slot: 1}
|
||||
newHeadSignedBlock := ðpb.SignedBeaconBlock{Block: newHeadBlock}
|
||||
service.beaconDB.SaveBlock(context.Background(), newHeadSignedBlock)
|
||||
newRoot, _ := ssz.HashTreeRoot(newHeadBlock)
|
||||
headState, _ := state.InitializeFromProto(&pb.BeaconState{Slot: 1})
|
||||
service.beaconDB.SaveState(context.Background(), headState, newRoot)
|
||||
|
||||
if err := service.beaconDB.SaveBlock(context.Background(), newHeadSignedBlock); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
newRoot, err := ssz.HashTreeRoot(newHeadBlock)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
headState := testutil.NewBeaconState()
|
||||
if err := headState.SetSlot(1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := service.beaconDB.SaveStateSummary(context.Background(), &pb.StateSummary{Slot: 1, Root: newRoot[:]}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := service.beaconDB.SaveState(context.Background(), headState, newRoot); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := service.saveHead(context.Background(), newRoot); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -5,9 +5,11 @@ import (
|
||||
"sort"
|
||||
|
||||
"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/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
|
||||
@@ -168,12 +170,29 @@ func (s *Service) generateState(ctx context.Context, startRoot [32]byte, endRoot
|
||||
return nil, err
|
||||
}
|
||||
if preState == nil {
|
||||
return nil, errors.New("finalized state does not exist in db")
|
||||
preState, err = s.stateGen.StateByRoot(ctx, startRoot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if preState == nil {
|
||||
return nil, errors.New("finalized state does not exist in db")
|
||||
}
|
||||
}
|
||||
endBlock, err := s.beaconDB.Block(ctx, endRoot)
|
||||
if err != nil {
|
||||
|
||||
if err := s.beaconDB.SaveBlocks(ctx, s.getInitSyncBlocks()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var endBlock *ethpb.SignedBeaconBlock
|
||||
if !featureconfig.Get().NoInitSyncBatchSaveBlocks && s.hasInitSyncBlock(endRoot) {
|
||||
endBlock = s.getInitSyncBlock(endRoot)
|
||||
s.clearInitSyncBlocks()
|
||||
} else {
|
||||
endBlock, err = s.beaconDB.Block(ctx, endRoot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if endBlock == nil {
|
||||
return nil, errors.New("provided block root does not have block saved in the db")
|
||||
}
|
||||
@@ -189,3 +208,48 @@ func (s *Service) generateState(ctx context.Context, startRoot [32]byte, endRoot
|
||||
}
|
||||
return postState, nil
|
||||
}
|
||||
|
||||
// This saves a beacon block to the initial sync blocks cache.
|
||||
func (s *Service) saveInitSyncBlock(r [32]byte, b *ethpb.SignedBeaconBlock) {
|
||||
s.initSyncBlocksLock.Lock()
|
||||
defer s.initSyncBlocksLock.Unlock()
|
||||
s.initSyncBlocks[r] = b
|
||||
}
|
||||
|
||||
// This checks if a beacon block exists in the initial sync blocks cache using the root
|
||||
// of the block.
|
||||
func (s *Service) hasInitSyncBlock(r [32]byte) bool {
|
||||
s.initSyncBlocksLock.RLock()
|
||||
defer s.initSyncBlocksLock.RUnlock()
|
||||
_, ok := s.initSyncBlocks[r]
|
||||
return ok
|
||||
}
|
||||
|
||||
// This retrieves a beacon block from the initial sync blocks cache using the root of
|
||||
// the block.
|
||||
func (s *Service) getInitSyncBlock(r [32]byte) *ethpb.SignedBeaconBlock {
|
||||
s.initSyncBlocksLock.RLock()
|
||||
defer s.initSyncBlocksLock.RUnlock()
|
||||
b := s.initSyncBlocks[r]
|
||||
return b
|
||||
}
|
||||
|
||||
// This retrieves all the beacon blocks from the initial sync blocks cache, the returned
|
||||
// blocks are unordered.
|
||||
func (s *Service) getInitSyncBlocks() []*ethpb.SignedBeaconBlock {
|
||||
s.initSyncBlocksLock.RLock()
|
||||
defer s.initSyncBlocksLock.RUnlock()
|
||||
|
||||
blks := make([]*ethpb.SignedBeaconBlock, 0, len(s.initSyncBlocks))
|
||||
for _, b := range s.initSyncBlocks {
|
||||
blks = append(blks, b)
|
||||
}
|
||||
return blks
|
||||
}
|
||||
|
||||
// This clears out the initial sync blocks cache.
|
||||
func (s *Service) clearInitSyncBlocks() {
|
||||
s.initSyncBlocksLock.Lock()
|
||||
defer s.initSyncBlocksLock.Unlock()
|
||||
s.initSyncBlocks = make(map[[32]byte]*ethpb.SignedBeaconBlock)
|
||||
}
|
||||
|
||||
@@ -6,16 +6,18 @@ import (
|
||||
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/go-ssz"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
|
||||
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
"gopkg.in/d4l3k/messagediff.v1"
|
||||
messagediff "gopkg.in/d4l3k/messagediff.v1"
|
||||
)
|
||||
|
||||
func TestFilterBoundaryCandidates_FilterCorrect(t *testing.T) {
|
||||
@@ -28,10 +30,15 @@ func TestFilterBoundaryCandidates_FilterCorrect(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
st, _ := stateTrie.InitializeFromProtoUnsafe(&pb.BeaconState{})
|
||||
st, err := stateTrie.InitializeFromProtoUnsafe(&pb.BeaconState{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for i := uint64(0); i < 500; i++ {
|
||||
st.SetSlot(i)
|
||||
if err := st.SetSlot(i); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
root := [32]byte{}
|
||||
copy(root[:], bytesutil.Bytes32(i))
|
||||
service.initSyncState[root] = st.Copy()
|
||||
@@ -41,14 +48,18 @@ func TestFilterBoundaryCandidates_FilterCorrect(t *testing.T) {
|
||||
}
|
||||
lastIndex := len(service.boundaryRoots) - 1
|
||||
for i := uint64(500); i < 2000; i++ {
|
||||
st.SetSlot(i)
|
||||
if err := st.SetSlot(i); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
root := [32]byte{}
|
||||
copy(root[:], bytesutil.Bytes32(i))
|
||||
service.initSyncState[root] = st.Copy()
|
||||
}
|
||||
// Set current state.
|
||||
latestSlot := helpers.RoundUpToNearestEpoch(2000)
|
||||
st.SetSlot(latestSlot)
|
||||
if err := st.SetSlot(latestSlot); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
lastRoot := [32]byte{}
|
||||
copy(lastRoot[:], bytesutil.Bytes32(latestSlot))
|
||||
|
||||
@@ -83,10 +94,15 @@ func TestFilterBoundaryCandidates_HandleSkippedSlots(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
st, _ := stateTrie.InitializeFromProtoUnsafe(&pb.BeaconState{})
|
||||
st, err := stateTrie.InitializeFromProtoUnsafe(&pb.BeaconState{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for i := uint64(0); i < 500; i++ {
|
||||
st.SetSlot(i)
|
||||
if err := st.SetSlot(i); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
root := [32]byte{}
|
||||
copy(root[:], bytesutil.Bytes32(i))
|
||||
service.initSyncState[root] = st.Copy()
|
||||
@@ -96,7 +112,9 @@ func TestFilterBoundaryCandidates_HandleSkippedSlots(t *testing.T) {
|
||||
}
|
||||
lastIndex := len(service.boundaryRoots) - 1
|
||||
for i := uint64(500); i < 2000; i++ {
|
||||
st.SetSlot(i)
|
||||
if err := st.SetSlot(i); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
root := [32]byte{}
|
||||
copy(root[:], bytesutil.Bytes32(i))
|
||||
// save only for offsetted slots
|
||||
@@ -106,7 +124,9 @@ func TestFilterBoundaryCandidates_HandleSkippedSlots(t *testing.T) {
|
||||
}
|
||||
// Set current state.
|
||||
latestSlot := helpers.RoundUpToNearestEpoch(2000)
|
||||
st.SetSlot(latestSlot)
|
||||
if err := st.SetSlot(latestSlot); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
lastRoot := [32]byte{}
|
||||
copy(lastRoot[:], bytesutil.Bytes32(latestSlot))
|
||||
|
||||
@@ -148,10 +168,15 @@ func TestPruneOldStates_AlreadyFinalized(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
st, _ := stateTrie.InitializeFromProtoUnsafe(&pb.BeaconState{})
|
||||
st, err := stateTrie.InitializeFromProtoUnsafe(&pb.BeaconState{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for i := uint64(100); i < 200; i++ {
|
||||
st.SetSlot(i)
|
||||
if err := st.SetSlot(i); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
root := [32]byte{}
|
||||
copy(root[:], bytesutil.Bytes32(i))
|
||||
service.initSyncState[root] = st.Copy()
|
||||
@@ -182,10 +207,15 @@ func TestPruneNonBoundary_CanPrune(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
st, _ := stateTrie.InitializeFromProtoUnsafe(&pb.BeaconState{})
|
||||
st, err := stateTrie.InitializeFromProtoUnsafe(&pb.BeaconState{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for i := uint64(0); i < 2000; i++ {
|
||||
st.SetSlot(i)
|
||||
if err := st.SetSlot(i); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
root := [32]byte{}
|
||||
copy(root[:], bytesutil.Bytes32(i))
|
||||
service.initSyncState[root] = st.Copy()
|
||||
@@ -209,7 +239,7 @@ func TestPruneNonBoundary_CanPrune(t *testing.T) {
|
||||
func TestGenerateState_CorrectlyGenerated(t *testing.T) {
|
||||
db := testDB.SetupDB(t)
|
||||
defer testDB.TeardownDB(t, db)
|
||||
cfg := &Config{BeaconDB: db}
|
||||
cfg := &Config{BeaconDB: db, StateGen: stategen.New(db, cache.NewStateSummaryCache())}
|
||||
service, err := NewService(context.Background(), cfg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -221,19 +251,28 @@ func TestGenerateState_CorrectlyGenerated(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
beaconState.SetLatestBlockHeader(ðpb.BeaconBlockHeader{
|
||||
err = beaconState.SetLatestBlockHeader(ðpb.BeaconBlockHeader{
|
||||
Slot: genesisBlock.Block.Slot,
|
||||
ParentRoot: genesisBlock.Block.ParentRoot,
|
||||
StateRoot: params.BeaconConfig().ZeroHash[:],
|
||||
BodyRoot: bodyRoot[:],
|
||||
})
|
||||
beaconState.SetSlashings(make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := beaconState.SetSlashings(make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cp := beaconState.CurrentJustifiedCheckpoint()
|
||||
mockRoot := [32]byte{}
|
||||
copy(mockRoot[:], "hello-world")
|
||||
cp.Root = mockRoot[:]
|
||||
beaconState.SetCurrentJustifiedCheckpoint(cp)
|
||||
beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{})
|
||||
if err := beaconState.SetCurrentJustifiedCheckpoint(cp); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = db.SaveBlock(context.Background(), genesisBlock)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
@@ -19,6 +19,8 @@ func logStateTransitionData(b *ethpb.BeaconBlock) {
|
||||
"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")
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ package blockchain
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
@@ -11,6 +10,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/flags"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/roughtime"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
@@ -71,6 +71,16 @@ func (s *Service) onAttestation(ctx context.Context, a *ethpb.Attestation) ([]ui
|
||||
ctx, span := trace.StartSpan(ctx, "blockchain.onAttestation")
|
||||
defer span.End()
|
||||
|
||||
if a == nil {
|
||||
return nil, errors.New("nil attestation")
|
||||
}
|
||||
if a.Data == nil {
|
||||
return nil, errors.New("nil attestation.Data field")
|
||||
}
|
||||
if a.Data.Target == nil {
|
||||
return nil, errors.New("nil attestation.Data.Target field")
|
||||
}
|
||||
|
||||
tgt := stateTrie.CopyCheckpoint(a.Data.Target)
|
||||
tgtSlot := helpers.StartSlot(tgt.Epoch)
|
||||
|
||||
@@ -93,12 +103,12 @@ func (s *Service) onAttestation(ctx context.Context, a *ethpb.Attestation) ([]ui
|
||||
genesisTime := baseState.GenesisTime()
|
||||
|
||||
// Verify attestation target is from current epoch or previous epoch.
|
||||
if err := s.verifyAttTargetEpoch(ctx, genesisTime, uint64(time.Now().Unix()), tgt); err != nil {
|
||||
if err := s.verifyAttTargetEpoch(ctx, genesisTime, uint64(roughtime.Now().Unix()), tgt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Verify Attestations cannot be from future epochs.
|
||||
if err := helpers.VerifySlotTime(genesisTime, tgtSlot); err != nil {
|
||||
if err := helpers.VerifySlotTime(genesisTime, tgtSlot, helpers.TimeShiftTolerance); err != nil {
|
||||
return nil, errors.Wrap(err, "could not verify attestation target slot")
|
||||
}
|
||||
|
||||
@@ -108,7 +118,7 @@ func (s *Service) onAttestation(ctx context.Context, a *ethpb.Attestation) ([]ui
|
||||
}
|
||||
|
||||
// Verify attestations can only affect the fork choice of subsequent slots.
|
||||
if err := helpers.VerifySlotTime(genesisTime, a.Data.Slot+1); err != nil {
|
||||
if err := helpers.VerifySlotTime(genesisTime, a.Data.Slot, helpers.TimeShiftTolerance); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -125,6 +135,10 @@ func (s *Service) onAttestation(ctx context.Context, a *ethpb.Attestation) ([]ui
|
||||
}
|
||||
}
|
||||
|
||||
if indexedAtt.AttestingIndices == nil {
|
||||
return nil, errors.New("nil attesting indices")
|
||||
}
|
||||
|
||||
// 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)
|
||||
|
||||
|
||||
@@ -30,30 +30,40 @@ func (s *Service) getAttPreState(ctx context.Context, c *ethpb.Checkpoint) (*sta
|
||||
if cachedState != nil {
|
||||
return cachedState, nil
|
||||
}
|
||||
if featureconfig.Get().CheckHeadState {
|
||||
headRoot, err := s.HeadRoot(ctx)
|
||||
|
||||
var baseState *stateTrie.BeaconState
|
||||
if !featureconfig.Get().DisableNewStateMgmt {
|
||||
baseState, err = s.stateGen.StateByRoot(ctx, bytesutil.ToBytes32(c.Root))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get head root")
|
||||
return nil, errors.Wrapf(err, "could not get pre state for slot %d", helpers.StartSlot(c.Epoch))
|
||||
}
|
||||
if bytes.Equal(headRoot, c.Root) {
|
||||
st, err := s.HeadState(ctx)
|
||||
} else {
|
||||
if featureconfig.Get().CheckHeadState {
|
||||
headRoot, err := s.HeadRoot(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get head state")
|
||||
return nil, errors.Wrapf(err, "could not get head root")
|
||||
}
|
||||
if err := s.checkpointState.AddCheckpointState(&cache.CheckpointState{
|
||||
Checkpoint: c,
|
||||
State: st.Copy(),
|
||||
}); err != nil {
|
||||
return nil, errors.Wrap(err, "could not saved checkpoint state to cache")
|
||||
if bytes.Equal(headRoot, c.Root) {
|
||||
st, err := s.HeadState(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get head state")
|
||||
}
|
||||
if err := s.checkpointState.AddCheckpointState(&cache.CheckpointState{
|
||||
Checkpoint: c,
|
||||
State: st.Copy(),
|
||||
}); err != nil {
|
||||
return nil, errors.Wrap(err, "could not saved checkpoint state to cache")
|
||||
}
|
||||
return st, nil
|
||||
}
|
||||
return st, nil
|
||||
}
|
||||
|
||||
baseState, err = s.beaconDB.State(ctx, bytesutil.ToBytes32(c.Root))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get pre state for slot %d", helpers.StartSlot(c.Epoch))
|
||||
}
|
||||
}
|
||||
|
||||
baseState, err := s.beaconDB.State(ctx, bytesutil.ToBytes32(c.Root))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get pre state for slot %d", helpers.StartSlot(c.Epoch))
|
||||
}
|
||||
if baseState == nil {
|
||||
return nil, fmt.Errorf("pre state of target block %d does not exist", helpers.StartSlot(c.Epoch))
|
||||
}
|
||||
@@ -100,7 +110,7 @@ func (s *Service) verifyBeaconBlock(ctx context.Context, data *ethpb.Attestation
|
||||
return fmt.Errorf("beacon block %#x does not exist", bytesutil.Trunc(data.BeaconBlockRoot))
|
||||
}
|
||||
if b.Block.Slot > data.Slot {
|
||||
return fmt.Errorf("could not process attestation for future block, %d > %d", b.Block.Slot, data.Slot)
|
||||
return fmt.Errorf("could not process attestation for future block, block.Slot=%d > attestation.Data.Slot=%d", b.Block.Slot, data.Slot)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -111,18 +121,26 @@ func (s *Service) verifyAttestation(ctx context.Context, baseState *stateTrie.Be
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
indexedAtt, err := attestationutil.ConvertToIndexed(ctx, a, committee)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not convert attestation to indexed attestation")
|
||||
}
|
||||
|
||||
indexedAtt := attestationutil.ConvertToIndexed(ctx, a, committee)
|
||||
if err := blocks.VerifyIndexedAttestation(ctx, baseState, indexedAtt); err != nil {
|
||||
if err == blocks.ErrSigFailedToVerify {
|
||||
if err == helpers.ErrSigFailedToVerify {
|
||||
// When sig fails to verify, check if there's a differences in committees due to
|
||||
// different seeds.
|
||||
aState, err := s.beaconDB.State(ctx, bytesutil.ToBytes32(a.Data.BeaconBlockRoot))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var aState *stateTrie.BeaconState
|
||||
var err error
|
||||
if !featureconfig.Get().DisableNewStateMgmt {
|
||||
aState, err = s.stateGen.StateByRoot(ctx, bytesutil.ToBytes32(a.Data.BeaconBlockRoot))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
aState, err = s.beaconDB.State(ctx, bytesutil.ToBytes32(a.Data.BeaconBlockRoot))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if aState == nil {
|
||||
return nil, fmt.Errorf("nil state for block root %#x", a.Data.BeaconBlockRoot)
|
||||
}
|
||||
epoch := helpers.SlotToEpoch(a.Data.Slot)
|
||||
origSeed, err := helpers.Seed(baseState, epoch, params.BeaconConfig().DomainBeaconAttester)
|
||||
|
||||
@@ -2,18 +2,19 @@ package blockchain
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/go-ssz"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
|
||||
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
|
||||
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
@@ -25,7 +26,11 @@ func TestStore_OnAttestation(t *testing.T) {
|
||||
db := testDB.SetupDB(t)
|
||||
defer testDB.TeardownDB(t, db)
|
||||
|
||||
cfg := &Config{BeaconDB: db, ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}
|
||||
cfg := &Config{
|
||||
BeaconDB: db,
|
||||
ForkChoiceStore: protoarray.New(0, 0, [32]byte{}),
|
||||
StateGen: stategen.New(db, cache.NewStateSummaryCache()),
|
||||
}
|
||||
service, err := NewService(ctx, cfg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -40,15 +45,21 @@ func TestStore_OnAttestation(t *testing.T) {
|
||||
if err := db.SaveBlock(ctx, BlkWithOutState); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
BlkWithOutStateRoot, _ := ssz.HashTreeRoot(BlkWithOutState.Block)
|
||||
BlkWithOutStateRoot, err := ssz.HashTreeRoot(BlkWithOutState.Block)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
BlkWithStateBadAtt := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 1}}
|
||||
if err := db.SaveBlock(ctx, BlkWithStateBadAtt); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
BlkWithStateBadAttRoot, _ := ssz.HashTreeRoot(BlkWithStateBadAtt.Block)
|
||||
BlkWithStateBadAttRoot, err := ssz.HashTreeRoot(BlkWithStateBadAtt.Block)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
s, err := beaconstate.InitializeFromProto(&pb.BeaconState{})
|
||||
s := testutil.NewBeaconState()
|
||||
if err := s.SetSlot(100 * params.BeaconConfig().SlotsPerEpoch); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -60,15 +71,19 @@ func TestStore_OnAttestation(t *testing.T) {
|
||||
if err := db.SaveBlock(ctx, BlkWithValidState); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
BlkWithValidStateRoot, _ := ssz.HashTreeRoot(BlkWithValidState.Block)
|
||||
s, _ = stateTrie.InitializeFromProto(&pb.BeaconState{
|
||||
Fork: &pb.Fork{
|
||||
Epoch: 0,
|
||||
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
|
||||
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
|
||||
},
|
||||
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
|
||||
})
|
||||
|
||||
BlkWithValidStateRoot, err := ssz.HashTreeRoot(BlkWithValidState.Block)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
s = testutil.NewBeaconState()
|
||||
if err := s.SetFork(&pb.Fork{
|
||||
Epoch: 0,
|
||||
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
|
||||
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := service.beaconDB.SaveState(ctx, s, BlkWithValidStateRoot); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -99,7 +114,7 @@ func TestStore_OnAttestation(t *testing.T) {
|
||||
a: ðpb.Attestation{Data: ðpb.AttestationData{Target: ðpb.Checkpoint{Root: BlkWithOutStateRoot[:]}}},
|
||||
s: &pb.BeaconState{},
|
||||
wantErr: true,
|
||||
wantErrString: "pre state of target block 0 does not exist",
|
||||
wantErrString: "could not get pre state for slot 0: could not get state summary",
|
||||
},
|
||||
{
|
||||
name: "process attestation doesn't match current epoch",
|
||||
@@ -109,13 +124,34 @@ func TestStore_OnAttestation(t *testing.T) {
|
||||
wantErr: true,
|
||||
wantErrString: "does not match current epoch",
|
||||
},
|
||||
{
|
||||
name: "process nil field (a.Target) in attestation",
|
||||
a: nil,
|
||||
s: &pb.BeaconState{},
|
||||
wantErr: true,
|
||||
wantErrString: "nil attestation",
|
||||
},
|
||||
{
|
||||
name: "process nil field (a.Data) in attestation",
|
||||
a: ðpb.Attestation{},
|
||||
s: &pb.BeaconState{},
|
||||
wantErr: true,
|
||||
wantErrString: "nil attestation.Data field",
|
||||
},
|
||||
{
|
||||
name: "process nil field (a.Target) in attestation",
|
||||
a: ðpb.Attestation{Data: ðpb.AttestationData{}},
|
||||
s: &pb.BeaconState{},
|
||||
wantErr: true,
|
||||
wantErrString: "nil attestation.Data.Target field",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
_, err := service.onAttestation(ctx, tt.a)
|
||||
if tt.wantErr {
|
||||
if !strings.Contains(err.Error(), tt.wantErrString) {
|
||||
if err == nil || !strings.Contains(err.Error(), tt.wantErrString) {
|
||||
t.Errorf("Store.onAttestation() error = %v, wantErr = %v", err, tt.wantErrString)
|
||||
}
|
||||
} else {
|
||||
@@ -129,15 +165,17 @@ func TestStore_SaveCheckpointState(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
db := testDB.SetupDB(t)
|
||||
defer testDB.TeardownDB(t, db)
|
||||
params.UseDemoBeaconConfig()
|
||||
|
||||
cfg := &Config{BeaconDB: db}
|
||||
cfg := &Config{
|
||||
BeaconDB: db,
|
||||
StateGen: stategen.New(db, cache.NewStateSummaryCache()),
|
||||
}
|
||||
service, err := NewService(ctx, cfg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
s, _ := stateTrie.InitializeFromProto(&pb.BeaconState{
|
||||
s, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
||||
Fork: &pb.Fork{
|
||||
Epoch: 0,
|
||||
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
|
||||
@@ -149,19 +187,31 @@ func TestStore_SaveCheckpointState(t *testing.T) {
|
||||
LatestBlockHeader: ðpb.BeaconBlockHeader{},
|
||||
JustificationBits: []byte{0},
|
||||
Slashings: make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector),
|
||||
FinalizedCheckpoint: ðpb.Checkpoint{},
|
||||
FinalizedCheckpoint: ðpb.Checkpoint{Root: bytesutil.PadTo([]byte{'A'}, 32)},
|
||||
Validators: []*ethpb.Validator{{PublicKey: bytesutil.PadTo([]byte("foo"), 48)}},
|
||||
Balances: []uint64{0},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
r := [32]byte{'g'}
|
||||
if err := service.beaconDB.SaveState(ctx, s, r); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
service.justifiedCheckpt = ðpb.Checkpoint{Root: r[:]}
|
||||
service.bestJustifiedCheckpt = ðpb.Checkpoint{Root: r[:]}
|
||||
service.finalizedCheckpt = ðpb.Checkpoint{Root: r[:]}
|
||||
service.prevFinalizedCheckpt = ðpb.Checkpoint{Root: r[:]}
|
||||
|
||||
cp1 := ðpb.Checkpoint{Epoch: 1, Root: []byte{'A'}}
|
||||
service.beaconDB.SaveState(ctx, s, bytesutil.ToBytes32([]byte{'A'}))
|
||||
r = bytesutil.ToBytes32([]byte{'A'})
|
||||
cp1 := ðpb.Checkpoint{Epoch: 1, Root: bytesutil.PadTo([]byte{'A'}, 32)}
|
||||
if err := service.beaconDB.SaveState(ctx, s, bytesutil.ToBytes32([]byte{'A'})); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := service.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{Root: bytesutil.PadTo([]byte{'A'}, 32)}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
s1, err := service.getAttPreState(ctx, cp1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -170,8 +220,13 @@ func TestStore_SaveCheckpointState(t *testing.T) {
|
||||
t.Errorf("Wanted state slot: %d, got: %d", 1*params.BeaconConfig().SlotsPerEpoch, s1.Slot())
|
||||
}
|
||||
|
||||
cp2 := ðpb.Checkpoint{Epoch: 2, Root: []byte{'B'}}
|
||||
service.beaconDB.SaveState(ctx, s, bytesutil.ToBytes32([]byte{'B'}))
|
||||
cp2 := ðpb.Checkpoint{Epoch: 2, Root: bytesutil.PadTo([]byte{'B'}, 32)}
|
||||
if err := service.beaconDB.SaveState(ctx, s, bytesutil.ToBytes32([]byte{'B'})); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := service.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{Root: bytesutil.PadTo([]byte{'B'}, 32)}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
s2, err := service.getAttPreState(ctx, cp2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -204,13 +259,20 @@ func TestStore_SaveCheckpointState(t *testing.T) {
|
||||
t.Errorf("Wanted state slot: %d, got: %d", 2*params.BeaconConfig().SlotsPerEpoch, s2.Slot())
|
||||
}
|
||||
|
||||
s.SetSlot(params.BeaconConfig().SlotsPerEpoch + 1)
|
||||
if err := s.SetSlot(params.BeaconConfig().SlotsPerEpoch + 1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
service.justifiedCheckpt = ðpb.Checkpoint{Root: r[:]}
|
||||
service.bestJustifiedCheckpt = ðpb.Checkpoint{Root: r[:]}
|
||||
service.finalizedCheckpt = ðpb.Checkpoint{Root: r[:]}
|
||||
service.prevFinalizedCheckpt = ðpb.Checkpoint{Root: r[:]}
|
||||
cp3 := ðpb.Checkpoint{Epoch: 1, Root: []byte{'C'}}
|
||||
service.beaconDB.SaveState(ctx, s, bytesutil.ToBytes32([]byte{'C'}))
|
||||
cp3 := ðpb.Checkpoint{Epoch: 1, Root: bytesutil.PadTo([]byte{'C'}, 32)}
|
||||
if err := service.beaconDB.SaveState(ctx, s, bytesutil.ToBytes32([]byte{'C'})); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := service.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{Root: bytesutil.PadTo([]byte{'C'}, 32)}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
s3, err := service.getAttPreState(ctx, cp3)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -225,7 +287,10 @@ func TestStore_UpdateCheckpointState(t *testing.T) {
|
||||
db := testDB.SetupDB(t)
|
||||
defer testDB.TeardownDB(t, db)
|
||||
|
||||
cfg := &Config{BeaconDB: db}
|
||||
cfg := &Config{
|
||||
BeaconDB: db,
|
||||
StateGen: stategen.New(db, cache.NewStateSummaryCache()),
|
||||
}
|
||||
service, err := NewService(ctx, cfg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -233,9 +298,13 @@ func TestStore_UpdateCheckpointState(t *testing.T) {
|
||||
|
||||
epoch := uint64(1)
|
||||
baseState, _ := testutil.DeterministicGenesisState(t, 1)
|
||||
baseState.SetSlot(epoch * params.BeaconConfig().SlotsPerEpoch)
|
||||
if err := baseState.SetSlot(epoch * params.BeaconConfig().SlotsPerEpoch); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
checkpoint := ðpb.Checkpoint{Epoch: epoch}
|
||||
service.beaconDB.SaveState(ctx, baseState, bytesutil.ToBytes32(checkpoint.Root))
|
||||
if err := service.beaconDB.SaveState(ctx, baseState, bytesutil.ToBytes32(checkpoint.Root)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
returned, err := service.getAttPreState(ctx, checkpoint)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -254,7 +323,9 @@ func TestStore_UpdateCheckpointState(t *testing.T) {
|
||||
|
||||
epoch = uint64(2)
|
||||
newCheckpoint := ðpb.Checkpoint{Epoch: epoch}
|
||||
service.beaconDB.SaveState(ctx, baseState, bytesutil.ToBytes32(newCheckpoint.Root))
|
||||
if err := service.beaconDB.SaveState(ctx, baseState, bytesutil.ToBytes32(newCheckpoint.Root)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
returned, err = service.getAttPreState(ctx, newCheckpoint)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -271,7 +342,7 @@ func TestStore_UpdateCheckpointState(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(returned, cached) {
|
||||
if !proto.Equal(returned.InnerStateUnsafe(), cached.InnerStateUnsafe()) {
|
||||
t.Error("Incorrectly cached base state")
|
||||
}
|
||||
}
|
||||
@@ -366,11 +437,17 @@ func TestVerifyBeaconBlock_futureBlock(t *testing.T) {
|
||||
}
|
||||
|
||||
b := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 2}}
|
||||
service.beaconDB.SaveBlock(ctx, b)
|
||||
r, _ := ssz.HashTreeRoot(b.Block)
|
||||
if err := service.beaconDB.SaveBlock(ctx, b); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
r, err := ssz.HashTreeRoot(b.Block)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
d := ðpb.AttestationData{Slot: 1, BeaconBlockRoot: r[:]}
|
||||
|
||||
if err := service.verifyBeaconBlock(ctx, d); !strings.Contains(err.Error(), "could not process attestation for future block") {
|
||||
err = service.verifyBeaconBlock(ctx, d)
|
||||
if err == nil || !strings.Contains(err.Error(), "could not process attestation for future block") {
|
||||
t.Error("Did not receive the wanted error")
|
||||
}
|
||||
}
|
||||
@@ -387,8 +464,13 @@ func TestVerifyBeaconBlock_OK(t *testing.T) {
|
||||
}
|
||||
|
||||
b := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 2}}
|
||||
service.beaconDB.SaveBlock(ctx, b)
|
||||
r, _ := ssz.HashTreeRoot(b.Block)
|
||||
if err := service.beaconDB.SaveBlock(ctx, b); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
r, err := ssz.HashTreeRoot(b.Block)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
d := ðpb.AttestationData{Slot: 2, BeaconBlockRoot: r[:]}
|
||||
|
||||
if err := service.verifyBeaconBlock(ctx, d); err != nil {
|
||||
|
||||
@@ -7,17 +7,22 @@ import (
|
||||
|
||||
"github.com/pkg/errors"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/go-ssz"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/flags"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
"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/sirupsen/logrus"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
// This defines size of the upper bound for initial sync block cache.
|
||||
var initialSyncBlockCacheSize = 2 * params.BeaconConfig().SlotsPerEpoch
|
||||
|
||||
// onBlock is called when a gossip block is received. It runs regular state transition on the block.
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
@@ -64,9 +69,8 @@ func (s *Service) onBlock(ctx context.Context, signed *ethpb.SignedBeaconBlock)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
preStateValidatorCount := preState.NumValidators()
|
||||
|
||||
root, err := ssz.HashTreeRoot(b)
|
||||
root, err := stateutil.BlockRoot(b)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get signing root of block %d", b.Slot)
|
||||
}
|
||||
@@ -88,8 +92,14 @@ func (s *Service) onBlock(ctx context.Context, signed *ethpb.SignedBeaconBlock)
|
||||
return nil, errors.Wrapf(err, "could not insert block %d to fork choice store", b.Slot)
|
||||
}
|
||||
|
||||
if err := s.beaconDB.SaveState(ctx, postState, root); err != nil {
|
||||
return nil, errors.Wrap(err, "could not save state")
|
||||
if !featureconfig.Get().DisableNewStateMgmt {
|
||||
if err := s.stateGen.SaveState(ctx, root, postState); err != nil {
|
||||
return nil, errors.Wrap(err, "could not save state")
|
||||
}
|
||||
} else {
|
||||
if err := s.beaconDB.SaveState(ctx, postState, root); err != nil {
|
||||
return nil, errors.Wrap(err, "could not save state")
|
||||
}
|
||||
}
|
||||
|
||||
// Update justified check point.
|
||||
@@ -101,22 +111,34 @@ func (s *Service) onBlock(ctx context.Context, signed *ethpb.SignedBeaconBlock)
|
||||
|
||||
// Update finalized check point. Prune the block cache and helper caches on every new finalized epoch.
|
||||
if postState.FinalizedCheckpointEpoch() > s.finalizedCheckpt.Epoch {
|
||||
if !featureconfig.Get().NoInitSyncBatchSaveBlocks {
|
||||
if err := s.beaconDB.SaveBlocks(ctx, s.getInitSyncBlocks()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.clearInitSyncBlocks()
|
||||
}
|
||||
|
||||
if err := s.beaconDB.SaveFinalizedCheckpoint(ctx, postState.FinalizedCheckpoint()); err != nil {
|
||||
return nil, errors.Wrap(err, "could not save finalized checkpoint")
|
||||
}
|
||||
|
||||
startSlot := helpers.StartSlot(s.prevFinalizedCheckpt.Epoch)
|
||||
endSlot := helpers.StartSlot(s.finalizedCheckpt.Epoch)
|
||||
if endSlot > startSlot {
|
||||
if err := s.rmStatesOlderThanLastFinalized(ctx, startSlot, endSlot); err != nil {
|
||||
return nil, errors.Wrapf(err, "could not delete states prior to finalized check point, range: %d, %d",
|
||||
startSlot, endSlot)
|
||||
if featureconfig.Get().DisableNewStateMgmt {
|
||||
startSlot := helpers.StartSlot(s.prevFinalizedCheckpt.Epoch)
|
||||
endSlot := helpers.StartSlot(s.finalizedCheckpt.Epoch)
|
||||
if endSlot > startSlot {
|
||||
if err := s.rmStatesOlderThanLastFinalized(ctx, startSlot, endSlot); err != nil {
|
||||
return nil, errors.Wrapf(err, "could not delete states prior to finalized check point, range: %d, %d",
|
||||
startSlot, endSlot)
|
||||
}
|
||||
}
|
||||
}
|
||||
fRoot := bytesutil.ToBytes32(postState.FinalizedCheckpoint().Root)
|
||||
|
||||
// Prune proto array fork choice nodes, all nodes before finalized check point will
|
||||
// be pruned.
|
||||
s.forkChoiceStore.Prune(ctx, bytesutil.ToBytes32(postState.FinalizedCheckpoint().Root))
|
||||
if err := s.forkChoiceStore.Prune(ctx, fRoot); err != nil {
|
||||
return nil, errors.Wrap(err, "could not prune proto array fork choice nodes")
|
||||
}
|
||||
|
||||
s.prevFinalizedCheckpt = s.finalizedCheckpt
|
||||
s.finalizedCheckpt = postState.FinalizedCheckpoint()
|
||||
@@ -124,11 +146,17 @@ func (s *Service) onBlock(ctx context.Context, signed *ethpb.SignedBeaconBlock)
|
||||
if err := s.finalizedImpliesNewJustified(ctx, postState); err != nil {
|
||||
return nil, errors.Wrap(err, "could not save new justified")
|
||||
}
|
||||
}
|
||||
|
||||
// Update validator indices in database as needed.
|
||||
if err := s.saveNewValidators(ctx, preStateValidatorCount, postState); err != nil {
|
||||
return nil, errors.Wrap(err, "could not save finalized checkpoint")
|
||||
if !featureconfig.Get().DisableNewStateMgmt {
|
||||
fRoot := bytesutil.ToBytes32(postState.FinalizedCheckpoint().Root)
|
||||
fBlock, err := s.beaconDB.Block(ctx, fRoot)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get finalized block to migrate")
|
||||
}
|
||||
if err := s.stateGen.MigrateToCold(ctx, fBlock.Block.Slot, fRoot); err != nil {
|
||||
return nil, errors.Wrap(err, "could not migrate to cold")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Epoch boundary bookkeeping such as logging epoch summaries.
|
||||
@@ -173,35 +201,48 @@ func (s *Service) onBlockInitialSyncStateTransition(ctx context.Context, signed
|
||||
|
||||
b := signed.Block
|
||||
|
||||
s.initSyncStateLock.Lock()
|
||||
defer s.initSyncStateLock.Unlock()
|
||||
|
||||
// Retrieve incoming block's pre state.
|
||||
preState, err := s.verifyBlkPreState(ctx, b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
preStateValidatorCount := preState.NumValidators()
|
||||
|
||||
// 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.ExecuteStateTransitionNoVerifyAttSigs(ctx, preState, signed)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not execute state transition")
|
||||
}
|
||||
|
||||
if err := s.beaconDB.SaveBlock(ctx, signed); err != nil {
|
||||
return errors.Wrapf(err, "could not save block from slot %d", b.Slot)
|
||||
}
|
||||
root, err := ssz.HashTreeRoot(b)
|
||||
root, err := stateutil.BlockRoot(b)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get signing root of block %d", b.Slot)
|
||||
}
|
||||
if !featureconfig.Get().NoInitSyncBatchSaveBlocks {
|
||||
s.saveInitSyncBlock(root, signed)
|
||||
} else {
|
||||
if err := s.beaconDB.SaveBlock(ctx, signed); err != nil {
|
||||
return errors.Wrapf(err, "could not save block from slot %d", b.Slot)
|
||||
}
|
||||
}
|
||||
|
||||
if err := s.insertBlockToForkChoiceStore(ctx, b, root, postState); err != nil {
|
||||
return errors.Wrapf(err, "could not insert block %d to fork choice store", b.Slot)
|
||||
}
|
||||
|
||||
s.initSyncState[root] = postState.Copy()
|
||||
s.filterBoundaryCandidates(ctx, root, postState)
|
||||
if !featureconfig.Get().DisableNewStateMgmt {
|
||||
if err := s.stateGen.SaveState(ctx, root, postState); err != nil {
|
||||
return errors.Wrap(err, "could not save state")
|
||||
}
|
||||
} else {
|
||||
s.initSyncStateLock.Lock()
|
||||
defer s.initSyncStateLock.Unlock()
|
||||
s.initSyncState[root] = postState.Copy()
|
||||
s.filterBoundaryCandidates(ctx, root, postState)
|
||||
}
|
||||
|
||||
if flags.Get().EnableArchive {
|
||||
atts := signed.Block.Body.Attestations
|
||||
@@ -217,19 +258,36 @@ func (s *Service) onBlockInitialSyncStateTransition(ctx context.Context, signed
|
||||
}
|
||||
}
|
||||
|
||||
// Rate limit how many blocks (2 epochs worth of blocks) a node keeps in the memory.
|
||||
if len(s.getInitSyncBlocks()) > int(initialSyncBlockCacheSize) {
|
||||
if err := s.beaconDB.SaveBlocks(ctx, s.getInitSyncBlocks()); err != nil {
|
||||
return err
|
||||
}
|
||||
s.clearInitSyncBlocks()
|
||||
}
|
||||
|
||||
// Update finalized check point. Prune the block cache and helper caches on every new finalized epoch.
|
||||
if postState.FinalizedCheckpointEpoch() > s.finalizedCheckpt.Epoch {
|
||||
startSlot := helpers.StartSlot(s.prevFinalizedCheckpt.Epoch)
|
||||
endSlot := helpers.StartSlot(s.finalizedCheckpt.Epoch)
|
||||
if endSlot > startSlot {
|
||||
if err := s.rmStatesOlderThanLastFinalized(ctx, startSlot, endSlot); err != nil {
|
||||
return errors.Wrapf(err, "could not delete states prior to finalized check point, range: %d, %d",
|
||||
startSlot, endSlot)
|
||||
if featureconfig.Get().DisableNewStateMgmt {
|
||||
startSlot := helpers.StartSlot(s.prevFinalizedCheckpt.Epoch)
|
||||
endSlot := helpers.StartSlot(s.finalizedCheckpt.Epoch)
|
||||
if endSlot > startSlot {
|
||||
if err := s.rmStatesOlderThanLastFinalized(ctx, startSlot, endSlot); err != nil {
|
||||
return errors.Wrapf(err, "could not delete states prior to finalized check point, range: %d, %d",
|
||||
startSlot, endSlot)
|
||||
}
|
||||
}
|
||||
|
||||
if err := s.saveInitState(ctx, postState); err != nil {
|
||||
return errors.Wrap(err, "could not save init sync finalized state")
|
||||
}
|
||||
}
|
||||
|
||||
if err := s.saveInitState(ctx, postState); err != nil {
|
||||
return errors.Wrap(err, "could not save init sync finalized state")
|
||||
if !featureconfig.Get().NoInitSyncBatchSaveBlocks {
|
||||
if err := s.beaconDB.SaveBlocks(ctx, s.getInitSyncBlocks()); err != nil {
|
||||
return err
|
||||
}
|
||||
s.clearInitSyncBlocks()
|
||||
}
|
||||
|
||||
if err := s.beaconDB.SaveFinalizedCheckpoint(ctx, postState.FinalizedCheckpoint()); err != nil {
|
||||
@@ -242,21 +300,29 @@ func (s *Service) onBlockInitialSyncStateTransition(ctx context.Context, signed
|
||||
if err := s.finalizedImpliesNewJustified(ctx, postState); err != nil {
|
||||
return errors.Wrap(err, "could not save new justified")
|
||||
}
|
||||
}
|
||||
|
||||
// Update validator indices in database as needed.
|
||||
if err := s.saveNewValidators(ctx, preStateValidatorCount, postState); err != nil {
|
||||
return errors.Wrap(err, "could not save finalized checkpoint")
|
||||
}
|
||||
|
||||
numOfStates := len(s.boundaryRoots)
|
||||
if numOfStates > initialSyncCacheSize {
|
||||
if err = s.persistCachedStates(ctx, numOfStates); err != nil {
|
||||
return err
|
||||
if !featureconfig.Get().DisableNewStateMgmt {
|
||||
fRoot := bytesutil.ToBytes32(postState.FinalizedCheckpoint().Root)
|
||||
fBlock, err := s.beaconDB.Block(ctx, fRoot)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get finalized block to migrate")
|
||||
}
|
||||
if err := s.stateGen.MigrateToCold(ctx, fBlock.Block.Slot, fRoot); err != nil {
|
||||
return errors.Wrap(err, "could not migrate to cold")
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(s.initSyncState) > maxCacheSize {
|
||||
s.pruneOldNonFinalizedStates()
|
||||
|
||||
if featureconfig.Get().DisableNewStateMgmt {
|
||||
numOfStates := len(s.boundaryRoots)
|
||||
if numOfStates > initialSyncCacheSize {
|
||||
if err = s.persistCachedStates(ctx, numOfStates); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if len(s.initSyncState) > maxCacheSize {
|
||||
s.pruneOldNonFinalizedStates()
|
||||
}
|
||||
}
|
||||
|
||||
// Epoch boundary bookkeeping such as logging epoch summaries.
|
||||
@@ -272,7 +338,7 @@ func (s *Service) onBlockInitialSyncStateTransition(ctx context.Context, signed
|
||||
return err
|
||||
}
|
||||
|
||||
if helpers.IsEpochStart(postState.Slot()) {
|
||||
if featureconfig.Get().DisableNewStateMgmt && helpers.IsEpochStart(postState.Slot()) {
|
||||
if err := s.beaconDB.SaveState(ctx, postState, root); err != nil {
|
||||
return errors.Wrap(err, "could not save state")
|
||||
}
|
||||
@@ -303,10 +369,7 @@ func (s *Service) insertBlockToForkChoiceStore(ctx context.Context, blk *ethpb.B
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
indices, err := attestationutil.AttestingIndices(a.AggregationBits, committee)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
indices := attestationutil.AttestingIndices(a.AggregationBits, committee)
|
||||
s.forkChoiceStore.ProcessAttestation(ctx, indices, bytesutil.ToBytes32(a.Data.BeaconBlockRoot), a.Data.Target.Epoch)
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
@@ -15,14 +14,19 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/roughtime"
|
||||
"github.com/prysmaticlabs/prysm/shared/traceutil"
|
||||
"github.com/sirupsen/logrus"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
// CurrentSlot returns the current slot based on time.
|
||||
func (s *Service) CurrentSlot() uint64 {
|
||||
return uint64(time.Now().Unix()-s.genesisTime.Unix()) / params.BeaconConfig().SecondsPerSlot
|
||||
now := roughtime.Now().Unix()
|
||||
genesis := s.genesisTime.Unix()
|
||||
if now < genesis {
|
||||
return 0
|
||||
}
|
||||
return uint64(now-genesis) / params.BeaconConfig().SecondsPerSlot
|
||||
}
|
||||
|
||||
// getBlockPreState returns the pre state of an incoming block. It uses the parent root of the block
|
||||
@@ -39,7 +43,7 @@ func (s *Service) getBlockPreState(ctx context.Context, b *ethpb.BeaconBlock) (*
|
||||
}
|
||||
|
||||
// Verify block slot time is not from the feature.
|
||||
if err := helpers.VerifySlotTime(preState.GenesisTime(), b.Slot); err != nil {
|
||||
if err := helpers.VerifySlotTime(preState.GenesisTime(), b.Slot, helpers.TimeShiftTolerance); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -58,6 +62,24 @@ func (s *Service) getBlockPreState(ctx context.Context, b *ethpb.BeaconBlock) (*
|
||||
|
||||
// verifyBlkPreState validates input block has a valid pre-state.
|
||||
func (s *Service) verifyBlkPreState(ctx context.Context, b *ethpb.BeaconBlock) (*stateTrie.BeaconState, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "chainService.verifyBlkPreState")
|
||||
defer span.End()
|
||||
|
||||
if !featureconfig.Get().DisableNewStateMgmt {
|
||||
parentRoot := bytesutil.ToBytes32(b.ParentRoot)
|
||||
if !s.stateGen.StateSummaryExists(ctx, parentRoot) {
|
||||
return nil, errors.New("provided block root does not have block saved in the db")
|
||||
}
|
||||
preState, err := s.stateGen.StateByRoot(ctx, parentRoot)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get pre state for slot %d", b.Slot)
|
||||
}
|
||||
if preState == nil {
|
||||
return nil, errors.Wrapf(err, "nil pre state for slot %d", b.Slot)
|
||||
}
|
||||
return preState, nil // No copy needed from newly hydrated state gen object.
|
||||
}
|
||||
|
||||
preState := s.initSyncState[bytesutil.ToBytes32(b.ParentRoot)]
|
||||
var err error
|
||||
if preState == nil {
|
||||
@@ -127,28 +149,6 @@ func (s *Service) verifyBlkFinalizedSlot(b *ethpb.BeaconBlock) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// saveNewValidators saves newly added validator indices from the state to db.
|
||||
// Does nothing if validator count has not changed.
|
||||
func (s *Service) saveNewValidators(ctx context.Context, preStateValidatorCount int, postState *stateTrie.BeaconState) error {
|
||||
postStateValidatorCount := postState.NumValidators()
|
||||
if preStateValidatorCount != postStateValidatorCount {
|
||||
indices := make([]uint64, 0)
|
||||
pubKeys := make([][48]byte, 0)
|
||||
for i := preStateValidatorCount; i < postStateValidatorCount; i++ {
|
||||
indices = append(indices, uint64(i))
|
||||
pubKeys = append(pubKeys, postState.PubkeyAtIndex(uint64(i)))
|
||||
}
|
||||
if err := s.beaconDB.SaveValidatorIndices(ctx, pubKeys, indices); err != nil {
|
||||
return errors.Wrapf(err, "could not save activated validators: %v", indices)
|
||||
}
|
||||
log.WithFields(logrus.Fields{
|
||||
"indices": indices,
|
||||
"totalValidatorCount": postStateValidatorCount - preStateValidatorCount,
|
||||
}).Trace("Validator indices saved in DB")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// rmStatesOlderThanLastFinalized deletes the states in db since last finalized check point.
|
||||
func (s *Service) rmStatesOlderThanLastFinalized(ctx context.Context, startSlot uint64, endSlot uint64) error {
|
||||
ctx, span := trace.StartSpan(ctx, "forkchoice.rmStatesBySlots")
|
||||
@@ -215,21 +215,36 @@ func (s *Service) shouldUpdateCurrentJustified(ctx context.Context, newJustified
|
||||
if helpers.SlotsSinceEpochStarts(s.CurrentSlot()) < params.BeaconConfig().SafeSlotsToUpdateJustified {
|
||||
return true, nil
|
||||
}
|
||||
newJustifiedBlockSigned, err := s.beaconDB.Block(ctx, bytesutil.ToBytes32(newJustifiedCheckpt.Root))
|
||||
if err != nil {
|
||||
return false, err
|
||||
var newJustifiedBlockSigned *ethpb.SignedBeaconBlock
|
||||
justifiedRoot := bytesutil.ToBytes32(newJustifiedCheckpt.Root)
|
||||
var err error
|
||||
if !featureconfig.Get().NoInitSyncBatchSaveBlocks && s.hasInitSyncBlock(justifiedRoot) {
|
||||
newJustifiedBlockSigned = s.getInitSyncBlock(justifiedRoot)
|
||||
} else {
|
||||
newJustifiedBlockSigned, err = s.beaconDB.Block(ctx, justifiedRoot)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
if newJustifiedBlockSigned == nil || newJustifiedBlockSigned.Block == nil {
|
||||
return false, errors.New("nil new justified block")
|
||||
}
|
||||
|
||||
newJustifiedBlock := newJustifiedBlockSigned.Block
|
||||
if newJustifiedBlock.Slot <= helpers.StartSlot(s.justifiedCheckpt.Epoch) {
|
||||
return false, nil
|
||||
}
|
||||
justifiedBlockSigned, err := s.beaconDB.Block(ctx, bytesutil.ToBytes32(s.justifiedCheckpt.Root))
|
||||
if err != nil {
|
||||
return false, err
|
||||
var justifiedBlockSigned *ethpb.SignedBeaconBlock
|
||||
cachedJustifiedRoot := bytesutil.ToBytes32(s.justifiedCheckpt.Root)
|
||||
if !featureconfig.Get().NoInitSyncBatchSaveBlocks && s.hasInitSyncBlock(cachedJustifiedRoot) {
|
||||
justifiedBlockSigned = s.getInitSyncBlock(cachedJustifiedRoot)
|
||||
} else {
|
||||
justifiedBlockSigned, err = s.beaconDB.Block(ctx, cachedJustifiedRoot)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
if justifiedBlockSigned == nil || justifiedBlockSigned.Block == nil {
|
||||
return false, errors.New("nil justified block")
|
||||
}
|
||||
@@ -253,29 +268,33 @@ func (s *Service) updateJustified(ctx context.Context, state *stateTrie.BeaconSt
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if canUpdate {
|
||||
s.prevJustifiedCheckpt = s.justifiedCheckpt
|
||||
s.justifiedCheckpt = cpt
|
||||
}
|
||||
|
||||
justifiedRoot := bytesutil.ToBytes32(cpt.Root)
|
||||
if featureconfig.Get().DisableNewStateMgmt {
|
||||
justifiedRoot := bytesutil.ToBytes32(cpt.Root)
|
||||
|
||||
justifiedState := s.initSyncState[justifiedRoot]
|
||||
// If justified state is nil, resume back to normal syncing process and save
|
||||
// justified check point.
|
||||
if justifiedState == nil {
|
||||
if s.beaconDB.HasState(ctx, justifiedRoot) {
|
||||
return s.beaconDB.SaveJustifiedCheckpoint(ctx, cpt)
|
||||
justifiedState := s.initSyncState[justifiedRoot]
|
||||
// If justified state is nil, resume back to normal syncing process and save
|
||||
// justified check point.
|
||||
var err error
|
||||
if justifiedState == nil {
|
||||
if s.beaconDB.HasState(ctx, justifiedRoot) {
|
||||
return s.beaconDB.SaveJustifiedCheckpoint(ctx, cpt)
|
||||
}
|
||||
justifiedState, err = s.generateState(ctx, bytesutil.ToBytes32(s.finalizedCheckpt.Root), justifiedRoot)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return s.beaconDB.SaveJustifiedCheckpoint(ctx, cpt)
|
||||
}
|
||||
}
|
||||
justifiedState, err = s.generateState(ctx, bytesutil.ToBytes32(s.finalizedCheckpt.Root), justifiedRoot)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return s.beaconDB.SaveJustifiedCheckpoint(ctx, cpt)
|
||||
if err := s.beaconDB.SaveState(ctx, justifiedState, justifiedRoot); err != nil {
|
||||
return errors.Wrap(err, "could not save justified state")
|
||||
}
|
||||
}
|
||||
if err := s.beaconDB.SaveState(ctx, justifiedState, justifiedRoot); err != nil {
|
||||
return errors.Wrap(err, "could not save justified state")
|
||||
}
|
||||
|
||||
return s.beaconDB.SaveJustifiedCheckpoint(ctx, cpt)
|
||||
}
|
||||
@@ -360,6 +379,11 @@ func (s *Service) ancestor(ctx context.Context, root []byte, slot uint64) ([]byt
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get ancestor block")
|
||||
}
|
||||
|
||||
if !featureconfig.Get().NoInitSyncBatchSaveBlocks && s.hasInitSyncBlock(bytesutil.ToBytes32(root)) {
|
||||
signed = s.getInitSyncBlock(bytesutil.ToBytes32(root))
|
||||
}
|
||||
|
||||
if signed == nil || signed.Block == nil {
|
||||
return nil, errors.New("nil block")
|
||||
}
|
||||
|
||||
@@ -9,15 +9,18 @@ import (
|
||||
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/go-ssz"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"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"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/roughtime"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
)
|
||||
|
||||
@@ -26,7 +29,10 @@ func TestStore_OnBlock(t *testing.T) {
|
||||
db := testDB.SetupDB(t)
|
||||
defer testDB.TeardownDB(t, db)
|
||||
|
||||
cfg := &Config{BeaconDB: db}
|
||||
cfg := &Config{
|
||||
BeaconDB: db,
|
||||
StateGen: stategen.New(db, cache.NewStateSummaryCache()),
|
||||
}
|
||||
service, err := NewService(ctx, cfg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -41,10 +47,7 @@ func TestStore_OnBlock(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
st, err := stateTrie.InitializeFromProtoUnsafe(&pb.BeaconState{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
st := testutil.NewBeaconState()
|
||||
if err := service.beaconDB.SaveState(ctx, st.Copy(), validGenesisRoot); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -60,10 +63,16 @@ func TestStore_OnBlock(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := service.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{Slot: st.Slot(), Root: randomParentRoot[:]}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := service.beaconDB.SaveState(ctx, st.Copy(), randomParentRoot); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
randomParentRoot2 := roots[1]
|
||||
if err := service.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{Slot: st.Slot(), Root: randomParentRoot2[:]}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := service.beaconDB.SaveState(ctx, st.Copy(), bytesutil.ToBytes32(randomParentRoot2)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -110,45 +119,13 @@ func TestStore_OnBlock(t *testing.T) {
|
||||
service.finalizedCheckpt.Root = roots[0]
|
||||
|
||||
_, err := service.onBlock(ctx, ðpb.SignedBeaconBlock{Block: tt.blk})
|
||||
if !strings.Contains(err.Error(), tt.wantErrString) {
|
||||
if err == nil || !strings.Contains(err.Error(), tt.wantErrString) {
|
||||
t.Errorf("Store.OnBlock() error = %v, wantErr = %v", err, tt.wantErrString)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestStore_SaveNewValidators(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
db := testDB.SetupDB(t)
|
||||
defer testDB.TeardownDB(t, db)
|
||||
|
||||
cfg := &Config{BeaconDB: db}
|
||||
service, err := NewService(ctx, cfg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
preCount := 2 // validators 0 and validators 1
|
||||
s, _ := stateTrie.InitializeFromProto(&pb.BeaconState{Validators: []*ethpb.Validator{
|
||||
{PublicKey: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
|
||||
{PublicKey: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}},
|
||||
{PublicKey: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2}},
|
||||
{PublicKey: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3}},
|
||||
}})
|
||||
if err := service.saveNewValidators(ctx, preCount, s); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !db.HasValidatorIndex(ctx, []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2}) {
|
||||
t.Error("Wanted validator saved in db")
|
||||
}
|
||||
if !db.HasValidatorIndex(ctx, []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3}) {
|
||||
t.Error("Wanted validator saved in db")
|
||||
}
|
||||
if db.HasValidatorIndex(ctx, []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}) {
|
||||
t.Error("validator not suppose to be saved in db")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemoveStateSinceLastFinalized(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
db := testDB.SetupDB(t)
|
||||
@@ -176,7 +153,10 @@ func TestRemoveStateSinceLastFinalized(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
s, _ := stateTrie.InitializeFromProto(&pb.BeaconState{Slot: uint64(i)})
|
||||
s := testutil.NewBeaconState()
|
||||
if err := s.SetSlot(uint64(i)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := service.beaconDB.SaveState(ctx, s, r); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -249,9 +229,15 @@ func TestRemoveStateSinceLastFinalized_EmptyStartSlot(t *testing.T) {
|
||||
}
|
||||
|
||||
lastJustifiedBlk := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{ParentRoot: []byte{'G'}}}
|
||||
lastJustifiedRoot, _ := ssz.HashTreeRoot(lastJustifiedBlk.Block)
|
||||
lastJustifiedRoot, err := ssz.HashTreeRoot(lastJustifiedBlk.Block)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
newJustifiedBlk := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 1, ParentRoot: lastJustifiedRoot[:]}}
|
||||
newJustifiedRoot, _ := ssz.HashTreeRoot(newJustifiedBlk.Block)
|
||||
newJustifiedRoot, err := ssz.HashTreeRoot(newJustifiedBlk.Block)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := service.beaconDB.SaveBlock(ctx, newJustifiedBlk); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -284,9 +270,15 @@ func TestShouldUpdateJustified_ReturnFalse(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
lastJustifiedBlk := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{ParentRoot: []byte{'G'}}}
|
||||
lastJustifiedRoot, _ := ssz.HashTreeRoot(lastJustifiedBlk.Block)
|
||||
lastJustifiedRoot, err := ssz.HashTreeRoot(lastJustifiedBlk.Block)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
newJustifiedBlk := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{ParentRoot: lastJustifiedRoot[:]}}
|
||||
newJustifiedRoot, _ := ssz.HashTreeRoot(newJustifiedBlk.Block)
|
||||
newJustifiedRoot, err := ssz.HashTreeRoot(newJustifiedBlk.Block)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := service.beaconDB.SaveBlock(ctx, newJustifiedBlk); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -307,21 +299,32 @@ func TestShouldUpdateJustified_ReturnFalse(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCachedPreState_CanGetFromCache(t *testing.T) {
|
||||
func TestCachedPreState_CanGetFromStateSummary(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
db := testDB.SetupDB(t)
|
||||
defer testDB.TeardownDB(t, db)
|
||||
|
||||
cfg := &Config{BeaconDB: db}
|
||||
cfg := &Config{
|
||||
BeaconDB: db,
|
||||
StateGen: stategen.New(db, cache.NewStateSummaryCache()),
|
||||
}
|
||||
service, err := NewService(ctx, cfg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
s, _ := stateTrie.InitializeFromProto(&pb.BeaconState{Slot: 1})
|
||||
s, err := stateTrie.InitializeFromProto(&pb.BeaconState{Slot: 1, GenesisValidatorsRoot: params.BeaconConfig().ZeroHash[:]})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
r := [32]byte{'A'}
|
||||
b := ðpb.BeaconBlock{Slot: 1, ParentRoot: r[:]}
|
||||
service.initSyncState[r] = s
|
||||
if err := service.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{Slot: 1, Root: r[:]}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := service.stateGen.SaveState(ctx, r, s); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
received, err := service.verifyBlkPreState(ctx, b)
|
||||
if err != nil {
|
||||
@@ -337,7 +340,10 @@ func TestCachedPreState_CanGetFromDB(t *testing.T) {
|
||||
db := testDB.SetupDB(t)
|
||||
defer testDB.TeardownDB(t, db)
|
||||
|
||||
cfg := &Config{BeaconDB: db}
|
||||
cfg := &Config{
|
||||
BeaconDB: db,
|
||||
StateGen: stategen.New(db, cache.NewStateSummaryCache()),
|
||||
}
|
||||
service, err := NewService(ctx, cfg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -348,19 +354,27 @@ func TestCachedPreState_CanGetFromDB(t *testing.T) {
|
||||
|
||||
service.finalizedCheckpt = ðpb.Checkpoint{Root: r[:]}
|
||||
_, err = service.verifyBlkPreState(ctx, b)
|
||||
wanted := "pre state of slot 1 does not exist"
|
||||
wanted := "provided block root does not have block saved in the db"
|
||||
if err.Error() != wanted {
|
||||
t.Error("Did not get wanted error")
|
||||
}
|
||||
|
||||
s, _ := stateTrie.InitializeFromProto(&pb.BeaconState{Slot: 1})
|
||||
service.beaconDB.SaveState(ctx, s, r)
|
||||
s, err := stateTrie.InitializeFromProto(&pb.BeaconState{Slot: 1})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := service.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{Slot: 1, Root: r[:]}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := service.stateGen.SaveState(ctx, r, s); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
received, err := service.verifyBlkPreState(ctx, b)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(s, received) {
|
||||
if s.Slot() != received.Slot() {
|
||||
t.Error("cached state not the same")
|
||||
}
|
||||
}
|
||||
@@ -378,16 +392,27 @@ func TestSaveInitState_CanSaveDelete(t *testing.T) {
|
||||
|
||||
for i := uint64(0); i < 64; i++ {
|
||||
b := ðpb.BeaconBlock{Slot: i}
|
||||
s, _ := stateTrie.InitializeFromProto(&pb.BeaconState{Slot: i})
|
||||
r, _ := ssz.HashTreeRoot(b)
|
||||
s := testutil.NewBeaconState()
|
||||
if err := s.SetSlot(i); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
r, err := ssz.HashTreeRoot(b)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
service.initSyncState[r] = s
|
||||
}
|
||||
|
||||
// Set finalized root as slot 32
|
||||
finalizedRoot, _ := ssz.HashTreeRoot(ðpb.BeaconBlock{Slot: 32})
|
||||
|
||||
s, _ := stateTrie.InitializeFromProto(&pb.BeaconState{FinalizedCheckpoint: ðpb.Checkpoint{
|
||||
Epoch: 1, Root: finalizedRoot[:]}})
|
||||
finalizedRoot, err := ssz.HashTreeRoot(ðpb.BeaconBlock{Slot: 32})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
s := testutil.NewBeaconState()
|
||||
if err := s.SetFinalizedCheckpoint(ðpb.Checkpoint{
|
||||
Epoch: 1, Root: finalizedRoot[:]}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := service.saveInitState(ctx, s); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -423,17 +448,17 @@ func TestUpdateJustified_CouldUpdateBest(t *testing.T) {
|
||||
}
|
||||
service.justifiedCheckpt = ðpb.Checkpoint{Root: []byte{'A'}}
|
||||
service.bestJustifiedCheckpt = ðpb.Checkpoint{Root: []byte{'A'}}
|
||||
st, err := stateTrie.InitializeFromProtoUnsafe(&pb.BeaconState{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
st := testutil.NewBeaconState()
|
||||
service.initSyncState[r] = st.Copy()
|
||||
if err := db.SaveState(ctx, st.Copy(), r); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Could update
|
||||
s, _ := stateTrie.InitializeFromProto(&pb.BeaconState{CurrentJustifiedCheckpoint: ðpb.Checkpoint{Epoch: 1, Root: r[:]}})
|
||||
s := testutil.NewBeaconState()
|
||||
if err := s.SetCurrentJustifiedCheckpoint(ðpb.Checkpoint{Epoch: 1, Root: r[:]}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := service.updateJustified(context.Background(), s); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -465,10 +490,16 @@ func TestFilterBlockRoots_CanFilter(t *testing.T) {
|
||||
}
|
||||
|
||||
fBlock := ðpb.BeaconBlock{}
|
||||
fRoot, _ := ssz.HashTreeRoot(fBlock)
|
||||
fRoot, err := ssz.HashTreeRoot(fBlock)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
hBlock := ðpb.BeaconBlock{Slot: 1}
|
||||
headRoot, _ := ssz.HashTreeRoot(hBlock)
|
||||
st, _ := stateTrie.InitializeFromProtoUnsafe(&pb.BeaconState{})
|
||||
headRoot, err := ssz.HashTreeRoot(hBlock)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
st := testutil.NewBeaconState()
|
||||
if err := service.beaconDB.SaveBlock(ctx, ðpb.SignedBeaconBlock{Block: fBlock}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -511,10 +542,12 @@ func TestPersistCache_CanSave(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
st, _ := stateTrie.InitializeFromProtoUnsafe(&pb.BeaconState{})
|
||||
st := testutil.NewBeaconState()
|
||||
|
||||
for i := uint64(0); i < initialSyncCacheSize; i++ {
|
||||
st.SetSlot(i)
|
||||
if err := st.SetSlot(i); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
root := [32]byte{}
|
||||
copy(root[:], bytesutil.Bytes32(i))
|
||||
service.initSyncState[root] = st.Copy()
|
||||
@@ -563,7 +596,8 @@ func TestFillForkChoiceMissingBlocks_CanSave(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
st, _ := stateTrie.InitializeFromProtoUnsafe(&pb.BeaconState{})
|
||||
st := testutil.NewBeaconState()
|
||||
|
||||
if err := service.beaconDB.SaveState(ctx, st.Copy(), validGenesisRoot); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -617,7 +651,8 @@ func TestFillForkChoiceMissingBlocks_FilterFinalized(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
st, _ := stateTrie.InitializeFromProtoUnsafe(&pb.BeaconState{})
|
||||
st := testutil.NewBeaconState()
|
||||
|
||||
if err := service.beaconDB.SaveState(ctx, st.Copy(), validGenesisRoot); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -627,12 +662,18 @@ func TestFillForkChoiceMissingBlocks_FilterFinalized(t *testing.T) {
|
||||
if err := service.beaconDB.SaveBlock(ctx, b63); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
r63, _ := ssz.HashTreeRoot(b63.Block)
|
||||
r63, err := ssz.HashTreeRoot(b63.Block)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
b64 := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 64, ParentRoot: r63[:]}}
|
||||
if err := service.beaconDB.SaveBlock(ctx, b64); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
r64, _ := ssz.HashTreeRoot(b64.Block)
|
||||
r64, err := ssz.HashTreeRoot(b64.Block)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
b65 := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 65, ParentRoot: r64[:]}}
|
||||
if err := service.beaconDB.SaveBlock(ctx, b65); err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -661,25 +702,47 @@ func TestFillForkChoiceMissingBlocks_FilterFinalized(t *testing.T) {
|
||||
// (B1, and B3 are all from the same slots)
|
||||
func blockTree1(db db.Database, genesisRoot []byte) ([][]byte, error) {
|
||||
b0 := ðpb.BeaconBlock{Slot: 0, ParentRoot: genesisRoot}
|
||||
r0, _ := ssz.HashTreeRoot(b0)
|
||||
b1 := ðpb.BeaconBlock{Slot: 1, ParentRoot: r0[:]}
|
||||
r1, _ := ssz.HashTreeRoot(b1)
|
||||
b3 := ðpb.BeaconBlock{Slot: 3, ParentRoot: r0[:]}
|
||||
r3, _ := ssz.HashTreeRoot(b3)
|
||||
b4 := ðpb.BeaconBlock{Slot: 4, ParentRoot: r3[:]}
|
||||
r4, _ := ssz.HashTreeRoot(b4)
|
||||
b5 := ðpb.BeaconBlock{Slot: 5, ParentRoot: r4[:]}
|
||||
r5, _ := ssz.HashTreeRoot(b5)
|
||||
b6 := ðpb.BeaconBlock{Slot: 6, ParentRoot: r4[:]}
|
||||
r6, _ := ssz.HashTreeRoot(b6)
|
||||
b7 := ðpb.BeaconBlock{Slot: 7, ParentRoot: r5[:]}
|
||||
r7, _ := ssz.HashTreeRoot(b7)
|
||||
b8 := ðpb.BeaconBlock{Slot: 8, ParentRoot: r6[:]}
|
||||
r8, _ := ssz.HashTreeRoot(b8)
|
||||
st, err := stateTrie.InitializeFromProtoUnsafe(&pb.BeaconState{})
|
||||
r0, err := ssz.HashTreeRoot(b0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b1 := ðpb.BeaconBlock{Slot: 1, ParentRoot: r0[:]}
|
||||
r1, err := ssz.HashTreeRoot(b1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b3 := ðpb.BeaconBlock{Slot: 3, ParentRoot: r0[:]}
|
||||
r3, err := ssz.HashTreeRoot(b3)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b4 := ðpb.BeaconBlock{Slot: 4, ParentRoot: r3[:]}
|
||||
r4, err := ssz.HashTreeRoot(b4)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b5 := ðpb.BeaconBlock{Slot: 5, ParentRoot: r4[:]}
|
||||
r5, err := ssz.HashTreeRoot(b5)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b6 := ðpb.BeaconBlock{Slot: 6, ParentRoot: r4[:]}
|
||||
r6, err := ssz.HashTreeRoot(b6)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b7 := ðpb.BeaconBlock{Slot: 7, ParentRoot: r5[:]}
|
||||
r7, err := ssz.HashTreeRoot(b7)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b8 := ðpb.BeaconBlock{Slot: 8, ParentRoot: r6[:]}
|
||||
r8, err := ssz.HashTreeRoot(b8)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
st := testutil.NewBeaconState()
|
||||
|
||||
for _, b := range []*ethpb.BeaconBlock{b0, b1, b3, b4, b5, b6, b7, b8} {
|
||||
if err := db.SaveBlock(context.Background(), ðpb.SignedBeaconBlock{Block: b}); err != nil {
|
||||
return nil, err
|
||||
@@ -699,3 +762,13 @@ func blockTree1(db db.Database, genesisRoot []byte) ([][]byte, error) {
|
||||
}
|
||||
return [][]byte{r0[:], r1[:], nil, r3[:], r4[:], r5[:], r6[:], r7[:], r8[:]}, nil
|
||||
}
|
||||
|
||||
func TestCurrentSlot_HandlesOverflow(t *testing.T) {
|
||||
svc := Service{genesisTime: roughtime.Now().Add(1 * time.Hour)}
|
||||
|
||||
slot := svc.CurrentSlot()
|
||||
|
||||
if slot != 0 {
|
||||
t.Fatalf("Expected slot to be 0, got %d", slot)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package blockchain
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
@@ -13,6 +12,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/roughtime"
|
||||
"github.com/prysmaticlabs/prysm/shared/slotutil"
|
||||
"github.com/sirupsen/logrus"
|
||||
"go.opencensus.io/trace"
|
||||
@@ -90,7 +90,13 @@ func (s *Service) processAttestation(subscribedToStateEvents chan struct{}) {
|
||||
ctx := context.Background()
|
||||
atts := s.attPool.ForkchoiceAttestations()
|
||||
for _, a := range atts {
|
||||
hasState := s.beaconDB.HasState(ctx, bytesutil.ToBytes32(a.Data.BeaconBlockRoot)) && s.beaconDB.HasState(ctx, bytesutil.ToBytes32(a.Data.Target.Root))
|
||||
var hasState bool
|
||||
if !featureconfig.Get().DisableNewStateMgmt {
|
||||
hasState = s.stateGen.StateSummaryExists(ctx, bytesutil.ToBytes32(a.Data.BeaconBlockRoot))
|
||||
} else {
|
||||
hasState = s.beaconDB.HasState(ctx, bytesutil.ToBytes32(a.Data.BeaconBlockRoot)) && s.beaconDB.HasState(ctx, bytesutil.ToBytes32(a.Data.Target.Root))
|
||||
}
|
||||
|
||||
hasBlock := s.hasBlock(ctx, bytesutil.ToBytes32(a.Data.BeaconBlockRoot))
|
||||
if !(hasState && hasBlock) {
|
||||
continue
|
||||
@@ -121,7 +127,7 @@ func (s *Service) processAttestation(subscribedToStateEvents chan struct{}) {
|
||||
// This verifies the epoch of input checkpoint is within current epoch and previous epoch
|
||||
// with respect to current time. Returns true if it's within, false if it's not.
|
||||
func (s *Service) verifyCheckpointEpoch(c *ethpb.Checkpoint) bool {
|
||||
now := uint64(time.Now().Unix())
|
||||
now := uint64(roughtime.Now().Unix())
|
||||
genesisTime := uint64(s.genesisTime.Unix())
|
||||
currentSlot := (now - genesisTime) / params.BeaconConfig().SecondsPerSlot
|
||||
currentEpoch := helpers.SlotToEpoch(currentSlot)
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
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/stateutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/traceutil"
|
||||
"github.com/sirupsen/logrus"
|
||||
@@ -25,6 +26,7 @@ type BlockReceiver interface {
|
||||
ReceiveBlockNoPubsub(ctx context.Context, block *ethpb.SignedBeaconBlock) error
|
||||
ReceiveBlockNoPubsubForkchoice(ctx context.Context, block *ethpb.SignedBeaconBlock) error
|
||||
ReceiveBlockNoVerify(ctx context.Context, block *ethpb.SignedBeaconBlock) error
|
||||
HasInitSyncBlock(root [32]byte) bool
|
||||
}
|
||||
|
||||
// ReceiveBlock is a function that defines the operations that are preformed on
|
||||
@@ -88,7 +90,7 @@ func (s *Service) ReceiveBlockNoPubsub(ctx context.Context, block *ethpb.SignedB
|
||||
defer s.epochParticipationLock.Unlock()
|
||||
s.epochParticipation[helpers.SlotToEpoch(blockCopy.Block.Slot)] = precompute.Balances
|
||||
|
||||
root, err := ssz.HashTreeRoot(blockCopy.Block)
|
||||
root, err := stateutil.BlockRoot(blockCopy.Block)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get signing root on received block")
|
||||
}
|
||||
@@ -139,7 +141,7 @@ func (s *Service) ReceiveBlockNoPubsubForkchoice(ctx context.Context, block *eth
|
||||
return err
|
||||
}
|
||||
|
||||
root, err := ssz.HashTreeRoot(blockCopy.Block)
|
||||
root, err := stateutil.BlockRoot(blockCopy.Block)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get signing root on received block")
|
||||
}
|
||||
@@ -191,7 +193,7 @@ func (s *Service) ReceiveBlockNoVerify(ctx context.Context, block *ethpb.SignedB
|
||||
return err
|
||||
}
|
||||
|
||||
root, err := ssz.HashTreeRoot(blockCopy.Block)
|
||||
root, err := stateutil.BlockRoot(blockCopy.Block)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get signing root on received blockCopy")
|
||||
}
|
||||
@@ -235,3 +237,8 @@ func (s *Service) ReceiveBlockNoVerify(ctx context.Context, block *ethpb.SignedB
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// HasInitSyncBlock returns true if the block of the input root exists in initial sync blocks cache.
|
||||
func (s *Service) HasInitSyncBlock(root [32]byte) bool {
|
||||
return s.hasInitSyncBlock(root)
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
@@ -73,6 +74,9 @@ type Service struct {
|
||||
checkpointState *cache.CheckpointStateCache
|
||||
checkpointStateLock sync.Mutex
|
||||
stateGen *stategen.State
|
||||
opsService *attestations.Service
|
||||
initSyncBlocks map[[32]byte]*ethpb.SignedBeaconBlock
|
||||
initSyncBlocksLock sync.RWMutex
|
||||
}
|
||||
|
||||
// Config options for the service.
|
||||
@@ -88,6 +92,8 @@ type Config struct {
|
||||
MaxRoutines int64
|
||||
StateNotifier statefeed.Notifier
|
||||
ForkChoiceStore f.ForkChoicer
|
||||
OpsService *attestations.Service
|
||||
StateGen *stategen.State
|
||||
}
|
||||
|
||||
// NewService instantiates a new block service instance that will
|
||||
@@ -111,7 +117,9 @@ func NewService(ctx context.Context, cfg *Config) (*Service, error) {
|
||||
initSyncState: make(map[[32]byte]*stateTrie.BeaconState),
|
||||
boundaryRoots: [][32]byte{},
|
||||
checkpointState: cache.NewCheckpointStateCache(),
|
||||
stateGen: stategen.New(cfg.BeaconDB),
|
||||
opsService: cfg.OpsService,
|
||||
stateGen: cfg.StateGen,
|
||||
initSyncBlocks: make(map[[32]byte]*ethpb.SignedBeaconBlock),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -130,10 +138,18 @@ func (s *Service) Start() {
|
||||
if err != nil {
|
||||
log.Fatalf("Could not fetch finalized cp: %v", err)
|
||||
}
|
||||
|
||||
if beaconState == nil {
|
||||
beaconState, err = s.beaconDB.State(ctx, bytesutil.ToBytes32(cp.Root))
|
||||
if err != nil {
|
||||
log.Fatalf("Could not fetch beacon state: %v", err)
|
||||
if !featureconfig.Get().DisableNewStateMgmt {
|
||||
beaconState, err = s.stateGen.StateByRoot(ctx, bytesutil.ToBytes32(cp.Root))
|
||||
if err != nil {
|
||||
log.Fatalf("Could not fetch beacon state by root: %v", err)
|
||||
}
|
||||
} else {
|
||||
beaconState, err = s.beaconDB.State(ctx, bytesutil.ToBytes32(cp.Root))
|
||||
if err != nil {
|
||||
log.Fatalf("Could not fetch beacon state: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,6 +160,7 @@ 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())
|
||||
if err := s.initializeChainInfo(ctx); err != nil {
|
||||
log.Fatalf("Could not set up chain info: %v", err)
|
||||
}
|
||||
@@ -164,16 +181,19 @@ func (s *Service) Start() {
|
||||
s.prevFinalizedCheckpt = stateTrie.CopyCheckpoint(finalizedCheckpoint)
|
||||
s.resumeForkChoice(justifiedCheckpoint, finalizedCheckpoint)
|
||||
|
||||
if finalizedCheckpoint.Epoch > 1 {
|
||||
if err := s.pruneGarbageState(ctx, helpers.StartSlot(finalizedCheckpoint.Epoch)-params.BeaconConfig().SlotsPerEpoch); err != nil {
|
||||
log.WithError(err).Warn("Could not prune old states")
|
||||
if featureconfig.Get().DisableNewStateMgmt {
|
||||
if finalizedCheckpoint.Epoch > 1 {
|
||||
if err := s.pruneGarbageState(ctx, helpers.StartSlot(finalizedCheckpoint.Epoch)-params.BeaconConfig().SlotsPerEpoch); err != nil {
|
||||
log.WithError(err).Warn("Could not prune old states")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s.stateNotifier.StateFeed().Send(&feed.Event{
|
||||
Type: statefeed.Initialized,
|
||||
Data: &statefeed.InitializedData{
|
||||
StartTime: s.genesisTime,
|
||||
StartTime: s.genesisTime,
|
||||
GenesisValidatorsRoot: beaconState.GenesisValidatorRoot(),
|
||||
},
|
||||
})
|
||||
} else {
|
||||
@@ -191,7 +211,11 @@ func (s *Service) Start() {
|
||||
select {
|
||||
case event := <-stateChannel:
|
||||
if event.Type == statefeed.ChainStarted {
|
||||
data := event.Data.(*statefeed.ChainStartedData)
|
||||
data, ok := event.Data.(*statefeed.ChainStartedData)
|
||||
if !ok {
|
||||
log.Error("event data is not type *statefeed.ChainStartedData")
|
||||
return
|
||||
}
|
||||
log.WithField("starttime", data.StartTime).Debug("Received chain start event")
|
||||
s.processChainStartTime(ctx, data.StartTime)
|
||||
return
|
||||
@@ -214,13 +238,15 @@ func (s *Service) Start() {
|
||||
// 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()
|
||||
if err := s.initializeBeaconChain(ctx, genesisTime, preGenesisState, s.chainStartFetcher.ChainStartEth1Data()); err != nil {
|
||||
initializedState, err := s.initializeBeaconChain(ctx, genesisTime, preGenesisState, s.chainStartFetcher.ChainStartEth1Data())
|
||||
if err != nil {
|
||||
log.Fatalf("Could not initialize beacon chain: %v", err)
|
||||
}
|
||||
s.stateNotifier.StateFeed().Send(&feed.Event{
|
||||
Type: statefeed.Initialized,
|
||||
Data: &statefeed.InitializedData{
|
||||
StartTime: genesisTime,
|
||||
StartTime: genesisTime,
|
||||
GenesisValidatorsRoot: initializedState.GenesisValidatorRoot(),
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -232,7 +258,7 @@ func (s *Service) initializeBeaconChain(
|
||||
ctx context.Context,
|
||||
genesisTime time.Time,
|
||||
preGenesisState *stateTrie.BeaconState,
|
||||
eth1data *ethpb.Eth1Data) error {
|
||||
eth1data *ethpb.Eth1Data) (*stateTrie.BeaconState, error) {
|
||||
_, span := trace.StartSpan(context.Background(), "beacon-chain.Service.initializeBeaconChain")
|
||||
defer span.End()
|
||||
s.genesisTime = genesisTime
|
||||
@@ -240,11 +266,11 @@ func (s *Service) initializeBeaconChain(
|
||||
|
||||
genesisState, err := state.OptimizedGenesisBeaconState(unixTime, preGenesisState, eth1data)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not initialize genesis state")
|
||||
return nil, errors.Wrap(err, "could not initialize genesis state")
|
||||
}
|
||||
|
||||
if err := s.saveGenesisData(ctx, genesisState); err != nil {
|
||||
return errors.Wrap(err, "could not save genesis data")
|
||||
return nil, errors.Wrap(err, "could not save genesis data")
|
||||
}
|
||||
|
||||
log.Info("Initialized beacon chain genesis state")
|
||||
@@ -254,13 +280,15 @@ func (s *Service) initializeBeaconChain(
|
||||
|
||||
// Update committee shuffled indices for genesis epoch.
|
||||
if err := helpers.UpdateCommitteeCache(genesisState, 0 /* genesis epoch */); err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
if err := helpers.UpdateProposerIndicesInCache(genesisState, 0 /* genesis epoch */); err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil
|
||||
s.opsService.SetGenesisTime(genesisState.GenesisTime())
|
||||
|
||||
return genesisState, nil
|
||||
}
|
||||
|
||||
// Stop the blockchain service's main event loop and associated goroutines.
|
||||
@@ -284,21 +312,9 @@ func (s *Service) ClearCachedStates() {
|
||||
s.initSyncState = map[[32]byte]*stateTrie.BeaconState{}
|
||||
}
|
||||
|
||||
// This gets called when beacon chain is first initialized to save validator indices and public keys in db.
|
||||
func (s *Service) saveGenesisValidators(ctx context.Context, state *stateTrie.BeaconState) error {
|
||||
pubkeys := make([][48]byte, state.NumValidators())
|
||||
indices := make([]uint64, state.NumValidators())
|
||||
|
||||
for i := 0; i < state.NumValidators(); i++ {
|
||||
pubkeys[i] = state.PubkeyAtIndex(uint64(i))
|
||||
indices[i] = uint64(i)
|
||||
}
|
||||
return s.beaconDB.SaveValidatorIndices(ctx, pubkeys, indices)
|
||||
}
|
||||
|
||||
// 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()
|
||||
stateRoot, err := genesisState.HashTreeRoot(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -311,8 +327,20 @@ func (s *Service) saveGenesisData(ctx context.Context, genesisState *stateTrie.B
|
||||
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 !featureconfig.Get().DisableNewStateMgmt {
|
||||
if err := s.stateGen.SaveState(ctx, genesisBlkRoot, genesisState); 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
|
||||
}
|
||||
} else {
|
||||
if err := s.beaconDB.SaveState(ctx, genesisState, genesisBlkRoot); err != nil {
|
||||
return errors.Wrap(err, "could not save genesis state")
|
||||
}
|
||||
}
|
||||
if err := s.beaconDB.SaveHeadBlockRoot(ctx, genesisBlkRoot); err != nil {
|
||||
return errors.Wrap(err, "could not save head block root")
|
||||
@@ -320,9 +348,6 @@ func (s *Service) saveGenesisData(ctx context.Context, genesisState *stateTrie.B
|
||||
if err := s.beaconDB.SaveGenesisBlockRoot(ctx, genesisBlkRoot); err != nil {
|
||||
return errors.Wrap(err, "could save genesis block root")
|
||||
}
|
||||
if err := s.saveGenesisValidators(ctx, genesisState); err != nil {
|
||||
return errors.Wrap(err, "could not save genesis validators")
|
||||
}
|
||||
|
||||
genesisCheckpoint := ðpb.Checkpoint{Root: genesisBlkRoot[:]}
|
||||
|
||||
@@ -388,11 +413,25 @@ func (s *Service) initializeChainInfo(ctx context.Context) error {
|
||||
// would be the genesis state and block.
|
||||
return errors.New("no finalized epoch in the database")
|
||||
}
|
||||
finalizedState, err := s.beaconDB.State(ctx, bytesutil.ToBytes32(finalized.Root))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get finalized state from db")
|
||||
finalizedRoot := bytesutil.ToBytes32(finalized.Root)
|
||||
var finalizedState *stateTrie.BeaconState
|
||||
if !featureconfig.Get().DisableNewStateMgmt {
|
||||
finalizedRoot = s.beaconDB.LastArchivedIndexRoot(ctx)
|
||||
finalizedState, err = s.stateGen.Resume(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get finalized state from db")
|
||||
}
|
||||
if finalizedRoot == params.BeaconConfig().ZeroHash {
|
||||
finalizedRoot = bytesutil.ToBytes32(finalized.Root)
|
||||
}
|
||||
} else {
|
||||
finalizedState, err = s.beaconDB.State(ctx, bytesutil.ToBytes32(finalized.Root))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get finalized state from db")
|
||||
}
|
||||
}
|
||||
finalizedBlock, err := s.beaconDB.Block(ctx, bytesutil.ToBytes32(finalized.Root))
|
||||
|
||||
finalizedBlock, err := s.beaconDB.Block(ctx, finalizedRoot)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get finalized block from db")
|
||||
}
|
||||
@@ -400,8 +439,7 @@ func (s *Service) initializeChainInfo(ctx context.Context) error {
|
||||
if finalizedState == nil || finalizedBlock == nil {
|
||||
return errors.New("finalized state and block can't be nil")
|
||||
}
|
||||
|
||||
s.setHead(bytesutil.ToBytes32(finalized.Root), finalizedBlock, finalizedState)
|
||||
s.setHead(finalizedRoot, finalizedBlock, finalizedState)
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -422,6 +460,10 @@ func (s *Service) pruneGarbageState(ctx context.Context, slot uint64) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := s.beaconDB.SaveLastArchivedIndex(ctx, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -21,13 +21,11 @@ func TestChainService_SaveHead_DataRace(t *testing.T) {
|
||||
beaconDB: db,
|
||||
}
|
||||
go func() {
|
||||
s.saveHead(
|
||||
context.Background(),
|
||||
[32]byte{},
|
||||
)
|
||||
if err := s.saveHead(context.Background(), [32]byte{}, ); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}()
|
||||
s.saveHead(
|
||||
context.Background(),
|
||||
[32]byte{},
|
||||
)
|
||||
if err := s.saveHead(context.Background(), [32]byte{}, ); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package blockchain
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"io/ioutil"
|
||||
"reflect"
|
||||
"testing"
|
||||
@@ -13,6 +12,7 @@ import (
|
||||
"github.com/gogo/protobuf/proto"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
ssz "github.com/prysmaticlabs/go-ssz"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
|
||||
b "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
"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/stategen"
|
||||
protodb "github.com/prysmaticlabs/prysm/proto/beacon/db"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/event"
|
||||
@@ -133,6 +134,10 @@ func setupBeaconChain(t *testing.T, beaconDB db.Database) *Service {
|
||||
t.Fatalf("unable to set up web3 service: %v", err)
|
||||
}
|
||||
|
||||
opsService, err := attestations.NewService(ctx, &attestations.Config{Pool: attestations.NewPool()})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cfg := &Config{
|
||||
BeaconBlockBuf: 0,
|
||||
BeaconDB: beaconDB,
|
||||
@@ -141,11 +146,11 @@ func setupBeaconChain(t *testing.T, beaconDB db.Database) *Service {
|
||||
P2p: &mockBroadcaster{},
|
||||
StateNotifier: &mockBeaconNode{},
|
||||
AttPool: attestations.NewPool(),
|
||||
StateGen: stategen.New(beaconDB, cache.NewStateSummaryCache()),
|
||||
ForkChoiceStore: protoarray.New(0, 0, params.BeaconConfig().ZeroHash),
|
||||
OpsService: opsService,
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("could not register blockchain service: %v", err)
|
||||
}
|
||||
|
||||
chainService, err := NewService(ctx, cfg)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to setup chain service: %v", err)
|
||||
@@ -226,8 +231,8 @@ func TestChainStartStop_Initialized(t *testing.T) {
|
||||
if err := db.SaveBlock(ctx, genesisBlk); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
s, err := beaconstate.InitializeFromProto(&pb.BeaconState{Slot: 1})
|
||||
if err != nil {
|
||||
s := testutil.NewBeaconState()
|
||||
if err := s.SetSlot(1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := db.SaveState(ctx, s, blkRoot); err != nil {
|
||||
@@ -267,7 +272,10 @@ func TestChainService_InitializeBeaconChain(t *testing.T) {
|
||||
|
||||
// Set up 10 deposits pre chain start for validators to register
|
||||
count := uint64(10)
|
||||
deposits, _, _ := testutil.DeterministicDepositsAndKeys(count)
|
||||
deposits, _, err := testutil.DeterministicDepositsAndKeys(count)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
trie, _, err := testutil.DepositTrieFromDeposits(deposits)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -277,31 +285,23 @@ func TestChainService_InitializeBeaconChain(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
genState.SetEth1Data(ðpb.Eth1Data{
|
||||
err = genState.SetEth1Data(ðpb.Eth1Data{
|
||||
DepositRoot: hashTreeRoot[:],
|
||||
DepositCount: uint64(len(deposits)),
|
||||
})
|
||||
genState, err = b.ProcessDeposits(ctx, genState, ðpb.BeaconBlockBody{Deposits: deposits})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
for _, deposit := range deposits {
|
||||
genState, err = b.ProcessPreGenesisDeposit(ctx, genState, deposit)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
if err := bc.initializeBeaconChain(ctx, time.Unix(0, 0), genState, ðpb.Eth1Data{
|
||||
|
||||
if _, err := bc.initializeBeaconChain(ctx, time.Unix(0, 0), genState, ðpb.Eth1Data{
|
||||
DepositRoot: hashTreeRoot[:],
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
s, err := bc.beaconDB.State(ctx, bc.headRoot())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for _, v := range s.Validators() {
|
||||
if !db.HasValidatorIndex(ctx, v.PublicKey) {
|
||||
t.Errorf("Validator %s missing from db", hex.EncodeToString(v.PublicKey))
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := bc.HeadState(ctx); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -336,14 +336,23 @@ func TestChainService_InitializeChainInfo(t *testing.T) {
|
||||
|
||||
finalizedSlot := params.BeaconConfig().SlotsPerEpoch*2 + 1
|
||||
headBlock := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: finalizedSlot, ParentRoot: genesisRoot[:]}}
|
||||
headState, err := beaconstate.InitializeFromProto(&pb.BeaconState{Slot: finalizedSlot})
|
||||
headState := testutil.NewBeaconState()
|
||||
if err := headState.SetSlot(finalizedSlot); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := headState.SetGenesisValidatorRoot(params.BeaconConfig().ZeroHash[:]); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
headRoot, err := ssz.HashTreeRoot(headBlock.Block)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
headRoot, _ := ssz.HashTreeRoot(headBlock.Block)
|
||||
if err := db.SaveState(ctx, headState, headRoot); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := db.SaveState(ctx, headState, genesisRoot); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := db.SaveBlock(ctx, headBlock); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -356,7 +365,7 @@ func TestChainService_InitializeChainInfo(t *testing.T) {
|
||||
if err := db.SaveBlock(ctx, headBlock); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
c := &Service{beaconDB: db}
|
||||
c := &Service{beaconDB: db, stateGen: stategen.New(db, cache.NewStateSummaryCache())}
|
||||
if err := c.initializeChainInfo(ctx); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -395,12 +404,18 @@ func TestChainService_SaveHeadNoDB(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
s := &Service{
|
||||
beaconDB: db,
|
||||
stateGen: stategen.New(db, cache.NewStateSummaryCache()),
|
||||
}
|
||||
b := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 1}}
|
||||
r, _ := ssz.HashTreeRoot(b)
|
||||
state := &pb.BeaconState{}
|
||||
newState, err := beaconstate.InitializeFromProto(state)
|
||||
s.beaconDB.SaveState(ctx, newState, r)
|
||||
r, err := ssz.HashTreeRoot(b)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
newState := testutil.NewBeaconState()
|
||||
if err := s.stateGen.SaveState(ctx, r, newState); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := s.saveHeadNoDB(ctx, b, r); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -431,9 +446,8 @@ func TestChainService_PruneOldStates(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
state := &pb.BeaconState{Slot: uint64(i)}
|
||||
newState, err := beaconstate.InitializeFromProto(state)
|
||||
if err != nil {
|
||||
newState := testutil.NewBeaconState()
|
||||
if err := newState.SetSlot(uint64(i)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := s.beaconDB.SaveState(ctx, newState, r); err != nil {
|
||||
@@ -473,9 +487,15 @@ func TestHasBlock_ForkChoiceAndDB(t *testing.T) {
|
||||
beaconDB: db,
|
||||
}
|
||||
block := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Body: ðpb.BeaconBlockBody{}}}
|
||||
r, _ := ssz.HashTreeRoot(block.Block)
|
||||
r, err := ssz.HashTreeRoot(block.Block)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
bs := &pb.BeaconState{FinalizedCheckpoint: ðpb.Checkpoint{}, CurrentJustifiedCheckpoint: ðpb.Checkpoint{}}
|
||||
state, _ := beaconstate.InitializeFromProto(bs)
|
||||
state, err := beaconstate.InitializeFromProto(bs)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := s.insertBlockToForkChoiceStore(ctx, block.Block, r, state); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -500,7 +520,10 @@ func BenchmarkHasBlockDB(b *testing.B) {
|
||||
if err := s.beaconDB.SaveBlock(ctx, block); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
r, _ := ssz.HashTreeRoot(block.Block)
|
||||
r, err := ssz.HashTreeRoot(block.Block)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
@@ -520,9 +543,15 @@ func BenchmarkHasBlockForkChoiceStore(b *testing.B) {
|
||||
beaconDB: db,
|
||||
}
|
||||
block := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Body: ðpb.BeaconBlockBody{}}}
|
||||
r, _ := ssz.HashTreeRoot(block.Block)
|
||||
r, err := ssz.HashTreeRoot(block.Block)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
bs := &pb.BeaconState{FinalizedCheckpoint: ðpb.Checkpoint{}, CurrentJustifiedCheckpoint: ðpb.Checkpoint{}}
|
||||
state, _ := beaconstate.InitializeFromProto(bs)
|
||||
state, err := beaconstate.InitializeFromProto(bs)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
if err := s.insertBlockToForkChoiceStore(ctx, block.Block, r, state); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -219,7 +219,7 @@ func (ms *ChainService) GenesisTime() time.Time {
|
||||
|
||||
// CurrentSlot mocks the same method in the chain service.
|
||||
func (ms *ChainService) CurrentSlot() uint64 {
|
||||
return 0
|
||||
return uint64(time.Now().Unix()-ms.Genesis.Unix()) / params.BeaconConfig().SecondsPerSlot
|
||||
}
|
||||
|
||||
// Participation mocks the same method in the chain service.
|
||||
@@ -234,3 +234,8 @@ func (ms *ChainService) IsValidAttestation(ctx context.Context, att *ethpb.Attes
|
||||
|
||||
// ClearCachedStates does nothing.
|
||||
func (ms *ChainService) ClearCachedStates() {}
|
||||
|
||||
// HasInitSyncBlock mocks the same method in the chain service.
|
||||
func (ms *ChainService) HasInitSyncBlock(root [32]byte) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
10
beacon-chain/cache/BUILD.bazel
vendored
10
beacon-chain/cache/BUILD.bazel
vendored
@@ -6,15 +6,21 @@ go_library(
|
||||
"attestation_data.go",
|
||||
"checkpoint_state.go",
|
||||
"committee.go",
|
||||
"committee_ids.go",
|
||||
"common.go",
|
||||
"eth1_data.go",
|
||||
"hot_state_cache.go",
|
||||
"skip_slot_cache.go",
|
||||
"state_summary.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/cache",
|
||||
visibility = ["//beacon-chain:__subpackages__"],
|
||||
visibility = [
|
||||
"//beacon-chain:__subpackages__",
|
||||
"//tools:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/featureconfig:go_default_library",
|
||||
"//shared/hashutil:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
@@ -24,6 +30,7 @@ go_library(
|
||||
"@com_github_prometheus_client_golang//prometheus/promauto:go_default_library",
|
||||
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
|
||||
"@io_k8s_client_go//tools/cache:go_default_library",
|
||||
"@io_opencensus_go//trace:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -34,6 +41,7 @@ go_test(
|
||||
"attestation_data_test.go",
|
||||
"checkpoint_state_test.go",
|
||||
"committee_fuzz_test.go",
|
||||
"committee_ids_test.go",
|
||||
"committee_test.go",
|
||||
"eth1_data_test.go",
|
||||
"feature_flag_test.go",
|
||||
|
||||
5
beacon-chain/cache/attestation_data.go
vendored
5
beacon-chain/cache/attestation_data.go
vendored
@@ -148,7 +148,10 @@ func (c *AttestationCache) Put(ctx context.Context, req *ethpb.AttestationDataRe
|
||||
}
|
||||
|
||||
func wrapperToKey(i interface{}) (string, error) {
|
||||
w := i.(*attestationReqResWrapper)
|
||||
w, ok := i.(*attestationReqResWrapper)
|
||||
if !ok {
|
||||
return "", errors.New("key is not of type *attestationReqResWrapper")
|
||||
}
|
||||
if w == nil {
|
||||
return "", errors.New("nil wrapper")
|
||||
}
|
||||
|
||||
14
beacon-chain/cache/checkpoint_state_test.go
vendored
14
beacon-chain/cache/checkpoint_state_test.go
vendored
@@ -4,14 +4,17 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
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/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
||||
)
|
||||
|
||||
func TestCheckpointStateCacheKeyFn_OK(t *testing.T) {
|
||||
cp := ðpb.Checkpoint{Epoch: 1, Root: []byte{'A'}}
|
||||
cp := ðpb.Checkpoint{Epoch: 1, Root: bytesutil.PadTo([]byte{'A'}, 32)}
|
||||
st, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
||||
Slot: 64,
|
||||
})
|
||||
@@ -45,9 +48,10 @@ func TestCheckpointStateCacheKeyFn_InvalidObj(t *testing.T) {
|
||||
func TestCheckpointStateCache_StateByCheckpoint(t *testing.T) {
|
||||
cache := NewCheckpointStateCache()
|
||||
|
||||
cp1 := ðpb.Checkpoint{Epoch: 1, Root: []byte{'A'}}
|
||||
cp1 := ðpb.Checkpoint{Epoch: 1, Root: bytesutil.PadTo([]byte{'A'}, 32)}
|
||||
st, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
||||
Slot: 64,
|
||||
GenesisValidatorsRoot: params.BeaconConfig().ZeroHash[:],
|
||||
Slot: 64,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -71,11 +75,11 @@ func TestCheckpointStateCache_StateByCheckpoint(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(state.InnerStateUnsafe(), info1.State.InnerStateUnsafe()) {
|
||||
if !proto.Equal(state.InnerStateUnsafe(), info1.State.InnerStateUnsafe()) {
|
||||
t.Error("incorrectly cached state")
|
||||
}
|
||||
|
||||
cp2 := ðpb.Checkpoint{Epoch: 2, Root: []byte{'B'}}
|
||||
cp2 := ðpb.Checkpoint{Epoch: 2, Root: bytesutil.PadTo([]byte{'B'}, 32)}
|
||||
st2, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
||||
Slot: 128,
|
||||
})
|
||||
|
||||
2
beacon-chain/cache/committee.go
vendored
2
beacon-chain/cache/committee.go
vendored
@@ -96,7 +96,7 @@ func (c *CommitteeCache) Committee(slot uint64, seed [32]byte, index uint64) ([]
|
||||
indexOffSet := index + (slot%params.BeaconConfig().SlotsPerEpoch)*committeeCountPerSlot
|
||||
start, end := startEndIndices(item, indexOffSet)
|
||||
|
||||
if int(end) > len(item.ShuffledIndices) {
|
||||
if int(end) > len(item.ShuffledIndices) || end < start {
|
||||
return nil, errors.New("requested index out of bound")
|
||||
}
|
||||
|
||||
|
||||
87
beacon-chain/cache/committee_ids.go
vendored
Normal file
87
beacon-chain/cache/committee_ids.go
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/sliceutil"
|
||||
)
|
||||
|
||||
type committeeIDs struct {
|
||||
attester *lru.Cache
|
||||
attesterLock sync.RWMutex
|
||||
aggregator *lru.Cache
|
||||
aggregatorLock sync.RWMutex
|
||||
}
|
||||
|
||||
// CommitteeIDs for attester and aggregator.
|
||||
var CommitteeIDs = newCommitteeIDs()
|
||||
|
||||
func newCommitteeIDs() *committeeIDs {
|
||||
// Given a node can calculate committee assignments of current epoch and next epoch.
|
||||
// Max size is set to 2 epoch length.
|
||||
cacheSize := int(params.BeaconConfig().MaxCommitteesPerSlot * params.BeaconConfig().SlotsPerEpoch * 2)
|
||||
attesterCache, err := lru.New(cacheSize)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
aggregatorCache, err := lru.New(cacheSize)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return &committeeIDs{attester: attesterCache, aggregator: aggregatorCache}
|
||||
}
|
||||
|
||||
// AddAttesterCommiteeID adds committee ID for subscribing subnet for the attester of a given slot.
|
||||
func (c *committeeIDs) AddAttesterCommiteeID(slot uint64, committeeID uint64) {
|
||||
c.attesterLock.Lock()
|
||||
defer c.attesterLock.Unlock()
|
||||
|
||||
ids := []uint64{committeeID}
|
||||
val, exists := c.attester.Get(slot)
|
||||
if exists {
|
||||
ids = sliceutil.UnionUint64(append(val.([]uint64), ids...))
|
||||
}
|
||||
c.attester.Add(slot, ids)
|
||||
}
|
||||
|
||||
// GetAttesterCommitteeIDs gets the committee ID for subscribing subnet for attester of the slot.
|
||||
func (c *committeeIDs) GetAttesterCommitteeIDs(slot uint64) []uint64 {
|
||||
c.attesterLock.RLock()
|
||||
defer c.attesterLock.RUnlock()
|
||||
|
||||
val, exists := c.attester.Get(slot)
|
||||
if !exists {
|
||||
return nil
|
||||
}
|
||||
if v, ok := val.([]uint64); ok {
|
||||
return v
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddAggregatorCommiteeID adds committee ID for subscribing subnet for the aggregator of a given slot.
|
||||
func (c *committeeIDs) AddAggregatorCommiteeID(slot uint64, committeeID uint64) {
|
||||
c.aggregatorLock.Lock()
|
||||
defer c.aggregatorLock.Unlock()
|
||||
|
||||
ids := []uint64{committeeID}
|
||||
val, exists := c.aggregator.Get(slot)
|
||||
if exists {
|
||||
ids = sliceutil.UnionUint64(append(val.([]uint64), ids...))
|
||||
}
|
||||
c.aggregator.Add(slot, ids)
|
||||
}
|
||||
|
||||
// GetAggregatorCommitteeIDs gets the committee ID for subscribing subnet for aggregator of the slot.
|
||||
func (c *committeeIDs) GetAggregatorCommitteeIDs(slot uint64) []uint64 {
|
||||
c.aggregatorLock.RLock()
|
||||
defer c.aggregatorLock.RUnlock()
|
||||
|
||||
val, exists := c.aggregator.Get(slot)
|
||||
if !exists {
|
||||
return []uint64{}
|
||||
}
|
||||
return val.([]uint64)
|
||||
}
|
||||
56
beacon-chain/cache/committee_ids_test.go
vendored
Normal file
56
beacon-chain/cache/committee_ids_test.go
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCommitteeIDCache_RoundTrip(t *testing.T) {
|
||||
c := newCommitteeIDs()
|
||||
slot := uint64(100)
|
||||
committeeIDs := c.GetAggregatorCommitteeIDs(slot)
|
||||
if len(committeeIDs) != 0 {
|
||||
t.Errorf("Empty cache returned an object: %v", committeeIDs)
|
||||
}
|
||||
|
||||
c.AddAggregatorCommiteeID(slot, 1)
|
||||
res := c.GetAggregatorCommitteeIDs(slot)
|
||||
if !reflect.DeepEqual(res, []uint64{1}) {
|
||||
t.Error("Expected equal value to return from cache")
|
||||
}
|
||||
|
||||
c.AddAggregatorCommiteeID(slot, 2)
|
||||
res = c.GetAggregatorCommitteeIDs(slot)
|
||||
if !reflect.DeepEqual(res, []uint64{1, 2}) {
|
||||
t.Error("Expected equal value to return from cache")
|
||||
}
|
||||
|
||||
c.AddAggregatorCommiteeID(slot, 3)
|
||||
res = c.GetAggregatorCommitteeIDs(slot)
|
||||
if !reflect.DeepEqual(res, []uint64{1, 2, 3}) {
|
||||
t.Error("Expected equal value to return from cache")
|
||||
}
|
||||
|
||||
committeeIDs = c.GetAttesterCommitteeIDs(slot)
|
||||
if len(committeeIDs) != 0 {
|
||||
t.Errorf("Empty cache returned an object: %v", committeeIDs)
|
||||
}
|
||||
|
||||
c.AddAttesterCommiteeID(slot, 11)
|
||||
res = c.GetAttesterCommitteeIDs(slot)
|
||||
if !reflect.DeepEqual(res, []uint64{11}) {
|
||||
t.Error("Expected equal value to return from cache")
|
||||
}
|
||||
|
||||
c.AddAttesterCommiteeID(slot, 22)
|
||||
res = c.GetAttesterCommitteeIDs(slot)
|
||||
if !reflect.DeepEqual(res, []uint64{11, 22}) {
|
||||
t.Error("Expected equal value to return from cache")
|
||||
}
|
||||
|
||||
c.AddAttesterCommiteeID(slot, 33)
|
||||
res = c.GetAttesterCommitteeIDs(slot)
|
||||
if !reflect.DeepEqual(res, []uint64{11, 22, 33}) {
|
||||
t.Error("Expected equal value to return from cache")
|
||||
}
|
||||
}
|
||||
20
beacon-chain/cache/committee_test.go
vendored
20
beacon-chain/cache/committee_test.go
vendored
@@ -1,6 +1,7 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"math"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
@@ -172,3 +173,22 @@ func TestCommitteeCache_CanRotate(t *testing.T) {
|
||||
t.Error("incorrect key received for slot 199")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommitteeCacheOutOfRange(t *testing.T) {
|
||||
cache := NewCommitteesCache()
|
||||
seed := bytesutil.ToBytes32([]byte("foo"))
|
||||
err := cache.CommitteeCache.Add(&Committees{
|
||||
CommitteeCount: 1,
|
||||
Seed: seed,
|
||||
ShuffledIndices: []uint64{0},
|
||||
SortedIndices: []uint64{},
|
||||
ProposerIndices: []uint64{},
|
||||
})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
_, err = cache.Committee(0, seed, math.MaxUint64) // Overflow!
|
||||
if err == nil {
|
||||
t.Fatal("Did not fail as expected")
|
||||
}
|
||||
}
|
||||
|
||||
8
beacon-chain/cache/common.go
vendored
8
beacon-chain/cache/common.go
vendored
@@ -14,8 +14,12 @@ var (
|
||||
// trim the FIFO queue to the maxSize.
|
||||
func trim(queue *cache.FIFO, maxSize int) {
|
||||
for s := len(queue.ListKeys()); s > maxSize; s-- {
|
||||
// #nosec G104 popProcessNoopFunc never returns an error
|
||||
_, _ = queue.Pop(popProcessNoopFunc)
|
||||
_, err := queue.Pop(popProcessNoopFunc)
|
||||
if err != nil {
|
||||
// popProcessNoopFunc never returns an error, but we handle this anyway to make linter
|
||||
// happy.
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/gogo/protobuf/proto"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
dbpb "github.com/prysmaticlabs/prysm/proto/beacon/db"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
)
|
||||
|
||||
var _ = PendingDepositsFetcher(&DepositCache{})
|
||||
@@ -33,8 +34,12 @@ func TestInsertPendingDeposit_ignoresNilDeposit(t *testing.T) {
|
||||
|
||||
func TestRemovePendingDeposit_OK(t *testing.T) {
|
||||
db := DepositCache{}
|
||||
depToRemove := ðpb.Deposit{Proof: [][]byte{[]byte("A")}}
|
||||
otherDep := ðpb.Deposit{Proof: [][]byte{[]byte("B")}}
|
||||
proof1 := make([][]byte, 33)
|
||||
proof1[0] = bytesutil.PadTo([]byte{'A'}, 32)
|
||||
proof2 := make([][]byte, 33)
|
||||
proof2[0] = bytesutil.PadTo([]byte{'A'}, 32)
|
||||
depToRemove := ðpb.Deposit{Proof: proof1}
|
||||
otherDep := ðpb.Deposit{Proof: proof2}
|
||||
db.pendingDeposits = []*dbpb.DepositContainer{
|
||||
{Deposit: depToRemove, Index: 1},
|
||||
{Deposit: otherDep, Index: 5},
|
||||
@@ -57,7 +62,9 @@ func TestRemovePendingDeposit_IgnoresNilDeposit(t *testing.T) {
|
||||
|
||||
func TestPendingDeposit_RoundTrip(t *testing.T) {
|
||||
dc := DepositCache{}
|
||||
dep := ðpb.Deposit{Proof: [][]byte{[]byte("A")}}
|
||||
proof := make([][]byte, 33)
|
||||
proof[0] = bytesutil.PadTo([]byte{'A'}, 32)
|
||||
dep := ðpb.Deposit{Proof: proof}
|
||||
dc.InsertPendingDeposit(context.Background(), dep, 111, 100, [32]byte{})
|
||||
dc.RemovePendingDeposit(context.Background(), dep)
|
||||
if len(dc.pendingDeposits) != 0 {
|
||||
|
||||
5
beacon-chain/cache/eth1_data.go
vendored
5
beacon-chain/cache/eth1_data.go
vendored
@@ -125,7 +125,10 @@ func (c *Eth1DataVoteCache) IncrementEth1DataVote(eth1DataHash [32]byte) (uint64
|
||||
|
||||
eth1DataVoteCacheHit.Inc()
|
||||
|
||||
eInfo, _ := obj.(*Eth1DataVote)
|
||||
eInfo, ok := obj.(*Eth1DataVote)
|
||||
if !ok {
|
||||
return 0, errors.New("cached value is not of type *Eth1DataVote")
|
||||
}
|
||||
eInfo.VoteCount++
|
||||
|
||||
if err := c.eth1DataVoteCache.Add(eInfo); err != nil {
|
||||
|
||||
7
beacon-chain/cache/eth1_data_test.go
vendored
7
beacon-chain/cache/eth1_data_test.go
vendored
@@ -74,8 +74,11 @@ func TestEth1DataVoteCache_CanIncrement(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, _ = cache.IncrementEth1DataVote(eInfo.Eth1DataHash)
|
||||
count, _ := cache.IncrementEth1DataVote(eInfo.Eth1DataHash)
|
||||
_, err = cache.IncrementEth1DataVote(eInfo.Eth1DataHash)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
count, err := cache.IncrementEth1DataVote(eInfo.Eth1DataHash)
|
||||
|
||||
if count != 58 {
|
||||
t.Errorf(
|
||||
|
||||
28
beacon-chain/cache/skip_slot_cache.go
vendored
28
beacon-chain/cache/skip_slot_cache.go
vendored
@@ -10,7 +10,7 @@ import (
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -29,6 +29,7 @@ var (
|
||||
type SkipSlotCache struct {
|
||||
cache *lru.Cache
|
||||
lock sync.RWMutex
|
||||
disabled bool // Allow for programmatic toggling of the cache, useful during initial sync.
|
||||
inProgress map[uint64]bool
|
||||
}
|
||||
|
||||
@@ -44,10 +45,22 @@ func NewSkipSlotCache() *SkipSlotCache {
|
||||
}
|
||||
}
|
||||
|
||||
// Enable the skip slot cache.
|
||||
func (c *SkipSlotCache) Enable() {
|
||||
c.disabled = false
|
||||
}
|
||||
|
||||
// Disable the skip slot cache.
|
||||
func (c *SkipSlotCache) Disable() {
|
||||
c.disabled = true
|
||||
}
|
||||
|
||||
// Get waits for any in progress calculation to complete before returning a
|
||||
// cached response, if any.
|
||||
func (c *SkipSlotCache) Get(ctx context.Context, slot uint64) (*stateTrie.BeaconState, error) {
|
||||
if !featureconfig.Get().EnableSkipSlotsCache {
|
||||
ctx, span := trace.StartSpan(ctx, "skipSlotCache.Get")
|
||||
defer span.End()
|
||||
if c.disabled {
|
||||
// Return a miss result if cache is not enabled.
|
||||
skipSlotCacheMiss.Inc()
|
||||
return nil, nil
|
||||
@@ -57,6 +70,7 @@ func (c *SkipSlotCache) Get(ctx context.Context, slot uint64) (*stateTrie.Beacon
|
||||
|
||||
// Another identical request may be in progress already. Let's wait until
|
||||
// any in progress request resolves or our timeout is exceeded.
|
||||
inProgress := false
|
||||
for {
|
||||
if ctx.Err() != nil {
|
||||
return nil, ctx.Err()
|
||||
@@ -67,6 +81,7 @@ func (c *SkipSlotCache) Get(ctx context.Context, slot uint64) (*stateTrie.Beacon
|
||||
c.lock.RUnlock()
|
||||
break
|
||||
}
|
||||
inProgress = true
|
||||
c.lock.RUnlock()
|
||||
|
||||
// This increasing backoff is to decrease the CPU cycles while waiting
|
||||
@@ -75,21 +90,24 @@ func (c *SkipSlotCache) Get(ctx context.Context, slot uint64) (*stateTrie.Beacon
|
||||
delay *= delayFactor
|
||||
delay = math.Min(delay, maxDelay)
|
||||
}
|
||||
span.AddAttributes(trace.BoolAttribute("inProgress", inProgress))
|
||||
|
||||
item, exists := c.cache.Get(slot)
|
||||
|
||||
if exists && item != nil {
|
||||
skipSlotCacheHit.Inc()
|
||||
span.AddAttributes(trace.BoolAttribute("hit", true))
|
||||
return item.(*stateTrie.BeaconState).Copy(), nil
|
||||
}
|
||||
skipSlotCacheMiss.Inc()
|
||||
span.AddAttributes(trace.BoolAttribute("hit", false))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// MarkInProgress a request so that any other similar requests will block on
|
||||
// Get until MarkNotInProgress is called.
|
||||
func (c *SkipSlotCache) MarkInProgress(slot uint64) error {
|
||||
if !featureconfig.Get().EnableSkipSlotsCache {
|
||||
if c.disabled {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -106,7 +124,7 @@ func (c *SkipSlotCache) MarkInProgress(slot uint64) error {
|
||||
// MarkNotInProgress will release the lock on a given request. This should be
|
||||
// called after put.
|
||||
func (c *SkipSlotCache) MarkNotInProgress(slot uint64) error {
|
||||
if !featureconfig.Get().EnableSkipSlotsCache {
|
||||
if c.disabled {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -119,7 +137,7 @@ func (c *SkipSlotCache) MarkNotInProgress(slot uint64) error {
|
||||
|
||||
// Put the response in the cache.
|
||||
func (c *SkipSlotCache) Put(ctx context.Context, slot uint64, state *stateTrie.BeaconState) error {
|
||||
if !featureconfig.Get().EnableSkipSlotsCache {
|
||||
if c.disabled {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
4
beacon-chain/cache/skip_slot_cache_test.go
vendored
4
beacon-chain/cache/skip_slot_cache_test.go
vendored
@@ -8,15 +8,11 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
)
|
||||
|
||||
func TestSkipSlotCache_RoundTrip(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
c := cache.NewSkipSlotCache()
|
||||
fc := featureconfig.Get()
|
||||
fc.EnableSkipSlotsCache = true
|
||||
featureconfig.Init(fc)
|
||||
|
||||
state, err := c.Get(ctx, 5)
|
||||
if err != nil {
|
||||
|
||||
65
beacon-chain/cache/state_summary.go
vendored
Normal file
65
beacon-chain/cache/state_summary.go
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
)
|
||||
|
||||
// StateSummaryCache caches state summary object.
|
||||
type StateSummaryCache struct {
|
||||
initSyncStateSummaries map[[32]byte]*pb.StateSummary
|
||||
initSyncStateSummariesLock sync.RWMutex
|
||||
}
|
||||
|
||||
// NewStateSummaryCache creates a new state summary cache.
|
||||
func NewStateSummaryCache() *StateSummaryCache {
|
||||
return &StateSummaryCache{
|
||||
initSyncStateSummaries: make(map[[32]byte]*pb.StateSummary),
|
||||
}
|
||||
}
|
||||
|
||||
// Put saves a state summary to the initial sync state summaries cache.
|
||||
func (s *StateSummaryCache) Put(r [32]byte, b *pb.StateSummary) {
|
||||
s.initSyncStateSummariesLock.Lock()
|
||||
defer s.initSyncStateSummariesLock.Unlock()
|
||||
s.initSyncStateSummaries[r] = b
|
||||
}
|
||||
|
||||
// Has checks if a state summary exists in the initial sync state summaries cache using the root
|
||||
// of the block.
|
||||
func (s *StateSummaryCache) Has(r [32]byte) bool {
|
||||
s.initSyncStateSummariesLock.RLock()
|
||||
defer s.initSyncStateSummariesLock.RUnlock()
|
||||
_, ok := s.initSyncStateSummaries[r]
|
||||
return ok
|
||||
}
|
||||
|
||||
// Get retrieves a state summary from the initial sync state summaries cache using the root of
|
||||
// the block.
|
||||
func (s *StateSummaryCache) Get(r [32]byte) *pb.StateSummary {
|
||||
s.initSyncStateSummariesLock.RLock()
|
||||
defer s.initSyncStateSummariesLock.RUnlock()
|
||||
b := s.initSyncStateSummaries[r]
|
||||
return b
|
||||
}
|
||||
|
||||
// GetAll retrieves all the beacon state summaries from the initial sync state summaries cache, the returned
|
||||
// state summaries are unordered.
|
||||
func (s *StateSummaryCache) GetAll() []*pb.StateSummary {
|
||||
s.initSyncStateSummariesLock.RLock()
|
||||
defer s.initSyncStateSummariesLock.RUnlock()
|
||||
|
||||
blks := make([]*pb.StateSummary, 0, len(s.initSyncStateSummaries))
|
||||
for _, b := range s.initSyncStateSummaries {
|
||||
blks = append(blks, b)
|
||||
}
|
||||
return blks
|
||||
}
|
||||
|
||||
// Clear clears out the initial sync state summaries cache.
|
||||
func (s *StateSummaryCache) Clear() {
|
||||
s.initSyncStateSummariesLock.Lock()
|
||||
defer s.initSyncStateSummariesLock.Unlock()
|
||||
s.initSyncStateSummaries = make(map[[32]byte]*pb.StateSummary)
|
||||
}
|
||||
@@ -42,6 +42,7 @@ go_test(
|
||||
srcs = [
|
||||
"block_operations_fuzz_test.go",
|
||||
"block_operations_test.go",
|
||||
"block_regression_test.go",
|
||||
"block_test.go",
|
||||
"eth1_data_test.go",
|
||||
],
|
||||
@@ -49,6 +50,7 @@ go_test(
|
||||
deps = [
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//beacon-chain/state/stateutil:go_default_library",
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/attestationutil:go_default_library",
|
||||
"//shared/bls:go_default_library",
|
||||
|
||||
@@ -35,31 +35,8 @@ var log = logrus.WithField("prefix", "blocks")
|
||||
|
||||
var eth1DataCache = cache.NewEth1DataVoteCache()
|
||||
|
||||
// ErrSigFailedToVerify returns when a signature of a block object(ie attestation, slashing, exit... etc)
|
||||
// failed to verify.
|
||||
var ErrSigFailedToVerify = errors.New("signature did not verify")
|
||||
|
||||
func verifySigningRoot(obj interface{}, pub []byte, signature []byte, domain uint64) error {
|
||||
publicKey, err := bls.PublicKeyFromBytes(pub)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not convert bytes to public key")
|
||||
}
|
||||
sig, err := bls.SignatureFromBytes(signature)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not convert bytes to signature")
|
||||
}
|
||||
root, err := ssz.HashTreeRoot(obj)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get signing root")
|
||||
}
|
||||
if !sig.Verify(root[:], publicKey, domain) {
|
||||
return ErrSigFailedToVerify
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Deprecated: This method uses deprecated ssz.SigningRoot.
|
||||
func verifyDepositDataSigningRoot(obj *ethpb.Deposit_Data, pub []byte, signature []byte, domain uint64) error {
|
||||
func verifyDepositDataSigningRoot(obj *ethpb.Deposit_Data, pub []byte, signature []byte, domain []byte) error {
|
||||
publicKey, err := bls.PublicKeyFromBytes(pub)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not convert bytes to public key")
|
||||
@@ -72,13 +49,21 @@ func verifyDepositDataSigningRoot(obj *ethpb.Deposit_Data, pub []byte, signature
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get signing root")
|
||||
}
|
||||
if !sig.Verify(root[:], publicKey, domain) {
|
||||
return ErrSigFailedToVerify
|
||||
sigRoot := &pb.SigningRoot{
|
||||
ObjectRoot: root[:],
|
||||
Domain: domain,
|
||||
}
|
||||
ctrRoot, err := ssz.HashTreeRoot(sigRoot)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get container root")
|
||||
}
|
||||
if !sig.Verify(ctrRoot[:], publicKey) {
|
||||
return helpers.ErrSigFailedToVerify
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func verifySignature(signedData []byte, pub []byte, signature []byte, domain uint64) error {
|
||||
func verifySignature(signedData []byte, pub []byte, signature []byte, domain []byte) error {
|
||||
publicKey, err := bls.PublicKeyFromBytes(pub)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not convert bytes to public key")
|
||||
@@ -87,8 +72,16 @@ func verifySignature(signedData []byte, pub []byte, signature []byte, domain uin
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not convert bytes to signature")
|
||||
}
|
||||
if !sig.Verify(signedData, publicKey, domain) {
|
||||
return ErrSigFailedToVerify
|
||||
ctr := &pb.SigningRoot{
|
||||
ObjectRoot: signedData,
|
||||
Domain: domain,
|
||||
}
|
||||
root, err := ssz.HashTreeRoot(ctr)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not hash container")
|
||||
}
|
||||
if !sig.Verify(root[:], publicKey) {
|
||||
return helpers.ErrSigFailedToVerify
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -100,7 +93,7 @@ func verifySignature(signedData []byte, pub []byte, signature []byte, domain uin
|
||||
// Official spec definition:
|
||||
// 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 > SLOTS_PER_ETH1_VOTING_PERIOD:
|
||||
// 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(beaconState *stateTrie.BeaconState, block *ethpb.BeaconBlock) (*stateTrie.BeaconState, error) {
|
||||
if beaconState == nil {
|
||||
@@ -151,7 +144,6 @@ func Eth1DataHasEnoughSupport(beaconState *stateTrie.BeaconState, data *ethpb.Et
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "could not retrieve eth1 data vote cache")
|
||||
}
|
||||
|
||||
}
|
||||
if voteCount == 0 {
|
||||
for _, vote := range beaconState.Eth1DataVotes() {
|
||||
@@ -174,7 +166,8 @@ func Eth1DataHasEnoughSupport(beaconState *stateTrie.BeaconState, data *ethpb.Et
|
||||
|
||||
// If 50+% majority converged on the same eth1data, then it has enough support to update the
|
||||
// state.
|
||||
return voteCount*2 > params.BeaconConfig().SlotsPerEth1VotingPeriod, nil
|
||||
support := params.BeaconConfig().EpochsPerEth1VotingPeriod * params.BeaconConfig().SlotsPerEpoch
|
||||
return voteCount*2 > support, nil
|
||||
}
|
||||
|
||||
// ProcessBlockHeader validates a block by its header.
|
||||
@@ -184,6 +177,8 @@ func Eth1DataHasEnoughSupport(beaconState *stateTrie.BeaconState, data *ethpb.Et
|
||||
// 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
|
||||
// assert block.proposer_index == get_beacon_proposer_index(state)
|
||||
// # Verify that the parent matches
|
||||
// assert block.parent_root == signing_root(state.latest_block_header)
|
||||
// # Save current block as the new latest block
|
||||
@@ -208,28 +203,29 @@ func ProcessBlockHeader(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
idx, err := helpers.BeaconProposerIndex(beaconState)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
proposer, err := beaconState.ValidatorAtIndex(idx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Verify proposer signature.
|
||||
currentEpoch := helpers.SlotToEpoch(beaconState.Slot())
|
||||
domain, err := helpers.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainBeaconProposer)
|
||||
if err != nil {
|
||||
if err := VerifyBlockHeaderSignature(beaconState, block); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := verifySigningRoot(block.Block, proposer.PublicKey, block.Signature, domain); err != nil {
|
||||
return nil, ErrSigFailedToVerify
|
||||
}
|
||||
|
||||
return beaconState, nil
|
||||
}
|
||||
|
||||
// VerifyBlockHeaderSignature verifies the proposer signature of a beacon block.
|
||||
func VerifyBlockHeaderSignature(beaconState *stateTrie.BeaconState, block *ethpb.SignedBeaconBlock) error {
|
||||
proposer, err := beaconState.ValidatorAtIndex(block.Block.ProposerIndex)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
currentEpoch := helpers.SlotToEpoch(beaconState.Slot())
|
||||
domain, err := helpers.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainBeaconProposer, beaconState.GenesisValidatorRoot())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return helpers.VerifySigningRoot(block.Block, proposer.PublicKey, block.Signature, domain)
|
||||
}
|
||||
|
||||
// ProcessBlockHeaderNoVerify validates a block by its header but skips proposer
|
||||
// signature verification.
|
||||
//
|
||||
@@ -240,6 +236,8 @@ 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
|
||||
// assert block.proposer_index == get_beacon_proposer_index(state)
|
||||
// # Verify that the parent matches
|
||||
// assert block.parent_root == signing_root(state.latest_block_header)
|
||||
// # Save current block as the new latest block
|
||||
@@ -261,7 +259,14 @@ func ProcessBlockHeaderNoVerify(
|
||||
return nil, errors.New("nil block")
|
||||
}
|
||||
if beaconState.Slot() != block.Slot {
|
||||
return nil, fmt.Errorf("state slot: %d is different then block slot: %d", beaconState.Slot(), block.Slot)
|
||||
return nil, fmt.Errorf("state slot: %d is different than block slot: %d", beaconState.Slot(), block.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)
|
||||
}
|
||||
parentRoot, err := stateutil.BlockHeaderRoot(beaconState.LatestBlockHeader())
|
||||
if err != nil {
|
||||
@@ -274,10 +279,6 @@ func ProcessBlockHeaderNoVerify(
|
||||
block.ParentRoot, parentRoot)
|
||||
}
|
||||
|
||||
idx, err := helpers.BeaconProposerIndex(beaconState)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
proposer, err := beaconState.ValidatorAtIndex(idx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -286,15 +287,16 @@ func ProcessBlockHeaderNoVerify(
|
||||
return nil, fmt.Errorf("proposer at index %d was previously slashed", idx)
|
||||
}
|
||||
|
||||
bodyRoot, err := ssz.HashTreeRoot(block.Body)
|
||||
bodyRoot, err := stateutil.BlockBodyRoot(block.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := beaconState.SetLatestBlockHeader(ðpb.BeaconBlockHeader{
|
||||
Slot: block.Slot,
|
||||
ParentRoot: block.ParentRoot,
|
||||
StateRoot: params.BeaconConfig().ZeroHash[:],
|
||||
BodyRoot: bodyRoot[:],
|
||||
Slot: block.Slot,
|
||||
ProposerIndex: block.ProposerIndex,
|
||||
ParentRoot: block.ParentRoot,
|
||||
StateRoot: params.BeaconConfig().ZeroHash[:],
|
||||
BodyRoot: bodyRoot[:],
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -334,7 +336,7 @@ func ProcessRandao(
|
||||
buf := make([]byte, 32)
|
||||
binary.LittleEndian.PutUint64(buf, currentEpoch)
|
||||
|
||||
domain, err := helpers.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainRandao)
|
||||
domain, err := helpers.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainRandao, beaconState.GenesisValidatorRoot())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -377,7 +379,7 @@ func ProcessRandaoNoVerify(
|
||||
for i, x := range blockRandaoReveal {
|
||||
latestMixSlice[i] ^= x
|
||||
}
|
||||
if err := beaconState.UpdateRandaoMixesAtIndex(latestMixSlice, currentEpoch%latestMixesLength); err != nil {
|
||||
if err := beaconState.UpdateRandaoMixesAtIndex(currentEpoch%latestMixesLength, latestMixSlice); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return beaconState, nil
|
||||
@@ -415,51 +417,51 @@ func ProcessProposerSlashings(
|
||||
if slashing == nil {
|
||||
return nil, errors.New("nil proposer slashings in block body")
|
||||
}
|
||||
if int(slashing.ProposerIndex) >= beaconState.NumValidators() {
|
||||
return nil, fmt.Errorf("invalid proposer index given in slashing %d", slashing.ProposerIndex)
|
||||
}
|
||||
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.ProposerIndex, 0, /* proposer is whistleblower */
|
||||
beaconState, slashing.Header_1.Header.ProposerIndex, 0, /* proposer is whistleblower */
|
||||
)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not slash proposer index %d", slashing.ProposerIndex)
|
||||
return nil, errors.Wrapf(err, "could not slash proposer index %d", slashing.Header_1.Header.ProposerIndex)
|
||||
}
|
||||
}
|
||||
return beaconState, nil
|
||||
}
|
||||
|
||||
// VerifyProposerSlashing verifies that the data provided fro slashing is valid.
|
||||
// VerifyProposerSlashing verifies that the data provided from slashing is valid.
|
||||
func VerifyProposerSlashing(
|
||||
beaconState *stateTrie.BeaconState,
|
||||
slashing *ethpb.ProposerSlashing,
|
||||
) error {
|
||||
proposer, err := beaconState.ValidatorAtIndex(slashing.ProposerIndex)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if slashing.Header_1 == nil || slashing.Header_1.Header == nil || slashing.Header_2 == nil || slashing.Header_2.Header == nil {
|
||||
return errors.New("nil header cannot be verified")
|
||||
}
|
||||
if slashing.Header_1.Header.Slot != slashing.Header_2.Header.Slot {
|
||||
return fmt.Errorf("mismatched header slots, received %d == %d", slashing.Header_1.Header.Slot, slashing.Header_2.Header.Slot)
|
||||
}
|
||||
if slashing.Header_1.Header.ProposerIndex != slashing.Header_2.Header.ProposerIndex {
|
||||
return fmt.Errorf("mismatched indices, received %d == %d", slashing.Header_1.Header.ProposerIndex, slashing.Header_2.Header.ProposerIndex)
|
||||
}
|
||||
if proto.Equal(slashing.Header_1, slashing.Header_2) {
|
||||
return errors.New("expected slashing headers to differ")
|
||||
}
|
||||
proposer, err := beaconState.ValidatorAtIndex(slashing.Header_1.Header.ProposerIndex)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !helpers.IsSlashableValidator(proposer, helpers.SlotToEpoch(beaconState.Slot())) {
|
||||
return fmt.Errorf("validator with key %#x is not slashable", proposer.PublicKey)
|
||||
}
|
||||
// Using headerEpoch1 here because both of the headers should have the same epoch.
|
||||
domain, err := helpers.Domain(beaconState.Fork(), helpers.StartSlot(slashing.Header_1.Header.Slot), params.BeaconConfig().DomainBeaconProposer)
|
||||
domain, err := helpers.Domain(beaconState.Fork(), helpers.SlotToEpoch(slashing.Header_1.Header.Slot), params.BeaconConfig().DomainBeaconProposer, beaconState.GenesisValidatorRoot())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
headers := []*ethpb.SignedBeaconBlockHeader{slashing.Header_1, slashing.Header_2}
|
||||
for _, header := range headers {
|
||||
if err := verifySigningRoot(header.Header, proposer.PublicKey, header.Signature, domain); err != nil {
|
||||
if err := helpers.VerifySigningRoot(header.Header, proposer.PublicKey, header.Signature, domain); err != nil {
|
||||
return errors.Wrap(err, "could not verify beacon block header")
|
||||
}
|
||||
}
|
||||
@@ -577,7 +579,7 @@ func slashableAttesterIndices(slashing *ethpb.AttesterSlashing) []uint64 {
|
||||
return nil
|
||||
}
|
||||
indices1 := slashing.Attestation_1.AttestingIndices
|
||||
indices2 := slashing.Attestation_1.AttestingIndices
|
||||
indices2 := slashing.Attestation_2.AttestingIndices
|
||||
return sliceutil.IntersectionUint64(indices1, indices2)
|
||||
}
|
||||
|
||||
@@ -808,30 +810,25 @@ func VerifyIndexedAttestation(ctx context.Context, beaconState *stateTrie.Beacon
|
||||
return errors.New("attesting indices is not uniquely sorted")
|
||||
}
|
||||
|
||||
domain, err := helpers.Domain(beaconState.Fork(), indexedAtt.Data.Target.Epoch, params.BeaconConfig().DomainBeaconAttester)
|
||||
domain, err := helpers.Domain(beaconState.Fork(), indexedAtt.Data.Target.Epoch, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorRoot())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var pubkey *bls.PublicKey
|
||||
pubkeys := []*bls.PublicKey{}
|
||||
if len(indices) > 0 {
|
||||
pubkeyAtIdx := beaconState.PubkeyAtIndex(indices[0])
|
||||
pubkey, err = bls.PublicKeyFromBytes(pubkeyAtIdx[:])
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not deserialize validator public key")
|
||||
}
|
||||
for i := 1; i < len(indices); i++ {
|
||||
pubkeyAtIdx = beaconState.PubkeyAtIndex(indices[i])
|
||||
for i := 0; i < len(indices); i++ {
|
||||
pubkeyAtIdx := beaconState.PubkeyAtIndex(indices[i])
|
||||
pk, err := bls.PublicKeyFromBytes(pubkeyAtIdx[:])
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not deserialize validator public key")
|
||||
}
|
||||
pubkey.Aggregate(pk)
|
||||
pubkeys = append(pubkeys, pk)
|
||||
}
|
||||
}
|
||||
|
||||
messageHash, err := ssz.HashTreeRoot(indexedAtt.Data)
|
||||
messageHash, err := helpers.ComputeSigningRoot(indexedAtt.Data, domain)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not tree hash att data")
|
||||
return errors.Wrap(err, "could not get signing root of object")
|
||||
}
|
||||
|
||||
sig, err := bls.SignatureFromBytes(indexedAtt.Signature)
|
||||
@@ -840,8 +837,8 @@ func VerifyIndexedAttestation(ctx context.Context, beaconState *stateTrie.Beacon
|
||||
}
|
||||
|
||||
voted := len(indices) > 0
|
||||
if voted && !sig.Verify(messageHash[:], pubkey, domain) {
|
||||
return ErrSigFailedToVerify
|
||||
if voted && !sig.FastAggregateVerify(pubkeys, messageHash) {
|
||||
return helpers.ErrSigFailedToVerify
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -856,10 +853,7 @@ func VerifyAttestation(ctx context.Context, beaconState *stateTrie.BeaconState,
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
indexedAtt, err := attestationutil.ConvertToIndexed(ctx, att, committee)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not convert to indexed attestation")
|
||||
}
|
||||
indexedAtt := attestationutil.ConvertToIndexed(ctx, att, committee)
|
||||
return VerifyIndexedAttestation(ctx, beaconState, indexedAtt)
|
||||
}
|
||||
|
||||
@@ -986,11 +980,14 @@ func ProcessDeposit(
|
||||
index, ok := beaconState.ValidatorIndexByPubkey(bytesutil.ToBytes48(pubKey))
|
||||
numVals := beaconState.NumValidators()
|
||||
if !ok {
|
||||
domain := bls.ComputeDomain(params.BeaconConfig().DomainDeposit)
|
||||
domain, err := helpers.ComputeDomain(params.BeaconConfig().DomainDeposit, nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
depositSig := deposit.Data.Signature
|
||||
if err := verifyDepositDataSigningRoot(deposit.Data, pubKey, depositSig, domain); err != nil {
|
||||
// Ignore this error as in the spec pseudo code.
|
||||
log.Errorf("Skipping deposit: could not verify deposit data signature: %v", err)
|
||||
log.Debugf("Skipping deposit: could not verify deposit data signature: %v", err)
|
||||
return beaconState, nil
|
||||
}
|
||||
|
||||
@@ -1096,7 +1093,7 @@ func ProcessVoluntaryExits(
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := VerifyExit(val, beaconState.Slot(), beaconState.Fork(), exit); err != nil {
|
||||
if err := VerifyExit(val, beaconState.Slot(), beaconState.Fork(), exit, beaconState.GenesisValidatorRoot()); err != nil {
|
||||
return nil, errors.Wrapf(err, "could not verify exit %d", idx)
|
||||
}
|
||||
beaconState, err = v.InitiateValidatorExit(beaconState, exit.Exit.ValidatorIndex)
|
||||
@@ -1147,7 +1144,7 @@ func ProcessVoluntaryExitsNoVerify(
|
||||
// # Verify signature
|
||||
// domain = get_domain(state, DOMAIN_VOLUNTARY_EXIT, exit.epoch)
|
||||
// assert bls_verify(validator.pubkey, signing_root(exit), exit.signature, domain)
|
||||
func VerifyExit(validator *ethpb.Validator, currentSlot uint64, fork *pb.Fork, signed *ethpb.SignedVoluntaryExit) error {
|
||||
func VerifyExit(validator *ethpb.Validator, currentSlot uint64, fork *pb.Fork, signed *ethpb.SignedVoluntaryExit, genesisRoot []byte) error {
|
||||
if signed == nil || signed.Exit == nil {
|
||||
return errors.New("nil exit")
|
||||
}
|
||||
@@ -1174,12 +1171,12 @@ func VerifyExit(validator *ethpb.Validator, currentSlot uint64, fork *pb.Fork, s
|
||||
validator.ActivationEpoch+params.BeaconConfig().PersistentCommitteePeriod,
|
||||
)
|
||||
}
|
||||
domain, err := helpers.Domain(fork, exit.Epoch, params.BeaconConfig().DomainVoluntaryExit)
|
||||
domain, err := helpers.Domain(fork, exit.Epoch, params.BeaconConfig().DomainVoluntaryExit, genesisRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := verifySigningRoot(exit, validator.PublicKey, signed.Signature, domain); err != nil {
|
||||
return ErrSigFailedToVerify
|
||||
if err := helpers.VerifySigningRoot(exit, validator.PublicKey, signed.Signature, domain); err != nil {
|
||||
return helpers.ErrSigFailedToVerify
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -4,12 +4,11 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
fuzz "github.com/google/gofuzz"
|
||||
eth "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
|
||||
fuzz "github.com/google/gofuzz"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
|
||||
//"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
@@ -25,8 +24,13 @@ func TestFuzzProcessAttestationNoVerify_10000(t *testing.T) {
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(att)
|
||||
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
_, _ = ProcessAttestationNoVerify(ctx, s, att)
|
||||
s, err := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
if _, err = ProcessAttestationNoVerify(ctx, s, att); err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,33 +43,13 @@ func TestFuzzProcessBlockHeader_10000(t *testing.T) {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(block)
|
||||
|
||||
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
_, _ = ProcessBlockHeader(s, block)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFuzzverifySigningRoot_10000(t *testing.T) {
|
||||
fuzzer := fuzz.NewWithSeed(0)
|
||||
state := ðereum_beacon_p2p_v1.BeaconState{}
|
||||
pubkey := [48]byte{}
|
||||
sig := [96]byte{}
|
||||
domain := [4]byte{}
|
||||
p := []byte{}
|
||||
s := []byte{}
|
||||
d := uint64(0)
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(&pubkey)
|
||||
fuzzer.Fuzz(&sig)
|
||||
fuzzer.Fuzz(&domain)
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(&p)
|
||||
fuzzer.Fuzz(&s)
|
||||
fuzzer.Fuzz(&d)
|
||||
domain := bytesutil.FromBytes4(domain[:])
|
||||
verifySigningRoot(state, pubkey[:], sig[:], domain)
|
||||
verifySigningRoot(state, p, s, d)
|
||||
|
||||
s, err := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
if _, err = ProcessBlockHeader(s, block); err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +61,7 @@ func TestFuzzverifyDepositDataSigningRoot_10000(t *testing.T) {
|
||||
domain := [4]byte{}
|
||||
p := []byte{}
|
||||
s := []byte{}
|
||||
d := uint64(0)
|
||||
d := []byte{}
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(&ba)
|
||||
fuzzer.Fuzz(&pubkey)
|
||||
@@ -86,9 +70,13 @@ func TestFuzzverifyDepositDataSigningRoot_10000(t *testing.T) {
|
||||
fuzzer.Fuzz(&p)
|
||||
fuzzer.Fuzz(&s)
|
||||
fuzzer.Fuzz(&d)
|
||||
domain := bytesutil.FromBytes4(domain[:])
|
||||
verifySignature(ba, pubkey[:], sig[:], domain)
|
||||
verifySignature(ba, p, s, d)
|
||||
if err := verifySignature(ba, pubkey[:], sig[:], domain[:]); err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
if err := verifySignature(ba, p, s, d); err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,10 +114,15 @@ func TestFuzzEth1DataHasEnoughSupport_10000(t *testing.T) {
|
||||
for i := 0; i < 100000; i++ {
|
||||
fuzzer.Fuzz(eth1data)
|
||||
fuzzer.Fuzz(&stateVotes)
|
||||
s, _ := beaconstate.InitializeFromProto(ðereum_beacon_p2p_v1.BeaconState{
|
||||
s, err := beaconstate.InitializeFromProto(ðereum_beacon_p2p_v1.BeaconState{
|
||||
Eth1DataVotes: stateVotes,
|
||||
})
|
||||
Eth1DataHasEnoughSupport(s, eth1data)
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
if _, err := Eth1DataHasEnoughSupport(s, eth1data); err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -142,8 +135,13 @@ func TestFuzzProcessBlockHeaderNoVerify_10000(t *testing.T) {
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(block)
|
||||
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
_, _ = ProcessBlockHeaderNoVerify(s, block)
|
||||
s, err := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
if _, err = ProcessBlockHeaderNoVerify(s, block); err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,7 +153,10 @@ func TestFuzzProcessRandao_10000(t *testing.T) {
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(blockBody)
|
||||
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
s, err := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
r, err := ProcessRandao(s, blockBody)
|
||||
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)
|
||||
@@ -171,7 +172,10 @@ func TestFuzzProcessRandaoNoVerify_10000(t *testing.T) {
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(blockBody)
|
||||
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
s, err := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
r, err := ProcessRandaoNoVerify(s, blockBody)
|
||||
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)
|
||||
@@ -187,7 +191,10 @@ func TestFuzzProcessProposerSlashings_10000(t *testing.T) {
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(blockBody)
|
||||
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
s, err := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
r, err := ProcessProposerSlashings(ctx, s, blockBody)
|
||||
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)
|
||||
@@ -202,8 +209,13 @@ func TestFuzzVerifyProposerSlashing_10000(t *testing.T) {
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(proposerSlashing)
|
||||
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
VerifyProposerSlashing(s, proposerSlashing)
|
||||
s, err := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
if err := VerifyProposerSlashing(s, proposerSlashing); err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,7 +227,10 @@ func TestFuzzProcessAttesterSlashings_10000(t *testing.T) {
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(blockBody)
|
||||
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
s, err := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
r, err := ProcessAttesterSlashings(ctx, s, blockBody)
|
||||
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)
|
||||
@@ -231,8 +246,13 @@ func TestFuzzVerifyAttesterSlashing_10000(t *testing.T) {
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(attesterSlashing)
|
||||
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
VerifyAttesterSlashing(ctx, s, attesterSlashing)
|
||||
s, err := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
if err := VerifyAttesterSlashing(ctx, s, attesterSlashing); err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -266,7 +286,10 @@ func TestFuzzProcessAttestations_10000(t *testing.T) {
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(blockBody)
|
||||
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
s, err := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
r, err := ProcessAttestations(ctx, s, blockBody)
|
||||
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)
|
||||
@@ -282,7 +305,10 @@ func TestFuzzProcessAttestationsNoVerify_10000(t *testing.T) {
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(blockBody)
|
||||
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
s, err := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
r, err := ProcessAttestationsNoVerify(ctx, s, blockBody)
|
||||
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)
|
||||
@@ -298,7 +324,10 @@ func TestFuzzProcessAttestation_10000(t *testing.T) {
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(attestation)
|
||||
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
s, err := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
r, err := ProcessAttestation(ctx, s, attestation)
|
||||
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, attestation)
|
||||
@@ -314,8 +343,13 @@ func TestFuzzVerifyIndexedAttestationn_10000(t *testing.T) {
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(idxAttestation)
|
||||
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
VerifyIndexedAttestation(ctx, s, idxAttestation)
|
||||
s, err := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
if err := VerifyIndexedAttestation(ctx, s, idxAttestation); err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -327,8 +361,13 @@ func TestFuzzVerifyAttestation_10000(t *testing.T) {
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(attestation)
|
||||
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
VerifyAttestation(ctx, s, attestation)
|
||||
s, err := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
if err := VerifyAttestation(ctx, s, attestation); err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -340,7 +379,10 @@ func TestFuzzProcessDeposits_10000(t *testing.T) {
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(blockBody)
|
||||
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
s, err := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
r, err := ProcessDeposits(ctx, s, blockBody)
|
||||
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)
|
||||
@@ -357,7 +399,10 @@ func TestFuzzProcessPreGenesisDeposit_10000(t *testing.T) {
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(deposit)
|
||||
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
s, err := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
r, err := ProcessPreGenesisDeposit(ctx, s, deposit)
|
||||
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, deposit)
|
||||
@@ -373,7 +418,10 @@ func TestFuzzProcessDeposit_10000(t *testing.T) {
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(deposit)
|
||||
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
s, err := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
r, err := ProcessDeposit(s, deposit)
|
||||
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, deposit)
|
||||
@@ -388,8 +436,13 @@ func TestFuzzverifyDeposit_10000(t *testing.T) {
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(deposit)
|
||||
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
verifyDeposit(s, deposit)
|
||||
s, err := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
if err := verifyDeposit(s, deposit); err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -401,7 +454,10 @@ func TestFuzzProcessVoluntaryExits_10000(t *testing.T) {
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(blockBody)
|
||||
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
s, err := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
r, err := ProcessVoluntaryExits(ctx, s, blockBody)
|
||||
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)
|
||||
@@ -416,7 +472,10 @@ func TestFuzzProcessVoluntaryExitsNoVerify_10000(t *testing.T) {
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(blockBody)
|
||||
s, _ := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
s, err := beaconstate.InitializeFromProtoUnsafe(state)
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
r, err := ProcessVoluntaryExitsNoVerify(s, blockBody)
|
||||
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)
|
||||
@@ -436,6 +495,8 @@ func TestFuzzVerifyExit_10000(t *testing.T) {
|
||||
fuzzer.Fuzz(val)
|
||||
fuzzer.Fuzz(fork)
|
||||
fuzzer.Fuzz(&slot)
|
||||
VerifyExit(val, slot, fork, ve)
|
||||
if err := VerifyExit(val, slot, fork, ve, params.BeaconConfig().ZeroHash[:]); err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
113
beacon-chain/core/blocks/block_regression_test.go
Normal file
113
beacon-chain/core/blocks/block_regression_test.go
Normal file
@@ -0,0 +1,113 @@
|
||||
package blocks_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/shared/bls"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
)
|
||||
|
||||
func TestProcessAttesterSlashings_RegressionSlashableIndices(t *testing.T) {
|
||||
testutil.ResetCache()
|
||||
beaconState, privKeys := testutil.DeterministicGenesisState(t, 5500)
|
||||
for _, vv := range beaconState.Validators() {
|
||||
vv.WithdrawableEpoch = 1 * params.BeaconConfig().SlotsPerEpoch
|
||||
}
|
||||
// This set of indices is very similar to the one from our sapphire testnet
|
||||
// when close to 100 validators were incorrectly slashed. The set is from 0 -5500,
|
||||
// instead of 55000 as it would take too long to generate a state.
|
||||
setA := []uint64{21, 92, 236, 244, 281, 321, 510, 524,
|
||||
538, 682, 828, 858, 913, 920, 922, 959, 1176, 1207,
|
||||
1222, 1229, 1354, 1394, 1436, 1454, 1510, 1550,
|
||||
1552, 1576, 1645, 1704, 1842, 1967, 2076, 2111, 2134, 2307,
|
||||
2343, 2354, 2417, 2524, 2532, 2555, 2740, 2749, 2759, 2762,
|
||||
2800, 2809, 2824, 2987, 3110, 3125, 3559, 3583, 3599, 3608,
|
||||
3657, 3685, 3723, 3756, 3759, 3761, 3820, 3826, 3979, 4030,
|
||||
4141, 4170, 4205, 4247, 4257, 4479, 4492, 4569, 5091,
|
||||
}
|
||||
// Only 2800 is the slashable index.
|
||||
setB := []uint64{1361, 1438, 2383, 2800}
|
||||
expectedSlashedVal := 2800
|
||||
|
||||
root1 := [32]byte{'d', 'o', 'u', 'b', 'l', 'e', '1'}
|
||||
att1 := ðpb.IndexedAttestation{
|
||||
Data: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 0},
|
||||
Target: ðpb.Checkpoint{Epoch: 0, Root: root1[:]},
|
||||
},
|
||||
AttestingIndices: setA,
|
||||
}
|
||||
domain, err := helpers.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorRoot())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
signingRoot, err := helpers.ComputeSigningRoot(att1.Data, domain)
|
||||
if err != nil {
|
||||
t.Errorf("Could not get signing root of beacon block header: %v", err)
|
||||
}
|
||||
aggSigs := []*bls.Signature{}
|
||||
for _, index := range setA {
|
||||
sig := privKeys[index].Sign(signingRoot[:])
|
||||
aggSigs = append(aggSigs, sig)
|
||||
}
|
||||
aggregateSig := bls.AggregateSignatures(aggSigs)
|
||||
att1.Signature = aggregateSig.Marshal()[:]
|
||||
|
||||
root2 := [32]byte{'d', 'o', 'u', 'b', 'l', 'e', '2'}
|
||||
att2 := ðpb.IndexedAttestation{
|
||||
Data: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 0},
|
||||
Target: ðpb.Checkpoint{Epoch: 0, Root: root2[:]},
|
||||
},
|
||||
AttestingIndices: setB,
|
||||
}
|
||||
signingRoot, err = helpers.ComputeSigningRoot(att2.Data, domain)
|
||||
if err != nil {
|
||||
t.Errorf("Could not get signing root of beacon block header: %v", err)
|
||||
}
|
||||
aggSigs = []*bls.Signature{}
|
||||
for _, index := range setB {
|
||||
sig := privKeys[index].Sign(signingRoot[:])
|
||||
aggSigs = append(aggSigs, sig)
|
||||
}
|
||||
aggregateSig = bls.AggregateSignatures(aggSigs)
|
||||
att2.Signature = aggregateSig.Marshal()[:]
|
||||
|
||||
slashings := []*ethpb.AttesterSlashing{
|
||||
{
|
||||
Attestation_1: att1,
|
||||
Attestation_2: att2,
|
||||
},
|
||||
}
|
||||
|
||||
currentSlot := 2 * params.BeaconConfig().SlotsPerEpoch
|
||||
if err := beaconState.SetSlot(currentSlot); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
block := ðpb.BeaconBlock{
|
||||
Body: ðpb.BeaconBlockBody{
|
||||
AttesterSlashings: slashings,
|
||||
},
|
||||
}
|
||||
|
||||
newState, err := blocks.ProcessAttesterSlashings(context.Background(), beaconState, block.Body)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
newRegistry := newState.Validators()
|
||||
if !newRegistry[expectedSlashedVal].Slashed {
|
||||
t.Errorf("Validator with index %d was not slashed despite performing a double vote", expectedSlashedVal)
|
||||
}
|
||||
|
||||
for idx, val := range newRegistry {
|
||||
if val.Slashed && idx != expectedSlashedVal {
|
||||
t.Errorf("validator with index: %d was unintentionally slashed", idx)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,17 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
|
||||
func FakeDeposits(n int) []*ethpb.Eth1Data {
|
||||
deposits := make([]*ethpb.Eth1Data, n)
|
||||
for i := 0; i < n; i++ {
|
||||
deposits[i] = ðpb.Eth1Data{
|
||||
DepositCount: 1,
|
||||
DepositRoot: []byte("root"),
|
||||
}
|
||||
}
|
||||
return deposits
|
||||
}
|
||||
|
||||
func TestEth1DataHasEnoughSupport(t *testing.T) {
|
||||
tests := []struct {
|
||||
stateVotes []*ethpb.Eth1Data
|
||||
@@ -19,21 +30,7 @@ func TestEth1DataHasEnoughSupport(t *testing.T) {
|
||||
votingPeriodLength uint64
|
||||
}{
|
||||
{
|
||||
stateVotes: []*ethpb.Eth1Data{
|
||||
{
|
||||
DepositCount: 1,
|
||||
DepositRoot: []byte("root"),
|
||||
}, {
|
||||
DepositCount: 1,
|
||||
DepositRoot: []byte("root"),
|
||||
}, {
|
||||
DepositCount: 1,
|
||||
DepositRoot: []byte("root"),
|
||||
}, {
|
||||
DepositCount: 1,
|
||||
DepositRoot: []byte("root"),
|
||||
},
|
||||
},
|
||||
stateVotes: FakeDeposits(4 * int(params.BeaconConfig().SlotsPerEpoch)),
|
||||
data: ðpb.Eth1Data{
|
||||
DepositCount: 1,
|
||||
DepositRoot: []byte("root"),
|
||||
@@ -41,21 +38,7 @@ func TestEth1DataHasEnoughSupport(t *testing.T) {
|
||||
hasSupport: true,
|
||||
votingPeriodLength: 7,
|
||||
}, {
|
||||
stateVotes: []*ethpb.Eth1Data{
|
||||
{
|
||||
DepositCount: 1,
|
||||
DepositRoot: []byte("root"),
|
||||
}, {
|
||||
DepositCount: 1,
|
||||
DepositRoot: []byte("root"),
|
||||
}, {
|
||||
DepositCount: 1,
|
||||
DepositRoot: []byte("root"),
|
||||
}, {
|
||||
DepositCount: 1,
|
||||
DepositRoot: []byte("root"),
|
||||
},
|
||||
},
|
||||
stateVotes: FakeDeposits(4 * int(params.BeaconConfig().SlotsPerEpoch)),
|
||||
data: ðpb.Eth1Data{
|
||||
DepositCount: 1,
|
||||
DepositRoot: []byte("root"),
|
||||
@@ -63,21 +46,7 @@ func TestEth1DataHasEnoughSupport(t *testing.T) {
|
||||
hasSupport: false,
|
||||
votingPeriodLength: 8,
|
||||
}, {
|
||||
stateVotes: []*ethpb.Eth1Data{
|
||||
{
|
||||
DepositCount: 1,
|
||||
DepositRoot: []byte("root"),
|
||||
}, {
|
||||
DepositCount: 1,
|
||||
DepositRoot: []byte("root"),
|
||||
}, {
|
||||
DepositCount: 1,
|
||||
DepositRoot: []byte("root"),
|
||||
}, {
|
||||
DepositCount: 1,
|
||||
DepositRoot: []byte("root"),
|
||||
},
|
||||
},
|
||||
stateVotes: FakeDeposits(4 * int(params.BeaconConfig().SlotsPerEpoch)),
|
||||
data: ðpb.Eth1Data{
|
||||
DepositCount: 1,
|
||||
DepositRoot: []byte("root"),
|
||||
@@ -90,12 +59,15 @@ func TestEth1DataHasEnoughSupport(t *testing.T) {
|
||||
for i, tt := range tests {
|
||||
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
|
||||
c := params.BeaconConfig()
|
||||
c.SlotsPerEth1VotingPeriod = tt.votingPeriodLength
|
||||
c.EpochsPerEth1VotingPeriod = tt.votingPeriodLength
|
||||
params.OverrideBeaconConfig(c)
|
||||
|
||||
s, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
s, err := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
Eth1DataVotes: tt.stateVotes,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
result, err := blocks.Eth1DataHasEnoughSupport(s, tt.data)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -103,8 +75,7 @@ func TestEth1DataHasEnoughSupport(t *testing.T) {
|
||||
|
||||
if result != tt.hasSupport {
|
||||
t.Errorf(
|
||||
"blocks.Eth1DataHasEnoughSupport(%+v, %+v) = %t, wanted %t",
|
||||
s,
|
||||
"blocks.Eth1DataHasEnoughSupport(%+v) = %t, wanted %t",
|
||||
tt.data,
|
||||
result,
|
||||
tt.hasSupport,
|
||||
|
||||
@@ -21,6 +21,10 @@ import (
|
||||
"gopkg.in/d4l3k/messagediff.v1"
|
||||
)
|
||||
|
||||
func init() {
|
||||
state.SkipSlotCache.Disable()
|
||||
}
|
||||
|
||||
func runBlockProcessingTest(t *testing.T, config string) {
|
||||
if err := spectest.SetConfig(config); err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -94,8 +98,8 @@ func runBlockProcessingTest(t *testing.T, config string) {
|
||||
t.Fatalf("Failed to unmarshal: %v", err)
|
||||
}
|
||||
|
||||
if !proto.Equal(beaconState.CloneInnerState(), postBeaconState) {
|
||||
diff, _ := messagediff.PrettyDiff(beaconState.CloneInnerState(), postBeaconState)
|
||||
if !proto.Equal(beaconState.InnerStateUnsafe(), postBeaconState) {
|
||||
diff, _ := messagediff.PrettyDiff(beaconState.InnerStateUnsafe(), postBeaconState)
|
||||
t.Log(diff)
|
||||
t.Fatal("Post state does not match expected")
|
||||
}
|
||||
|
||||
@@ -170,7 +170,7 @@ func ProcessSlashings(state *stateTrie.BeaconState) (*stateTrie.BeaconState, err
|
||||
|
||||
// a callback is used here to apply the following actions to all validators
|
||||
// below equally.
|
||||
err = state.ApplyToEveryValidator(func(idx int, val *ethpb.Validator) error {
|
||||
err = state.ApplyToEveryValidator(func(idx int, val *ethpb.Validator) (bool, error) {
|
||||
correctEpoch := (currentEpoch + exitLength/2) == val.WithdrawableEpoch
|
||||
if val.Slashed && correctEpoch {
|
||||
minSlashing := mathutil.Min(totalSlashing*3, totalBalance)
|
||||
@@ -178,10 +178,11 @@ func ProcessSlashings(state *stateTrie.BeaconState) (*stateTrie.BeaconState, err
|
||||
penaltyNumerator := val.EffectiveBalance / increment * minSlashing
|
||||
penalty := penaltyNumerator / totalBalance * increment
|
||||
if err := helpers.DecreaseBalance(state, uint64(idx), penalty); err != nil {
|
||||
return err
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
return nil
|
||||
return false, nil
|
||||
})
|
||||
return state, err
|
||||
}
|
||||
@@ -193,15 +194,18 @@ func ProcessSlashings(state *stateTrie.BeaconState) (*stateTrie.BeaconState, err
|
||||
// current_epoch = get_current_epoch(state)
|
||||
// next_epoch = Epoch(current_epoch + 1)
|
||||
// # Reset eth1 data votes
|
||||
// if (state.slot + 1) % SLOTS_PER_ETH1_VOTING_PERIOD == 0:
|
||||
// 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]
|
||||
// HALF_INCREMENT = EFFECTIVE_BALANCE_INCREMENT // 2
|
||||
// if balance < validator.effective_balance or validator.effective_balance + 3 * HALF_INCREMENT < balance:
|
||||
// validator.effective_balance = min(balance - balance % EFFECTIVE_BALANCE_INCREMENT, MAX_EFFECTIVE_BALANCE)
|
||||
// # Set active index root
|
||||
// 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
|
||||
// ):
|
||||
// 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))
|
||||
@@ -227,7 +231,7 @@ func ProcessFinalUpdates(state *stateTrie.BeaconState) (*stateTrie.BeaconState,
|
||||
nextEpoch := currentEpoch + 1
|
||||
|
||||
// Reset ETH1 data votes.
|
||||
if (state.Slot()+1)%params.BeaconConfig().SlotsPerEth1VotingPeriod == 0 {
|
||||
if nextEpoch%params.BeaconConfig().EpochsPerEth1VotingPeriod == 0 {
|
||||
if err := state.SetEth1DataVotes([]*ethpb.Eth1Data{}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -235,22 +239,26 @@ func ProcessFinalUpdates(state *stateTrie.BeaconState) (*stateTrie.BeaconState,
|
||||
|
||||
bals := state.Balances()
|
||||
// Update effective balances with hysteresis.
|
||||
validatorFunc := func(idx int, val *ethpb.Validator) error {
|
||||
validatorFunc := func(idx int, val *ethpb.Validator) (bool, error) {
|
||||
if val == nil {
|
||||
return fmt.Errorf("validator %d is nil in state", idx)
|
||||
return false, fmt.Errorf("validator %d is nil in state", idx)
|
||||
}
|
||||
if idx >= len(bals) {
|
||||
return fmt.Errorf("validator index exceeds validator length in state %d >= %d", idx, len(state.Balances()))
|
||||
return false, fmt.Errorf("validator index exceeds validator length in state %d >= %d", idx, len(state.Balances()))
|
||||
}
|
||||
balance := bals[idx]
|
||||
halfInc := params.BeaconConfig().EffectiveBalanceIncrement / 2
|
||||
if balance < val.EffectiveBalance || val.EffectiveBalance+3*halfInc < balance {
|
||||
hysteresisInc := params.BeaconConfig().EffectiveBalanceIncrement / params.BeaconConfig().HysteresisQuotient
|
||||
downwardThreshold := hysteresisInc * params.BeaconConfig().HysteresisDownwardMultiplier
|
||||
upwardThreshold := hysteresisInc * params.BeaconConfig().HysteresisUpwardMultiplier
|
||||
|
||||
if balance+downwardThreshold < val.EffectiveBalance || val.EffectiveBalance+upwardThreshold < balance {
|
||||
val.EffectiveBalance = params.BeaconConfig().MaxEffectiveBalance
|
||||
if val.EffectiveBalance > balance-balance%params.BeaconConfig().EffectiveBalanceIncrement {
|
||||
val.EffectiveBalance = balance - balance%params.BeaconConfig().EffectiveBalanceIncrement
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
return nil
|
||||
return false, nil
|
||||
}
|
||||
|
||||
if err := state.ApplyToEveryValidator(validatorFunc); err != nil {
|
||||
@@ -285,7 +293,7 @@ func ProcessFinalUpdates(state *stateTrie.BeaconState) (*stateTrie.BeaconState,
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := state.UpdateRandaoMixesAtIndex(mix, nextEpoch%randaoMixLength); err != nil {
|
||||
if err := state.UpdateRandaoMixesAtIndex(nextEpoch%randaoMixLength, mix); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -334,10 +342,7 @@ func unslashedAttestingIndices(state *stateTrie.BeaconState, atts []*pb.PendingA
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
attestingIndices, err := attestationutil.AttestingIndices(att.AggregationBits, committee)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get attester indices")
|
||||
}
|
||||
attestingIndices := attestationutil.AttestingIndices(att.AggregationBits, committee)
|
||||
// Create a set for attesting indices
|
||||
set := make([]uint64, 0, len(attestingIndices))
|
||||
for _, index := range attestingIndices {
|
||||
@@ -352,7 +357,11 @@ func unslashedAttestingIndices(state *stateTrie.BeaconState, atts []*pb.PendingA
|
||||
sort.Slice(setIndices, func(i, j int) bool { return setIndices[i] < setIndices[j] })
|
||||
// Remove the slashed validator indices.
|
||||
for i := 0; i < len(setIndices); i++ {
|
||||
if v, _ := state.ValidatorAtIndex(setIndices[i]); v != nil && v.Slashed {
|
||||
v, err := state.ValidatorAtIndex(setIndices[i])
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to look up validator")
|
||||
}
|
||||
if v != nil && v.Slashed {
|
||||
setIndices = append(setIndices[:i], setIndices[i+1:]...)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,9 @@ func TestFuzzFinalUpdates_10000(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, _ = ProcessFinalUpdates(s)
|
||||
_, err = ProcessFinalUpdates(s)
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,9 @@ func TestUnslashedAttestingIndices_CanSortAndFilter(t *testing.T) {
|
||||
slashedValidator := indices[0]
|
||||
validators = state.Validators()
|
||||
validators[slashedValidator].Slashed = true
|
||||
state.SetValidators(validators)
|
||||
if err = state.SetValidators(validators); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
indices, err = unslashedAttestingIndices(state, atts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -311,25 +313,38 @@ func TestProcessFinalUpdates_CanProcess(t *testing.T) {
|
||||
s := buildState(params.BeaconConfig().SlotsPerHistoricalRoot-1, params.BeaconConfig().SlotsPerEpoch)
|
||||
ce := helpers.CurrentEpoch(s)
|
||||
ne := ce + 1
|
||||
s.SetEth1DataVotes([]*ethpb.Eth1Data{})
|
||||
if err := s.SetEth1DataVotes([]*ethpb.Eth1Data{}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
balances := s.Balances()
|
||||
balances[0] = 29 * 1e9
|
||||
s.SetBalances(balances)
|
||||
balances[0] = 31.75 * 1e9
|
||||
balances[1] = 31.74 * 1e9
|
||||
if err := s.SetBalances(balances); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
slashings := s.Slashings()
|
||||
slashings[ce] = 0
|
||||
s.SetSlashings(slashings)
|
||||
if err := s.SetSlashings(slashings); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
mixes := s.RandaoMixes()
|
||||
mixes[ce] = []byte{'A'}
|
||||
s.SetRandaoMixes(mixes)
|
||||
if err := s.SetRandaoMixes(mixes); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
newS, err := ProcessFinalUpdates(s)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Verify effective balance is correctly updated.
|
||||
if newS.Validators()[0].EffectiveBalance != 29*1e9 {
|
||||
if newS.Validators()[0].EffectiveBalance != params.BeaconConfig().MaxEffectiveBalance {
|
||||
t.Errorf("effective balance incorrectly updated, got %d", s.Validators()[0].EffectiveBalance)
|
||||
}
|
||||
if newS.Validators()[1].EffectiveBalance != 31*1e9 {
|
||||
t.Errorf("effective balance incorrectly updated, got %d", s.Validators()[1].EffectiveBalance)
|
||||
}
|
||||
|
||||
// Verify slashed balances correctly updated.
|
||||
if newS.Slashings()[ce] != newS.Slashings()[ne] {
|
||||
@@ -339,7 +354,7 @@ func TestProcessFinalUpdates_CanProcess(t *testing.T) {
|
||||
}
|
||||
|
||||
// Verify randao is correctly updated in the right position.
|
||||
if mix, _ := newS.RandaoMixAtIndex(ne); bytes.Equal(mix, params.BeaconConfig().ZeroHash[:]) {
|
||||
if mix, err := newS.RandaoMixAtIndex(ne); err != nil || bytes.Equal(mix, params.BeaconConfig().ZeroHash[:]) {
|
||||
t.Error("latest RANDAO still zero hashes")
|
||||
}
|
||||
|
||||
|
||||
@@ -47,10 +47,7 @@ func ProcessAttestations(
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
indices, err := attestationutil.AttestingIndices(a.AggregationBits, committee)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
indices := attestationutil.AttestingIndices(a.AggregationBits, committee)
|
||||
vp = UpdateValidator(vp, v, indices, a, a.Data.Slot)
|
||||
}
|
||||
|
||||
|
||||
@@ -74,13 +74,17 @@ func TestUpdateBalance(t *testing.T) {
|
||||
|
||||
func TestSameHead(t *testing.T) {
|
||||
beaconState, _ := testutil.DeterministicGenesisState(t, 100)
|
||||
beaconState.SetSlot(1)
|
||||
if err := beaconState.SetSlot(1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
att := ðpb.Attestation{Data: ðpb.AttestationData{
|
||||
Target: ðpb.Checkpoint{Epoch: 0}}}
|
||||
r := [32]byte{'A'}
|
||||
br := beaconState.BlockRoots()
|
||||
br[0] = r[:]
|
||||
beaconState.SetBlockRoots(br)
|
||||
if err := beaconState.SetBlockRoots(br); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
att.Data.BeaconBlockRoot = r[:]
|
||||
same, err := precompute.SameHead(beaconState, &pb.PendingAttestation{Data: att.Data})
|
||||
if err != nil {
|
||||
@@ -102,13 +106,17 @@ func TestSameHead(t *testing.T) {
|
||||
|
||||
func TestSameTarget(t *testing.T) {
|
||||
beaconState, _ := testutil.DeterministicGenesisState(t, 100)
|
||||
beaconState.SetSlot(1)
|
||||
if err := beaconState.SetSlot(1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
att := ðpb.Attestation{Data: ðpb.AttestationData{
|
||||
Target: ðpb.Checkpoint{Epoch: 0}}}
|
||||
r := [32]byte{'A'}
|
||||
br := beaconState.BlockRoots()
|
||||
br[0] = r[:]
|
||||
beaconState.SetBlockRoots(br)
|
||||
if err := beaconState.SetBlockRoots(br); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
att.Data.Target.Root = r[:]
|
||||
same, err := precompute.SameTarget(beaconState, &pb.PendingAttestation{Data: att.Data}, 0)
|
||||
if err != nil {
|
||||
@@ -130,13 +138,17 @@ func TestSameTarget(t *testing.T) {
|
||||
|
||||
func TestAttestedPrevEpoch(t *testing.T) {
|
||||
beaconState, _ := testutil.DeterministicGenesisState(t, 100)
|
||||
beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch)
|
||||
if err := beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
att := ðpb.Attestation{Data: ðpb.AttestationData{
|
||||
Target: ðpb.Checkpoint{Epoch: 0}}}
|
||||
r := [32]byte{'A'}
|
||||
br := beaconState.BlockRoots()
|
||||
br[0] = r[:]
|
||||
beaconState.SetBlockRoots(br)
|
||||
if err := beaconState.SetBlockRoots(br); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
att.Data.Target.Root = r[:]
|
||||
att.Data.BeaconBlockRoot = r[:]
|
||||
votedEpoch, votedTarget, votedHead, err := precompute.AttestedPrevEpoch(beaconState, &pb.PendingAttestation{Data: att.Data})
|
||||
@@ -156,14 +168,18 @@ func TestAttestedPrevEpoch(t *testing.T) {
|
||||
|
||||
func TestAttestedCurrentEpoch(t *testing.T) {
|
||||
beaconState, _ := testutil.DeterministicGenesisState(t, 100)
|
||||
beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch + 1)
|
||||
if err := beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch + 1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
att := ðpb.Attestation{Data: ðpb.AttestationData{
|
||||
Target: ðpb.Checkpoint{Epoch: 1}}}
|
||||
r := [32]byte{'A'}
|
||||
|
||||
br := beaconState.BlockRoots()
|
||||
br[params.BeaconConfig().SlotsPerEpoch] = r[:]
|
||||
beaconState.SetBlockRoots(br)
|
||||
if err := beaconState.SetBlockRoots(br); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
att.Data.Target.Root = r[:]
|
||||
att.Data.BeaconBlockRoot = r[:]
|
||||
votedEpoch, votedTarget, err := precompute.AttestedCurrentEpoch(beaconState, &pb.PendingAttestation{Data: att.Data})
|
||||
@@ -184,7 +200,9 @@ func TestProcessAttestations(t *testing.T) {
|
||||
|
||||
validators := uint64(64)
|
||||
beaconState, _ := testutil.DeterministicGenesisState(t, validators)
|
||||
beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch)
|
||||
if err := beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
bf := []byte{0xff}
|
||||
att1 := ðpb.Attestation{Data: ðpb.AttestationData{
|
||||
@@ -199,18 +217,26 @@ func TestProcessAttestations(t *testing.T) {
|
||||
br := beaconState.BlockRoots()
|
||||
newRt := [32]byte{'B'}
|
||||
br[0] = newRt[:]
|
||||
beaconState.SetBlockRoots(br)
|
||||
if err := beaconState.SetBlockRoots(br); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
att2.Data.Target.Root = rt[:]
|
||||
att2.Data.BeaconBlockRoot = newRt[:]
|
||||
beaconState.SetPreviousEpochAttestations([]*pb.PendingAttestation{{Data: att1.Data, AggregationBits: bf}})
|
||||
beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{{Data: att2.Data, AggregationBits: bf}})
|
||||
err := beaconState.SetPreviousEpochAttestations([]*pb.PendingAttestation{{Data: att1.Data, AggregationBits: bf}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{{Data: att2.Data, AggregationBits: bf}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
vp := make([]*precompute.Validator, validators)
|
||||
for i := 0; i < len(vp); i++ {
|
||||
vp[i] = &precompute.Validator{CurrentEpochEffectiveBalance: 100}
|
||||
}
|
||||
bp := &precompute.Balance{}
|
||||
vp, bp, err := precompute.ProcessAttestations(context.Background(), beaconState, vp, bp)
|
||||
vp, bp, err = precompute.ProcessAttestations(context.Background(), beaconState, vp, bp)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -219,7 +245,7 @@ func TestProcessAttestations(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
indices, _ := attestationutil.AttestingIndices(att1.AggregationBits, committee)
|
||||
indices := attestationutil.AttestingIndices(att1.AggregationBits, committee)
|
||||
for _, i := range indices {
|
||||
if !vp[i].IsPrevEpochAttester {
|
||||
t.Error("Not a prev epoch attester")
|
||||
@@ -229,7 +255,7 @@ func TestProcessAttestations(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
indices, _ = attestationutil.AttestingIndices(att2.AggregationBits, committee)
|
||||
indices = attestationutil.AttestingIndices(att2.AggregationBits, committee)
|
||||
for _, i := range indices {
|
||||
if !vp[i].IsPrevEpochAttester {
|
||||
t.Error("Not a prev epoch attester")
|
||||
|
||||
@@ -3,6 +3,7 @@ package precompute
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
@@ -12,7 +13,7 @@ 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) {
|
||||
func New(ctx context.Context, state *stateTrie.BeaconState) ([]*Validator, *Balance, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "precomputeEpoch.New")
|
||||
defer span.End()
|
||||
vp := make([]*Validator, state.NumValidators())
|
||||
@@ -21,7 +22,7 @@ func New(ctx context.Context, state *stateTrie.BeaconState) ([]*Validator, *Bala
|
||||
currentEpoch := helpers.CurrentEpoch(state)
|
||||
prevEpoch := helpers.PrevEpoch(state)
|
||||
|
||||
state.ReadFromEveryValidator(func(idx int, val *stateTrie.ReadOnlyValidator) error {
|
||||
if err := state.ReadFromEveryValidator(func(idx int, val *stateTrie.ReadOnlyValidator) error {
|
||||
// Was validator withdrawable or slashed
|
||||
withdrawable := currentEpoch >= val.WithdrawableEpoch()
|
||||
p := &Validator{
|
||||
@@ -46,6 +47,8 @@ func New(ctx context.Context, state *stateTrie.BeaconState) ([]*Validator, *Bala
|
||||
|
||||
vp[idx] = p
|
||||
return nil
|
||||
})
|
||||
return vp, bp
|
||||
}); err != nil {
|
||||
return nil, nil, errors.Wrap(err, "failed to initialize precompute")
|
||||
}
|
||||
return vp, bp, nil
|
||||
}
|
||||
|
||||
@@ -31,7 +31,10 @@ func TestNew(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
e := params.BeaconConfig().FarFutureEpoch
|
||||
v, b := precompute.New(context.Background(), s)
|
||||
v, b, err := precompute.New(context.Background(), s)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(v[0], &precompute.Validator{IsSlashed: true, CurrentEpochEffectiveBalance: 100,
|
||||
InclusionDistance: e, InclusionSlot: e}) {
|
||||
t.Error("Incorrect validator 0 status")
|
||||
|
||||
@@ -72,7 +72,7 @@ func attestationDeltas(state *stateTrie.BeaconState, bp *Balance, vp []*Validato
|
||||
|
||||
func attestationDelta(state *stateTrie.BeaconState, bp *Balance, v *Validator) (uint64, uint64) {
|
||||
eligible := v.IsActivePrevEpoch || (v.IsSlashed && !v.IsWithdrawableCurrentEpoch)
|
||||
if !eligible {
|
||||
if !eligible || bp.CurrentEpoch == 0 {
|
||||
return 0, 0
|
||||
}
|
||||
|
||||
@@ -83,7 +83,9 @@ func attestationDelta(state *stateTrie.BeaconState, bp *Balance, v *Validator) (
|
||||
|
||||
// Process source reward / penalty
|
||||
if v.IsPrevEpochAttester && !v.IsSlashed {
|
||||
r += br * bp.PrevEpochAttesters / bp.CurrentEpoch
|
||||
inc := params.BeaconConfig().EffectiveBalanceIncrement
|
||||
rewardNumerator := br * bp.PrevEpochAttesters / inc
|
||||
r += rewardNumerator / (bp.CurrentEpoch / inc)
|
||||
proposerReward := br / params.BeaconConfig().ProposerRewardQuotient
|
||||
maxAtteserReward := br - proposerReward
|
||||
r += maxAtteserReward / v.InclusionDistance
|
||||
@@ -93,14 +95,18 @@ func attestationDelta(state *stateTrie.BeaconState, bp *Balance, v *Validator) (
|
||||
|
||||
// Process target reward / penalty
|
||||
if v.IsPrevEpochTargetAttester && !v.IsSlashed {
|
||||
r += br * bp.PrevEpochTargetAttesters / bp.CurrentEpoch
|
||||
inc := params.BeaconConfig().EffectiveBalanceIncrement
|
||||
rewardNumerator := br * bp.PrevEpochAttesters / inc
|
||||
r += rewardNumerator / (bp.CurrentEpoch / inc)
|
||||
} else {
|
||||
p += br
|
||||
}
|
||||
|
||||
// Process head reward / penalty
|
||||
if v.IsPrevEpochHeadAttester && !v.IsSlashed {
|
||||
r += br * bp.PrevEpochHeadAttesters / bp.CurrentEpoch
|
||||
inc := params.BeaconConfig().EffectiveBalanceIncrement
|
||||
rewardNumerator := br * bp.PrevEpochAttesters / inc
|
||||
r += rewardNumerator / (bp.CurrentEpoch / inc)
|
||||
} else {
|
||||
p += br
|
||||
}
|
||||
|
||||
@@ -35,7 +35,10 @@ func TestProcessRewardsAndPenaltiesPrecompute(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
vp, bp := New(context.Background(), state)
|
||||
vp, bp, err := New(context.Background(), state)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
vp, bp, err = ProcessAttestations(context.Background(), state, vp, bp)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -88,7 +91,10 @@ func TestAttestationDeltaPrecompute(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
vp, bp := New(context.Background(), state)
|
||||
vp, bp, err := New(context.Background(), state)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
vp, bp, err = ProcessAttestations(context.Background(), state, vp, bp)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -146,6 +152,50 @@ func TestAttestationDeltaPrecompute(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestAttestationDeltas_ZeroEpoch(t *testing.T) {
|
||||
e := params.BeaconConfig().SlotsPerEpoch
|
||||
validatorCount := uint64(2048)
|
||||
base := buildState(e+2, validatorCount)
|
||||
atts := make([]*pb.PendingAttestation, 3)
|
||||
var emptyRoot [32]byte
|
||||
for i := 0; i < len(atts); i++ {
|
||||
atts[i] = &pb.PendingAttestation{
|
||||
Data: ðpb.AttestationData{
|
||||
Target: ðpb.Checkpoint{
|
||||
Root: emptyRoot[:],
|
||||
},
|
||||
Source: ðpb.Checkpoint{
|
||||
Root: emptyRoot[:],
|
||||
},
|
||||
BeaconBlockRoot: emptyRoot[:],
|
||||
},
|
||||
AggregationBits: bitfield.Bitlist{0xC0, 0xC0, 0xC0, 0xC0, 0x01},
|
||||
InclusionDelay: 1,
|
||||
}
|
||||
}
|
||||
base.PreviousEpochAttestations = atts
|
||||
state, err := state.InitializeFromProto(base)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
vp, bp, err := New(context.Background(), state)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
vp, bp, err = ProcessAttestations(context.Background(), state, vp, bp)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
bp.CurrentEpoch = 0 // Could cause a divide by zero panic.
|
||||
|
||||
_, _, err = attestationDeltas(state, bp, vp)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func buildState(slot uint64, validatorCount uint64) *pb.BeaconState {
|
||||
validators := make([]*ethpb.Validator, validatorCount)
|
||||
for i := 0; i < len(validators); i++ {
|
||||
|
||||
@@ -21,7 +21,7 @@ func ProcessSlashingsPrecompute(state *stateTrie.BeaconState, p *Balance) error
|
||||
totalSlashing += slashing
|
||||
}
|
||||
|
||||
validatorFunc := func(idx int, val *ethpb.Validator) error {
|
||||
validatorFunc := func(idx int, val *ethpb.Validator) (bool, error) {
|
||||
correctEpoch := (currentEpoch + exitLength/2) == val.WithdrawableEpoch
|
||||
if val.Slashed && correctEpoch {
|
||||
minSlashing := mathutil.Min(totalSlashing*3, p.CurrentEpoch)
|
||||
@@ -29,10 +29,11 @@ func ProcessSlashingsPrecompute(state *stateTrie.BeaconState, p *Balance) error
|
||||
penaltyNumerator := val.EffectiveBalance / increment * minSlashing
|
||||
penalty := penaltyNumerator / p.CurrentEpoch * increment
|
||||
if err := helpers.DecreaseBalance(state, uint64(idx), penalty); err != nil {
|
||||
return err
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
return nil
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return state.ApplyToEveryValidator(validatorFunc)
|
||||
|
||||
@@ -28,8 +28,11 @@ func runJustificationAndFinalizationTests(t *testing.T, config string) {
|
||||
|
||||
func processJustificationAndFinalizationPrecomputeWrapper(t *testing.T, state *state.BeaconState) (*state.BeaconState, error) {
|
||||
ctx := context.Background()
|
||||
vp, bp := precompute.New(ctx, state)
|
||||
_, bp, err := precompute.ProcessAttestations(ctx, state, vp, bp)
|
||||
vp, bp, err := precompute.New(ctx, state)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, bp, err = precompute.ProcessAttestations(ctx, state, vp, bp)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -37,8 +37,11 @@ func processSlashingsWrapper(t *testing.T, state *beaconstate.BeaconState) (*bea
|
||||
|
||||
func processSlashingsPrecomputeWrapper(t *testing.T, state *beaconstate.BeaconState) (*beaconstate.BeaconState, error) {
|
||||
ctx := context.Background()
|
||||
vp, bp := precompute.New(ctx, state)
|
||||
_, bp, err := precompute.ProcessAttestations(ctx, state, vp, bp)
|
||||
vp, bp, err := precompute.New(ctx, state)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, bp, err = precompute.ProcessAttestations(ctx, state, vp, bp)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -31,4 +31,6 @@ type ChainStartedData struct {
|
||||
type InitializedData struct {
|
||||
// StartTime is the time at which the chain started.
|
||||
StartTime time.Time
|
||||
// GenesisValidatorsRoot represents ssz.HashTreeRoot(state.validators).
|
||||
GenesisValidatorsRoot []byte
|
||||
}
|
||||
|
||||
@@ -9,17 +9,21 @@ go_library(
|
||||
"randao.go",
|
||||
"rewards_penalties.go",
|
||||
"shuffle.go",
|
||||
"signing_root.go",
|
||||
"slot_epoch.go",
|
||||
"validators.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers",
|
||||
visibility = [
|
||||
"//beacon-chain:__subpackages__",
|
||||
"//shared/testutil:__pkg__",
|
||||
"//shared/benchutil/benchmark_files:__subpackages__",
|
||||
"//shared/testutil:__pkg__",
|
||||
"//shared/keystore:__pkg__",
|
||||
"//shared/interop:__pkg__",
|
||||
"//slasher:__subpackages__",
|
||||
"//tools:__subpackages__",
|
||||
"//validator:__subpackages__",
|
||||
"//endtoend/evaluators:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
"//beacon-chain/cache:go_default_library",
|
||||
@@ -48,6 +52,7 @@ go_test(
|
||||
"randao_test.go",
|
||||
"rewards_penalties_test.go",
|
||||
"shuffle_test.go",
|
||||
"signing_root_test.go",
|
||||
"slot_epoch_test.go",
|
||||
"validators_test.go",
|
||||
],
|
||||
@@ -64,6 +69,7 @@ go_test(
|
||||
"//shared/params:go_default_library",
|
||||
"//shared/sliceutil:go_default_library",
|
||||
"//shared/testutil:go_default_library",
|
||||
"@com_github_google_gofuzz//:go_default_library",
|
||||
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
|
||||
"github.com/pkg/errors"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/go-ssz"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/shared/bls"
|
||||
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
||||
@@ -124,15 +123,15 @@ func AggregateAttestation(a1 *ethpb.Attestation, a2 *ethpb.Attestation) (*ethpb.
|
||||
// domain = get_domain(state, DOMAIN_BEACON_ATTESTER, compute_epoch_at_slot(slot))
|
||||
// return bls_sign(privkey, hash_tree_root(slot), domain)
|
||||
func SlotSignature(state *stateTrie.BeaconState, slot uint64, privKey *bls.SecretKey) (*bls.Signature, error) {
|
||||
d, err := Domain(state.Fork(), CurrentEpoch(state), params.BeaconConfig().DomainBeaconAttester)
|
||||
d, err := Domain(state.Fork(), CurrentEpoch(state), params.BeaconConfig().DomainBeaconAttester, state.GenesisValidatorRoot())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s, err := ssz.HashTreeRoot(slot)
|
||||
s, err := ComputeSigningRoot(slot, d)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return privKey.Sign(s[:], d), nil
|
||||
return privKey.Sign(s[:]), nil
|
||||
}
|
||||
|
||||
// IsAggregator returns true if the signature is from the input validator. The committee
|
||||
|
||||
@@ -202,7 +202,7 @@ func TestAggregateAttestations(t *testing.T) {
|
||||
atts := make([]*ethpb.Attestation, len(bl))
|
||||
for i, b := range bl {
|
||||
sk := bls.RandKey()
|
||||
sig := sk.Sign([]byte("dummy_test_data"), 0 /*domain*/)
|
||||
sig := sk.Sign([]byte("dummy_test_data"))
|
||||
atts[i] = ðpb.Attestation{
|
||||
AggregationBits: b,
|
||||
Data: nil,
|
||||
@@ -240,7 +240,7 @@ func TestAggregateAttestations(t *testing.T) {
|
||||
func TestSlotSignature_Verify(t *testing.T) {
|
||||
priv := bls.RandKey()
|
||||
pub := priv.PublicKey()
|
||||
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
Fork: &pb.Fork{
|
||||
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
|
||||
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
|
||||
@@ -248,6 +248,9 @@ func TestSlotSignature_Verify(t *testing.T) {
|
||||
},
|
||||
Slot: 100,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
slot := uint64(101)
|
||||
|
||||
sig, err := helpers.SlotSignature(state, slot, priv)
|
||||
@@ -255,12 +258,15 @@ func TestSlotSignature_Verify(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
domain, err := helpers.Domain(state.Fork(), helpers.CurrentEpoch(state), params.BeaconConfig().DomainBeaconAttester)
|
||||
domain, err := helpers.Domain(state.Fork(), helpers.CurrentEpoch(state), params.BeaconConfig().DomainBeaconAttester, state.GenesisValidatorRoot())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
msg, _ := ssz.HashTreeRoot(slot)
|
||||
if !sig.Verify(msg[:], pub, domain) {
|
||||
msg, err := helpers.ComputeSigningRoot(slot, domain)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !sig.Verify(msg[:], pub) {
|
||||
t.Error("Could not verify slot signature")
|
||||
}
|
||||
}
|
||||
@@ -272,7 +278,7 @@ func TestIsAggregator_True(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
sig := privKeys[0].Sign([]byte{}, 0)
|
||||
sig := privKeys[0].Sign([]byte{'A'})
|
||||
agg, err := helpers.IsAggregator(uint64(len(committee)), sig.Marshal())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -291,7 +297,7 @@ func TestIsAggregator_False(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
sig := privKeys[0].Sign([]byte{}, 0)
|
||||
sig := privKeys[0].Sign([]byte{'A'})
|
||||
agg, err := helpers.IsAggregator(uint64(len(committee)), sig.Marshal())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -304,11 +310,11 @@ func TestIsAggregator_False(t *testing.T) {
|
||||
func TestAggregateSignature_True(t *testing.T) {
|
||||
pubkeys := make([]*bls.PublicKey, 0, 100)
|
||||
atts := make([]*ethpb.Attestation, 0, 100)
|
||||
msg := []byte("hello")
|
||||
msg := bytesutil.ToBytes32([]byte("hello"))
|
||||
for i := 0; i < 100; i++ {
|
||||
priv := bls.RandKey()
|
||||
pub := priv.PublicKey()
|
||||
sig := priv.Sign(msg[:], 0)
|
||||
sig := priv.Sign(msg[:])
|
||||
pubkeys = append(pubkeys, pub)
|
||||
att := ðpb.Attestation{Signature: sig.Marshal()}
|
||||
atts = append(atts, att)
|
||||
@@ -317,7 +323,7 @@ func TestAggregateSignature_True(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !aggSig.VerifyAggregateCommon(pubkeys, bytesutil.ToBytes32(msg), 0) {
|
||||
if !aggSig.FastAggregateVerify(pubkeys, msg) {
|
||||
t.Error("Signature did not verify")
|
||||
}
|
||||
}
|
||||
@@ -329,7 +335,7 @@ func TestAggregateSignature_False(t *testing.T) {
|
||||
for i := 0; i < 100; i++ {
|
||||
priv := bls.RandKey()
|
||||
pub := priv.PublicKey()
|
||||
sig := priv.Sign(msg[:], 0)
|
||||
sig := priv.Sign(msg[:])
|
||||
pubkeys = append(pubkeys, pub)
|
||||
att := ðpb.Attestation{Signature: sig.Marshal()}
|
||||
atts = append(atts, att)
|
||||
@@ -338,7 +344,7 @@ func TestAggregateSignature_False(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if aggSig.VerifyAggregateCommon(pubkeys, bytesutil.ToBytes32(msg), 0) {
|
||||
if aggSig.FastAggregateVerify(pubkeys, bytesutil.ToBytes32(msg)) {
|
||||
t.Error("Signature not suppose to verify")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,10 @@ func TestBlockRootAtSlot_CorrectBlockRoot(t *testing.T) {
|
||||
for i, tt := range tests {
|
||||
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
|
||||
s.Slot = tt.stateSlot
|
||||
state, _ := beaconstate.InitializeFromProto(s)
|
||||
state, err := beaconstate.InitializeFromProto(s)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
wantedSlot := tt.slot
|
||||
result, err := helpers.BlockRootAtSlot(state, wantedSlot)
|
||||
if err != nil {
|
||||
@@ -111,8 +114,11 @@ func TestBlockRootAtSlot_OutOfBounds(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
state.Slot = tt.stateSlot
|
||||
s, _ := beaconstate.InitializeFromProto(state)
|
||||
_, err := helpers.BlockRootAtSlot(s, tt.slot)
|
||||
s, err := beaconstate.InitializeFromProto(state)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = helpers.BlockRootAtSlot(s, tt.slot)
|
||||
if err == nil {
|
||||
t.Errorf("Expected error %s, got nil", tt.expectedErr)
|
||||
}
|
||||
|
||||
@@ -181,7 +181,10 @@ type CommitteeAssignmentContainer struct {
|
||||
// 2. Compute all committees.
|
||||
// 3. Determine the attesting slot for each committee.
|
||||
// 4. Construct a map of validator indices pointing to the respective committees.
|
||||
func CommitteeAssignments(state *stateTrie.BeaconState, epoch uint64) (map[uint64]*CommitteeAssignmentContainer, map[uint64]uint64, error) {
|
||||
func CommitteeAssignments(
|
||||
state *stateTrie.BeaconState,
|
||||
epoch uint64,
|
||||
) (map[uint64]*CommitteeAssignmentContainer, map[uint64][]uint64, error) {
|
||||
nextEpoch := NextEpoch(state)
|
||||
if epoch > nextEpoch {
|
||||
return nil, nil, fmt.Errorf(
|
||||
@@ -191,9 +194,11 @@ func CommitteeAssignments(state *stateTrie.BeaconState, epoch uint64) (map[uint6
|
||||
)
|
||||
}
|
||||
|
||||
// Track which slot has which proposer.
|
||||
// We determine the slots in which proposers are supposed to act.
|
||||
// Some validators may need to propose multiple times per epoch, so
|
||||
// we use a map of proposer idx -> []slot to keep track of this possibility.
|
||||
startSlot := StartSlot(epoch)
|
||||
proposerIndexToSlot := make(map[uint64]uint64)
|
||||
proposerIndexToSlots := make(map[uint64][]uint64)
|
||||
for slot := startSlot; slot < startSlot+params.BeaconConfig().SlotsPerEpoch; slot++ {
|
||||
if err := state.SetSlot(slot); err != nil {
|
||||
return nil, nil, err
|
||||
@@ -202,7 +207,7 @@ func CommitteeAssignments(state *stateTrie.BeaconState, epoch uint64) (map[uint6
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrapf(err, "could not check proposer at slot %d", state.Slot())
|
||||
}
|
||||
proposerIndexToSlot[i] = slot
|
||||
proposerIndexToSlots[i] = append(proposerIndexToSlots[i], slot)
|
||||
}
|
||||
|
||||
activeValidatorIndices, err := ActiveValidatorIndices(state, epoch)
|
||||
@@ -235,85 +240,7 @@ func CommitteeAssignments(state *stateTrie.BeaconState, epoch uint64) (map[uint6
|
||||
}
|
||||
}
|
||||
|
||||
return validatorIndexToCommittee, proposerIndexToSlot, nil
|
||||
}
|
||||
|
||||
// CommitteeAssignment is used to query committee assignment from
|
||||
// current and previous epoch.
|
||||
//
|
||||
// Deprecated: Consider using CommitteeAssignments, especially when computing more than one
|
||||
// validator assignment as this method is O(n^2) in computational complexity. This method exists to
|
||||
// ensure spec definition conformance and otherwise should probably not be used.
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
// def get_committee_assignment(state: BeaconState,
|
||||
// epoch: Epoch,
|
||||
// validator_index: ValidatorIndex
|
||||
// ) -> Optional[Tuple[Sequence[ValidatorIndex], CommitteeIndex, Slot]]:
|
||||
// """
|
||||
// Return the committee assignment in the ``epoch`` for ``validator_index``.
|
||||
// ``assignment`` returned is a tuple of the following form:
|
||||
// * ``assignment[0]`` is the list of validators in the committee
|
||||
// * ``assignment[1]`` is the index to which the committee is assigned
|
||||
// * ``assignment[2]`` is the slot at which the committee is assigned
|
||||
// Return None if no assignment.
|
||||
// """
|
||||
// next_epoch = get_current_epoch(state) + 1
|
||||
// assert epoch <= next_epoch
|
||||
//
|
||||
// start_slot = compute_start_slot_at_epoch(epoch)
|
||||
// for slot in range(start_slot, start_slot + SLOTS_PER_EPOCH):
|
||||
// for index in range(get_committee_count_at_slot(state, Slot(slot))):
|
||||
// committee = get_beacon_committee(state, Slot(slot), CommitteeIndex(index))
|
||||
// if validator_index in committee:
|
||||
// return committee, CommitteeIndex(index), Slot(slot)
|
||||
// return None
|
||||
func CommitteeAssignment(
|
||||
state *stateTrie.BeaconState,
|
||||
epoch uint64,
|
||||
validatorIndex uint64,
|
||||
) ([]uint64, uint64, uint64, uint64, error) {
|
||||
nextEpoch := NextEpoch(state)
|
||||
if epoch > nextEpoch {
|
||||
return nil, 0, 0, 0, fmt.Errorf(
|
||||
"epoch %d can't be greater than next epoch %d",
|
||||
epoch, nextEpoch)
|
||||
}
|
||||
|
||||
// Track which slot has which proposer.
|
||||
startSlot := StartSlot(epoch)
|
||||
proposerIndexToSlot := make(map[uint64]uint64)
|
||||
for slot := startSlot; slot < startSlot+params.BeaconConfig().SlotsPerEpoch; slot++ {
|
||||
if err := state.SetSlot(slot); err != nil {
|
||||
return nil, 0, 0, 0, err
|
||||
}
|
||||
i, err := BeaconProposerIndex(state)
|
||||
if err != nil {
|
||||
return nil, 0, 0, 0, errors.Wrapf(err, "could not check proposer at slot %d", state.Slot())
|
||||
}
|
||||
proposerIndexToSlot[i] = slot
|
||||
}
|
||||
|
||||
activeValidatorIndices, err := ActiveValidatorIndices(state, epoch)
|
||||
if err != nil {
|
||||
return nil, 0, 0, 0, err
|
||||
}
|
||||
for slot := startSlot; slot < startSlot+params.BeaconConfig().SlotsPerEpoch; slot++ {
|
||||
countAtSlot := SlotCommitteeCount(uint64(len(activeValidatorIndices)))
|
||||
for i := uint64(0); i < countAtSlot; i++ {
|
||||
committee, err := BeaconCommitteeFromState(state, slot, i)
|
||||
if err != nil {
|
||||
return nil, 0, 0, 0, errors.Wrapf(err, "could not get crosslink committee at slot %d", slot)
|
||||
}
|
||||
for _, v := range committee {
|
||||
if validatorIndex == v {
|
||||
proposerSlot, _ := proposerIndexToSlot[v]
|
||||
return committee, i, slot, proposerSlot, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return []uint64{}, 0, 0, 0, fmt.Errorf("validator with index %d not found in assignments", validatorIndex)
|
||||
return validatorIndexToCommittee, proposerIndexToSlots, nil
|
||||
}
|
||||
|
||||
// VerifyBitfieldLength verifies that a bitfield length matches the given committee size.
|
||||
@@ -354,12 +281,14 @@ func ShuffledIndices(state *stateTrie.BeaconState, epoch uint64) ([]uint64, erro
|
||||
}
|
||||
|
||||
indices := make([]uint64, 0, state.NumValidators())
|
||||
state.ReadFromEveryValidator(func(idx int, val *stateTrie.ReadOnlyValidator) error {
|
||||
if err := state.ReadFromEveryValidator(func(idx int, val *stateTrie.ReadOnlyValidator) error {
|
||||
if IsActiveValidatorUsingTrie(val, epoch) {
|
||||
indices = append(indices, uint64(idx))
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return UnshuffleList(indices, seed)
|
||||
}
|
||||
@@ -407,7 +336,6 @@ func UpdateCommitteeCache(state *stateTrie.BeaconState, epoch uint64) error {
|
||||
|
||||
// UpdateProposerIndicesInCache updates proposer indices entry of the committee cache.
|
||||
func UpdateProposerIndicesInCache(state *stateTrie.BeaconState, epoch uint64) error {
|
||||
|
||||
indices, err := ActiveValidatorIndices(state, epoch)
|
||||
if err != nil {
|
||||
return nil
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
@@ -96,11 +95,14 @@ func TestAttestationParticipants_NoCommitteeCache(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
Slot: params.BeaconConfig().SlotsPerEpoch,
|
||||
Validators: validators,
|
||||
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
attestationData := ðpb.AttestationData{}
|
||||
|
||||
@@ -134,7 +136,7 @@ func TestAttestationParticipants_NoCommitteeCache(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
result, err := attestationutil.AttestingIndices(tt.bitfield, committee)
|
||||
result := attestationutil.AttestingIndices(tt.bitfield, committee)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to get attestation participants: %v", err)
|
||||
}
|
||||
@@ -157,21 +159,20 @@ func TestAttestationParticipants_EmptyBitfield(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
Validators: validators,
|
||||
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
attestationData := ðpb.AttestationData{Target: ðpb.Checkpoint{}}
|
||||
|
||||
committee, err := BeaconCommitteeFromState(state, attestationData.Slot, attestationData.CommitteeIndex)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
indices, err := attestationutil.AttestingIndices(bitfield.NewBitlist(128), committee)
|
||||
if err != nil {
|
||||
t.Fatalf("attesting indices failed: %v", err)
|
||||
}
|
||||
|
||||
indices := attestationutil.AttestingIndices(bitfield.NewBitlist(128), committee)
|
||||
if len(indices) != 0 {
|
||||
t.Errorf("Attesting indices are non-zero despite an empty bitfield being provided; Size %d", len(indices))
|
||||
}
|
||||
@@ -191,148 +192,6 @@ func TestVerifyBitfieldLength_OK(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommitteeAssignment_CanRetrieve(t *testing.T) {
|
||||
ClearCache()
|
||||
// Initialize test with 128 validators, each slot and each index gets 2 validators.
|
||||
validators := make([]*ethpb.Validator, 2*params.BeaconConfig().SlotsPerEpoch)
|
||||
for i := 0; i < len(validators); i++ {
|
||||
validators[i] = ðpb.Validator{
|
||||
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
|
||||
}
|
||||
}
|
||||
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
Validators: validators,
|
||||
Slot: params.BeaconConfig().SlotsPerEpoch,
|
||||
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
|
||||
})
|
||||
|
||||
tests := []struct {
|
||||
index uint64
|
||||
slot uint64
|
||||
committee []uint64
|
||||
committeeIndex uint64
|
||||
isProposer bool
|
||||
proposerSlot uint64
|
||||
}{
|
||||
{
|
||||
index: 0,
|
||||
slot: 78,
|
||||
committee: []uint64{0, 38},
|
||||
committeeIndex: 0,
|
||||
isProposer: false,
|
||||
},
|
||||
{
|
||||
index: 1,
|
||||
slot: 71,
|
||||
committee: []uint64{1, 4},
|
||||
committeeIndex: 0,
|
||||
isProposer: true,
|
||||
proposerSlot: 79,
|
||||
},
|
||||
{
|
||||
index: 11,
|
||||
slot: 90,
|
||||
committee: []uint64{31, 11},
|
||||
committeeIndex: 0,
|
||||
isProposer: false,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
|
||||
committee, committeeIndex, slot, proposerSlot, err := CommitteeAssignment(state, tt.slot/params.BeaconConfig().SlotsPerEpoch, tt.index)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to execute NextEpochCommitteeAssignment: %v", err)
|
||||
}
|
||||
if committeeIndex != tt.committeeIndex {
|
||||
t.Errorf("wanted committeeIndex %d, got committeeIndex %d for validator index %d",
|
||||
tt.committeeIndex, committeeIndex, tt.index)
|
||||
}
|
||||
if slot != tt.slot {
|
||||
t.Errorf("wanted slot %d, got slot %d for validator index %d",
|
||||
tt.slot, slot, tt.index)
|
||||
}
|
||||
if proposerSlot != tt.proposerSlot {
|
||||
t.Errorf("wanted proposer slot %d, got proposer slot %d for validator index %d",
|
||||
tt.proposerSlot, proposerSlot, tt.index)
|
||||
}
|
||||
if !reflect.DeepEqual(committee, tt.committee) {
|
||||
t.Errorf("wanted committee %v, got committee %v for validator index %d",
|
||||
tt.committee, committee, tt.index)
|
||||
}
|
||||
if proposerSlot != tt.proposerSlot {
|
||||
t.Errorf("wanted proposer slot slot %d, got slot %d for validator index %d",
|
||||
tt.slot, slot, tt.index)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommitteeAssignment_CantFindValidator(t *testing.T) {
|
||||
ClearCache()
|
||||
validators := make([]*ethpb.Validator, 1)
|
||||
for i := 0; i < len(validators); i++ {
|
||||
validators[i] = ðpb.Validator{
|
||||
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
|
||||
}
|
||||
}
|
||||
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
Validators: validators,
|
||||
Slot: params.BeaconConfig().SlotsPerEpoch,
|
||||
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
|
||||
})
|
||||
|
||||
index := uint64(10000)
|
||||
_, _, _, _, err := CommitteeAssignment(state, 1, index)
|
||||
if err != nil && !strings.Contains(err.Error(), "not found in assignments") {
|
||||
t.Errorf("Wanted 'not found in assignments', received %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Test helpers.CommitteeAssignments against the results of helpers.CommitteeAssignment by validator
|
||||
// index. Warning: this test is a bit slow!
|
||||
func TestCommitteeAssignments_AgreesWithSpecDefinitionMethod(t *testing.T) {
|
||||
ClearCache()
|
||||
// Initialize test with 256 validators, each slot and each index gets 4 validators.
|
||||
validators := make([]*ethpb.Validator, 4*params.BeaconConfig().SlotsPerEpoch)
|
||||
for i := 0; i < len(validators); i++ {
|
||||
validators[i] = ðpb.Validator{
|
||||
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
|
||||
}
|
||||
}
|
||||
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
Validators: validators,
|
||||
Slot: params.BeaconConfig().SlotsPerEpoch,
|
||||
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
|
||||
})
|
||||
// Test for 2 epochs.
|
||||
for epoch := uint64(0); epoch < 2; epoch++ {
|
||||
state, _ := beaconstate.InitializeFromProto(state.CloneInnerState())
|
||||
assignments, proposers, err := CommitteeAssignments(state, epoch)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for i := uint64(0); int(i) < len(validators); i++ {
|
||||
committee, committeeIndex, slot, proposerSlot, err := CommitteeAssignment(state, epoch, i)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(committee, assignments[i].Committee) {
|
||||
t.Errorf("Computed different committees for validator %d", i)
|
||||
}
|
||||
if committeeIndex != assignments[i].CommitteeIndex {
|
||||
t.Errorf("Computed different committee index for validator %d", i)
|
||||
}
|
||||
if slot != assignments[i].AttesterSlot {
|
||||
t.Errorf("Computed different attesting slot for validator %d", i)
|
||||
}
|
||||
if proposerSlot != proposers[i] {
|
||||
t.Errorf("Computed different proposing slot for validator %d", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommitteeAssignments_CanRetrieve(t *testing.T) {
|
||||
// Initialize test with 256 validators, each slot and each index gets 4 validators.
|
||||
validators := make([]*ethpb.Validator, 4*params.BeaconConfig().SlotsPerEpoch)
|
||||
@@ -348,11 +207,14 @@ func TestCommitteeAssignments_CanRetrieve(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
Validators: validators,
|
||||
Slot: 2 * params.BeaconConfig().SlotsPerEpoch, // epoch 2
|
||||
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
index uint64
|
||||
@@ -395,7 +257,7 @@ func TestCommitteeAssignments_CanRetrieve(t *testing.T) {
|
||||
for i, tt := range tests {
|
||||
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
|
||||
ClearCache()
|
||||
validatorIndexToCommittee, proposerIndexToSlot, err := CommitteeAssignments(state, SlotToEpoch(tt.slot))
|
||||
validatorIndexToCommittee, proposerIndexToSlots, err := CommitteeAssignments(state, SlotToEpoch(tt.slot))
|
||||
if err != nil {
|
||||
t.Fatalf("failed to determine CommitteeAssignments: %v", err)
|
||||
}
|
||||
@@ -408,9 +270,9 @@ func TestCommitteeAssignments_CanRetrieve(t *testing.T) {
|
||||
t.Errorf("wanted slot %d, got slot %d for validator index %d",
|
||||
tt.slot, cac.AttesterSlot, tt.index)
|
||||
}
|
||||
if proposerIndexToSlot[tt.index] != tt.proposerSlot {
|
||||
if len(proposerIndexToSlots[tt.index]) > 0 && proposerIndexToSlots[tt.index][0] != tt.proposerSlot {
|
||||
t.Errorf("wanted proposer slot %d, got proposer slot %d for validator index %d",
|
||||
tt.proposerSlot, proposerIndexToSlot[tt.index], tt.index)
|
||||
tt.proposerSlot, proposerIndexToSlots[tt.index][0], tt.index)
|
||||
}
|
||||
if !reflect.DeepEqual(cac.Committee, tt.committee) {
|
||||
t.Errorf("wanted committee %v, got committee %v for validator index %d",
|
||||
@@ -429,10 +291,13 @@ func TestVerifyAttestationBitfieldLengths_OK(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
Validators: validators,
|
||||
RandaoMixes: activeRoots,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
attestation *ethpb.Attestation
|
||||
@@ -506,7 +371,9 @@ func TestVerifyAttestationBitfieldLengths_OK(t *testing.T) {
|
||||
|
||||
for i, tt := range tests {
|
||||
ClearCache()
|
||||
state.SetSlot(tt.stateSlot)
|
||||
if err := state.SetSlot(tt.stateSlot); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err := VerifyAttestationBitfieldLengths(state, tt.attestation)
|
||||
if tt.verificationFailure {
|
||||
if err == nil {
|
||||
@@ -655,10 +522,13 @@ func BenchmarkComputeCommittee3000000_WithPreCache(b *testing.B) {
|
||||
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
|
||||
}
|
||||
}
|
||||
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
Validators: validators,
|
||||
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
|
||||
})
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
epoch := CurrentEpoch(state)
|
||||
indices, err := ActiveValidatorIndices(state, epoch)
|
||||
@@ -692,10 +562,13 @@ func BenchmarkComputeCommittee128000_WithOutPreCache(b *testing.B) {
|
||||
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
|
||||
}
|
||||
}
|
||||
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
Validators: validators,
|
||||
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
|
||||
})
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
epoch := CurrentEpoch(state)
|
||||
indices, err := ActiveValidatorIndices(state, epoch)
|
||||
@@ -730,10 +603,13 @@ func BenchmarkComputeCommittee1000000_WithOutCache(b *testing.B) {
|
||||
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
|
||||
}
|
||||
}
|
||||
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
Validators: validators,
|
||||
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
|
||||
})
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
epoch := CurrentEpoch(state)
|
||||
indices, err := ActiveValidatorIndices(state, epoch)
|
||||
@@ -768,10 +644,13 @@ func BenchmarkComputeCommittee4000000_WithOutCache(b *testing.B) {
|
||||
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
|
||||
}
|
||||
}
|
||||
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
Validators: validators,
|
||||
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
|
||||
})
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
epoch := CurrentEpoch(state)
|
||||
indices, err := ActiveValidatorIndices(state, epoch)
|
||||
@@ -812,11 +691,14 @@ func TestBeaconCommitteeFromState_UpdateCacheForPreviousEpoch(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
Slot: params.BeaconConfig().SlotsPerEpoch,
|
||||
Validators: validators,
|
||||
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := BeaconCommitteeFromState(state, 1 /* previous epoch */, 0); err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -844,10 +726,13 @@ func TestPrecomputeProposerIndices_Ok(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
Validators: validators,
|
||||
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
indices, err := ActiveValidatorIndices(state, 0)
|
||||
if err != nil {
|
||||
|
||||
@@ -18,7 +18,10 @@ func TestRandaoMix_OK(t *testing.T) {
|
||||
binary.LittleEndian.PutUint64(intInBytes, uint64(i))
|
||||
randaoMixes[i] = intInBytes
|
||||
}
|
||||
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{RandaoMixes: randaoMixes})
|
||||
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{RandaoMixes: randaoMixes})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tests := []struct {
|
||||
epoch uint64
|
||||
randaoMix []byte
|
||||
@@ -37,7 +40,9 @@ func TestRandaoMix_OK(t *testing.T) {
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
state.SetSlot((test.epoch + 1) * params.BeaconConfig().SlotsPerEpoch)
|
||||
if err := state.SetSlot((test.epoch + 1) * params.BeaconConfig().SlotsPerEpoch); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
mix, err := RandaoMix(state, test.epoch)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -56,7 +61,10 @@ func TestRandaoMix_CopyOK(t *testing.T) {
|
||||
binary.LittleEndian.PutUint64(intInBytes, uint64(i))
|
||||
randaoMixes[i] = intInBytes
|
||||
}
|
||||
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{RandaoMixes: randaoMixes})
|
||||
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{RandaoMixes: randaoMixes})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tests := []struct {
|
||||
epoch uint64
|
||||
randaoMix []byte
|
||||
@@ -75,7 +83,9 @@ func TestRandaoMix_CopyOK(t *testing.T) {
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
state.SetSlot((test.epoch + 1) * params.BeaconConfig().SlotsPerEpoch)
|
||||
if err := state.SetSlot((test.epoch + 1) * params.BeaconConfig().SlotsPerEpoch); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
mix, err := RandaoMix(state, test.epoch)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -101,9 +111,13 @@ func TestGenerateSeed_OK(t *testing.T) {
|
||||
randaoMixes[i] = intInBytes
|
||||
}
|
||||
slot := 10 * params.BeaconConfig().MinSeedLookahead * params.BeaconConfig().SlotsPerEpoch
|
||||
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
RandaoMixes: randaoMixes,
|
||||
Slot: slot})
|
||||
Slot: slot,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
got, err := Seed(state, 10, params.BeaconConfig().DomainBeaconAttester)
|
||||
if err != nil {
|
||||
|
||||
@@ -2,6 +2,7 @@ package helpers
|
||||
|
||||
import (
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
|
||||
// TotalBalance returns the total amount at stake in Gwei
|
||||
@@ -10,9 +11,10 @@ import (
|
||||
// Spec pseudocode definition:
|
||||
// def get_total_balance(state: BeaconState, indices: Set[ValidatorIndex]) -> Gwei:
|
||||
// """
|
||||
// Return the combined effective balance of the ``indices``. (1 Gwei minimum to avoid divisions by zero.)
|
||||
// Return the combined effective balance of the ``indices``.
|
||||
// ``EFFECTIVE_BALANCE_INCREMENT`` Gwei minimum to avoid divisions by zero.
|
||||
// """
|
||||
// return Gwei(max(1, sum([state.validators[index].effective_balance for index in indices])))
|
||||
// return Gwei(max(EFFECTIVE_BALANCE_INCREMENT, sum([state.validators[index].effective_balance for index in indices])))
|
||||
func TotalBalance(state *stateTrie.BeaconState, indices []uint64) uint64 {
|
||||
total := uint64(0)
|
||||
|
||||
@@ -24,9 +26,9 @@ func TotalBalance(state *stateTrie.BeaconState, indices []uint64) uint64 {
|
||||
total += val.EffectiveBalance()
|
||||
}
|
||||
|
||||
// Return 1 Gwei minimum to avoid divisions by zero
|
||||
// Return EFFECTIVE_BALANCE_INCREMENT to avoid divisions by zero.
|
||||
if total == 0 {
|
||||
return 1
|
||||
return params.BeaconConfig().EffectiveBalanceIncrement
|
||||
}
|
||||
|
||||
return total
|
||||
@@ -43,12 +45,14 @@ func TotalBalance(state *stateTrie.BeaconState, indices []uint64) uint64 {
|
||||
// return get_total_balance(state, set(get_active_validator_indices(state, get_current_epoch(state))))
|
||||
func TotalActiveBalance(state *stateTrie.BeaconState) (uint64, error) {
|
||||
total := uint64(0)
|
||||
state.ReadFromEveryValidator(func(idx int, val *stateTrie.ReadOnlyValidator) error {
|
||||
if err := state.ReadFromEveryValidator(func(idx int, val *stateTrie.ReadOnlyValidator) error {
|
||||
if IsActiveValidatorUsingTrie(val, SlotToEpoch(state.Slot())) {
|
||||
total += val.EffectiveBalance()
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return total, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -10,10 +10,13 @@ import (
|
||||
)
|
||||
|
||||
func TestTotalBalance_OK(t *testing.T) {
|
||||
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{Validators: []*ethpb.Validator{
|
||||
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{Validators: []*ethpb.Validator{
|
||||
{EffectiveBalance: 27 * 1e9}, {EffectiveBalance: 28 * 1e9},
|
||||
{EffectiveBalance: 32 * 1e9}, {EffectiveBalance: 40 * 1e9},
|
||||
}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
balance := TotalBalance(state, []uint64{0, 1, 2, 3})
|
||||
wanted := state.Validators()[0].EffectiveBalance + state.Validators()[1].EffectiveBalance +
|
||||
@@ -24,11 +27,14 @@ func TestTotalBalance_OK(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestTotalBalance_ReturnsOne(t *testing.T) {
|
||||
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{Validators: []*ethpb.Validator{}})
|
||||
func TestTotalBalance_ReturnsEffectiveBalanceIncrement(t *testing.T) {
|
||||
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{Validators: []*ethpb.Validator{}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
balance := TotalBalance(state, []uint64{})
|
||||
wanted := uint64(1)
|
||||
wanted := params.BeaconConfig().EffectiveBalanceIncrement
|
||||
|
||||
if balance != wanted {
|
||||
t.Errorf("Incorrect TotalBalance. Wanted: %d, got: %d", wanted, balance)
|
||||
@@ -36,7 +42,7 @@ func TestTotalBalance_ReturnsOne(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestTotalActiveBalance_OK(t *testing.T) {
|
||||
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{Validators: []*ethpb.Validator{
|
||||
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{Validators: []*ethpb.Validator{
|
||||
{
|
||||
EffectiveBalance: 32 * 1e9,
|
||||
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
|
||||
@@ -54,6 +60,9 @@ func TestTotalActiveBalance_OK(t *testing.T) {
|
||||
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
|
||||
},
|
||||
}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
balance, err := TotalActiveBalance(state)
|
||||
if err != nil {
|
||||
@@ -79,7 +88,10 @@ func TestGetBalance_OK(t *testing.T) {
|
||||
{i: 2, b: []uint64{0, 0, 0}},
|
||||
}
|
||||
for _, test := range tests {
|
||||
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{Balances: test.b})
|
||||
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{Balances: test.b})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if state.Balances()[test.i] != test.b[test.i] {
|
||||
t.Errorf("Incorrect Validator balance. Wanted: %d, got: %d", test.b[test.i], state.Balances()[test.i])
|
||||
}
|
||||
@@ -98,11 +110,14 @@ func TestIncreaseBalance_OK(t *testing.T) {
|
||||
{i: 2, b: []uint64{27 * 1e9, 28 * 1e9, 32 * 1e9}, nb: 33 * 1e9, eb: 65 * 1e9},
|
||||
}
|
||||
for _, test := range tests {
|
||||
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
Validators: []*ethpb.Validator{
|
||||
{EffectiveBalance: 4}, {EffectiveBalance: 4}, {EffectiveBalance: 4}},
|
||||
Balances: test.b,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := IncreaseBalance(state, test.i, test.nb); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -125,11 +140,14 @@ func TestDecreaseBalance_OK(t *testing.T) {
|
||||
{i: 3, b: []uint64{27 * 1e9, 28 * 1e9, 1, 28 * 1e9}, nb: 28 * 1e9, eb: 0},
|
||||
}
|
||||
for _, test := range tests {
|
||||
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
Validators: []*ethpb.Validator{
|
||||
{EffectiveBalance: 4}, {EffectiveBalance: 4}, {EffectiveBalance: 4}, {EffectiveBalance: 3}},
|
||||
Balances: test.b,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := DecreaseBalance(state, test.i, test.nb); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -101,7 +101,9 @@ func BenchmarkShuffledIndex(b *testing.B) {
|
||||
for _, listSize := range listSizes {
|
||||
b.Run(fmt.Sprintf("ShuffledIndex_%d", listSize), func(ib *testing.B) {
|
||||
for i := uint64(0); i < uint64(ib.N); i++ {
|
||||
ShuffledIndex(i%listSize, listSize, seed)
|
||||
if _, err := ShuffledIndex(i%listSize, listSize, seed); err != nil {
|
||||
b.Error(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -115,7 +117,9 @@ func BenchmarkIndexComparison(b *testing.B) {
|
||||
for i := 0; i < ib.N; i++ {
|
||||
// Simulate a list-shuffle by running shuffle-index listSize times.
|
||||
for j := uint64(0); j < listSize; j++ {
|
||||
ShuffledIndex(j, listSize, seed)
|
||||
if _, err := ShuffledIndex(j, listSize, seed); err != nil {
|
||||
b.Error(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -132,7 +136,9 @@ func BenchmarkShuffleList(b *testing.B) {
|
||||
}
|
||||
b.Run(fmt.Sprintf("ShuffleList_%d", listSize), func(ib *testing.B) {
|
||||
for i := 0; i < ib.N; i++ {
|
||||
ShuffleList(testIndices, seed)
|
||||
if _, err := ShuffleList(testIndices, seed); err != nil {
|
||||
b.Error(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
146
beacon-chain/core/helpers/signing_root.go
Normal file
146
beacon-chain/core/helpers/signing_root.go
Normal file
@@ -0,0 +1,146 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/go-ssz"
|
||||
p2ppb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bls"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
|
||||
// ForkVersionByteLength length of fork version byte array.
|
||||
const ForkVersionByteLength = 4
|
||||
|
||||
// DomainByteLength length of domain byte array.
|
||||
const DomainByteLength = 4
|
||||
|
||||
// ErrSigFailedToVerify returns when a signature of a block object(ie attestation, slashing, exit... etc)
|
||||
// failed to verify.
|
||||
var ErrSigFailedToVerify = errors.New("signature did not verify")
|
||||
|
||||
// ComputeSigningRoot computes the root of the object by calculating the root of the object domain tree.
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
// def compute_signing_root(ssz_object: SSZObject, domain: Domain) -> Root:
|
||||
// """
|
||||
// Return the signing root of an object by calculating the root of the object-domain tree.
|
||||
// """
|
||||
// domain_wrapped_object = SigningRoot(
|
||||
// object_root=hash_tree_root(ssz_object),
|
||||
// domain=domain,
|
||||
// )
|
||||
// return hash_tree_root(domain_wrapped_object)
|
||||
func ComputeSigningRoot(object interface{}, domain []byte) ([32]byte, error) {
|
||||
objRoot, err := ssz.HashTreeRoot(object)
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
container := &p2ppb.SigningRoot{
|
||||
ObjectRoot: objRoot[:],
|
||||
Domain: domain,
|
||||
}
|
||||
return ssz.HashTreeRoot(container)
|
||||
}
|
||||
|
||||
// VerifySigningRoot verifies the signing root of an object given it's public key, signature and domain.
|
||||
func VerifySigningRoot(obj interface{}, pub []byte, signature []byte, domain []byte) error {
|
||||
publicKey, err := bls.PublicKeyFromBytes(pub)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not convert bytes to public key")
|
||||
}
|
||||
sig, err := bls.SignatureFromBytes(signature)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not convert bytes to signature")
|
||||
}
|
||||
root, err := ComputeSigningRoot(obj, domain)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not compute signing root")
|
||||
}
|
||||
if !sig.Verify(root[:], publicKey) {
|
||||
return ErrSigFailedToVerify
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ComputeDomain returns the domain version for BLS private key to sign and verify with a zeroed 4-byte
|
||||
// array as the fork version.
|
||||
//
|
||||
// def compute_domain(domain_type: DomainType, fork_version: Version=None, genesis_validators_root: Root=None) -> Domain:
|
||||
// """
|
||||
// Return the domain for the ``domain_type`` and ``fork_version``.
|
||||
// """
|
||||
// if fork_version is None:
|
||||
// fork_version = GENESIS_FORK_VERSION
|
||||
// if genesis_validators_root is None:
|
||||
// genesis_validators_root = Root() # all bytes zero by default
|
||||
// fork_data_root = compute_fork_data_root(fork_version, genesis_validators_root)
|
||||
// return Domain(domain_type + fork_data_root[:28])
|
||||
func ComputeDomain(domainType [DomainByteLength]byte, forkVersion []byte, genesisValidatorsRoot []byte) ([]byte, error) {
|
||||
if forkVersion == nil {
|
||||
forkVersion = params.BeaconConfig().GenesisForkVersion
|
||||
}
|
||||
if genesisValidatorsRoot == nil {
|
||||
genesisValidatorsRoot = params.BeaconConfig().ZeroHash[:]
|
||||
}
|
||||
forkBytes := [ForkVersionByteLength]byte{}
|
||||
copy(forkBytes[:], forkVersion)
|
||||
|
||||
forkDataRoot, err := computeForkDataRoot(forkBytes[:], genesisValidatorsRoot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return domain(domainType, forkDataRoot[:]), nil
|
||||
}
|
||||
|
||||
// This returns the bls domain given by the domain type and fork data root.
|
||||
func domain(domainType [DomainByteLength]byte, forkDataRoot []byte) []byte {
|
||||
b := []byte{}
|
||||
b = append(b, domainType[:4]...)
|
||||
b = append(b, forkDataRoot[:28]...)
|
||||
return b
|
||||
}
|
||||
|
||||
// this returns the 32byte fork data root for the ``current_version`` and ``genesis_validators_root``.
|
||||
// This is used primarily in signature domains to avoid collisions across forks/chains.
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
// def compute_fork_data_root(current_version: Version, genesis_validators_root: Root) -> Root:
|
||||
// """
|
||||
// Return the 32-byte fork data root for the ``current_version`` and ``genesis_validators_root``.
|
||||
// This is used primarily in signature domains to avoid collisions across forks/chains.
|
||||
// """
|
||||
// return hash_tree_root(ForkData(
|
||||
// current_version=current_version,
|
||||
// genesis_validators_root=genesis_validators_root,
|
||||
// ))
|
||||
func computeForkDataRoot(version []byte, root []byte) ([32]byte, error) {
|
||||
r, err := ssz.HashTreeRoot(&pb.ForkData{
|
||||
CurrentVersion: version,
|
||||
GenesisValidatorsRoot: root,
|
||||
})
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// ComputeForkDigest returns the fork for the current version and genesis validator root
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
// def compute_fork_digest(current_version: Version, genesis_validators_root: Root) -> ForkDigest:
|
||||
// """
|
||||
// Return the 4-byte fork digest for the ``current_version`` and ``genesis_validators_root``.
|
||||
// This is a digest primarily used for domain separation on the p2p layer.
|
||||
// 4-bytes suffices for practical separation of forks/chains.
|
||||
// """
|
||||
// return ForkDigest(compute_fork_data_root(current_version, genesis_validators_root)[:4])
|
||||
func ComputeForkDigest(version []byte, genesisValidatorsRoot []byte) ([4]byte, error) {
|
||||
dataRoot, err := computeForkDataRoot(version, genesisValidatorsRoot)
|
||||
if err != nil {
|
||||
return [4]byte{}, nil
|
||||
}
|
||||
return bytesutil.ToBytes4(dataRoot[:]), nil
|
||||
}
|
||||
86
beacon-chain/core/helpers/signing_root_test.go
Normal file
86
beacon-chain/core/helpers/signing_root_test.go
Normal file
@@ -0,0 +1,86 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
fuzz "github.com/google/gofuzz"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
ethereum_beacon_p2p_v1 "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
|
||||
func TestSigningRoot_ComputeOK(t *testing.T) {
|
||||
emptyBlock := ðpb.BeaconBlock{}
|
||||
_, err := ComputeSigningRoot(emptyBlock, []byte{'T', 'E', 'S', 'T'})
|
||||
if err != nil {
|
||||
t.Errorf("Could not compute signing root of block: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestComputeDomain_OK(t *testing.T) {
|
||||
tests := []struct {
|
||||
epoch uint64
|
||||
domainType [4]byte
|
||||
domain []byte
|
||||
}{
|
||||
{epoch: 1, domainType: [4]byte{4, 0, 0, 0}, domain: []byte{4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
|
||||
{epoch: 2, domainType: [4]byte{4, 0, 0, 0}, domain: []byte{4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
|
||||
{epoch: 2, domainType: [4]byte{5, 0, 0, 0}, domain: []byte{5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
|
||||
{epoch: 3, domainType: [4]byte{4, 0, 0, 0}, domain: []byte{4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
|
||||
{epoch: 3, domainType: [4]byte{5, 0, 0, 0}, domain: []byte{5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
if !bytes.Equal(domain(tt.domainType, params.BeaconConfig().ZeroHash[:]), tt.domain) {
|
||||
t.Errorf("wanted domain version: %d, got: %d", tt.domain, domain(tt.domainType, params.BeaconConfig().ZeroHash[:]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestComputeForkDigest_OK(t *testing.T) {
|
||||
tests := []struct {
|
||||
version []byte
|
||||
root [32]byte
|
||||
result [4]byte
|
||||
}{
|
||||
{version: []byte{'A', 'B', 'C', 'D'}, root: [32]byte{'i', 'o', 'p'}, result: [4]byte{0x69, 0x5c, 0x26, 0x47}},
|
||||
{version: []byte{'i', 'm', 'n', 'a'}, root: [32]byte{'z', 'a', 'b'}, result: [4]byte{0x1c, 0x38, 0x84, 0x58}},
|
||||
{version: []byte{'b', 'w', 'r', 't'}, root: [32]byte{'r', 'd', 'c'}, result: [4]byte{0x83, 0x34, 0x38, 0x88}},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
digest, err := ComputeForkDigest(tt.version, tt.root[:])
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if digest != tt.result {
|
||||
t.Errorf("wanted domain version: %#x, got: %#x", digest, tt.result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFuzzverifySigningRoot_10000(t *testing.T) {
|
||||
fuzzer := fuzz.NewWithSeed(0)
|
||||
state := ðereum_beacon_p2p_v1.BeaconState{}
|
||||
pubkey := [48]byte{}
|
||||
sig := [96]byte{}
|
||||
domain := [4]byte{}
|
||||
p := []byte{}
|
||||
s := []byte{}
|
||||
d := []byte{}
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(&pubkey)
|
||||
fuzzer.Fuzz(&sig)
|
||||
fuzzer.Fuzz(&domain)
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(&p)
|
||||
fuzzer.Fuzz(&s)
|
||||
fuzzer.Fuzz(&d)
|
||||
if err := VerifySigningRoot(state, pubkey[:], sig[:], domain[:]); err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
if err := VerifySigningRoot(state, p, s, d); err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -89,15 +89,17 @@ func SlotsSinceEpochStarts(slot uint64) uint64 {
|
||||
return slot - StartSlot(SlotToEpoch(slot))
|
||||
}
|
||||
|
||||
// Allow for slots "from the future" within a certain tolerance.
|
||||
const timeShiftTolerance = 10 // ms
|
||||
// TimeShiftTolerance specifies the tolerance threshold for slots "from the future".
|
||||
const TimeShiftTolerance = 500 * time.Millisecond // ms
|
||||
|
||||
// VerifySlotTime validates the input slot is not from the future.
|
||||
func VerifySlotTime(genesisTime uint64, slot uint64) error {
|
||||
slotTime := genesisTime + slot*params.BeaconConfig().SecondsPerSlot
|
||||
currentTime := uint64(roughtime.Now().Unix())
|
||||
if slotTime > currentTime+timeShiftTolerance {
|
||||
return fmt.Errorf("could not process slot from the future, slot time %d > current time %d", slotTime, currentTime)
|
||||
func VerifySlotTime(genesisTime uint64, slot uint64, timeTolerance time.Duration) error {
|
||||
// denominate everything in milliseconds
|
||||
slotTime := 1000 * (genesisTime + slot*params.BeaconConfig().SecondsPerSlot)
|
||||
currentTime := 1000 * uint64(roughtime.Now().Unix())
|
||||
tolerance := uint64(timeTolerance.Milliseconds())
|
||||
if slotTime > currentTime+tolerance {
|
||||
return fmt.Errorf("could not process slot from the future, slot time(ms) %d > current time(ms) %d", slotTime, currentTime)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -38,7 +38,10 @@ func TestCurrentEpoch_OK(t *testing.T) {
|
||||
{slot: 200, epoch: 6},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{Slot: tt.slot})
|
||||
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{Slot: tt.slot})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if tt.epoch != CurrentEpoch(state) {
|
||||
t.Errorf("CurrentEpoch(%d) = %d, wanted: %d", state.Slot(), CurrentEpoch(state), tt.epoch)
|
||||
}
|
||||
@@ -55,7 +58,10 @@ func TestPrevEpoch_OK(t *testing.T) {
|
||||
{slot: 2 * params.BeaconConfig().SlotsPerEpoch, epoch: 1},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{Slot: tt.slot})
|
||||
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{Slot: tt.slot})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if tt.epoch != PrevEpoch(state) {
|
||||
t.Errorf("PrevEpoch(%d) = %d, wanted: %d", state.Slot(), PrevEpoch(state), tt.epoch)
|
||||
}
|
||||
@@ -74,7 +80,10 @@ func TestNextEpoch_OK(t *testing.T) {
|
||||
{slot: 200, epoch: 200/params.BeaconConfig().SlotsPerEpoch + 1},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{Slot: tt.slot})
|
||||
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{Slot: tt.slot})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if tt.epoch != NextEpoch(state) {
|
||||
t.Errorf("NextEpoch(%d) = %d, wanted: %d", state.Slot(), NextEpoch(state), tt.epoch)
|
||||
}
|
||||
|
||||
@@ -74,12 +74,14 @@ func ActiveValidatorIndices(state *stateTrie.BeaconState, epoch uint64) ([]uint6
|
||||
return activeIndices, nil
|
||||
}
|
||||
var indices []uint64
|
||||
state.ReadFromEveryValidator(func(idx int, val *stateTrie.ReadOnlyValidator) error {
|
||||
if err := state.ReadFromEveryValidator(func(idx int, val *stateTrie.ReadOnlyValidator) error {
|
||||
if IsActiveValidatorUsingTrie(val, epoch) {
|
||||
indices = append(indices, uint64(idx))
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := UpdateCommitteeCache(state, epoch); err != nil {
|
||||
return nil, errors.Wrap(err, "could not update committee cache")
|
||||
@@ -92,12 +94,14 @@ func ActiveValidatorIndices(state *stateTrie.BeaconState, epoch uint64) ([]uint6
|
||||
// at the given epoch.
|
||||
func ActiveValidatorCount(state *stateTrie.BeaconState, epoch uint64) (uint64, error) {
|
||||
count := uint64(0)
|
||||
state.ReadFromEveryValidator(func(idx int, val *stateTrie.ReadOnlyValidator) error {
|
||||
if err := state.ReadFromEveryValidator(func(idx int, val *stateTrie.ReadOnlyValidator) error {
|
||||
if IsActiveValidatorUsingTrie(val, epoch) {
|
||||
count++
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
@@ -231,18 +235,16 @@ func ComputeProposerIndex(validators []*ethpb.Validator, activeIndices []uint64,
|
||||
// Domain returns the domain version for BLS private key to sign and verify.
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
// def get_domain(state: BeaconState,
|
||||
// domain_type: int,
|
||||
// message_epoch: Epoch=None) -> int:
|
||||
// def get_domain(state: BeaconState, domain_type: DomainType, epoch: Epoch=None) -> Domain:
|
||||
// """
|
||||
// Return the signature domain (fork version concatenated with domain type) of a message.
|
||||
// """
|
||||
// epoch = get_current_epoch(state) if message_epoch is None else message_epoch
|
||||
// epoch = get_current_epoch(state) if epoch is None else epoch
|
||||
// fork_version = state.fork.previous_version if epoch < state.fork.epoch else state.fork.current_version
|
||||
// return bls_domain(domain_type, fork_version)
|
||||
func Domain(fork *pb.Fork, epoch uint64, domainType [bls.DomainByteLength]byte) (uint64, error) {
|
||||
// return compute_domain(domain_type, fork_version, state.genesis_validators_root)
|
||||
func Domain(fork *pb.Fork, epoch uint64, domainType [bls.DomainByteLength]byte, genesisRoot []byte) ([]byte, error) {
|
||||
if fork == nil {
|
||||
return 0, errors.New("nil fork or domain type")
|
||||
return []byte{}, errors.New("nil fork or domain type")
|
||||
}
|
||||
var forkVersion []byte
|
||||
if epoch < fork.Epoch {
|
||||
@@ -251,11 +253,11 @@ func Domain(fork *pb.Fork, epoch uint64, domainType [bls.DomainByteLength]byte)
|
||||
forkVersion = fork.CurrentVersion
|
||||
}
|
||||
if len(forkVersion) != 4 {
|
||||
return 0, errors.New("fork version length is not 4 byte")
|
||||
return []byte{}, errors.New("fork version length is not 4 byte")
|
||||
}
|
||||
var forkVersionArray [4]byte
|
||||
copy(forkVersionArray[:], forkVersion[:4])
|
||||
return bls.Domain(domainType, forkVersionArray), nil
|
||||
return ComputeDomain(domainType, forkVersionArray[:], genesisRoot)
|
||||
}
|
||||
|
||||
// IsEligibleForActivationQueue checks if the validator is eligible to
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
@@ -128,11 +129,14 @@ func TestBeaconProposerIndex_OK(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
state, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
Validators: validators,
|
||||
Slot: 0,
|
||||
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
slot uint64
|
||||
@@ -162,7 +166,9 @@ func TestBeaconProposerIndex_OK(t *testing.T) {
|
||||
|
||||
for _, tt := range tests {
|
||||
ClearCache()
|
||||
state.SetSlot(tt.slot)
|
||||
if err := state.SetSlot(tt.slot); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
result, err := BeaconProposerIndex(state)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to get shard and committees at slot: %v", err)
|
||||
@@ -205,11 +211,14 @@ func TestChurnLimit_OK(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
beaconState, _ := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
beaconState, err := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
Slot: 1,
|
||||
Validators: validators,
|
||||
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
validatorCount, err := ActiveValidatorCount(beaconState, CurrentEpoch(beaconState))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -235,22 +244,22 @@ func TestDomain_OK(t *testing.T) {
|
||||
}
|
||||
tests := []struct {
|
||||
epoch uint64
|
||||
domainType uint64
|
||||
version uint64
|
||||
domainType [4]byte
|
||||
result []byte
|
||||
}{
|
||||
{epoch: 1, domainType: 4, version: 144115188075855876},
|
||||
{epoch: 2, domainType: 4, version: 144115188075855876},
|
||||
{epoch: 2, domainType: 5, version: 144115188075855877},
|
||||
{epoch: 3, domainType: 4, version: 216172782113783812},
|
||||
{epoch: 3, domainType: 5, version: 216172782113783813},
|
||||
{epoch: 1, domainType: bytesutil.ToBytes4(bytesutil.Bytes4(4)), result: bytesutil.ToBytes(947067381421703172, 32)},
|
||||
{epoch: 2, domainType: bytesutil.ToBytes4(bytesutil.Bytes4(4)), result: bytesutil.ToBytes(947067381421703172, 32)},
|
||||
{epoch: 2, domainType: bytesutil.ToBytes4(bytesutil.Bytes4(5)), result: bytesutil.ToBytes(947067381421703173, 32)},
|
||||
{epoch: 3, domainType: bytesutil.ToBytes4(bytesutil.Bytes4(4)), result: bytesutil.ToBytes(9369798235163459588, 32)},
|
||||
{epoch: 3, domainType: bytesutil.ToBytes4(bytesutil.Bytes4(5)), result: bytesutil.ToBytes(9369798235163459589, 32)},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
domain, err := Domain(state.Fork, tt.epoch, bytesutil.ToBytes4(bytesutil.Bytes4(tt.domainType)))
|
||||
domain, err := Domain(state.Fork, tt.epoch, tt.domainType, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if domain != tt.version {
|
||||
t.Errorf("wanted domain version: %d, got: %d", tt.version, domain)
|
||||
if !bytes.Equal(domain[:8], tt.result[:8]) {
|
||||
t.Errorf("wanted domain version: %d, got: %d", tt.result, domain)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -404,7 +413,10 @@ func TestActiveValidatorIndices(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s, _ := beaconstate.InitializeFromProto(tt.args.state)
|
||||
s, err := beaconstate.InitializeFromProto(tt.args.state)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got, err := ActiveValidatorIndices(s, tt.args.epoch)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("ActiveValidatorIndices() error = %v, wantErr %v", err, tt.wantErr)
|
||||
@@ -588,7 +600,10 @@ func TestIsIsEligibleForActivation(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s, _ := beaconstate.InitializeFromProto(tt.state)
|
||||
s, err := beaconstate.InitializeFromProto(tt.state)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got := IsEligibleForActivation(s, tt.validator); got != tt.want {
|
||||
t.Errorf("IsEligibleForActivation() = %v, want %v", got, tt.want)
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ go_library(
|
||||
"//shared/testutil:__pkg__",
|
||||
"//tools/benchmark-files-gen:__pkg__",
|
||||
"//tools/genesis-state-gen:__pkg__",
|
||||
"//endtoend:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
"//beacon-chain/cache:go_default_library",
|
||||
@@ -34,6 +35,7 @@ go_library(
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@io_opencensus_go//trace:go_default_library",
|
||||
],
|
||||
)
|
||||
@@ -42,7 +44,6 @@ go_test(
|
||||
name = "go_default_test",
|
||||
size = "small",
|
||||
srcs = [
|
||||
"benchmarks_test.go",
|
||||
"skip_slot_cache_test.go",
|
||||
"state_fuzz_test.go",
|
||||
"state_test.go",
|
||||
@@ -51,15 +52,15 @@ go_test(
|
||||
],
|
||||
data = ["//shared/benchutil/benchmark_files:benchmark_data"],
|
||||
embed = [":go_default_library"],
|
||||
shard_count = 3,
|
||||
deps = [
|
||||
"//beacon-chain/core/blocks:go_default_library",
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//beacon-chain/state/stateutil:go_default_library",
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/attestationutil:go_default_library",
|
||||
"//shared/benchutil:go_default_library",
|
||||
"//shared/bls:go_default_library",
|
||||
"//shared/featureconfig:go_default_library",
|
||||
"//shared/hashutil:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"//shared/testutil:go_default_library",
|
||||
@@ -72,3 +73,31 @@ go_test(
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_benchmark_test",
|
||||
size = "large",
|
||||
srcs = ["benchmarks_test.go"],
|
||||
args = [
|
||||
"-test.bench=.",
|
||||
"-test.benchmem",
|
||||
"-test.v",
|
||||
],
|
||||
local = True,
|
||||
tags = [
|
||||
"benchmark",
|
||||
"manual",
|
||||
"no-cache",
|
||||
],
|
||||
deps = [
|
||||
"//beacon-chain/core/blocks:go_default_library",
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/core/state:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/benchutil:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"@com_github_gogo_protobuf//proto:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
package state
|
||||
package state_benchmark_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/prysmaticlabs/go-ssz"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
|
||||
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/benchutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
@@ -24,9 +27,14 @@ func TestBenchmarkExecuteStateTransition(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := ExecuteStateTransition(context.Background(), beaconState, block); err != nil {
|
||||
oldSlot := beaconState.Slot()
|
||||
beaconState, err = state.ExecuteStateTransition(context.Background(), beaconState, block)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to process block, benchmarks will fail: %v", err)
|
||||
}
|
||||
if oldSlot == beaconState.Slot() {
|
||||
t.Fatal("Expected slots to be different")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkExecuteStateTransition_FullBlock(b *testing.B) {
|
||||
@@ -44,7 +52,7 @@ func BenchmarkExecuteStateTransition_FullBlock(b *testing.B) {
|
||||
b.N = runAmount
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := ExecuteStateTransition(context.Background(), cleanStates[i], block); err != nil {
|
||||
if _, err := state.ExecuteStateTransition(context.Background(), cleanStates[i], block); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -66,20 +74,24 @@ func BenchmarkExecuteStateTransition_WithCache(b *testing.B) {
|
||||
// We have to reset slot back to last epoch to hydrate cache. Since
|
||||
// some attestations in block are from previous epoch
|
||||
currentSlot := beaconState.Slot()
|
||||
beaconState.SetSlot(beaconState.Slot() - params.BeaconConfig().SlotsPerEpoch)
|
||||
if err := beaconState.SetSlot(beaconState.Slot() - params.BeaconConfig().SlotsPerEpoch); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
if err := helpers.UpdateCommitteeCache(beaconState, helpers.CurrentEpoch(beaconState)); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
beaconState.SetSlot(currentSlot)
|
||||
if err := beaconState.SetSlot(currentSlot); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
// Run the state transition once to populate the cache.
|
||||
if _, err := ExecuteStateTransition(context.Background(), beaconState, block); err != nil {
|
||||
if _, err := state.ExecuteStateTransition(context.Background(), beaconState, block); err != nil {
|
||||
b.Fatalf("failed to process block, benchmarks will fail: %v", err)
|
||||
}
|
||||
|
||||
b.N = runAmount
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := ExecuteStateTransition(context.Background(), cleanStates[i], block); err != nil {
|
||||
if _, err := state.ExecuteStateTransition(context.Background(), cleanStates[i], block); err != nil {
|
||||
b.Fatalf("failed to process block, benchmarks will fail: %v", err)
|
||||
}
|
||||
}
|
||||
@@ -95,17 +107,21 @@ func BenchmarkProcessEpoch_2FullEpochs(b *testing.B) {
|
||||
// We have to reset slot back to last epoch to hydrate cache. Since
|
||||
// some attestations in block are from previous epoch
|
||||
currentSlot := beaconState.Slot()
|
||||
beaconState.SetSlot(beaconState.Slot() - params.BeaconConfig().SlotsPerEpoch)
|
||||
if err := beaconState.SetSlot(beaconState.Slot() - params.BeaconConfig().SlotsPerEpoch); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
if err := helpers.UpdateCommitteeCache(beaconState, helpers.CurrentEpoch(beaconState)); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
beaconState.SetSlot(currentSlot)
|
||||
if err := beaconState.SetSlot(currentSlot); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
// ProcessEpochPrecompute is the optimized version of process epoch. It's enabled by default
|
||||
// at run time.
|
||||
if _, err := ProcessEpochPrecompute(context.Background(), beaconState.Copy()); err != nil {
|
||||
if _, err := state.ProcessEpochPrecompute(context.Background(), beaconState.Copy()); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -133,19 +149,88 @@ func BenchmarkHashTreeRootState_FullState(b *testing.B) {
|
||||
}
|
||||
|
||||
// Hydrate the HashTreeRootState cache.
|
||||
if _, err := beaconState.HashTreeRoot(); err != nil {
|
||||
if _, err := beaconState.HashTreeRoot(ctx); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
b.N = 50
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := beaconState.HashTreeRoot(); err != nil {
|
||||
if _, err := beaconState.HashTreeRoot(ctx); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMarshalState_FullState(b *testing.B) {
|
||||
beaconState, err := benchutil.PreGenState2FullEpochs()
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
natState := beaconState.InnerStateUnsafe()
|
||||
|
||||
b.Run("Proto_Marshal", func(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
b.N = 1000
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := proto.Marshal(natState); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
b.Run("Fast_SSZ_Marshal", func(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
b.N = 1000
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := natState.MarshalSSZ(); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkUnmarshalState_FullState(b *testing.B) {
|
||||
beaconState, err := benchutil.PreGenState2FullEpochs()
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
natState := beaconState.InnerStateUnsafe()
|
||||
protoObject, err := proto.Marshal(natState)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
sszObject, err := natState.MarshalSSZ()
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
b.Run("Proto_Unmarshal", func(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
b.N = 1000
|
||||
for i := 0; i < b.N; i++ {
|
||||
if err := proto.Unmarshal(protoObject, &pb.BeaconState{}); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
b.Run("Fast_SSZ_Unmarshal", func(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
b.N = 1000
|
||||
for i := 0; i < b.N; i++ {
|
||||
sszState := &pb.BeaconState{}
|
||||
if err := sszState.UnmarshalSSZ(sszObject); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func clonedStates(beaconState *beaconstate.BeaconState) []*beaconstate.BeaconState {
|
||||
clonedStates := make([]*beaconstate.BeaconState, runAmount)
|
||||
for i := 0; i < runAmount; i++ {
|
||||
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||
)
|
||||
|
||||
// skipSlotCache exists for the unlikely scenario that is a large gap between the head state and
|
||||
// SkipSlotCache exists for the unlikely scenario that is a large gap between the head state and
|
||||
// the current slot. If the beacon chain were ever to be stalled for several epochs, it may be
|
||||
// difficult or impossible to compute the appropriate beacon state for assignments within a
|
||||
// reasonable amount of time.
|
||||
var skipSlotCache = cache.NewSkipSlotCache()
|
||||
var SkipSlotCache = cache.NewSkipSlotCache()
|
||||
|
||||
@@ -7,26 +7,22 @@ import (
|
||||
"github.com/prysmaticlabs/go-ssz"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
|
||||
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
)
|
||||
|
||||
func TestSkipSlotCache_OK(t *testing.T) {
|
||||
state.SkipSlotCache.Enable()
|
||||
defer state.SkipSlotCache.Disable()
|
||||
bState, privs := testutil.DeterministicGenesisState(t, params.MinimalSpecConfig().MinGenesisActiveValidatorCount)
|
||||
originalState, _ := beaconstate.InitializeFromProto(bState.CloneInnerState())
|
||||
originalState, err := beaconstate.InitializeFromProto(bState.CloneInnerState())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
blkCfg := testutil.DefaultBlockGenConfig()
|
||||
blkCfg.NumAttestations = 1
|
||||
|
||||
cfg := featureconfig.Get()
|
||||
cfg.EnableSkipSlotsCache = true
|
||||
featureconfig.Init(cfg)
|
||||
defer func() {
|
||||
cfg.EnableSkipSlotsCache = false
|
||||
featureconfig.Init(cfg)
|
||||
}()
|
||||
|
||||
// First transition will be with an empty cache, so the cache becomes populated
|
||||
// with the state
|
||||
blk, err := testutil.GenerateFullBlock(bState, privs, blkCfg, originalState.Slot()+10)
|
||||
|
||||
@@ -34,8 +34,8 @@ go_test(
|
||||
"@com_github_gogo_protobuf//proto:go_default_library",
|
||||
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
|
||||
"@com_github_urfave_cli//:go_default_library",
|
||||
"@in_gopkg_d4l3k_messagediff_v1//:go_default_library",
|
||||
"@in_gopkg_urfave_cli_v2//:go_default_library",
|
||||
"@io_bazel_rules_go//go/tools/bazel:go_default_library",
|
||||
],
|
||||
)
|
||||
@@ -68,8 +68,8 @@ go_test(
|
||||
"@com_github_gogo_protobuf//proto:go_default_library",
|
||||
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
|
||||
"@com_github_urfave_cli//:go_default_library",
|
||||
"@in_gopkg_d4l3k_messagediff_v1//:go_default_library",
|
||||
"@in_gopkg_urfave_cli_v2//:go_default_library",
|
||||
"@io_bazel_rules_go//go/tools/bazel:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -15,6 +15,10 @@ import (
|
||||
"gopkg.in/d4l3k/messagediff.v1"
|
||||
)
|
||||
|
||||
func init() {
|
||||
state.SkipSlotCache.Disable()
|
||||
}
|
||||
|
||||
func runSlotProcessingTests(t *testing.T, config string) {
|
||||
if err := spectest.SetConfig(config); err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/prysmaticlabs/go-ssz"
|
||||
b "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/trieutil"
|
||||
@@ -137,10 +138,16 @@ func OptimizedGenesisBeaconState(genesisTime uint64, preState *stateTrie.BeaconS
|
||||
|
||||
slashings := make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector)
|
||||
|
||||
genesisValidatorsRoot, err := stateutil.ValidatorRegistryRoot(preState.Validators())
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not hash tree root genesis validators %v", err)
|
||||
}
|
||||
|
||||
state := &pb.BeaconState{
|
||||
// Misc fields.
|
||||
Slot: 0,
|
||||
GenesisTime: genesisTime,
|
||||
Slot: 0,
|
||||
GenesisTime: genesisTime,
|
||||
GenesisValidatorsRoot: genesisValidatorsRoot[:],
|
||||
|
||||
Fork: &pb.Fork{
|
||||
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
|
||||
|
||||
@@ -9,6 +9,8 @@ import (
|
||||
)
|
||||
|
||||
func TestGenesisBeaconState_1000(t *testing.T) {
|
||||
SkipSlotCache.Disable()
|
||||
defer SkipSlotCache.Enable()
|
||||
fuzzer := fuzz.NewWithSeed(0)
|
||||
fuzzer.NilChance(0.1)
|
||||
deposits := make([]*ethpb.Deposit, 300000)
|
||||
@@ -29,6 +31,8 @@ func TestGenesisBeaconState_1000(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestOptimizedGenesisBeaconState_1000(t *testing.T) {
|
||||
SkipSlotCache.Disable()
|
||||
defer SkipSlotCache.Enable()
|
||||
fuzzer := fuzz.NewWithSeed(0)
|
||||
fuzzer.NilChance(0.1)
|
||||
var genesisTime uint64
|
||||
@@ -49,6 +53,8 @@ func TestOptimizedGenesisBeaconState_1000(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestIsValidGenesisState_100000(t *testing.T) {
|
||||
SkipSlotCache.Disable()
|
||||
defer SkipSlotCache.Enable()
|
||||
fuzzer := fuzz.NewWithSeed(0)
|
||||
fuzzer.NilChance(0.1)
|
||||
var chainStartDepositCount, currentTime uint64
|
||||
|
||||
@@ -42,7 +42,10 @@ func TestGenesisBeaconState_OK(t *testing.T) {
|
||||
}
|
||||
|
||||
genesisTime := uint64(99999)
|
||||
deposits, _, _ := testutil.DeterministicDepositsAndKeys(uint64(depositsForChainStart))
|
||||
deposits, _, err := testutil.DeterministicDepositsAndKeys(uint64(depositsForChainStart))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
eth1Data, err := testutil.DeterministicEth1Data(len(deposits))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -68,10 +71,18 @@ func TestGenesisBeaconState_OK(t *testing.T) {
|
||||
if len(newState.Validators()) != depositsForChainStart {
|
||||
t.Error("Validators was not correctly initialized")
|
||||
}
|
||||
if v, _ := newState.ValidatorAtIndex(0); v.ActivationEpoch != 0 {
|
||||
v, err := newState.ValidatorAtIndex(0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if v.ActivationEpoch != 0 {
|
||||
t.Error("Validators was not correctly initialized")
|
||||
}
|
||||
if v, _ := newState.ValidatorAtIndex(0); v.ActivationEligibilityEpoch != 0 {
|
||||
v, err = newState.ValidatorAtIndex(0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if v.ActivationEligibilityEpoch != 0 {
|
||||
t.Error("Validators was not correctly initialized")
|
||||
}
|
||||
if len(newState.Balances()) != depositsForChainStart {
|
||||
@@ -82,7 +93,11 @@ func TestGenesisBeaconState_OK(t *testing.T) {
|
||||
if len(newState.RandaoMixes()) != latestRandaoMixesLength {
|
||||
t.Error("Length of RandaoMixes was not correctly initialized")
|
||||
}
|
||||
if mix, _ := newState.RandaoMixAtIndex(0); !bytes.Equal(mix, eth1Data.BlockHash) {
|
||||
mix, err := newState.RandaoMixAtIndex(0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Equal(mix, eth1Data.BlockHash) {
|
||||
t.Error("RandaoMixes was not correctly initialized")
|
||||
}
|
||||
|
||||
@@ -130,7 +145,10 @@ func TestGenesisBeaconState_OK(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGenesisState_HashEquality(t *testing.T) {
|
||||
deposits, _, _ := testutil.DeterministicDepositsAndKeys(100)
|
||||
deposits, _, err := testutil.DeterministicDepositsAndKeys(100)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
state1, err := state.GenesisBeaconState(deposits, 0, ðpb.Eth1Data{BlockHash: make([]byte, 32)})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/shared/mathutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/traceutil"
|
||||
"github.com/sirupsen/logrus"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
@@ -72,7 +73,7 @@ func ExecuteStateTransition(
|
||||
interop.WriteBlockToDisk(signed, false)
|
||||
interop.WriteStateToDisk(state)
|
||||
|
||||
postStateRoot, err := state.HashTreeRoot()
|
||||
postStateRoot, err := state.HashTreeRoot(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -181,7 +182,7 @@ func CalculateStateRoot(
|
||||
return [32]byte{}, errors.Wrap(err, "could not process block")
|
||||
}
|
||||
|
||||
return state.HashTreeRoot()
|
||||
return state.HashTreeRoot(ctx)
|
||||
}
|
||||
|
||||
// ProcessSlot happens every slot and focuses on the slot counter and block roots record updates.
|
||||
@@ -205,7 +206,7 @@ func ProcessSlot(ctx context.Context, state *stateTrie.BeaconState) (*stateTrie.
|
||||
defer span.End()
|
||||
span.AddAttributes(trace.Int64Attribute("slot", int64(state.Slot())))
|
||||
|
||||
prevStateRoot, err := state.HashTreeRoot()
|
||||
prevStateRoot, err := state.HashTreeRoot(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -274,7 +275,7 @@ func ProcessSlots(ctx context.Context, state *stateTrie.BeaconState, slot uint64
|
||||
key := state.Slot()
|
||||
|
||||
// Restart from cached value, if one exists.
|
||||
cachedState, err := skipSlotCache.Get(ctx, key)
|
||||
cachedState, err := SkipSlotCache.Get(ctx, key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -283,8 +284,8 @@ func ProcessSlots(ctx context.Context, state *stateTrie.BeaconState, slot uint64
|
||||
highestSlot = cachedState.Slot()
|
||||
state = cachedState
|
||||
}
|
||||
if err := skipSlotCache.MarkInProgress(key); err == cache.ErrAlreadyInProgress {
|
||||
cachedState, err = skipSlotCache.Get(ctx, key)
|
||||
if err := SkipSlotCache.MarkInProgress(key); err == cache.ErrAlreadyInProgress {
|
||||
cachedState, err = SkipSlotCache.Get(ctx, key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -295,14 +296,21 @@ func ProcessSlots(ctx context.Context, state *stateTrie.BeaconState, slot uint64
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer skipSlotCache.MarkNotInProgress(key)
|
||||
defer func() {
|
||||
if err := SkipSlotCache.MarkNotInProgress(key); err != nil {
|
||||
traceutil.AnnotateError(span, err)
|
||||
logrus.WithError(err).Error("Failed to mark skip slot no longer in progress")
|
||||
}
|
||||
}()
|
||||
|
||||
for state.Slot() < slot {
|
||||
if ctx.Err() != nil {
|
||||
traceutil.AnnotateError(span, ctx.Err())
|
||||
// Cache last best value.
|
||||
if highestSlot < state.Slot() {
|
||||
skipSlotCache.Put(ctx, key, state)
|
||||
if err := SkipSlotCache.Put(ctx, key, state); err != nil {
|
||||
logrus.WithError(err).Error("Failed to put skip slot cache value")
|
||||
}
|
||||
}
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
@@ -318,11 +326,17 @@ func ProcessSlots(ctx context.Context, state *stateTrie.BeaconState, slot uint64
|
||||
return nil, errors.Wrap(err, "could not process epoch with optimizations")
|
||||
}
|
||||
}
|
||||
state.SetSlot(state.Slot() + 1)
|
||||
if err := state.SetSlot(state.Slot() + 1); err != nil {
|
||||
traceutil.AnnotateError(span, err)
|
||||
return nil, errors.Wrap(err, "failed to increment state slot")
|
||||
}
|
||||
}
|
||||
|
||||
if highestSlot < state.Slot() {
|
||||
skipSlotCache.Put(ctx, key, state)
|
||||
if err := SkipSlotCache.Put(ctx, key, state); err != nil {
|
||||
logrus.WithError(err).Error("Failed to put skip slot cache value")
|
||||
traceutil.AnnotateError(span, err)
|
||||
}
|
||||
}
|
||||
|
||||
return state, nil
|
||||
@@ -605,8 +619,11 @@ func ProcessEpochPrecompute(ctx context.Context, state *stateTrie.BeaconState) (
|
||||
if state == nil {
|
||||
return nil, errors.New("nil state")
|
||||
}
|
||||
vp, bp := precompute.New(ctx, state)
|
||||
vp, bp, err := precompute.ProcessAttestations(ctx, state, vp, bp)
|
||||
vp, bp, err := precompute.New(ctx, state)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
vp, bp, err = precompute.ProcessAttestations(ctx, state, vp, bp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ import (
|
||||
)
|
||||
|
||||
func TestFuzzExecuteStateTransition_1000(t *testing.T) {
|
||||
SkipSlotCache.Disable()
|
||||
defer SkipSlotCache.Enable()
|
||||
ctx := context.Background()
|
||||
state := &stateTrie.BeaconState{}
|
||||
sb := ðpb.SignedBeaconBlock{}
|
||||
@@ -26,6 +28,8 @@ func TestFuzzExecuteStateTransition_1000(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFuzzExecuteStateTransitionNoVerifyAttSigs_1000(t *testing.T) {
|
||||
SkipSlotCache.Disable()
|
||||
defer SkipSlotCache.Enable()
|
||||
ctx := context.Background()
|
||||
state := &stateTrie.BeaconState{}
|
||||
sb := ðpb.SignedBeaconBlock{}
|
||||
@@ -42,6 +46,8 @@ func TestFuzzExecuteStateTransitionNoVerifyAttSigs_1000(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFuzzCalculateStateRoot_1000(t *testing.T) {
|
||||
SkipSlotCache.Disable()
|
||||
defer SkipSlotCache.Enable()
|
||||
ctx := context.Background()
|
||||
state := &stateTrie.BeaconState{}
|
||||
sb := ðpb.SignedBeaconBlock{}
|
||||
@@ -58,6 +64,8 @@ func TestFuzzCalculateStateRoot_1000(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFuzzProcessSlot_1000(t *testing.T) {
|
||||
SkipSlotCache.Disable()
|
||||
defer SkipSlotCache.Enable()
|
||||
ctx := context.Background()
|
||||
state := &stateTrie.BeaconState{}
|
||||
fuzzer := fuzz.NewWithSeed(0)
|
||||
@@ -72,6 +80,8 @@ func TestFuzzProcessSlot_1000(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFuzzProcessSlots_1000(t *testing.T) {
|
||||
SkipSlotCache.Disable()
|
||||
defer SkipSlotCache.Enable()
|
||||
ctx := context.Background()
|
||||
state := &stateTrie.BeaconState{}
|
||||
slot := uint64(0)
|
||||
@@ -88,6 +98,8 @@ func TestFuzzProcessSlots_1000(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFuzzProcessBlock_1000(t *testing.T) {
|
||||
SkipSlotCache.Disable()
|
||||
defer SkipSlotCache.Enable()
|
||||
ctx := context.Background()
|
||||
state := &stateTrie.BeaconState{}
|
||||
sb := ðpb.SignedBeaconBlock{}
|
||||
@@ -104,6 +116,8 @@ func TestFuzzProcessBlock_1000(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFuzzProcessBlockNoVerifyAttSigs_1000(t *testing.T) {
|
||||
SkipSlotCache.Disable()
|
||||
defer SkipSlotCache.Enable()
|
||||
ctx := context.Background()
|
||||
state := &stateTrie.BeaconState{}
|
||||
sb := ðpb.SignedBeaconBlock{}
|
||||
@@ -120,6 +134,8 @@ func TestFuzzProcessBlockNoVerifyAttSigs_1000(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFuzzProcessOperations_1000(t *testing.T) {
|
||||
SkipSlotCache.Disable()
|
||||
defer SkipSlotCache.Enable()
|
||||
ctx := context.Background()
|
||||
state := &stateTrie.BeaconState{}
|
||||
bb := ðpb.BeaconBlockBody{}
|
||||
@@ -136,6 +152,8 @@ func TestFuzzProcessOperations_1000(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFuzzprocessOperationsNoVerify_1000(t *testing.T) {
|
||||
SkipSlotCache.Disable()
|
||||
defer SkipSlotCache.Enable()
|
||||
ctx := context.Background()
|
||||
state := &stateTrie.BeaconState{}
|
||||
bb := ðpb.BeaconBlockBody{}
|
||||
@@ -152,6 +170,8 @@ func TestFuzzprocessOperationsNoVerify_1000(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFuzzverifyOperationLengths_10000(t *testing.T) {
|
||||
SkipSlotCache.Disable()
|
||||
defer SkipSlotCache.Enable()
|
||||
state := &stateTrie.BeaconState{}
|
||||
bb := ðpb.BeaconBlockBody{}
|
||||
fuzzer := fuzz.NewWithSeed(0)
|
||||
@@ -159,11 +179,15 @@ func TestFuzzverifyOperationLengths_10000(t *testing.T) {
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(state)
|
||||
fuzzer.Fuzz(bb)
|
||||
verifyOperationLengths(state, bb)
|
||||
if err := verifyOperationLengths(state, bb); err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFuzzCanProcessEpoch_10000(t *testing.T) {
|
||||
SkipSlotCache.Disable()
|
||||
defer SkipSlotCache.Enable()
|
||||
state := &stateTrie.BeaconState{}
|
||||
fuzzer := fuzz.NewWithSeed(0)
|
||||
fuzzer.NilChance(0.1)
|
||||
@@ -174,6 +198,8 @@ func TestFuzzCanProcessEpoch_10000(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFuzzProcessEpochPrecompute_1000(t *testing.T) {
|
||||
SkipSlotCache.Disable()
|
||||
defer SkipSlotCache.Enable()
|
||||
ctx := context.Background()
|
||||
state := &stateTrie.BeaconState{}
|
||||
fuzzer := fuzz.NewWithSeed(0)
|
||||
@@ -188,6 +214,8 @@ func TestFuzzProcessEpochPrecompute_1000(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFuzzProcessBlockForStateRoot_1000(t *testing.T) {
|
||||
SkipSlotCache.Disable()
|
||||
defer SkipSlotCache.Enable()
|
||||
ctx := context.Background()
|
||||
state := &stateTrie.BeaconState{}
|
||||
sb := ðpb.SignedBeaconBlock{}
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
|
||||
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/attestationutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/bls"
|
||||
@@ -25,6 +26,10 @@ import (
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func init() {
|
||||
state.SkipSlotCache.Disable()
|
||||
}
|
||||
|
||||
func TestExecuteStateTransition_IncorrectSlot(t *testing.T) {
|
||||
base := &pb.BeaconState{
|
||||
Slot: 5,
|
||||
@@ -39,7 +44,8 @@ func TestExecuteStateTransition_IncorrectSlot(t *testing.T) {
|
||||
},
|
||||
}
|
||||
want := "expected state.slot"
|
||||
if _, err := state.ExecuteStateTransition(context.Background(), beaconState, block); !strings.Contains(err.Error(), want) {
|
||||
_, err = state.ExecuteStateTransition(context.Background(), beaconState, block)
|
||||
if err == nil || !strings.Contains(err.Error(), want) {
|
||||
t.Errorf("Expected %s, received %v", want, err)
|
||||
}
|
||||
}
|
||||
@@ -51,33 +57,46 @@ func TestExecuteStateTransition_FullProcess(t *testing.T) {
|
||||
DepositCount: 100,
|
||||
DepositRoot: []byte{2},
|
||||
}
|
||||
beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch - 1)
|
||||
if err := beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch - 1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
e := beaconState.Eth1Data()
|
||||
e.DepositCount = 100
|
||||
beaconState.SetEth1Data(e)
|
||||
beaconState.SetLatestBlockHeader(ðpb.BeaconBlockHeader{Slot: beaconState.Slot()})
|
||||
beaconState.SetEth1DataVotes([]*ethpb.Eth1Data{eth1Data})
|
||||
if err := beaconState.SetEth1Data(e); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := beaconState.SetLatestBlockHeader(ðpb.BeaconBlockHeader{Slot: beaconState.Slot()}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := beaconState.SetEth1DataVotes([]*ethpb.Eth1Data{eth1Data}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
oldMix, err := beaconState.RandaoMixAtIndex(1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
parentRoot, err := ssz.HashTreeRoot(beaconState.LatestBlockHeader())
|
||||
parentRoot, err := stateutil.BlockHeaderRoot(beaconState.LatestBlockHeader())
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
beaconState.SetSlot(beaconState.Slot() + 1)
|
||||
if err := beaconState.SetSlot(beaconState.Slot() + 1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
epoch := helpers.CurrentEpoch(beaconState)
|
||||
randaoReveal, err := testutil.RandaoReveal(beaconState, epoch, privKeys)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
beaconState.SetSlot(beaconState.Slot() - 1)
|
||||
if err := beaconState.SetSlot(beaconState.Slot() - 1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
block := ðpb.SignedBeaconBlock{
|
||||
Block: ðpb.BeaconBlock{
|
||||
Slot: beaconState.Slot() + 1,
|
||||
ParentRoot: parentRoot[:],
|
||||
ProposerIndex: 74,
|
||||
Slot: beaconState.Slot() + 1,
|
||||
ParentRoot: parentRoot[:],
|
||||
Body: ðpb.BeaconBlockBody{
|
||||
RandaoReveal: randaoReveal,
|
||||
Eth1Data: eth1Data,
|
||||
@@ -107,7 +126,11 @@ func TestExecuteStateTransition_FullProcess(t *testing.T) {
|
||||
t.Errorf("Unexpected Slot number, expected: 64, received: %d", beaconState.Slot())
|
||||
}
|
||||
|
||||
if mix, _ := beaconState.RandaoMixAtIndex(1); bytes.Equal(mix, oldMix) {
|
||||
mix, err := beaconState.RandaoMixAtIndex(1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if bytes.Equal(mix, oldMix) {
|
||||
t.Errorf("Did not expect new and old randao mix to equal, %#x == %#x", mix, oldMix)
|
||||
}
|
||||
}
|
||||
@@ -125,21 +148,25 @@ func TestProcessBlock_IncorrectProposerSlashing(t *testing.T) {
|
||||
}
|
||||
block.Block.Body.ProposerSlashings = []*ethpb.ProposerSlashing{slashing}
|
||||
|
||||
blockRoot, err := ssz.HashTreeRoot(block.Block)
|
||||
if err != nil {
|
||||
if err := beaconState.SetSlot(beaconState.Slot() + 1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
beaconState.SetSlot(beaconState.Slot() + 1)
|
||||
proposerIdx, err := helpers.BeaconProposerIndex(beaconState)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
beaconState.SetSlot(beaconState.Slot() - 1)
|
||||
domain, err := helpers.Domain(beaconState.Fork(), helpers.CurrentEpoch(beaconState), params.BeaconConfig().DomainBeaconProposer)
|
||||
if err := beaconState.SetSlot(beaconState.Slot() - 1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
domain, err := helpers.Domain(beaconState.Fork(), helpers.CurrentEpoch(beaconState), params.BeaconConfig().DomainBeaconProposer, beaconState.GenesisValidatorRoot())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
sig := privKeys[proposerIdx].Sign(blockRoot[:], domain)
|
||||
root, err := helpers.ComputeSigningRoot(block.Block, domain)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
sig := privKeys[proposerIdx].Sign(root[:])
|
||||
block.Signature = sig.Marshal()
|
||||
|
||||
beaconState, err = state.ProcessSlots(context.Background(), beaconState, 1)
|
||||
@@ -147,7 +174,8 @@ func TestProcessBlock_IncorrectProposerSlashing(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
want := "could not process block proposer slashing"
|
||||
if _, err := state.ProcessBlock(context.Background(), beaconState, block); !strings.Contains(err.Error(), want) {
|
||||
_, err = state.ProcessBlock(context.Background(), beaconState, block)
|
||||
if err == nil || !strings.Contains(err.Error(), want) {
|
||||
t.Errorf("Expected %s, received %v", want, err)
|
||||
}
|
||||
}
|
||||
@@ -168,21 +196,25 @@ func TestProcessBlock_IncorrectProcessBlockAttestations(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
block.Block.Body.Attestations = []*ethpb.Attestation{att}
|
||||
blockRoot, err := ssz.HashTreeRoot(block.Block)
|
||||
if err != nil {
|
||||
if err := beaconState.SetSlot(beaconState.Slot() + 1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
beaconState.SetSlot(beaconState.Slot() + 1)
|
||||
proposerIdx, err := helpers.BeaconProposerIndex(beaconState)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
beaconState.SetSlot(beaconState.Slot() - 1)
|
||||
domain, err := helpers.Domain(beaconState.Fork(), helpers.CurrentEpoch(beaconState), params.BeaconConfig().DomainBeaconProposer)
|
||||
if err := beaconState.SetSlot(beaconState.Slot() - 1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
domain, err := helpers.Domain(beaconState.Fork(), helpers.CurrentEpoch(beaconState), params.BeaconConfig().DomainBeaconProposer, beaconState.GenesisValidatorRoot())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
sig := privKeys[proposerIdx].Sign(blockRoot[:], domain)
|
||||
root, err := helpers.ComputeSigningRoot(block.Block, domain)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
sig := privKeys[proposerIdx].Sign(root[:])
|
||||
block.Signature = sig.Marshal()
|
||||
|
||||
beaconState, err = state.ProcessSlots(context.Background(), beaconState, 1)
|
||||
@@ -191,7 +223,8 @@ func TestProcessBlock_IncorrectProcessBlockAttestations(t *testing.T) {
|
||||
}
|
||||
|
||||
want := "could not process block attestations"
|
||||
if _, err := state.ProcessBlock(context.Background(), beaconState, block); !strings.Contains(err.Error(), want) {
|
||||
_, err = state.ProcessBlock(context.Background(), beaconState, block)
|
||||
if err == nil || !strings.Contains(err.Error(), want) {
|
||||
t.Errorf("Expected %s, received %v", want, err)
|
||||
}
|
||||
}
|
||||
@@ -201,16 +234,17 @@ func TestProcessBlock_IncorrectProcessExits(t *testing.T) {
|
||||
|
||||
proposerSlashings := []*ethpb.ProposerSlashing{
|
||||
{
|
||||
ProposerIndex: 3,
|
||||
Header_1: ðpb.SignedBeaconBlockHeader{
|
||||
Header: ðpb.BeaconBlockHeader{
|
||||
Slot: 1,
|
||||
ProposerIndex: 3,
|
||||
Slot: 1,
|
||||
},
|
||||
Signature: []byte("A"),
|
||||
},
|
||||
Header_2: ðpb.SignedBeaconBlockHeader{
|
||||
Header: ðpb.BeaconBlockHeader{
|
||||
Slot: 1,
|
||||
ProposerIndex: 3,
|
||||
Slot: 1,
|
||||
},
|
||||
Signature: []byte("B"),
|
||||
},
|
||||
@@ -238,7 +272,9 @@ func TestProcessBlock_IncorrectProcessExits(t *testing.T) {
|
||||
for i := uint64(0); i < params.BeaconConfig().SlotsPerHistoricalRoot; i++ {
|
||||
blockRoots = append(blockRoots, []byte{byte(i)})
|
||||
}
|
||||
beaconState.SetBlockRoots(blockRoots)
|
||||
if err := beaconState.SetBlockRoots(blockRoots); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
blockAtt := ðpb.Attestation{
|
||||
Data: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 0},
|
||||
@@ -256,11 +292,14 @@ func TestProcessBlock_IncorrectProcessExits(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
beaconState.SetLatestBlockHeader(ðpb.BeaconBlockHeader{
|
||||
err = beaconState.SetLatestBlockHeader(ðpb.BeaconBlockHeader{
|
||||
Slot: genesisBlock.Block.Slot,
|
||||
ParentRoot: genesisBlock.Block.ParentRoot,
|
||||
BodyRoot: bodyRoot[:],
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
parentRoot, err := ssz.HashTreeRoot(beaconState.LatestBlockHeader())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -282,11 +321,18 @@ func TestProcessBlock_IncorrectProcessExits(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
beaconState.SetSlot(beaconState.Slot() + params.BeaconConfig().MinAttestationInclusionDelay)
|
||||
err = beaconState.SetSlot(beaconState.Slot() + params.BeaconConfig().MinAttestationInclusionDelay)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cp := beaconState.CurrentJustifiedCheckpoint()
|
||||
cp.Root = []byte("hello-world")
|
||||
beaconState.SetCurrentJustifiedCheckpoint(cp)
|
||||
beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{})
|
||||
if err := beaconState.SetCurrentJustifiedCheckpoint(cp); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := state.ProcessBlock(context.Background(), beaconState, block); err == nil {
|
||||
t.Error("Expected err, received nil")
|
||||
}
|
||||
@@ -299,29 +345,43 @@ func TestProcessBlock_PassesProcessingConditions(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
beaconState.SetLatestBlockHeader(ðpb.BeaconBlockHeader{
|
||||
err = beaconState.SetLatestBlockHeader(ðpb.BeaconBlockHeader{
|
||||
Slot: genesisBlock.Block.Slot,
|
||||
ParentRoot: genesisBlock.Block.ParentRoot,
|
||||
StateRoot: params.BeaconConfig().ZeroHash[:],
|
||||
BodyRoot: bodyRoot[:],
|
||||
})
|
||||
beaconState.SetSlashings(make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = beaconState.SetSlashings(make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cp := beaconState.CurrentJustifiedCheckpoint()
|
||||
mockRoot := [32]byte{}
|
||||
copy(mockRoot[:], "hello-world")
|
||||
cp.Root = mockRoot[:]
|
||||
beaconState.SetCurrentJustifiedCheckpoint(cp)
|
||||
beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{})
|
||||
if err := beaconState.SetCurrentJustifiedCheckpoint(cp); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
proposerSlashIdx := uint64(3)
|
||||
slotsPerEpoch := params.BeaconConfig().SlotsPerEpoch
|
||||
beaconState.SetSlot((params.BeaconConfig().PersistentCommitteePeriod * slotsPerEpoch) + params.BeaconConfig().MinAttestationInclusionDelay)
|
||||
err = beaconState.SetSlot((params.BeaconConfig().PersistentCommitteePeriod * slotsPerEpoch) + params.BeaconConfig().MinAttestationInclusionDelay)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
currentEpoch := helpers.CurrentEpoch(beaconState)
|
||||
domain, err := helpers.Domain(
|
||||
beaconState.Fork(),
|
||||
currentEpoch,
|
||||
params.BeaconConfig().DomainBeaconProposer,
|
||||
beaconState.GenesisValidatorRoot(),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -329,38 +389,41 @@ func TestProcessBlock_PassesProcessingConditions(t *testing.T) {
|
||||
|
||||
header1 := ðpb.SignedBeaconBlockHeader{
|
||||
Header: ðpb.BeaconBlockHeader{
|
||||
Slot: 1,
|
||||
StateRoot: []byte("A"),
|
||||
ProposerIndex: proposerSlashIdx,
|
||||
Slot: 1,
|
||||
StateRoot: []byte("A"),
|
||||
},
|
||||
}
|
||||
signingRoot, err := ssz.HashTreeRoot(header1.Header)
|
||||
root, err := helpers.ComputeSigningRoot(header1.Header, domain)
|
||||
if err != nil {
|
||||
t.Errorf("Could not get signing root of beacon block header: %v", err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
header1.Signature = privKeys[proposerSlashIdx].Sign(signingRoot[:], domain).Marshal()[:]
|
||||
header1.Signature = privKeys[proposerSlashIdx].Sign(root[:]).Marshal()[:]
|
||||
|
||||
header2 := ðpb.SignedBeaconBlockHeader{
|
||||
Header: ðpb.BeaconBlockHeader{
|
||||
Slot: 1,
|
||||
StateRoot: []byte("B"),
|
||||
ProposerIndex: proposerSlashIdx,
|
||||
Slot: 1,
|
||||
StateRoot: []byte("B"),
|
||||
},
|
||||
}
|
||||
signingRoot, err = ssz.HashTreeRoot(header2.Header)
|
||||
root, err = helpers.ComputeSigningRoot(header2.Header, domain)
|
||||
if err != nil {
|
||||
t.Errorf("Could not get signing root of beacon block header: %v", err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
header2.Signature = privKeys[proposerSlashIdx].Sign(signingRoot[:], domain).Marshal()[:]
|
||||
header2.Signature = privKeys[proposerSlashIdx].Sign(root[:]).Marshal()[:]
|
||||
|
||||
proposerSlashings := []*ethpb.ProposerSlashing{
|
||||
{
|
||||
ProposerIndex: proposerSlashIdx,
|
||||
Header_1: header1,
|
||||
Header_2: header2,
|
||||
Header_1: header1,
|
||||
Header_2: header2,
|
||||
},
|
||||
}
|
||||
validators := beaconState.Validators()
|
||||
validators[proposerSlashIdx].PublicKey = privKeys[proposerSlashIdx].PublicKey().Marshal()[:]
|
||||
beaconState.SetValidators(validators)
|
||||
if err := beaconState.SetValidators(validators); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
mockRoot2 := [32]byte{'A'}
|
||||
att1 := ðpb.IndexedAttestation{
|
||||
@@ -369,16 +432,16 @@ func TestProcessBlock_PassesProcessingConditions(t *testing.T) {
|
||||
Target: ðpb.Checkpoint{Epoch: 0}},
|
||||
AttestingIndices: []uint64{0, 1},
|
||||
}
|
||||
hashTreeRoot, err := ssz.HashTreeRoot(att1.Data)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
domain, err = helpers.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainBeaconAttester)
|
||||
domain, err = helpers.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorRoot())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
sig0 := privKeys[0].Sign(hashTreeRoot[:], domain)
|
||||
sig1 := privKeys[1].Sign(hashTreeRoot[:], domain)
|
||||
hashTreeRoot, err := helpers.ComputeSigningRoot(att1.Data, domain)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
sig0 := privKeys[0].Sign(hashTreeRoot[:])
|
||||
sig1 := privKeys[1].Sign(hashTreeRoot[:])
|
||||
aggregateSig := bls.AggregateSignatures([]*bls.Signature{sig0, sig1})
|
||||
att1.Signature = aggregateSig.Marshal()[:]
|
||||
|
||||
@@ -389,12 +452,13 @@ func TestProcessBlock_PassesProcessingConditions(t *testing.T) {
|
||||
Target: ðpb.Checkpoint{Epoch: 0}},
|
||||
AttestingIndices: []uint64{0, 1},
|
||||
}
|
||||
hashTreeRoot, err = ssz.HashTreeRoot(att2.Data)
|
||||
|
||||
hashTreeRoot, err = helpers.ComputeSigningRoot(att2.Data, domain)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
sig0 = privKeys[0].Sign(hashTreeRoot[:], domain)
|
||||
sig1 = privKeys[1].Sign(hashTreeRoot[:], domain)
|
||||
sig0 = privKeys[0].Sign(hashTreeRoot[:])
|
||||
sig1 = privKeys[1].Sign(hashTreeRoot[:])
|
||||
aggregateSig = bls.AggregateSignatures([]*bls.Signature{sig0, sig1})
|
||||
att2.Signature = aggregateSig.Marshal()[:]
|
||||
|
||||
@@ -409,7 +473,9 @@ func TestProcessBlock_PassesProcessingConditions(t *testing.T) {
|
||||
for i := uint64(0); i < params.BeaconConfig().SlotsPerHistoricalRoot; i++ {
|
||||
blockRoots = append(blockRoots, []byte{byte(i)})
|
||||
}
|
||||
beaconState.SetBlockRoots(blockRoots)
|
||||
if err := beaconState.SetBlockRoots(blockRoots); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
aggBits := bitfield.NewBitlist(1)
|
||||
aggBits.SetBitAt(0, true)
|
||||
@@ -428,17 +494,17 @@ func TestProcessBlock_PassesProcessingConditions(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
attestingIndices, err := attestationutil.AttestingIndices(blockAtt.AggregationBits, committee)
|
||||
attestingIndices := attestationutil.AttestingIndices(blockAtt.AggregationBits, committee)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
hashTreeRoot, err = ssz.HashTreeRoot(blockAtt.Data)
|
||||
hashTreeRoot, err = helpers.ComputeSigningRoot(blockAtt.Data, domain)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
sigs := make([]*bls.Signature, len(attestingIndices))
|
||||
for i, indice := range attestingIndices {
|
||||
sig := privKeys[indice].Sign(hashTreeRoot[:], domain)
|
||||
sig := privKeys[indice].Sign(hashTreeRoot[:])
|
||||
sigs[i] = sig
|
||||
}
|
||||
blockAtt.Signature = bls.AggregateSignatures(sigs).Marshal()[:]
|
||||
@@ -449,17 +515,17 @@ func TestProcessBlock_PassesProcessingConditions(t *testing.T) {
|
||||
Epoch: 0,
|
||||
},
|
||||
}
|
||||
signingRoot, err = ssz.HashTreeRoot(exit.Exit)
|
||||
if err != nil {
|
||||
t.Errorf("Could not get signing root of beacon block header: %v", err)
|
||||
}
|
||||
domain, err = helpers.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainVoluntaryExit)
|
||||
domain, err = helpers.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainVoluntaryExit, beaconState.GenesisValidatorRoot())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
exit.Signature = privKeys[exit.Exit.ValidatorIndex].Sign(signingRoot[:], domain).Marshal()[:]
|
||||
signingRoot, err := helpers.ComputeSigningRoot(exit.Exit, domain)
|
||||
if err != nil {
|
||||
t.Errorf("Could not get signing root of beacon block header: %v", err)
|
||||
}
|
||||
exit.Signature = privKeys[exit.Exit.ValidatorIndex].Sign(signingRoot[:]).Marshal()[:]
|
||||
|
||||
parentRoot, err := ssz.HashTreeRoot(beaconState.LatestBlockHeader())
|
||||
parentRoot, err := stateutil.BlockHeaderRoot(beaconState.LatestBlockHeader())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -470,8 +536,9 @@ func TestProcessBlock_PassesProcessingConditions(t *testing.T) {
|
||||
}
|
||||
block := ðpb.SignedBeaconBlock{
|
||||
Block: ðpb.BeaconBlock{
|
||||
ParentRoot: parentRoot[:],
|
||||
Slot: beaconState.Slot(),
|
||||
ParentRoot: parentRoot[:],
|
||||
Slot: beaconState.Slot(),
|
||||
ProposerIndex: 17,
|
||||
Body: ðpb.BeaconBlockBody{
|
||||
RandaoReveal: randaoReveal,
|
||||
ProposerSlashings: proposerSlashings,
|
||||
@@ -497,15 +564,25 @@ func TestProcessBlock_PassesProcessingConditions(t *testing.T) {
|
||||
t.Fatalf("Expected block to pass processing conditions: %v", err)
|
||||
}
|
||||
|
||||
if v, _ := beaconState.ValidatorAtIndex(proposerSlashings[0].ProposerIndex); !v.Slashed {
|
||||
t.Errorf("Expected validator at index %d to be slashed, received false", proposerSlashings[0].ProposerIndex)
|
||||
v, err := beaconState.ValidatorAtIndex(proposerSlashings[0].Header_1.Header.ProposerIndex)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if v, _ := beaconState.ValidatorAtIndex(1); !v.Slashed {
|
||||
if !v.Slashed {
|
||||
t.Errorf("Expected validator at index %d to be slashed, received false", proposerSlashings[0].Header_1.Header.ProposerIndex)
|
||||
}
|
||||
v, err = beaconState.ValidatorAtIndex(1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !v.Slashed {
|
||||
t.Error("Expected validator at index 1 to be slashed, received false")
|
||||
}
|
||||
|
||||
v, _ := beaconState.ValidatorAtIndex(exit.Exit.ValidatorIndex)
|
||||
v, err = beaconState.ValidatorAtIndex(exit.Exit.ValidatorIndex)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
received := v.ExitEpoch
|
||||
wanted := params.BeaconConfig().FarFutureEpoch
|
||||
if received == wanted {
|
||||
@@ -527,6 +604,7 @@ func TestProcessEpochPrecompute_CanProcess(t *testing.T) {
|
||||
FinalizedCheckpoint: ðpb.Checkpoint{},
|
||||
JustificationBits: bitfield.Bitvector4{0x00},
|
||||
CurrentJustifiedCheckpoint: ðpb.Checkpoint{},
|
||||
Validators: []*ethpb.Validator{},
|
||||
}
|
||||
s, err := beaconstate.InitializeFromProto(base)
|
||||
if err != nil {
|
||||
@@ -590,16 +668,17 @@ func BenchmarkProcessBlk_65536Validators_FullBlock(b *testing.B) {
|
||||
// Set up proposer slashing object for block
|
||||
proposerSlashings := []*ethpb.ProposerSlashing{
|
||||
{
|
||||
ProposerIndex: 1,
|
||||
Header_1: ðpb.SignedBeaconBlockHeader{
|
||||
Header: ðpb.BeaconBlockHeader{
|
||||
Slot: 0,
|
||||
ProposerIndex: 1,
|
||||
Slot: 0,
|
||||
},
|
||||
Signature: []byte("A"),
|
||||
},
|
||||
Header_2: ðpb.SignedBeaconBlockHeader{
|
||||
Header: ðpb.BeaconBlockHeader{
|
||||
Slot: 0,
|
||||
ProposerIndex: 1,
|
||||
Slot: 0,
|
||||
},
|
||||
Signature: []byte("B"),
|
||||
},
|
||||
@@ -652,11 +731,19 @@ func BenchmarkProcessBlk_65536Validators_FullBlock(b *testing.B) {
|
||||
v[proposerIdx].PublicKey = priv.PublicKey().Marshal()
|
||||
buf := make([]byte, 32)
|
||||
binary.LittleEndian.PutUint64(buf, 0)
|
||||
domain, err := helpers.Domain(s.Fork(), 0, params.BeaconConfig().DomainRandao)
|
||||
domain, err := helpers.Domain(s.Fork(), 0, params.BeaconConfig().DomainRandao, s.GenesisValidatorRoot())
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
epochSignature := priv.Sign(buf, domain)
|
||||
ctr := &pb.SigningRoot{
|
||||
ObjectRoot: buf,
|
||||
Domain: domain,
|
||||
}
|
||||
root, err = ssz.HashTreeRoot(ctr)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
epochSignature := priv.Sign(root[:])
|
||||
|
||||
buf = []byte{params.BeaconConfig().BLSWithdrawalPrefixByte}
|
||||
pubKey := []byte("A")
|
||||
@@ -664,7 +751,9 @@ func BenchmarkProcessBlk_65536Validators_FullBlock(b *testing.B) {
|
||||
buf = append(buf, hashed[:]...)
|
||||
v[3].WithdrawalCredentials = buf
|
||||
|
||||
s.SetValidators(v)
|
||||
if err := s.SetValidators(v); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
attestations := make([]*ethpb.Attestation, 128)
|
||||
for i := 0; i < len(attestations); i++ {
|
||||
@@ -709,10 +798,14 @@ func BenchmarkProcessBlk_65536Validators_FullBlock(b *testing.B) {
|
||||
v := s.Validators()
|
||||
v[1].Slashed = false
|
||||
v[2].Slashed = false
|
||||
s.SetValidators(v)
|
||||
b := s.Balances()
|
||||
b[3] += 2 * params.BeaconConfig().MinDepositAmount
|
||||
s.SetBalances(b)
|
||||
if err := s.SetValidators(v); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
balances := s.Balances()
|
||||
balances[3] += 2 * params.BeaconConfig().MinDepositAmount
|
||||
if err := s.SetBalances(balances); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -722,7 +815,9 @@ func TestProcessBlk_AttsBasedOnValidatorCount(t *testing.T) {
|
||||
// Default at 256 validators, can raise this number with faster BLS.
|
||||
validatorCount := uint64(256)
|
||||
s, privKeys := testutil.DeterministicGenesisState(t, validatorCount)
|
||||
s.SetSlot(params.BeaconConfig().SlotsPerEpoch)
|
||||
if err := s.SetSlot(params.BeaconConfig().SlotsPerEpoch); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
bitCount := validatorCount / params.BeaconConfig().SlotsPerEpoch
|
||||
aggBits := bitfield.NewBitlist(bitCount)
|
||||
@@ -743,33 +838,40 @@ func TestProcessBlk_AttsBasedOnValidatorCount(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
attestingIndices, err := attestationutil.AttestingIndices(att.AggregationBits, committee)
|
||||
attestingIndices := attestationutil.AttestingIndices(att.AggregationBits, committee)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
domain, err := helpers.Domain(s.Fork(), 0, params.BeaconConfig().DomainBeaconAttester)
|
||||
domain, err := helpers.Domain(s.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, s.GenesisValidatorRoot())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
sigs := make([]*bls.Signature, len(attestingIndices))
|
||||
for i, indice := range attestingIndices {
|
||||
hashTreeRoot, err := ssz.HashTreeRoot(att.Data)
|
||||
hashTreeRoot, err := helpers.ComputeSigningRoot(att.Data, domain)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
sig := privKeys[indice].Sign(hashTreeRoot[:], domain)
|
||||
sig := privKeys[indice].Sign(hashTreeRoot[:])
|
||||
sigs[i] = sig
|
||||
}
|
||||
att.Signature = bls.AggregateSignatures(sigs).Marshal()[:]
|
||||
atts[i] = att
|
||||
}
|
||||
|
||||
epochSignature, _ := testutil.RandaoReveal(s, helpers.CurrentEpoch(s), privKeys)
|
||||
parentRoot, _ := ssz.HashTreeRoot(s.LatestBlockHeader())
|
||||
epochSignature, err := testutil.RandaoReveal(s, helpers.CurrentEpoch(s), privKeys)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
parentRoot, err := stateutil.BlockHeaderRoot(s.LatestBlockHeader())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
blk := ðpb.SignedBeaconBlock{
|
||||
Block: ðpb.BeaconBlock{
|
||||
Slot: s.Slot(),
|
||||
ParentRoot: parentRoot[:],
|
||||
ProposerIndex: 72,
|
||||
Slot: s.Slot(),
|
||||
ParentRoot: parentRoot[:],
|
||||
Body: ðpb.BeaconBlockBody{
|
||||
Eth1Data: ðpb.Eth1Data{},
|
||||
RandaoReveal: epochSignature,
|
||||
@@ -847,7 +949,7 @@ func TestProcessOperations_OverMaxProposerSlashings(t *testing.T) {
|
||||
context.Background(),
|
||||
&beaconstate.BeaconState{},
|
||||
block.Body,
|
||||
); !strings.Contains(err.Error(), want) {
|
||||
); err == nil || !strings.Contains(err.Error(), want) {
|
||||
t.Errorf("Expected %s, received %v", want, err)
|
||||
}
|
||||
}
|
||||
@@ -866,7 +968,7 @@ func TestProcessOperations_OverMaxAttesterSlashings(t *testing.T) {
|
||||
context.Background(),
|
||||
&beaconstate.BeaconState{},
|
||||
block.Body,
|
||||
); !strings.Contains(err.Error(), want) {
|
||||
); err == nil || !strings.Contains(err.Error(), want) {
|
||||
t.Errorf("Expected %s, received %v", want, err)
|
||||
}
|
||||
}
|
||||
@@ -884,7 +986,7 @@ func TestProcessOperations_OverMaxAttestations(t *testing.T) {
|
||||
context.Background(),
|
||||
&beaconstate.BeaconState{},
|
||||
block.Body,
|
||||
); !strings.Contains(err.Error(), want) {
|
||||
); err == nil || !strings.Contains(err.Error(), want) {
|
||||
t.Errorf("Expected %s, received %v", want, err)
|
||||
}
|
||||
}
|
||||
@@ -903,7 +1005,7 @@ func TestProcessOperation_OverMaxVoluntaryExits(t *testing.T) {
|
||||
context.Background(),
|
||||
&beaconstate.BeaconState{},
|
||||
block.Body,
|
||||
); !strings.Contains(err.Error(), want) {
|
||||
); err == nil || !strings.Contains(err.Error(), want) {
|
||||
t.Errorf("Expected %s, received %v", want, err)
|
||||
}
|
||||
}
|
||||
@@ -929,7 +1031,7 @@ func TestProcessOperations_IncorrectDeposits(t *testing.T) {
|
||||
context.Background(),
|
||||
s,
|
||||
block.Body,
|
||||
); !strings.Contains(err.Error(), want) {
|
||||
); err == nil || !strings.Contains(err.Error(), want) {
|
||||
t.Errorf("Expected %s, received %v", want, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,20 +166,19 @@ func SlashValidator(state *stateTrie.BeaconState, slashedIdx uint64, whistleBlow
|
||||
return state, nil
|
||||
}
|
||||
|
||||
// ActivatedValidatorIndices determines the indices activated during the current epoch.
|
||||
// ActivatedValidatorIndices determines the indices activated during the given epoch.
|
||||
func ActivatedValidatorIndices(epoch uint64, validators []*ethpb.Validator) []uint64 {
|
||||
activations := make([]uint64, 0)
|
||||
delayedActivationEpoch := helpers.ActivationExitEpoch(epoch)
|
||||
for i := 0; i < len(validators); i++ {
|
||||
val := validators[i]
|
||||
if val.ActivationEpoch == delayedActivationEpoch {
|
||||
if val.ActivationEpoch <= epoch && epoch < val.ExitEpoch {
|
||||
activations = append(activations, uint64(i))
|
||||
}
|
||||
}
|
||||
return activations
|
||||
}
|
||||
|
||||
// SlashedValidatorIndices determines the indices slashed during the current epoch.
|
||||
// SlashedValidatorIndices determines the indices slashed during the given epoch.
|
||||
func SlashedValidatorIndices(epoch uint64, validators []*ethpb.Validator) []uint64 {
|
||||
slashed := make([]uint64, 0)
|
||||
for i := 0; i < len(validators); i++ {
|
||||
@@ -225,9 +224,51 @@ func ExitedValidatorIndices(epoch uint64, validators []*ethpb.Validator, activeV
|
||||
}
|
||||
withdrawableEpoch := exitQueueEpoch + params.BeaconConfig().MinValidatorWithdrawabilityDelay
|
||||
for i, val := range validators {
|
||||
if val.ExitEpoch == epoch && val.WithdrawableEpoch == withdrawableEpoch {
|
||||
if val.ExitEpoch == epoch && val.WithdrawableEpoch == withdrawableEpoch &&
|
||||
val.EffectiveBalance > params.BeaconConfig().EjectionBalance {
|
||||
exited = append(exited, uint64(i))
|
||||
}
|
||||
}
|
||||
return exited, nil
|
||||
}
|
||||
|
||||
// EjectedValidatorIndices determines the indices ejected during the given epoch.
|
||||
func EjectedValidatorIndices(epoch uint64, validators []*ethpb.Validator, activeValidatorCount uint64) ([]uint64, error) {
|
||||
ejected := make([]uint64, 0)
|
||||
exitEpochs := make([]uint64, 0)
|
||||
for i := 0; i < len(validators); i++ {
|
||||
val := validators[i]
|
||||
if val.ExitEpoch != params.BeaconConfig().FarFutureEpoch {
|
||||
exitEpochs = append(exitEpochs, val.ExitEpoch)
|
||||
}
|
||||
}
|
||||
exitQueueEpoch := uint64(0)
|
||||
for _, i := range exitEpochs {
|
||||
if exitQueueEpoch < i {
|
||||
exitQueueEpoch = i
|
||||
}
|
||||
}
|
||||
|
||||
// We use the exit queue churn to determine if we have passed a churn limit.
|
||||
exitQueueChurn := 0
|
||||
for _, val := range validators {
|
||||
if val.ExitEpoch == exitQueueEpoch {
|
||||
exitQueueChurn++
|
||||
}
|
||||
}
|
||||
churn, err := helpers.ValidatorChurnLimit(activeValidatorCount)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get churn limit")
|
||||
}
|
||||
if churn < uint64(exitQueueChurn) {
|
||||
exitQueueEpoch++
|
||||
}
|
||||
withdrawableEpoch := exitQueueEpoch + params.BeaconConfig().MinValidatorWithdrawabilityDelay
|
||||
for i, val := range validators {
|
||||
if val.ExitEpoch == epoch && val.WithdrawableEpoch == withdrawableEpoch &&
|
||||
val.EffectiveBalance <= params.BeaconConfig().EjectionBalance {
|
||||
ejected = append(ejected, uint64(i))
|
||||
}
|
||||
}
|
||||
return ejected, nil
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user