mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-10 13:58:09 -05:00
Compare commits
244 Commits
v1.0.0-bet
...
v1.0.5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2428880058 | ||
|
|
4d1f01aacc | ||
|
|
b9848dc94f | ||
|
|
579335f81a | ||
|
|
11bbf06d03 | ||
|
|
29804fa572 | ||
|
|
4ec396c025 | ||
|
|
1fbfd52e52 | ||
|
|
2e18df642d | ||
|
|
99b3835f19 | ||
|
|
46d99fdc00 | ||
|
|
923e4d3a5e | ||
|
|
bb9e2ba12c | ||
|
|
f44b2a35e4 | ||
|
|
00dacbd00d | ||
|
|
92736d0188 | ||
|
|
c96db1a122 | ||
|
|
c5770a2e56 | ||
|
|
ade3b2f2df | ||
|
|
9d7052796b | ||
|
|
fbbdd94fea | ||
|
|
b51aec6981 | ||
|
|
b4437e6cec | ||
|
|
8ad328d9b3 | ||
|
|
21ede7634e | ||
|
|
57b74283d3 | ||
|
|
be078d6a16 | ||
|
|
ccba8cfa5a | ||
|
|
afbfaedea4 | ||
|
|
3ce96701de | ||
|
|
d2ba45aad9 | ||
|
|
14e1f08208 | ||
|
|
647b4cf108 | ||
|
|
c090c6a1c5 | ||
|
|
7dd0c24fea | ||
|
|
e1755b6066 | ||
|
|
3092f75ec2 | ||
|
|
821620c520 | ||
|
|
5417e8cf31 | ||
|
|
323769bf1a | ||
|
|
c51754fa8a | ||
|
|
2153a2d7c3 | ||
|
|
20514cd97f | ||
|
|
32f6bfd0a5 | ||
|
|
c7f7a29d7e | ||
|
|
387f7b28c1 | ||
|
|
cf3181e2de | ||
|
|
9d2fe80140 | ||
|
|
f9c696ed54 | ||
|
|
3bd5e58a5c | ||
|
|
fc7c6776f6 | ||
|
|
9a1423d62d | ||
|
|
a13de7da11 | ||
|
|
01bf97293f | ||
|
|
645931802f | ||
|
|
ea10784a4a | ||
|
|
3af7809964 | ||
|
|
b150acffca | ||
|
|
54a42ce4a8 | ||
|
|
9d174d5927 | ||
|
|
1b1b36497f | ||
|
|
04615cb97b | ||
|
|
b243665d3e | ||
|
|
654ef1afe5 | ||
|
|
0dbf5c4e63 | ||
|
|
c456dcdce8 | ||
|
|
10857223d0 | ||
|
|
4ef8a0f99e | ||
|
|
af0977b8d0 | ||
|
|
528272fc66 | ||
|
|
c5c868d0a6 | ||
|
|
622ab94465 | ||
|
|
ae8a619775 | ||
|
|
36b1eb66d5 | ||
|
|
639dcb028c | ||
|
|
edb40ddea4 | ||
|
|
0d2e3d978c | ||
|
|
29c6a0c42c | ||
|
|
aefa3e191a | ||
|
|
987205afc6 | ||
|
|
3ae4b793e6 | ||
|
|
600427bdb0 | ||
|
|
c7dd33431f | ||
|
|
0cf9800b75 | ||
|
|
3cc2ebc5d5 | ||
|
|
2cb814648a | ||
|
|
dc897a2007 | ||
|
|
a051e684ae | ||
|
|
64be627a6d | ||
|
|
6f766ed583 | ||
|
|
b0dfc46603 | ||
|
|
8c3faaa4c7 | ||
|
|
4c0db8bca4 | ||
|
|
0c5c246ee7 | ||
|
|
f871e1f3ef | ||
|
|
658dd95313 | ||
|
|
57fe012bc2 | ||
|
|
d62420b940 | ||
|
|
11bbea2562 | ||
|
|
2172cd60a6 | ||
|
|
2a546cc50b | ||
|
|
7d0031ee77 | ||
|
|
acf49fb38f | ||
|
|
26658a9f1f | ||
|
|
60d99c83eb | ||
|
|
98557e8f5e | ||
|
|
1ba747b3c9 | ||
|
|
71ec919306 | ||
|
|
34a26740ff | ||
|
|
7e76b02bb7 | ||
|
|
519b003fc3 | ||
|
|
9a10462c64 | ||
|
|
ac60ff2bc2 | ||
|
|
f8a855d168 | ||
|
|
74c7733abf | ||
|
|
f63e89813d | ||
|
|
c021e2e8bc | ||
|
|
c3fc40907d | ||
|
|
3fb78ff575 | ||
|
|
7bd97546f0 | ||
|
|
5140ceec68 | ||
|
|
97ad5cd5fd | ||
|
|
4dc65c5787 | ||
|
|
1b012ccfa5 | ||
|
|
60cdd69b05 | ||
|
|
90a66df529 | ||
|
|
c4a1fe4d0d | ||
|
|
8a256de2dd | ||
|
|
c3451a6ce9 | ||
|
|
4b6441f626 | ||
|
|
eb7ab16f92 | ||
|
|
e6ecda5ebe | ||
|
|
095c4d5dd5 | ||
|
|
59d63087b1 | ||
|
|
e1dd532af3 | ||
|
|
cfed4fa1b5 | ||
|
|
7735a083b2 | ||
|
|
fec469291e | ||
|
|
acb47f2920 | ||
|
|
925fba0570 | ||
|
|
1a72733c53 | ||
|
|
2976bf7723 | ||
|
|
7c54cfea3f | ||
|
|
d3f8599d19 | ||
|
|
2034c662af | ||
|
|
ad5151f25d | ||
|
|
f75a8efc0d | ||
|
|
39817c0586 | ||
|
|
168cffb0dd | ||
|
|
194ee7c439 | ||
|
|
5889670cc7 | ||
|
|
7449eba612 | ||
|
|
d85cf028ef | ||
|
|
71c6164c42 | ||
|
|
83601245f2 | ||
|
|
758ec96d6d | ||
|
|
977e539fe9 | ||
|
|
f361450e8d | ||
|
|
0c9389a438 | ||
|
|
f200a16418 | ||
|
|
28ad21c410 | ||
|
|
da835afbaf | ||
|
|
16bccf05cf | ||
|
|
8dcdfea2a8 | ||
|
|
244d9633af | ||
|
|
d281ef9c56 | ||
|
|
58fcb52220 | ||
|
|
8d50fa10e6 | ||
|
|
21d4c8f3f8 | ||
|
|
5fdb916b4f | ||
|
|
18be4a4e3e | ||
|
|
e9136e9679 | ||
|
|
5f9239595b | ||
|
|
47daedaf11 | ||
|
|
52d850f355 | ||
|
|
d1b9f12a1e | ||
|
|
56fd535dd5 | ||
|
|
79d19ea438 | ||
|
|
ec2e677668 | ||
|
|
8e3c6e45ef | ||
|
|
a21a2c9e95 | ||
|
|
25118fb8dc | ||
|
|
06902c667d | ||
|
|
d3ca9985eb | ||
|
|
bd506bf4e8 | ||
|
|
1a05fcae3c | ||
|
|
3c5bf9bf72 | ||
|
|
24457e1aae | ||
|
|
660ed2d9a8 | ||
|
|
4290ba416c | ||
|
|
9e9a172248 | ||
|
|
2f11e55869 | ||
|
|
7f7d18e910 | ||
|
|
e22dd3758d | ||
|
|
8638e2c0b5 | ||
|
|
0fb465ba07 | ||
|
|
09e3f0360e | ||
|
|
7b0ee3adfe | ||
|
|
f57bab78aa | ||
|
|
ce75b2f684 | ||
|
|
742808c6cf | ||
|
|
b4bce7c726 | ||
|
|
9e9a913069 | ||
|
|
93c11e0e53 | ||
|
|
1b9911ccc3 | ||
|
|
be40e1a3b9 | ||
|
|
d4c954648c | ||
|
|
15706a36cb | ||
|
|
5995d2394c | ||
|
|
1c5d533c93 | ||
|
|
8cac198692 | ||
|
|
4dcae8707a | ||
|
|
b8644bdeb4 | ||
|
|
d733f2781a | ||
|
|
20370e2017 | ||
|
|
51796d77f6 | ||
|
|
135ec5f247 | ||
|
|
d4b23e6821 | ||
|
|
6e21b7a623 | ||
|
|
f6cbfd5e27 | ||
|
|
bafc7479b0 | ||
|
|
edf7ed614e | ||
|
|
882d30c382 | ||
|
|
d2694ee198 | ||
|
|
c5a8363998 | ||
|
|
7acd73e1fe | ||
|
|
3485f3b8b0 | ||
|
|
3a06f6e228 | ||
|
|
8661eb356f | ||
|
|
090b71bec5 | ||
|
|
f1e6aba34e | ||
|
|
b996824446 | ||
|
|
0b0d77dd0c | ||
|
|
1a03dad6bc | ||
|
|
5d93ee1843 | ||
|
|
2da1ec8052 | ||
|
|
c949913822 | ||
|
|
cd00b6f594 | ||
|
|
d22f48f84d | ||
|
|
19ac6782c9 | ||
|
|
0b5db9d4a1 | ||
|
|
40368bedd3 | ||
|
|
51b39420dc | ||
|
|
d2ae1b9286 |
@@ -1 +1 @@
|
||||
3.2.0
|
||||
3.7.0
|
||||
|
||||
@@ -10,3 +10,7 @@ enabled = true
|
||||
[[analyzers]]
|
||||
name = "test-coverage"
|
||||
enabled = true
|
||||
|
||||
[[analyzers]]
|
||||
name = "shell"
|
||||
enabled = true
|
||||
|
||||
6
.github/PULL_REQUEST_TEMPLATE.md
vendored
6
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,8 +1,8 @@
|
||||
<!-- Thanks for sending a PR! Before submitting:
|
||||
|
||||
1. If this is your first PR, please read CONTRIBUTING.md and sign the CLA
|
||||
first. We cannot review code without a signed CLA.
|
||||
2. Please file an issue *first*. All features and most bug fixes should have
|
||||
1. If this is your first PR, check out our contribution guide here https://docs.prylabs.network/docs/contribute/contribution-guidelines
|
||||
You will then need to sign our Contributor License Agreement (CLA), which will show up as a comment from a bot in this pull request after you open it. We cannot review code without a signed CLA.
|
||||
2. Please file an associated tracking issue if this pull request is non-trivial and requires context for our team to understand. All features and most bug fixes should have
|
||||
an associated issue with a design discussed and decided upon. Small bug
|
||||
fixes and documentation improvements don't need issues.
|
||||
3. New features and bug fixes must have tests. Documentation may need to
|
||||
|
||||
218
.well-known/security.pub
Normal file
218
.well-known/security.pub
Normal file
@@ -0,0 +1,218 @@
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
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
|
||||
=a30p
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
@@ -3,24 +3,23 @@ Hash: SHA512
|
||||
|
||||
Contact: mailto:security@prysmaticlabs.com
|
||||
Encryption: openpgp4fpr:0AE0051D647BA3C1A917AF4072E33E4DF1A5036E
|
||||
Encryption: openpgp4fpr:341396BAFACC28C5082327F889725027FC8EC0D4
|
||||
Encryption: openpgp4fpr:FEE44615A19049DF0CA0C2735E2B7E5734DFADCB
|
||||
Encryption: openpgp4fpr:CD08DE68C60B82D3EE2A3F7D95452A701810FEDB
|
||||
Encryption: openpgp4fpr:317D6E91058F8F3C2303BA7756313E44581297A6
|
||||
Preferred-Languages: en
|
||||
Canonical: https://github.com/prysmaticlabs/prysm/tree/master/.well-known/security.txt
|
||||
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQIzBAEBCgAdFiEECuAFHWR7o8GpF69AcuM+TfGlA24FAl6HrcwACgkQcuM+TfGl
|
||||
A26voQ/8DFB5wUHP0uyY8k7FGbxhLzSeImxomnUHJaUGfdczbCdYPMEHc9zI1iZP
|
||||
6LRiy9wS6qhqj/GSKVwvDPr+ZymXuV3L22GOP2lRhl7Z9Mm21ZJNOcoQBFOZnyHu
|
||||
DAy9HeTmeuJxYkf8weqZYXyzEoKJBDmfuWmEFjrtMcFXUfT3aJn1E2A/AQdcVQIC
|
||||
9L+iGWwFwjsPhcfaMuwcB7QMheDO6KSB7XPPCbrZ036Np8UTZ4qbZ5y73tlfkcOc
|
||||
tYTrMSPtS4eNutiDOP5Np36cLzRtNpm/BziAK+7ZKiYY0HI5h9IkCTLO4x2UmAMX
|
||||
sPoeaAB5z2QLIwmU9J2NhJrwiNMGTpJ+0bowy8U4cgzAX20CXVjRqGhy+cir8Ewg
|
||||
DjEGjWINUw6W0yzJp0mKSKzuOhdTTmzIYBeMBsyce+pgN1KGFCxeIwxGxyJzADdw
|
||||
mYQdljRXn4yEYP/KEpu/F2o8L4ptRO2jZWKvTvdzSSGGSyKyF4HsIRJ7m98DaB6S
|
||||
0oGq1KpbKKTbQi5g8UShGV2gPeMCs5ZIIqK2b/cRzUet18aUuofLmR4lkKZa9yEG
|
||||
rbzuJq/gB2vgQwExUEgVQ3/DfVc+y80e3YZ5s+rzV0vbLxl4Gh4yExpLo7hRf9iY
|
||||
EFvMzH+BEEb5VfCwByZyV1BmesZVIosr7K6UmVtPe0bZGvv3uIg=
|
||||
=5qpD
|
||||
iQIzBAEBCgAdFiEECuAFHWR7o8GpF69AcuM+TfGlA24FAl++klgACgkQcuM+TfGl
|
||||
A27rQw/6A29p1W20J0v+h218p8XWLSUpTIGLnZTxw6KqdyVXMzlsQK0YG4G2s2AB
|
||||
0LKh7Ae/Di5E0U+Z4AjUW5nc5eaCxK36GMscH9Ah0rgJwNYxEJw7/2o8ZqVT/Ip2
|
||||
+56rFihRqxFZfaCNKFVuZFaL9jKewV9FKYP38ID6/SnTcrOHiu2AoAlyZGmB03p+
|
||||
iT57SPRHatygeY4xb/gwcfREFWEv+VHGyBTv8A+6ABZDxyurboCFMERHzFICrbmk
|
||||
8UdHxxlWZDnHAbAUyAwpERC5znx6IHXQJwF8TMtu6XY6a6axT2XBOyJDF9/mZOz+
|
||||
kdkz6loX5uxaQBGLtTv6Kqf1yUGANOZ16VhHvWwL209LmHmigIVQ+qSM6c79PsW/
|
||||
vrsqdz3GBsiMC5Fq2vYgnbgzpfE8Atjn0y7E+j4R7IvwOAE/Ro/b++nqnc4YqhME
|
||||
P/yTcfGftaCrdSNnQCXeoV9JxpFM5Xy8KV3eexvNKbcgA/9DtgxL5i+s5ZJkUT9A
|
||||
+qJvoRrRyIym32ghkHgtFJKB3PLCdobeoOVRk6EnMo9zKSiSK2rZEJW8Ccbo515D
|
||||
W9qUOn3GF7lNVuUFAU/YKEdmDp/AVaViZ7vH+8aq0LC0HBkZ8XlzWnWoArS8sMhw
|
||||
fX0R9g/HMgrwNte/d0mwim5lJ2Plgv60Bh4grJqwZJeWbU0zi1U=
|
||||
=uW+X
|
||||
-----END PGP SIGNATURE-----
|
||||
|
||||
@@ -112,6 +112,7 @@ nogo(
|
||||
"//tools/analyzers/nop:go_tool_library",
|
||||
"//tools/analyzers/slicedirect:go_tool_library",
|
||||
"//tools/analyzers/ineffassign:go_tool_library",
|
||||
"//tools/analyzers/properpermissions:go_tool_library",
|
||||
] + select({
|
||||
# nogo checks that fail with coverage enabled.
|
||||
":coverage_enabled": [],
|
||||
|
||||
@@ -4,7 +4,7 @@ Note: The latest and most up to date documenation can be found on our [docs port
|
||||
|
||||
Excited by our work and want to get involved in building out our sharding releases? Or maybe you haven't learned as much about the Ethereum protocol but are a savvy developer?
|
||||
|
||||
You can explore our [Open Issues](https://github.com/prysmaticlabs/prysm/issues) in-the works for our different releases. Feel free to fork our repo and start creating PR’s after assigning yourself to an issue of interest. We are always chatting on [Discord](https://discord.gg/che9auJ) or [Gitter](https://gitter.im/prysmaticlabs/geth-sharding) drop us a line there if you want to get more involved or have any questions on our implementation!
|
||||
You can explore our [Open Issues](https://github.com/prysmaticlabs/prysm/issues) in-the works for our different releases. Feel free to fork our repo and start creating PR’s after assigning yourself to an issue of interest. We are always chatting on [Discord](https://discord.gg/CTYGPUJ) drop us a line there if you want to get more involved or have any questions on our implementation!
|
||||
|
||||
## Contribution Steps
|
||||
|
||||
@@ -62,12 +62,6 @@ Changes that only affect a single file can be tested with
|
||||
$ go test <file_you_are_working_on>
|
||||
```
|
||||
|
||||
Changes that affect multiple files can be tested with ...
|
||||
|
||||
```
|
||||
$ golangci-lint run && bazel test //...
|
||||
```
|
||||
|
||||
**10. Stage the file or files that you want to commit.**
|
||||
|
||||
```
|
||||
@@ -181,7 +175,7 @@ We consider two types of contributions to our repo and categorize them as follow
|
||||
|
||||
### Part-Time Contributors
|
||||
|
||||
Anyone can become a part-time contributor and help out on implementing sharding. The responsibilities of a part-time contributor include:
|
||||
Anyone can become a part-time contributor and help out on implementing eth2. The responsibilities of a part-time contributor include:
|
||||
|
||||
- Engaging in Gitter conversations, asking the questions on how to begin contributing to the project
|
||||
- Opening up github issues to express interest in code to implement
|
||||
@@ -192,8 +186,6 @@ Anyone can become a part-time contributor and help out on implementing sharding.
|
||||
- Follow up on open PRs
|
||||
- Have an estimated timeframe to completion and let the core contributors know if a PR will take longer than expected
|
||||
|
||||
We do not expect all part-time contributors to be experts on all the latest sharding documentation, but all contributors should at least be familiarized with our sharding [README.md](https://github.com/prysmaticlabs/prysm/blob/master/validator/README.md) and have gone through the required Ethereum readings as posted on our [READINGS.md](https://github.com/prysmaticlabs/prysm/blob/master/docs/READINGS.md) document.
|
||||
|
||||
### Core Contributors
|
||||
|
||||
Core contributors are remote contractors of Prysmatic Labs, LLC. and are considered critical team members of our organization. Core devs have all of the responsibilities of part-time contributors plus the majority of the following:
|
||||
|
||||
@@ -61,7 +61,7 @@ Example:
|
||||
|
||||
```bash
|
||||
go get github.com/prysmaticlabs/example@v1.2.3
|
||||
bazel run //:gazelle -- update-repos -from_file=go.mod -to_macro=deps.bzl%prysm_deps
|
||||
bazel run //:gazelle -- update-repos -from_file=go.mod -to_macro=deps.bzl%prysm_deps -prune=true
|
||||
```
|
||||
|
||||
The deps.bzl file should have been updated with the dependency and any transitive dependencies.
|
||||
|
||||
31
README.md
31
README.md
@@ -1,20 +1,35 @@
|
||||
# Prysm: An Ethereum 2.0 Client Written in Go
|
||||
# Prysm: An Ethereum 2.0 Implementation Written in Go
|
||||
|
||||
[](https://buildkite.com/prysmatic-labs/prysm)
|
||||
[](https://github.com/ethereum/eth2.0-specs/tree/v0.12.3)
|
||||
[](https://discord.gg/KSA7rPr)
|
||||
[](https://gitter.im/prysmaticlabs/geth-sharding?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||
[](https://goreportcard.com/report/github.com/prysmaticlabs/prysm)
|
||||
[](https://github.com/ethereum/eth2.0-specs/tree/v1.0.0)
|
||||
[](https://discord.gg/CTYGPUJ)
|
||||
|
||||
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).
|
||||
This is the core repository for Prysm, a [Golang](https://golang.org/) implementation of the Ethereum 2.0 specification, developed by [Prysmatic Labs](https://prysmaticlabs.com).
|
||||
|
||||
### 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. 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).
|
||||
A detailed set of installation and usage instructions as well as breakdowns of each individual component are available in the [official documentation portal](https://docs.prylabs.network). If you still have questions, feel free to stop by our [Discord](https://discord.gg/CTYGPUJ).
|
||||
|
||||
### Staking on Mainnet
|
||||
|
||||
To participate in staking, you can join the [official eth2 launchpad](https://launchpad.ethereum.org). The launchpad is the only recommended way to become a validator on mainnet. You can 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 [beaconscan](https://beaconscan.com).
|
||||
|
||||
|
||||
## Contributing
|
||||
### Branches
|
||||
Prysm maintains two permanent branches:
|
||||
|
||||
* master: This points to the latest stable release. It is ideal for most users.
|
||||
* develop: This is used for development, it contains the latest PRs. Developers should base their PRs on this branch.
|
||||
|
||||
### Guide
|
||||
Want to get involved? Check out our [Contribution Guide](https://docs.prylabs.network/docs/contribute/contribution-guidelines/) to learn more!
|
||||
|
||||
## License
|
||||
|
||||
[GNU General Public License v3.0](https://www.gnu.org/licenses/gpl-3.0.en.html)
|
||||
|
||||
## Legal Disclaimer
|
||||
|
||||
[Terms of Use](/TERMS_OF_SERVICE.md)
|
||||
|
||||
43
TESTNET.md
43
TESTNET.md
@@ -1,43 +0,0 @@
|
||||
# Testnet
|
||||
|
||||
The Prysmatic Labs test network is available for anyone to join. The easiest way to participate is by joining through the website, https://prylabs.net.
|
||||
|
||||
## Interop
|
||||
|
||||
For developers looking to connect a client other than Prysm to the test network, here is the relevant information for compatability.
|
||||
|
||||
|
||||
**Spec version** - [v0.8.3](https://github.com/ethereum/eth2.0-specs/tree/v0.8.3)
|
||||
|
||||
**ETH 1 Deposit Contract Address** - See https://prylabs.net/contract. This contract is deployed on the [goerli](https://goerli.net/) network.
|
||||
|
||||
**Genesis time** - The ETH1 block time in which the 64th deposit to start ETH2 was included. This is NOT midnight of the next day as required by spec.
|
||||
|
||||
### ETH 2 Configuration
|
||||
|
||||
Use the [minimal config](https://github.com/ethereum/eth2.0-specs/blob/v0.8.3/configs/minimal.yaml) with the following changes.
|
||||
|
||||
| field | value |
|
||||
|-------|-------|
|
||||
| MIN_DEPOSIT_AMOUNT | 100 |
|
||||
| MAX_EFFECTIVE_BALANCE | 3.2 * 1e9 |
|
||||
| EJECTION_BALANCE | 1.6 * 1e9 |
|
||||
| EFFECTIVE_BALANCE_INCREMENT | 0.1 * 1e9 |
|
||||
| ETH1_FOLLOW_DISTANCE | 16 |
|
||||
| GENESIS_FORK_VERSION | See [latest code](https://github.com/prysmaticlabs/prysm/blob/master/shared/params/config.go#L236) |
|
||||
|
||||
These parameters reduce the minimal config to 1/10 of the required ETH.
|
||||
|
||||
We have a genesis.ssz file available for download [here](https://prysmaticlabs.com/uploads/genesis.ssz)
|
||||
|
||||
### Connecting to the network
|
||||
|
||||
We have a libp2p bootstrap node available at `/dns4/prylabs.net/tcp/30001/p2p/16Uiu2HAm7Qwe19vz9WzD2Mxn7fXd1vgHHp4iccuyq7TxwRXoAGfc`.
|
||||
|
||||
Some of the Prysmatic Labs hosted nodes are behind a libp2p relay, so your libp2p implementation protocol should understand this functionality.
|
||||
|
||||
### Other
|
||||
|
||||
Undoubtably, you will have bugs. Reach out to us on [Discord](https://discord.gg/KSA7rPr) and be sure to capture issues on Github at https://github.com/prysmaticlabs/prysm/issues.
|
||||
|
||||
If you have instructions for you client, we would love to attempt this on your behalf. Kindly send over the instructions via github issue, PR, email to team@prysmaticlabs.com, or discord.
|
||||
69
WORKSPACE
69
WORKSPACE
@@ -5,19 +5,19 @@ load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
|
||||
|
||||
http_archive(
|
||||
name = "bazel_toolchains",
|
||||
sha256 = "db48eed61552e25d36fe051a65d2a329cc0fb08442627e8f13960c5ab087a44e",
|
||||
strip_prefix = "bazel-toolchains-3.2.0",
|
||||
sha256 = "8e0633dfb59f704594f19ae996a35650747adc621ada5e8b9fb588f808c89cb0",
|
||||
strip_prefix = "bazel-toolchains-3.7.0",
|
||||
urls = [
|
||||
"https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/releases/download/3.2.0/bazel-toolchains-3.2.0.tar.gz",
|
||||
"https://github.com/bazelbuild/bazel-toolchains/releases/download/3.2.0/bazel-toolchains-3.2.0.tar.gz",
|
||||
"https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/releases/download/3.7.0/bazel-toolchains-3.7.0.tar.gz",
|
||||
"https://github.com/bazelbuild/bazel-toolchains/releases/download/3.7.0/bazel-toolchains-3.7.0.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
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"],
|
||||
sha256 = "b924b102adc0c3368d38a19bd971cb4fa75362a27bc363d0084b90ca6877d3f0",
|
||||
strip_prefix = "bazel-toolchain-0.5.7",
|
||||
urls = ["https://github.com/grailbio/bazel-toolchain/archive/0.5.7.tar.gz"],
|
||||
)
|
||||
|
||||
load("@com_grail_bazel_toolchain//toolchain:deps.bzl", "bazel_toolchain_dependencies")
|
||||
@@ -28,7 +28,7 @@ load("@com_grail_bazel_toolchain//toolchain:rules.bzl", "llvm_toolchain")
|
||||
|
||||
llvm_toolchain(
|
||||
name = "llvm_toolchain",
|
||||
llvm_version = "9.0.0",
|
||||
llvm_version = "10.0.0",
|
||||
)
|
||||
|
||||
load("@llvm_toolchain//:toolchains.bzl", "llvm_register_toolchains")
|
||||
@@ -47,10 +47,10 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
|
||||
http_archive(
|
||||
name = "bazel_skylib",
|
||||
sha256 = "97e70364e9249702246c0e9444bccdc4b847bed1eb03c5a3ece4f83dfe6abc44",
|
||||
sha256 = "1c531376ac7e5a180e0237938a2536de0c54d93f5c278634818e0efc952dd56c",
|
||||
urls = [
|
||||
"https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.0.2/bazel-skylib-1.0.2.tar.gz",
|
||||
"https://github.com/bazelbuild/bazel-skylib/releases/download/1.0.2/bazel-skylib-1.0.2.tar.gz",
|
||||
"https://github.com/bazelbuild/bazel-skylib/releases/download/1.0.3/bazel-skylib-1.0.3.tar.gz",
|
||||
"https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.0.3/bazel-skylib-1.0.3.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -60,10 +60,10 @@ bazel_skylib_workspace()
|
||||
|
||||
http_archive(
|
||||
name = "bazel_gazelle",
|
||||
sha256 = "d8c45ee70ec39a57e7a05e5027c32b1576cc7f16d9dd37135b0eddde45cf1b10",
|
||||
sha256 = "1f4fc1d91826ec436ae04833430626f4cc02c20bb0a813c0c2f3c4c421307b1d",
|
||||
strip_prefix = "bazel-gazelle-e368a11b76e92932122d824970dc0ce5feb9c349",
|
||||
urls = [
|
||||
"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",
|
||||
"https://github.com/bazelbuild/bazel-gazelle/archive/e368a11b76e92932122d824970dc0ce5feb9c349.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -76,9 +76,9 @@ http_archive(
|
||||
|
||||
http_archive(
|
||||
name = "io_bazel_rules_docker",
|
||||
sha256 = "dc97fccceacd4c6be14e800b2a00693d5e8d07f69ee187babfd04a80a9f8e250",
|
||||
strip_prefix = "rules_docker-0.14.1",
|
||||
url = "https://github.com/bazelbuild/rules_docker/archive/v0.14.1.tar.gz",
|
||||
sha256 = "1698624e878b0607052ae6131aa216d45ebb63871ec497f26c67455b34119c80",
|
||||
strip_prefix = "rules_docker-0.15.0",
|
||||
urls = ["https://github.com/bazelbuild/rules_docker/releases/download/v0.15.0/rules_docker-v0.15.0.tar.gz"],
|
||||
)
|
||||
|
||||
http_archive(
|
||||
@@ -89,10 +89,10 @@ http_archive(
|
||||
# nogo check fails for certain third_party dependencies.
|
||||
"//third_party:io_bazel_rules_go.patch",
|
||||
],
|
||||
sha256 = "7b9bbe3ea1fccb46dcfa6c3f3e29ba7ec740d8733370e21cdc8937467b4a4349",
|
||||
sha256 = "81eff5df9077783b18e93d0c7ff990d8ad7a3b8b3ca5b785e1c483aacdb342d7",
|
||||
urls = [
|
||||
"https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.22.4/rules_go-v0.22.4.tar.gz",
|
||||
"https://github.com/bazelbuild/rules_go/releases/download/v0.22.4/rules_go-v0.22.4.tar.gz",
|
||||
"https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.24.9/rules_go-v0.24.9.tar.gz",
|
||||
"https://github.com/bazelbuild/rules_go/releases/download/v0.24.9/rules_go-v0.24.9.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -139,9 +139,9 @@ load(
|
||||
|
||||
container_pull(
|
||||
name = "alpine_cc_linux_amd64",
|
||||
digest = "sha256:3f7f4dfcb6dceac3a902f36609cc232262e49f5656a6dc4bb3da89e35fecc8a5",
|
||||
digest = "sha256:752aa0c9a88461ffc50c5267bb7497ef03a303e38b2c8f7f2ded9bebe5f1f00e",
|
||||
registry = "index.docker.io",
|
||||
repository = "fasibio/alpine-libgcc",
|
||||
repository = "pinglamb/alpine-glibc",
|
||||
)
|
||||
|
||||
container_pull(
|
||||
@@ -155,7 +155,10 @@ load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_depe
|
||||
|
||||
go_rules_dependencies()
|
||||
|
||||
go_register_toolchains(nogo = "@//:nogo")
|
||||
go_register_toolchains(
|
||||
go_version = "1.15.6",
|
||||
nogo = "@//:nogo",
|
||||
)
|
||||
|
||||
load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies")
|
||||
|
||||
@@ -219,8 +222,8 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "6b3498001de98c477aa2c256beffc20a85ce1b12b8e0f8e88502a5c3a18c01de",
|
||||
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v1.0.0-rc.0/general.tar.gz",
|
||||
sha256 = "ef5396e4b13995da9776eeb5ae346a2de90970c28da3c4f0dcaa4ab9f0ad1f93",
|
||||
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v1.0.0/general.tar.gz",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
@@ -235,8 +238,8 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "72c2f561db879ddcdf729fef93d10e0f9162b4cf3a697c513ef8935b93f6165a",
|
||||
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.12.3/minimal.tar.gz",
|
||||
sha256 = "170551b441e7d54b73248372ad9ce8cb6c148810b5f1364637117a63f4f1c085",
|
||||
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v1.0.0/minimal.tar.gz",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
@@ -251,8 +254,8 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "63eca02503692a0b6a2d7b70118e0dd62dff094153a3a542af6dbea721841b0d",
|
||||
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.12.3/mainnet.tar.gz",
|
||||
sha256 = "b541a9979b4703fa5ee5d2182b0b5313c38efc54ae7eaec2eef793230a52ec83",
|
||||
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v1.0.0/mainnet.tar.gz",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
@@ -268,9 +271,9 @@ buildifier_dependencies()
|
||||
|
||||
git_repository(
|
||||
name = "com_google_protobuf",
|
||||
commit = "4059c61f27eb1b06c4ee979546a238be792df0a4",
|
||||
commit = "fde7cf7358ec7cd69e8db9be4f1fa6a5c431386a", # v3.13.0
|
||||
remote = "https://github.com/protocolbuffers/protobuf",
|
||||
shallow_since = "1558721209 -0700",
|
||||
shallow_since = "1597443653 -0700",
|
||||
)
|
||||
|
||||
load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps")
|
||||
@@ -349,9 +352,9 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "6bb16ff0dc9348090cc31a9ea453643d32b617e66ac6e7bb38985d530070631b",
|
||||
sha256 = "117f5366af9cf009354ed1abe02f906168158473461d69c8056984b9b0292619",
|
||||
urls = [
|
||||
"https://github.com/prysmaticlabs/prysm-web-ui/releases/download/0.0.2-alpha/prysm-web-ui.tar.gz",
|
||||
"https://github.com/prysmaticlabs/prysm-web-ui/releases/download/v1.0.0-beta.2/prysm-web-ui.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_library")
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_test")
|
||||
load("@io_bazel_rules_docker//go:image.bzl", "go_image")
|
||||
load("@io_bazel_rules_docker//container:container.bzl", "container_bundle")
|
||||
load("@io_bazel_rules_docker//container:container.bzl", "container_bundle", "container_image")
|
||||
load("//tools:go_image.bzl", "go_image_alpine", "go_image_debug")
|
||||
load("@io_bazel_rules_docker//contrib:push-all.bzl", "docker_push")
|
||||
|
||||
@@ -14,6 +14,7 @@ go_library(
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain",
|
||||
visibility = ["//beacon-chain:__subpackages__"],
|
||||
deps = [
|
||||
"//beacon-chain/db:go_default_library",
|
||||
"//beacon-chain/flags:go_default_library",
|
||||
"//beacon-chain/node:go_default_library",
|
||||
"//shared/cmd:go_default_library",
|
||||
@@ -35,49 +36,29 @@ go_library(
|
||||
|
||||
go_image(
|
||||
name = "image",
|
||||
srcs = [
|
||||
"main.go",
|
||||
"usage.go",
|
||||
],
|
||||
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",
|
||||
race = "off",
|
||||
static = "off", # Static enabled binary seems to cause issues with DNS lookup with cgo.
|
||||
binary = ":beacon-chain",
|
||||
tags = ["manual"],
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
"//beacon-chain/flags:go_default_library",
|
||||
"//beacon-chain/node:go_default_library",
|
||||
"//shared/tos:go_default_library",
|
||||
"//shared/cmd:go_default_library",
|
||||
"//shared/debug:go_default_library",
|
||||
"//shared/featureconfig:go_default_library",
|
||||
"//shared/journald:go_default_library",
|
||||
"//shared/logutil:go_default_library",
|
||||
"//shared/maxprocs:go_default_library",
|
||||
"//shared/version:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//log:go_default_library",
|
||||
"@com_github_ipfs_go_log_v2//:go_default_library",
|
||||
"@com_github_joonix_log//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@com_github_urfave_cli_v2//:go_default_library",
|
||||
"@com_github_x_cray_logrus_prefixed_formatter//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
container_image(
|
||||
name = "image_with_creation_time",
|
||||
base = "image",
|
||||
stamp = True,
|
||||
)
|
||||
|
||||
container_bundle(
|
||||
name = "image_bundle",
|
||||
images = {
|
||||
"gcr.io/prysmaticlabs/prysm/beacon-chain:latest": ":image",
|
||||
"gcr.io/prysmaticlabs/prysm/beacon-chain:{DOCKER_TAG}": ":image",
|
||||
"index.docker.io/prysmaticlabs/prysm-beacon-chain:latest": ":image",
|
||||
"index.docker.io/prysmaticlabs/prysm-beacon-chain:{DOCKER_TAG}": ":image",
|
||||
"gcr.io/prysmaticlabs/prysm/beacon-chain:latest": ":image_with_creation_time",
|
||||
"gcr.io/prysmaticlabs/prysm/beacon-chain:{DOCKER_TAG}": ":image_with_creation_time",
|
||||
"index.docker.io/prysmaticlabs/prysm-beacon-chain:latest": ":image_with_creation_time",
|
||||
"index.docker.io/prysmaticlabs/prysm-beacon-chain:{DOCKER_TAG}": ":image_with_creation_time",
|
||||
},
|
||||
tags = ["manual"],
|
||||
)
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
# Prysmatic Labs Beacon Chain Implementation
|
||||
|
||||
This is the main project folder for the beacon chain implementation of Ethereum Serenity in Golang by [Prysmatic Labs](https://prysmaticlabs.com). Before you begin, check out our [Contribution Guidelines](https://github.com/prysmaticlabs/prysm/blob/master/CONTRIBUTING.md) and join our active chat room on Discord or Gitter below:
|
||||
This is the main project folder for the beacon chain implementation of eth2 written in Go by [Prysmatic Labs](https://prysmaticlabs.com).
|
||||
|
||||
[](https://discord.gg/KSA7rPr)
|
||||
[](https://gitter.im/prysmaticlabs/prysm?badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||
You can also read our main [README](https://github.com/prysmaticlabs/prysm/blob/master/README.md) and join our active chat room on Discord.
|
||||
|
||||
Also, read the latest beacon chain [design spec](https://github.com/ethereum/eth2.0-specs/blob/dev/specs/phase0/beacon-chain.md), this design spec serves as a source of truth for the beacon chain implementation we follow at prysmatic labs.
|
||||
Check out the [FAQs](https://notes.ethereum.org/9MMuzWeFTTSg-3Tz_YeiBA?view). Refer this page on [why](http://email.mg2.substack.com/c/eJwlj9GOhCAMRb9G3jRQQPGBh5mM8xsbhKrsDGIAM9m_X9xN2qZtbpt7rCm4xvSjj5gLOTOmL-809CMbKXFaOKakIl4DZYr2AGyQIGjHOnWH22OiYnoIxmDijaBhhS6fcy7GvjobA9m0mSXOcnZq5GBqLkilXBZhBsus5ZK89VbKkRt-a-BZI6DzZ7iur1lQ953KJ9bemnxgahuQU9XJu6pFPdu8meT8vragzEjpMCwMGLlgLo6h5z1JumQTu4IJd4v15xqMf_8ZLP_Y1bSLdbnrD-LL71i2Kj7DLxaWWF4)
|
||||
we are combining sharding and casper together.
|
||||
[](https://discord.gg/CTYGPUJ)
|
||||
|
||||
Also, read the official beacon chain [specification](https://github.com/ethereum/eth2.0-specs/blob/master/specs/phase0/beacon-chain.md), this design spec serves as a source of truth for the beacon chain implementation we follow at Prysmatic Labs.
|
||||
|
||||
@@ -50,6 +50,7 @@ go_library(
|
||||
"//shared/bls:go_default_library",
|
||||
"//shared/bytesutil:go_default_library",
|
||||
"//shared/featureconfig:go_default_library",
|
||||
"//shared/mputil:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"//shared/slotutil:go_default_library",
|
||||
"//shared/timeutils:go_default_library",
|
||||
@@ -76,6 +77,7 @@ go_test(
|
||||
name = "go_raceoff_test",
|
||||
size = "medium",
|
||||
srcs = [
|
||||
"blockchain_test.go",
|
||||
"chain_info_test.go",
|
||||
"head_test.go",
|
||||
"info_test.go",
|
||||
|
||||
15
beacon-chain/blockchain/blockchain_test.go
Normal file
15
beacon-chain/blockchain/blockchain_test.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package blockchain
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
logrus.SetLevel(logrus.DebugLevel)
|
||||
logrus.SetOutput(ioutil.Discard)
|
||||
|
||||
m.Run()
|
||||
}
|
||||
@@ -7,7 +7,9 @@ import (
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
@@ -60,19 +62,19 @@ func TestFinalizedCheckpt_GenesisRootOk(t *testing.T) {
|
||||
func TestCurrentJustifiedCheckpt_CanRetrieve(t *testing.T) {
|
||||
db, sc := testDB.SetupDB(t)
|
||||
|
||||
cp := ðpb.Checkpoint{Epoch: 6, Root: bytesutil.PadTo([]byte("foo"), 32)}
|
||||
c := setupBeaconChain(t, db, sc)
|
||||
assert.Equal(t, params.BeaconConfig().ZeroHash, bytesutil.ToBytes32(c.CurrentJustifiedCheckpt().Root), "Unexpected justified epoch")
|
||||
cp := ðpb.Checkpoint{Epoch: 6, Root: bytesutil.PadTo([]byte("foo"), 32)}
|
||||
c.justifiedCheckpt = cp
|
||||
|
||||
assert.Equal(t, cp.Epoch, c.CurrentJustifiedCheckpt().Epoch, "Unexpected justified epoch")
|
||||
}
|
||||
|
||||
func TestJustifiedCheckpt_GenesisRootOk(t *testing.T) {
|
||||
db, sc := testDB.SetupDB(t)
|
||||
|
||||
c := setupBeaconChain(t, db, sc)
|
||||
genesisRoot := [32]byte{'B'}
|
||||
cp := ðpb.Checkpoint{Root: genesisRoot[:]}
|
||||
c := setupBeaconChain(t, db, sc)
|
||||
c.justifiedCheckpt = cp
|
||||
c.genesisRoot = genesisRoot
|
||||
assert.DeepEqual(t, c.genesisRoot[:], c.CurrentJustifiedCheckpt().Root)
|
||||
@@ -83,6 +85,7 @@ func TestPreviousJustifiedCheckpt_CanRetrieve(t *testing.T) {
|
||||
|
||||
cp := ðpb.Checkpoint{Epoch: 7, Root: bytesutil.PadTo([]byte("foo"), 32)}
|
||||
c := setupBeaconChain(t, db, sc)
|
||||
assert.Equal(t, params.BeaconConfig().ZeroHash, bytesutil.ToBytes32(c.CurrentJustifiedCheckpt().Root), "Unexpected justified epoch")
|
||||
c.prevJustifiedCheckpt = cp
|
||||
assert.Equal(t, cp.Epoch, c.PreviousJustifiedCheckpt().Epoch, "Unexpected previous justified epoch")
|
||||
}
|
||||
@@ -114,6 +117,21 @@ func TestHeadRoot_CanRetrieve(t *testing.T) {
|
||||
assert.Equal(t, [32]byte{'A'}, bytesutil.ToBytes32(r))
|
||||
}
|
||||
|
||||
func TestHeadRoot_UseDB(t *testing.T) {
|
||||
db, _ := testDB.SetupDB(t)
|
||||
c := &Service{beaconDB: db}
|
||||
c.head = &head{root: params.BeaconConfig().ZeroHash}
|
||||
b := testutil.NewBeaconBlock()
|
||||
br, err := b.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, db.SaveBlock(context.Background(), b))
|
||||
require.NoError(t, db.SaveStateSummary(context.Background(), &pb.StateSummary{Root: br[:]}))
|
||||
require.NoError(t, db.SaveHeadBlockRoot(context.Background(), br))
|
||||
r, err := c.HeadRoot(context.Background())
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, br, bytesutil.ToBytes32(r))
|
||||
}
|
||||
|
||||
func TestHeadBlock_CanRetrieve(t *testing.T) {
|
||||
b := testutil.NewBeaconBlock()
|
||||
b.Block.Slot = 1
|
||||
@@ -154,6 +172,17 @@ func TestCurrentFork_CanRetrieve(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCurrentFork_NilHeadSTate(t *testing.T) {
|
||||
f := &pb.Fork{
|
||||
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
|
||||
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
|
||||
}
|
||||
c := &Service{}
|
||||
if !proto.Equal(c.CurrentFork(), f) {
|
||||
t.Error("Received incorrect fork version")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenesisValidatorRoot_CanRetrieve(t *testing.T) {
|
||||
// Should not panic if head state is nil.
|
||||
c := &Service{}
|
||||
@@ -201,3 +230,54 @@ func TestIsCanonical_Ok(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, false, can)
|
||||
}
|
||||
|
||||
func TestService_HeadValidatorsIndices(t *testing.T) {
|
||||
s, _ := testutil.DeterministicGenesisState(t, 10)
|
||||
c := &Service{}
|
||||
|
||||
c.head = &head{}
|
||||
indices, err := c.HeadValidatorsIndices(context.Background(), 0)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 0, len(indices))
|
||||
|
||||
c.head = &head{state: s}
|
||||
indices, err = c.HeadValidatorsIndices(context.Background(), 0)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 10, len(indices))
|
||||
}
|
||||
|
||||
func TestService_HeadSeed(t *testing.T) {
|
||||
s, _ := testutil.DeterministicGenesisState(t, 1)
|
||||
c := &Service{}
|
||||
seed, err := helpers.Seed(s, 0, params.BeaconConfig().DomainBeaconAttester)
|
||||
require.NoError(t, err)
|
||||
|
||||
c.head = &head{}
|
||||
root, err := c.HeadSeed(context.Background(), 0)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, [32]byte{}, root)
|
||||
|
||||
c.head = &head{state: s}
|
||||
root, err = c.HeadSeed(context.Background(), 0)
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, seed, root)
|
||||
}
|
||||
|
||||
func TestService_HeadGenesisValidatorRoot(t *testing.T) {
|
||||
s, _ := testutil.DeterministicGenesisState(t, 1)
|
||||
c := &Service{}
|
||||
|
||||
c.head = &head{}
|
||||
root := c.HeadGenesisValidatorRoot()
|
||||
require.Equal(t, [32]byte{}, root)
|
||||
|
||||
c.head = &head{state: s}
|
||||
root = c.HeadGenesisValidatorRoot()
|
||||
require.DeepEqual(t, root[:], s.GenesisValidatorRoot())
|
||||
}
|
||||
|
||||
func TestService_ProtoArrayStore(t *testing.T) {
|
||||
c := &Service{forkChoiceStore: protoarray.New(0, 0, [32]byte{})}
|
||||
p := c.ProtoArrayStore()
|
||||
require.Equal(t, 0, int(p.FinalizedEpoch()))
|
||||
}
|
||||
|
||||
@@ -276,7 +276,7 @@ func (s *Service) cacheJustifiedStateBalances(ctx context.Context, justifiedRoot
|
||||
epoch := helpers.CurrentEpoch(justifiedState)
|
||||
|
||||
justifiedBalances := make([]uint64, justifiedState.NumValidators())
|
||||
if err := justifiedState.ReadFromEveryValidator(func(idx int, val *stateTrie.ReadOnlyValidator) error {
|
||||
if err := justifiedState.ReadFromEveryValidator(func(idx int, val stateTrie.ReadOnlyValidator) error {
|
||||
if helpers.IsActiveValidatorUsingTrie(val, epoch) {
|
||||
justifiedBalances[idx] = val.EffectiveBalance()
|
||||
} else {
|
||||
|
||||
@@ -173,6 +173,10 @@ func reportEpochMetrics(ctx context.Context, postState, headState *stateTrie.Bea
|
||||
activeBalance += bal
|
||||
activeEffectiveBalance += validator.EffectiveBalance
|
||||
}
|
||||
activeInstances += exitingInstances + slashingInstances
|
||||
activeBalance += exitingBalance + slashingBalance
|
||||
activeEffectiveBalance += exitingEffectiveBalance + slashingEffectiveBalance
|
||||
|
||||
validatorsCount.WithLabelValues("Pending").Set(float64(pendingInstances))
|
||||
validatorsCount.WithLabelValues("Active").Set(float64(activeInstances))
|
||||
validatorsCount.WithLabelValues("Exiting").Set(float64(exitingInstances))
|
||||
|
||||
@@ -4,22 +4,29 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"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"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/shared/attestationutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/mputil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
|
||||
// getAttPreState retrieves the att pre state by either from the cache or the DB.
|
||||
func (s *Service) getAttPreState(ctx context.Context, c *ethpb.Checkpoint) (*stateTrie.BeaconState, error) {
|
||||
cachedState, err := s.checkpointStateCache.StateByCheckpoint(ctx, c)
|
||||
// Use a multilock to allow scoped holding of a mutex by a checkpoint root + epoch
|
||||
// allowing us to behave smarter in terms of how this function is used concurrently.
|
||||
epochKey := strconv.FormatUint(c.Epoch, 10 /* base 10 */)
|
||||
lock := mputil.NewMultilock(string(c.Root) + epochKey)
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
cachedState, err := s.checkpointStateCache.StateByCheckpoint(c)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get cached checkpoint state")
|
||||
}
|
||||
@@ -27,33 +34,17 @@ func (s *Service) getAttPreState(ctx context.Context, c *ethpb.Checkpoint) (*sta
|
||||
return cachedState, nil
|
||||
}
|
||||
|
||||
if err := s.checkpointStateCache.MarkInProgress(c); err != nil {
|
||||
if errors.Is(err, cache.ErrAlreadyInProgress) {
|
||||
cachedState, err = s.checkpointStateCache.StateByCheckpoint(ctx, c)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get cached checkpoint state")
|
||||
}
|
||||
if cachedState != nil {
|
||||
return cachedState, nil
|
||||
}
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
defer func() {
|
||||
if err := s.checkpointStateCache.MarkNotInProgress(c); err != nil {
|
||||
log.WithError(err).Error("Failed to mark cache not in progress")
|
||||
}
|
||||
}()
|
||||
baseState, err := s.stateGen.StateByRoot(ctx, bytesutil.ToBytes32(c.Root))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get pre state for epoch %d", c.Epoch)
|
||||
}
|
||||
|
||||
epochStartSlot, err := helpers.StartSlot(c.Epoch)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if epochStartSlot > baseState.Slot() {
|
||||
baseState = baseState.Copy()
|
||||
baseState, err = state.ProcessSlots(ctx, baseState, epochStartSlot)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not process slots up to epoch %d", c.Epoch)
|
||||
@@ -76,6 +67,7 @@ func (s *Service) getAttPreState(ctx context.Context, c *ethpb.Checkpoint) (*sta
|
||||
}
|
||||
}
|
||||
return baseState, nil
|
||||
|
||||
}
|
||||
|
||||
// verifyAttTargetEpoch validates attestation is from the current or previous epoch.
|
||||
|
||||
@@ -2,9 +2,7 @@ package blockchain
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
@@ -180,11 +178,11 @@ func TestStore_SaveCheckpointState(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1*params.BeaconConfig().SlotsPerEpoch, s1.Slot(), "Unexpected state slot")
|
||||
|
||||
s1, err = service.checkpointStateCache.StateByCheckpoint(ctx, cp1)
|
||||
s1, err = service.checkpointStateCache.StateByCheckpoint(cp1)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1*params.BeaconConfig().SlotsPerEpoch, s1.Slot(), "Unexpected state slot")
|
||||
|
||||
s2, err = service.checkpointStateCache.StateByCheckpoint(ctx, cp2)
|
||||
s2, err = service.checkpointStateCache.StateByCheckpoint(cp2)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 2*params.BeaconConfig().SlotsPerEpoch, s2.Slot(), "Unexpected state slot")
|
||||
|
||||
@@ -220,7 +218,7 @@ func TestStore_UpdateCheckpointState(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, returned.Slot(), checkpoint.Epoch*params.BeaconConfig().SlotsPerEpoch, "Incorrectly returned base state")
|
||||
|
||||
cached, err := service.checkpointStateCache.StateByCheckpoint(ctx, checkpoint)
|
||||
cached, err := service.checkpointStateCache.StateByCheckpoint(checkpoint)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, returned.Slot(), cached.Slot(), "State should have been cached")
|
||||
|
||||
@@ -235,53 +233,13 @@ func TestStore_UpdateCheckpointState(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, returned.Slot(), baseState.Slot(), "Incorrectly returned base state")
|
||||
|
||||
cached, err = service.checkpointStateCache.StateByCheckpoint(ctx, newCheckpoint)
|
||||
cached, err = service.checkpointStateCache.StateByCheckpoint(newCheckpoint)
|
||||
require.NoError(t, err)
|
||||
if !proto.Equal(returned.InnerStateUnsafe(), cached.InnerStateUnsafe()) {
|
||||
t.Error("Incorrectly cached base state")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStore_CheckpointState_InProgress(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
db, sc := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{
|
||||
BeaconDB: db,
|
||||
StateGen: stategen.New(db, sc),
|
||||
}
|
||||
service, err := NewService(ctx, cfg)
|
||||
require.NoError(t, err)
|
||||
|
||||
epoch := uint64(1)
|
||||
baseState, _ := testutil.DeterministicGenesisState(t, 1)
|
||||
checkpoint := ðpb.Checkpoint{Epoch: epoch, Root: bytesutil.PadTo([]byte("hi"), 32)}
|
||||
require.NoError(t, service.beaconDB.SaveState(ctx, baseState, bytesutil.ToBytes32(checkpoint.Root)))
|
||||
require.NoError(t, service.checkpointStateCache.MarkInProgress(checkpoint))
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
response, err := service.getAttPreState(ctx, checkpoint)
|
||||
require.NoError(t, err)
|
||||
if !proto.Equal(baseState.InnerStateUnsafe(), response.InnerStateUnsafe()) {
|
||||
t.Error("Expected equal responses from cache")
|
||||
}
|
||||
}()
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
assert.NoError(t, service.checkpointStateCache.AddCheckpointState(checkpoint, baseState))
|
||||
assert.NoError(t, service.checkpointStateCache.MarkNotInProgress(checkpoint))
|
||||
}()
|
||||
|
||||
testutil.WaitTimeout(&wg, time.Second*2)
|
||||
}
|
||||
|
||||
func TestAttEpoch_MatchPrevEpoch(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
db, _ := testDB.SetupDB(t)
|
||||
|
||||
@@ -84,10 +84,17 @@ func (s *Service) onBlock(ctx context.Context, signed *ethpb.SignedBeaconBlock,
|
||||
return err
|
||||
}
|
||||
|
||||
postState, err := state.ExecuteStateTransition(ctx, preState, signed)
|
||||
set, postState, err := state.ExecuteStateTransitionNoVerifyAnySig(ctx, preState, signed)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not execute state transition")
|
||||
}
|
||||
valid, err := set.Verify()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not batch verify signature")
|
||||
}
|
||||
if !valid {
|
||||
return errors.New("signature in block failed to verify")
|
||||
}
|
||||
|
||||
if err := s.savePostStateInfo(ctx, blockRoot, signed, postState, false /* reg sync */); err != nil {
|
||||
return err
|
||||
|
||||
@@ -363,6 +363,7 @@ func (s *Service) finalizedImpliesNewJustified(ctx context.Context, state *state
|
||||
func (s *Service) fillInForkChoiceMissingBlocks(ctx context.Context, blk *ethpb.BeaconBlock,
|
||||
fCheckpoint, jCheckpoint *ethpb.Checkpoint) error {
|
||||
pendingNodes := make([]*ethpb.BeaconBlock, 0)
|
||||
pendingRoots := make([][32]byte, 0)
|
||||
|
||||
parentRoot := bytesutil.ToBytes32(blk.ParentRoot)
|
||||
slot := blk.Slot
|
||||
@@ -380,6 +381,8 @@ func (s *Service) fillInForkChoiceMissingBlocks(ctx context.Context, blk *ethpb.
|
||||
}
|
||||
|
||||
pendingNodes = append(pendingNodes, b.Block)
|
||||
copiedRoot := parentRoot
|
||||
pendingRoots = append(pendingRoots, copiedRoot)
|
||||
parentRoot = bytesutil.ToBytes32(b.Block.ParentRoot)
|
||||
slot = b.Block.Slot
|
||||
higherThanFinalized = slot > fSlot
|
||||
@@ -389,11 +392,7 @@ func (s *Service) fillInForkChoiceMissingBlocks(ctx context.Context, blk *ethpb.
|
||||
// Lower slots should be at the end of the list.
|
||||
for i := len(pendingNodes) - 1; i >= 0; i-- {
|
||||
b := pendingNodes[i]
|
||||
r, err := b.HashTreeRoot()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r := pendingRoots[i]
|
||||
if err := s.forkChoiceStore.ProcessBlock(ctx,
|
||||
b.Slot, r, bytesutil.ToBytes32(b.ParentRoot), bytesutil.ToBytes32(b.Body.Graffiti),
|
||||
jCheckpoint.Epoch,
|
||||
|
||||
@@ -2,6 +2,7 @@ package blockchain
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -372,6 +373,46 @@ func TestFillForkChoiceMissingBlocks_CanSave(t *testing.T) {
|
||||
assert.Equal(t, true, service.forkChoiceStore.HasNode(bytesutil.ToBytes32(roots[8])), "Didn't save node")
|
||||
}
|
||||
|
||||
func TestFillForkChoiceMissingBlocks_RootsMatch(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
db, _ := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{BeaconDB: db}
|
||||
service, err := NewService(ctx, cfg)
|
||||
require.NoError(t, err)
|
||||
service.forkChoiceStore = protoarray.New(0, 0, [32]byte{'A'})
|
||||
service.finalizedCheckpt = ðpb.Checkpoint{Root: make([]byte, 32)}
|
||||
|
||||
genesisStateRoot := [32]byte{}
|
||||
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
|
||||
require.NoError(t, db.SaveBlock(ctx, genesis))
|
||||
validGenesisRoot, err := genesis.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
st := testutil.NewBeaconState()
|
||||
|
||||
require.NoError(t, service.beaconDB.SaveState(ctx, st.Copy(), validGenesisRoot))
|
||||
roots, err := blockTree1(db, validGenesisRoot[:])
|
||||
require.NoError(t, err)
|
||||
|
||||
beaconState, _ := testutil.DeterministicGenesisState(t, 32)
|
||||
block := testutil.NewBeaconBlock()
|
||||
block.Block.Slot = 9
|
||||
block.Block.ParentRoot = roots[8]
|
||||
|
||||
err = service.fillInForkChoiceMissingBlocks(
|
||||
context.Background(), block.Block, beaconState.FinalizedCheckpoint(), beaconState.CurrentJustifiedCheckpoint())
|
||||
require.NoError(t, err)
|
||||
|
||||
// 5 nodes from the block tree 1. B0 - B3 - B4 - B6 - B8
|
||||
assert.Equal(t, 5, len(service.forkChoiceStore.Nodes()), "Miss match nodes")
|
||||
// Ensure all roots and their respective blocks exist.
|
||||
wantedRoots := [][]byte{roots[0], roots[3], roots[4], roots[6], roots[8]}
|
||||
for i, rt := range wantedRoots {
|
||||
assert.Equal(t, true, service.forkChoiceStore.HasNode(bytesutil.ToBytes32(rt)), fmt.Sprintf("Didn't save node: %d", i))
|
||||
assert.Equal(t, true, service.beaconDB.HasBlock(context.Background(), bytesutil.ToBytes32(rt)))
|
||||
}
|
||||
}
|
||||
|
||||
func TestFillForkChoiceMissingBlocks_FilterFinalized(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
db, _ := testDB.SetupDB(t)
|
||||
@@ -755,7 +796,6 @@ func TestVerifyBlkDescendant(t *testing.T) {
|
||||
type args struct {
|
||||
parentRoot [32]byte
|
||||
finalizedRoot [32]byte
|
||||
finalizedSlot uint64
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
@@ -99,6 +100,14 @@ func (s *Service) processAttestation(subscribedToStateEvents chan struct{}) {
|
||||
<-stateChannel
|
||||
stateSub.Unsubscribe()
|
||||
|
||||
if s.genesisTime.IsZero() {
|
||||
log.Warn("ProcessAttestations routine waiting for genesis time")
|
||||
for s.genesisTime.IsZero() {
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
log.Warn("Genesis time received, now available to process attestations")
|
||||
}
|
||||
|
||||
st := slotutil.GetSlotTicker(s.genesisTime, params.BeaconConfig().SecondsPerSlot)
|
||||
for {
|
||||
select {
|
||||
|
||||
@@ -78,7 +78,6 @@ func TestService_ReceiveBlock(t *testing.T) {
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "updates exit pool",
|
||||
args: args{
|
||||
@@ -93,14 +92,13 @@ func TestService_ReceiveBlock(t *testing.T) {
|
||||
),
|
||||
},
|
||||
check: func(t *testing.T, s *Service) {
|
||||
var n int
|
||||
for i := uint64(0); int(i) < genesis.NumValidators(); i++ {
|
||||
if s.exitPool.HasBeenIncluded(i) {
|
||||
n++
|
||||
}
|
||||
}
|
||||
if n != 3 {
|
||||
t.Errorf("Did not mark the correct number of exits. Got %d but wanted %d", n, 3)
|
||||
pending := s.exitPool.PendingExits(genesis, 1, true /* no limit */)
|
||||
if len(pending) != 0 {
|
||||
t.Errorf(
|
||||
"Did not mark the correct number of exits. Got %d pending but wanted %d",
|
||||
len(pending),
|
||||
0,
|
||||
)
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
@@ -38,6 +38,10 @@ import (
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
// headSyncMinEpochsAfterCheckpoint defines how many epochs should elapse after known finalization
|
||||
// checkpoint for head sync to be triggered.
|
||||
const headSyncMinEpochsAfterCheckpoint = 128
|
||||
|
||||
// Service represents a service that handles the internal
|
||||
// logic of managing the full PoS beacon chain.
|
||||
type Service struct {
|
||||
@@ -171,7 +175,11 @@ func (s *Service) Start() {
|
||||
if err != nil {
|
||||
log.Fatalf("Could not retrieve genesis state: %v", err)
|
||||
}
|
||||
go slotutil.CountdownToGenesis(s.ctx, s.genesisTime, uint64(gState.NumValidators()))
|
||||
gRoot, err := gState.HashTreeRoot(s.ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not hash tree root genesis state: %v", err)
|
||||
}
|
||||
go slotutil.CountdownToGenesis(s.ctx, s.genesisTime, uint64(gState.NumValidators()), gRoot)
|
||||
|
||||
justifiedCheckpoint, err := s.beaconDB.JustifiedCheckpoint(s.ctx)
|
||||
if err != nil {
|
||||
@@ -198,12 +206,14 @@ func (s *Service) Start() {
|
||||
log.Fatalf("Could not get start slot of finalized epoch: %v", err)
|
||||
}
|
||||
h := s.headBlock().Block
|
||||
log.WithFields(logrus.Fields{
|
||||
"startSlot": ss,
|
||||
"endSlot": h.Slot,
|
||||
}).Info("Loading blocks to fork choice store, this may take a while.")
|
||||
if err := s.fillInForkChoiceMissingBlocks(s.ctx, h, s.finalizedCheckpt, s.justifiedCheckpt); err != nil {
|
||||
log.Fatalf("Could not fill in fork choice store missing blocks: %v", err)
|
||||
if h.Slot > ss {
|
||||
log.WithFields(logrus.Fields{
|
||||
"startSlot": ss,
|
||||
"endSlot": h.Slot,
|
||||
}).Info("Loading blocks to fork choice store, this may take a while.")
|
||||
if err := s.fillInForkChoiceMissingBlocks(s.ctx, h, s.finalizedCheckpt, s.justifiedCheckpt); err != nil {
|
||||
log.Fatalf("Could not fill in fork choice store missing blocks: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := s.VerifyWeakSubjectivityRoot(s.ctx); err != nil {
|
||||
@@ -265,7 +275,11 @@ func (s *Service) processChainStartTime(ctx context.Context, genesisTime time.Ti
|
||||
log.Fatalf("Could not initialize beacon chain: %v", err)
|
||||
}
|
||||
// We start a counter to genesis, if needed.
|
||||
go slotutil.CountdownToGenesis(ctx, genesisTime, uint64(initializedState.NumValidators()))
|
||||
gRoot, err := initializedState.HashTreeRoot(s.ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not hash tree root genesis state: %v", err)
|
||||
}
|
||||
go slotutil.CountdownToGenesis(ctx, genesisTime, uint64(initializedState.NumValidators()), gRoot)
|
||||
|
||||
// We send out a state initialized event to the rest of the services
|
||||
// running in the beacon node.
|
||||
@@ -328,6 +342,11 @@ func (s *Service) Stop() error {
|
||||
}
|
||||
}
|
||||
|
||||
// Save cached state summaries to the DB before stop.
|
||||
if err := s.stateGen.SaveStateSummariesToDB(s.ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Save initial sync cached blocks to the DB before stop.
|
||||
return s.beaconDB.SaveBlocks(s.ctx, s.getInitSyncBlocks())
|
||||
}
|
||||
@@ -335,6 +354,9 @@ func (s *Service) Stop() error {
|
||||
// Status always returns nil unless there is an error condition that causes
|
||||
// this service to be unhealthy.
|
||||
func (s *Service) Status() error {
|
||||
if s.genesisRoot == params.BeaconConfig().ZeroHash {
|
||||
return errors.New("genesis state has not been created")
|
||||
}
|
||||
if runtime.NumGoroutine() > s.maxRoutines {
|
||||
return fmt.Errorf("too many goroutines %d", runtime.NumGoroutine())
|
||||
}
|
||||
@@ -418,29 +440,6 @@ func (s *Service) initializeChainInfo(ctx context.Context) error {
|
||||
}
|
||||
s.genesisRoot = genesisBlkRoot
|
||||
|
||||
if flags.Get().HeadSync {
|
||||
headBlock, err := s.beaconDB.HeadBlock(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not retrieve head block")
|
||||
}
|
||||
headRoot, err := headBlock.Block.HashTreeRoot()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not hash head block")
|
||||
}
|
||||
finalizedState, err := s.stateGen.Resume(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get finalized state from db")
|
||||
}
|
||||
log.Infof("Regenerating state from the last checkpoint at slot %d to current head slot of %d."+
|
||||
"This process may take a while, please wait.", finalizedState.Slot(), headBlock.Block.Slot)
|
||||
headState, err := s.stateGen.StateByRoot(ctx, headRoot)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not retrieve head state")
|
||||
}
|
||||
s.setHead(headRoot, headBlock, headState)
|
||||
return nil
|
||||
}
|
||||
|
||||
finalized, err := s.beaconDB.FinalizedCheckpoint(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get finalized checkpoint from db")
|
||||
@@ -458,6 +457,42 @@ func (s *Service) initializeChainInfo(ctx context.Context) error {
|
||||
return errors.Wrap(err, "could not get finalized state from db")
|
||||
}
|
||||
|
||||
if flags.Get().HeadSync {
|
||||
headBlock, err := s.beaconDB.HeadBlock(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not retrieve head block")
|
||||
}
|
||||
headEpoch := helpers.SlotToEpoch(headBlock.Block.Slot)
|
||||
var epochsSinceFinality uint64
|
||||
if headEpoch > finalized.Epoch {
|
||||
epochsSinceFinality = headEpoch - finalized.Epoch
|
||||
}
|
||||
// Head sync when node is far enough beyond known finalized epoch,
|
||||
// this becomes really useful during long period of non-finality.
|
||||
if epochsSinceFinality >= headSyncMinEpochsAfterCheckpoint {
|
||||
headRoot, err := headBlock.Block.HashTreeRoot()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not hash head block")
|
||||
}
|
||||
finalizedState, err := s.stateGen.Resume(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get finalized state from db")
|
||||
}
|
||||
log.Infof("Regenerating state from the last checkpoint at slot %d to current head slot of %d."+
|
||||
"This process may take a while, please wait.", finalizedState.Slot(), headBlock.Block.Slot)
|
||||
headState, err := s.stateGen.StateByRoot(ctx, headRoot)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not retrieve head state")
|
||||
}
|
||||
s.setHead(headRoot, headBlock, headState)
|
||||
return nil
|
||||
} else {
|
||||
log.Warnf("Finalized checkpoint at slot %d is too close to the current head slot, "+
|
||||
"resetting head from the checkpoint ('--%s' flag is ignored).",
|
||||
finalizedState.Slot(), flags.HeadSync.Name)
|
||||
}
|
||||
}
|
||||
|
||||
finalizedBlock, err := s.beaconDB.Block(ctx, finalizedRoot)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get finalized block from db")
|
||||
|
||||
@@ -3,7 +3,6 @@ package blockchain
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -18,6 +17,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db"
|
||||
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/flags"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/attestations"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
|
||||
@@ -32,15 +32,9 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
"github.com/sirupsen/logrus"
|
||||
logTest "github.com/sirupsen/logrus/hooks/test"
|
||||
)
|
||||
|
||||
func init() {
|
||||
logrus.SetLevel(logrus.DebugLevel)
|
||||
logrus.SetOutput(ioutil.Discard)
|
||||
}
|
||||
|
||||
type mockBeaconNode struct {
|
||||
stateFeed *event.Feed
|
||||
}
|
||||
@@ -93,7 +87,7 @@ func setupBeaconChain(t *testing.T, beaconDB db.Database, sc *cache.StateSummary
|
||||
require.NoError(t, err)
|
||||
web3Service, err = powchain.NewService(ctx, &powchain.Web3ServiceConfig{
|
||||
BeaconDB: beaconDB,
|
||||
HTTPEndPoint: endpoint,
|
||||
HTTPEndpoints: []string{endpoint},
|
||||
DepositContract: common.Address{},
|
||||
})
|
||||
require.NoError(t, err, "Unable to set up web3 service")
|
||||
@@ -323,6 +317,87 @@ func TestChainService_InitializeChainInfo_SetHeadAtGenesis(t *testing.T) {
|
||||
assert.DeepEqual(t, genesis, c.head.block)
|
||||
}
|
||||
|
||||
func TestChainService_InitializeChainInfo_HeadSync(t *testing.T) {
|
||||
resetFlags := flags.Get()
|
||||
flags.Init(&flags.GlobalFlags{
|
||||
HeadSync: true,
|
||||
})
|
||||
defer func() {
|
||||
flags.Init(resetFlags)
|
||||
}()
|
||||
|
||||
hook := logTest.NewGlobal()
|
||||
finalizedSlot := params.BeaconConfig().SlotsPerEpoch*2 + 1
|
||||
db, sc := testDB.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
|
||||
genesisBlock := testutil.NewBeaconBlock()
|
||||
genesisRoot, err := genesisBlock.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, db.SaveGenesisBlockRoot(ctx, genesisRoot))
|
||||
require.NoError(t, db.SaveBlock(ctx, genesisBlock))
|
||||
|
||||
finalizedBlock := testutil.NewBeaconBlock()
|
||||
finalizedBlock.Block.Slot = finalizedSlot
|
||||
finalizedBlock.Block.ParentRoot = genesisRoot[:]
|
||||
finalizedRoot, err := finalizedBlock.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, db.SaveBlock(ctx, finalizedBlock))
|
||||
|
||||
// Set head slot close to the finalization point, no head sync is triggered.
|
||||
headBlock := testutil.NewBeaconBlock()
|
||||
headBlock.Block.Slot = finalizedSlot + params.BeaconConfig().SlotsPerEpoch*5
|
||||
headBlock.Block.ParentRoot = finalizedRoot[:]
|
||||
headRoot, err := headBlock.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, db.SaveBlock(ctx, headBlock))
|
||||
|
||||
headState := testutil.NewBeaconState()
|
||||
require.NoError(t, headState.SetSlot(headBlock.Block.Slot))
|
||||
require.NoError(t, headState.SetGenesisValidatorRoot(params.BeaconConfig().ZeroHash[:]))
|
||||
require.NoError(t, db.SaveState(ctx, headState, genesisRoot))
|
||||
require.NoError(t, db.SaveState(ctx, headState, finalizedRoot))
|
||||
require.NoError(t, db.SaveState(ctx, headState, headRoot))
|
||||
require.NoError(t, db.SaveHeadBlockRoot(ctx, headRoot))
|
||||
require.NoError(t, db.SaveFinalizedCheckpoint(ctx, ðpb.Checkpoint{
|
||||
Epoch: helpers.SlotToEpoch(finalizedBlock.Block.Slot),
|
||||
Root: finalizedRoot[:],
|
||||
}))
|
||||
|
||||
c := &Service{beaconDB: db, stateGen: stategen.New(db, sc)}
|
||||
|
||||
require.NoError(t, c.initializeChainInfo(ctx))
|
||||
s, err := c.HeadState(ctx)
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, headState.InnerStateUnsafe(), s.InnerStateUnsafe(), "Head state incorrect")
|
||||
assert.Equal(t, genesisRoot, c.genesisRoot, "Genesis block root incorrect")
|
||||
// Since head sync is not triggered, chain is initialized to the last finalization checkpoint.
|
||||
assert.DeepEqual(t, finalizedBlock, c.head.block)
|
||||
assert.LogsContain(t, hook, "resetting head from the checkpoint ('--head-sync' flag is ignored)")
|
||||
assert.LogsDoNotContain(t, hook, "Regenerating state from the last checkpoint at slot")
|
||||
|
||||
// Set head slot far beyond the finalization point, head sync should be triggered.
|
||||
headBlock = testutil.NewBeaconBlock()
|
||||
headBlock.Block.Slot = finalizedSlot + params.BeaconConfig().SlotsPerEpoch*headSyncMinEpochsAfterCheckpoint
|
||||
headBlock.Block.ParentRoot = finalizedRoot[:]
|
||||
headRoot, err = headBlock.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, db.SaveBlock(ctx, headBlock))
|
||||
require.NoError(t, db.SaveState(ctx, headState, headRoot))
|
||||
require.NoError(t, db.SaveHeadBlockRoot(ctx, headRoot))
|
||||
|
||||
hook.Reset()
|
||||
require.NoError(t, c.initializeChainInfo(ctx))
|
||||
s, err = c.HeadState(ctx)
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, headState.InnerStateUnsafe(), s.InnerStateUnsafe(), "Head state incorrect")
|
||||
assert.Equal(t, genesisRoot, c.genesisRoot, "Genesis block root incorrect")
|
||||
// Head slot is far beyond the latest finalized checkpoint, head sync is triggered.
|
||||
assert.DeepEqual(t, headBlock, c.head.block)
|
||||
assert.LogsContain(t, hook, "Regenerating state from the last checkpoint at slot 225")
|
||||
assert.LogsDoNotContain(t, hook, "resetting head from the checkpoint ('--head-sync' flag is ignored)")
|
||||
}
|
||||
|
||||
func TestChainService_SaveHeadNoDB(t *testing.T) {
|
||||
db, sc := testDB.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
@@ -371,6 +446,7 @@ func TestServiceStop_SaveCachedBlocks(t *testing.T) {
|
||||
cancel: cancel,
|
||||
beaconDB: db,
|
||||
initSyncBlocks: make(map[[32]byte]*ethpb.SignedBeaconBlock),
|
||||
stateGen: stategen.New(db, cache.NewStateSummaryCache()),
|
||||
}
|
||||
b := testutil.NewBeaconBlock()
|
||||
r, err := b.Block.HashTreeRoot()
|
||||
@@ -380,6 +456,25 @@ func TestServiceStop_SaveCachedBlocks(t *testing.T) {
|
||||
require.Equal(t, true, s.beaconDB.HasBlock(ctx, r))
|
||||
}
|
||||
|
||||
func TestServiceStop_SaveCachedStateSummaries(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
db, _ := testDB.SetupDB(t)
|
||||
c := cache.NewStateSummaryCache()
|
||||
s := &Service{
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
beaconDB: db,
|
||||
initSyncBlocks: make(map[[32]byte]*ethpb.SignedBeaconBlock),
|
||||
stateGen: stategen.New(db, c),
|
||||
}
|
||||
|
||||
r := [32]byte{'a'}
|
||||
ss := &pb.StateSummary{Root: r[:], Slot: 1}
|
||||
c.Put(r, ss)
|
||||
require.NoError(t, s.Stop())
|
||||
require.Equal(t, true, s.beaconDB.HasStateSummary(ctx, r))
|
||||
}
|
||||
|
||||
func BenchmarkHasBlockDB(b *testing.B) {
|
||||
db, _ := testDB.SetupDB(b)
|
||||
ctx := context.Background()
|
||||
|
||||
@@ -20,7 +20,6 @@ go_library(
|
||||
"//beacon-chain/forkchoice/protoarray:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/bytesutil:go_default_library",
|
||||
"//shared/event:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
|
||||
@@ -20,7 +20,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
|
||||
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/event"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/sirupsen/logrus"
|
||||
@@ -377,33 +376,3 @@ func (ms *ChainService) VerifyFinalizedConsistency(_ context.Context, r []byte)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AttestationCheckPtInfo mocks AttestationCheckPtInfo and always returns nil.
|
||||
func (ms *ChainService) AttestationCheckPtInfo(_ context.Context, att *ethpb.Attestation) (*pb.CheckPtInfo, error) {
|
||||
f := ms.State.Fork()
|
||||
g := bytesutil.ToBytes32(ms.State.GenesisValidatorRoot())
|
||||
seed, err := helpers.Seed(ms.State, helpers.SlotToEpoch(att.Data.Slot), params.BeaconConfig().DomainBeaconAttester)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
indices, err := helpers.ActiveValidatorIndices(ms.State, helpers.SlotToEpoch(att.Data.Slot))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
validators := ms.State.ValidatorsReadOnly()
|
||||
pks := make([][]byte, len(validators))
|
||||
for i := 0; i < len(pks); i++ {
|
||||
pk := validators[i].PublicKey()
|
||||
pks[i] = pk[:]
|
||||
}
|
||||
|
||||
info := &pb.CheckPtInfo{
|
||||
Fork: f,
|
||||
GenesisRoot: g[:],
|
||||
Seed: seed[:],
|
||||
ActiveIndices: indices,
|
||||
PubKeys: pks,
|
||||
}
|
||||
|
||||
return info, nil
|
||||
}
|
||||
|
||||
2
beacon-chain/cache/BUILD.bazel
vendored
2
beacon-chain/cache/BUILD.bazel
vendored
@@ -57,7 +57,7 @@ go_test(
|
||||
"checkpoint_state_test.go",
|
||||
"committee_fuzz_test.go",
|
||||
"committee_test.go",
|
||||
"feature_flag_test.go",
|
||||
"cache_test.go",
|
||||
"hot_state_cache_test.go",
|
||||
"skip_slot_cache_test.go",
|
||||
"subnet_ids_test.go",
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
@@ -10,8 +9,5 @@ import (
|
||||
func TestMain(m *testing.M) {
|
||||
resetCfg := featureconfig.InitWithReset(&featureconfig.Flags{EnableEth1DataVoteCache: true})
|
||||
defer resetCfg()
|
||||
code := m.Run()
|
||||
// os.Exit will prevent defer from being called
|
||||
resetCfg()
|
||||
os.Exit(code)
|
||||
m.Run()
|
||||
}
|
||||
86
beacon-chain/cache/checkpoint_state.go
vendored
86
beacon-chain/cache/checkpoint_state.go
vendored
@@ -1,10 +1,7 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
@@ -33,9 +30,8 @@ var (
|
||||
|
||||
// CheckpointStateCache is a struct with 1 queue for looking up state by checkpoint.
|
||||
type CheckpointStateCache struct {
|
||||
cache *lru.Cache
|
||||
lock sync.RWMutex
|
||||
inProgress map[string]bool
|
||||
cache *lru.Cache
|
||||
lock sync.RWMutex
|
||||
}
|
||||
|
||||
// NewCheckpointStateCache creates a new checkpoint state cache for storing/accessing processed state.
|
||||
@@ -45,45 +41,22 @@ func NewCheckpointStateCache() *CheckpointStateCache {
|
||||
panic(err)
|
||||
}
|
||||
return &CheckpointStateCache{
|
||||
cache: cache,
|
||||
inProgress: map[string]bool{},
|
||||
cache: cache,
|
||||
}
|
||||
}
|
||||
|
||||
// StateByCheckpoint fetches state by checkpoint. Returns true with a
|
||||
// reference to the CheckpointState info, if exists. Otherwise returns false, nil.
|
||||
func (c *CheckpointStateCache) StateByCheckpoint(ctx context.Context, cp *ethpb.Checkpoint) (*stateTrie.BeaconState, error) {
|
||||
k, err := checkpointKey(cp)
|
||||
func (c *CheckpointStateCache) StateByCheckpoint(cp *ethpb.Checkpoint) (*stateTrie.BeaconState, error) {
|
||||
c.lock.RLock()
|
||||
defer c.lock.RUnlock()
|
||||
h, err := hashutil.HashProto(cp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
delay := minDelay
|
||||
item, exists := c.cache.Get(h)
|
||||
|
||||
// Another identical request may be in progress already. Let's wait until
|
||||
// any in progress request resolves or our timeout is exceeded.
|
||||
for {
|
||||
if ctx.Err() != nil {
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
|
||||
c.lock.RLock()
|
||||
if !c.inProgress[k] {
|
||||
c.lock.RUnlock()
|
||||
break
|
||||
}
|
||||
c.lock.RUnlock()
|
||||
|
||||
// This increasing backoff is to decrease the CPU cycles while waiting
|
||||
// for the in progress boolean to flip to false.
|
||||
time.Sleep(time.Duration(delay) * time.Nanosecond)
|
||||
delay *= delayFactor
|
||||
delay = math.Min(delay, maxDelay)
|
||||
}
|
||||
|
||||
c.lock.RLock()
|
||||
defer c.lock.RUnlock()
|
||||
item, exists := c.cache.Get(k)
|
||||
if exists && item != nil {
|
||||
checkpointStateHit.Inc()
|
||||
// Copy here is unnecessary since the return will only be used to verify attestation signature.
|
||||
@@ -99,47 +72,10 @@ func (c *CheckpointStateCache) StateByCheckpoint(ctx context.Context, cp *ethpb.
|
||||
func (c *CheckpointStateCache) AddCheckpointState(cp *ethpb.Checkpoint, s *stateTrie.BeaconState) error {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
k, err := checkpointKey(cp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.cache.ContainsOrAdd(k, s)
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarkInProgress a request so that any other similar requests will block on
|
||||
// Get until MarkNotInProgress is called.
|
||||
func (c *CheckpointStateCache) MarkInProgress(cp *ethpb.Checkpoint) error {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
k, err := checkpointKey(cp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if c.inProgress[k] {
|
||||
return ErrAlreadyInProgress
|
||||
}
|
||||
c.inProgress[k] = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarkNotInProgress will release the lock on a given request. This should be
|
||||
// called after put.
|
||||
func (c *CheckpointStateCache) MarkNotInProgress(cp *ethpb.Checkpoint) error {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
k, err := checkpointKey(cp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
delete(c.inProgress, k)
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkpointKey(cp *ethpb.Checkpoint) (string, error) {
|
||||
h, err := hashutil.HashProto(cp)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return err
|
||||
}
|
||||
return string(h[:]), nil
|
||||
c.cache.Add(h, s)
|
||||
return nil
|
||||
}
|
||||
|
||||
9
beacon-chain/cache/checkpoint_state_test.go
vendored
9
beacon-chain/cache/checkpoint_state_test.go
vendored
@@ -1,7 +1,6 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
@@ -24,13 +23,13 @@ func TestCheckpointStateCache_StateByCheckpoint(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
state, err := cache.StateByCheckpoint(context.Background(), cp1)
|
||||
state, err := cache.StateByCheckpoint(cp1)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, (*stateTrie.BeaconState)(nil), state, "Expected state not to exist in empty cache")
|
||||
|
||||
require.NoError(t, cache.AddCheckpointState(cp1, st))
|
||||
|
||||
state, err = cache.StateByCheckpoint(context.Background(), cp1)
|
||||
state, err = cache.StateByCheckpoint(cp1)
|
||||
require.NoError(t, err)
|
||||
|
||||
if !proto.Equal(state.InnerStateUnsafe(), st.InnerStateUnsafe()) {
|
||||
@@ -44,11 +43,11 @@ func TestCheckpointStateCache_StateByCheckpoint(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, cache.AddCheckpointState(cp2, st2))
|
||||
|
||||
state, err = cache.StateByCheckpoint(context.Background(), cp2)
|
||||
state, err = cache.StateByCheckpoint(cp2)
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, st2.CloneInnerState(), state.CloneInnerState(), "incorrectly cached state")
|
||||
|
||||
state, err = cache.StateByCheckpoint(context.Background(), cp1)
|
||||
state, err = cache.StateByCheckpoint(cp1)
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, st.CloneInnerState(), state.CloneInnerState(), "incorrectly cached state")
|
||||
}
|
||||
|
||||
@@ -50,12 +50,10 @@ type FinalizedDeposits struct {
|
||||
// stores all the deposit related data that is required by the beacon-node.
|
||||
type DepositCache struct {
|
||||
// Beacon chain deposits in memory.
|
||||
pendingDeposits []*dbpb.DepositContainer
|
||||
deposits []*dbpb.DepositContainer
|
||||
finalizedDeposits *FinalizedDeposits
|
||||
depositsLock sync.RWMutex
|
||||
chainStartPubkeys map[string]bool
|
||||
chainStartPubkeysLock sync.RWMutex
|
||||
pendingDeposits []*dbpb.DepositContainer
|
||||
deposits []*dbpb.DepositContainer
|
||||
finalizedDeposits *FinalizedDeposits
|
||||
depositsLock sync.RWMutex
|
||||
}
|
||||
|
||||
// New instantiates a new deposit cache
|
||||
@@ -71,7 +69,6 @@ func New() (*DepositCache, error) {
|
||||
pendingDeposits: []*dbpb.DepositContainer{},
|
||||
deposits: []*dbpb.DepositContainer{},
|
||||
finalizedDeposits: &FinalizedDeposits{Deposits: finalizedDepositsTrie, MerkleTrieIndex: -1},
|
||||
chainStartPubkeys: make(map[string]bool),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -151,28 +148,6 @@ func (dc *DepositCache) AllDepositContainers(ctx context.Context) []*dbpb.Deposi
|
||||
return dc.deposits
|
||||
}
|
||||
|
||||
// MarkPubkeyForChainstart sets the pubkey deposit status to true.
|
||||
func (dc *DepositCache) MarkPubkeyForChainstart(ctx context.Context, pubkey string) {
|
||||
ctx, span := trace.StartSpan(ctx, "DepositsCache.MarkPubkeyForChainstart")
|
||||
defer span.End()
|
||||
dc.chainStartPubkeysLock.Lock()
|
||||
defer dc.chainStartPubkeysLock.Unlock()
|
||||
dc.chainStartPubkeys[pubkey] = true
|
||||
}
|
||||
|
||||
// PubkeyInChainstart returns bool for whether the pubkey passed in has deposited.
|
||||
func (dc *DepositCache) PubkeyInChainstart(ctx context.Context, pubkey string) bool {
|
||||
ctx, span := trace.StartSpan(ctx, "DepositsCache.PubkeyInChainstart")
|
||||
defer span.End()
|
||||
dc.chainStartPubkeysLock.RLock()
|
||||
defer dc.chainStartPubkeysLock.RUnlock()
|
||||
if dc.chainStartPubkeys != nil {
|
||||
return dc.chainStartPubkeys[pubkey]
|
||||
}
|
||||
dc.chainStartPubkeys = make(map[string]bool)
|
||||
return false
|
||||
}
|
||||
|
||||
// AllDeposits returns a list of historical deposits until the given block number
|
||||
// (inclusive). If no block is specified then this method returns all historical deposits.
|
||||
func (dc *DepositCache) AllDeposits(ctx context.Context, untilBlk *big.Int) []*ethpb.Deposit {
|
||||
@@ -269,7 +244,7 @@ func (dc *DepositCache) PruneProofs(ctx context.Context, untilDepositIndex int64
|
||||
dc.depositsLock.Lock()
|
||||
defer dc.depositsLock.Unlock()
|
||||
|
||||
if untilDepositIndex > int64(len(dc.deposits)) {
|
||||
if untilDepositIndex >= int64(len(dc.deposits)) {
|
||||
untilDepositIndex = int64(len(dc.deposits) - 1)
|
||||
}
|
||||
|
||||
|
||||
@@ -700,6 +700,49 @@ func TestPruneProofs_PruneAllWhenDepositIndexTooBig(t *testing.T) {
|
||||
assert.DeepEqual(t, ([][]byte)(nil), dc.deposits[3].Deposit.Proof)
|
||||
}
|
||||
|
||||
func TestPruneProofs_CorrectlyHandleLastIndex(t *testing.T) {
|
||||
dc, err := New()
|
||||
require.NoError(t, err)
|
||||
|
||||
deposits := []struct {
|
||||
blkNum uint64
|
||||
deposit *ethpb.Deposit
|
||||
index int64
|
||||
}{
|
||||
{
|
||||
blkNum: 0,
|
||||
deposit: ðpb.Deposit{Proof: makeDepositProof()},
|
||||
index: 0,
|
||||
},
|
||||
{
|
||||
blkNum: 0,
|
||||
deposit: ðpb.Deposit{Proof: makeDepositProof()},
|
||||
index: 1,
|
||||
},
|
||||
{
|
||||
blkNum: 0,
|
||||
deposit: ðpb.Deposit{Proof: makeDepositProof()},
|
||||
index: 2,
|
||||
},
|
||||
{
|
||||
blkNum: 0,
|
||||
deposit: ðpb.Deposit{Proof: makeDepositProof()},
|
||||
index: 3,
|
||||
},
|
||||
}
|
||||
|
||||
for _, ins := range deposits {
|
||||
dc.InsertDeposit(context.Background(), ins.deposit, ins.blkNum, ins.index, [32]byte{})
|
||||
}
|
||||
|
||||
require.NoError(t, dc.PruneProofs(context.Background(), 4))
|
||||
|
||||
assert.DeepEqual(t, ([][]byte)(nil), dc.deposits[0].Deposit.Proof)
|
||||
assert.DeepEqual(t, ([][]byte)(nil), dc.deposits[1].Deposit.Proof)
|
||||
assert.DeepEqual(t, ([][]byte)(nil), dc.deposits[2].Deposit.Proof)
|
||||
assert.DeepEqual(t, ([][]byte)(nil), dc.deposits[3].Deposit.Proof)
|
||||
}
|
||||
|
||||
func makeDepositProof() [][]byte {
|
||||
proof := make([][]byte, int(params.BeaconConfig().DepositContractTreeDepth)+1)
|
||||
for i := range proof {
|
||||
|
||||
@@ -60,6 +60,7 @@ go_test(
|
||||
"exit_test.go",
|
||||
"genesis_test.go",
|
||||
"header_test.go",
|
||||
"proposer_slashing_regression_test.go",
|
||||
"proposer_slashing_test.go",
|
||||
"randao_test.go",
|
||||
],
|
||||
|
||||
@@ -53,7 +53,7 @@ func ProcessAttesterSlashings(
|
||||
currentEpoch := helpers.SlotToEpoch(beaconState.Slot())
|
||||
var err error
|
||||
var slashedAny bool
|
||||
var val *stateTrie.ReadOnlyValidator
|
||||
var val stateTrie.ReadOnlyValidator
|
||||
for _, validatorIndex := range slashableIndices {
|
||||
val, err = beaconState.ValidatorAtIndexReadOnly(validatorIndex)
|
||||
if err != nil {
|
||||
|
||||
@@ -429,13 +429,13 @@ func TestFuzzProcessVoluntaryExitsNoVerify_10000(t *testing.T) {
|
||||
func TestFuzzVerifyExit_10000(t *testing.T) {
|
||||
fuzzer := fuzz.NewWithSeed(0)
|
||||
ve := ð.SignedVoluntaryExit{}
|
||||
val := &stateTrie.ReadOnlyValidator{}
|
||||
val := stateTrie.ReadOnlyValidator{}
|
||||
fork := &pb.Fork{}
|
||||
var slot uint64
|
||||
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(ve)
|
||||
fuzzer.Fuzz(val)
|
||||
fuzzer.Fuzz(&val)
|
||||
fuzzer.Fuzz(fork)
|
||||
fuzzer.Fuzz(&slot)
|
||||
err := VerifyExitAndSignature(val, slot, fork, ve, params.BeaconConfig().ZeroHash[:])
|
||||
|
||||
@@ -33,8 +33,10 @@ func ProcessPreGenesisDeposits(
|
||||
for _, deposit := range deposits {
|
||||
pubkey := deposit.Data.PublicKey
|
||||
index, ok := beaconState.ValidatorIndexByPubkey(bytesutil.ToBytes48(pubkey))
|
||||
// In the event of the pubkey not existing, we continue processing the other
|
||||
// deposits.
|
||||
if !ok {
|
||||
return beaconState, nil
|
||||
continue
|
||||
}
|
||||
balance, err := beaconState.BalanceAtIndex(index)
|
||||
if err != nil {
|
||||
|
||||
@@ -272,3 +272,71 @@ func TestProcessDeposit_SkipsInvalidDeposit(t *testing.T) {
|
||||
t.Errorf("Expected validator balance at index 0 to stay 0, received: %v", newState.Balances()[0])
|
||||
}
|
||||
}
|
||||
|
||||
func TestPreGenesisDeposits_SkipInvalidDeposit(t *testing.T) {
|
||||
testutil.ResetCache()
|
||||
dep, _, err := testutil.DeterministicDepositsAndKeys(100)
|
||||
require.NoError(t, err)
|
||||
defer func() {
|
||||
testutil.ResetCache()
|
||||
}()
|
||||
dep[0].Data.Signature = make([]byte, 96)
|
||||
trie, _, err := testutil.DepositTrieFromDeposits(dep)
|
||||
require.NoError(t, err)
|
||||
|
||||
for i := range dep {
|
||||
proof, err := trie.MerkleProof(i)
|
||||
require.NoError(t, err)
|
||||
dep[i].Proof = proof
|
||||
}
|
||||
root := trie.Root()
|
||||
eth1Data := ðpb.Eth1Data{
|
||||
DepositRoot: root[:],
|
||||
DepositCount: 1,
|
||||
}
|
||||
registry := []*ethpb.Validator{
|
||||
{
|
||||
PublicKey: []byte{1},
|
||||
WithdrawalCredentials: []byte{1, 2, 3},
|
||||
},
|
||||
}
|
||||
balances := []uint64{0}
|
||||
beaconState, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
||||
Validators: registry,
|
||||
Balances: balances,
|
||||
Eth1Data: eth1Data,
|
||||
Fork: &pb.Fork{
|
||||
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
|
||||
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
newState, err := blocks.ProcessPreGenesisDeposits(context.Background(), beaconState, dep)
|
||||
require.NoError(t, err, "Expected invalid block deposit to be ignored without error")
|
||||
|
||||
_, ok := newState.ValidatorIndexByPubkey(bytesutil.ToBytes48(dep[0].Data.PublicKey))
|
||||
require.Equal(t, false, ok, "bad pubkey should not exist in state")
|
||||
|
||||
for i := 1; i < newState.NumValidators(); i++ {
|
||||
val, err := newState.ValidatorAtIndex(uint64(i))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, params.BeaconConfig().MaxEffectiveBalance, val.EffectiveBalance, "unequal effective balance")
|
||||
require.Equal(t, uint64(0), val.ActivationEpoch)
|
||||
require.Equal(t, uint64(0), val.ActivationEligibilityEpoch)
|
||||
}
|
||||
if newState.Eth1DepositIndex() != 100 {
|
||||
t.Errorf(
|
||||
"Expected Eth1DepositIndex to be increased by 99 after processing an invalid deposit, received change: %v",
|
||||
newState.Eth1DepositIndex(),
|
||||
)
|
||||
}
|
||||
if len(newState.Validators()) != 100 {
|
||||
t.Errorf("Expected validator list to have length 100, received: %v", len(newState.Validators()))
|
||||
}
|
||||
if len(newState.Balances()) != 100 {
|
||||
t.Errorf("Expected validator balances list to have length 100, received: %v", len(newState.Balances()))
|
||||
}
|
||||
if newState.Balances()[0] != 0 {
|
||||
t.Errorf("Expected validator balance at index 0 to stay 0, received: %v", newState.Balances()[0])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
)
|
||||
|
||||
// ValidatorAlreadyExitedMsg defines a message saying that a validator has already exited.
|
||||
var ValidatorAlreadyExitedMsg = "validator has already submitted an exit, which will take place at epoch"
|
||||
var ValidatorAlreadyExitedMsg = "has already submitted an exit, which will take place at epoch"
|
||||
|
||||
// ValidatorCannotExitYetMsg defines a message saying that a validator cannot exit
|
||||
// because it has not been active long enough.
|
||||
@@ -125,7 +125,7 @@ func ProcessVoluntaryExitsNoVerifySignature(
|
||||
// # Verify signature
|
||||
// domain = get_domain(state, DOMAIN_VOLUNTARY_EXIT, exit.epoch)
|
||||
// assert bls_verify(validator.pubkey, signing_root(exit), exit.signature, domain)
|
||||
func VerifyExitAndSignature(validator *stateTrie.ReadOnlyValidator, currentSlot uint64, fork *pb.Fork, signed *ethpb.SignedVoluntaryExit, genesisRoot []byte) error {
|
||||
func VerifyExitAndSignature(validator stateTrie.ReadOnlyValidator, currentSlot uint64, fork *pb.Fork, signed *ethpb.SignedVoluntaryExit, genesisRoot []byte) error {
|
||||
if signed == nil || signed.Exit == nil {
|
||||
return errors.New("nil exit")
|
||||
}
|
||||
@@ -161,7 +161,7 @@ func VerifyExitAndSignature(validator *stateTrie.ReadOnlyValidator, currentSlot
|
||||
// assert get_current_epoch(state) >= exit.epoch
|
||||
// # Verify the validator has been active long enough
|
||||
// assert get_current_epoch(state) >= validator.activation_epoch + SHARD_COMMITTEE_PERIOD
|
||||
func verifyExitConditions(validator *stateTrie.ReadOnlyValidator, currentSlot uint64, exit *ethpb.VoluntaryExit) error {
|
||||
func verifyExitConditions(validator stateTrie.ReadOnlyValidator, currentSlot uint64, exit *ethpb.VoluntaryExit) error {
|
||||
currentEpoch := helpers.SlotToEpoch(currentSlot)
|
||||
// Verify the validator is active.
|
||||
if !helpers.IsActiveValidatorUsingTrie(validator, currentEpoch) {
|
||||
@@ -169,7 +169,7 @@ func verifyExitConditions(validator *stateTrie.ReadOnlyValidator, currentSlot ui
|
||||
}
|
||||
// Verify the validator has not yet submitted an exit.
|
||||
if validator.ExitEpoch() != params.BeaconConfig().FarFutureEpoch {
|
||||
return fmt.Errorf("%s: %v", ValidatorAlreadyExitedMsg, validator.ExitEpoch())
|
||||
return fmt.Errorf("validator with index %d %s: %v", exit.ValidatorIndex, ValidatorAlreadyExitedMsg, validator.ExitEpoch())
|
||||
}
|
||||
// Exits must specify an epoch when they become valid; they are not valid before then.
|
||||
if currentEpoch < exit.Epoch {
|
||||
|
||||
@@ -139,7 +139,7 @@ func TestProcessVoluntaryExits_ExitAlreadySubmitted(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
want := "validator has already submitted an exit, which will take place at epoch: 10"
|
||||
want := "validator with index 0 has already submitted an exit, which will take place at epoch: 10"
|
||||
_, err = blocks.ProcessVoluntaryExits(context.Background(), state, b)
|
||||
assert.ErrorContains(t, want, err)
|
||||
}
|
||||
|
||||
@@ -4,13 +4,14 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/pkg/errors"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
v "github.com/prysmaticlabs/prysm/beacon-chain/core/validators"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
|
||||
// ProcessProposerSlashings is one of the operations performed
|
||||
@@ -86,7 +87,7 @@ func VerifyProposerSlashing(
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !helpers.IsSlashableValidatorUsingTrie(proposer, helpers.SlotToEpoch(hSlot)) {
|
||||
if !helpers.IsSlashableValidatorUsingTrie(proposer, helpers.CurrentEpoch(beaconState)) {
|
||||
return fmt.Errorf("validator with key %#x is not slashable", proposer.PublicKey())
|
||||
}
|
||||
headers := []*ethpb.SignedBeaconBlockHeader{slashing.Header_1, slashing.Header_2}
|
||||
@@ -96,6 +97,5 @@ func VerifyProposerSlashing(
|
||||
return errors.Wrap(err, "could not verify beacon block header")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package blocks_test
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
)
|
||||
|
||||
// Beaconfuzz discovered an issue where a proposer slashing could be produced which would pass
|
||||
// validation where we use the slashing's slot instead of the current epoch of our state for validation.
|
||||
// This would lead to us accepting an invalid slashing by marking the respective validator as 'slashable'
|
||||
// when it was not in actuality.
|
||||
// See: https://github.com/sigp/beacon-fuzz/issues/91
|
||||
func TestVerifyProposerSlashing_BeaconFuzzIssue91(t *testing.T) {
|
||||
file, err := ioutil.ReadFile("testdata/beaconfuzz_91_beacon.ssz")
|
||||
require.NoError(t, err)
|
||||
rawState := &pb.BeaconState{}
|
||||
err = rawState.UnmarshalSSZ(file)
|
||||
require.NoError(t, err)
|
||||
|
||||
st, err := stateTrie.InitializeFromProtoUnsafe(rawState)
|
||||
require.NoError(t, err)
|
||||
|
||||
file, err = ioutil.ReadFile("testdata/beaconfuzz_91_proposer_slashing.ssz")
|
||||
require.NoError(t, err)
|
||||
slashing := ðpb.ProposerSlashing{}
|
||||
err = slashing.UnmarshalSSZ(file)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = blocks.VerifyProposerSlashing(st, slashing)
|
||||
require.ErrorContains(t, "validator with key 0x97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb is not slashable", err)
|
||||
}
|
||||
@@ -86,7 +86,7 @@ func TestRandaoSignatureSet_OK(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
set, _, err := blocks.RandaoSignatureSet(beaconState, block.Body)
|
||||
set, err := blocks.RandaoSignatureSet(beaconState, block.Body)
|
||||
require.NoError(t, err)
|
||||
verified, err := set.Verify()
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -92,16 +92,16 @@ func BlockSignatureSet(beaconState *stateTrie.BeaconState, block *ethpb.SignedBe
|
||||
// from a block and its corresponding state.
|
||||
func RandaoSignatureSet(beaconState *stateTrie.BeaconState,
|
||||
body *ethpb.BeaconBlockBody,
|
||||
) (*bls.SignatureSet, *stateTrie.BeaconState, error) {
|
||||
) (*bls.SignatureSet, error) {
|
||||
buf, proposerPub, domain, err := randaoSigningData(beaconState)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
set, err := retrieveSignatureSet(buf, proposerPub, body.RandaoReveal, domain)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
return set, beaconState, nil
|
||||
return set, nil
|
||||
}
|
||||
|
||||
// retrieves the randao related signing data from the state.
|
||||
|
||||
BIN
beacon-chain/core/blocks/testdata/beaconfuzz_91_beacon.ssz
vendored
Normal file
BIN
beacon-chain/core/blocks/testdata/beaconfuzz_91_beacon.ssz
vendored
Normal file
Binary file not shown.
BIN
beacon-chain/core/blocks/testdata/beaconfuzz_91_proposer_slashing.ssz
vendored
Normal file
BIN
beacon-chain/core/blocks/testdata/beaconfuzz_91_proposer_slashing.ssz
vendored
Normal file
Binary file not shown.
@@ -366,7 +366,7 @@ func UnslashedAttestingIndices(state *stateTrie.BeaconState, atts []*pb.PendingA
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to look up validator")
|
||||
}
|
||||
if v != nil && v.Slashed() {
|
||||
if !v.IsNil() && v.Slashed() {
|
||||
setIndices = append(setIndices[:i], setIndices[i+1:]...)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,9 +196,9 @@ func TestProcessSlashings_SlashedLess(t *testing.T) {
|
||||
Balances: []uint64{params.BeaconConfig().MaxEffectiveBalance, params.BeaconConfig().MaxEffectiveBalance},
|
||||
Slashings: []uint64{0, 1e9},
|
||||
},
|
||||
// penalty = validator balance / increment * (3*total_penalties) / total_balance * increment
|
||||
// 3000000000 = (32 * 1e9) / (1 * 1e9) * (3*1e9) / (32*1e9) * (1 * 1e9)
|
||||
want: uint64(29000000000), // 32 * 1e9 - 3000000000
|
||||
// penalty = validator balance / increment * (2*total_penalties) / total_balance * increment
|
||||
// 1000000000 = (32 * 1e9) / (1 * 1e9) * (1*1e9) / (32*1e9) * (1 * 1e9)
|
||||
want: uint64(31000000000), // 32 * 1e9 - 1000000000
|
||||
},
|
||||
{
|
||||
state: &pb.BeaconState{
|
||||
@@ -212,9 +212,9 @@ func TestProcessSlashings_SlashedLess(t *testing.T) {
|
||||
Balances: []uint64{params.BeaconConfig().MaxEffectiveBalance, params.BeaconConfig().MaxEffectiveBalance},
|
||||
Slashings: []uint64{0, 1e9},
|
||||
},
|
||||
// penalty = validator balance / increment * (3*total_penalties) / total_balance * increment
|
||||
// 1000000000 = (32 * 1e9) / (1 * 1e9) * (3*1e9) / (64*1e9) * (1 * 1e9)
|
||||
want: uint64(31000000000), // 32 * 1e9 - 1000000000
|
||||
// penalty = validator balance / increment * (2*total_penalties) / total_balance * increment
|
||||
// 500000000 = (32 * 1e9) / (1 * 1e9) * (1*1e9) / (32*1e9) * (1 * 1e9)
|
||||
want: uint64(32000000000), // 32 * 1e9 - 500000000
|
||||
},
|
||||
{
|
||||
state: &pb.BeaconState{
|
||||
@@ -229,8 +229,8 @@ func TestProcessSlashings_SlashedLess(t *testing.T) {
|
||||
Slashings: []uint64{0, 2 * 1e9},
|
||||
},
|
||||
// penalty = validator balance / increment * (3*total_penalties) / total_balance * increment
|
||||
// 3000000000 = (32 * 1e9) / (1 * 1e9) * (3*2e9) / (64*1e9) * (1 * 1e9)
|
||||
want: uint64(29000000000), // 32 * 1e9 - 3000000000
|
||||
// 1000000000 = (32 * 1e9) / (1 * 1e9) * (1*2e9) / (64*1e9) * (1 * 1e9)
|
||||
want: uint64(31000000000), // 32 * 1e9 - 1000000000
|
||||
},
|
||||
{
|
||||
state: &pb.BeaconState{
|
||||
@@ -243,8 +243,8 @@ func TestProcessSlashings_SlashedLess(t *testing.T) {
|
||||
Slashings: []uint64{0, 1e9},
|
||||
},
|
||||
// penalty = validator balance / increment * (3*total_penalties) / total_balance * increment
|
||||
// 3000000000 = (32 * 1e9 - 1*1e9) / (1 * 1e9) * (3*1e9) / (31*1e9) * (1 * 1e9)
|
||||
want: uint64(28000000000), // 31 * 1e9 - 3000000000
|
||||
// 2000000000 = (32 * 1e9 - 1*1e9) / (1 * 1e9) * (2*1e9) / (31*1e9) * (1 * 1e9)
|
||||
want: uint64(30000000000), // 32 * 1e9 - 2000000000
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ func New(ctx context.Context, state *stateTrie.BeaconState) ([]*Validator, *Bala
|
||||
currentEpoch := helpers.CurrentEpoch(state)
|
||||
prevEpoch := helpers.PrevEpoch(state)
|
||||
|
||||
if err := state.ReadFromEveryValidator(func(idx int, val *stateTrie.ReadOnlyValidator) error {
|
||||
if err := state.ReadFromEveryValidator(func(idx int, val stateTrie.ReadOnlyValidator) error {
|
||||
// Was validator withdrawable or slashed
|
||||
withdrawable := prevEpoch+1 >= val.WithdrawableEpoch()
|
||||
pVal := &Validator{
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package precompute
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
@@ -26,18 +24,17 @@ func ProcessSlashingsPrecompute(state *stateTrie.BeaconState, pBal *Balance) err
|
||||
minSlashing := mathutil.Min(totalSlashing*params.BeaconConfig().ProportionalSlashingMultiplier, pBal.ActiveCurrentEpoch)
|
||||
epochToWithdraw := currentEpoch + exitLength/2
|
||||
|
||||
vs := state.ValidatorsReadOnly()
|
||||
var hasSlashing bool
|
||||
// Iterate through validator list in state, stop until a validator satisfies slashing condition of current epoch.
|
||||
for _, v := range vs {
|
||||
if v == nil {
|
||||
return errors.New("nil validator in state")
|
||||
}
|
||||
correctEpoch := epochToWithdraw == v.WithdrawableEpoch()
|
||||
if v.Slashed() && correctEpoch {
|
||||
err := state.ReadFromEveryValidator(func(idx int, val stateTrie.ReadOnlyValidator) error {
|
||||
correctEpoch := epochToWithdraw == val.WithdrawableEpoch()
|
||||
if val.Slashed() && correctEpoch {
|
||||
hasSlashing = true
|
||||
break
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Exit early if there's no meaningful slashing to process.
|
||||
if !hasSlashing {
|
||||
|
||||
@@ -58,9 +58,9 @@ func TestProcessSlashingsPrecompute_SlashedLess(t *testing.T) {
|
||||
Balances: []uint64{params.BeaconConfig().MaxEffectiveBalance, params.BeaconConfig().MaxEffectiveBalance},
|
||||
Slashings: []uint64{0, 1e9},
|
||||
},
|
||||
// penalty = validator balance / increment * (3*total_penalties) / total_balance * increment
|
||||
// 3000000000 = (32 * 1e9) / (1 * 1e9) * (3*1e9) / (32*1e9) * (1 * 1e9)
|
||||
want: uint64(29000000000), // 32 * 1e9 - 3000000000
|
||||
// penalty = validator balance / increment * (2*total_penalties) / total_balance * increment
|
||||
// 1000000000 = (32 * 1e9) / (1 * 1e9) * (1*1e9) / (32*1e9) * (1 * 1e9)
|
||||
want: uint64(31000000000), // 32 * 1e9 - 1000000000
|
||||
},
|
||||
{
|
||||
state: &pb.BeaconState{
|
||||
@@ -74,9 +74,9 @@ func TestProcessSlashingsPrecompute_SlashedLess(t *testing.T) {
|
||||
Balances: []uint64{params.BeaconConfig().MaxEffectiveBalance, params.BeaconConfig().MaxEffectiveBalance, params.BeaconConfig().MaxEffectiveBalance},
|
||||
Slashings: []uint64{0, 1e9},
|
||||
},
|
||||
// penalty = validator balance / increment * (3*total_penalties) / total_balance * increment
|
||||
// 1000000000 = (32 * 1e9) / (1 * 1e9) * (3*1e9) / (64*1e9) * (1 * 1e9)
|
||||
want: uint64(31000000000), // 32 * 1e9 - 1000000000
|
||||
// penalty = validator balance / increment * (2*total_penalties) / total_balance * increment
|
||||
// 500000000 = (32 * 1e9) / (1 * 1e9) * (1*1e9) / (32*1e9) * (1 * 1e9)
|
||||
want: uint64(32000000000), // 32 * 1e9 - 500000000
|
||||
},
|
||||
{
|
||||
state: &pb.BeaconState{
|
||||
@@ -91,8 +91,8 @@ func TestProcessSlashingsPrecompute_SlashedLess(t *testing.T) {
|
||||
Slashings: []uint64{0, 2 * 1e9},
|
||||
},
|
||||
// penalty = validator balance / increment * (3*total_penalties) / total_balance * increment
|
||||
// 3000000000 = (32 * 1e9) / (1 * 1e9) * (3*2e9) / (64*1e9) * (1 * 1e9)
|
||||
want: uint64(29000000000), // 32 * 1e9 - 3000000000
|
||||
// 1000000000 = (32 * 1e9) / (1 * 1e9) * (1*2e9) / (64*1e9) * (1 * 1e9)
|
||||
want: uint64(31000000000), // 32 * 1e9 - 1000000000
|
||||
},
|
||||
{
|
||||
state: &pb.BeaconState{
|
||||
@@ -105,8 +105,8 @@ func TestProcessSlashingsPrecompute_SlashedLess(t *testing.T) {
|
||||
Slashings: []uint64{0, 1e9},
|
||||
},
|
||||
// penalty = validator balance / increment * (3*total_penalties) / total_balance * increment
|
||||
// 3000000000 = (32 * 1e9 - 1*1e9) / (1 * 1e9) * (3*1e9) / (31*1e9) * (1 * 1e9)
|
||||
want: uint64(28000000000), // 31 * 1e9 - 3000000000
|
||||
// 2000000000 = (32 * 1e9 - 1*1e9) / (1 * 1e9) * (2*1e9) / (31*1e9) * (1 * 1e9)
|
||||
want: uint64(30000000000), // 32 * 1e9 - 2000000000
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -31,15 +31,15 @@ go_test(
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/params/spectest:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"//shared/params/spectest:go_default_library",
|
||||
"//shared/testutil:go_default_library",
|
||||
"//shared/testutil/require:go_default_library",
|
||||
"@com_github_ghodss_yaml//:go_default_library",
|
||||
"@com_github_gogo_protobuf//proto:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
|
||||
"@in_gopkg_d4l3k_messagediff_v1//:go_default_library",
|
||||
"@io_bazel_rules_go//go/tools/bazel:go_default_library",
|
||||
"@com_github_ghodss_yaml//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -65,14 +65,14 @@ go_test(
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/params/spectest:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"//shared/params/spectest:go_default_library",
|
||||
"//shared/testutil:go_default_library",
|
||||
"//shared/testutil/require:go_default_library",
|
||||
"@com_github_ghodss_yaml//:go_default_library",
|
||||
"@com_github_gogo_protobuf//proto:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
|
||||
"@in_gopkg_d4l3k_messagediff_v1//:go_default_library",
|
||||
"@io_bazel_rules_go//go/tools/bazel:go_default_library",
|
||||
"@com_github_ghodss_yaml//:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -30,8 +30,8 @@ go_test(
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/params/spectest:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"//shared/params/spectest:go_default_library",
|
||||
"//shared/testutil:go_default_library",
|
||||
"//shared/testutil/require:go_default_library",
|
||||
"@com_github_gogo_protobuf//proto:go_default_library",
|
||||
@@ -63,8 +63,8 @@ go_test(
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/params/spectest:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"//shared/params/spectest:go_default_library",
|
||||
"//shared/testutil:go_default_library",
|
||||
"//shared/testutil/require:go_default_library",
|
||||
"@com_github_gogo_protobuf//proto:go_default_library",
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package spectest
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
@@ -9,11 +8,10 @@ import (
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
prevConfig := params.BeaconConfig().Copy()
|
||||
defer params.OverrideBeaconConfig(prevConfig)
|
||||
c := params.BeaconConfig()
|
||||
c.MinGenesisActiveValidatorCount = 16384
|
||||
params.OverrideBeaconConfig(c)
|
||||
|
||||
retVal := m.Run()
|
||||
params.OverrideBeaconConfig(prevConfig)
|
||||
os.Exit(retVal)
|
||||
m.Run()
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
@@ -17,6 +19,9 @@ import (
|
||||
// assert slot < state.slot <= slot + SLOTS_PER_HISTORICAL_ROOT
|
||||
// return state.block_roots[slot % SLOTS_PER_HISTORICAL_ROOT]
|
||||
func BlockRootAtSlot(state *stateTrie.BeaconState, slot uint64) ([]byte, error) {
|
||||
if math.MaxUint64-slot < params.BeaconConfig().SlotsPerHistoricalRoot {
|
||||
return []byte{}, errors.New("slot overflows uint64")
|
||||
}
|
||||
if slot >= state.Slot() || state.Slot() > slot+params.BeaconConfig().SlotsPerHistoricalRoot {
|
||||
return []byte{}, errors.Errorf("slot %d out of bounds", slot)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package helpers_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
@@ -101,6 +102,11 @@ func TestBlockRootAtSlot_OutOfBounds(t *testing.T) {
|
||||
stateSlot: params.BeaconConfig().SlotsPerHistoricalRoot + 2,
|
||||
expectedErr: "slot 1 out of bounds",
|
||||
},
|
||||
{
|
||||
slot: math.MaxUint64 - 5,
|
||||
stateSlot: 0, // Doesn't matter
|
||||
expectedErr: "slot overflows uint64",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
state.Slot = tt.stateSlot
|
||||
|
||||
@@ -274,7 +274,7 @@ func ShuffledIndices(state *stateTrie.BeaconState, epoch uint64) ([]uint64, erro
|
||||
}
|
||||
|
||||
indices := make([]uint64, 0, state.NumValidators())
|
||||
if err := 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))
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ 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)
|
||||
if err := 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()
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ func IsActiveValidator(validator *ethpb.Validator, epoch uint64) bool {
|
||||
}
|
||||
|
||||
// IsActiveValidatorUsingTrie checks if a read only validator is active.
|
||||
func IsActiveValidatorUsingTrie(validator *stateTrie.ReadOnlyValidator, epoch uint64) bool {
|
||||
func IsActiveValidatorUsingTrie(validator stateTrie.ReadOnlyValidator, epoch uint64) bool {
|
||||
return checkValidatorActiveStatus(validator.ActivationEpoch(), validator.ExitEpoch(), epoch)
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ func IsSlashableValidator(activationEpoch, withdrawableEpoch uint64, slashed boo
|
||||
}
|
||||
|
||||
// IsSlashableValidatorUsingTrie checks if a read only validator is slashable.
|
||||
func IsSlashableValidatorUsingTrie(val *stateTrie.ReadOnlyValidator, epoch uint64) bool {
|
||||
func IsSlashableValidatorUsingTrie(val stateTrie.ReadOnlyValidator, epoch uint64) bool {
|
||||
return checkValidatorSlashable(val.ActivationEpoch(), val.WithdrawableEpoch(), val.Slashed(), epoch)
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ func ActiveValidatorIndices(state *stateTrie.BeaconState, epoch uint64) ([]uint6
|
||||
return activeIndices, nil
|
||||
}
|
||||
var indices []uint64
|
||||
if err := 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))
|
||||
}
|
||||
@@ -117,7 +117,7 @@ func ActiveValidatorCount(state *stateTrie.BeaconState, epoch uint64) (uint64, e
|
||||
}
|
||||
|
||||
count := uint64(0)
|
||||
if err := 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++
|
||||
}
|
||||
@@ -319,7 +319,7 @@ func IsEligibleForActivationQueue(validator *ethpb.Validator) bool {
|
||||
|
||||
// IsEligibleForActivationQueueUsingTrie checks if the read-only validator is eligible to
|
||||
// be placed into the activation queue.
|
||||
func IsEligibleForActivationQueueUsingTrie(validator *stateTrie.ReadOnlyValidator) bool {
|
||||
func IsEligibleForActivationQueueUsingTrie(validator stateTrie.ReadOnlyValidator) bool {
|
||||
return isEligibileForActivationQueue(validator.ActivationEligibilityEpoch(), validator.EffectiveBalance())
|
||||
}
|
||||
|
||||
@@ -348,7 +348,7 @@ func IsEligibleForActivation(state *stateTrie.BeaconState, validator *ethpb.Vali
|
||||
}
|
||||
|
||||
// IsEligibleForActivationUsingTrie checks if the validator is eligible for activation.
|
||||
func IsEligibleForActivationUsingTrie(state *stateTrie.BeaconState, validator *stateTrie.ReadOnlyValidator) bool {
|
||||
func IsEligibleForActivationUsingTrie(state *stateTrie.BeaconState, validator stateTrie.ReadOnlyValidator) bool {
|
||||
cpt := state.FinalizedCheckpoint()
|
||||
if cpt == nil {
|
||||
return false
|
||||
|
||||
@@ -16,19 +16,6 @@ import (
|
||||
|
||||
var runAmount = 25
|
||||
|
||||
func TestExecuteStateTransition_FullBlock(t *testing.T) {
|
||||
benchutil.SetBenchmarkConfig()
|
||||
beaconState, err := benchutil.PreGenState1Epoch()
|
||||
require.NoError(t, err)
|
||||
block, err := benchutil.PreGenFullBlock()
|
||||
require.NoError(t, err)
|
||||
|
||||
oldSlot := beaconState.Slot()
|
||||
beaconState, err = state.ExecuteStateTransition(context.Background(), beaconState, block)
|
||||
require.NoError(t, err, "Failed to process block, benchmarks will fail")
|
||||
require.NotEqual(t, oldSlot, beaconState.Slot(), "Expected slots to be different")
|
||||
}
|
||||
|
||||
func BenchmarkExecuteStateTransition_FullBlock(b *testing.B) {
|
||||
benchutil.SetBenchmarkConfig()
|
||||
beaconState, err := benchutil.PreGenState1Epoch()
|
||||
|
||||
@@ -15,6 +15,7 @@ go_library(
|
||||
deps = [
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//shared/featureconfig:go_default_library",
|
||||
"//shared/fileutil:go_default_library",
|
||||
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
],
|
||||
|
||||
@@ -2,12 +2,12 @@ package interop
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/fileutil"
|
||||
)
|
||||
|
||||
// WriteBlockToDisk as a block ssz. Writes to temp directory. Debug!
|
||||
@@ -27,7 +27,7 @@ func WriteBlockToDisk(block *ethpb.SignedBeaconBlock, failed bool) {
|
||||
log.WithError(err).Error("Failed to ssz encode block")
|
||||
return
|
||||
}
|
||||
if err := ioutil.WriteFile(fp, enc, 0664); err != nil {
|
||||
if err := fileutil.WriteFile(fp, enc); err != nil {
|
||||
log.WithError(err).Error("Failed to write to disk")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,12 @@ package interop
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/fileutil"
|
||||
)
|
||||
|
||||
// WriteStateToDisk as a state ssz. Writes to temp directory. Debug!
|
||||
@@ -22,7 +22,7 @@ func WriteStateToDisk(state *stateTrie.BeaconState) {
|
||||
log.WithError(err).Error("Failed to ssz encode state")
|
||||
return
|
||||
}
|
||||
if err := ioutil.WriteFile(fp, enc, 0664); err != nil {
|
||||
if err := fileutil.WriteFile(fp, enc); err != nil {
|
||||
log.WithError(err).Error("Failed to write to disk")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,8 +19,8 @@ go_test(
|
||||
name = "go_default_test",
|
||||
size = "small",
|
||||
srcs = ["validator_index_map_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
":go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/bytesutil:go_default_library",
|
||||
|
||||
@@ -415,7 +415,7 @@ func ProcessBlockNoVerifyAnySig(
|
||||
traceutil.AnnotateError(span, err)
|
||||
return nil, nil, errors.Wrap(err, "could not retrieve block signature set")
|
||||
}
|
||||
rSet, state, err := b.RandaoSignatureSet(state, signed.Block.Body)
|
||||
rSet, err := b.RandaoSignatureSet(state, signed.Block.Body)
|
||||
if err != nil {
|
||||
traceutil.AnnotateError(span, err)
|
||||
return nil, nil, errors.Wrap(err, "could not retrieve randao signature set")
|
||||
|
||||
@@ -45,7 +45,7 @@ func InitiateValidatorExit(state *stateTrie.BeaconState, idx uint64) (*stateTrie
|
||||
return state, nil
|
||||
}
|
||||
var exitEpochs []uint64
|
||||
err = state.ReadFromEveryValidator(func(idx int, val *stateTrie.ReadOnlyValidator) error {
|
||||
err = state.ReadFromEveryValidator(func(idx int, val stateTrie.ReadOnlyValidator) error {
|
||||
if val.ExitEpoch() != params.BeaconConfig().FarFutureEpoch {
|
||||
exitEpochs = append(exitEpochs, val.ExitEpoch())
|
||||
}
|
||||
@@ -66,7 +66,7 @@ func InitiateValidatorExit(state *stateTrie.BeaconState, idx uint64) (*stateTrie
|
||||
|
||||
// We use the exit queue churn to determine if we have passed a churn limit.
|
||||
exitQueueChurn := uint64(0)
|
||||
err = state.ReadFromEveryValidator(func(idx int, val *stateTrie.ReadOnlyValidator) error {
|
||||
err = state.ReadFromEveryValidator(func(idx int, val stateTrie.ReadOnlyValidator) error {
|
||||
if val.ExitEpoch() == exitQueueEpoch {
|
||||
exitQueueChurn++
|
||||
}
|
||||
|
||||
@@ -11,7 +11,8 @@ go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"alias.go",
|
||||
"http_backup_handler.go",
|
||||
"cmd.go",
|
||||
"restore.go",
|
||||
] + select({
|
||||
":kafka_disabled": [
|
||||
"db.go",
|
||||
@@ -30,7 +31,13 @@ go_library(
|
||||
"//beacon-chain/cache:go_default_library",
|
||||
"//beacon-chain/db/iface:go_default_library",
|
||||
"//beacon-chain/db/kv:go_default_library",
|
||||
"//shared/cmd:go_default_library",
|
||||
"//shared/fileutil:go_default_library",
|
||||
"//shared/promptutil:go_default_library",
|
||||
"//shared/tos:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@com_github_urfave_cli_v2//:go_default_library",
|
||||
] + select({
|
||||
"//conditions:default": [
|
||||
"//beacon-chain/db/kafka:go_default_library",
|
||||
|
||||
32
beacon-chain/db/cmd.go
Normal file
32
beacon-chain/db/cmd.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/shared/cmd"
|
||||
"github.com/prysmaticlabs/prysm/shared/tos"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// DatabaseCommands for Prysm beacon node.
|
||||
var DatabaseCommands = &cli.Command{
|
||||
Name: "db",
|
||||
Category: "db",
|
||||
Usage: "defines commands for interacting with eth2 beacon node database",
|
||||
Subcommands: []*cli.Command{
|
||||
{
|
||||
Name: "restore",
|
||||
Description: `restores a database from a backup file`,
|
||||
Flags: cmd.WrapFlags([]cli.Flag{
|
||||
cmd.RestoreSourceFileFlag,
|
||||
cmd.RestoreTargetDirFlag,
|
||||
}),
|
||||
Before: tos.VerifyTosAcceptedOrPrompt,
|
||||
Action: func(cliCtx *cli.Context) error {
|
||||
if err := restore(cliCtx); err != nil {
|
||||
logrus.Fatalf("Could not restore database: %v", err)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -11,6 +11,7 @@ go_library(
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//proto/beacon/db:go_default_library",
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/backuputil:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common:go_default_library",
|
||||
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
|
||||
],
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/proto/beacon/db"
|
||||
ethereum_beacon_p2p_v1 "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/backuputil"
|
||||
)
|
||||
|
||||
// ReadOnlyDatabase defines a struct which only has read access to database methods.
|
||||
@@ -84,6 +85,8 @@ type NoHeadAccessDatabase interface {
|
||||
|
||||
// Run any required database migrations.
|
||||
RunMigrations(ctx context.Context) error
|
||||
|
||||
CleanUpDirtyStates(ctx context.Context, slotsPerArchivedPoint uint64) error
|
||||
}
|
||||
|
||||
// HeadAccessDatabase defines a struct with access to reading chain head data.
|
||||
@@ -98,11 +101,9 @@ type HeadAccessDatabase interface {
|
||||
// Database interface with full access.
|
||||
type Database interface {
|
||||
io.Closer
|
||||
backuputil.BackupExporter
|
||||
HeadAccessDatabase
|
||||
|
||||
DatabasePath() string
|
||||
ClearDB() error
|
||||
|
||||
// Backup and restore methods
|
||||
Backup(ctx context.Context, outputDir string) error
|
||||
}
|
||||
|
||||
@@ -250,3 +250,8 @@ func (e Exporter) LastArchivedSlot(ctx context.Context) (uint64, error) {
|
||||
func (e Exporter) RunMigrations(ctx context.Context) error {
|
||||
return e.db.RunMigrations(ctx)
|
||||
}
|
||||
|
||||
// CleanUpDirtyStates -- passthrough
|
||||
func (e Exporter) CleanUpDirtyStates(ctx context.Context, slotsPerArchivedPoint uint64) error {
|
||||
return e.db.RunMigrations(ctx)
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package kv
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
@@ -40,7 +39,7 @@ func (s *Store) Backup(ctx context.Context, outputDir string) error {
|
||||
return errors.New("no head block")
|
||||
}
|
||||
// Ensure the backups directory exists.
|
||||
if err := os.MkdirAll(backupsDir, params.BeaconIoConfig().ReadWriteExecutePermissions); err != nil {
|
||||
if err := fileutil.MkdirAll(backupsDir); err != nil {
|
||||
return err
|
||||
}
|
||||
backupPath := path.Join(backupsDir, fmt.Sprintf("prysm_beacondb_at_slot_%07d.backup", head.Block.Slot))
|
||||
@@ -52,11 +51,11 @@ func (s *Store) Backup(ctx context.Context, outputDir string) error {
|
||||
&bolt.Options{Timeout: params.BeaconIoConfig().BoltTimeout},
|
||||
)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err := copyDB.Close(); err != nil {
|
||||
logrus.WithError(err).Error("Failed to close destination database")
|
||||
logrus.WithError(err).Error("Failed to close backup database")
|
||||
}
|
||||
}()
|
||||
|
||||
|
||||
@@ -3,7 +3,8 @@ package kv
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"path"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
@@ -26,7 +27,22 @@ func TestStore_Backup(t *testing.T) {
|
||||
|
||||
require.NoError(t, db.Backup(ctx, ""))
|
||||
|
||||
files, err := ioutil.ReadDir(path.Join(db.databasePath, backupsDirectoryName))
|
||||
backupsPath := filepath.Join(db.databasePath, backupsDirectoryName)
|
||||
files, err := ioutil.ReadDir(backupsPath)
|
||||
require.NoError(t, err)
|
||||
require.NotEqual(t, 0, len(files), "No backups created")
|
||||
require.NoError(t, db.Close(), "Failed to close database")
|
||||
|
||||
oldFilePath := filepath.Join(backupsPath, files[0].Name())
|
||||
newFilePath := filepath.Join(backupsPath, DatabaseFileName)
|
||||
// We rename the file to match the database file name
|
||||
// our NewKVStore function expects when opening a database.
|
||||
require.NoError(t, os.Rename(oldFilePath, newFilePath))
|
||||
|
||||
backedDB, err := NewKVStore(backupsPath, nil)
|
||||
require.NoError(t, err, "Failed to instantiate DB")
|
||||
t.Cleanup(func() {
|
||||
require.NoError(t, backedDB.Close(), "Failed to close database")
|
||||
})
|
||||
require.Equal(t, true, backedDB.HasState(ctx, root))
|
||||
}
|
||||
|
||||
@@ -106,15 +106,13 @@ func TestStore_BlocksHandleZeroCase(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
numBlocks := 10
|
||||
totalBlocks := make([]*ethpb.SignedBeaconBlock, numBlocks)
|
||||
blockRoots := make([][32]byte, 0)
|
||||
for i := 0; i < len(totalBlocks); i++ {
|
||||
b := testutil.NewBeaconBlock()
|
||||
b.Block.Slot = uint64(i)
|
||||
b.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32)
|
||||
totalBlocks[i] = b
|
||||
r, err := totalBlocks[i].Block.HashTreeRoot()
|
||||
_, err := totalBlocks[i].Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
blockRoots = append(blockRoots, r)
|
||||
}
|
||||
require.NoError(t, db.SaveBlocks(ctx, totalBlocks))
|
||||
zeroFilter := filters.NewFilter().SetStartSlot(0).SetEndSlot(0)
|
||||
@@ -128,16 +126,14 @@ func TestStore_BlocksHandleInvalidEndSlot(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
numBlocks := 10
|
||||
totalBlocks := make([]*ethpb.SignedBeaconBlock, numBlocks)
|
||||
blockRoots := make([][32]byte, 0)
|
||||
// Save blocks from slot 1 onwards.
|
||||
for i := 0; i < len(totalBlocks); i++ {
|
||||
b := testutil.NewBeaconBlock()
|
||||
b.Block.Slot = uint64(i) + 1
|
||||
b.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32)
|
||||
totalBlocks[i] = b
|
||||
r, err := totalBlocks[i].Block.HashTreeRoot()
|
||||
_, err := totalBlocks[i].Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
blockRoots = append(blockRoots, r)
|
||||
}
|
||||
require.NoError(t, db.SaveBlocks(ctx, totalBlocks))
|
||||
badFilter := filters.NewFilter().SetStartSlot(5).SetEndSlot(1)
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
prombolt "github.com/prysmaticlabs/prombbolt"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db/iface"
|
||||
"github.com/prysmaticlabs/prysm/shared/fileutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
bolt "go.etcd.io/bbolt"
|
||||
)
|
||||
@@ -23,9 +24,13 @@ const (
|
||||
// VotesCacheSize with 1M validators will be 8MB.
|
||||
VotesCacheSize = 1 << 23
|
||||
// NumOfVotes specifies the vote cache size.
|
||||
NumOfVotes = 1 << 20
|
||||
databaseFileName = "beaconchain.db"
|
||||
boltAllocSize = 8 * 1024 * 1024
|
||||
NumOfVotes = 1 << 20
|
||||
// BeaconNodeDbDirName is the name of the directory containing the beacon node database.
|
||||
BeaconNodeDbDirName = "beaconchaindata"
|
||||
// DatabaseFileName is the name of the beacon node database.
|
||||
DatabaseFileName = "beaconchain.db"
|
||||
|
||||
boltAllocSize = 8 * 1024 * 1024
|
||||
)
|
||||
|
||||
// BlockCacheSize specifies 1000 slots worth of blocks cached, which
|
||||
@@ -46,10 +51,16 @@ type Store struct {
|
||||
// path specified, creates the kv-buckets based on the schema, and stores
|
||||
// an open connection db object as a property of the Store struct.
|
||||
func NewKVStore(dirPath string, stateSummaryCache *cache.StateSummaryCache) (*Store, error) {
|
||||
if err := os.MkdirAll(dirPath, params.BeaconIoConfig().ReadWriteExecutePermissions); err != nil {
|
||||
hasDir, err := fileutil.HasDir(dirPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
datafile := path.Join(dirPath, databaseFileName)
|
||||
if !hasDir {
|
||||
if err := fileutil.MkdirAll(dirPath); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
datafile := path.Join(dirPath, DatabaseFileName)
|
||||
boltDB, err := bolt.Open(datafile, params.BeaconIoConfig().ReadWritePermissions, &bolt.Options{Timeout: 1 * time.Second, InitialMmapSize: 10e6})
|
||||
if err != nil {
|
||||
if errors.Is(err, bolt.ErrTimeout) {
|
||||
@@ -127,7 +138,7 @@ func (s *Store) ClearDB() error {
|
||||
return nil
|
||||
}
|
||||
prometheus.Unregister(createBoltCollector(s.db))
|
||||
if err := os.Remove(path.Join(s.databasePath, databaseFileName)); err != nil {
|
||||
if err := os.Remove(path.Join(s.databasePath, DatabaseFileName)); err != nil {
|
||||
return errors.Wrap(err, "could not remove database file")
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -1,29 +1,18 @@
|
||||
package kv
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"os"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
)
|
||||
|
||||
// setupDB instantiates and returns a Store instance.
|
||||
func setupDB(t testing.TB) *Store {
|
||||
randPath, err := rand.Int(rand.Reader, big.NewInt(1000000))
|
||||
require.NoError(t, err, "Could not generate random file path")
|
||||
p := path.Join(testutil.TempDir(), fmt.Sprintf("/%d", randPath))
|
||||
require.NoError(t, os.RemoveAll(p), "Failed to remove directory")
|
||||
db, err := NewKVStore(p, cache.NewStateSummaryCache())
|
||||
db, err := NewKVStore(t.TempDir(), cache.NewStateSummaryCache())
|
||||
require.NoError(t, err, "Failed to instantiate DB")
|
||||
t.Cleanup(func() {
|
||||
require.NoError(t, db.Close(), "Failed to close database")
|
||||
require.NoError(t, os.RemoveAll(db.DatabasePath()), "Failed to remove directory")
|
||||
})
|
||||
return db
|
||||
}
|
||||
|
||||
@@ -6,9 +6,11 @@ import (
|
||||
|
||||
"github.com/pkg/errors"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
log "github.com/sirupsen/logrus"
|
||||
bolt "go.etcd.io/bbolt"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
@@ -119,23 +121,6 @@ func (s *Store) HasState(ctx context.Context, blockRoot [32]byte) bool {
|
||||
func (s *Store) DeleteState(ctx context.Context, blockRoot [32]byte) error {
|
||||
ctx, span := trace.StartSpan(ctx, "BeaconDB.DeleteState")
|
||||
defer span.End()
|
||||
return s.DeleteStates(ctx, [][32]byte{blockRoot})
|
||||
}
|
||||
|
||||
// DeleteStates by block roots.
|
||||
//
|
||||
// Note: bkt.Delete(key) uses a binary search to find the item in the database. Iterating with a
|
||||
// cursor is faster when there are a large set of keys to delete. This method is O(n) deletion where
|
||||
// n is the number of keys in the database. The alternative of calling bkt.Delete on each key to
|
||||
// delete would be O(m*log(n)) which would be much slower given a large set of keys to delete.
|
||||
func (s *Store) DeleteStates(ctx context.Context, blockRoots [][32]byte) error {
|
||||
ctx, span := trace.StartSpan(ctx, "BeaconDB.DeleteStates")
|
||||
defer span.End()
|
||||
|
||||
rootMap := make(map[[32]byte]bool, len(blockRoots))
|
||||
for _, blockRoot := range blockRoots {
|
||||
rootMap[blockRoot] = true
|
||||
}
|
||||
|
||||
return s.db.Update(func(tx *bolt.Tx) error {
|
||||
bkt := tx.Bucket(blocksBucket)
|
||||
@@ -153,34 +138,38 @@ func (s *Store) DeleteStates(ctx context.Context, blockRoots [][32]byte) error {
|
||||
blockBkt := tx.Bucket(blocksBucket)
|
||||
headBlkRoot := blockBkt.Get(headBlockRootKey)
|
||||
bkt = tx.Bucket(stateBucket)
|
||||
c := bkt.Cursor()
|
||||
|
||||
for blockRoot, _ := c.First(); blockRoot != nil; blockRoot, _ = c.Next() {
|
||||
if !rootMap[bytesutil.ToBytes32(blockRoot)] {
|
||||
continue
|
||||
}
|
||||
// Safe guard against deleting genesis, finalized, head state.
|
||||
if bytes.Equal(blockRoot, checkpoint.Root) || bytes.Equal(blockRoot, genesisBlockRoot) || bytes.Equal(blockRoot, headBlkRoot) {
|
||||
return errors.New("cannot delete genesis, finalized, or head state")
|
||||
}
|
||||
|
||||
slot, err := slotByBlockRoot(ctx, tx, blockRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
indicesByBucket := createStateIndicesFromStateSlot(ctx, slot)
|
||||
if err := deleteValueForIndices(ctx, indicesByBucket, blockRoot, tx); err != nil {
|
||||
return errors.Wrap(err, "could not delete root for DB indices")
|
||||
}
|
||||
|
||||
if err := c.Delete(); err != nil {
|
||||
return err
|
||||
}
|
||||
// Safe guard against deleting genesis, finalized, head state.
|
||||
if bytes.Equal(blockRoot[:], checkpoint.Root) || bytes.Equal(blockRoot[:], genesisBlockRoot) || bytes.Equal(blockRoot[:], headBlkRoot) {
|
||||
return errors.New("cannot delete genesis, finalized, or head state")
|
||||
}
|
||||
return nil
|
||||
|
||||
slot, err := slotByBlockRoot(ctx, tx, blockRoot[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
indicesByBucket := createStateIndicesFromStateSlot(ctx, slot)
|
||||
if err := deleteValueForIndices(ctx, indicesByBucket, blockRoot[:], tx); err != nil {
|
||||
return errors.Wrap(err, "could not delete root for DB indices")
|
||||
}
|
||||
|
||||
return bkt.Delete(blockRoot[:])
|
||||
})
|
||||
}
|
||||
|
||||
// DeleteStates by block roots.
|
||||
func (s *Store) DeleteStates(ctx context.Context, blockRoots [][32]byte) error {
|
||||
ctx, span := trace.StartSpan(ctx, "BeaconDB.DeleteStates")
|
||||
defer span.End()
|
||||
|
||||
for _, r := range blockRoots {
|
||||
if err := s.DeleteState(ctx, r); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// creates state from marshaled proto state bytes.
|
||||
func createState(ctx context.Context, enc []byte) (*pb.BeaconState, error) {
|
||||
protoState := &pb.BeaconState{}
|
||||
@@ -318,3 +307,61 @@ func createStateIndicesFromStateSlot(ctx context.Context, slot uint64) map[strin
|
||||
}
|
||||
return indicesByBucket
|
||||
}
|
||||
|
||||
// CleanUpDirtyStates removes states in DB that falls to under archived point interval rules.
|
||||
// Only following states would be kept:
|
||||
// 1.) state_slot % archived_interval == 0. (e.g. archived_interval=2048, states with slot 2048, 4096... etc)
|
||||
// 2.) archived_interval - archived_interval/3 < state_slot % archived_interval
|
||||
// (e.g. archived_interval=2048, states with slots after 1365).
|
||||
// This is to tolerate skip slots. Not every state lays on the boundary.
|
||||
// 3.) state with current finalized root
|
||||
// 4.) unfinalized States
|
||||
func (s *Store) CleanUpDirtyStates(ctx context.Context, slotsPerArchivedPoint uint64) error {
|
||||
ctx, span := trace.StartSpan(ctx, "BeaconDB. CleanUpDirtyStates")
|
||||
defer span.End()
|
||||
|
||||
f, err := s.FinalizedCheckpoint(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
finalizedSlot, err := helpers.StartSlot(f.Epoch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
deletedRoots := make([][32]byte, 0)
|
||||
|
||||
err = s.db.View(func(tx *bolt.Tx) error {
|
||||
bkt := tx.Bucket(stateSlotIndicesBucket)
|
||||
return bkt.ForEach(func(k, v []byte) error {
|
||||
if ctx.Err() != nil {
|
||||
return ctx.Err()
|
||||
}
|
||||
|
||||
finalizedChkpt := bytesutil.ToBytes32(f.Root) == bytesutil.ToBytes32(v)
|
||||
slot := bytesutil.BytesToUint64BigEndian(k)
|
||||
mod := slot % slotsPerArchivedPoint
|
||||
nonFinalized := slot > finalizedSlot
|
||||
|
||||
// The following conditions cover 1, 2, 3 and 4 above.
|
||||
if mod != 0 && mod <= slotsPerArchivedPoint-slotsPerArchivedPoint/3 && !finalizedChkpt && !nonFinalized {
|
||||
deletedRoots = append(deletedRoots, bytesutil.ToBytes32(v))
|
||||
}
|
||||
return nil
|
||||
})
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Length of to be deleted roots is 0. Nothing to do.
|
||||
if len(deletedRoots) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
log.WithField("count", len(deletedRoots)).Info("Cleaning up dirty states")
|
||||
if err := s.DeleteStates(ctx, deletedRoots); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
@@ -226,3 +227,96 @@ func TestStore_GenesisState_CanGetHighestBelow(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, true, proto.Equal(highest[0].InnerStateUnsafe(), genesisState.InnerStateUnsafe()))
|
||||
}
|
||||
|
||||
func TestStore_CleanUpDirtyStates_AboveThreshold(t *testing.T) {
|
||||
db := setupDB(t)
|
||||
|
||||
genesisState := testutil.NewBeaconState()
|
||||
genesisRoot := [32]byte{'a'}
|
||||
require.NoError(t, db.SaveGenesisBlockRoot(context.Background(), genesisRoot))
|
||||
require.NoError(t, db.SaveState(context.Background(), genesisState, genesisRoot))
|
||||
|
||||
bRoots := make([][32]byte, 0)
|
||||
slotsPerArchivedPoint := uint64(128)
|
||||
prevRoot := genesisRoot
|
||||
for i := uint64(1); i <= slotsPerArchivedPoint; i++ {
|
||||
b := testutil.NewBeaconBlock()
|
||||
b.Block.Slot = i
|
||||
b.Block.ParentRoot = prevRoot[:]
|
||||
r, err := b.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, db.SaveBlock(context.Background(), b))
|
||||
bRoots = append(bRoots, r)
|
||||
prevRoot = r
|
||||
|
||||
st := testutil.NewBeaconState()
|
||||
require.NoError(t, st.SetSlot(i))
|
||||
require.NoError(t, db.SaveState(context.Background(), st, r))
|
||||
}
|
||||
|
||||
require.NoError(t, db.SaveFinalizedCheckpoint(context.Background(), ðpb.Checkpoint{Root: bRoots[len(bRoots)-1][:], Epoch: slotsPerArchivedPoint / params.BeaconConfig().SlotsPerEpoch}))
|
||||
require.NoError(t, db.CleanUpDirtyStates(context.Background(), slotsPerArchivedPoint))
|
||||
|
||||
for i, root := range bRoots {
|
||||
if uint64(i) >= slotsPerArchivedPoint-slotsPerArchivedPoint/3 {
|
||||
require.Equal(t, true, db.HasState(context.Background(), root))
|
||||
} else {
|
||||
require.Equal(t, false, db.HasState(context.Background(), root))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestStore_CleanUpDirtyStates_Finalized(t *testing.T) {
|
||||
db := setupDB(t)
|
||||
|
||||
genesisState := testutil.NewBeaconState()
|
||||
genesisRoot := [32]byte{'a'}
|
||||
require.NoError(t, db.SaveGenesisBlockRoot(context.Background(), genesisRoot))
|
||||
require.NoError(t, db.SaveState(context.Background(), genesisState, genesisRoot))
|
||||
|
||||
for i := uint64(1); i <= params.BeaconConfig().SlotsPerEpoch; i++ {
|
||||
b := testutil.NewBeaconBlock()
|
||||
b.Block.Slot = i
|
||||
r, err := b.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, db.SaveBlock(context.Background(), b))
|
||||
|
||||
st := testutil.NewBeaconState()
|
||||
require.NoError(t, st.SetSlot(i))
|
||||
require.NoError(t, db.SaveState(context.Background(), st, r))
|
||||
}
|
||||
|
||||
require.NoError(t, db.SaveFinalizedCheckpoint(context.Background(), ðpb.Checkpoint{Root: genesisRoot[:]}))
|
||||
require.NoError(t, db.CleanUpDirtyStates(context.Background(), params.BeaconConfig().SlotsPerEpoch))
|
||||
require.Equal(t, true, db.HasState(context.Background(), genesisRoot))
|
||||
}
|
||||
|
||||
func TestStore_CleanUpDirtyStates_DontDeleteNonFinalized(t *testing.T) {
|
||||
db := setupDB(t)
|
||||
|
||||
genesisState := testutil.NewBeaconState()
|
||||
genesisRoot := [32]byte{'a'}
|
||||
require.NoError(t, db.SaveGenesisBlockRoot(context.Background(), genesisRoot))
|
||||
require.NoError(t, db.SaveState(context.Background(), genesisState, genesisRoot))
|
||||
|
||||
unfinalizedRoots := [][32]byte{}
|
||||
for i := uint64(1); i <= params.BeaconConfig().SlotsPerEpoch; i++ {
|
||||
b := testutil.NewBeaconBlock()
|
||||
b.Block.Slot = i
|
||||
r, err := b.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, db.SaveBlock(context.Background(), b))
|
||||
unfinalizedRoots = append(unfinalizedRoots, r)
|
||||
|
||||
st := testutil.NewBeaconState()
|
||||
require.NoError(t, st.SetSlot(i))
|
||||
require.NoError(t, db.SaveState(context.Background(), st, r))
|
||||
}
|
||||
|
||||
require.NoError(t, db.SaveFinalizedCheckpoint(context.Background(), ðpb.Checkpoint{Root: genesisRoot[:]}))
|
||||
require.NoError(t, db.CleanUpDirtyStates(context.Background(), params.BeaconConfig().SlotsPerEpoch))
|
||||
|
||||
for _, rt := range unfinalizedRoots {
|
||||
require.Equal(t, true, db.HasState(context.Background(), rt))
|
||||
}
|
||||
}
|
||||
|
||||
46
beacon-chain/db/restore.go
Normal file
46
beacon-chain/db/restore.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db/kv"
|
||||
"github.com/prysmaticlabs/prysm/shared/cmd"
|
||||
"github.com/prysmaticlabs/prysm/shared/fileutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/promptutil"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
const dbExistsYesNoPrompt = "A database file already exists in the target directory. " +
|
||||
"Are you sure that you want to overwrite it? [y/n]"
|
||||
|
||||
func restore(cliCtx *cli.Context) error {
|
||||
sourceFile := cliCtx.String(cmd.RestoreSourceFileFlag.Name)
|
||||
targetDir := cliCtx.String(cmd.RestoreTargetDirFlag.Name)
|
||||
|
||||
restoreDir := path.Join(targetDir, kv.BeaconNodeDbDirName)
|
||||
if fileutil.FileExists(path.Join(restoreDir, kv.DatabaseFileName)) {
|
||||
resp, err := promptutil.ValidatePrompt(
|
||||
os.Stdin, dbExistsYesNoPrompt, promptutil.ValidateYesOrNo,
|
||||
)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not validate choice")
|
||||
}
|
||||
if strings.ToLower(resp) == "n" {
|
||||
logrus.Info("Restore aborted")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if err := fileutil.MkdirAll(restoreDir); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := fileutil.CopyFile(sourceFile, path.Join(restoreDir, kv.DatabaseFileName)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
logrus.Info("Restore completed successfully")
|
||||
return nil
|
||||
}
|
||||
71
beacon-chain/db/restore_test.go
Normal file
71
beacon-chain/db/restore_test.go
Normal file
@@ -0,0 +1,71 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db/kv"
|
||||
"github.com/prysmaticlabs/prysm/shared/cmd"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
logTest "github.com/sirupsen/logrus/hooks/test"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func TestRestore(t *testing.T) {
|
||||
logHook := logTest.NewGlobal()
|
||||
ctx := context.Background()
|
||||
|
||||
backupDb, err := kv.NewKVStore(t.TempDir(), cache.NewStateSummaryCache())
|
||||
defer func() {
|
||||
require.NoError(t, backupDb.Close())
|
||||
}()
|
||||
require.NoError(t, err)
|
||||
head := testutil.NewBeaconBlock()
|
||||
head.Block.Slot = 5000
|
||||
require.NoError(t, backupDb.SaveBlock(ctx, head))
|
||||
root, err := head.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
st := testutil.NewBeaconState()
|
||||
require.NoError(t, backupDb.SaveState(ctx, st, root))
|
||||
require.NoError(t, backupDb.SaveHeadBlockRoot(ctx, root))
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, backupDb.Close())
|
||||
// We rename the backup file so that we can later verify
|
||||
// whether the restored db has been renamed correctly.
|
||||
require.NoError(t, os.Rename(
|
||||
path.Join(backupDb.DatabasePath(), kv.DatabaseFileName),
|
||||
path.Join(backupDb.DatabasePath(), "backup.db")))
|
||||
|
||||
restoreDir := t.TempDir()
|
||||
app := cli.App{}
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.String(cmd.RestoreSourceFileFlag.Name, "", "")
|
||||
set.String(cmd.RestoreTargetDirFlag.Name, "", "")
|
||||
require.NoError(t, set.Set(cmd.RestoreSourceFileFlag.Name, path.Join(backupDb.DatabasePath(), "backup.db")))
|
||||
require.NoError(t, set.Set(cmd.RestoreTargetDirFlag.Name, restoreDir))
|
||||
cliCtx := cli.NewContext(&app, set, nil)
|
||||
|
||||
assert.NoError(t, restore(cliCtx))
|
||||
|
||||
files, err := ioutil.ReadDir(path.Join(restoreDir, kv.BeaconNodeDbDirName))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, len(files))
|
||||
assert.Equal(t, kv.DatabaseFileName, files[0].Name())
|
||||
restoredDb, err := kv.NewKVStore(path.Join(restoreDir, kv.BeaconNodeDbDirName), nil)
|
||||
defer func() {
|
||||
require.NoError(t, restoredDb.Close())
|
||||
}()
|
||||
require.NoError(t, err)
|
||||
headBlock, err := restoredDb.HeadBlock(ctx)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, uint64(5000), headBlock.Block.Slot, "Restored database has incorrect data")
|
||||
assert.LogsContain(t, logHook, "Restore completed successfully")
|
||||
|
||||
}
|
||||
@@ -10,7 +10,5 @@ go_library(
|
||||
"//beacon-chain/cache:go_default_library",
|
||||
"//beacon-chain/db:go_default_library",
|
||||
"//beacon-chain/db/kv:go_default_library",
|
||||
"//shared/rand:go_default_library",
|
||||
"//shared/testutil:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -3,27 +3,17 @@
|
||||
package testing
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db/kv"
|
||||
"github.com/prysmaticlabs/prysm/shared/rand"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
)
|
||||
|
||||
// SetupDB instantiates and returns database backed by key value store.
|
||||
func SetupDB(t testing.TB) (db.Database, *cache.StateSummaryCache) {
|
||||
randPath := rand.NewDeterministicGenerator().Int()
|
||||
p := path.Join(testutil.TempDir(), fmt.Sprintf("/%d", randPath))
|
||||
if err := os.RemoveAll(p); err != nil {
|
||||
t.Fatalf("failed to remove directory: %v", err)
|
||||
}
|
||||
sc := cache.NewStateSummaryCache()
|
||||
s, err := kv.NewKVStore(p, sc)
|
||||
s, err := kv.NewKVStore(t.TempDir(), sc)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -31,9 +21,6 @@ func SetupDB(t testing.TB) (db.Database, *cache.StateSummaryCache) {
|
||||
if err := s.Close(); err != nil {
|
||||
t.Fatalf("failed to close database: %v", err)
|
||||
}
|
||||
if err := os.RemoveAll(s.DatabasePath()); err != nil {
|
||||
t.Fatalf("could not remove tmp db dir: %v", err)
|
||||
}
|
||||
})
|
||||
return s, sc
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ go_library(
|
||||
visibility = ["//beacon-chain:__subpackages__"],
|
||||
deps = [
|
||||
"//shared/cmd:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@com_github_urfave_cli_v2//:go_default_library",
|
||||
],
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
package flags
|
||||
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
@@ -10,14 +11,17 @@ var (
|
||||
// HTTPWeb3ProviderFlag provides an HTTP access endpoint to an ETH 1.0 RPC.
|
||||
HTTPWeb3ProviderFlag = &cli.StringFlag{
|
||||
Name: "http-web3provider",
|
||||
Usage: "A mainchain web3 provider string http endpoint",
|
||||
Value: "",
|
||||
Usage: "A mainchain web3 provider string http endpoint. This is our primary web3 provider",
|
||||
}
|
||||
FallbackWeb3ProviderFlag = &cli.StringSliceFlag{
|
||||
Name: "fallback-web3provider",
|
||||
Usage: "A mainchain web3 provider string http endpoint. This is our fallback web3 provider, this flag maybe used multiple times.",
|
||||
}
|
||||
// DepositContractFlag defines a flag for the deposit contract address.
|
||||
DepositContractFlag = &cli.StringFlag{
|
||||
Name: "deposit-contract",
|
||||
Usage: "Deposit contract address. Beacon chain node will listen logs coming from the deposit contract to determine when validator is eligible to participate.",
|
||||
Value: "0x07b39F4fDE4A38bACe212b546dAc87C58DfE3fDC", // Medalla deposit contract address.
|
||||
Value: params.BeaconNetworkConfig().DepositContractAddress,
|
||||
}
|
||||
// RPCHost defines the host on which the RPC server should listen.
|
||||
RPCHost = &cli.StringFlag{
|
||||
@@ -69,7 +73,7 @@ var (
|
||||
Name: "grpc-gateway-corsdomain",
|
||||
Usage: "Comma separated list of domains from which to accept cross origin requests " +
|
||||
"(browser enforced). This flag has no effect if not used with --grpc-gateway-port.",
|
||||
Value: "http://localhost:4242,http://127.0.0.1:4242,http://localhost:4200",
|
||||
Value: "http://localhost:4200,http://localhost:7500,http://127.0.0.1:4200,http://127.0.0.1:7500,http://0.0.0.0:4200,http://0.0.0.0:7500",
|
||||
}
|
||||
// MinSyncPeers specifies the required number of successful peer handshakes in order
|
||||
// to start syncing with external peers.
|
||||
@@ -82,7 +86,7 @@ var (
|
||||
ContractDeploymentBlock = &cli.IntFlag{
|
||||
Name: "contract-deployment-block",
|
||||
Usage: "The eth1 block in which the deposit contract was deployed.",
|
||||
Value: 2844925,
|
||||
Value: 11184524,
|
||||
}
|
||||
// SetGCPercent is the percentage of current live allocations at which the garbage collector is to run.
|
||||
SetGCPercent = &cli.IntFlag{
|
||||
@@ -130,6 +134,10 @@ var (
|
||||
Name: "enable-debug-rpc-endpoints",
|
||||
Usage: "Enables the debug rpc service, containing utility endpoints such as /eth/v1alpha1/beacon/state.",
|
||||
}
|
||||
SubscribeToAllSubnets = &cli.BoolFlag{
|
||||
Name: "subscribe-all-subnets",
|
||||
Usage: "Subscribe to all possible attestation subnets.",
|
||||
}
|
||||
// HistoricalSlasherNode is a set of beacon node flags required for performing historical detection with a slasher.
|
||||
HistoricalSlasherNode = &cli.BoolFlag{
|
||||
Name: "historical-slasher-node",
|
||||
@@ -152,14 +160,10 @@ var (
|
||||
"If such a sync is not possible, the node will treat it a critical and irrecoverable failure",
|
||||
Value: "",
|
||||
}
|
||||
// EnableBackupWebhookFlag for users to trigger db backups via an HTTP webhook.
|
||||
EnableBackupWebhookFlag = &cli.BoolFlag{
|
||||
Name: "enable-db-backup-webhook",
|
||||
Usage: "Serve HTTP handler to initiate database backups. The handler is served on the monitoring port at path /db/backup.",
|
||||
}
|
||||
// BackupWebhookOutputDir to customize the output directory for db backups.
|
||||
BackupWebhookOutputDir = &cli.StringFlag{
|
||||
Name: "db-backup-output-dir",
|
||||
Usage: "Output directory for db backups",
|
||||
// Eth1HeaderReqLimit defines a flag to set the maximum number of headers that a deposit log query can fetch. If none is set, 1000 will be the limit.
|
||||
Eth1HeaderReqLimit = &cli.Uint64Flag{
|
||||
Name: "eth1-header-req-limit",
|
||||
Usage: "Sets the maximum number of headers that a deposit log query can fetch.",
|
||||
Value: uint64(1000),
|
||||
}
|
||||
)
|
||||
|
||||
@@ -12,6 +12,7 @@ type GlobalFlags struct {
|
||||
HeadSync bool
|
||||
DisableSync bool
|
||||
DisableDiscv5 bool
|
||||
SubscribeToAllSubnets bool
|
||||
MinimumSyncPeers int
|
||||
BlockBatchLimit int
|
||||
BlockBatchLimitBurstFactor int
|
||||
@@ -44,6 +45,10 @@ func ConfigureGlobalFlags(ctx *cli.Context) {
|
||||
log.Warn("Using Disable Sync flag, using this flag on a live network might lead to adverse consequences.")
|
||||
cfg.DisableSync = true
|
||||
}
|
||||
if ctx.Bool(SubscribeToAllSubnets.Name) {
|
||||
log.Warn("Subscribing to All Attestation Subnets")
|
||||
cfg.SubscribeToAllSubnets = true
|
||||
}
|
||||
cfg.DisableDiscv5 = ctx.Bool(DisableDiscv5.Name)
|
||||
cfg.BlockBatchLimit = ctx.Int(BlockBatchLimit.Name)
|
||||
cfg.BlockBatchLimitBurstFactor = ctx.Int(BlockBatchLimitBurstFactor.Name)
|
||||
|
||||
@@ -62,6 +62,7 @@ func (g *Gateway) Start() {
|
||||
ethpb.RegisterNodeHandler,
|
||||
ethpb.RegisterBeaconChainHandler,
|
||||
ethpb.RegisterBeaconNodeValidatorHandler,
|
||||
pbrpc.RegisterHealthHandler,
|
||||
}
|
||||
if g.enableDebugRPCEndpoints {
|
||||
handlers = append(handlers, pbrpc.RegisterDebugHandler)
|
||||
|
||||
@@ -25,23 +25,10 @@ go_binary(
|
||||
|
||||
go_image(
|
||||
name = "image",
|
||||
srcs = [
|
||||
"main.go",
|
||||
],
|
||||
base = "//tools:go_image",
|
||||
goarch = "amd64",
|
||||
goos = "linux",
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/gateway/server",
|
||||
race = "off",
|
||||
binary = ":server",
|
||||
tags = ["manual"],
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
"//beacon-chain/gateway:go_default_library",
|
||||
"@com_github_grpc_ecosystem_grpc_gateway//runtime:go_default_library",
|
||||
"@com_github_joonix_log//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"//shared/maxprocs:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
container_bundle(
|
||||
|
||||
@@ -97,7 +97,11 @@ func NewService(ctx context.Context, cfg *Config) *Service {
|
||||
// Generated genesis time; fetch it
|
||||
s.genesisTime = genesisTrie.GenesisTime()
|
||||
}
|
||||
go slotutil.CountdownToGenesis(ctx, time.Unix(int64(s.genesisTime), 0), s.numValidators)
|
||||
gRoot, err := genesisTrie.HashTreeRoot(s.ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not hash tree root genesis state: %v", err)
|
||||
}
|
||||
go slotutil.CountdownToGenesis(ctx, time.Unix(int64(s.genesisTime), 0), s.numValidators, gRoot)
|
||||
|
||||
if err := s.saveGenesisState(ctx, genesisTrie); err != nil {
|
||||
log.Fatalf("Could not save interop genesis state %v", err)
|
||||
@@ -203,12 +207,8 @@ func (s *Service) saveGenesisState(ctx context.Context, genesisState *stateTrie.
|
||||
return errors.Wrap(err, "could not save finalized checkpoint")
|
||||
}
|
||||
|
||||
pubKeys := make([][48]byte, 0, genesisState.NumValidators())
|
||||
indices := make([]uint64, 0, genesisState.NumValidators())
|
||||
for i := uint64(0); i < uint64(genesisState.NumValidators()); i++ {
|
||||
pk := genesisState.PubkeyAtIndex(i)
|
||||
pubKeys = append(pubKeys, pk)
|
||||
indices = append(indices, i)
|
||||
s.chainStartDeposits[i] = ðpb.Deposit{
|
||||
Data: ðpb.Deposit_Data{
|
||||
PublicKey: pk[:],
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
gethlog "github.com/ethereum/go-ethereum/log"
|
||||
golog "github.com/ipfs/go-log/v2"
|
||||
joonix "github.com/joonix/log"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/flags"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/node"
|
||||
"github.com/prysmaticlabs/prysm/shared/cmd"
|
||||
@@ -28,6 +29,7 @@ import (
|
||||
var appFlags = []cli.Flag{
|
||||
flags.DepositContractFlag,
|
||||
flags.HTTPWeb3ProviderFlag,
|
||||
flags.FallbackWeb3ProviderFlag,
|
||||
flags.RPCHost,
|
||||
flags.RPCPort,
|
||||
flags.CertFlag,
|
||||
@@ -50,12 +52,14 @@ var appFlags = []cli.Flag{
|
||||
flags.InteropGenesisTimeFlag,
|
||||
flags.SlotsPerArchivedPoint,
|
||||
flags.EnableDebugRPCEndpoints,
|
||||
flags.EnableBackupWebhookFlag,
|
||||
flags.BackupWebhookOutputDir,
|
||||
flags.SubscribeToAllSubnets,
|
||||
flags.HistoricalSlasherNode,
|
||||
flags.ChainID,
|
||||
flags.NetworkID,
|
||||
flags.WeakSubjectivityCheckpt,
|
||||
flags.Eth1HeaderReqLimit,
|
||||
cmd.EnableBackupWebhookFlag,
|
||||
cmd.BackupWebhookOutputDir,
|
||||
cmd.MinimalConfigFlag,
|
||||
cmd.E2EConfigFlag,
|
||||
cmd.RPCMaxPageSizeFlag,
|
||||
@@ -98,6 +102,8 @@ var appFlags = []cli.Flag{
|
||||
cmd.ChainConfigFileFlag,
|
||||
cmd.GrpcMaxCallRecvMsgSizeFlag,
|
||||
cmd.AcceptTosFlag,
|
||||
cmd.RestoreSourceFileFlag,
|
||||
cmd.RestoreTargetDirFlag,
|
||||
}
|
||||
|
||||
func init() {
|
||||
@@ -111,6 +117,9 @@ func main() {
|
||||
app.Usage = "this is a beacon chain implementation for Ethereum 2.0"
|
||||
app.Action = startNode
|
||||
app.Version = version.GetVersion()
|
||||
app.Commands = []*cli.Command{
|
||||
db.DatabaseCommands,
|
||||
}
|
||||
|
||||
app.Flags = appFlags
|
||||
|
||||
@@ -152,11 +161,12 @@ func main() {
|
||||
log.WithError(err).Error("Failed to configuring logging to disk.")
|
||||
}
|
||||
}
|
||||
|
||||
if err := cmd.ExpandWeb3EndpointIfFile(ctx, flags.HTTPWeb3ProviderFlag); err != nil {
|
||||
if err := cmd.ExpandSingleEndpointIfFile(ctx, flags.HTTPWeb3ProviderFlag); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.ExpandWeb3EndpointsIfFile(ctx, flags.FallbackWeb3ProviderFlag); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if ctx.IsSet(flags.SetGCPercent.Name) {
|
||||
runtimeDebug.SetGCPercent(ctx.Int(flags.SetGCPercent.Name))
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ go_library(
|
||||
"//beacon-chain/cache:go_default_library",
|
||||
"//beacon-chain/cache/depositcache:go_default_library",
|
||||
"//beacon-chain/db:go_default_library",
|
||||
"//beacon-chain/db/kv:go_default_library",
|
||||
"//beacon-chain/flags:go_default_library",
|
||||
"//beacon-chain/forkchoice:go_default_library",
|
||||
"//beacon-chain/forkchoice/protoarray:go_default_library",
|
||||
@@ -29,6 +30,7 @@ go_library(
|
||||
"//beacon-chain/sync:go_default_library",
|
||||
"//beacon-chain/sync/initial-sync:go_default_library",
|
||||
"//shared:go_default_library",
|
||||
"//shared/backuputil:go_default_library",
|
||||
"//shared/cmd:go_default_library",
|
||||
"//shared/debug:go_default_library",
|
||||
"//shared/event:go_default_library",
|
||||
@@ -58,7 +60,6 @@ go_test(
|
||||
deps = [
|
||||
"//beacon-chain/core/feed/state:go_default_library",
|
||||
"//shared/cmd:go_default_library",
|
||||
"//shared/testutil:go_default_library",
|
||||
"//shared/testutil/assert:go_default_library",
|
||||
"//shared/testutil/require:go_default_library",
|
||||
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db/kv"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/flags"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
|
||||
@@ -36,6 +37,7 @@ import (
|
||||
regularsync "github.com/prysmaticlabs/prysm/beacon-chain/sync"
|
||||
initialsync "github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync"
|
||||
"github.com/prysmaticlabs/prysm/shared"
|
||||
"github.com/prysmaticlabs/prysm/shared/backuputil"
|
||||
"github.com/prysmaticlabs/prysm/shared/cmd"
|
||||
"github.com/prysmaticlabs/prysm/shared/debug"
|
||||
"github.com/prysmaticlabs/prysm/shared/event"
|
||||
@@ -53,7 +55,6 @@ import (
|
||||
|
||||
var log = logrus.WithField("prefix", "node")
|
||||
|
||||
const beaconChainDBName = "beaconchaindata"
|
||||
const testSkipPowFlag = "test-skip-pow"
|
||||
|
||||
// BeaconNode defines a struct that handles the services running a random beacon chain
|
||||
@@ -290,7 +291,7 @@ func (b *BeaconNode) startForkChoice() {
|
||||
|
||||
func (b *BeaconNode) startDB(cliCtx *cli.Context) error {
|
||||
baseDir := cliCtx.String(cmd.DataDirFlag.Name)
|
||||
dbPath := filepath.Join(baseDir, beaconChainDBName)
|
||||
dbPath := filepath.Join(baseDir, kv.BeaconNodeDbDirName)
|
||||
clearDB := cliCtx.Bool(cmd.ClearDB.Name)
|
||||
forceClearDB := cliCtx.Bool(cmd.ForceClearDB.Name)
|
||||
|
||||
@@ -484,14 +485,17 @@ func (b *BeaconNode) registerPOWChainService() error {
|
||||
log.Error("No ETH1 node specified to run with the beacon node. Please consider running your own ETH1 node for better uptime, security, and decentralization of ETH2. Visit https://docs.prylabs.network/docs/prysm-usage/setup-eth1 for more information.")
|
||||
log.Error("You will need to specify --http-web3provider to attach an eth1 node to the prysm node. Without an eth1 node block proposals for your validator will be affected and the beacon node will not be able to initialize the genesis state.")
|
||||
}
|
||||
endpoints := []string{b.cliCtx.String(flags.HTTPWeb3ProviderFlag.Name)}
|
||||
endpoints = append(endpoints, b.cliCtx.StringSlice(flags.FallbackWeb3ProviderFlag.Name)...)
|
||||
|
||||
cfg := &powchain.Web3ServiceConfig{
|
||||
HTTPEndPoint: b.cliCtx.String(flags.HTTPWeb3ProviderFlag.Name),
|
||||
DepositContract: common.HexToAddress(depAddress),
|
||||
BeaconDB: b.db,
|
||||
DepositCache: b.depositCache,
|
||||
StateNotifier: b,
|
||||
StateGen: b.stateGen,
|
||||
HTTPEndpoints: endpoints,
|
||||
DepositContract: common.HexToAddress(depAddress),
|
||||
BeaconDB: b.db,
|
||||
DepositCache: b.depositCache,
|
||||
StateNotifier: b,
|
||||
StateGen: b.stateGen,
|
||||
Eth1HeaderReqLimit: b.cliCtx.Uint64(flags.Eth1HeaderReqLimit.Name),
|
||||
}
|
||||
web3Service, err := powchain.NewService(b.ctx, cfg)
|
||||
if err != nil {
|
||||
@@ -507,7 +511,10 @@ func (b *BeaconNode) registerPOWChainService() error {
|
||||
}
|
||||
}
|
||||
if len(knownContract) > 0 && !bytes.Equal(cfg.DepositContract.Bytes(), knownContract) {
|
||||
return fmt.Errorf("database contract is %#x but tried to run with %#x", knownContract, cfg.DepositContract.Bytes())
|
||||
return fmt.Errorf("database contract is %#x but tried to run with %#x. This likely means "+
|
||||
"you are trying to run on a different network than what the database contains. You can run once with "+
|
||||
"'--clear-db' to wipe the old database or use an alternative data directory with '--datadir'",
|
||||
knownContract, cfg.DepositContract.Bytes())
|
||||
}
|
||||
|
||||
log.Infof("Deposit contract: %#x", cfg.DepositContract.Bytes())
|
||||
@@ -598,14 +605,19 @@ func (b *BeaconNode) registerRPCService() error {
|
||||
|
||||
host := b.cliCtx.String(flags.RPCHost.Name)
|
||||
port := b.cliCtx.String(flags.RPCPort.Name)
|
||||
beaconMonitoringHost := b.cliCtx.String(cmd.MonitoringHostFlag.Name)
|
||||
beaconMonitoringPort := b.cliCtx.Int(flags.MonitoringPortFlag.Name)
|
||||
cert := b.cliCtx.String(flags.CertFlag.Name)
|
||||
key := b.cliCtx.String(flags.KeyFlag.Name)
|
||||
mockEth1DataVotes := b.cliCtx.Bool(flags.InteropMockEth1DataVotesFlag.Name)
|
||||
enableDebugRPCEndpoints := b.cliCtx.Bool(flags.EnableDebugRPCEndpoints.Name)
|
||||
maxMsgSize := b.cliCtx.Int(cmd.GrpcMaxCallRecvMsgSizeFlag.Name)
|
||||
p2pService := b.fetchP2P()
|
||||
rpcService := rpc.NewService(b.ctx, &rpc.Config{
|
||||
Host: host,
|
||||
Port: port,
|
||||
BeaconMonitoringHost: beaconMonitoringHost,
|
||||
BeaconMonitoringPort: beaconMonitoringPort,
|
||||
CertFlag: cert,
|
||||
KeyFlag: key,
|
||||
BeaconDB: b.db,
|
||||
@@ -634,6 +646,7 @@ func (b *BeaconNode) registerRPCService() error {
|
||||
OperationNotifier: b,
|
||||
StateGen: b.stateGen,
|
||||
EnableDebugRPCEndpoints: enableDebugRPCEndpoints,
|
||||
MaxMsgSize: maxMsgSize,
|
||||
})
|
||||
|
||||
return b.services.RegisterService(rpcService)
|
||||
@@ -652,12 +665,12 @@ func (b *BeaconNode) registerPrometheusService(cliCtx *cli.Context) error {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if cliCtx.IsSet(flags.EnableBackupWebhookFlag.Name) {
|
||||
if cliCtx.IsSet(cmd.EnableBackupWebhookFlag.Name) {
|
||||
additionalHandlers = append(
|
||||
additionalHandlers,
|
||||
prometheus.Handler{
|
||||
Path: "/db/backup",
|
||||
Handler: db.BackupHandler(b.db, cliCtx.String(flags.BackupWebhookOutputDir.Name)),
|
||||
Handler: backuputil.BackupHandler(b.db, cliCtx.String(cmd.BackupWebhookOutputDir.Name)),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math/big"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
|
||||
"github.com/prysmaticlabs/prysm/shared/cmd"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
logTest "github.com/sirupsen/logrus/hooks/test"
|
||||
@@ -26,8 +23,7 @@ var _ statefeed.Notifier = (*BeaconNode)(nil)
|
||||
func TestNodeClose_OK(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
|
||||
tmp := fmt.Sprintf("%s/datadirtest2", testutil.TempDir())
|
||||
require.NoError(t, os.RemoveAll(tmp))
|
||||
tmp := fmt.Sprintf("%s/datadirtest2", t.TempDir())
|
||||
|
||||
app := cli.App{}
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
@@ -49,11 +45,8 @@ func TestNodeClose_OK(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBootStrapNodeFile(t *testing.T) {
|
||||
file, err := ioutil.TempFile(testutil.TempDir(), "bootstrapFile")
|
||||
file, err := ioutil.TempFile(t.TempDir(), "bootstrapFile")
|
||||
require.NoError(t, err)
|
||||
defer func() {
|
||||
assert.NoError(t, os.Remove(file.Name()))
|
||||
}()
|
||||
|
||||
sampleNode0 := "- enr:-Ku4QMKVC_MowDsmEa20d5uGjrChI0h8_KsKXDmgVQbIbngZV0i" +
|
||||
"dV6_RL7fEtZGo-kTNZ5o7_EJI_vCPJ6scrhwX0Z4Bh2F0dG5ldHOIAAAAAAAAAACEZXRoMpD" +
|
||||
@@ -74,10 +67,7 @@ func TestBootStrapNodeFile(t *testing.T) {
|
||||
func TestClearDB(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
|
||||
randPath, err := rand.Int(rand.Reader, big.NewInt(1000000))
|
||||
require.NoError(t, err, "Could not generate random number for file path")
|
||||
tmp := filepath.Join(testutil.TempDir(), fmt.Sprintf("datadirtest%d", randPath))
|
||||
require.NoError(t, os.RemoveAll(tmp))
|
||||
tmp := filepath.Join(t.TempDir(), "datadirtest")
|
||||
|
||||
app := cli.App{}
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
@@ -85,7 +75,7 @@ func TestClearDB(t *testing.T) {
|
||||
set.Bool(cmd.ForceClearDB.Name, true, "force clear db")
|
||||
|
||||
context := cli.NewContext(&app, set, nil)
|
||||
_, err = NewBeaconNode(context)
|
||||
_, err := NewBeaconNode(context)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.LogsContain(t, hook, "Removing database")
|
||||
|
||||
@@ -6,12 +6,6 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
numPendingAttesterSlashingFailedSigVerify = promauto.NewCounter(
|
||||
prometheus.CounterOpts{
|
||||
Name: "pending_attester_slashing_fail_sig_verify_total",
|
||||
Help: "Times an pending attester slashing fails sig verification",
|
||||
},
|
||||
)
|
||||
numPendingAttesterSlashings = promauto.NewGauge(
|
||||
prometheus.GaugeOpts{
|
||||
Name: "num_pending_attester_slashings",
|
||||
@@ -24,18 +18,6 @@ var (
|
||||
Help: "Number of attester slashings included in blocks",
|
||||
},
|
||||
)
|
||||
attesterSlashingReattempts = promauto.NewCounter(
|
||||
prometheus.CounterOpts{
|
||||
Name: "attester_slashing_reattempts_total",
|
||||
Help: "Times an attester slashing for an already slashed validator is received",
|
||||
},
|
||||
)
|
||||
numPendingProposerSlashingFailedSigVerify = promauto.NewCounter(
|
||||
prometheus.CounterOpts{
|
||||
Name: "pending_proposer_slashing_fail_sig_verify_total",
|
||||
Help: "Times an pending proposer slashing fails sig verification",
|
||||
},
|
||||
)
|
||||
numPendingProposerSlashings = promauto.NewGauge(
|
||||
prometheus.GaugeOpts{
|
||||
Name: "num_pending_proposer_slashings",
|
||||
@@ -48,10 +30,4 @@ var (
|
||||
Help: "Number of proposer slashings included in blocks",
|
||||
},
|
||||
)
|
||||
proposerSlashingReattempts = promauto.NewCounter(
|
||||
prometheus.CounterOpts{
|
||||
Name: "proposer_slashing_reattempts_total",
|
||||
Help: "Times a proposer slashing for an already slashed validator is received",
|
||||
},
|
||||
)
|
||||
)
|
||||
|
||||
@@ -124,7 +124,6 @@ func (p *Pool) InsertAttesterSlashing(
|
||||
defer span.End()
|
||||
|
||||
if err := blocks.VerifyAttesterSlashing(ctx, state, slashing); err != nil {
|
||||
numPendingAttesterSlashingFailedSigVerify.Inc()
|
||||
return errors.Wrap(err, "could not verify attester slashing")
|
||||
}
|
||||
|
||||
@@ -139,7 +138,6 @@ func (p *Pool) InsertAttesterSlashing(
|
||||
// If the validator has already exited, has already been slashed, or if its index
|
||||
// has been recently included in the pool of slashings, skip including this indice.
|
||||
if !ok {
|
||||
attesterSlashingReattempts.Inc()
|
||||
cantSlash = append(cantSlash, val)
|
||||
continue
|
||||
}
|
||||
@@ -150,7 +148,6 @@ func (p *Pool) InsertAttesterSlashing(
|
||||
return p.pendingAttesterSlashing[i].validatorToSlash >= val
|
||||
})
|
||||
if found != len(p.pendingAttesterSlashing) && p.pendingAttesterSlashing[found].validatorToSlash == val {
|
||||
attesterSlashingReattempts.Inc()
|
||||
cantSlash = append(cantSlash, val)
|
||||
continue
|
||||
}
|
||||
@@ -185,7 +182,6 @@ func (p *Pool) InsertProposerSlashing(
|
||||
defer span.End()
|
||||
|
||||
if err := blocks.VerifyProposerSlashing(state, slashing); err != nil {
|
||||
numPendingProposerSlashingFailedSigVerify.Inc()
|
||||
return errors.Wrap(err, "could not verify proposer slashing")
|
||||
}
|
||||
|
||||
@@ -198,7 +194,6 @@ func (p *Pool) InsertProposerSlashing(
|
||||
// has been recently included in the pool of slashings, do not process this new
|
||||
// slashing.
|
||||
if !ok {
|
||||
proposerSlashingReattempts.Inc()
|
||||
return fmt.Errorf("validator at index %d cannot be slashed", idx)
|
||||
}
|
||||
|
||||
|
||||
@@ -69,7 +69,6 @@ func TestPool_InsertAttesterSlashing(t *testing.T) {
|
||||
pending []*PendingAttesterSlashing
|
||||
included map[uint64]bool
|
||||
wantErr []bool
|
||||
err string
|
||||
}
|
||||
type args struct {
|
||||
slashings []*ethpb.AttesterSlashing
|
||||
|
||||
@@ -30,7 +30,6 @@ go_test(
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"//shared/testutil/assert:go_default_library",
|
||||
"//shared/testutil/require:go_default_library",
|
||||
"@com_github_gogo_protobuf//proto:go_default_library",
|
||||
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
|
||||
|
||||
@@ -12,20 +12,18 @@ import (
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
// Pool implements a struct to maintain pending and recently included voluntary exits. This pool
|
||||
// Pool implements a struct to maintain pending and seen voluntary exits. This pool
|
||||
// is used by proposers to insert into new blocks.
|
||||
type Pool struct {
|
||||
lock sync.RWMutex
|
||||
pending []*ethpb.SignedVoluntaryExit
|
||||
included map[uint64]bool
|
||||
lock sync.RWMutex
|
||||
pending []*ethpb.SignedVoluntaryExit
|
||||
}
|
||||
|
||||
// NewPool accepts a head fetcher (for reading the validator set) and returns an initialized
|
||||
// voluntary exit pool.
|
||||
func NewPool() *Pool {
|
||||
return &Pool{
|
||||
pending: make([]*ethpb.SignedVoluntaryExit, 0),
|
||||
included: make(map[uint64]bool),
|
||||
pending: make([]*ethpb.SignedVoluntaryExit, 0),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,48 +44,48 @@ func (p *Pool) PendingExits(state *beaconstate.BeaconState, slot uint64, noLimit
|
||||
if e.Exit.Epoch > helpers.SlotToEpoch(slot) {
|
||||
continue
|
||||
}
|
||||
if v, err := state.ValidatorAtIndexReadOnly(e.Exit.ValidatorIndex); err == nil && v.ExitEpoch() == params.BeaconConfig().FarFutureEpoch {
|
||||
if v, err := state.ValidatorAtIndexReadOnly(e.Exit.ValidatorIndex); err == nil &&
|
||||
v.ExitEpoch() == params.BeaconConfig().FarFutureEpoch {
|
||||
pending = append(pending, e)
|
||||
if uint64(len(pending)) == maxExits {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if uint64(len(pending)) > maxExits {
|
||||
pending = pending[:maxExits]
|
||||
}
|
||||
return pending
|
||||
}
|
||||
|
||||
// InsertVoluntaryExit into the pool. This method is a no-op if the pending exit already exists,
|
||||
// has been included recently, or the validator is already exited.
|
||||
// or the validator is already exited.
|
||||
func (p *Pool) InsertVoluntaryExit(ctx context.Context, state *beaconstate.BeaconState, exit *ethpb.SignedVoluntaryExit) {
|
||||
ctx, span := trace.StartSpan(ctx, "exitPool.InsertVoluntaryExit")
|
||||
defer span.End()
|
||||
|
||||
p.lock.Lock()
|
||||
defer p.lock.Unlock()
|
||||
|
||||
// Has this validator index been included recently?
|
||||
if p.included[exit.Exit.ValidatorIndex] {
|
||||
// Prevent malformed messages from being inserted.
|
||||
if exit == nil || exit.Exit == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Has the validator been exited already?
|
||||
if v, err := state.ValidatorAtIndexReadOnly(exit.Exit.ValidatorIndex); err != nil || v.ExitEpoch() != params.BeaconConfig().FarFutureEpoch {
|
||||
return
|
||||
}
|
||||
|
||||
// Does this validator exist in the list already? Use binary search to find the answer.
|
||||
if found := sort.Search(len(p.pending), func(i int) bool {
|
||||
e := p.pending[i].Exit
|
||||
return e.ValidatorIndex == exit.Exit.ValidatorIndex
|
||||
}); found != len(p.pending) {
|
||||
// If an exit exists with this validator index, prefer one with an earlier exit epoch.
|
||||
if p.pending[found].Exit.Epoch > exit.Exit.Epoch {
|
||||
p.pending[found] = exit
|
||||
existsInPending, index := existsInList(p.pending, exit.Exit.ValidatorIndex)
|
||||
// If the item exists in the pending list and includes a more favorable, earlier
|
||||
// exit epoch, we replace it in the pending list. If it exists but the prior condition is false,
|
||||
// we simply return.
|
||||
if existsInPending {
|
||||
if exit.Exit.Epoch < p.pending[index].Exit.Epoch {
|
||||
p.pending[index] = exit
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Insert into pending list and sort again.
|
||||
// Has the validator been exited already?
|
||||
if v, err := state.ValidatorAtIndexReadOnly(exit.Exit.ValidatorIndex); err != nil ||
|
||||
v.ExitEpoch() != params.BeaconConfig().FarFutureEpoch {
|
||||
return
|
||||
}
|
||||
|
||||
// Insert into pending list and sort.
|
||||
p.pending = append(p.pending, exit)
|
||||
sort.Slice(p.pending, func(i, j int) bool {
|
||||
return p.pending[i].Exit.ValidatorIndex < p.pending[j].Exit.ValidatorIndex
|
||||
@@ -95,22 +93,25 @@ func (p *Pool) InsertVoluntaryExit(ctx context.Context, state *beaconstate.Beaco
|
||||
}
|
||||
|
||||
// MarkIncluded is used when an exit has been included in a beacon block. Every block seen by this
|
||||
// node should call this method to include the exit.
|
||||
// node should call this method to include the exit. This will remove the exit from
|
||||
// the pending exits slice.
|
||||
func (p *Pool) MarkIncluded(exit *ethpb.SignedVoluntaryExit) {
|
||||
p.lock.Lock()
|
||||
defer p.lock.Unlock()
|
||||
i := sort.Search(len(p.pending), func(i int) bool {
|
||||
return p.pending[i].Exit.ValidatorIndex == exit.Exit.ValidatorIndex
|
||||
})
|
||||
if i != len(p.pending) {
|
||||
p.pending = append(p.pending[:i], p.pending[i+1:]...)
|
||||
exists, index := existsInList(p.pending, exit.Exit.ValidatorIndex)
|
||||
if exists {
|
||||
// Exit we want is present at p.pending[index], so we remove it.
|
||||
p.pending = append(p.pending[:index], p.pending[index+1:]...)
|
||||
}
|
||||
p.included[exit.Exit.ValidatorIndex] = true
|
||||
}
|
||||
|
||||
// HasBeenIncluded returns true if the pool has recorded that a validator index has been recorded.
|
||||
func (p *Pool) HasBeenIncluded(bIdx uint64) bool {
|
||||
p.lock.RLock()
|
||||
defer p.lock.RUnlock()
|
||||
return p.included[bIdx]
|
||||
// Binary search to check if the index exists in the list of pending exits.
|
||||
func existsInList(pending []*ethpb.SignedVoluntaryExit, searchingFor uint64) (bool, int) {
|
||||
i := sort.Search(len(pending), func(j int) bool {
|
||||
return pending[j].Exit.ValidatorIndex >= searchingFor
|
||||
})
|
||||
if i < len(pending) && pending[i].Exit.ValidatorIndex == searchingFor {
|
||||
return true, i
|
||||
}
|
||||
return false, -1
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user