mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-10 05:47:59 -05:00
Compare commits
128 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a069738c20 | ||
|
|
aef5a7b428 | ||
|
|
4bed8d4ed4 | ||
|
|
f4a6b90e8b | ||
|
|
36b6a71af4 | ||
|
|
7c3827a9a4 | ||
|
|
d17f210024 | ||
|
|
28631e7791 | ||
|
|
28839fbab2 | ||
|
|
0716519be9 | ||
|
|
068f758f49 | ||
|
|
e2c5ae53e7 | ||
|
|
473172ca8b | ||
|
|
47fdb3b99a | ||
|
|
143d3a3203 | ||
|
|
66471c2f13 | ||
|
|
7f6b15271a | ||
|
|
cbb0f1e11d | ||
|
|
25caa6d1be | ||
|
|
d551c8e1d0 | ||
|
|
2fd2bafdfa | ||
|
|
e236dedc32 | ||
|
|
7d2f7ae9e1 | ||
|
|
ed9c69ec61 | ||
|
|
b6a40094a6 | ||
|
|
de15d6d2c1 | ||
|
|
143cb142bc | ||
|
|
d3e93dd106 | ||
|
|
56c5938898 | ||
|
|
d44ab1ace5 | ||
|
|
ae028d9c1d | ||
|
|
cbd01d4ff4 | ||
|
|
65645face1 | ||
|
|
cd3851c3d5 | ||
|
|
2f98e6aaaf | ||
|
|
9afc9d92d9 | ||
|
|
a8e501b3cf | ||
|
|
5727d4eb8a | ||
|
|
fed65122fe | ||
|
|
86a9d4c6a4 | ||
|
|
0a180dc662 | ||
|
|
f9303ca2e4 | ||
|
|
4c25fe978a | ||
|
|
cf88afb287 | ||
|
|
c97ea766ca | ||
|
|
e52a821f73 | ||
|
|
d4f241d875 | ||
|
|
48ae49765e | ||
|
|
afa5b5e790 | ||
|
|
c5551ebebb | ||
|
|
616081fbdd | ||
|
|
842bafb002 | ||
|
|
953cc9733c | ||
|
|
caac08df33 | ||
|
|
3fd8c4c046 | ||
|
|
b5a82b9075 | ||
|
|
c6e96204e8 | ||
|
|
2456e6f34d | ||
|
|
48ed506487 | ||
|
|
4595789ac8 | ||
|
|
d53fdcf781 | ||
|
|
372dc47b64 | ||
|
|
82426abf5f | ||
|
|
f5f1284cef | ||
|
|
609418ecd3 | ||
|
|
f20c9122e8 | ||
|
|
afc3b3168a | ||
|
|
902c30e389 | ||
|
|
3aaa98decf | ||
|
|
e592cd7a80 | ||
|
|
b74dd967af | ||
|
|
d254f24a23 | ||
|
|
8d505e06bd | ||
|
|
09b1e06885 | ||
|
|
d9c451d547 | ||
|
|
e677b19d31 | ||
|
|
2bf03d5cba | ||
|
|
0753636159 | ||
|
|
b8037b0b50 | ||
|
|
2f063d0ddc | ||
|
|
1cfae7e098 | ||
|
|
91fe32a3d1 | ||
|
|
c0fda583e7 | ||
|
|
9f62405a81 | ||
|
|
d121b19145 | ||
|
|
a7345c1094 | ||
|
|
db79481c21 | ||
|
|
8d986bd414 | ||
|
|
c827672a30 | ||
|
|
d5ec248691 | ||
|
|
b2d6012371 | ||
|
|
d21365b882 | ||
|
|
1c43ea9e69 | ||
|
|
fc8dc21aa2 | ||
|
|
7f5ffb7dd1 | ||
|
|
92932ae58e | ||
|
|
8ffb95bd9d | ||
|
|
229abed848 | ||
|
|
c5e9b1ec9e | ||
|
|
7842fd9da6 | ||
|
|
75fc3b045b | ||
|
|
50e5b1b4f5 | ||
|
|
33e266388f | ||
|
|
2586be29ac | ||
|
|
9cc1438ea9 | ||
|
|
6e643aca12 | ||
|
|
cc5a847eeb | ||
|
|
241322a7c1 | ||
|
|
d697b0b2e5 | ||
|
|
9ec4f727c6 | ||
|
|
ffcadcf184 | ||
|
|
7c59615ae2 | ||
|
|
d6cccc18c3 | ||
|
|
befe8d88b8 | ||
|
|
153737803a | ||
|
|
4b14fa4317 | ||
|
|
27847ee2fe | ||
|
|
578dabe27c | ||
|
|
ed2c0a3e5e | ||
|
|
5d841874f7 | ||
|
|
ab9d596a5f | ||
|
|
084e5bd020 | ||
|
|
bc2c206832 | ||
|
|
655a7e98c3 | ||
|
|
f89fd67952 | ||
|
|
20b836d038 | ||
|
|
b33a8eb59f | ||
|
|
8b6abcbf0c |
11
.bazelrc
11
.bazelrc
@@ -17,9 +17,12 @@ test --host_force_python=PY2
|
||||
run --host_force_python=PY2
|
||||
|
||||
# Networking is blocked for tests by default, add "requires-network" tag to your test if networking
|
||||
# is required within the sandbox. This flag is no longer experimental after 0.29.0.
|
||||
# Network sandboxing only works on linux.
|
||||
--experimental_sandbox_default_allow_network=false
|
||||
# is required within the sandbox. Network sandboxing only works on linux.
|
||||
build --sandbox_default_allow_network=false
|
||||
|
||||
# Stamp binaries with git information
|
||||
build --workspace_status_command=./scripts/workspace_status.sh
|
||||
build --stamp
|
||||
|
||||
# Use mainnet protobufs at runtime
|
||||
run --define ssz=mainnet
|
||||
@@ -48,8 +51,6 @@ build:blst_enabled --define blst_enabled=true
|
||||
build:blst_enabled --define gotags=blst_enabled
|
||||
|
||||
# Release flags
|
||||
build:release --workspace_status_command=./scripts/workspace_status.sh
|
||||
build:release --stamp
|
||||
build:release --compilation_mode=opt
|
||||
build:release --config=llvm
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
[](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 specification, 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](https://ethereum.org/en/eth2/) specification, developed by [Prysmatic Labs](https://prysmaticlabs.com). See the [Changelog](https://github.com/prysmaticlabs/prysm/releases) for details of the latest releases and upcoming breaking changes.
|
||||
|
||||
### Getting Started
|
||||
|
||||
@@ -13,15 +13,15 @@ A detailed set of installation and usage instructions as well as breakdowns of e
|
||||
|
||||
### 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).
|
||||
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 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.
|
||||
* [master](https://github.com/prysmaticlabs/prysm/tree/master): This points to the latest stable release. It is ideal for most users.
|
||||
* [develop](https://github.com/prysmaticlabs/prysm/tree/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!
|
||||
|
||||
27
WORKSPACE
27
WORKSPACE
@@ -89,10 +89,10 @@ http_archive(
|
||||
# nogo check fails for certain third_party dependencies.
|
||||
"//third_party:io_bazel_rules_go.patch",
|
||||
],
|
||||
sha256 = "81eff5df9077783b18e93d0c7ff990d8ad7a3b8b3ca5b785e1c483aacdb342d7",
|
||||
sha256 = "dbf5a9ef855684f84cac2e7ae7886c5a001d4f66ae23f6904da0faaaef0d61fc",
|
||||
urls = [
|
||||
"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",
|
||||
"https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.24.11/rules_go-v0.24.11.tar.gz",
|
||||
"https://github.com/bazelbuild/rules_go/releases/download/v0.24.11/rules_go-v0.24.11.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -156,7 +156,7 @@ load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_depe
|
||||
go_rules_dependencies()
|
||||
|
||||
go_register_toolchains(
|
||||
go_version = "1.15.6",
|
||||
go_version = "1.15.7",
|
||||
nogo = "@//:nogo",
|
||||
)
|
||||
|
||||
@@ -210,6 +210,21 @@ http_archive(
|
||||
url = "https://github.com/kubernetes/repo-infra/archive/6537f2101fb432b679f3d103ee729dd8ac5d30a0.tar.gz",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "eip3076_spec_tests",
|
||||
build_file_content = """
|
||||
filegroup(
|
||||
name = "test_data",
|
||||
srcs = glob([
|
||||
"**/*.json",
|
||||
]),
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "91434d5fd5e1c6eb7b0174fed2afe25e09bddf00e1e4c431db931b2cee4e7773",
|
||||
url = "https://github.com/eth2-clients/slashing-protection-interchange-tests/archive/b8413ca42dc92308019d0d4db52c87e9e125c4e9.tar.gz",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "eth2_spec_tests_general",
|
||||
build_file_content = """
|
||||
@@ -363,10 +378,6 @@ load("//:deps.bzl", "prysm_deps")
|
||||
# gazelle:repository_macro deps.bzl%prysm_deps
|
||||
prysm_deps()
|
||||
|
||||
load("@com_github_prysmaticlabs_go_ssz//:deps.bzl", "go_ssz_dependencies")
|
||||
|
||||
go_ssz_dependencies()
|
||||
|
||||
load("@prysm//third_party/herumi:herumi.bzl", "bls_dependencies")
|
||||
|
||||
bls_dependencies()
|
||||
|
||||
@@ -59,6 +59,7 @@ go_library(
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_prometheus_client_golang//prometheus:go_default_library",
|
||||
"@com_github_prometheus_client_golang//prometheus/promauto:go_default_library",
|
||||
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
|
||||
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@io_opencensus_go//trace:go_default_library",
|
||||
@@ -116,7 +117,6 @@ go_test(
|
||||
"@com_github_ethereum_go_ethereum//core/types:go_default_library",
|
||||
"@com_github_gogo_protobuf//proto:go_default_library",
|
||||
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
|
||||
"@in_gopkg_d4l3k_messagediff_v1//:go_default_library",
|
||||
@@ -165,7 +165,6 @@ go_test(
|
||||
"@com_github_ethereum_go_ethereum//core/types:go_default_library",
|
||||
"@com_github_gogo_protobuf//proto:go_default_library",
|
||||
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
|
||||
"@org_golang_x_net//context:go_default_library",
|
||||
|
||||
@@ -4,15 +4,15 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"go.opencensus.io/trace"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"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"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
// ChainInfoFetcher defines a common interface for methods in blockchain service which
|
||||
@@ -27,7 +27,7 @@ type ChainInfoFetcher interface {
|
||||
// TimeFetcher retrieves the Eth2 data that's related to time.
|
||||
type TimeFetcher interface {
|
||||
GenesisTime() time.Time
|
||||
CurrentSlot() uint64
|
||||
CurrentSlot() types.Slot
|
||||
}
|
||||
|
||||
// GenesisFetcher retrieves the eth2 data related to its genesis.
|
||||
@@ -38,12 +38,12 @@ type GenesisFetcher interface {
|
||||
// HeadFetcher defines a common interface for methods in blockchain service which
|
||||
// directly retrieves head related data.
|
||||
type HeadFetcher interface {
|
||||
HeadSlot() uint64
|
||||
HeadSlot() types.Slot
|
||||
HeadRoot(ctx context.Context) ([]byte, error)
|
||||
HeadBlock(ctx context.Context) (*ethpb.SignedBeaconBlock, error)
|
||||
HeadState(ctx context.Context) (*state.BeaconState, error)
|
||||
HeadValidatorsIndices(ctx context.Context, epoch uint64) ([]uint64, error)
|
||||
HeadSeed(ctx context.Context, epoch uint64) ([32]byte, error)
|
||||
HeadValidatorsIndices(ctx context.Context, epoch types.Epoch) ([]uint64, error)
|
||||
HeadSeed(ctx context.Context, epoch types.Epoch) ([32]byte, error)
|
||||
HeadGenesisValidatorRoot() [32]byte
|
||||
HeadETH1Data() *ethpb.Eth1Data
|
||||
ProtoArrayStore() *protoarray.Store
|
||||
@@ -96,7 +96,7 @@ func (s *Service) PreviousJustifiedCheckpt() *ethpb.Checkpoint {
|
||||
}
|
||||
|
||||
// HeadSlot returns the slot of the head of the chain.
|
||||
func (s *Service) HeadSlot() uint64 {
|
||||
func (s *Service) HeadSlot() types.Slot {
|
||||
s.headLock.RLock()
|
||||
defer s.headLock.RUnlock()
|
||||
|
||||
@@ -167,7 +167,7 @@ func (s *Service) HeadState(ctx context.Context) (*state.BeaconState, error) {
|
||||
}
|
||||
|
||||
// HeadValidatorsIndices returns a list of active validator indices from the head view of a given epoch.
|
||||
func (s *Service) HeadValidatorsIndices(ctx context.Context, epoch uint64) ([]uint64, error) {
|
||||
func (s *Service) HeadValidatorsIndices(ctx context.Context, epoch types.Epoch) ([]uint64, error) {
|
||||
s.headLock.RLock()
|
||||
defer s.headLock.RUnlock()
|
||||
|
||||
@@ -178,7 +178,7 @@ func (s *Service) HeadValidatorsIndices(ctx context.Context, epoch uint64) ([]ui
|
||||
}
|
||||
|
||||
// HeadSeed returns the seed from the head view of a given epoch.
|
||||
func (s *Service) HeadSeed(ctx context.Context, epoch uint64) ([32]byte, error) {
|
||||
func (s *Service) HeadSeed(ctx context.Context, epoch types.Epoch) ([32]byte, error) {
|
||||
s.headLock.RLock()
|
||||
defer s.headLock.RUnlock()
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||
@@ -106,7 +107,7 @@ func TestHeadSlot_CanRetrieve(t *testing.T) {
|
||||
s, err := state.InitializeFromProto(&pb.BeaconState{})
|
||||
require.NoError(t, err)
|
||||
c.head = &head{slot: 100, state: s}
|
||||
assert.Equal(t, uint64(100), c.HeadSlot())
|
||||
assert.Equal(t, types.Slot(100), c.HeadSlot())
|
||||
}
|
||||
|
||||
func TestHeadRoot_CanRetrieve(t *testing.T) {
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
|
||||
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
|
||||
@@ -20,7 +21,7 @@ import (
|
||||
|
||||
// This defines the current chain service's view of head.
|
||||
type head struct {
|
||||
slot uint64 // current head slot.
|
||||
slot types.Slot // current head slot.
|
||||
root [32]byte // current head root.
|
||||
block *ethpb.SignedBeaconBlock // current head block.
|
||||
state *stateTrie.BeaconState // current head state.
|
||||
@@ -148,6 +149,9 @@ func (s *Service) saveHead(ctx context.Context, headRoot [32]byte) error {
|
||||
// root in DB. With the inception of initial-sync-cache-state flag, it uses finalized
|
||||
// check point as anchors to resume sync therefore head is no longer needed to be saved on per slot basis.
|
||||
func (s *Service) saveHeadNoDB(ctx context.Context, b *ethpb.SignedBeaconBlock, r [32]byte, hs *stateTrie.BeaconState) error {
|
||||
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
|
||||
return err
|
||||
}
|
||||
cachedHeadRoot, err := s.HeadRoot(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get head root from cache")
|
||||
@@ -156,10 +160,6 @@ func (s *Service) saveHeadNoDB(ctx context.Context, b *ethpb.SignedBeaconBlock,
|
||||
return nil
|
||||
}
|
||||
|
||||
if b == nil || b.Block == nil {
|
||||
return errors.New("cannot save nil head block")
|
||||
}
|
||||
|
||||
s.setHeadInitialSync(r, stateTrie.CopySignedBeaconBlock(b), hs)
|
||||
return nil
|
||||
}
|
||||
@@ -196,7 +196,7 @@ func (s *Service) setHeadInitialSync(root [32]byte, block *ethpb.SignedBeaconBlo
|
||||
|
||||
// This returns the head slot.
|
||||
// This is a lock free version.
|
||||
func (s *Service) headSlot() uint64 {
|
||||
func (s *Service) headSlot() types.Slot {
|
||||
return s.head.slot
|
||||
}
|
||||
|
||||
@@ -234,14 +234,6 @@ func (s *Service) headGenesisValidatorRoot() [32]byte {
|
||||
return bytesutil.ToBytes32(s.head.state.GenesisValidatorRoot())
|
||||
}
|
||||
|
||||
// HasHeadState returns true if head state exists.
|
||||
func (s *Service) HasHeadState() bool {
|
||||
s.headLock.RLock()
|
||||
defer s.headLock.RUnlock()
|
||||
|
||||
return s.hasHeadState()
|
||||
}
|
||||
|
||||
// Returns true if head state exists.
|
||||
// This is the lock free version.
|
||||
func (s *Service) hasHeadState() bool {
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
@@ -22,7 +23,7 @@ func TestSaveHead_Same(t *testing.T) {
|
||||
service.head = &head{slot: 0, root: r}
|
||||
|
||||
require.NoError(t, service.saveHead(context.Background(), r))
|
||||
assert.Equal(t, uint64(0), service.headSlot(), "Head did not stay the same")
|
||||
assert.Equal(t, types.Slot(0), service.headSlot(), "Head did not stay the same")
|
||||
assert.Equal(t, r, service.headRoot(), "Head did not stay the same")
|
||||
}
|
||||
|
||||
@@ -41,19 +42,18 @@ func TestSaveHead_Different(t *testing.T) {
|
||||
require.NoError(t, service.beaconDB.SaveBlock(context.Background(), newHeadSignedBlock))
|
||||
newRoot, err := newHeadBlock.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
headState := testutil.NewBeaconState()
|
||||
headState, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, headState.SetSlot(1))
|
||||
require.NoError(t, service.beaconDB.SaveStateSummary(context.Background(), &pb.StateSummary{Slot: 1, Root: newRoot[:]}))
|
||||
require.NoError(t, service.beaconDB.SaveState(context.Background(), headState, newRoot))
|
||||
require.NoError(t, service.saveHead(context.Background(), newRoot))
|
||||
|
||||
assert.Equal(t, uint64(1), service.HeadSlot(), "Head did not change")
|
||||
assert.Equal(t, types.Slot(1), service.HeadSlot(), "Head did not change")
|
||||
|
||||
cachedRoot, err := service.HeadRoot(context.Background())
|
||||
require.NoError(t, err)
|
||||
if !bytes.Equal(cachedRoot, newRoot[:]) {
|
||||
t.Error("Head did not change")
|
||||
}
|
||||
assert.DeepEqual(t, cachedRoot, newRoot[:], "Head did not change")
|
||||
assert.DeepEqual(t, newHeadSignedBlock, service.headBlock(), "Head did not change")
|
||||
assert.DeepEqual(t, headState.CloneInnerState(), service.headState(ctx).CloneInnerState(), "Head did not change")
|
||||
}
|
||||
@@ -76,13 +76,14 @@ func TestSaveHead_Different_Reorg(t *testing.T) {
|
||||
require.NoError(t, service.beaconDB.SaveBlock(context.Background(), newHeadSignedBlock))
|
||||
newRoot, err := newHeadBlock.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
headState := testutil.NewBeaconState()
|
||||
headState, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, headState.SetSlot(1))
|
||||
require.NoError(t, service.beaconDB.SaveStateSummary(context.Background(), &pb.StateSummary{Slot: 1, Root: newRoot[:]}))
|
||||
require.NoError(t, service.beaconDB.SaveState(context.Background(), headState, newRoot))
|
||||
require.NoError(t, service.saveHead(context.Background(), newRoot))
|
||||
|
||||
assert.Equal(t, uint64(1), service.HeadSlot(), "Head did not change")
|
||||
assert.Equal(t, types.Slot(1), service.HeadSlot(), "Head did not change")
|
||||
|
||||
cachedRoot, err := service.HeadRoot(context.Background())
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -21,7 +21,8 @@ func TestService_TreeHandler(t *testing.T) {
|
||||
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
headState := testutil.NewBeaconState()
|
||||
headState, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, headState.SetBalances([]uint64{params.BeaconConfig().GweiPerEth}))
|
||||
cfg := &Config{
|
||||
BeaconDB: beaconDB,
|
||||
|
||||
@@ -3,10 +3,12 @@ package blockchain
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/timeutils"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
@@ -23,13 +25,20 @@ func logStateTransitionData(b *ethpb.BeaconBlock) {
|
||||
}).Info("Finished applying state transition")
|
||||
}
|
||||
|
||||
func logBlockSyncStatus(block *ethpb.BeaconBlock, blockRoot [32]byte, finalized *ethpb.Checkpoint) {
|
||||
func logBlockSyncStatus(block *ethpb.BeaconBlock, blockRoot [32]byte, finalized *ethpb.Checkpoint, receivedTime time.Time, genesisTime uint64) error {
|
||||
startTime, err := helpers.SlotToTime(genesisTime, block.Slot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.WithFields(logrus.Fields{
|
||||
"slot": block.Slot,
|
||||
"slotInEpoch": block.Slot % params.BeaconConfig().SlotsPerEpoch,
|
||||
"block": fmt.Sprintf("0x%s...", hex.EncodeToString(blockRoot[:])[:8]),
|
||||
"epoch": helpers.SlotToEpoch(block.Slot),
|
||||
"finalizedEpoch": finalized.Epoch,
|
||||
"finalizedRoot": fmt.Sprintf("0x%s...", hex.EncodeToString(finalized.Root)[:8]),
|
||||
"slot": block.Slot,
|
||||
"slotInEpoch": block.Slot % params.BeaconConfig().SlotsPerEpoch,
|
||||
"block": fmt.Sprintf("0x%s...", hex.EncodeToString(blockRoot[:])[:8]),
|
||||
"epoch": helpers.SlotToEpoch(block.Slot),
|
||||
"finalizedEpoch": finalized.Epoch,
|
||||
"finalizedRoot": fmt.Sprintf("0x%s...", hex.EncodeToString(finalized.Root)[:8]),
|
||||
"sinceSlotStartTime": timeutils.Now().Sub(startTime),
|
||||
"chainServiceProcessedTime": timeutils.Now().Sub(receivedTime),
|
||||
}).Info("Synced new block")
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
@@ -108,7 +109,7 @@ var (
|
||||
)
|
||||
|
||||
// reportSlotMetrics reports slot related metrics.
|
||||
func reportSlotMetrics(stateSlot, headSlot, clockSlot uint64, finalizedCheckpoint *ethpb.Checkpoint) {
|
||||
func reportSlotMetrics(stateSlot, headSlot, clockSlot types.Slot, finalizedCheckpoint *ethpb.Checkpoint) {
|
||||
clockTimeSlot.Set(float64(clockSlot))
|
||||
beaconSlot.Set(float64(stateSlot))
|
||||
beaconHeadSlot.Set(float64(headSlot))
|
||||
@@ -120,7 +121,7 @@ func reportSlotMetrics(stateSlot, headSlot, clockSlot uint64, finalizedCheckpoin
|
||||
|
||||
// reportEpochMetrics reports epoch related metrics.
|
||||
func reportEpochMetrics(ctx context.Context, postState, headState *stateTrie.BeaconState) error {
|
||||
currentEpoch := postState.Slot() / params.BeaconConfig().SlotsPerEpoch
|
||||
currentEpoch := types.Epoch(postState.Slot() / params.BeaconConfig().SlotsPerEpoch)
|
||||
|
||||
// Validator instances
|
||||
pendingInstances := 0
|
||||
|
||||
@@ -4,23 +4,39 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
eth "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
)
|
||||
|
||||
func TestReportEpochMetrics_BadHeadState(t *testing.T) {
|
||||
s := testutil.NewBeaconState()
|
||||
h := testutil.NewBeaconState()
|
||||
s, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
h, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, h.SetValidators(nil))
|
||||
err := reportEpochMetrics(context.Background(), s, h)
|
||||
err = reportEpochMetrics(context.Background(), s, h)
|
||||
require.ErrorContains(t, "failed to initialize precompute: nil validators in state", err)
|
||||
}
|
||||
|
||||
func TestReportEpochMetrics_BadAttestation(t *testing.T) {
|
||||
s := testutil.NewBeaconState()
|
||||
h := testutil.NewBeaconState()
|
||||
s, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
h, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, h.SetCurrentEpochAttestations([]*pb.PendingAttestation{{InclusionDelay: 0}}))
|
||||
err := reportEpochMetrics(context.Background(), s, h)
|
||||
err = reportEpochMetrics(context.Background(), s, h)
|
||||
require.ErrorContains(t, "attestation with inclusion delay of 0", err)
|
||||
}
|
||||
|
||||
func TestReportEpochMetrics_SlashedValidatorOutOfBound(t *testing.T) {
|
||||
h, _ := testutil.DeterministicGenesisState(t, 1)
|
||||
v, err := h.ValidatorAtIndex(0)
|
||||
require.NoError(t, err)
|
||||
v.Slashed = true
|
||||
require.NoError(t, h.UpdateValidatorAtIndex(0, v))
|
||||
require.NoError(t, h.SetCurrentEpochAttestations([]*pb.PendingAttestation{{InclusionDelay: 1, Data: testutil.HydrateAttestationData(ð.AttestationData{})}}))
|
||||
err = reportEpochMetrics(context.Background(), h, h)
|
||||
require.ErrorContains(t, "slot 0 out of bounds", err)
|
||||
}
|
||||
|
||||
@@ -2,25 +2,21 @@ package blockchain
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/shared/attestationutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/timeutils"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
// ErrTargetRootNotInDB returns when the target block root of an attestation cannot be found in the
|
||||
// beacon database.
|
||||
var ErrTargetRootNotInDB = errors.New("target root does not exist in db")
|
||||
|
||||
// onAttestation is called whenever an attestation is received, verifies the attestation is valid and saves
|
||||
// it to the DB. As a stateless function, this does not hold nor delay attestation based on the spec descriptions.
|
||||
// The delay is handled by the caller in `processAttestation`.
|
||||
// The delay is handled by the caller in `processAttestations`.
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
// def on_attestation(store: Store, attestation: Attestation) -> None:
|
||||
@@ -40,73 +36,68 @@ var ErrTargetRootNotInDB = errors.New("target root does not exist in db")
|
||||
//
|
||||
// # Update latest messages for attesting indices
|
||||
// update_latest_messages(store, indexed_attestation.attesting_indices, attestation)
|
||||
// TODO(#6072): This code path is highly untested. Requires comprehensive tests and simpler refactoring.
|
||||
func (s *Service) onAttestation(ctx context.Context, a *ethpb.Attestation) ([]uint64, error) {
|
||||
func (s *Service) onAttestation(ctx context.Context, a *ethpb.Attestation) error {
|
||||
ctx, span := trace.StartSpan(ctx, "blockChain.onAttestation")
|
||||
defer span.End()
|
||||
|
||||
if a == nil {
|
||||
return nil, errors.New("nil attestation")
|
||||
if err := helpers.ValidateNilAttestation(a); err != nil {
|
||||
return err
|
||||
}
|
||||
if a.Data == nil {
|
||||
return nil, errors.New("nil attestation.Data field")
|
||||
if err := helpers.ValidateSlotTargetEpoch(a.Data); err != nil {
|
||||
return err
|
||||
}
|
||||
if a.Data.Target == nil {
|
||||
return nil, errors.New("nil attestation.Data.Target field")
|
||||
}
|
||||
|
||||
tgt := stateTrie.CopyCheckpoint(a.Data.Target)
|
||||
|
||||
if helpers.SlotToEpoch(a.Data.Slot) != a.Data.Target.Epoch {
|
||||
return nil, fmt.Errorf("data slot is not in the same epoch as target %d != %d", helpers.SlotToEpoch(a.Data.Slot), a.Data.Target.Epoch)
|
||||
}
|
||||
|
||||
// Verify beacon node has seen the target block before.
|
||||
if !s.hasBlock(ctx, bytesutil.ToBytes32(tgt.Root)) {
|
||||
return nil, ErrTargetRootNotInDB
|
||||
}
|
||||
// Note that target root check is ignored here because it was performed in sync's validation pipeline:
|
||||
// validate_aggregate_proof.go and validate_beacon_attestation.go
|
||||
// If missing target root were to fail in this method, it would have just failed in `getAttPreState`.
|
||||
|
||||
// Retrieve attestation's data beacon block pre state. Advance pre state to latest epoch if necessary and
|
||||
// save it to the cache.
|
||||
baseState, err := s.getAttPreState(ctx, tgt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
genesisTime := baseState.GenesisTime()
|
||||
|
||||
// Verify attestation target is from current epoch or previous epoch.
|
||||
if err := s.verifyAttTargetEpoch(ctx, genesisTime, uint64(timeutils.Now().Unix()), tgt); err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
// Verify attestation beacon block is known and not from the future.
|
||||
if err := s.verifyBeaconBlock(ctx, a.Data); err != nil {
|
||||
return nil, errors.Wrap(err, "could not verify attestation beacon block")
|
||||
return errors.Wrap(err, "could not verify attestation beacon block")
|
||||
}
|
||||
|
||||
// Verify LMG GHOST and FFG votes are consistent with each other.
|
||||
if err := s.verifyLMDFFGConsistent(ctx, a.Data.Target.Epoch, a.Data.Target.Root, a.Data.BeaconBlockRoot); err != nil {
|
||||
return nil, errors.Wrap(err, "could not verify attestation beacon block")
|
||||
}
|
||||
// Note that LMG GHOST and FFG consistency check is ignored because it was performed in sync's validation pipeline:
|
||||
// validate_aggregate_proof.go and validate_beacon_attestation.go
|
||||
|
||||
// Verify attestations can only affect the fork choice of subsequent slots.
|
||||
if err := helpers.VerifySlotTime(genesisTime, a.Data.Slot+1, params.BeaconNetworkConfig().MaximumGossipClockDisparity); err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
// Use the target state to validate attestation and calculate the committees.
|
||||
indexedAtt, err := s.verifyAttestation(ctx, baseState, a)
|
||||
// Use the target state to verify attesting indices are valid.
|
||||
committee, err := helpers.BeaconCommitteeFromState(baseState, a.Data.Slot, a.Data.CommitteeIndex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
indexedAtt, err := attestationutil.ConvertToIndexed(ctx, a, committee)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := attestationutil.IsValidAttestationIndices(ctx, indexedAtt); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if indexedAtt.AttestingIndices == nil {
|
||||
return nil, errors.New("nil attesting indices")
|
||||
}
|
||||
// Note that signature verification is ignored here because it was performed in sync's validation pipeline:
|
||||
// validate_aggregate_proof.go and validate_beacon_attestation.go
|
||||
// We assume trusted attestation in this function has verified signature.
|
||||
|
||||
// Update forkchoice store with the new attestation for updating weight.
|
||||
s.forkChoiceStore.ProcessAttestation(ctx, indexedAtt.AttestingIndices, bytesutil.ToBytes32(a.Data.BeaconBlockRoot), a.Data.Target.Epoch)
|
||||
|
||||
return indexedAtt.AttestingIndices, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
package blockchain
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/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/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/mputil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
@@ -22,7 +21,7 @@ import (
|
||||
func (s *Service) getAttPreState(ctx context.Context, c *ethpb.Checkpoint) (*stateTrie.BeaconState, error) {
|
||||
// Use a multilock to allow scoped holding of a mutex by a checkpoint root + epoch
|
||||
// allowing us to behave smarter in terms of how this function is used concurrently.
|
||||
epochKey := strconv.FormatUint(c.Epoch, 10 /* base 10 */)
|
||||
epochKey := strconv.FormatUint(uint64(c.Epoch), 10 /* base 10 */)
|
||||
lock := mputil.NewMultilock(string(c.Root) + epochKey)
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
@@ -44,10 +43,16 @@ func (s *Service) getAttPreState(ctx context.Context, c *ethpb.Checkpoint) (*sta
|
||||
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)
|
||||
if featureconfig.Get().EnableNextSlotStateCache {
|
||||
baseState, err = state.ProcessSlotsUsingNextSlotCache(ctx, baseState, c.Root, epochStartSlot)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not process slots up to epoch %d", c.Epoch)
|
||||
}
|
||||
} else {
|
||||
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)
|
||||
}
|
||||
}
|
||||
if err := s.checkpointStateCache.AddCheckpointState(c, baseState); err != nil {
|
||||
return nil, errors.Wrap(err, "could not saved checkpoint state to cache")
|
||||
@@ -72,9 +77,9 @@ func (s *Service) getAttPreState(ctx context.Context, c *ethpb.Checkpoint) (*sta
|
||||
|
||||
// verifyAttTargetEpoch validates attestation is from the current or previous epoch.
|
||||
func (s *Service) verifyAttTargetEpoch(_ context.Context, genesisTime, nowTime uint64, c *ethpb.Checkpoint) error {
|
||||
currentSlot := (nowTime - genesisTime) / params.BeaconConfig().SecondsPerSlot
|
||||
currentSlot := types.Slot((nowTime - genesisTime) / params.BeaconConfig().SecondsPerSlot)
|
||||
currentEpoch := helpers.SlotToEpoch(currentSlot)
|
||||
var prevEpoch uint64
|
||||
var prevEpoch types.Epoch
|
||||
// Prevents previous epoch under flow
|
||||
if currentEpoch > 1 {
|
||||
prevEpoch = currentEpoch - 1
|
||||
@@ -97,41 +102,11 @@ func (s *Service) verifyBeaconBlock(ctx context.Context, data *ethpb.Attestation
|
||||
if b == nil && s.hasInitSyncBlock(r) {
|
||||
b = s.getInitSyncBlock(r)
|
||||
}
|
||||
if b == nil || b.Block == nil {
|
||||
return fmt.Errorf("beacon block %#x does not exist", bytesutil.Trunc(data.BeaconBlockRoot))
|
||||
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
|
||||
return err
|
||||
}
|
||||
if b.Block.Slot > data.Slot {
|
||||
return fmt.Errorf("could not process attestation for future block, block.Slot=%d > attestation.Data.Slot=%d", b.Block.Slot, data.Slot)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// verifyLMDFFGConsistent verifies LMD GHOST and FFG votes are consistent with each other.
|
||||
func (s *Service) verifyLMDFFGConsistent(ctx context.Context, ffgEpoch uint64, ffgRoot, lmdRoot []byte) error {
|
||||
ffgSlot, err := helpers.StartSlot(ffgEpoch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r, err := s.ancestor(ctx, lmdRoot, ffgSlot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !bytes.Equal(ffgRoot, r) {
|
||||
return errors.New("FFG and LMD votes are not consistent")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// verifyAttestation validates input attestation is valid.
|
||||
func (s *Service) verifyAttestation(ctx context.Context, baseState *stateTrie.BeaconState, a *ethpb.Attestation) (*ethpb.IndexedAttestation, error) {
|
||||
committee, err := helpers.BeaconCommitteeFromState(baseState, a.Data.Slot, a.Data.CommitteeIndex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
indexedAtt := attestationutil.ConvertToIndexed(ctx, a, committee)
|
||||
if err := blocks.VerifyIndexedAttestation(ctx, baseState, indexedAtt); err != nil {
|
||||
return nil, errors.Wrap(err, "could not verify indexed attestation")
|
||||
}
|
||||
return indexedAtt, nil
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
|
||||
@@ -17,9 +18,10 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
"github.com/prysmaticlabs/prysm/shared/timeutils"
|
||||
)
|
||||
|
||||
func TestStore_OnAttestation(t *testing.T) {
|
||||
func TestStore_OnAttestation_ErrorConditions(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
@@ -31,7 +33,7 @@ func TestStore_OnAttestation(t *testing.T) {
|
||||
service, err := NewService(ctx, cfg)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = blockTree1(beaconDB, []byte{'g'})
|
||||
_, err = blockTree1(t, beaconDB, []byte{'g'})
|
||||
require.NoError(t, err)
|
||||
|
||||
BlkWithOutState := testutil.NewBeaconBlock()
|
||||
@@ -46,7 +48,8 @@ func TestStore_OnAttestation(t *testing.T) {
|
||||
BlkWithStateBadAttRoot, err := BlkWithStateBadAtt.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
s := testutil.NewBeaconState()
|
||||
s, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, s.SetSlot(100*params.BeaconConfig().SlotsPerEpoch))
|
||||
require.NoError(t, service.beaconDB.SaveState(ctx, s, BlkWithStateBadAttRoot))
|
||||
|
||||
@@ -56,7 +59,8 @@ func TestStore_OnAttestation(t *testing.T) {
|
||||
|
||||
BlkWithValidStateRoot, err := BlkWithValidState.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
s = testutil.NewBeaconState()
|
||||
s, err = testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
err = s.SetFork(&pb.Fork{
|
||||
Epoch: 0,
|
||||
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
|
||||
@@ -72,34 +76,29 @@ func TestStore_OnAttestation(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
name: "attestation's data slot not aligned with target vote",
|
||||
a: ðpb.Attestation{Data: ðpb.AttestationData{Slot: params.BeaconConfig().SlotsPerEpoch, Target: ðpb.Checkpoint{Root: make([]byte, 32)}}},
|
||||
wantedErr: "data slot is not in the same epoch as target 1 != 0",
|
||||
},
|
||||
{
|
||||
name: "attestation's target root not in db",
|
||||
a: ðpb.Attestation{Data: ðpb.AttestationData{Target: ðpb.Checkpoint{Root: bytesutil.PadTo([]byte{'A'}, 32)}}},
|
||||
wantedErr: "target root does not exist in db",
|
||||
a: testutil.HydrateAttestation(ðpb.Attestation{Data: ðpb.AttestationData{Slot: params.BeaconConfig().SlotsPerEpoch, Target: ðpb.Checkpoint{Root: make([]byte, 32)}}}),
|
||||
wantedErr: "slot 32 does not match target epoch 0",
|
||||
},
|
||||
{
|
||||
name: "no pre state for attestations's target block",
|
||||
a: ðpb.Attestation{Data: ðpb.AttestationData{Target: ðpb.Checkpoint{Root: BlkWithOutStateRoot[:]}}},
|
||||
a: testutil.HydrateAttestation(ðpb.Attestation{Data: ðpb.AttestationData{Target: ðpb.Checkpoint{Root: BlkWithOutStateRoot[:]}}}),
|
||||
wantedErr: "could not get pre state for epoch 0",
|
||||
},
|
||||
{
|
||||
name: "process attestation doesn't match current epoch",
|
||||
a: ðpb.Attestation{Data: ðpb.AttestationData{Slot: 100 * params.BeaconConfig().SlotsPerEpoch, Target: ðpb.Checkpoint{Epoch: 100,
|
||||
Root: BlkWithStateBadAttRoot[:]}}},
|
||||
a: testutil.HydrateAttestation(ðpb.Attestation{Data: ðpb.AttestationData{Slot: 100 * params.BeaconConfig().SlotsPerEpoch, Target: ðpb.Checkpoint{Epoch: 100,
|
||||
Root: BlkWithStateBadAttRoot[:]}}}),
|
||||
wantedErr: "target epoch 100 does not match current epoch",
|
||||
},
|
||||
{
|
||||
name: "process nil attestation",
|
||||
a: nil,
|
||||
wantedErr: "nil attestation",
|
||||
wantedErr: "attestation can't be nil",
|
||||
},
|
||||
{
|
||||
name: "process nil field (a.Data) in attestation",
|
||||
a: ðpb.Attestation{},
|
||||
wantedErr: "nil attestation.Data field",
|
||||
wantedErr: "attestation's data can't be nil",
|
||||
},
|
||||
{
|
||||
name: "process nil field (a.Target) in attestation",
|
||||
@@ -112,13 +111,13 @@ func TestStore_OnAttestation(t *testing.T) {
|
||||
AggregationBits: make([]byte, 1),
|
||||
Signature: make([]byte, 96),
|
||||
},
|
||||
wantedErr: "nil attestation.Data.Target field",
|
||||
wantedErr: "attestation's target can't be nil",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
_, err := service.onAttestation(ctx, tt.a)
|
||||
err := service.onAttestation(ctx, tt.a)
|
||||
if tt.wantedErr != "" {
|
||||
assert.ErrorContains(t, tt.wantedErr, err)
|
||||
} else {
|
||||
@@ -128,6 +127,31 @@ func TestStore_OnAttestation(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestStore_OnAttestation_Ok(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{
|
||||
BeaconDB: beaconDB,
|
||||
ForkChoiceStore: protoarray.New(0, 0, [32]byte{}),
|
||||
StateGen: stategen.New(beaconDB),
|
||||
}
|
||||
service, err := NewService(ctx, cfg)
|
||||
require.NoError(t, err)
|
||||
genesisState, pks := testutil.DeterministicGenesisState(t, 64)
|
||||
require.NoError(t, genesisState.SetGenesisTime(uint64(timeutils.Now().Unix())-params.BeaconConfig().SecondsPerSlot))
|
||||
require.NoError(t, service.saveGenesisData(ctx, genesisState))
|
||||
att, err := testutil.GenerateAttestations(genesisState, pks, 1, 0, false)
|
||||
require.NoError(t, err)
|
||||
tRoot := bytesutil.ToBytes32(att[0].Data.Target.Root)
|
||||
copied := genesisState.Copy()
|
||||
copied, err = state.ProcessSlots(ctx, copied, 1)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, service.beaconDB.SaveState(ctx, copied, tRoot))
|
||||
require.NoError(t, service.forkChoiceStore.ProcessBlock(ctx, 0, tRoot, tRoot, tRoot, 1, 1))
|
||||
require.NoError(t, service.onAttestation(ctx, att[0]))
|
||||
}
|
||||
|
||||
func TestStore_SaveCheckpointState(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
@@ -139,7 +163,8 @@ func TestStore_SaveCheckpointState(t *testing.T) {
|
||||
service, err := NewService(ctx, cfg)
|
||||
require.NoError(t, err)
|
||||
|
||||
s := testutil.NewBeaconState()
|
||||
s, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
err = s.SetFinalizedCheckpoint(ðpb.Checkpoint{Root: bytesutil.PadTo([]byte{'A'}, 32)})
|
||||
require.NoError(t, err)
|
||||
val := ðpb.Validator{
|
||||
@@ -210,19 +235,19 @@ func TestStore_UpdateCheckpointState(t *testing.T) {
|
||||
service, err := NewService(ctx, cfg)
|
||||
require.NoError(t, err)
|
||||
|
||||
epoch := uint64(1)
|
||||
epoch := types.Epoch(1)
|
||||
baseState, _ := testutil.DeterministicGenesisState(t, 1)
|
||||
checkpoint := ðpb.Checkpoint{Epoch: epoch, Root: bytesutil.PadTo([]byte("hi"), 32)}
|
||||
require.NoError(t, service.beaconDB.SaveState(ctx, baseState, bytesutil.ToBytes32(checkpoint.Root)))
|
||||
returned, err := service.getAttPreState(ctx, checkpoint)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, returned.Slot(), checkpoint.Epoch*params.BeaconConfig().SlotsPerEpoch, "Incorrectly returned base state")
|
||||
assert.Equal(t, params.BeaconConfig().SlotsPerEpoch.Mul(uint64(checkpoint.Epoch)), returned.Slot(), "Incorrectly returned base state")
|
||||
|
||||
cached, err := service.checkpointStateCache.StateByCheckpoint(checkpoint)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, returned.Slot(), cached.Slot(), "State should have been cached")
|
||||
|
||||
epoch = uint64(2)
|
||||
epoch = 2
|
||||
newCheckpoint := ðpb.Checkpoint{Epoch: epoch, Root: bytesutil.PadTo([]byte("bye"), 32)}
|
||||
require.NoError(t, service.beaconDB.SaveState(ctx, baseState, bytesutil.ToBytes32(newCheckpoint.Root)))
|
||||
returned, err = service.getAttPreState(ctx, newCheckpoint)
|
||||
@@ -248,7 +273,7 @@ func TestAttEpoch_MatchPrevEpoch(t *testing.T) {
|
||||
service, err := NewService(ctx, cfg)
|
||||
require.NoError(t, err)
|
||||
|
||||
nowTime := params.BeaconConfig().SlotsPerEpoch * params.BeaconConfig().SecondsPerSlot
|
||||
nowTime := uint64(params.BeaconConfig().SlotsPerEpoch) * params.BeaconConfig().SecondsPerSlot
|
||||
require.NoError(t, service.verifyAttTargetEpoch(ctx, 0, nowTime, ðpb.Checkpoint{Root: make([]byte, 32)}))
|
||||
}
|
||||
|
||||
@@ -260,7 +285,7 @@ func TestAttEpoch_MatchCurrentEpoch(t *testing.T) {
|
||||
service, err := NewService(ctx, cfg)
|
||||
require.NoError(t, err)
|
||||
|
||||
nowTime := params.BeaconConfig().SlotsPerEpoch * params.BeaconConfig().SecondsPerSlot
|
||||
nowTime := uint64(params.BeaconConfig().SlotsPerEpoch) * params.BeaconConfig().SecondsPerSlot
|
||||
require.NoError(t, service.verifyAttTargetEpoch(ctx, 0, nowTime, ðpb.Checkpoint{Epoch: 1}))
|
||||
}
|
||||
|
||||
@@ -272,7 +297,7 @@ func TestAttEpoch_NotMatch(t *testing.T) {
|
||||
service, err := NewService(ctx, cfg)
|
||||
require.NoError(t, err)
|
||||
|
||||
nowTime := 2 * params.BeaconConfig().SlotsPerEpoch * params.BeaconConfig().SecondsPerSlot
|
||||
nowTime := 2 * uint64(params.BeaconConfig().SlotsPerEpoch) * params.BeaconConfig().SecondsPerSlot
|
||||
err = service.verifyAttTargetEpoch(ctx, 0, nowTime, ðpb.Checkpoint{Root: make([]byte, 32)})
|
||||
assert.ErrorContains(t, "target epoch 0 does not match current epoch 2 or prev epoch 1", err)
|
||||
}
|
||||
@@ -286,7 +311,7 @@ func TestVerifyBeaconBlock_NoBlock(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
d := testutil.HydrateAttestationData(ðpb.AttestationData{})
|
||||
assert.ErrorContains(t, "beacon block 0x000000000000 does not exist", service.verifyBeaconBlock(ctx, d))
|
||||
assert.ErrorContains(t, "signed beacon block can't be nil", service.verifyBeaconBlock(ctx, d))
|
||||
}
|
||||
|
||||
func TestVerifyBeaconBlock_futureBlock(t *testing.T) {
|
||||
@@ -325,54 +350,6 @@ func TestVerifyBeaconBlock_OK(t *testing.T) {
|
||||
assert.NoError(t, service.verifyBeaconBlock(ctx, d), "Did not receive the wanted error")
|
||||
}
|
||||
|
||||
func TestVerifyLMDFFGConsistent_NotOK(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{BeaconDB: beaconDB, ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}
|
||||
service, err := NewService(ctx, cfg)
|
||||
require.NoError(t, err)
|
||||
|
||||
b32 := testutil.NewBeaconBlock()
|
||||
b32.Block.Slot = 32
|
||||
require.NoError(t, service.beaconDB.SaveBlock(ctx, b32))
|
||||
r32, err := b32.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
b33 := testutil.NewBeaconBlock()
|
||||
b33.Block.Slot = 33
|
||||
b33.Block.ParentRoot = r32[:]
|
||||
require.NoError(t, service.beaconDB.SaveBlock(ctx, b33))
|
||||
r33, err := b33.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
wanted := "FFG and LMD votes are not consistent"
|
||||
assert.ErrorContains(t, wanted, service.verifyLMDFFGConsistent(context.Background(), 1, []byte{'a'}, r33[:]))
|
||||
}
|
||||
|
||||
func TestVerifyLMDFFGConsistent_OK(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{BeaconDB: beaconDB, ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}
|
||||
service, err := NewService(ctx, cfg)
|
||||
require.NoError(t, err)
|
||||
|
||||
b32 := testutil.NewBeaconBlock()
|
||||
b32.Block.Slot = 32
|
||||
require.NoError(t, service.beaconDB.SaveBlock(ctx, b32))
|
||||
r32, err := b32.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
b33 := testutil.NewBeaconBlock()
|
||||
b33.Block.Slot = 33
|
||||
b33.Block.ParentRoot = r32[:]
|
||||
require.NoError(t, service.beaconDB.SaveBlock(ctx, b33))
|
||||
r33, err := b33.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
err = service.verifyLMDFFGConsistent(context.Background(), 1, r32[:], r33[:])
|
||||
assert.NoError(t, err, "Could not verify LMD and FFG votes to be consistent")
|
||||
}
|
||||
|
||||
func TestVerifyFinalizedConsistency_InconsistentRoot(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
@@ -3,9 +3,12 @@ package blockchain
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
|
||||
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
@@ -18,8 +21,14 @@ import (
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
// A custom slot deadline for processing state slots in our cache.
|
||||
const slotDeadline = 5 * time.Second
|
||||
|
||||
// A custom deadline for deposit trie insertion.
|
||||
const depositDeadline = 20 * time.Second
|
||||
|
||||
// This defines size of the upper bound for initial sync block cache.
|
||||
var initialSyncBlockCacheSize = 2 * params.BeaconConfig().SlotsPerEpoch
|
||||
var initialSyncBlockCacheSize = uint64(2 * params.BeaconConfig().SlotsPerEpoch)
|
||||
|
||||
// onBlock is called when a gossip block is received. It runs regular state transition on the block.
|
||||
// The block's signing root should be computed before calling this method to avoid redundant
|
||||
@@ -101,6 +110,20 @@ func (s *Service) onBlock(ctx context.Context, signed *ethpb.SignedBeaconBlock,
|
||||
return err
|
||||
}
|
||||
|
||||
// Updating next slot state cache can happen in the background. It shouldn't block rest of the process.
|
||||
if featureconfig.Get().EnableNextSlotStateCache {
|
||||
go func() {
|
||||
// Use a custom deadline here, since this method runs asynchronously.
|
||||
// We ignore the parent method's context and instead create a new one
|
||||
// with a custom deadline, therefore using the background context instead.
|
||||
slotCtx, cancel := context.WithTimeout(context.Background(), slotDeadline)
|
||||
defer cancel()
|
||||
if err := state.UpdateNextSlotCache(slotCtx, blockRoot[:], postState); err != nil {
|
||||
log.WithError(err).Debug("could not update next slot state cache")
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// Update justified check point.
|
||||
if postState.CurrentJustifiedCheckpoint().Epoch > s.justifiedCheckpt.Epoch {
|
||||
if err := s.updateJustified(ctx, postState); err != nil {
|
||||
@@ -108,42 +131,56 @@ func (s *Service) onBlock(ctx context.Context, signed *ethpb.SignedBeaconBlock,
|
||||
}
|
||||
}
|
||||
|
||||
// Update finalized check point.
|
||||
if postState.FinalizedCheckpointEpoch() > s.finalizedCheckpt.Epoch {
|
||||
if err := s.beaconDB.SaveBlocks(ctx, s.getInitSyncBlocks()); err != nil {
|
||||
return err
|
||||
newFinalized := postState.FinalizedCheckpointEpoch() > s.finalizedCheckpt.Epoch
|
||||
if featureconfig.Get().UpdateHeadTimely {
|
||||
if newFinalized {
|
||||
if err := s.finalizedImpliesNewJustified(ctx, postState); err != nil {
|
||||
return errors.Wrap(err, "could not save new justified")
|
||||
}
|
||||
s.prevFinalizedCheckpt = s.finalizedCheckpt
|
||||
s.finalizedCheckpt = postState.FinalizedCheckpoint()
|
||||
}
|
||||
s.clearInitSyncBlocks()
|
||||
|
||||
if err := s.updateHead(ctx, s.getJustifiedBalances()); err != nil {
|
||||
log.WithError(err).Warn("Could not update head")
|
||||
}
|
||||
|
||||
// Send notification of the processed block to the state feed.
|
||||
s.stateNotifier.StateFeed().Send(&feed.Event{
|
||||
Type: statefeed.BlockProcessed,
|
||||
Data: &statefeed.BlockProcessedData{
|
||||
Slot: signed.Block.Slot,
|
||||
BlockRoot: blockRoot,
|
||||
SignedBlock: signed,
|
||||
Verified: true,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// Update finalized check point.
|
||||
if newFinalized {
|
||||
if err := s.updateFinalized(ctx, postState.FinalizedCheckpoint()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fRoot := bytesutil.ToBytes32(postState.FinalizedCheckpoint().Root)
|
||||
if err := s.forkChoiceStore.Prune(ctx, fRoot); err != nil {
|
||||
return errors.Wrap(err, "could not prune proto array fork choice nodes")
|
||||
}
|
||||
|
||||
if err := s.finalizedImpliesNewJustified(ctx, postState); err != nil {
|
||||
return errors.Wrap(err, "could not save new justified")
|
||||
}
|
||||
|
||||
// Update deposit cache.
|
||||
finalizedState, err := s.stateGen.StateByRoot(ctx, fRoot)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not fetch finalized state")
|
||||
}
|
||||
// We update the cache up to the last deposit index in the finalized block's state.
|
||||
// We can be confident that these deposits will be included in some block
|
||||
// because the Eth1 follow distance makes such long-range reorgs extremely unlikely.
|
||||
eth1DepositIndex := int64(finalizedState.Eth1Data().DepositCount - 1)
|
||||
s.depositCache.InsertFinalizedDeposits(ctx, eth1DepositIndex)
|
||||
if featureconfig.Get().EnablePruningDepositProofs {
|
||||
// Deposit proofs are only used during state transition and can be safely removed to save space.
|
||||
if err = s.depositCache.PruneProofs(ctx, eth1DepositIndex); err != nil {
|
||||
return errors.Wrap(err, "could not prune deposit proofs")
|
||||
if !featureconfig.Get().UpdateHeadTimely {
|
||||
if err := s.finalizedImpliesNewJustified(ctx, postState); err != nil {
|
||||
return errors.Wrap(err, "could not save new justified")
|
||||
}
|
||||
}
|
||||
go func() {
|
||||
// Use a custom deadline here, since this method runs asynchronously.
|
||||
// We ignore the parent method's context and instead create a new one
|
||||
// with a custom deadline, therefore using the background context instead.
|
||||
depCtx, cancel := context.WithTimeout(context.Background(), depositDeadline)
|
||||
defer cancel()
|
||||
if err := s.insertFinalizedDeposits(depCtx, fRoot); err != nil {
|
||||
log.WithError(err).Error("Could not insert finalized deposits.")
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
defer reportAttestationInclusion(b)
|
||||
@@ -341,7 +378,12 @@ func (s *Service) handleEpochBoundary(ctx context.Context, postState *stateTrie.
|
||||
if err := helpers.UpdateCommitteeCache(postState, helpers.NextEpoch(postState)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := helpers.UpdateProposerIndicesInCache(postState, helpers.NextEpoch(postState)); err != nil {
|
||||
copied := postState.Copy()
|
||||
copied, err := state.ProcessSlots(ctx, copied, copied.Slot()+1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := helpers.UpdateProposerIndicesInCache(copied); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if postState.Slot() >= s.nextEpochBoundarySlot {
|
||||
@@ -359,7 +401,7 @@ func (s *Service) handleEpochBoundary(ctx context.Context, postState *stateTrie.
|
||||
if err := helpers.UpdateCommitteeCache(postState, helpers.CurrentEpoch(postState)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := helpers.UpdateProposerIndicesInCache(postState, helpers.CurrentEpoch(postState)); err != nil {
|
||||
if err := helpers.UpdateProposerIndicesInCache(postState); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -382,7 +424,10 @@ func (s *Service) insertBlockAndAttestationsToForkChoiceStore(ctx context.Contex
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
indices := attestationutil.AttestingIndices(a.AggregationBits, committee)
|
||||
indices, err := attestationutil.AttestingIndices(a.AggregationBits, committee)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.forkChoiceStore.ProcessAttestation(ctx, indices, bytesutil.ToBytes32(a.Data.BeaconBlockRoot), a.Data.Target.Epoch)
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -6,18 +6,20 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/shared/attestationutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/traceutil"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
// CurrentSlot returns the current slot based on time.
|
||||
func (s *Service) CurrentSlot() uint64 {
|
||||
func (s *Service) CurrentSlot() types.Slot {
|
||||
return helpers.CurrentSlot(uint64(s.genesisTime.Unix()))
|
||||
}
|
||||
|
||||
@@ -230,9 +232,10 @@ func (s *Service) updateFinalized(ctx context.Context, cp *ethpb.Checkpoint) err
|
||||
if err := s.beaconDB.SaveFinalizedCheckpoint(ctx, cp); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.prevFinalizedCheckpt = s.finalizedCheckpt
|
||||
s.finalizedCheckpt = cp
|
||||
if !featureconfig.Get().UpdateHeadTimely {
|
||||
s.prevFinalizedCheckpt = s.finalizedCheckpt
|
||||
s.finalizedCheckpt = cp
|
||||
}
|
||||
|
||||
fRoot := bytesutil.ToBytes32(cp.Root)
|
||||
if err := s.stateGen.MigrateToCold(ctx, fRoot); err != nil {
|
||||
@@ -254,7 +257,7 @@ func (s *Service) updateFinalized(ctx context.Context, cp *ethpb.Checkpoint) err
|
||||
// else:
|
||||
// # root is older than queried slot, thus a skip slot. Return most recent root prior to slot
|
||||
// return root
|
||||
func (s *Service) ancestor(ctx context.Context, root []byte, slot uint64) ([]byte, error) {
|
||||
func (s *Service) ancestor(ctx context.Context, root []byte, slot types.Slot) ([]byte, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "blockChain.ancestor")
|
||||
defer span.End()
|
||||
|
||||
@@ -275,7 +278,7 @@ func (s *Service) ancestor(ctx context.Context, root []byte, slot uint64) ([]byt
|
||||
}
|
||||
|
||||
// This retrieves an ancestor root using fork choice store. The look up is looping through the a flat array structure.
|
||||
func (s *Service) ancestorByForkChoiceStore(ctx context.Context, r [32]byte, slot uint64) ([]byte, error) {
|
||||
func (s *Service) ancestorByForkChoiceStore(ctx context.Context, r [32]byte, slot types.Slot) ([]byte, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "blockChain.ancestorByForkChoiceStore")
|
||||
defer span.End()
|
||||
|
||||
@@ -286,7 +289,7 @@ func (s *Service) ancestorByForkChoiceStore(ctx context.Context, r [32]byte, slo
|
||||
}
|
||||
|
||||
// This retrieves an ancestor root using DB. The look up is recursively looking up DB. Slower than `ancestorByForkChoiceStore`.
|
||||
func (s *Service) ancestorByDB(ctx context.Context, r [32]byte, slot uint64) ([]byte, error) {
|
||||
func (s *Service) ancestorByDB(ctx context.Context, r [32]byte, slot types.Slot) ([]byte, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "blockChain.ancestorByDB")
|
||||
defer span.End()
|
||||
|
||||
@@ -404,6 +407,30 @@ func (s *Service) fillInForkChoiceMissingBlocks(ctx context.Context, blk *ethpb.
|
||||
return nil
|
||||
}
|
||||
|
||||
// inserts finalized deposits into our finalized deposit trie.
|
||||
func (s *Service) insertFinalizedDeposits(ctx context.Context, fRoot [32]byte) error {
|
||||
ctx, span := trace.StartSpan(ctx, "blockChain.insertFinalizedDeposits")
|
||||
defer span.End()
|
||||
|
||||
// Update deposit cache.
|
||||
finalizedState, err := s.stateGen.StateByRoot(ctx, fRoot)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not fetch finalized state")
|
||||
}
|
||||
// We update the cache up to the last deposit index in the finalized block's state.
|
||||
// We can be confident that these deposits will be included in some block
|
||||
// because the Eth1 follow distance makes such long-range reorgs extremely unlikely.
|
||||
eth1DepositIndex := int64(finalizedState.Eth1Data().DepositCount - 1)
|
||||
s.depositCache.InsertFinalizedDeposits(ctx, eth1DepositIndex)
|
||||
if featureconfig.Get().EnablePruningDepositProofs {
|
||||
// Deposit proofs are only used during state transition and can be safely removed to save space.
|
||||
if err = s.depositCache.PruneProofs(ctx, eth1DepositIndex); err != nil {
|
||||
return errors.Wrap(err, "could not prune deposit proofs")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// The deletes input attestations from the attestation pool, so proposers don't include them in a block for the future.
|
||||
func (s *Service) deletePoolAtts(atts []*ethpb.Attestation) error {
|
||||
for _, att := range atts {
|
||||
|
||||
@@ -3,10 +3,13 @@ package blockchain
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
@@ -19,6 +22,7 @@ import (
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/attestationutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
|
||||
@@ -42,9 +46,10 @@ func TestStore_OnBlock(t *testing.T) {
|
||||
assert.NoError(t, beaconDB.SaveBlock(ctx, genesis))
|
||||
validGenesisRoot, err := genesis.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
st := testutil.NewBeaconState()
|
||||
st, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, service.beaconDB.SaveState(ctx, st.Copy(), validGenesisRoot))
|
||||
roots, err := blockTree1(beaconDB, validGenesisRoot[:])
|
||||
roots, err := blockTree1(t, beaconDB, validGenesisRoot[:])
|
||||
require.NoError(t, err)
|
||||
random := testutil.NewBeaconBlock()
|
||||
random.Block.Slot = 1
|
||||
@@ -76,7 +81,7 @@ func TestStore_OnBlock(t *testing.T) {
|
||||
blk: func() *ethpb.SignedBeaconBlock {
|
||||
b := testutil.NewBeaconBlock()
|
||||
b.Block.ParentRoot = randomParentRoot2
|
||||
b.Block.Slot = params.BeaconConfig().FarFutureEpoch
|
||||
b.Block.Slot = params.BeaconConfig().FarFutureSlot
|
||||
return b
|
||||
}(),
|
||||
s: st.Copy(),
|
||||
@@ -151,7 +156,7 @@ func TestStore_OnBlockBatch(t *testing.T) {
|
||||
var blkRoots [][32]byte
|
||||
var firstState *stateTrie.BeaconState
|
||||
for i := 1; i < 10; i++ {
|
||||
b, err := testutil.GenerateFullBlock(bState, keys, testutil.DefaultBlockGenConfig(), uint64(i))
|
||||
b, err := testutil.GenerateFullBlock(bState, keys, testutil.DefaultBlockGenConfig(), types.Slot(i))
|
||||
require.NoError(t, err)
|
||||
bState, err = state.ExecuteStateTransition(ctx, bState, b)
|
||||
require.NoError(t, err)
|
||||
@@ -198,7 +203,7 @@ func TestRemoveStateSinceLastFinalized_EmptyStartSlot(t *testing.T) {
|
||||
require.NoError(t, service.beaconDB.SaveBlock(ctx, newJustifiedBlk))
|
||||
require.NoError(t, service.beaconDB.SaveBlock(ctx, lastJustifiedBlk))
|
||||
|
||||
diff := (params.BeaconConfig().SlotsPerEpoch - 1) * params.BeaconConfig().SecondsPerSlot
|
||||
diff := params.BeaconConfig().SlotsPerEpoch.Sub(1).Mul(params.BeaconConfig().SecondsPerSlot)
|
||||
service.genesisTime = time.Unix(time.Now().Unix()-int64(diff), 0)
|
||||
service.justifiedCheckpt = ðpb.Checkpoint{Root: lastJustifiedRoot[:]}
|
||||
update, err = service.shouldUpdateCurrentJustified(ctx, ðpb.Checkpoint{Root: newJustifiedRoot[:]})
|
||||
@@ -226,7 +231,7 @@ func TestShouldUpdateJustified_ReturnFalse(t *testing.T) {
|
||||
require.NoError(t, service.beaconDB.SaveBlock(ctx, newJustifiedBlk))
|
||||
require.NoError(t, service.beaconDB.SaveBlock(ctx, lastJustifiedBlk))
|
||||
|
||||
diff := (params.BeaconConfig().SlotsPerEpoch - 1) * params.BeaconConfig().SecondsPerSlot
|
||||
diff := params.BeaconConfig().SlotsPerEpoch.Sub(1).Mul(params.BeaconConfig().SecondsPerSlot)
|
||||
service.genesisTime = time.Unix(time.Now().Unix()-int64(diff), 0)
|
||||
service.justifiedCheckpt = ðpb.Checkpoint{Root: lastJustifiedRoot[:]}
|
||||
|
||||
@@ -319,11 +324,13 @@ func TestUpdateJustified_CouldUpdateBest(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
service.justifiedCheckpt = ðpb.Checkpoint{Root: []byte{'A'}}
|
||||
service.bestJustifiedCheckpt = ðpb.Checkpoint{Root: []byte{'A'}}
|
||||
st := testutil.NewBeaconState()
|
||||
st, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconDB.SaveState(ctx, st.Copy(), r))
|
||||
|
||||
// Could update
|
||||
s := testutil.NewBeaconState()
|
||||
s, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, s.SetCurrentJustifiedCheckpoint(ðpb.Checkpoint{Epoch: 1, Root: r[:]}))
|
||||
require.NoError(t, service.updateJustified(context.Background(), s))
|
||||
|
||||
@@ -333,7 +340,7 @@ func TestUpdateJustified_CouldUpdateBest(t *testing.T) {
|
||||
service.bestJustifiedCheckpt.Epoch = 2
|
||||
require.NoError(t, service.updateJustified(context.Background(), s))
|
||||
|
||||
assert.Equal(t, uint64(2), service.bestJustifiedCheckpt.Epoch, "Incorrect justified epoch in service")
|
||||
assert.Equal(t, types.Epoch(2), service.bestJustifiedCheckpt.Epoch, "Incorrect justified epoch in service")
|
||||
}
|
||||
|
||||
func TestFillForkChoiceMissingBlocks_CanSave(t *testing.T) {
|
||||
@@ -351,10 +358,11 @@ func TestFillForkChoiceMissingBlocks_CanSave(t *testing.T) {
|
||||
require.NoError(t, beaconDB.SaveBlock(ctx, genesis))
|
||||
validGenesisRoot, err := genesis.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
st := testutil.NewBeaconState()
|
||||
st, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, service.beaconDB.SaveState(ctx, st.Copy(), validGenesisRoot))
|
||||
roots, err := blockTree1(beaconDB, validGenesisRoot[:])
|
||||
roots, err := blockTree1(t, beaconDB, validGenesisRoot[:])
|
||||
require.NoError(t, err)
|
||||
|
||||
beaconState, _ := testutil.DeterministicGenesisState(t, 32)
|
||||
@@ -388,10 +396,11 @@ func TestFillForkChoiceMissingBlocks_RootsMatch(t *testing.T) {
|
||||
require.NoError(t, beaconDB.SaveBlock(ctx, genesis))
|
||||
validGenesisRoot, err := genesis.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
st := testutil.NewBeaconState()
|
||||
st, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, service.beaconDB.SaveState(ctx, st.Copy(), validGenesisRoot))
|
||||
roots, err := blockTree1(beaconDB, validGenesisRoot[:])
|
||||
roots, err := blockTree1(t, beaconDB, validGenesisRoot[:])
|
||||
require.NoError(t, err)
|
||||
|
||||
beaconState, _ := testutil.DeterministicGenesisState(t, 32)
|
||||
@@ -429,7 +438,8 @@ func TestFillForkChoiceMissingBlocks_FilterFinalized(t *testing.T) {
|
||||
assert.NoError(t, beaconDB.SaveBlock(ctx, genesis))
|
||||
validGenesisRoot, err := genesis.Block.HashTreeRoot()
|
||||
assert.NoError(t, err)
|
||||
st := testutil.NewBeaconState()
|
||||
st, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, service.beaconDB.SaveState(ctx, st.Copy(), validGenesisRoot))
|
||||
|
||||
@@ -467,7 +477,7 @@ func TestFillForkChoiceMissingBlocks_FilterFinalized(t *testing.T) {
|
||||
// B0 /- B5 - B7
|
||||
// \- B3 - B4 - B6 - B8
|
||||
// (B1, and B3 are all from the same slots)
|
||||
func blockTree1(beaconDB db.Database, genesisRoot []byte) ([][]byte, error) {
|
||||
func blockTree1(t *testing.T, beaconDB db.Database, genesisRoot []byte) ([][]byte, error) {
|
||||
genesisRoot = bytesutil.PadTo(genesisRoot, 32)
|
||||
b0 := testutil.NewBeaconBlock()
|
||||
b0.Block.Slot = 0
|
||||
@@ -525,7 +535,8 @@ func blockTree1(beaconDB db.Database, genesisRoot []byte) ([][]byte, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
st := testutil.NewBeaconState()
|
||||
st, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, b := range []*ethpb.SignedBeaconBlock{b0, b1, b3, b4, b5, b6, b7, b8} {
|
||||
beaconBlock := testutil.NewBeaconBlock()
|
||||
@@ -554,7 +565,7 @@ func TestCurrentSlot_HandlesOverflow(t *testing.T) {
|
||||
svc := Service{genesisTime: timeutils.Now().Add(1 * time.Hour)}
|
||||
|
||||
slot := svc.CurrentSlot()
|
||||
require.Equal(t, uint64(0), slot, "Unexpected slot")
|
||||
require.Equal(t, types.Slot(0), slot, "Unexpected slot")
|
||||
}
|
||||
func TestAncestorByDB_CtxErr(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
@@ -741,13 +752,15 @@ func TestFinalizedImpliesNewJustified(t *testing.T) {
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
beaconState := testutil.NewBeaconState()
|
||||
beaconState, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(test.args.stateCheckPoint))
|
||||
service, err := NewService(ctx, &Config{BeaconDB: beaconDB, StateGen: stategen.New(beaconDB), ForkChoiceStore: protoarray.New(0, 0, [32]byte{})})
|
||||
require.NoError(t, err)
|
||||
service.justifiedCheckpt = test.args.cachedCheckPoint
|
||||
require.NoError(t, service.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{Root: bytesutil.PadTo(test.want.Root, 32)}))
|
||||
genesisState := testutil.NewBeaconState()
|
||||
genesisState, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, service.beaconDB.SaveState(ctx, genesisState, bytesutil.ToBytes32(test.want.Root)))
|
||||
|
||||
if test.args.diffFinalizedCheckPoint {
|
||||
@@ -870,11 +883,11 @@ func TestUpdateJustifiedInitSync(t *testing.T) {
|
||||
|
||||
require.NoError(t, service.updateJustifiedInitSync(ctx, newCp))
|
||||
|
||||
assert.DeepEqual(t, currentCp, service.prevJustifiedCheckpt, "Incorrect previous justified checkpoint")
|
||||
assert.DeepEqual(t, newCp, service.CurrentJustifiedCheckpt(), "Incorrect current justified checkpoint in cache")
|
||||
assert.DeepSSZEqual(t, currentCp, service.prevJustifiedCheckpt, "Incorrect previous justified checkpoint")
|
||||
assert.DeepSSZEqual(t, newCp, service.CurrentJustifiedCheckpt(), "Incorrect current justified checkpoint in cache")
|
||||
cp, err := service.beaconDB.JustifiedCheckpoint(ctx)
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, newCp, cp, "Incorrect current justified checkpoint in db")
|
||||
assert.DeepSSZEqual(t, newCp, cp, "Incorrect current justified checkpoint in db")
|
||||
}
|
||||
|
||||
func TestHandleEpochBoundary_BadMetrics(t *testing.T) {
|
||||
@@ -883,7 +896,8 @@ func TestHandleEpochBoundary_BadMetrics(t *testing.T) {
|
||||
service, err := NewService(ctx, cfg)
|
||||
require.NoError(t, err)
|
||||
|
||||
s := testutil.NewBeaconState()
|
||||
s, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, s.SetSlot(1))
|
||||
service.head = &head{}
|
||||
require.ErrorContains(t, "failed to initialize precompute: nil inner state", service.handleEpochBoundary(ctx, s))
|
||||
@@ -925,7 +939,7 @@ func TestOnBlock_CanFinalize(t *testing.T) {
|
||||
service.finalizedCheckpt = ðpb.Checkpoint{Root: gRoot[:]}
|
||||
|
||||
testState := gs.Copy()
|
||||
for i := uint64(1); i <= 4*params.BeaconConfig().SlotsPerEpoch; i++ {
|
||||
for i := types.Slot(1); i <= 4*params.BeaconConfig().SlotsPerEpoch; i++ {
|
||||
blk, err := testutil.GenerateFullBlock(testState, keys, testutil.DefaultBlockGenConfig(), i)
|
||||
require.NoError(t, err)
|
||||
r, err := blk.Block.HashTreeRoot()
|
||||
@@ -934,6 +948,54 @@ func TestOnBlock_CanFinalize(t *testing.T) {
|
||||
testState, err = service.stateGen.StateByRoot(ctx, r)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
require.Equal(t, uint64(3), service.CurrentJustifiedCheckpt().Epoch)
|
||||
require.Equal(t, uint64(2), service.FinalizedCheckpt().Epoch)
|
||||
require.Equal(t, types.Epoch(3), service.CurrentJustifiedCheckpt().Epoch)
|
||||
require.Equal(t, types.Epoch(2), service.FinalizedCheckpt().Epoch)
|
||||
}
|
||||
|
||||
func TestInsertFinalizedDeposits(t *testing.T) {
|
||||
flags := featureconfig.Get()
|
||||
flags.EnablePruningDepositProofs = true
|
||||
reset := featureconfig.InitWithReset(flags)
|
||||
defer reset()
|
||||
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
cfg := &Config{
|
||||
BeaconDB: beaconDB,
|
||||
StateGen: stategen.New(beaconDB),
|
||||
ForkChoiceStore: protoarray.New(0, 0, [32]byte{}),
|
||||
DepositCache: depositCache,
|
||||
}
|
||||
service, err := NewService(ctx, cfg)
|
||||
require.NoError(t, err)
|
||||
|
||||
gs, _ := testutil.DeterministicGenesisState(t, 32)
|
||||
require.NoError(t, service.saveGenesisData(ctx, gs))
|
||||
gBlk, err := service.beaconDB.GenesisBlock(ctx)
|
||||
require.NoError(t, err)
|
||||
gRoot, err := gBlk.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
service.finalizedCheckpt = ðpb.Checkpoint{Root: gRoot[:]}
|
||||
gs = gs.Copy()
|
||||
assert.NoError(t, gs.SetEth1Data(ðpb.Eth1Data{DepositCount: 10}))
|
||||
assert.NoError(t, service.stateGen.SaveState(ctx, [32]byte{'m', 'o', 'c', 'k'}, gs))
|
||||
zeroSig := [96]byte{}
|
||||
for i := uint64(0); i < uint64(4*params.BeaconConfig().SlotsPerEpoch); i++ {
|
||||
root := []byte(strconv.Itoa(int(i)))
|
||||
depositCache.InsertDeposit(ctx, ðpb.Deposit{Data: ðpb.Deposit_Data{
|
||||
PublicKey: bytesutil.FromBytes48([48]byte{}),
|
||||
WithdrawalCredentials: params.BeaconConfig().ZeroHash[:],
|
||||
Amount: 0,
|
||||
Signature: zeroSig[:],
|
||||
}, Proof: [][]byte{root}}, 100+i, int64(i), bytesutil.ToBytes32(root))
|
||||
}
|
||||
assert.NoError(t, service.insertFinalizedDeposits(ctx, [32]byte{'m', 'o', 'c', 'k'}))
|
||||
fDeposits := depositCache.FinalizedDeposits(ctx)
|
||||
assert.Equal(t, 9, int(fDeposits.MerkleTrieIndex), "Finalized deposits not inserted correctly")
|
||||
deps := depositCache.AllDeposits(ctx, big.NewInt(109))
|
||||
for _, d := range deps {
|
||||
assert.DeepEqual(t, [][]byte(nil), d.Proof, "Proofs are not empty")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,16 +35,10 @@ func (s *Service) ReceiveAttestationNoPubsub(ctx context.Context, att *ethpb.Att
|
||||
ctx, span := trace.StartSpan(ctx, "beacon-chain.blockchain.ReceiveAttestationNoPubsub")
|
||||
defer span.End()
|
||||
|
||||
_, err := s.onAttestation(ctx, att)
|
||||
if err != nil {
|
||||
if err := s.onAttestation(ctx, att); err != nil {
|
||||
return errors.Wrap(err, "could not process attestation")
|
||||
}
|
||||
|
||||
if err := s.updateHead(ctx, s.getJustifiedBalances()); err != nil {
|
||||
log.Warnf("Resolving fork due to new attestation: %v", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -62,7 +56,18 @@ func (s *Service) AttestationPreState(ctx context.Context, att *ethpb.Attestatio
|
||||
|
||||
// VerifyLmdFfgConsistency verifies that attestation's LMD and FFG votes are consistency to each other.
|
||||
func (s *Service) VerifyLmdFfgConsistency(ctx context.Context, a *ethpb.Attestation) error {
|
||||
return s.verifyLMDFFGConsistent(ctx, a.Data.Target.Epoch, a.Data.Target.Root, a.Data.BeaconBlockRoot)
|
||||
targetSlot, err := helpers.StartSlot(a.Data.Target.Epoch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r, err := s.ancestor(ctx, a.Data.BeaconBlockRoot, targetSlot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !bytes.Equal(a.Data.Target.Root, r) {
|
||||
return errors.New("FFG and LMD votes are not consistent")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// VerifyFinalizedConsistency verifies input root is consistent with finalized store.
|
||||
@@ -91,8 +96,8 @@ func (s *Service) VerifyFinalizedConsistency(ctx context.Context, root []byte) e
|
||||
return nil
|
||||
}
|
||||
|
||||
// This processes attestations from the attestation pool to account for validator votes and fork choice.
|
||||
func (s *Service) processAttestation(subscribedToStateEvents chan struct{}) {
|
||||
// This routine processes fork choice attestations from the pool to account for validator votes and fork choice.
|
||||
func (s *Service) processAttestationsRoutine(subscribedToStateEvents chan struct{}) {
|
||||
// Wait for state to be initialized.
|
||||
stateChannel := make(chan *feed.Event, 1)
|
||||
stateSub := s.stateNotifier.StateFeed().Subscribe(stateChannel)
|
||||
@@ -108,47 +113,59 @@ func (s *Service) processAttestation(subscribedToStateEvents chan struct{}) {
|
||||
log.Warn("Genesis time received, now available to process attestations")
|
||||
}
|
||||
|
||||
st := slotutil.GetSlotTicker(s.genesisTime, params.BeaconConfig().SecondsPerSlot)
|
||||
st := slotutil.NewSlotTicker(s.genesisTime, params.BeaconConfig().SecondsPerSlot)
|
||||
for {
|
||||
select {
|
||||
case <-s.ctx.Done():
|
||||
return
|
||||
case <-st.C():
|
||||
ctx := s.ctx
|
||||
atts := s.attPool.ForkchoiceAttestations()
|
||||
for _, a := range atts {
|
||||
// Based on the spec, don't process the attestation until the subsequent slot.
|
||||
// This delays consideration in the fork choice until their slot is in the past.
|
||||
// https://github.com/ethereum/eth2.0-specs/blob/dev/specs/phase0/fork-choice.md#validate_on_attestation
|
||||
nextSlot := a.Data.Slot + 1
|
||||
if err := helpers.VerifySlotTime(uint64(s.genesisTime.Unix()), nextSlot, params.BeaconNetworkConfig().MaximumGossipClockDisparity); err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
hasState := s.beaconDB.HasStateSummary(ctx, bytesutil.ToBytes32(a.Data.BeaconBlockRoot))
|
||||
hasBlock := s.hasBlock(ctx, bytesutil.ToBytes32(a.Data.BeaconBlockRoot))
|
||||
if !(hasState && hasBlock) {
|
||||
continue
|
||||
}
|
||||
|
||||
if err := s.attPool.DeleteForkchoiceAttestation(a); err != nil {
|
||||
log.WithError(err).Error("Could not delete fork choice attestation in pool")
|
||||
}
|
||||
|
||||
if !helpers.VerifyCheckpointEpoch(a.Data.Target, s.genesisTime) {
|
||||
continue
|
||||
}
|
||||
|
||||
if err := s.ReceiveAttestationNoPubsub(ctx, a); err != nil {
|
||||
log.WithFields(logrus.Fields{
|
||||
"slot": a.Data.Slot,
|
||||
"committeeIndex": a.Data.CommitteeIndex,
|
||||
"beaconBlockRoot": fmt.Sprintf("%#x", bytesutil.Trunc(a.Data.BeaconBlockRoot)),
|
||||
"targetRoot": fmt.Sprintf("%#x", bytesutil.Trunc(a.Data.Target.Root)),
|
||||
"aggregationCount": a.AggregationBits.Count(),
|
||||
}).WithError(err).Warn("Could not receive attestation in chain service")
|
||||
}
|
||||
// Continue when there's no fork choice attestation, there's nothing to process and update head.
|
||||
// This covers the condition when the node is still initial syncing to the head of the chain.
|
||||
if s.attPool.ForkchoiceAttestationCount() == 0 {
|
||||
continue
|
||||
}
|
||||
s.processAttestations(s.ctx)
|
||||
if err := s.updateHead(s.ctx, s.getJustifiedBalances()); err != nil {
|
||||
log.Warnf("Resolving fork due to new attestation: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This processes fork choice attestations from the pool to account for validator votes and fork choice.
|
||||
func (s *Service) processAttestations(ctx context.Context) {
|
||||
atts := s.attPool.ForkchoiceAttestations()
|
||||
for _, a := range atts {
|
||||
// Based on the spec, don't process the attestation until the subsequent slot.
|
||||
// This delays consideration in the fork choice until their slot is in the past.
|
||||
// https://github.com/ethereum/eth2.0-specs/blob/dev/specs/phase0/fork-choice.md#validate_on_attestation
|
||||
nextSlot := a.Data.Slot + 1
|
||||
if err := helpers.VerifySlotTime(uint64(s.genesisTime.Unix()), nextSlot, params.BeaconNetworkConfig().MaximumGossipClockDisparity); err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
hasState := s.beaconDB.HasStateSummary(ctx, bytesutil.ToBytes32(a.Data.BeaconBlockRoot))
|
||||
hasBlock := s.hasBlock(ctx, bytesutil.ToBytes32(a.Data.BeaconBlockRoot))
|
||||
if !(hasState && hasBlock) {
|
||||
continue
|
||||
}
|
||||
|
||||
if err := s.attPool.DeleteForkchoiceAttestation(a); err != nil {
|
||||
log.WithError(err).Error("Could not delete fork choice attestation in pool")
|
||||
}
|
||||
|
||||
if !helpers.VerifyCheckpointEpoch(a.Data.Target, s.genesisTime) {
|
||||
continue
|
||||
}
|
||||
|
||||
if err := s.ReceiveAttestationNoPubsub(ctx, a); err != nil {
|
||||
log.WithFields(logrus.Fields{
|
||||
"slot": a.Data.Slot,
|
||||
"committeeIndex": a.Data.CommitteeIndex,
|
||||
"beaconBlockRoot": fmt.Sprintf("%#x", bytesutil.Trunc(a.Data.BeaconBlockRoot)),
|
||||
"targetRoot": fmt.Sprintf("%#x", bytesutil.Trunc(a.Data.Target.Root)),
|
||||
"aggregationCount": a.AggregationBits.Count(),
|
||||
}).WithError(err).Warn("Could not process attestation for fork choice")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,11 +5,20 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
|
||||
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/attestations"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
"github.com/prysmaticlabs/prysm/shared/timeutils"
|
||||
logTest "github.com/sirupsen/logrus/hooks/test"
|
||||
)
|
||||
|
||||
func TestAttestationCheckPtState_FarFutureSlot(t *testing.T) {
|
||||
@@ -19,7 +28,94 @@ func TestAttestationCheckPtState_FarFutureSlot(t *testing.T) {
|
||||
chainService := setupBeaconChain(t, beaconDB)
|
||||
chainService.genesisTime = time.Now()
|
||||
|
||||
e := helpers.MaxSlotBuffer/params.BeaconConfig().SlotsPerEpoch + 1
|
||||
e := types.Epoch(helpers.MaxSlotBuffer/uint64(params.BeaconConfig().SlotsPerEpoch) + 1)
|
||||
_, err := chainService.AttestationPreState(context.Background(), ðpb.Attestation{Data: ðpb.AttestationData{Target: ðpb.Checkpoint{Epoch: e}}})
|
||||
require.ErrorContains(t, "exceeds max allowed value relative to the local clock", err)
|
||||
}
|
||||
|
||||
func TestVerifyLMDFFGConsistent_NotOK(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{BeaconDB: beaconDB, ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}
|
||||
service, err := NewService(ctx, cfg)
|
||||
require.NoError(t, err)
|
||||
|
||||
b32 := testutil.NewBeaconBlock()
|
||||
b32.Block.Slot = 32
|
||||
require.NoError(t, service.beaconDB.SaveBlock(ctx, b32))
|
||||
r32, err := b32.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
b33 := testutil.NewBeaconBlock()
|
||||
b33.Block.Slot = 33
|
||||
b33.Block.ParentRoot = r32[:]
|
||||
require.NoError(t, service.beaconDB.SaveBlock(ctx, b33))
|
||||
r33, err := b33.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
wanted := "FFG and LMD votes are not consistent"
|
||||
a := testutil.NewAttestation()
|
||||
a.Data.Target.Epoch = 1
|
||||
a.Data.Target.Root = []byte{'a'}
|
||||
a.Data.BeaconBlockRoot = r33[:]
|
||||
require.ErrorContains(t, wanted, service.VerifyLmdFfgConsistency(context.Background(), a))
|
||||
}
|
||||
|
||||
func TestVerifyLMDFFGConsistent_OK(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{BeaconDB: beaconDB, ForkChoiceStore: protoarray.New(0, 0, [32]byte{})}
|
||||
service, err := NewService(ctx, cfg)
|
||||
require.NoError(t, err)
|
||||
|
||||
b32 := testutil.NewBeaconBlock()
|
||||
b32.Block.Slot = 32
|
||||
require.NoError(t, service.beaconDB.SaveBlock(ctx, b32))
|
||||
r32, err := b32.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
b33 := testutil.NewBeaconBlock()
|
||||
b33.Block.Slot = 33
|
||||
b33.Block.ParentRoot = r32[:]
|
||||
require.NoError(t, service.beaconDB.SaveBlock(ctx, b33))
|
||||
r33, err := b33.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
a := testutil.NewAttestation()
|
||||
a.Data.Target.Epoch = 1
|
||||
a.Data.Target.Root = r32[:]
|
||||
a.Data.BeaconBlockRoot = r33[:]
|
||||
err = service.VerifyLmdFfgConsistency(context.Background(), a)
|
||||
require.NoError(t, err, "Could not verify LMD and FFG votes to be consistent")
|
||||
}
|
||||
|
||||
func TestProcessAttestations_Ok(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
|
||||
cfg := &Config{
|
||||
BeaconDB: beaconDB,
|
||||
ForkChoiceStore: protoarray.New(0, 0, [32]byte{}),
|
||||
StateGen: stategen.New(beaconDB),
|
||||
AttPool: attestations.NewPool(),
|
||||
}
|
||||
service, err := NewService(ctx, cfg)
|
||||
service.genesisTime = timeutils.Now().Add(-1 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second)
|
||||
require.NoError(t, err)
|
||||
genesisState, pks := testutil.DeterministicGenesisState(t, 64)
|
||||
require.NoError(t, genesisState.SetGenesisTime(uint64(timeutils.Now().Unix())-params.BeaconConfig().SecondsPerSlot))
|
||||
require.NoError(t, service.saveGenesisData(ctx, genesisState))
|
||||
atts, err := testutil.GenerateAttestations(genesisState, pks, 1, 0, false)
|
||||
require.NoError(t, err)
|
||||
tRoot := bytesutil.ToBytes32(atts[0].Data.Target.Root)
|
||||
copied := genesisState.Copy()
|
||||
copied, err = state.ProcessSlots(ctx, copied, 1)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, service.beaconDB.SaveState(ctx, copied, tRoot))
|
||||
require.NoError(t, service.forkChoiceStore.ProcessBlock(ctx, 0, tRoot, tRoot, tRoot, 1, 1))
|
||||
require.NoError(t, service.attPool.SaveForkchoiceAttestations(atts))
|
||||
service.processAttestations(ctx)
|
||||
require.Equal(t, 0, len(service.attPool.ForkchoiceAttestations()))
|
||||
require.LogsDoNotContain(t, hook, "Could not process attestation for fork choice")
|
||||
}
|
||||
|
||||
@@ -4,18 +4,21 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
|
||||
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/timeutils"
|
||||
"github.com/prysmaticlabs/prysm/shared/traceutil"
|
||||
"github.com/sirupsen/logrus"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
// This defines how many epochs since finality the run time will begin to save hot state on to the DB.
|
||||
var epochsSinceFinalitySaveHotStateDB = 100
|
||||
var epochsSinceFinalitySaveHotStateDB = types.Epoch(100)
|
||||
|
||||
// BlockReceiver interface defines the methods of chain service receive and processing new blocks.
|
||||
type BlockReceiver interface {
|
||||
@@ -33,6 +36,7 @@ type BlockReceiver interface {
|
||||
func (s *Service) ReceiveBlock(ctx context.Context, block *ethpb.SignedBeaconBlock, blockRoot [32]byte) error {
|
||||
ctx, span := trace.StartSpan(ctx, "blockChain.ReceiveBlock")
|
||||
defer span.End()
|
||||
receivedTime := timeutils.Now()
|
||||
blockCopy := stateTrie.CopySignedBeaconBlock(block)
|
||||
|
||||
// Apply state transition on the new block.
|
||||
@@ -43,21 +47,22 @@ func (s *Service) ReceiveBlock(ctx context.Context, block *ethpb.SignedBeaconBlo
|
||||
}
|
||||
|
||||
// Update and save head block after fork choice.
|
||||
if err := s.updateHead(ctx, s.getJustifiedBalances()); err != nil {
|
||||
log.WithError(err).Warn("Could not update head")
|
||||
if !featureconfig.Get().UpdateHeadTimely {
|
||||
if err := s.updateHead(ctx, s.getJustifiedBalances()); err != nil {
|
||||
log.WithError(err).Warn("Could not update head")
|
||||
}
|
||||
// Send notification of the processed block to the state feed.
|
||||
s.stateNotifier.StateFeed().Send(&feed.Event{
|
||||
Type: statefeed.BlockProcessed,
|
||||
Data: &statefeed.BlockProcessedData{
|
||||
Slot: blockCopy.Block.Slot,
|
||||
BlockRoot: blockRoot,
|
||||
SignedBlock: blockCopy,
|
||||
Verified: true,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// Send notification of the processed block to the state feed.
|
||||
s.stateNotifier.StateFeed().Send(&feed.Event{
|
||||
Type: statefeed.BlockProcessed,
|
||||
Data: &statefeed.BlockProcessedData{
|
||||
Slot: blockCopy.Block.Slot,
|
||||
BlockRoot: blockRoot,
|
||||
SignedBlock: blockCopy,
|
||||
Verified: true,
|
||||
},
|
||||
})
|
||||
|
||||
// Handle post block operations such as attestations and exits.
|
||||
if err := s.handlePostBlockOperations(blockCopy.Block); err != nil {
|
||||
return err
|
||||
@@ -72,8 +77,9 @@ func (s *Service) ReceiveBlock(ctx context.Context, block *ethpb.SignedBeaconBlo
|
||||
reportSlotMetrics(blockCopy.Block.Slot, s.HeadSlot(), s.CurrentSlot(), s.finalizedCheckpt)
|
||||
|
||||
// Log block sync status.
|
||||
logBlockSyncStatus(blockCopy.Block, blockRoot, s.finalizedCheckpt)
|
||||
|
||||
if err := logBlockSyncStatus(blockCopy.Block, blockRoot, s.finalizedCheckpt, receivedTime, uint64(s.genesisTime.Unix())); err != nil {
|
||||
return err
|
||||
}
|
||||
// Log state transition data.
|
||||
logStateTransitionData(blockCopy.Block)
|
||||
|
||||
@@ -197,12 +203,12 @@ func (s *Service) handlePostBlockOperations(b *ethpb.BeaconBlock) error {
|
||||
func (s *Service) checkSaveHotStateDB(ctx context.Context) error {
|
||||
currentEpoch := helpers.SlotToEpoch(s.CurrentSlot())
|
||||
// Prevent `sinceFinality` going underflow.
|
||||
var sinceFinality uint64
|
||||
var sinceFinality types.Epoch
|
||||
if currentEpoch > s.finalizedCheckpt.Epoch {
|
||||
sinceFinality = currentEpoch - s.finalizedCheckpt.Epoch
|
||||
}
|
||||
|
||||
if sinceFinality >= uint64(epochsSinceFinalitySaveHotStateDB) {
|
||||
if sinceFinality >= epochsSinceFinalitySaveHotStateDB {
|
||||
s.stateGen.EnableSaveHotStateToDB(ctx)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
blockchainTesting "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
|
||||
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||
@@ -25,7 +26,7 @@ func TestService_ReceiveBlock(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
genesis, keys := testutil.DeterministicGenesisState(t, 64)
|
||||
genFullBlock := func(t *testing.T, conf *testutil.BlockGenConfig, slot uint64) *ethpb.SignedBeaconBlock {
|
||||
genFullBlock := func(t *testing.T, conf *testutil.BlockGenConfig, slot types.Slot) *ethpb.SignedBeaconBlock {
|
||||
blk, err := testutil.GenerateFullBlock(genesis, keys, conf, slot)
|
||||
assert.NoError(t, err)
|
||||
return blk
|
||||
@@ -202,7 +203,7 @@ func TestService_ReceiveBlockInitialSync(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
genesis, keys := testutil.DeterministicGenesisState(t, 64)
|
||||
genFullBlock := func(t *testing.T, conf *testutil.BlockGenConfig, slot uint64) *ethpb.SignedBeaconBlock {
|
||||
genFullBlock := func(t *testing.T, conf *testutil.BlockGenConfig, slot types.Slot) *ethpb.SignedBeaconBlock {
|
||||
blk, err := testutil.GenerateFullBlock(genesis, keys, conf, slot)
|
||||
assert.NoError(t, err)
|
||||
return blk
|
||||
@@ -223,8 +224,8 @@ func TestService_ReceiveBlockInitialSync(t *testing.T) {
|
||||
block: genFullBlock(t, testutil.DefaultBlockGenConfig(), 2 /*slot*/),
|
||||
},
|
||||
check: func(t *testing.T, s *Service) {
|
||||
assert.Equal(t, uint64(2), s.head.state.Slot(), "Incorrect head state slot")
|
||||
assert.Equal(t, uint64(2), s.head.block.Block.Slot, "Incorrect head block slot")
|
||||
assert.Equal(t, types.Slot(2), s.head.state.Slot(), "Incorrect head state slot")
|
||||
assert.Equal(t, types.Slot(2), s.head.block.Block.Slot, "Incorrect head block slot")
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -283,7 +284,7 @@ func TestService_ReceiveBlockBatch(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
genesis, keys := testutil.DeterministicGenesisState(t, 64)
|
||||
genFullBlock := func(t *testing.T, conf *testutil.BlockGenConfig, slot uint64) *ethpb.SignedBeaconBlock {
|
||||
genFullBlock := func(t *testing.T, conf *testutil.BlockGenConfig, slot types.Slot) *ethpb.SignedBeaconBlock {
|
||||
blk, err := testutil.GenerateFullBlock(genesis, keys, conf, slot)
|
||||
assert.NoError(t, err)
|
||||
return blk
|
||||
@@ -304,8 +305,8 @@ func TestService_ReceiveBlockBatch(t *testing.T) {
|
||||
block: genFullBlock(t, testutil.DefaultBlockGenConfig(), 2 /*slot*/),
|
||||
},
|
||||
check: func(t *testing.T, s *Service) {
|
||||
assert.Equal(t, uint64(2), s.head.state.Slot(), "Incorrect head state slot")
|
||||
assert.Equal(t, uint64(2), s.head.block.Block.Slot, "Incorrect head block slot")
|
||||
assert.Equal(t, types.Slot(2), s.head.state.Slot(), "Incorrect head state slot")
|
||||
assert.Equal(t, types.Slot(2), s.head.block.Block.Slot, "Incorrect head block slot")
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -379,7 +380,7 @@ func TestCheckSaveHotStateDB_Enabling(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
s, err := NewService(context.Background(), &Config{StateGen: stategen.New(beaconDB)})
|
||||
require.NoError(t, err)
|
||||
st := params.BeaconConfig().SlotsPerEpoch * uint64(epochsSinceFinalitySaveHotStateDB)
|
||||
st := params.BeaconConfig().SlotsPerEpoch.Mul(uint64(epochsSinceFinalitySaveHotStateDB))
|
||||
s.genesisTime = time.Now().Add(time.Duration(-1*int64(st)*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second)
|
||||
s.finalizedCheckpt = ðpb.Checkpoint{}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
|
||||
@@ -66,7 +67,7 @@ type Service struct {
|
||||
bestJustifiedCheckpt *ethpb.Checkpoint
|
||||
finalizedCheckpt *ethpb.Checkpoint
|
||||
prevFinalizedCheckpt *ethpb.Checkpoint
|
||||
nextEpochBoundarySlot uint64
|
||||
nextEpochBoundarySlot types.Slot
|
||||
boundaryRoots [][32]byte
|
||||
checkpointStateCache *cache.CheckpointStateCache
|
||||
stateGen *stategen.State
|
||||
@@ -75,7 +76,7 @@ type Service struct {
|
||||
initSyncBlocksLock sync.RWMutex
|
||||
justifiedBalances []uint64
|
||||
justifiedBalancesLock sync.RWMutex
|
||||
wsEpoch uint64
|
||||
wsEpoch types.Epoch
|
||||
wsRoot []byte
|
||||
wsVerified bool
|
||||
}
|
||||
@@ -96,7 +97,7 @@ type Config struct {
|
||||
OpsService *attestations.Service
|
||||
StateGen *stategen.State
|
||||
WspBlockRoot []byte
|
||||
WspEpoch uint64
|
||||
WspEpoch types.Epoch
|
||||
}
|
||||
|
||||
// NewService instantiates a new block service instance that will
|
||||
@@ -263,7 +264,7 @@ func (s *Service) Start() {
|
||||
}()
|
||||
}
|
||||
|
||||
go s.processAttestation(attestationProcessorSubscribed)
|
||||
go s.processAttestationsRoutine(attestationProcessorSubscribed)
|
||||
}
|
||||
|
||||
// processChainStartTime initializes a series of deposits from the ChainStart deposits in the eth1
|
||||
@@ -323,7 +324,7 @@ func (s *Service) initializeBeaconChain(
|
||||
if err := helpers.UpdateCommitteeCache(genesisState, 0 /* genesis epoch */); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := helpers.UpdateProposerIndicesInCache(genesisState, 0 /* genesis epoch */); err != nil {
|
||||
if err := helpers.UpdateProposerIndicesInCache(genesisState); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -458,7 +459,7 @@ func (s *Service) initializeChainInfo(ctx context.Context) error {
|
||||
return errors.Wrap(err, "could not retrieve head block")
|
||||
}
|
||||
headEpoch := helpers.SlotToEpoch(headBlock.Block.Slot)
|
||||
var epochsSinceFinality uint64
|
||||
var epochsSinceFinality types.Epoch
|
||||
if headEpoch > finalized.Epoch {
|
||||
epochsSinceFinality = headEpoch - finalized.Epoch
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@ import (
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
|
||||
b "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
|
||||
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db"
|
||||
@@ -131,7 +133,8 @@ func TestChainStartStop_Initialized(t *testing.T) {
|
||||
blkRoot, err := genesisBlk.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconDB.SaveBlock(ctx, genesisBlk))
|
||||
s := testutil.NewBeaconState()
|
||||
s, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, s.SetSlot(1))
|
||||
require.NoError(t, beaconDB.SaveState(ctx, s, blkRoot))
|
||||
require.NoError(t, beaconDB.SaveHeadBlockRoot(ctx, blkRoot))
|
||||
@@ -160,7 +163,8 @@ func TestChainStartStop_GenesisZeroHashes(t *testing.T) {
|
||||
blkRoot, err := genesisBlk.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconDB.SaveBlock(ctx, genesisBlk))
|
||||
s := testutil.NewBeaconState()
|
||||
s, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconDB.SaveState(ctx, s, blkRoot))
|
||||
require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, blkRoot))
|
||||
require.NoError(t, beaconDB.SaveJustifiedCheckpoint(ctx, ðpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]}))
|
||||
@@ -228,7 +232,8 @@ func TestChainService_CorrectGenesisRoots(t *testing.T) {
|
||||
blkRoot, err := genesisBlk.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconDB.SaveBlock(ctx, genesisBlk))
|
||||
s := testutil.NewBeaconState()
|
||||
s, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, s.SetSlot(0))
|
||||
require.NoError(t, beaconDB.SaveState(ctx, s, blkRoot))
|
||||
require.NoError(t, beaconDB.SaveHeadBlockRoot(ctx, blkRoot))
|
||||
@@ -259,7 +264,8 @@ func TestChainService_InitializeChainInfo(t *testing.T) {
|
||||
headBlock := testutil.NewBeaconBlock()
|
||||
headBlock.Block.Slot = finalizedSlot
|
||||
headBlock.Block.ParentRoot = bytesutil.PadTo(genesisRoot[:], 32)
|
||||
headState := testutil.NewBeaconState()
|
||||
headState, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, headState.SetSlot(finalizedSlot))
|
||||
require.NoError(t, headState.SetGenesisValidatorRoot(params.BeaconConfig().ZeroHash[:]))
|
||||
headRoot, err := headBlock.Block.HashTreeRoot()
|
||||
@@ -299,7 +305,8 @@ func TestChainService_InitializeChainInfo_SetHeadAtGenesis(t *testing.T) {
|
||||
headBlock := testutil.NewBeaconBlock()
|
||||
headBlock.Block.Slot = finalizedSlot
|
||||
headBlock.Block.ParentRoot = bytesutil.PadTo(genesisRoot[:], 32)
|
||||
headState := testutil.NewBeaconState()
|
||||
headState, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, headState.SetSlot(finalizedSlot))
|
||||
require.NoError(t, headState.SetGenesisValidatorRoot(params.BeaconConfig().ZeroHash[:]))
|
||||
headRoot, err := headBlock.Block.HashTreeRoot()
|
||||
@@ -351,7 +358,8 @@ func TestChainService_InitializeChainInfo_HeadSync(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, beaconDB.SaveBlock(ctx, headBlock))
|
||||
|
||||
headState := testutil.NewBeaconState()
|
||||
headState, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, headState.SetSlot(headBlock.Block.Slot))
|
||||
require.NoError(t, headState.SetGenesisValidatorRoot(params.BeaconConfig().ZeroHash[:]))
|
||||
require.NoError(t, beaconDB.SaveState(ctx, headState, genesisRoot))
|
||||
@@ -408,7 +416,8 @@ func TestChainService_SaveHeadNoDB(t *testing.T) {
|
||||
blk.Block.Slot = 1
|
||||
r, err := blk.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
newState := testutil.NewBeaconState()
|
||||
newState, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, s.stateGen.SaveState(ctx, r, newState))
|
||||
require.NoError(t, s.saveHeadNoDB(ctx, blk, r, newState))
|
||||
|
||||
@@ -430,7 +439,8 @@ func TestHasBlock_ForkChoiceAndDB(t *testing.T) {
|
||||
block := testutil.NewBeaconBlock()
|
||||
r, err := block.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
beaconState := testutil.NewBeaconState()
|
||||
beaconState, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, s.insertBlockAndAttestationsToForkChoiceStore(ctx, block.Block, r, beaconState))
|
||||
|
||||
assert.Equal(t, false, s.hasBlock(ctx, [32]byte{}), "Should not have block")
|
||||
@@ -455,6 +465,20 @@ func TestServiceStop_SaveCachedBlocks(t *testing.T) {
|
||||
require.Equal(t, true, s.beaconDB.HasBlock(ctx, r))
|
||||
}
|
||||
|
||||
func TestProcessChainStartTime_ReceivedFeed(t *testing.T) {
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
service := setupBeaconChain(t, beaconDB)
|
||||
stateChannel := make(chan *feed.Event, 1)
|
||||
stateSub := service.stateNotifier.StateFeed().Subscribe(stateChannel)
|
||||
defer stateSub.Unsubscribe()
|
||||
service.processChainStartTime(context.Background(), time.Now())
|
||||
|
||||
stateEvent := <-stateChannel
|
||||
require.Equal(t, int(stateEvent.Type), statefeed.Initialized)
|
||||
_, ok := stateEvent.Data.(*statefeed.InitializedData)
|
||||
require.Equal(t, true, ok)
|
||||
}
|
||||
|
||||
func BenchmarkHasBlockDB(b *testing.B) {
|
||||
beaconDB := testDB.SetupDB(b)
|
||||
ctx := context.Background()
|
||||
|
||||
@@ -23,6 +23,7 @@ go_library(
|
||||
"//shared/event:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
|
||||
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
],
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
|
||||
@@ -47,23 +48,23 @@ type ChainService struct {
|
||||
ValidAttestation bool
|
||||
ForkChoiceStore *protoarray.Store
|
||||
VerifyBlkDescendantErr error
|
||||
Slot *uint64 // Pointer because 0 is a useful value, so checking against it can be incorrect.
|
||||
Slot *types.Slot // Pointer because 0 is a useful value, so checking against it can be incorrect.
|
||||
}
|
||||
|
||||
// StateNotifier mocks the same method in the chain service.
|
||||
func (ms *ChainService) StateNotifier() statefeed.Notifier {
|
||||
if ms.stateNotifier == nil {
|
||||
ms.stateNotifier = &MockStateNotifier{}
|
||||
func (s *ChainService) StateNotifier() statefeed.Notifier {
|
||||
if s.stateNotifier == nil {
|
||||
s.stateNotifier = &MockStateNotifier{}
|
||||
}
|
||||
return ms.stateNotifier
|
||||
return s.stateNotifier
|
||||
}
|
||||
|
||||
// BlockNotifier mocks the same method in the chain service.
|
||||
func (ms *ChainService) BlockNotifier() blockfeed.Notifier {
|
||||
if ms.blockNotifier == nil {
|
||||
ms.blockNotifier = &MockBlockNotifier{}
|
||||
func (s *ChainService) BlockNotifier() blockfeed.Notifier {
|
||||
if s.blockNotifier == nil {
|
||||
s.blockNotifier = &MockBlockNotifier{}
|
||||
}
|
||||
return ms.blockNotifier
|
||||
return s.blockNotifier
|
||||
}
|
||||
|
||||
// MockBlockNotifier mocks the block notifier.
|
||||
@@ -72,11 +73,11 @@ type MockBlockNotifier struct {
|
||||
}
|
||||
|
||||
// BlockFeed returns a block feed.
|
||||
func (msn *MockBlockNotifier) BlockFeed() *event.Feed {
|
||||
if msn.feed == nil {
|
||||
msn.feed = new(event.Feed)
|
||||
func (mbn *MockBlockNotifier) BlockFeed() *event.Feed {
|
||||
if mbn.feed == nil {
|
||||
mbn.feed = new(event.Feed)
|
||||
}
|
||||
return msn.feed
|
||||
return mbn.feed
|
||||
}
|
||||
|
||||
// MockStateNotifier mocks the state notifier.
|
||||
@@ -125,11 +126,11 @@ func (msn *MockStateNotifier) StateFeed() *event.Feed {
|
||||
}
|
||||
|
||||
// OperationNotifier mocks the same method in the chain service.
|
||||
func (ms *ChainService) OperationNotifier() opfeed.Notifier {
|
||||
if ms.opNotifier == nil {
|
||||
ms.opNotifier = &MockOperationNotifier{}
|
||||
func (s *ChainService) OperationNotifier() opfeed.Notifier {
|
||||
if s.opNotifier == nil {
|
||||
s.opNotifier = &MockOperationNotifier{}
|
||||
}
|
||||
return ms.opNotifier
|
||||
return s.opNotifier
|
||||
}
|
||||
|
||||
// MockOperationNotifier mocks the operation notifier.
|
||||
@@ -146,227 +147,227 @@ func (mon *MockOperationNotifier) OperationFeed() *event.Feed {
|
||||
}
|
||||
|
||||
// ReceiveBlockInitialSync mocks ReceiveBlockInitialSync method in chain service.
|
||||
func (ms *ChainService) ReceiveBlockInitialSync(ctx context.Context, block *ethpb.SignedBeaconBlock, _ [32]byte) error {
|
||||
if ms.State == nil {
|
||||
ms.State = &stateTrie.BeaconState{}
|
||||
func (s *ChainService) ReceiveBlockInitialSync(ctx context.Context, block *ethpb.SignedBeaconBlock, _ [32]byte) error {
|
||||
if s.State == nil {
|
||||
s.State = &stateTrie.BeaconState{}
|
||||
}
|
||||
if !bytes.Equal(ms.Root, block.Block.ParentRoot) {
|
||||
return errors.Errorf("wanted %#x but got %#x", ms.Root, block.Block.ParentRoot)
|
||||
if !bytes.Equal(s.Root, block.Block.ParentRoot) {
|
||||
return errors.Errorf("wanted %#x but got %#x", s.Root, block.Block.ParentRoot)
|
||||
}
|
||||
if err := ms.State.SetSlot(block.Block.Slot); err != nil {
|
||||
if err := s.State.SetSlot(block.Block.Slot); err != nil {
|
||||
return err
|
||||
}
|
||||
ms.BlocksReceived = append(ms.BlocksReceived, block)
|
||||
s.BlocksReceived = append(s.BlocksReceived, block)
|
||||
signingRoot, err := block.Block.HashTreeRoot()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if ms.DB != nil {
|
||||
if err := ms.DB.SaveBlock(ctx, block); err != nil {
|
||||
if s.DB != nil {
|
||||
if err := s.DB.SaveBlock(ctx, block); err != nil {
|
||||
return err
|
||||
}
|
||||
logrus.Infof("Saved block with root: %#x at slot %d", signingRoot, block.Block.Slot)
|
||||
}
|
||||
ms.Root = signingRoot[:]
|
||||
ms.Block = block
|
||||
s.Root = signingRoot[:]
|
||||
s.Block = block
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReceiveBlockBatch processes blocks in batches from initial-sync.
|
||||
func (ms *ChainService) ReceiveBlockBatch(ctx context.Context, blks []*ethpb.SignedBeaconBlock, _ [][32]byte) error {
|
||||
if ms.State == nil {
|
||||
ms.State = &stateTrie.BeaconState{}
|
||||
func (s *ChainService) ReceiveBlockBatch(ctx context.Context, blks []*ethpb.SignedBeaconBlock, _ [][32]byte) error {
|
||||
if s.State == nil {
|
||||
s.State = &stateTrie.BeaconState{}
|
||||
}
|
||||
for _, block := range blks {
|
||||
if !bytes.Equal(ms.Root, block.Block.ParentRoot) {
|
||||
return errors.Errorf("wanted %#x but got %#x", ms.Root, block.Block.ParentRoot)
|
||||
if !bytes.Equal(s.Root, block.Block.ParentRoot) {
|
||||
return errors.Errorf("wanted %#x but got %#x", s.Root, block.Block.ParentRoot)
|
||||
}
|
||||
if err := ms.State.SetSlot(block.Block.Slot); err != nil {
|
||||
if err := s.State.SetSlot(block.Block.Slot); err != nil {
|
||||
return err
|
||||
}
|
||||
ms.BlocksReceived = append(ms.BlocksReceived, block)
|
||||
s.BlocksReceived = append(s.BlocksReceived, block)
|
||||
signingRoot, err := block.Block.HashTreeRoot()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if ms.DB != nil {
|
||||
if err := ms.DB.SaveBlock(ctx, block); err != nil {
|
||||
if s.DB != nil {
|
||||
if err := s.DB.SaveBlock(ctx, block); err != nil {
|
||||
return err
|
||||
}
|
||||
logrus.Infof("Saved block with root: %#x at slot %d", signingRoot, block.Block.Slot)
|
||||
}
|
||||
ms.Root = signingRoot[:]
|
||||
ms.Block = block
|
||||
s.Root = signingRoot[:]
|
||||
s.Block = block
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReceiveBlock mocks ReceiveBlock method in chain service.
|
||||
func (ms *ChainService) ReceiveBlock(ctx context.Context, block *ethpb.SignedBeaconBlock, _ [32]byte) error {
|
||||
if ms.State == nil {
|
||||
ms.State = &stateTrie.BeaconState{}
|
||||
func (s *ChainService) ReceiveBlock(ctx context.Context, block *ethpb.SignedBeaconBlock, _ [32]byte) error {
|
||||
if s.State == nil {
|
||||
s.State = &stateTrie.BeaconState{}
|
||||
}
|
||||
if !bytes.Equal(ms.Root, block.Block.ParentRoot) {
|
||||
return errors.Errorf("wanted %#x but got %#x", ms.Root, block.Block.ParentRoot)
|
||||
if !bytes.Equal(s.Root, block.Block.ParentRoot) {
|
||||
return errors.Errorf("wanted %#x but got %#x", s.Root, block.Block.ParentRoot)
|
||||
}
|
||||
if err := ms.State.SetSlot(block.Block.Slot); err != nil {
|
||||
if err := s.State.SetSlot(block.Block.Slot); err != nil {
|
||||
return err
|
||||
}
|
||||
ms.BlocksReceived = append(ms.BlocksReceived, block)
|
||||
s.BlocksReceived = append(s.BlocksReceived, block)
|
||||
signingRoot, err := block.Block.HashTreeRoot()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if ms.DB != nil {
|
||||
if err := ms.DB.SaveBlock(ctx, block); err != nil {
|
||||
if s.DB != nil {
|
||||
if err := s.DB.SaveBlock(ctx, block); err != nil {
|
||||
return err
|
||||
}
|
||||
logrus.Infof("Saved block with root: %#x at slot %d", signingRoot, block.Block.Slot)
|
||||
}
|
||||
ms.Root = signingRoot[:]
|
||||
ms.Block = block
|
||||
s.Root = signingRoot[:]
|
||||
s.Block = block
|
||||
return nil
|
||||
}
|
||||
|
||||
// HeadSlot mocks HeadSlot method in chain service.
|
||||
func (ms *ChainService) HeadSlot() uint64 {
|
||||
if ms.State == nil {
|
||||
func (s *ChainService) HeadSlot() types.Slot {
|
||||
if s.State == nil {
|
||||
return 0
|
||||
}
|
||||
return ms.State.Slot()
|
||||
return s.State.Slot()
|
||||
}
|
||||
|
||||
// HeadRoot mocks HeadRoot method in chain service.
|
||||
func (ms *ChainService) HeadRoot(_ context.Context) ([]byte, error) {
|
||||
if len(ms.Root) > 0 {
|
||||
return ms.Root, nil
|
||||
func (s *ChainService) HeadRoot(_ context.Context) ([]byte, error) {
|
||||
if len(s.Root) > 0 {
|
||||
return s.Root, nil
|
||||
}
|
||||
return make([]byte, 32), nil
|
||||
}
|
||||
|
||||
// HeadBlock mocks HeadBlock method in chain service.
|
||||
func (ms *ChainService) HeadBlock(context.Context) (*ethpb.SignedBeaconBlock, error) {
|
||||
return ms.Block, nil
|
||||
func (s *ChainService) HeadBlock(context.Context) (*ethpb.SignedBeaconBlock, error) {
|
||||
return s.Block, nil
|
||||
}
|
||||
|
||||
// HeadState mocks HeadState method in chain service.
|
||||
func (ms *ChainService) HeadState(context.Context) (*stateTrie.BeaconState, error) {
|
||||
return ms.State, nil
|
||||
func (s *ChainService) HeadState(context.Context) (*stateTrie.BeaconState, error) {
|
||||
return s.State, nil
|
||||
}
|
||||
|
||||
// CurrentFork mocks HeadState method in chain service.
|
||||
func (ms *ChainService) CurrentFork() *pb.Fork {
|
||||
return ms.Fork
|
||||
func (s *ChainService) CurrentFork() *pb.Fork {
|
||||
return s.Fork
|
||||
}
|
||||
|
||||
// FinalizedCheckpt mocks FinalizedCheckpt method in chain service.
|
||||
func (ms *ChainService) FinalizedCheckpt() *ethpb.Checkpoint {
|
||||
return ms.FinalizedCheckPoint
|
||||
func (s *ChainService) FinalizedCheckpt() *ethpb.Checkpoint {
|
||||
return s.FinalizedCheckPoint
|
||||
}
|
||||
|
||||
// CurrentJustifiedCheckpt mocks CurrentJustifiedCheckpt method in chain service.
|
||||
func (ms *ChainService) CurrentJustifiedCheckpt() *ethpb.Checkpoint {
|
||||
return ms.CurrentJustifiedCheckPoint
|
||||
func (s *ChainService) CurrentJustifiedCheckpt() *ethpb.Checkpoint {
|
||||
return s.CurrentJustifiedCheckPoint
|
||||
}
|
||||
|
||||
// PreviousJustifiedCheckpt mocks PreviousJustifiedCheckpt method in chain service.
|
||||
func (ms *ChainService) PreviousJustifiedCheckpt() *ethpb.Checkpoint {
|
||||
return ms.PreviousJustifiedCheckPoint
|
||||
func (s *ChainService) PreviousJustifiedCheckpt() *ethpb.Checkpoint {
|
||||
return s.PreviousJustifiedCheckPoint
|
||||
}
|
||||
|
||||
// ReceiveAttestation mocks ReceiveAttestation method in chain service.
|
||||
func (ms *ChainService) ReceiveAttestation(_ context.Context, _ *ethpb.Attestation) error {
|
||||
func (s *ChainService) ReceiveAttestation(_ context.Context, _ *ethpb.Attestation) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReceiveAttestationNoPubsub mocks ReceiveAttestationNoPubsub method in chain service.
|
||||
func (ms *ChainService) ReceiveAttestationNoPubsub(context.Context, *ethpb.Attestation) error {
|
||||
func (s *ChainService) ReceiveAttestationNoPubsub(context.Context, *ethpb.Attestation) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// AttestationPreState mocks AttestationPreState method in chain service.
|
||||
func (ms *ChainService) AttestationPreState(_ context.Context, _ *ethpb.Attestation) (*stateTrie.BeaconState, error) {
|
||||
return ms.State, nil
|
||||
func (s *ChainService) AttestationPreState(_ context.Context, _ *ethpb.Attestation) (*stateTrie.BeaconState, error) {
|
||||
return s.State, nil
|
||||
}
|
||||
|
||||
// HeadValidatorsIndices mocks the same method in the chain service.
|
||||
func (ms *ChainService) HeadValidatorsIndices(_ context.Context, epoch uint64) ([]uint64, error) {
|
||||
if ms.State == nil {
|
||||
func (s *ChainService) HeadValidatorsIndices(_ context.Context, epoch types.Epoch) ([]uint64, error) {
|
||||
if s.State == nil {
|
||||
return []uint64{}, nil
|
||||
}
|
||||
return helpers.ActiveValidatorIndices(ms.State, epoch)
|
||||
return helpers.ActiveValidatorIndices(s.State, epoch)
|
||||
}
|
||||
|
||||
// HeadSeed mocks the same method in the chain service.
|
||||
func (ms *ChainService) HeadSeed(_ context.Context, epoch uint64) ([32]byte, error) {
|
||||
return helpers.Seed(ms.State, epoch, params.BeaconConfig().DomainBeaconAttester)
|
||||
func (s *ChainService) HeadSeed(_ context.Context, epoch types.Epoch) ([32]byte, error) {
|
||||
return helpers.Seed(s.State, epoch, params.BeaconConfig().DomainBeaconAttester)
|
||||
}
|
||||
|
||||
// HeadETH1Data provides the current ETH1Data of the head state.
|
||||
func (ms *ChainService) HeadETH1Data() *ethpb.Eth1Data {
|
||||
return ms.ETH1Data
|
||||
func (s *ChainService) HeadETH1Data() *ethpb.Eth1Data {
|
||||
return s.ETH1Data
|
||||
}
|
||||
|
||||
// ProtoArrayStore mocks the same method in the chain service.
|
||||
func (ms *ChainService) ProtoArrayStore() *protoarray.Store {
|
||||
return ms.ForkChoiceStore
|
||||
func (s *ChainService) ProtoArrayStore() *protoarray.Store {
|
||||
return s.ForkChoiceStore
|
||||
}
|
||||
|
||||
// GenesisTime mocks the same method in the chain service.
|
||||
func (ms *ChainService) GenesisTime() time.Time {
|
||||
return ms.Genesis
|
||||
func (s *ChainService) GenesisTime() time.Time {
|
||||
return s.Genesis
|
||||
}
|
||||
|
||||
// GenesisValidatorRoot mocks the same method in the chain service.
|
||||
func (ms *ChainService) GenesisValidatorRoot() [32]byte {
|
||||
return ms.ValidatorsRoot
|
||||
func (s *ChainService) GenesisValidatorRoot() [32]byte {
|
||||
return s.ValidatorsRoot
|
||||
}
|
||||
|
||||
// CurrentSlot mocks the same method in the chain service.
|
||||
func (ms *ChainService) CurrentSlot() uint64 {
|
||||
if ms.Slot != nil {
|
||||
return *ms.Slot
|
||||
func (s *ChainService) CurrentSlot() types.Slot {
|
||||
if s.Slot != nil {
|
||||
return *s.Slot
|
||||
}
|
||||
return uint64(time.Now().Unix()-ms.Genesis.Unix()) / params.BeaconConfig().SecondsPerSlot
|
||||
return types.Slot(uint64(time.Now().Unix()-s.Genesis.Unix()) / params.BeaconConfig().SecondsPerSlot)
|
||||
}
|
||||
|
||||
// Participation mocks the same method in the chain service.
|
||||
func (ms *ChainService) Participation(_ uint64) *precompute.Balance {
|
||||
return ms.Balance
|
||||
func (s *ChainService) Participation(_ uint64) *precompute.Balance {
|
||||
return s.Balance
|
||||
}
|
||||
|
||||
// IsValidAttestation always returns true.
|
||||
func (ms *ChainService) IsValidAttestation(_ context.Context, _ *ethpb.Attestation) bool {
|
||||
return ms.ValidAttestation
|
||||
func (s *ChainService) IsValidAttestation(_ context.Context, _ *ethpb.Attestation) bool {
|
||||
return s.ValidAttestation
|
||||
}
|
||||
|
||||
// IsCanonical returns and determines whether a block with the provided root is part of
|
||||
// the canonical chain.
|
||||
func (ms *ChainService) IsCanonical(_ context.Context, r [32]byte) (bool, error) {
|
||||
if ms.CanonicalRoots != nil {
|
||||
_, ok := ms.CanonicalRoots[r]
|
||||
func (s *ChainService) IsCanonical(_ context.Context, r [32]byte) (bool, error) {
|
||||
if s.CanonicalRoots != nil {
|
||||
_, ok := s.CanonicalRoots[r]
|
||||
return ok, nil
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// HasInitSyncBlock mocks the same method in the chain service.
|
||||
func (ms *ChainService) HasInitSyncBlock(_ [32]byte) bool {
|
||||
func (s *ChainService) HasInitSyncBlock(_ [32]byte) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// HeadGenesisValidatorRoot mocks HeadGenesisValidatorRoot method in chain service.
|
||||
func (ms *ChainService) HeadGenesisValidatorRoot() [32]byte {
|
||||
func (s *ChainService) HeadGenesisValidatorRoot() [32]byte {
|
||||
return [32]byte{}
|
||||
}
|
||||
|
||||
// VerifyBlkDescendant mocks VerifyBlkDescendant and always returns nil.
|
||||
func (ms *ChainService) VerifyBlkDescendant(_ context.Context, _ [32]byte) error {
|
||||
return ms.VerifyBlkDescendantErr
|
||||
func (s *ChainService) VerifyBlkDescendant(_ context.Context, _ [32]byte) error {
|
||||
return s.VerifyBlkDescendantErr
|
||||
}
|
||||
|
||||
// VerifyLmdFfgConsistency mocks VerifyLmdFfgConsistency and always returns nil.
|
||||
func (ms *ChainService) VerifyLmdFfgConsistency(_ context.Context, a *ethpb.Attestation) error {
|
||||
func (s *ChainService) VerifyLmdFfgConsistency(_ context.Context, a *ethpb.Attestation) error {
|
||||
if !bytes.Equal(a.Data.BeaconBlockRoot, a.Data.Target.Root) {
|
||||
return errors.New("LMD and FFG miss matched")
|
||||
}
|
||||
@@ -374,8 +375,8 @@ func (ms *ChainService) VerifyLmdFfgConsistency(_ context.Context, a *ethpb.Atte
|
||||
}
|
||||
|
||||
// VerifyFinalizedConsistency mocks VerifyFinalizedConsistency and always returns nil.
|
||||
func (ms *ChainService) VerifyFinalizedConsistency(_ context.Context, r []byte) error {
|
||||
if !bytes.Equal(r, ms.FinalizedCheckPoint.Root) {
|
||||
func (s *ChainService) VerifyFinalizedConsistency(_ context.Context, r []byte) error {
|
||||
if !bytes.Equal(r, s.FinalizedCheckPoint.Root) {
|
||||
return errors.New("Root and finalized store are not consistent")
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
@@ -22,8 +23,8 @@ func TestService_VerifyWeakSubjectivityRoot(t *testing.T) {
|
||||
wsVerified bool
|
||||
wantErr bool
|
||||
wsRoot [32]byte
|
||||
wsEpoch uint64
|
||||
finalizedEpoch uint64
|
||||
wsEpoch types.Epoch
|
||||
finalizedEpoch types.Epoch
|
||||
errString string
|
||||
name string
|
||||
}{
|
||||
|
||||
2
beacon-chain/cache/BUILD.bazel
vendored
2
beacon-chain/cache/BUILD.bazel
vendored
@@ -41,6 +41,7 @@ go_library(
|
||||
"@com_github_patrickmn_go_cache//:go_default_library",
|
||||
"@com_github_prometheus_client_golang//prometheus:go_default_library",
|
||||
"@com_github_prometheus_client_golang//prometheus/promauto:go_default_library",
|
||||
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
|
||||
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
|
||||
"@io_k8s_client_go//tools/cache:go_default_library",
|
||||
"@io_opencensus_go//trace:go_default_library",
|
||||
@@ -71,6 +72,7 @@ go_test(
|
||||
"//shared/testutil/require:go_default_library",
|
||||
"@com_github_gogo_protobuf//proto:go_default_library",
|
||||
"@com_github_google_gofuzz//:go_default_library",
|
||||
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
|
||||
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
5
beacon-chain/cache/checkpoint_state_test.go
vendored
5
beacon-chain/cache/checkpoint_state_test.go
vendored
@@ -4,6 +4,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
@@ -60,8 +61,8 @@ func TestCheckpointStateCache_MaxSize(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
for i := uint64(0); i < uint64(maxCheckpointStateSize+100); i++ {
|
||||
require.NoError(t, st.SetSlot(i))
|
||||
require.NoError(t, c.AddCheckpointState(ðpb.Checkpoint{Epoch: i, Root: make([]byte, 32)}, st))
|
||||
require.NoError(t, st.SetSlot(types.Slot(i)))
|
||||
require.NoError(t, c.AddCheckpointState(ðpb.Checkpoint{Epoch: types.Epoch(i), Root: make([]byte, 32)}, st))
|
||||
}
|
||||
|
||||
assert.Equal(t, maxCheckpointStateSize, len(c.cache.Keys()))
|
||||
|
||||
9
beacon-chain/cache/committee.go
vendored
9
beacon-chain/cache/committee.go
vendored
@@ -8,6 +8,7 @@ import (
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/sliceutil"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
@@ -55,7 +56,7 @@ func NewCommitteesCache() *CommitteeCache {
|
||||
|
||||
// Committee fetches the shuffled indices by slot and committee index. Every list of indices
|
||||
// represent one committee. Returns true if the list exists with slot and committee index. Otherwise returns false, nil.
|
||||
func (c *CommitteeCache) Committee(slot uint64, seed [32]byte, index uint64) ([]uint64, error) {
|
||||
func (c *CommitteeCache) Committee(slot types.Slot, seed [32]byte, index uint64) ([]uint64, error) {
|
||||
c.lock.RLock()
|
||||
defer c.lock.RUnlock()
|
||||
|
||||
@@ -77,11 +78,11 @@ func (c *CommitteeCache) Committee(slot uint64, seed [32]byte, index uint64) ([]
|
||||
}
|
||||
|
||||
committeeCountPerSlot := uint64(1)
|
||||
if item.CommitteeCount/params.BeaconConfig().SlotsPerEpoch > 1 {
|
||||
committeeCountPerSlot = item.CommitteeCount / params.BeaconConfig().SlotsPerEpoch
|
||||
if item.CommitteeCount/uint64(params.BeaconConfig().SlotsPerEpoch) > 1 {
|
||||
committeeCountPerSlot = item.CommitteeCount / uint64(params.BeaconConfig().SlotsPerEpoch)
|
||||
}
|
||||
|
||||
indexOffSet := index + (slot%params.BeaconConfig().SlotsPerEpoch)*committeeCountPerSlot
|
||||
indexOffSet := index + uint64(slot.ModSlot(params.BeaconConfig().SlotsPerEpoch).Mul(committeeCountPerSlot))
|
||||
start, end := startEndIndices(item, indexOffSet)
|
||||
|
||||
if end > uint64(len(item.ShuffledIndices)) || end < start {
|
||||
|
||||
4
beacon-chain/cache/committee_disabled.go
vendored
4
beacon-chain/cache/committee_disabled.go
vendored
@@ -3,6 +3,8 @@
|
||||
// This file is used in fuzzer builds to bypass global committee caches.
|
||||
package cache
|
||||
|
||||
import types "github.com/prysmaticlabs/eth2-types"
|
||||
|
||||
// FakeCommitteeCache is a struct with 1 queue for looking up shuffled indices list by seed.
|
||||
type FakeCommitteeCache struct {
|
||||
}
|
||||
@@ -14,7 +16,7 @@ func NewCommitteesCache() *FakeCommitteeCache {
|
||||
|
||||
// Committee fetches the shuffled indices by slot and committee index. Every list of indices
|
||||
// represent one committee. Returns true if the list exists with slot and committee index. Otherwise returns false, nil.
|
||||
func (c *FakeCommitteeCache) Committee(slot uint64, seed [32]byte, index uint64) ([]uint64, error) {
|
||||
func (c *FakeCommitteeCache) Committee(slot types.Slot, seed [32]byte, index uint64) ([]uint64, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
||||
2
beacon-chain/cache/common.go
vendored
2
beacon-chain/cache/common.go
vendored
@@ -8,7 +8,7 @@ import (
|
||||
var (
|
||||
// maxCacheSize is 4x of the epoch length for additional cache padding.
|
||||
// Requests should be only accessing committees within defined epoch length.
|
||||
maxCacheSize = 4 * params.BeaconConfig().SlotsPerEpoch
|
||||
maxCacheSize = uint64(4 * params.BeaconConfig().SlotsPerEpoch)
|
||||
)
|
||||
|
||||
// trim the FIFO queue to the maxSize.
|
||||
|
||||
65
beacon-chain/cache/subnet_ids.go
vendored
65
beacon-chain/cache/subnet_ids.go
vendored
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
"github.com/patrickmn/go-cache"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/sliceutil"
|
||||
)
|
||||
@@ -25,7 +26,7 @@ var SubnetIDs = newSubnetIDs()
|
||||
func newSubnetIDs() *subnetIDs {
|
||||
// Given a node can calculate committee assignments of current epoch and next epoch.
|
||||
// Max size is set to 2 epoch length.
|
||||
cacheSize := int(params.BeaconConfig().MaxCommitteesPerSlot * params.BeaconConfig().SlotsPerEpoch * 2)
|
||||
cacheSize := int(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().MaxCommitteesPerSlot * 2))
|
||||
attesterCache, err := lru.New(cacheSize)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@@ -34,31 +35,31 @@ func newSubnetIDs() *subnetIDs {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
epochDuration := time.Duration(params.BeaconConfig().SlotsPerEpoch * params.BeaconConfig().SecondsPerSlot)
|
||||
epochDuration := time.Duration(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().SecondsPerSlot))
|
||||
subLength := epochDuration * time.Duration(params.BeaconConfig().EpochsPerRandomSubnetSubscription)
|
||||
persistentCache := cache.New(subLength*time.Second, epochDuration*time.Second)
|
||||
return &subnetIDs{attester: attesterCache, aggregator: aggregatorCache, persistentSubnets: persistentCache}
|
||||
}
|
||||
|
||||
// AddAttesterSubnetID adds the subnet index for subscribing subnet for the attester of a given slot.
|
||||
func (c *subnetIDs) AddAttesterSubnetID(slot, subnetID uint64) {
|
||||
c.attesterLock.Lock()
|
||||
defer c.attesterLock.Unlock()
|
||||
func (s *subnetIDs) AddAttesterSubnetID(slot types.Slot, subnetID uint64) {
|
||||
s.attesterLock.Lock()
|
||||
defer s.attesterLock.Unlock()
|
||||
|
||||
ids := []uint64{subnetID}
|
||||
val, exists := c.attester.Get(slot)
|
||||
val, exists := s.attester.Get(slot)
|
||||
if exists {
|
||||
ids = sliceutil.UnionUint64(append(val.([]uint64), ids...))
|
||||
}
|
||||
c.attester.Add(slot, ids)
|
||||
s.attester.Add(slot, ids)
|
||||
}
|
||||
|
||||
// GetAttesterSubnetIDs gets the subnet IDs for subscribed subnets for attesters of the slot.
|
||||
func (c *subnetIDs) GetAttesterSubnetIDs(slot uint64) []uint64 {
|
||||
c.attesterLock.RLock()
|
||||
defer c.attesterLock.RUnlock()
|
||||
func (s *subnetIDs) GetAttesterSubnetIDs(slot types.Slot) []uint64 {
|
||||
s.attesterLock.RLock()
|
||||
defer s.attesterLock.RUnlock()
|
||||
|
||||
val, exists := c.attester.Get(slot)
|
||||
val, exists := s.attester.Get(slot)
|
||||
if !exists {
|
||||
return nil
|
||||
}
|
||||
@@ -69,24 +70,24 @@ func (c *subnetIDs) GetAttesterSubnetIDs(slot uint64) []uint64 {
|
||||
}
|
||||
|
||||
// AddAggregatorSubnetID adds the subnet ID for subscribing subnet for the aggregator of a given slot.
|
||||
func (c *subnetIDs) AddAggregatorSubnetID(slot, subnetID uint64) {
|
||||
c.aggregatorLock.Lock()
|
||||
defer c.aggregatorLock.Unlock()
|
||||
func (s *subnetIDs) AddAggregatorSubnetID(slot types.Slot, subnetID uint64) {
|
||||
s.aggregatorLock.Lock()
|
||||
defer s.aggregatorLock.Unlock()
|
||||
|
||||
ids := []uint64{subnetID}
|
||||
val, exists := c.aggregator.Get(slot)
|
||||
val, exists := s.aggregator.Get(slot)
|
||||
if exists {
|
||||
ids = sliceutil.UnionUint64(append(val.([]uint64), ids...))
|
||||
}
|
||||
c.aggregator.Add(slot, ids)
|
||||
s.aggregator.Add(slot, ids)
|
||||
}
|
||||
|
||||
// GetAggregatorSubnetIDs gets the subnet IDs for subscribing subnet for aggregator of the slot.
|
||||
func (c *subnetIDs) GetAggregatorSubnetIDs(slot uint64) []uint64 {
|
||||
c.aggregatorLock.RLock()
|
||||
defer c.aggregatorLock.RUnlock()
|
||||
func (s *subnetIDs) GetAggregatorSubnetIDs(slot types.Slot) []uint64 {
|
||||
s.aggregatorLock.RLock()
|
||||
defer s.aggregatorLock.RUnlock()
|
||||
|
||||
val, exists := c.aggregator.Get(slot)
|
||||
val, exists := s.aggregator.Get(slot)
|
||||
if !exists {
|
||||
return []uint64{}
|
||||
}
|
||||
@@ -95,11 +96,11 @@ func (c *subnetIDs) GetAggregatorSubnetIDs(slot uint64) []uint64 {
|
||||
|
||||
// GetPersistentSubnets retrieves the persistent subnet and expiration time of that validator's
|
||||
// subscription.
|
||||
func (c *subnetIDs) GetPersistentSubnets(pubkey []byte) ([]uint64, bool, time.Time) {
|
||||
c.subnetsLock.RLock()
|
||||
defer c.subnetsLock.RUnlock()
|
||||
func (s *subnetIDs) GetPersistentSubnets(pubkey []byte) ([]uint64, bool, time.Time) {
|
||||
s.subnetsLock.RLock()
|
||||
defer s.subnetsLock.RUnlock()
|
||||
|
||||
id, duration, ok := c.persistentSubnets.GetWithExpiration(string(pubkey))
|
||||
id, duration, ok := s.persistentSubnets.GetWithExpiration(string(pubkey))
|
||||
if !ok {
|
||||
return []uint64{}, ok, time.Time{}
|
||||
}
|
||||
@@ -108,11 +109,11 @@ func (c *subnetIDs) GetPersistentSubnets(pubkey []byte) ([]uint64, bool, time.Ti
|
||||
|
||||
// GetAllSubnets retrieves all the non-expired subscribed subnets of all the validators
|
||||
// in the cache.
|
||||
func (c *subnetIDs) GetAllSubnets() []uint64 {
|
||||
c.subnetsLock.RLock()
|
||||
defer c.subnetsLock.RUnlock()
|
||||
func (s *subnetIDs) GetAllSubnets() []uint64 {
|
||||
s.subnetsLock.RLock()
|
||||
defer s.subnetsLock.RUnlock()
|
||||
|
||||
itemsMap := c.persistentSubnets.Items()
|
||||
itemsMap := s.persistentSubnets.Items()
|
||||
var committees []uint64
|
||||
|
||||
for _, v := range itemsMap {
|
||||
@@ -126,9 +127,9 @@ func (c *subnetIDs) GetAllSubnets() []uint64 {
|
||||
|
||||
// AddPersistentCommittee adds the relevant committee for that particular validator along with its
|
||||
// expiration period.
|
||||
func (c *subnetIDs) AddPersistentCommittee(pubkey []byte, comIndex []uint64, duration time.Duration) {
|
||||
c.subnetsLock.Lock()
|
||||
defer c.subnetsLock.Unlock()
|
||||
func (s *subnetIDs) AddPersistentCommittee(pubkey []byte, comIndex []uint64, duration time.Duration) {
|
||||
s.subnetsLock.Lock()
|
||||
defer s.subnetsLock.Unlock()
|
||||
|
||||
c.persistentSubnets.Set(string(pubkey), comIndex, duration)
|
||||
s.persistentSubnets.Set(string(pubkey), comIndex, duration)
|
||||
}
|
||||
|
||||
3
beacon-chain/cache/subnet_ids_test.go
vendored
3
beacon-chain/cache/subnet_ids_test.go
vendored
@@ -3,13 +3,14 @@ package cache
|
||||
import (
|
||||
"testing"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
)
|
||||
|
||||
func TestSubnetIDsCache_RoundTrip(t *testing.T) {
|
||||
c := newSubnetIDs()
|
||||
slot := uint64(100)
|
||||
slot := types.Slot(100)
|
||||
committeeIDs := c.GetAggregatorSubnetIDs(slot)
|
||||
assert.Equal(t, 0, len(committeeIDs), "Empty cache returned an object")
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ go_library(
|
||||
"//shared/trieutil:go_default_library",
|
||||
"@com_github_gogo_protobuf//proto:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
|
||||
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@io_opencensus_go//trace:go_default_library",
|
||||
@@ -69,6 +70,7 @@ go_test(
|
||||
shard_count = 2,
|
||||
deps = [
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/p2p/types:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/aggregation:go_default_library",
|
||||
@@ -83,6 +85,7 @@ go_test(
|
||||
"//shared/trieutil:go_default_library",
|
||||
"@com_github_gogo_protobuf//proto:go_default_library",
|
||||
"@com_github_google_gofuzz//:go_default_library",
|
||||
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
|
||||
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package blocks
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
@@ -23,8 +22,8 @@ func ProcessAttestations(
|
||||
beaconState *stateTrie.BeaconState,
|
||||
b *ethpb.SignedBeaconBlock,
|
||||
) (*stateTrie.BeaconState, error) {
|
||||
if b.Block == nil || b.Block.Body == nil {
|
||||
return nil, errors.New("block and block body can't be nil")
|
||||
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var err error
|
||||
@@ -85,8 +84,8 @@ func ProcessAttestationsNoVerifySignature(
|
||||
beaconState *stateTrie.BeaconState,
|
||||
b *ethpb.SignedBeaconBlock,
|
||||
) (*stateTrie.BeaconState, error) {
|
||||
if b.Block == nil || b.Block.Body == nil {
|
||||
return nil, errors.New("block and block body can't be nil")
|
||||
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
body := b.Block.Body
|
||||
var err error
|
||||
@@ -112,13 +111,8 @@ func ProcessAttestationNoVerifySignature(
|
||||
if err := helpers.ValidateNilAttestation(att); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
currEpoch := helpers.SlotToEpoch(beaconState.Slot())
|
||||
var prevEpoch uint64
|
||||
if currEpoch == 0 {
|
||||
prevEpoch = 0
|
||||
} else {
|
||||
prevEpoch = currEpoch - 1
|
||||
}
|
||||
currEpoch := helpers.CurrentEpoch(beaconState)
|
||||
prevEpoch := helpers.PrevEpoch(beaconState)
|
||||
data := att.Data
|
||||
if data.Target.Epoch != prevEpoch && data.Target.Epoch != currEpoch {
|
||||
return nil, fmt.Errorf(
|
||||
@@ -128,8 +122,8 @@ func ProcessAttestationNoVerifySignature(
|
||||
currEpoch,
|
||||
)
|
||||
}
|
||||
if helpers.SlotToEpoch(data.Slot) != data.Target.Epoch {
|
||||
return nil, fmt.Errorf("data slot is not in the same epoch as target %d != %d", helpers.SlotToEpoch(data.Slot), data.Target.Epoch)
|
||||
if err := helpers.ValidateSlotTargetEpoch(att.Data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s := att.Data.Slot
|
||||
@@ -175,40 +169,31 @@ func ProcessAttestationNoVerifySignature(
|
||||
ProposerIndex: proposerIndex,
|
||||
}
|
||||
|
||||
var ffgSourceEpoch uint64
|
||||
var ffgSourceRoot []byte
|
||||
var ffgTargetEpoch uint64
|
||||
if data.Target.Epoch == currEpoch {
|
||||
ffgSourceEpoch = beaconState.CurrentJustifiedCheckpoint().Epoch
|
||||
ffgSourceRoot = beaconState.CurrentJustifiedCheckpoint().Root
|
||||
ffgTargetEpoch = currEpoch
|
||||
if !beaconState.MatchCurrentJustifiedCheckpoint(data.Source) {
|
||||
return nil, errors.New("source check point not equal to current justified checkpoint")
|
||||
}
|
||||
if err := beaconState.AppendCurrentEpochAttestations(pendingAtt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
ffgSourceEpoch = beaconState.PreviousJustifiedCheckpoint().Epoch
|
||||
ffgSourceRoot = beaconState.PreviousJustifiedCheckpoint().Root
|
||||
ffgTargetEpoch = prevEpoch
|
||||
if !beaconState.MatchPreviousJustifiedCheckpoint(data.Source) {
|
||||
return nil, errors.New("source check point not equal to previous justified checkpoint")
|
||||
}
|
||||
if err := beaconState.AppendPreviousEpochAttestations(pendingAtt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if data.Source.Epoch != ffgSourceEpoch {
|
||||
return nil, fmt.Errorf("expected source epoch %d, received %d", ffgSourceEpoch, data.Source.Epoch)
|
||||
}
|
||||
if !bytes.Equal(data.Source.Root, ffgSourceRoot) {
|
||||
return nil, fmt.Errorf("expected source root %#x, received %#x", ffgSourceRoot, data.Source.Root)
|
||||
}
|
||||
if data.Target.Epoch != ffgTargetEpoch {
|
||||
return nil, fmt.Errorf("expected target epoch %d, received %d", ffgTargetEpoch, data.Target.Epoch)
|
||||
}
|
||||
|
||||
// Verify attesting indices are correct.
|
||||
committee, err := helpers.BeaconCommitteeFromState(beaconState, att.Data.Slot, att.Data.CommitteeIndex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
indexedAtt := attestationutil.ConvertToIndexed(ctx, att, committee)
|
||||
indexedAtt, err := attestationutil.ConvertToIndexed(ctx, att, committee)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := attestationutil.IsValidAttestationIndices(ctx, indexedAtt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -216,60 +201,6 @@ func ProcessAttestationNoVerifySignature(
|
||||
return beaconState, nil
|
||||
}
|
||||
|
||||
// VerifyAttestationsSignatures will verify the signatures of the provided attestations. This method performs
|
||||
// a single BLS verification call to verify the signatures of all of the provided attestations. All
|
||||
// of the provided attestations must have valid signatures or this method will return an error.
|
||||
// This method does not determine which attestation signature is invalid, only that one or more
|
||||
// attestation signatures were not valid.
|
||||
func VerifyAttestationsSignatures(ctx context.Context, beaconState *stateTrie.BeaconState, b *ethpb.SignedBeaconBlock) error {
|
||||
ctx, span := trace.StartSpan(ctx, "core.VerifyAttestationsSignatures")
|
||||
defer span.End()
|
||||
atts := b.Block.Body.Attestations
|
||||
span.AddAttributes(trace.Int64Attribute("attestations", int64(len(atts))))
|
||||
|
||||
if len(atts) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
fork := beaconState.Fork()
|
||||
gvr := beaconState.GenesisValidatorRoot()
|
||||
dt := params.BeaconConfig().DomainBeaconAttester
|
||||
|
||||
// Split attestations by fork. Note: the signature domain will differ based on the fork.
|
||||
var preForkAtts []*ethpb.Attestation
|
||||
var postForkAtts []*ethpb.Attestation
|
||||
for _, a := range atts {
|
||||
if helpers.SlotToEpoch(a.Data.Slot) < fork.Epoch {
|
||||
preForkAtts = append(preForkAtts, a)
|
||||
} else {
|
||||
postForkAtts = append(postForkAtts, a)
|
||||
}
|
||||
}
|
||||
|
||||
// Check attestations from before the fork.
|
||||
if fork.Epoch > 0 { // Check to prevent underflow.
|
||||
prevDomain, err := helpers.Domain(fork, fork.Epoch-1, dt, gvr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := verifyAttestationsSigWithDomain(ctx, beaconState, preForkAtts, prevDomain); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if len(preForkAtts) > 0 {
|
||||
// This is a sanity check that preForkAtts were not ignored when fork.Epoch == 0. This
|
||||
// condition is not possible, but it doesn't hurt to check anyway.
|
||||
return errors.New("some attestations were not verified from previous fork before genesis")
|
||||
}
|
||||
|
||||
// Then check attestations from after the fork.
|
||||
currDomain, err := helpers.Domain(fork, fork.Epoch, dt, gvr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return verifyAttestationsSigWithDomain(ctx, beaconState, postForkAtts, currDomain)
|
||||
}
|
||||
|
||||
// VerifyAttestationSignature converts and attestation into an indexed attestation and verifies
|
||||
// the signature in that attestation.
|
||||
func VerifyAttestationSignature(ctx context.Context, beaconState *stateTrie.BeaconState, att *ethpb.Attestation) error {
|
||||
@@ -280,7 +211,10 @@ func VerifyAttestationSignature(ctx context.Context, beaconState *stateTrie.Beac
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
indexedAtt := attestationutil.ConvertToIndexed(ctx, att, committee)
|
||||
indexedAtt, err := attestationutil.ConvertToIndexed(ctx, att, committee)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return VerifyIndexedAttestation(ctx, beaconState, indexedAtt)
|
||||
}
|
||||
|
||||
@@ -323,23 +257,3 @@ func VerifyIndexedAttestation(ctx context.Context, beaconState *stateTrie.Beacon
|
||||
}
|
||||
return attestationutil.VerifyIndexedAttestationSig(ctx, indexedAtt, pubkeys, domain)
|
||||
}
|
||||
|
||||
// Inner method to verify attestations. This abstraction allows for the domain to be provided as an
|
||||
// argument.
|
||||
func verifyAttestationsSigWithDomain(ctx context.Context, beaconState *stateTrie.BeaconState, atts []*ethpb.Attestation, domain []byte) error {
|
||||
if len(atts) == 0 {
|
||||
return nil
|
||||
}
|
||||
set, err := createAttestationSignatureSet(ctx, beaconState, atts, domain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
verify, err := set.Verify()
|
||||
if err != nil {
|
||||
return errors.Errorf("got error in multiple verification: %v", err)
|
||||
}
|
||||
if !verify {
|
||||
return errors.New("one or more attestation signatures did not verify")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
@@ -103,22 +104,11 @@ func TestProcessAttestations_CurrentEpochFFGDataMismatches(t *testing.T) {
|
||||
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(cfc))
|
||||
require.NoError(t, beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{}))
|
||||
|
||||
want := fmt.Sprintf(
|
||||
"expected source epoch %d, received %d",
|
||||
helpers.CurrentEpoch(beaconState),
|
||||
attestations[0].Data.Source.Epoch,
|
||||
)
|
||||
want := "source check point not equal to current justified checkpoint"
|
||||
_, err := blocks.ProcessAttestations(context.Background(), beaconState, b)
|
||||
assert.ErrorContains(t, want, err)
|
||||
|
||||
b.Block.Body.Attestations[0].Data.Source.Epoch = helpers.CurrentEpoch(beaconState)
|
||||
b.Block.Body.Attestations[0].Data.Source.Root = []byte{}
|
||||
|
||||
want = fmt.Sprintf(
|
||||
"expected source root %#x, received %#x",
|
||||
beaconState.CurrentJustifiedCheckpoint().Root,
|
||||
attestations[0].Data.Source.Root,
|
||||
)
|
||||
_, err = blocks.ProcessAttestations(context.Background(), beaconState, b)
|
||||
assert.ErrorContains(t, want, err)
|
||||
}
|
||||
@@ -145,30 +135,19 @@ func TestProcessAttestations_PrevEpochFFGDataMismatches(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
err := beaconState.SetSlot(beaconState.Slot() + params.BeaconConfig().SlotsPerEpoch + params.BeaconConfig().MinAttestationInclusionDelay)
|
||||
err := beaconState.SetSlot(beaconState.Slot() + 2*params.BeaconConfig().SlotsPerEpoch)
|
||||
require.NoError(t, err)
|
||||
pfc := beaconState.PreviousJustifiedCheckpoint()
|
||||
pfc.Root = []byte("hello-world")
|
||||
require.NoError(t, beaconState.SetPreviousJustifiedCheckpoint(pfc))
|
||||
require.NoError(t, beaconState.SetPreviousEpochAttestations([]*pb.PendingAttestation{}))
|
||||
|
||||
want := fmt.Sprintf(
|
||||
"expected source epoch %d, received %d",
|
||||
helpers.PrevEpoch(beaconState),
|
||||
attestations[0].Data.Source.Epoch,
|
||||
)
|
||||
want := "source check point not equal to previous justified checkpoint"
|
||||
_, err = blocks.ProcessAttestations(context.Background(), beaconState, b)
|
||||
assert.ErrorContains(t, want, err)
|
||||
|
||||
b.Block.Body.Attestations[0].Data.Source.Epoch = helpers.PrevEpoch(beaconState)
|
||||
b.Block.Body.Attestations[0].Data.Target.Epoch = helpers.CurrentEpoch(beaconState)
|
||||
b.Block.Body.Attestations[0].Data.Target.Epoch = helpers.PrevEpoch(beaconState)
|
||||
b.Block.Body.Attestations[0].Data.Source.Root = []byte{}
|
||||
|
||||
want = fmt.Sprintf(
|
||||
"expected source root %#x, received %#x",
|
||||
beaconState.CurrentJustifiedCheckpoint().Root,
|
||||
attestations[0].Data.Source.Root,
|
||||
)
|
||||
_, err = blocks.ProcessAttestations(context.Background(), beaconState, b)
|
||||
assert.ErrorContains(t, want, err)
|
||||
}
|
||||
@@ -226,7 +205,7 @@ func TestProcessAttestations_OK(t *testing.T) {
|
||||
|
||||
committee, err := helpers.BeaconCommitteeFromState(beaconState, att.Data.Slot, att.Data.CommitteeIndex)
|
||||
require.NoError(t, err)
|
||||
attestingIndices := attestationutil.AttestingIndices(att.AggregationBits, committee)
|
||||
attestingIndices, err := attestationutil.AttestingIndices(att.AggregationBits, committee)
|
||||
require.NoError(t, err)
|
||||
sigs := make([]bls.Signature, len(attestingIndices))
|
||||
for i, indice := range attestingIndices {
|
||||
@@ -253,10 +232,9 @@ func TestProcessAggregatedAttestation_OverlappingBits(t *testing.T) {
|
||||
Source: ðpb.Checkpoint{Epoch: 0, Root: bytesutil.PadTo([]byte("hello-world"), 32)},
|
||||
Target: ðpb.Checkpoint{Epoch: 0, Root: bytesutil.PadTo([]byte("hello-world"), 32)},
|
||||
})
|
||||
aggBits1 := bitfield.NewBitlist(4)
|
||||
aggBits1 := bitfield.NewBitlist(3)
|
||||
aggBits1.SetBitAt(0, true)
|
||||
aggBits1.SetBitAt(1, true)
|
||||
aggBits1.SetBitAt(2, true)
|
||||
att1 := ðpb.Attestation{
|
||||
Data: data,
|
||||
AggregationBits: aggBits1,
|
||||
@@ -269,7 +247,7 @@ func TestProcessAggregatedAttestation_OverlappingBits(t *testing.T) {
|
||||
|
||||
committee, err := helpers.BeaconCommitteeFromState(beaconState, att1.Data.Slot, att1.Data.CommitteeIndex)
|
||||
require.NoError(t, err)
|
||||
attestingIndices1 := attestationutil.AttestingIndices(att1.AggregationBits, committee)
|
||||
attestingIndices1, err := attestationutil.AttestingIndices(att1.AggregationBits, committee)
|
||||
require.NoError(t, err)
|
||||
sigs := make([]bls.Signature, len(attestingIndices1))
|
||||
for i, indice := range attestingIndices1 {
|
||||
@@ -281,10 +259,9 @@ func TestProcessAggregatedAttestation_OverlappingBits(t *testing.T) {
|
||||
}
|
||||
att1.Signature = bls.AggregateSignatures(sigs).Marshal()
|
||||
|
||||
aggBits2 := bitfield.NewBitlist(4)
|
||||
aggBits2 := bitfield.NewBitlist(3)
|
||||
aggBits2.SetBitAt(1, true)
|
||||
aggBits2.SetBitAt(2, true)
|
||||
aggBits2.SetBitAt(3, true)
|
||||
att2 := ðpb.Attestation{
|
||||
Data: data,
|
||||
AggregationBits: aggBits2,
|
||||
@@ -292,7 +269,7 @@ func TestProcessAggregatedAttestation_OverlappingBits(t *testing.T) {
|
||||
|
||||
committee, err = helpers.BeaconCommitteeFromState(beaconState, att2.Data.Slot, att2.Data.CommitteeIndex)
|
||||
require.NoError(t, err)
|
||||
attestingIndices2 := attestationutil.AttestingIndices(att2.AggregationBits, committee)
|
||||
attestingIndices2, err := attestationutil.AttestingIndices(att2.AggregationBits, committee)
|
||||
require.NoError(t, err)
|
||||
sigs = make([]bls.Signature, len(attestingIndices2))
|
||||
for i, indice := range attestingIndices2 {
|
||||
@@ -333,7 +310,7 @@ func TestProcessAggregatedAttestation_NoOverlappingBits(t *testing.T) {
|
||||
|
||||
committee, err := helpers.BeaconCommitteeFromState(beaconState, att1.Data.Slot, att1.Data.CommitteeIndex)
|
||||
require.NoError(t, err)
|
||||
attestingIndices1 := attestationutil.AttestingIndices(att1.AggregationBits, committee)
|
||||
attestingIndices1, err := attestationutil.AttestingIndices(att1.AggregationBits, committee)
|
||||
require.NoError(t, err)
|
||||
sigs := make([]bls.Signature, len(attestingIndices1))
|
||||
for i, indice := range attestingIndices1 {
|
||||
@@ -356,7 +333,7 @@ func TestProcessAggregatedAttestation_NoOverlappingBits(t *testing.T) {
|
||||
|
||||
committee, err = helpers.BeaconCommitteeFromState(beaconState, att2.Data.Slot, att2.Data.CommitteeIndex)
|
||||
require.NoError(t, err)
|
||||
attestingIndices2 := attestationutil.AttestingIndices(att2.AggregationBits, committee)
|
||||
attestingIndices2, err := attestationutil.AttestingIndices(att2.AggregationBits, committee)
|
||||
require.NoError(t, err)
|
||||
sigs = make([]bls.Signature, len(attestingIndices2))
|
||||
for i, indice := range attestingIndices2 {
|
||||
@@ -389,7 +366,7 @@ func TestProcessAttestationsNoVerify_IncorrectSlotTargetEpoch(t *testing.T) {
|
||||
Target: ðpb.Checkpoint{Root: make([]byte, 32)},
|
||||
},
|
||||
})
|
||||
wanted := fmt.Sprintf("data slot is not in the same epoch as target %d != %d", helpers.SlotToEpoch(att.Data.Slot), att.Data.Target.Epoch)
|
||||
wanted := "slot 32 does not match target epoch 0"
|
||||
_, err := blocks.ProcessAttestationNoVerifySignature(context.TODO(), beaconState, att)
|
||||
assert.ErrorContains(t, wanted, err)
|
||||
}
|
||||
@@ -474,11 +451,11 @@ func TestConvertToIndexed_OK(t *testing.T) {
|
||||
wantedAttestingIndices: []uint64{43, 47},
|
||||
},
|
||||
{
|
||||
aggregationBitfield: bitfield.Bitlist{0x03},
|
||||
aggregationBitfield: bitfield.Bitlist{0x05},
|
||||
wantedAttestingIndices: []uint64{47},
|
||||
},
|
||||
{
|
||||
aggregationBitfield: bitfield.Bitlist{0x01},
|
||||
aggregationBitfield: bitfield.Bitlist{0x04},
|
||||
wantedAttestingIndices: []uint64{},
|
||||
},
|
||||
}
|
||||
@@ -498,13 +475,14 @@ func TestConvertToIndexed_OK(t *testing.T) {
|
||||
|
||||
committee, err := helpers.BeaconCommitteeFromState(state, attestation.Data.Slot, attestation.Data.CommitteeIndex)
|
||||
require.NoError(t, err)
|
||||
ia := attestationutil.ConvertToIndexed(context.Background(), attestation, committee)
|
||||
ia, err := attestationutil.ConvertToIndexed(context.Background(), attestation, committee)
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, wanted, ia, "Convert attestation to indexed attestation didn't result as wanted")
|
||||
}
|
||||
}
|
||||
|
||||
func TestVerifyIndexedAttestation_OK(t *testing.T) {
|
||||
numOfValidators := 4 * params.BeaconConfig().SlotsPerEpoch
|
||||
numOfValidators := uint64(params.BeaconConfig().SlotsPerEpoch.Mul(4))
|
||||
validators := make([]*ethpb.Validator, numOfValidators)
|
||||
_, keys, err := testutil.DeterministicDepositsAndKeys(numOfValidators)
|
||||
require.NoError(t, err)
|
||||
@@ -597,7 +575,7 @@ func TestValidateIndexedAttestation_AboveMaxLength(t *testing.T) {
|
||||
indexedAtt1.AttestingIndices[i] = i
|
||||
indexedAtt1.Data = ðpb.AttestationData{
|
||||
Target: ðpb.Checkpoint{
|
||||
Epoch: i,
|
||||
Epoch: types.Epoch(i),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -608,10 +586,10 @@ func TestValidateIndexedAttestation_AboveMaxLength(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestValidateIndexedAttestation_BadAttestationsSignatureSet(t *testing.T) {
|
||||
beaconState, keys := testutil.DeterministicGenesisState(t, 1000)
|
||||
beaconState, keys := testutil.DeterministicGenesisState(t, 128)
|
||||
|
||||
sig := keys[0].Sign([]byte{'t', 'e', 's', 't'})
|
||||
list := bitfield.Bitlist{0b11111111}
|
||||
list := bitfield.Bitlist{0b11111}
|
||||
var atts []*ethpb.Attestation
|
||||
for i := uint64(0); i < 1000; i++ {
|
||||
atts = append(atts, ðpb.Attestation{
|
||||
@@ -629,7 +607,7 @@ func TestValidateIndexedAttestation_BadAttestationsSignatureSet(t *testing.T) {
|
||||
assert.ErrorContains(t, want, err)
|
||||
|
||||
atts = []*ethpb.Attestation{}
|
||||
list = bitfield.Bitlist{0b00000000}
|
||||
list = bitfield.Bitlist{0b10000}
|
||||
for i := uint64(0); i < 1000; i++ {
|
||||
atts = append(atts, ðpb.Attestation{
|
||||
Data: ðpb.AttestationData{
|
||||
@@ -649,70 +627,9 @@ func TestValidateIndexedAttestation_BadAttestationsSignatureSet(t *testing.T) {
|
||||
assert.ErrorContains(t, want, err)
|
||||
}
|
||||
|
||||
func TestVerifyAttestations_VerifiesMultipleAttestations(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
numOfValidators := 4 * params.BeaconConfig().SlotsPerEpoch
|
||||
validators := make([]*ethpb.Validator, numOfValidators)
|
||||
_, keys, err := testutil.DeterministicDepositsAndKeys(numOfValidators)
|
||||
require.NoError(t, err)
|
||||
for i := 0; i < len(validators); i++ {
|
||||
validators[i] = ðpb.Validator{
|
||||
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
|
||||
PublicKey: keys[i].PublicKey().Marshal(),
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
}
|
||||
}
|
||||
|
||||
st := testutil.NewBeaconState()
|
||||
require.NoError(t, st.SetSlot(5))
|
||||
require.NoError(t, st.SetValidators(validators))
|
||||
|
||||
comm1, err := helpers.BeaconCommitteeFromState(st, 1 /*slot*/, 0 /*committeeIndex*/)
|
||||
require.NoError(t, err)
|
||||
att1 := testutil.HydrateAttestation(ðpb.Attestation{
|
||||
AggregationBits: bitfield.NewBitlist(uint64(len(comm1))),
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 1,
|
||||
},
|
||||
})
|
||||
domain, err := helpers.Domain(st.Fork(), st.Fork().Epoch, params.BeaconConfig().DomainBeaconAttester, st.GenesisValidatorRoot())
|
||||
require.NoError(t, err)
|
||||
root, err := helpers.ComputeSigningRoot(att1.Data, domain)
|
||||
require.NoError(t, err)
|
||||
var sigs []bls.Signature
|
||||
for i, u := range comm1 {
|
||||
att1.AggregationBits.SetBitAt(uint64(i), true)
|
||||
sigs = append(sigs, keys[u].Sign(root[:]))
|
||||
}
|
||||
att1.Signature = bls.AggregateSignatures(sigs).Marshal()
|
||||
|
||||
comm2, err := helpers.BeaconCommitteeFromState(st, 1 /*slot*/, 1 /*committeeIndex*/)
|
||||
require.NoError(t, err)
|
||||
att2 := testutil.HydrateAttestation(ðpb.Attestation{
|
||||
AggregationBits: bitfield.NewBitlist(uint64(len(comm2))),
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 1,
|
||||
CommitteeIndex: 1,
|
||||
},
|
||||
})
|
||||
root, err = helpers.ComputeSigningRoot(att2.Data, domain)
|
||||
require.NoError(t, err)
|
||||
sigs = nil
|
||||
for i, u := range comm2 {
|
||||
att2.AggregationBits.SetBitAt(uint64(i), true)
|
||||
sigs = append(sigs, keys[u].Sign(root[:]))
|
||||
}
|
||||
att2.Signature = bls.AggregateSignatures(sigs).Marshal()
|
||||
|
||||
b := testutil.NewBeaconBlock()
|
||||
b.Block.Body.Attestations = []*ethpb.Attestation{att1, att2}
|
||||
require.NoError(t, blocks.VerifyAttestationsSignatures(ctx, st, b))
|
||||
}
|
||||
|
||||
func TestVerifyAttestations_HandlesPlannedFork(t *testing.T) {
|
||||
// In this test, att1 is from the prior fork and att2 is from the new fork.
|
||||
ctx := context.Background()
|
||||
numOfValidators := 4 * params.BeaconConfig().SlotsPerEpoch
|
||||
numOfValidators := uint64(params.BeaconConfig().SlotsPerEpoch.Mul(4))
|
||||
validators := make([]*ethpb.Validator, numOfValidators)
|
||||
_, keys, err := testutil.DeterministicDepositsAndKeys(numOfValidators)
|
||||
require.NoError(t, err)
|
||||
@@ -724,7 +641,8 @@ func TestVerifyAttestations_HandlesPlannedFork(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
st := testutil.NewBeaconState()
|
||||
st, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, st.SetSlot(35))
|
||||
require.NoError(t, st.SetValidators(validators))
|
||||
require.NoError(t, st.SetFork(&pb.Fork{
|
||||
@@ -771,15 +689,11 @@ func TestVerifyAttestations_HandlesPlannedFork(t *testing.T) {
|
||||
sigs = append(sigs, keys[u].Sign(root[:]))
|
||||
}
|
||||
att2.Signature = bls.AggregateSignatures(sigs).Marshal()
|
||||
|
||||
b := testutil.NewBeaconBlock()
|
||||
b.Block.Body.Attestations = []*ethpb.Attestation{att1, att2}
|
||||
require.NoError(t, blocks.VerifyAttestationsSignatures(ctx, st, b))
|
||||
}
|
||||
|
||||
func TestRetrieveAttestationSignatureSet_VerifiesMultipleAttestations(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
numOfValidators := 4 * params.BeaconConfig().SlotsPerEpoch
|
||||
numOfValidators := uint64(params.BeaconConfig().SlotsPerEpoch.Mul(4))
|
||||
validators := make([]*ethpb.Validator, numOfValidators)
|
||||
_, keys, err := testutil.DeterministicDepositsAndKeys(numOfValidators)
|
||||
require.NoError(t, err)
|
||||
@@ -791,7 +705,8 @@ func TestRetrieveAttestationSignatureSet_VerifiesMultipleAttestations(t *testing
|
||||
}
|
||||
}
|
||||
|
||||
st := testutil.NewBeaconState()
|
||||
st, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, st.SetSlot(5))
|
||||
require.NoError(t, st.SetValidators(validators))
|
||||
|
||||
|
||||
@@ -38,8 +38,8 @@ func ProcessAttesterSlashings(
|
||||
beaconState *stateTrie.BeaconState,
|
||||
b *ethpb.SignedBeaconBlock,
|
||||
) (*stateTrie.BeaconState, error) {
|
||||
if b.Block == nil || b.Block.Body == nil {
|
||||
return nil, errors.New("block and block body can't be nil")
|
||||
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
body := b.Block.Body
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
@@ -43,7 +44,7 @@ func TestProcessAttesterSlashings_DataNotSlashable(t *testing.T) {
|
||||
})}}
|
||||
|
||||
var registry []*ethpb.Validator
|
||||
currentSlot := uint64(0)
|
||||
currentSlot := types.Slot(0)
|
||||
|
||||
beaconState, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
||||
Validators: registry,
|
||||
@@ -62,7 +63,7 @@ func TestProcessAttesterSlashings_DataNotSlashable(t *testing.T) {
|
||||
|
||||
func TestProcessAttesterSlashings_IndexedAttestationFailedToVerify(t *testing.T) {
|
||||
var registry []*ethpb.Validator
|
||||
currentSlot := uint64(0)
|
||||
currentSlot := types.Slot(0)
|
||||
|
||||
beaconState, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
||||
Validators: registry,
|
||||
@@ -98,7 +99,7 @@ func TestProcessAttesterSlashings_IndexedAttestationFailedToVerify(t *testing.T)
|
||||
func TestProcessAttesterSlashings_AppliesCorrectStatus(t *testing.T) {
|
||||
beaconState, privKeys := testutil.DeterministicGenesisState(t, 100)
|
||||
for _, vv := range beaconState.Validators() {
|
||||
vv.WithdrawableEpoch = 1 * params.BeaconConfig().SlotsPerEpoch
|
||||
vv.WithdrawableEpoch = types.Epoch(params.BeaconConfig().SlotsPerEpoch)
|
||||
}
|
||||
|
||||
att1 := testutil.HydrateIndexedAttestation(ðpb.IndexedAttestation{
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"testing"
|
||||
|
||||
fuzz "github.com/google/gofuzz"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
eth "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
@@ -431,7 +432,7 @@ func TestFuzzVerifyExit_10000(t *testing.T) {
|
||||
ve := ð.SignedVoluntaryExit{}
|
||||
val := stateTrie.ReadOnlyValidator{}
|
||||
fork := &pb.Fork{}
|
||||
var slot uint64
|
||||
var slot types.Slot
|
||||
|
||||
for i := 0; i < 10000; i++ {
|
||||
fuzzer.Fuzz(ve)
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
@@ -18,7 +19,7 @@ func TestProcessAttesterSlashings_RegressionSlashableIndices(t *testing.T) {
|
||||
testutil.ResetCache()
|
||||
beaconState, privKeys := testutil.DeterministicGenesisState(t, 5500)
|
||||
for _, vv := range beaconState.Validators() {
|
||||
vv.WithdrawableEpoch = 1 * params.BeaconConfig().SlotsPerEpoch
|
||||
vv.WithdrawableEpoch = types.Epoch(params.BeaconConfig().SlotsPerEpoch)
|
||||
}
|
||||
// This set of indices is very similar to the one from our sapphire testnet
|
||||
// when close to 100 validators were incorrectly slashed. The set is from 0 -5500,
|
||||
|
||||
@@ -70,8 +70,8 @@ func ProcessDeposits(
|
||||
beaconState *stateTrie.BeaconState,
|
||||
b *ethpb.SignedBeaconBlock,
|
||||
) (*stateTrie.BeaconState, error) {
|
||||
if b.Block == nil || b.Block.Body == nil {
|
||||
return nil, errors.New("block and block body can't be nil")
|
||||
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
deposits := b.Block.Body.Deposits
|
||||
@@ -251,19 +251,11 @@ func verifyDepositDataWithDomain(ctx context.Context, deps []*ethpb.Deposit, dom
|
||||
WithdrawalCredentials: dep.Data.WithdrawalCredentials,
|
||||
Amount: dep.Data.Amount,
|
||||
}
|
||||
root, err := depositMessage.HashTreeRoot()
|
||||
sr, err := helpers.ComputeSigningRoot(depositMessage, domain)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get signing root")
|
||||
return err
|
||||
}
|
||||
signingData := &pb.SigningData{
|
||||
ObjectRoot: root[:],
|
||||
Domain: domain,
|
||||
}
|
||||
ctrRoot, err := signingData.HashTreeRoot()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get container root")
|
||||
}
|
||||
msgs[i] = ctrRoot
|
||||
msgs[i] = sr
|
||||
}
|
||||
verify, err := bls.VerifyMultipleSignatures(sigs, msgs, pks)
|
||||
if err != nil {
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
@@ -319,8 +320,8 @@ func TestPreGenesisDeposits_SkipInvalidDeposit(t *testing.T) {
|
||||
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)
|
||||
require.Equal(t, types.Epoch(0), val.ActivationEpoch)
|
||||
require.Equal(t, types.Epoch(0), val.ActivationEligibilityEpoch)
|
||||
}
|
||||
if newState.Eth1DepositIndex() != 100 {
|
||||
t.Errorf(
|
||||
|
||||
@@ -71,6 +71,6 @@ func Eth1DataHasEnoughSupport(beaconState *stateTrie.BeaconState, data *ethpb.Et
|
||||
|
||||
// If 50+% majority converged on the same eth1data, then it has enough support to update the
|
||||
// state.
|
||||
support := params.BeaconConfig().EpochsPerEth1VotingPeriod * params.BeaconConfig().SlotsPerEpoch
|
||||
return voteCount*2 > support, nil
|
||||
support := params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().EpochsPerEth1VotingPeriod))
|
||||
return voteCount*2 > uint64(support), nil
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
@@ -33,10 +34,10 @@ func TestEth1DataHasEnoughSupport(t *testing.T) {
|
||||
stateVotes []*ethpb.Eth1Data
|
||||
data *ethpb.Eth1Data
|
||||
hasSupport bool
|
||||
votingPeriodLength uint64
|
||||
votingPeriodLength types.Epoch
|
||||
}{
|
||||
{
|
||||
stateVotes: FakeDeposits(4 * params.BeaconConfig().SlotsPerEpoch),
|
||||
stateVotes: FakeDeposits(uint64(params.BeaconConfig().SlotsPerEpoch.Mul(4))),
|
||||
data: ðpb.Eth1Data{
|
||||
DepositCount: 1,
|
||||
DepositRoot: bytesutil.PadTo([]byte("root"), 32),
|
||||
@@ -44,7 +45,7 @@ func TestEth1DataHasEnoughSupport(t *testing.T) {
|
||||
hasSupport: true,
|
||||
votingPeriodLength: 7,
|
||||
}, {
|
||||
stateVotes: FakeDeposits(4 * params.BeaconConfig().SlotsPerEpoch),
|
||||
stateVotes: FakeDeposits(uint64(params.BeaconConfig().SlotsPerEpoch.Mul(4))),
|
||||
data: ðpb.Eth1Data{
|
||||
DepositCount: 1,
|
||||
DepositRoot: bytesutil.PadTo([]byte("root"), 32),
|
||||
@@ -52,7 +53,7 @@ func TestEth1DataHasEnoughSupport(t *testing.T) {
|
||||
hasSupport: false,
|
||||
votingPeriodLength: 8,
|
||||
}, {
|
||||
stateVotes: FakeDeposits(4 * params.BeaconConfig().SlotsPerEpoch),
|
||||
stateVotes: FakeDeposits(uint64(params.BeaconConfig().SlotsPerEpoch.Mul(4))),
|
||||
data: ðpb.Eth1Data{
|
||||
DepositCount: 1,
|
||||
DepositRoot: bytesutil.PadTo([]byte("root"), 32),
|
||||
@@ -174,7 +175,7 @@ func TestProcessEth1Data_SetsCorrectly(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
period := params.BeaconConfig().EpochsPerEth1VotingPeriod * params.BeaconConfig().SlotsPerEpoch
|
||||
period := uint64(params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().EpochsPerEth1VotingPeriod)))
|
||||
for i := uint64(0); i < period; i++ {
|
||||
beaconState, err = blocks.ProcessEth1DataInBlock(context.Background(), beaconState, b)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
v "github.com/prysmaticlabs/prysm/beacon-chain/core/validators"
|
||||
@@ -48,8 +49,8 @@ func ProcessVoluntaryExits(
|
||||
beaconState *stateTrie.BeaconState,
|
||||
b *ethpb.SignedBeaconBlock,
|
||||
) (*stateTrie.BeaconState, error) {
|
||||
if b.Block == nil || b.Block.Body == nil {
|
||||
return nil, errors.New("block and block body can't be nil")
|
||||
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
body := b.Block.Body
|
||||
@@ -73,39 +74,6 @@ func ProcessVoluntaryExits(
|
||||
return beaconState, nil
|
||||
}
|
||||
|
||||
// ProcessVoluntaryExitsNoVerifySignature processes all the voluntary exits in
|
||||
// a block body, without verifying their BLS signatures.
|
||||
// This function is here to satisfy fuzz tests.
|
||||
func ProcessVoluntaryExitsNoVerifySignature(
|
||||
beaconState *stateTrie.BeaconState,
|
||||
body *ethpb.BeaconBlockBody,
|
||||
) (*stateTrie.BeaconState, error) {
|
||||
exits := body.VoluntaryExits
|
||||
|
||||
for idx, exit := range exits {
|
||||
if exit == nil || exit.Exit == nil {
|
||||
return nil, errors.New("nil exit")
|
||||
}
|
||||
val, err := beaconState.ValidatorAtIndexReadOnly(exit.Exit.ValidatorIndex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := verifyExitConditions(val, beaconState.Slot(), exit.Exit); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Validate that fork and genesis root are valid.
|
||||
_, err = helpers.Domain(beaconState.Fork(), exit.Exit.Epoch, params.BeaconConfig().DomainVoluntaryExit, beaconState.GenesisValidatorRoot())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
beaconState, err = v.InitiateValidatorExit(beaconState, exit.Exit.ValidatorIndex)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to process voluntary exit at index %d", idx)
|
||||
}
|
||||
}
|
||||
return beaconState, nil
|
||||
}
|
||||
|
||||
// VerifyExitAndSignature implements the spec defined validation for voluntary exits.
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
@@ -125,7 +93,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 types.Slot, fork *pb.Fork, signed *ethpb.SignedVoluntaryExit, genesisRoot []byte) error {
|
||||
if signed == nil || signed.Exit == nil {
|
||||
return errors.New("nil exit")
|
||||
}
|
||||
@@ -161,7 +129,7 @@ func VerifyExitAndSignature(validator stateTrie.ReadOnlyValidator, currentSlot u
|
||||
// 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 types.Slot, exit *ethpb.VoluntaryExit) error {
|
||||
currentEpoch := helpers.SlotToEpoch(currentSlot)
|
||||
// Verify the validator is active.
|
||||
if !helpers.IsActiveValidatorUsingTrie(validator, currentEpoch) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
@@ -16,73 +17,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
)
|
||||
|
||||
func TestProcessVoluntaryExits_ValidatorNotActive(t *testing.T) {
|
||||
exits := []*ethpb.SignedVoluntaryExit{
|
||||
{
|
||||
Exit: ðpb.VoluntaryExit{
|
||||
ValidatorIndex: 0,
|
||||
},
|
||||
},
|
||||
}
|
||||
registry := []*ethpb.Validator{
|
||||
{
|
||||
ExitEpoch: 0,
|
||||
},
|
||||
}
|
||||
state, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
||||
Validators: registry,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
b := testutil.NewBeaconBlock()
|
||||
b.Block = ðpb.BeaconBlock{
|
||||
Body: ðpb.BeaconBlockBody{
|
||||
VoluntaryExits: exits,
|
||||
},
|
||||
}
|
||||
|
||||
want := "non-active validator cannot exit"
|
||||
_, err = blocks.ProcessVoluntaryExits(context.Background(), state, b)
|
||||
assert.ErrorContains(t, want, err)
|
||||
|
||||
// Check conformance of no verify method.
|
||||
_, err = blocks.ProcessVoluntaryExitsNoVerifySignature(state, b.Block.Body)
|
||||
assert.ErrorContains(t, want, err)
|
||||
}
|
||||
|
||||
func TestProcessVoluntaryExits_InvalidExitEpoch(t *testing.T) {
|
||||
exits := []*ethpb.SignedVoluntaryExit{
|
||||
{
|
||||
Exit: ðpb.VoluntaryExit{
|
||||
Epoch: 10,
|
||||
},
|
||||
},
|
||||
}
|
||||
registry := []*ethpb.Validator{
|
||||
{
|
||||
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
|
||||
},
|
||||
}
|
||||
state, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
||||
Validators: registry,
|
||||
Slot: 0,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
b := testutil.NewBeaconBlock()
|
||||
b.Block = ðpb.BeaconBlock{
|
||||
Body: ðpb.BeaconBlockBody{
|
||||
VoluntaryExits: exits,
|
||||
},
|
||||
}
|
||||
|
||||
want := "expected current epoch >= exit epoch"
|
||||
_, err = blocks.ProcessVoluntaryExits(context.Background(), state, b)
|
||||
assert.ErrorContains(t, want, err)
|
||||
|
||||
// Check conformance of no verify method.
|
||||
_, err = blocks.ProcessVoluntaryExitsNoVerifySignature(state, b.Block.Body)
|
||||
assert.ErrorContains(t, want, err)
|
||||
}
|
||||
|
||||
func TestProcessVoluntaryExits_NotActiveLongEnoughToExit(t *testing.T) {
|
||||
exits := []*ethpb.SignedVoluntaryExit{
|
||||
{
|
||||
@@ -168,7 +102,7 @@ func TestProcessVoluntaryExits_AppliesCorrectStatus(t *testing.T) {
|
||||
Slot: params.BeaconConfig().SlotsPerEpoch * 5,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
err = state.SetSlot(state.Slot() + (params.BeaconConfig().ShardCommitteePeriod * params.BeaconConfig().SlotsPerEpoch))
|
||||
err = state.SetSlot(state.Slot() + params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().ShardCommitteePeriod)))
|
||||
require.NoError(t, err)
|
||||
|
||||
priv, err := bls.RandKey()
|
||||
@@ -188,21 +122,11 @@ func TestProcessVoluntaryExits_AppliesCorrectStatus(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
stateCopy := state.Copy()
|
||||
newState, err := blocks.ProcessVoluntaryExits(context.Background(), state, b)
|
||||
require.NoError(t, err, "Could not process exits")
|
||||
newRegistry := newState.Validators()
|
||||
if newRegistry[0].ExitEpoch != helpers.ActivationExitEpoch(state.Slot()/params.BeaconConfig().SlotsPerEpoch) {
|
||||
if newRegistry[0].ExitEpoch != helpers.ActivationExitEpoch(types.Epoch(state.Slot()/params.BeaconConfig().SlotsPerEpoch)) {
|
||||
t.Errorf("Expected validator exit epoch to be %d, got %d",
|
||||
helpers.ActivationExitEpoch(state.Slot()/params.BeaconConfig().SlotsPerEpoch), newRegistry[0].ExitEpoch)
|
||||
}
|
||||
|
||||
// Check conformance with NoVerify Exit Method.
|
||||
newState, err = blocks.ProcessVoluntaryExitsNoVerifySignature(stateCopy, b.Block.Body)
|
||||
require.NoError(t, err, "Could not process exits")
|
||||
newRegistry = newState.Validators()
|
||||
if newRegistry[0].ExitEpoch != helpers.ActivationExitEpoch(stateCopy.Slot()/params.BeaconConfig().SlotsPerEpoch) {
|
||||
t.Errorf("Expected validator exit epoch to be %d, got %d",
|
||||
helpers.ActivationExitEpoch(stateCopy.Slot()/params.BeaconConfig().SlotsPerEpoch), newRegistry[0].ExitEpoch)
|
||||
helpers.ActivationExitEpoch(types.Epoch(state.Slot()/params.BeaconConfig().SlotsPerEpoch)), newRegistry[0].ExitEpoch)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,16 +7,16 @@ import (
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
p2ptypes "github.com/prysmaticlabs/prysm/beacon-chain/p2p/types"
|
||||
"github.com/prysmaticlabs/prysm/shared/bls"
|
||||
"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"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -34,7 +34,8 @@ func TestProcessBlockHeader_ImproperBlockSlot(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
state := testutil.NewBeaconState()
|
||||
state, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, state.SetSlot(10))
|
||||
require.NoError(t, state.SetValidators(validators))
|
||||
require.NoError(t, state.SetLatestBlockHeader(testutil.HydrateBeaconHeader(ðpb.BeaconBlockHeader{
|
||||
@@ -106,7 +107,8 @@ func TestProcessBlockHeader_DifferentSlots(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
state := testutil.NewBeaconState()
|
||||
state, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, state.SetValidators(validators))
|
||||
require.NoError(t, state.SetSlot(10))
|
||||
require.NoError(t, state.SetLatestBlockHeader(testutil.HydrateBeaconHeader(ðpb.BeaconBlockHeader{
|
||||
@@ -119,7 +121,8 @@ func TestProcessBlockHeader_DifferentSlots(t *testing.T) {
|
||||
|
||||
priv, err := bls.RandKey()
|
||||
require.NoError(t, err)
|
||||
blockSig, err := helpers.ComputeDomainAndSign(state, currentEpoch, []byte("hello"), params.BeaconConfig().DomainBeaconProposer, priv)
|
||||
sszBytes := p2ptypes.SSZBytes("hello")
|
||||
blockSig, err := helpers.ComputeDomainAndSign(state, currentEpoch, &sszBytes, params.BeaconConfig().DomainBeaconProposer, priv)
|
||||
require.NoError(t, err)
|
||||
validators[5896].PublicKey = priv.PublicKey().Marshal()
|
||||
block := ðpb.SignedBeaconBlock{
|
||||
@@ -149,7 +152,8 @@ func TestProcessBlockHeader_PreviousBlockRootNotSignedRoot(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
state := testutil.NewBeaconState()
|
||||
state, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, state.SetValidators(validators))
|
||||
require.NoError(t, state.SetSlot(10))
|
||||
bh := state.LatestBlockHeader()
|
||||
@@ -158,7 +162,8 @@ func TestProcessBlockHeader_PreviousBlockRootNotSignedRoot(t *testing.T) {
|
||||
currentEpoch := helpers.CurrentEpoch(state)
|
||||
priv, err := bls.RandKey()
|
||||
require.NoError(t, err)
|
||||
blockSig, err := helpers.ComputeDomainAndSign(state, currentEpoch, []byte("hello"), params.BeaconConfig().DomainBeaconProposer, priv)
|
||||
sszBytes := p2ptypes.SSZBytes("hello")
|
||||
blockSig, err := helpers.ComputeDomainAndSign(state, currentEpoch, &sszBytes, params.BeaconConfig().DomainBeaconProposer, priv)
|
||||
require.NoError(t, err)
|
||||
validators[5896].PublicKey = priv.PublicKey().Marshal()
|
||||
pID, err := helpers.BeaconProposerIndex(state)
|
||||
@@ -186,7 +191,8 @@ func TestProcessBlockHeader_SlashedProposer(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
state := testutil.NewBeaconState()
|
||||
state, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, state.SetValidators(validators))
|
||||
require.NoError(t, state.SetSlot(10))
|
||||
bh := state.LatestBlockHeader()
|
||||
@@ -197,7 +203,8 @@ func TestProcessBlockHeader_SlashedProposer(t *testing.T) {
|
||||
currentEpoch := helpers.CurrentEpoch(state)
|
||||
priv, err := bls.RandKey()
|
||||
require.NoError(t, err)
|
||||
blockSig, err := helpers.ComputeDomainAndSign(state, currentEpoch, []byte("hello"), params.BeaconConfig().DomainBeaconProposer, priv)
|
||||
sszBytes := p2ptypes.SSZBytes("hello")
|
||||
blockSig, err := helpers.ComputeDomainAndSign(state, currentEpoch, &sszBytes, params.BeaconConfig().DomainBeaconProposer, priv)
|
||||
require.NoError(t, err)
|
||||
|
||||
validators[12683].PublicKey = priv.PublicKey().Marshal()
|
||||
@@ -226,7 +233,8 @@ func TestProcessBlockHeader_OK(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
state := testutil.NewBeaconState()
|
||||
state, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, state.SetValidators(validators))
|
||||
require.NoError(t, state.SetSlot(10))
|
||||
require.NoError(t, state.SetLatestBlockHeader(testutil.HydrateBeaconHeader(ðpb.BeaconBlockHeader{
|
||||
@@ -283,7 +291,8 @@ func TestBlockSignatureSet_OK(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
state := testutil.NewBeaconState()
|
||||
state, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, state.SetValidators(validators))
|
||||
require.NoError(t, state.SetSlot(10))
|
||||
require.NoError(t, state.SetLatestBlockHeader(testutil.HydrateBeaconHeader(ðpb.BeaconBlockHeader{
|
||||
|
||||
@@ -41,8 +41,8 @@ func ProcessProposerSlashings(
|
||||
beaconState *stateTrie.BeaconState,
|
||||
b *ethpb.SignedBeaconBlock,
|
||||
) (*stateTrie.BeaconState, error) {
|
||||
if b.Block == nil || b.Block.Body == nil {
|
||||
return nil, errors.New("block and block body can't be nil")
|
||||
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
body := b.Block.Body
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
@@ -21,7 +22,7 @@ import (
|
||||
func TestProcessProposerSlashings_UnmatchedHeaderSlots(t *testing.T) {
|
||||
testutil.ResetCache()
|
||||
beaconState, _ := testutil.DeterministicGenesisState(t, 20)
|
||||
currentSlot := uint64(0)
|
||||
currentSlot := types.Slot(0)
|
||||
slashings := []*ethpb.ProposerSlashing{
|
||||
{
|
||||
Header_1: ðpb.SignedBeaconBlockHeader{
|
||||
@@ -54,7 +55,7 @@ func TestProcessProposerSlashings_UnmatchedHeaderSlots(t *testing.T) {
|
||||
func TestProcessProposerSlashings_SameHeaders(t *testing.T) {
|
||||
testutil.ResetCache()
|
||||
beaconState, _ := testutil.DeterministicGenesisState(t, 2)
|
||||
currentSlot := uint64(0)
|
||||
currentSlot := types.Slot(0)
|
||||
slashings := []*ethpb.ProposerSlashing{
|
||||
{
|
||||
Header_1: ðpb.SignedBeaconBlockHeader{
|
||||
@@ -93,7 +94,7 @@ func TestProcessProposerSlashings_ValidatorNotSlashable(t *testing.T) {
|
||||
WithdrawableEpoch: 0,
|
||||
},
|
||||
}
|
||||
currentSlot := uint64(0)
|
||||
currentSlot := types.Slot(0)
|
||||
slashings := []*ethpb.ProposerSlashing{
|
||||
{
|
||||
Header_1: ðpb.SignedBeaconBlockHeader{
|
||||
@@ -186,7 +187,7 @@ func TestVerifyProposerSlashing(t *testing.T) {
|
||||
}
|
||||
|
||||
beaconState, sks := testutil.DeterministicGenesisState(t, 2)
|
||||
currentSlot := uint64(0)
|
||||
currentSlot := types.Slot(0)
|
||||
require.NoError(t, beaconState.SetSlot(currentSlot))
|
||||
rand1, err := bls.RandKey()
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -30,10 +30,9 @@ func ProcessRandao(
|
||||
beaconState *stateTrie.BeaconState,
|
||||
b *ethpb.SignedBeaconBlock,
|
||||
) (*stateTrie.BeaconState, error) {
|
||||
if b.Block == nil || b.Block.Body == nil {
|
||||
return nil, errors.New("block and block body can't be nil")
|
||||
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
body := b.Block.Body
|
||||
buf, proposerPub, domain, err := randaoSigningData(beaconState)
|
||||
if err != nil {
|
||||
@@ -67,7 +66,7 @@ func ProcessRandaoNoVerify(
|
||||
// If block randao passed verification, we XOR the state's latest randao mix with the block's
|
||||
// randao and update the state's corresponding latest randao mix value.
|
||||
latestMixesLength := params.BeaconConfig().EpochsPerHistoricalVector
|
||||
latestMixSlice, err := beaconState.RandaoMixAtIndex(currentEpoch % latestMixesLength)
|
||||
latestMixSlice, err := beaconState.RandaoMixAtIndex(uint64(currentEpoch % latestMixesLength))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -78,7 +77,7 @@ func ProcessRandaoNoVerify(
|
||||
for i, x := range blockRandaoReveal {
|
||||
latestMixSlice[i] ^= x
|
||||
}
|
||||
if err := beaconState.UpdateRandaoMixesAtIndex(currentEpoch%latestMixesLength, latestMixSlice); err != nil {
|
||||
if err := beaconState.UpdateRandaoMixesAtIndex(uint64(currentEpoch%latestMixesLength), latestMixSlice); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return beaconState, nil
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package blocks_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"testing"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
@@ -21,9 +21,9 @@ func TestProcessRandao_IncorrectProposerFailsVerification(t *testing.T) {
|
||||
// We fetch the proposer's index as that is whom the RANDAO will be verified against.
|
||||
proposerIdx, err := helpers.BeaconProposerIndex(beaconState)
|
||||
require.NoError(t, err)
|
||||
epoch := uint64(0)
|
||||
epoch := types.Epoch(0)
|
||||
buf := make([]byte, 32)
|
||||
binary.LittleEndian.PutUint64(buf, epoch)
|
||||
binary.LittleEndian.PutUint64(buf, uint64(epoch))
|
||||
domain, err := helpers.Domain(beaconState.Fork(), epoch, params.BeaconConfig().DomainRandao, beaconState.GenesisValidatorRoot())
|
||||
require.NoError(t, err)
|
||||
root, err := (&pb.SigningData{ObjectRoot: buf, Domain: domain}).HashTreeRoot()
|
||||
@@ -64,13 +64,7 @@ func TestProcessRandao_SignatureVerifiesAndUpdatesLatestStateMixes(t *testing.T)
|
||||
require.NoError(t, err, "Unexpected error processing block randao")
|
||||
currentEpoch := helpers.CurrentEpoch(beaconState)
|
||||
mix := newState.RandaoMixes()[currentEpoch%params.BeaconConfig().EpochsPerHistoricalVector]
|
||||
|
||||
if bytes.Equal(mix, params.BeaconConfig().ZeroHash[:]) {
|
||||
t.Errorf(
|
||||
"Expected empty signature to be overwritten by randao reveal, received %v",
|
||||
params.BeaconConfig().EmptySignature,
|
||||
)
|
||||
}
|
||||
assert.DeepNotEqual(t, params.BeaconConfig().ZeroHash[:], mix, "Expected empty signature to be overwritten by randao reveal")
|
||||
}
|
||||
|
||||
func TestRandaoSignatureSet_OK(t *testing.T) {
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
)
|
||||
|
||||
// retrieves the signature set from the raw data, public key,signature and domain provided.
|
||||
func retrieveSignatureSet(signedData, pub, signature, domain []byte) (*bls.SignatureSet, error) {
|
||||
func signatureSet(signedData, pub, signature, domain []byte) (*bls.SignatureSet, error) {
|
||||
publicKey, err := bls.PublicKeyFromBytes(pub)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not convert bytes to public key")
|
||||
@@ -37,7 +37,7 @@ func retrieveSignatureSet(signedData, pub, signature, domain []byte) (*bls.Signa
|
||||
|
||||
// verifies the signature from the raw data, public key and domain provided.
|
||||
func verifySignature(signedData, pub, signature, domain []byte) error {
|
||||
set, err := retrieveSignatureSet(signedData, pub, signature, domain)
|
||||
set, err := signatureSet(signedData, pub, signature, domain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -85,7 +85,7 @@ func BlockSignatureSet(beaconState *stateTrie.BeaconState, block *ethpb.SignedBe
|
||||
return nil, err
|
||||
}
|
||||
proposerPubKey := proposer.PublicKey
|
||||
return helpers.RetrieveBlockSignatureSet(block.Block, proposerPubKey, block.Signature, domain)
|
||||
return helpers.BlockSignatureSet(block.Block, proposerPubKey, block.Signature, domain)
|
||||
}
|
||||
|
||||
// RandaoSignatureSet retrieves the relevant randao specific signature set object
|
||||
@@ -97,7 +97,7 @@ func RandaoSignatureSet(beaconState *stateTrie.BeaconState,
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
set, err := retrieveSignatureSet(buf, proposerPub, body.RandaoReveal, domain)
|
||||
set, err := signatureSet(buf, proposerPub, body.RandaoReveal, domain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -114,7 +114,7 @@ func randaoSigningData(beaconState *stateTrie.BeaconState) ([]byte, []byte, []by
|
||||
|
||||
currentEpoch := helpers.SlotToEpoch(beaconState.Slot())
|
||||
buf := make([]byte, 32)
|
||||
binary.LittleEndian.PutUint64(buf, currentEpoch)
|
||||
binary.LittleEndian.PutUint64(buf, uint64(currentEpoch))
|
||||
|
||||
domain, err := helpers.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainRandao, beaconState.GenesisValidatorRoot())
|
||||
if err != nil {
|
||||
@@ -138,7 +138,10 @@ func createAttestationSignatureSet(ctx context.Context, beaconState *stateTrie.B
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ia := attestationutil.ConvertToIndexed(ctx, a, c)
|
||||
ia, err := attestationutil.ConvertToIndexed(ctx, a, c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := attestationutil.IsValidAttestationIndices(ctx, ia); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -44,7 +44,6 @@ go_test(
|
||||
"//shared/testutil/require:go_default_library",
|
||||
"@com_github_gogo_protobuf//proto:go_default_library",
|
||||
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
|
||||
"@in_gopkg_d4l3k_messagediff_v1//:go_default_library",
|
||||
"@io_bazel_rules_go//go/tools/bazel:go_default_library",
|
||||
],
|
||||
@@ -80,7 +79,6 @@ go_test(
|
||||
"//shared/testutil/require:go_default_library",
|
||||
"@com_github_gogo_protobuf//proto:go_default_library",
|
||||
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
|
||||
"@in_gopkg_d4l3k_messagediff_v1//:go_default_library",
|
||||
"@io_bazel_rules_go//go/tools/bazel:go_default_library",
|
||||
],
|
||||
|
||||
@@ -37,6 +37,7 @@ go_test(
|
||||
"//shared/testutil/require:go_default_library",
|
||||
"@com_github_gogo_protobuf//proto:go_default_library",
|
||||
"@com_github_google_gofuzz//:go_default_library",
|
||||
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
|
||||
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
|
||||
],
|
||||
|
||||
@@ -175,17 +175,17 @@ func ProcessSlashings(state *stateTrie.BeaconState) (*stateTrie.BeaconState, err
|
||||
// below equally.
|
||||
increment := params.BeaconConfig().EffectiveBalanceIncrement
|
||||
minSlashing := mathutil.Min(totalSlashing*params.BeaconConfig().ProportionalSlashingMultiplier, totalBalance)
|
||||
err = state.ApplyToEveryValidator(func(idx int, val *ethpb.Validator) (bool, error) {
|
||||
err = state.ApplyToEveryValidator(func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error) {
|
||||
correctEpoch := (currentEpoch + exitLength/2) == val.WithdrawableEpoch
|
||||
if val.Slashed && correctEpoch {
|
||||
penaltyNumerator := val.EffectiveBalance / increment * minSlashing
|
||||
penalty := penaltyNumerator / totalBalance * increment
|
||||
if err := helpers.DecreaseBalance(state, uint64(idx), penalty); err != nil {
|
||||
return false, err
|
||||
return false, val, err
|
||||
}
|
||||
return true, nil
|
||||
return true, val, nil
|
||||
}
|
||||
return false, nil
|
||||
return false, val, nil
|
||||
})
|
||||
return state, err
|
||||
}
|
||||
@@ -249,23 +249,24 @@ func ProcessFinalUpdates(state *stateTrie.BeaconState) (*stateTrie.BeaconState,
|
||||
|
||||
bals := state.Balances()
|
||||
// Update effective balances with hysteresis.
|
||||
validatorFunc := func(idx int, val *ethpb.Validator) (bool, error) {
|
||||
validatorFunc := func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error) {
|
||||
if val == nil {
|
||||
return false, fmt.Errorf("validator %d is nil in state", idx)
|
||||
return false, nil, fmt.Errorf("validator %d is nil in state", idx)
|
||||
}
|
||||
if idx >= len(bals) {
|
||||
return false, fmt.Errorf("validator index exceeds validator length in state %d >= %d", idx, len(state.Balances()))
|
||||
return false, nil, fmt.Errorf("validator index exceeds validator length in state %d >= %d", idx, len(state.Balances()))
|
||||
}
|
||||
balance := bals[idx]
|
||||
|
||||
if balance+downwardThreshold < val.EffectiveBalance || val.EffectiveBalance+upwardThreshold < balance {
|
||||
val.EffectiveBalance = maxEffBalance
|
||||
if val.EffectiveBalance > balance-balance%effBalanceInc {
|
||||
val.EffectiveBalance = balance - balance%effBalanceInc
|
||||
newVal := stateTrie.CopyValidator(val)
|
||||
newVal.EffectiveBalance = maxEffBalance
|
||||
if newVal.EffectiveBalance > balance-balance%effBalanceInc {
|
||||
newVal.EffectiveBalance = balance - balance%effBalanceInc
|
||||
}
|
||||
return true, nil
|
||||
return true, newVal, nil
|
||||
}
|
||||
return false, nil
|
||||
return false, val, nil
|
||||
}
|
||||
|
||||
if err := state.ApplyToEveryValidator(validatorFunc); err != nil {
|
||||
@@ -276,20 +277,20 @@ func ProcessFinalUpdates(state *stateTrie.BeaconState) (*stateTrie.BeaconState,
|
||||
slashedExitLength := params.BeaconConfig().EpochsPerSlashingsVector
|
||||
slashedEpoch := nextEpoch % slashedExitLength
|
||||
slashings := state.Slashings()
|
||||
if uint64(len(slashings)) != slashedExitLength {
|
||||
if uint64(len(slashings)) != uint64(slashedExitLength) {
|
||||
return nil, fmt.Errorf(
|
||||
"state slashing length %d different than EpochsPerHistoricalVector %d",
|
||||
len(slashings),
|
||||
slashedExitLength,
|
||||
)
|
||||
}
|
||||
if err := state.UpdateSlashingsAtIndex(slashedEpoch /* index */, 0 /* value */); err != nil {
|
||||
if err := state.UpdateSlashingsAtIndex(uint64(slashedEpoch) /* index */, 0 /* value */); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Set RANDAO mix.
|
||||
randaoMixLength := params.BeaconConfig().EpochsPerHistoricalVector
|
||||
if uint64(state.RandaoMixesLength()) != randaoMixLength {
|
||||
if uint64(state.RandaoMixesLength()) != uint64(randaoMixLength) {
|
||||
return nil, fmt.Errorf(
|
||||
"state randao length %d different than EpochsPerHistoricalVector %d",
|
||||
state.RandaoMixesLength(),
|
||||
@@ -300,13 +301,13 @@ func ProcessFinalUpdates(state *stateTrie.BeaconState) (*stateTrie.BeaconState,
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := state.UpdateRandaoMixesAtIndex(nextEpoch%randaoMixLength, mix); err != nil {
|
||||
if err := state.UpdateRandaoMixesAtIndex(uint64(nextEpoch%randaoMixLength), mix); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Set historical root accumulator.
|
||||
epochsPerHistoricalRoot := params.BeaconConfig().SlotsPerHistoricalRoot / params.BeaconConfig().SlotsPerEpoch
|
||||
if nextEpoch%epochsPerHistoricalRoot == 0 {
|
||||
epochsPerHistoricalRoot := params.BeaconConfig().SlotsPerHistoricalRoot.DivSlot(params.BeaconConfig().SlotsPerEpoch)
|
||||
if nextEpoch.Mod(uint64(epochsPerHistoricalRoot)) == 0 {
|
||||
historicalBatch := &pb.HistoricalBatch{
|
||||
BlockRoots: state.BlockRoots(),
|
||||
StateRoots: state.StateRoots(),
|
||||
@@ -349,7 +350,10 @@ func UnslashedAttestingIndices(state *stateTrie.BeaconState, atts []*pb.PendingA
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
attestingIndices := attestationutil.AttestingIndices(att.AggregationBits, committee)
|
||||
attestingIndices, err := attestationutil.AttestingIndices(att.AggregationBits, committee)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Create a set for attesting indices
|
||||
for _, index := range attestingIndices {
|
||||
if !seen[index] {
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch"
|
||||
@@ -25,7 +26,7 @@ func TestUnslashedAttestingIndices_CanSortAndFilter(t *testing.T) {
|
||||
Data: ðpb.AttestationData{Source: ðpb.Checkpoint{Root: make([]byte, 32)},
|
||||
Target: ðpb.Checkpoint{Epoch: 0, Root: make([]byte, 32)},
|
||||
},
|
||||
AggregationBits: bitfield.Bitlist{0xFF, 0xFF, 0xFF},
|
||||
AggregationBits: bitfield.Bitlist{0x00, 0xFF, 0xFF, 0xFF},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +72,7 @@ func TestUnslashedAttestingIndices_DuplicatedAttestations(t *testing.T) {
|
||||
atts[i] = &pb.PendingAttestation{
|
||||
Data: ðpb.AttestationData{Source: ðpb.Checkpoint{Root: make([]byte, 32)},
|
||||
Target: ðpb.Checkpoint{Epoch: 0}},
|
||||
AggregationBits: bitfield.Bitlist{0xFF, 0xFF, 0xFF},
|
||||
AggregationBits: bitfield.Bitlist{0x00, 0xFF, 0xFF, 0xFF},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,7 +110,7 @@ func TestAttestingBalance_CorrectBalance(t *testing.T) {
|
||||
Data: ðpb.AttestationData{
|
||||
Target: ðpb.Checkpoint{Root: make([]byte, 32)},
|
||||
Source: ðpb.Checkpoint{Root: make([]byte, 32)},
|
||||
Slot: uint64(i),
|
||||
Slot: types.Slot(i),
|
||||
},
|
||||
AggregationBits: bitfield.Bitlist{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01},
|
||||
@@ -262,7 +263,7 @@ func TestProcessSlashings_SlashedLess(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestProcessFinalUpdates_CanProcess(t *testing.T) {
|
||||
s := buildState(t, params.BeaconConfig().SlotsPerHistoricalRoot-1, params.BeaconConfig().SlotsPerEpoch)
|
||||
s := buildState(t, params.BeaconConfig().SlotsPerHistoricalRoot-1, uint64(params.BeaconConfig().SlotsPerEpoch))
|
||||
ce := helpers.CurrentEpoch(s)
|
||||
ne := ce + 1
|
||||
require.NoError(t, s.SetEth1DataVotes([]*ethpb.Eth1Data{}))
|
||||
@@ -288,7 +289,7 @@ func TestProcessFinalUpdates_CanProcess(t *testing.T) {
|
||||
assert.Equal(t, newS.Slashings()[ce], newS.Slashings()[ne], "Unexpected slashed balance")
|
||||
|
||||
// Verify randao is correctly updated in the right position.
|
||||
mix, err := newS.RandaoMixAtIndex(ne)
|
||||
mix, err := newS.RandaoMixAtIndex(uint64(ne))
|
||||
assert.NoError(t, err)
|
||||
assert.DeepNotEqual(t, params.BeaconConfig().ZeroHash[:], mix, "latest RANDAO still zero hashes")
|
||||
|
||||
@@ -396,11 +397,11 @@ func TestProcessRegistryUpdates_ValidatorsEjected(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestProcessRegistryUpdates_CanExits(t *testing.T) {
|
||||
e := uint64(5)
|
||||
e := types.Epoch(5)
|
||||
exitEpoch := helpers.ActivationExitEpoch(e)
|
||||
minWithdrawalDelay := params.BeaconConfig().MinValidatorWithdrawabilityDelay
|
||||
base := &pb.BeaconState{
|
||||
Slot: e * params.BeaconConfig().SlotsPerEpoch,
|
||||
Slot: params.BeaconConfig().SlotsPerEpoch.Mul(uint64(e)),
|
||||
Validators: []*ethpb.Validator{
|
||||
{
|
||||
ExitEpoch: exitEpoch,
|
||||
@@ -420,7 +421,7 @@ func TestProcessRegistryUpdates_CanExits(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func buildState(t testing.TB, slot, validatorCount uint64) *state.BeaconState {
|
||||
func buildState(t testing.TB, slot types.Slot, validatorCount uint64) *state.BeaconState {
|
||||
validators := make([]*ethpb.Validator, validatorCount)
|
||||
for i := 0; i < len(validators); i++ {
|
||||
validators[i] = ðpb.Validator{
|
||||
@@ -446,7 +447,8 @@ func buildState(t testing.TB, slot, validatorCount uint64) *state.BeaconState {
|
||||
for i := 0; i < len(latestRandaoMixes); i++ {
|
||||
latestRandaoMixes[i] = params.BeaconConfig().ZeroHash[:]
|
||||
}
|
||||
s := testutil.NewBeaconState()
|
||||
s, err := testutil.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
if err := s.SetSlot(slot); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ go_library(
|
||||
"//shared/params:go_default_library",
|
||||
"//shared/traceutil:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
|
||||
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
|
||||
"@io_opencensus_go//trace:go_default_library",
|
||||
],
|
||||
@@ -49,6 +50,7 @@ go_test(
|
||||
"//shared/testutil/assert:go_default_library",
|
||||
"//shared/testutil/require:go_default_library",
|
||||
"@com_github_gogo_protobuf//proto:go_default_library",
|
||||
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
|
||||
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
|
||||
],
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
@@ -47,7 +48,10 @@ func ProcessAttestations(
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
indices := attestationutil.AttestingIndices(a.AggregationBits, committee)
|
||||
indices, err := attestationutil.AttestingIndices(a.AggregationBits, committee)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
vp = UpdateValidator(vp, v, indices, a, a.Data.Slot)
|
||||
}
|
||||
|
||||
@@ -103,7 +107,7 @@ func AttestedPrevEpoch(s *stateTrie.BeaconState, a *pb.PendingAttestation) (bool
|
||||
}
|
||||
|
||||
// SameTarget returns true if attestation `a` attested to the same target block in state.
|
||||
func SameTarget(state *stateTrie.BeaconState, a *pb.PendingAttestation, e uint64) (bool, error) {
|
||||
func SameTarget(state *stateTrie.BeaconState, a *pb.PendingAttestation, e types.Epoch) (bool, error) {
|
||||
r, err := helpers.BlockRoot(state, e)
|
||||
if err != nil {
|
||||
return false, err
|
||||
@@ -127,7 +131,7 @@ func SameHead(state *stateTrie.BeaconState, a *pb.PendingAttestation) (bool, err
|
||||
}
|
||||
|
||||
// UpdateValidator updates pre computed validator store.
|
||||
func UpdateValidator(vp []*Validator, record *Validator, indices []uint64, a *pb.PendingAttestation, aSlot uint64) []*Validator {
|
||||
func UpdateValidator(vp []*Validator, record *Validator, indices []uint64, a *pb.PendingAttestation, aSlot types.Slot) []*Validator {
|
||||
inclusionSlot := aSlot + a.InclusionDelay
|
||||
|
||||
for _, i := range indices {
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"testing"
|
||||
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
@@ -16,7 +17,7 @@ import (
|
||||
)
|
||||
|
||||
func TestUpdateValidator_Works(t *testing.T) {
|
||||
e := params.BeaconConfig().FarFutureEpoch
|
||||
e := params.BeaconConfig().FarFutureSlot
|
||||
vp := []*precompute.Validator{{}, {InclusionSlot: e}, {}, {InclusionSlot: e}, {}, {InclusionSlot: e}}
|
||||
record := &precompute.Validator{IsCurrentEpochAttester: true, IsCurrentEpochTargetAttester: true,
|
||||
IsPrevEpochAttester: true, IsPrevEpochTargetAttester: true, IsPrevEpochHeadAttester: true}
|
||||
@@ -33,7 +34,7 @@ func TestUpdateValidator_Works(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUpdateValidator_InclusionOnlyCountsPrevEpoch(t *testing.T) {
|
||||
e := params.BeaconConfig().FarFutureEpoch
|
||||
e := params.BeaconConfig().FarFutureSlot
|
||||
vp := []*precompute.Validator{{InclusionSlot: e}}
|
||||
record := &precompute.Validator{IsCurrentEpochAttester: true, IsCurrentEpochTargetAttester: true}
|
||||
a := &pb.PendingAttestation{InclusionDelay: 1, ProposerIndex: 2}
|
||||
@@ -149,11 +150,11 @@ func TestProcessAttestations(t *testing.T) {
|
||||
params.UseMinimalConfig()
|
||||
defer params.UseMainnetConfig()
|
||||
|
||||
validators := uint64(64)
|
||||
validators := uint64(128)
|
||||
beaconState, _ := testutil.DeterministicGenesisState(t, validators)
|
||||
require.NoError(t, beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch))
|
||||
|
||||
bf := []byte{0xff}
|
||||
c := helpers.SlotCommitteeCount(validators)
|
||||
bf := bitfield.NewBitlist(c)
|
||||
att1 := ðpb.Attestation{Data: ðpb.AttestationData{
|
||||
Target: ðpb.Checkpoint{Epoch: 0}},
|
||||
AggregationBits: bf}
|
||||
@@ -183,7 +184,8 @@ func TestProcessAttestations(t *testing.T) {
|
||||
|
||||
committee, err := helpers.BeaconCommitteeFromState(beaconState, att1.Data.Slot, att1.Data.CommitteeIndex)
|
||||
require.NoError(t, err)
|
||||
indices := attestationutil.AttestingIndices(att1.AggregationBits, committee)
|
||||
indices, err := attestationutil.AttestingIndices(att1.AggregationBits, committee)
|
||||
require.NoError(t, err)
|
||||
for _, i := range indices {
|
||||
if !pVals[i].IsPrevEpochAttester {
|
||||
t.Error("Not a prev epoch attester")
|
||||
@@ -191,7 +193,8 @@ func TestProcessAttestations(t *testing.T) {
|
||||
}
|
||||
committee, err = helpers.BeaconCommitteeFromState(beaconState, att2.Data.Slot, att2.Data.CommitteeIndex)
|
||||
require.NoError(t, err)
|
||||
indices = attestationutil.AttestingIndices(att2.AggregationBits, committee)
|
||||
indices, err = attestationutil.AttestingIndices(att2.AggregationBits, committee)
|
||||
require.NoError(t, err)
|
||||
for _, i := range indices {
|
||||
assert.Equal(t, true, pVals[i].IsPrevEpochAttester, "Not a prev epoch attester")
|
||||
assert.Equal(t, true, pVals[i].IsPrevEpochTargetAttester, "Not a prev epoch target attester")
|
||||
|
||||
@@ -3,6 +3,7 @@ package precompute_test
|
||||
import (
|
||||
"testing"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute"
|
||||
@@ -38,16 +39,16 @@ func TestProcessJustificationAndFinalizationPreCompute_ConsecutiveEpochs(t *test
|
||||
}
|
||||
state, err := beaconstate.InitializeFromProto(base)
|
||||
require.NoError(t, err)
|
||||
attestedBalance := 4 * e * 3 / 2
|
||||
attestedBalance := 4 * uint64(e) * 3 / 2
|
||||
b := &precompute.Balance{PrevEpochTargetAttested: attestedBalance}
|
||||
newState, err := precompute.ProcessJustificationAndFinalizationPreCompute(state, b)
|
||||
require.NoError(t, err)
|
||||
rt := [32]byte{byte(64)}
|
||||
assert.DeepEqual(t, rt[:], newState.CurrentJustifiedCheckpoint().Root, "Unexpected justified root")
|
||||
assert.Equal(t, uint64(2), newState.CurrentJustifiedCheckpoint().Epoch, "Unexpected justified epoch")
|
||||
assert.Equal(t, uint64(0), newState.PreviousJustifiedCheckpoint().Epoch, "Unexpected previous justified epoch")
|
||||
assert.Equal(t, types.Epoch(2), newState.CurrentJustifiedCheckpoint().Epoch, "Unexpected justified epoch")
|
||||
assert.Equal(t, types.Epoch(0), newState.PreviousJustifiedCheckpoint().Epoch, "Unexpected previous justified epoch")
|
||||
assert.DeepEqual(t, params.BeaconConfig().ZeroHash[:], newState.FinalizedCheckpoint().Root, "Unexpected finalized root")
|
||||
assert.Equal(t, uint64(0), newState.FinalizedCheckpointEpoch(), "Unexpected finalized epoch")
|
||||
assert.Equal(t, types.Epoch(0), newState.FinalizedCheckpointEpoch(), "Unexpected finalized epoch")
|
||||
}
|
||||
|
||||
func TestProcessJustificationAndFinalizationPreCompute_JustifyCurrentEpoch(t *testing.T) {
|
||||
@@ -75,16 +76,16 @@ func TestProcessJustificationAndFinalizationPreCompute_JustifyCurrentEpoch(t *te
|
||||
}
|
||||
state, err := beaconstate.InitializeFromProto(base)
|
||||
require.NoError(t, err)
|
||||
attestedBalance := 4 * e * 3 / 2
|
||||
attestedBalance := 4 * uint64(e) * 3 / 2
|
||||
b := &precompute.Balance{PrevEpochTargetAttested: attestedBalance}
|
||||
newState, err := precompute.ProcessJustificationAndFinalizationPreCompute(state, b)
|
||||
require.NoError(t, err)
|
||||
rt := [32]byte{byte(64)}
|
||||
assert.DeepEqual(t, rt[:], newState.CurrentJustifiedCheckpoint().Root, "Unexpected current justified root")
|
||||
assert.Equal(t, uint64(2), newState.CurrentJustifiedCheckpoint().Epoch, "Unexpected justified epoch")
|
||||
assert.Equal(t, uint64(0), newState.PreviousJustifiedCheckpoint().Epoch, "Unexpected previous justified epoch")
|
||||
assert.Equal(t, types.Epoch(2), newState.CurrentJustifiedCheckpoint().Epoch, "Unexpected justified epoch")
|
||||
assert.Equal(t, types.Epoch(0), newState.PreviousJustifiedCheckpoint().Epoch, "Unexpected previous justified epoch")
|
||||
assert.DeepEqual(t, params.BeaconConfig().ZeroHash[:], newState.FinalizedCheckpoint().Root)
|
||||
assert.Equal(t, uint64(0), newState.FinalizedCheckpointEpoch(), "Unexpected finalized epoch")
|
||||
assert.Equal(t, types.Epoch(0), newState.FinalizedCheckpointEpoch(), "Unexpected finalized epoch")
|
||||
}
|
||||
|
||||
func TestProcessJustificationAndFinalizationPreCompute_JustifyPrevEpoch(t *testing.T) {
|
||||
@@ -111,14 +112,14 @@ func TestProcessJustificationAndFinalizationPreCompute_JustifyPrevEpoch(t *testi
|
||||
}
|
||||
state, err := beaconstate.InitializeFromProto(base)
|
||||
require.NoError(t, err)
|
||||
attestedBalance := 4 * e * 3 / 2
|
||||
attestedBalance := 4 * uint64(e) * 3 / 2
|
||||
b := &precompute.Balance{PrevEpochTargetAttested: attestedBalance}
|
||||
newState, err := precompute.ProcessJustificationAndFinalizationPreCompute(state, b)
|
||||
require.NoError(t, err)
|
||||
rt := [32]byte{byte(64)}
|
||||
assert.DeepEqual(t, rt[:], newState.CurrentJustifiedCheckpoint().Root, "Unexpected current justified root")
|
||||
assert.Equal(t, uint64(0), newState.PreviousJustifiedCheckpoint().Epoch, "Unexpected previous justified epoch")
|
||||
assert.Equal(t, uint64(2), newState.CurrentJustifiedCheckpoint().Epoch, "Unexpected justified epoch")
|
||||
assert.Equal(t, types.Epoch(0), newState.PreviousJustifiedCheckpoint().Epoch, "Unexpected previous justified epoch")
|
||||
assert.Equal(t, types.Epoch(2), newState.CurrentJustifiedCheckpoint().Epoch, "Unexpected justified epoch")
|
||||
assert.DeepEqual(t, params.BeaconConfig().ZeroHash[:], newState.FinalizedCheckpoint().Root)
|
||||
assert.Equal(t, uint64(0), newState.FinalizedCheckpointEpoch(), "Unexpected finalized epoch")
|
||||
assert.Equal(t, types.Epoch(0), newState.FinalizedCheckpointEpoch(), "Unexpected finalized epoch")
|
||||
}
|
||||
|
||||
@@ -45,8 +45,8 @@ func New(ctx context.Context, state *stateTrie.BeaconState) ([]*Validator, *Bala
|
||||
}
|
||||
// Set inclusion slot and inclusion distance to be max, they will be compared and replaced
|
||||
// with the lower values
|
||||
pVal.InclusionSlot = params.BeaconConfig().FarFutureEpoch
|
||||
pVal.InclusionDistance = params.BeaconConfig().FarFutureEpoch
|
||||
pVal.InclusionSlot = params.BeaconConfig().FarFutureSlot
|
||||
pVal.InclusionDistance = params.BeaconConfig().FarFutureSlot
|
||||
|
||||
pValidators[idx] = pVal
|
||||
return nil
|
||||
|
||||
@@ -29,7 +29,7 @@ func TestNew(t *testing.T) {
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
e := params.BeaconConfig().FarFutureEpoch
|
||||
e := params.BeaconConfig().FarFutureSlot
|
||||
v, b, err := precompute.New(context.Background(), s)
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, &precompute.Validator{
|
||||
|
||||
@@ -2,6 +2,7 @@ package precompute
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/shared/mathutil"
|
||||
@@ -68,7 +69,7 @@ func AttestationsDelta(state *stateTrie.BeaconState, pBal *Balance, vp []*Valida
|
||||
return rewards, penalties, nil
|
||||
}
|
||||
|
||||
func attestationDelta(pBal *Balance, v *Validator, prevEpoch, finalizedEpoch uint64) (uint64, uint64) {
|
||||
func attestationDelta(pBal *Balance, v *Validator, prevEpoch, finalizedEpoch types.Epoch) (uint64, uint64) {
|
||||
eligible := v.IsActivePrevEpoch || (v.IsSlashed && !v.IsWithdrawableCurrentEpoch)
|
||||
if !eligible || pBal.ActiveCurrentEpoch == 0 {
|
||||
return 0, 0
|
||||
@@ -85,7 +86,7 @@ func attestationDelta(pBal *Balance, v *Validator, prevEpoch, finalizedEpoch uin
|
||||
if v.IsPrevEpochAttester && !v.IsSlashed {
|
||||
proposerReward := br / params.BeaconConfig().ProposerRewardQuotient
|
||||
maxAttesterReward := br - proposerReward
|
||||
r += maxAttesterReward / v.InclusionDistance
|
||||
r += maxAttesterReward / uint64(v.InclusionDistance)
|
||||
|
||||
if isInInactivityLeak(prevEpoch, finalizedEpoch) {
|
||||
// Since full base reward will be canceled out by inactivity penalty deltas,
|
||||
@@ -139,7 +140,7 @@ func attestationDelta(pBal *Balance, v *Validator, prevEpoch, finalizedEpoch uin
|
||||
// Equivalent to the following condition from the spec:
|
||||
// `index not in get_unslashed_attesting_indices(state, matching_target_attestations)`
|
||||
if !v.IsPrevEpochTargetAttester || v.IsSlashed {
|
||||
p += vb * finalityDelay / params.BeaconConfig().InactivityPenaltyQuotient
|
||||
p += vb * uint64(finalityDelay) / params.BeaconConfig().InactivityPenaltyQuotient
|
||||
}
|
||||
}
|
||||
return r, p
|
||||
@@ -182,7 +183,7 @@ func ProposersDelta(state *stateTrie.BeaconState, pBal *Balance, vp []*Validator
|
||||
// Spec code:
|
||||
// def is_in_inactivity_leak(state: BeaconState) -> bool:
|
||||
// return get_finality_delay(state) > MIN_EPOCHS_TO_INACTIVITY_PENALTY
|
||||
func isInInactivityLeak(prevEpoch, finalizedEpoch uint64) bool {
|
||||
func isInInactivityLeak(prevEpoch, finalizedEpoch types.Epoch) bool {
|
||||
return finalityDelay(prevEpoch, finalizedEpoch) > params.BeaconConfig().MinEpochsToInactivityPenalty
|
||||
}
|
||||
|
||||
@@ -191,6 +192,6 @@ func isInInactivityLeak(prevEpoch, finalizedEpoch uint64) bool {
|
||||
// Spec code:
|
||||
// def get_finality_delay(state: BeaconState) -> uint64:
|
||||
// return get_previous_epoch(state) - state.finalized_checkpoint.epoch
|
||||
func finalityDelay(prevEpoch, finalizedEpoch uint64) uint64 {
|
||||
func finalityDelay(prevEpoch, finalizedEpoch types.Epoch) types.Epoch {
|
||||
return prevEpoch - finalizedEpoch
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch"
|
||||
@@ -27,7 +28,7 @@ func TestProcessRewardsAndPenaltiesPrecompute(t *testing.T) {
|
||||
Target: ðpb.Checkpoint{Root: make([]byte, 32)},
|
||||
Source: ðpb.Checkpoint{Root: make([]byte, 32)},
|
||||
},
|
||||
AggregationBits: bitfield.Bitlist{0xC0, 0xC0, 0xC0, 0xC0, 0x01},
|
||||
AggregationBits: bitfield.Bitlist{0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0x01},
|
||||
InclusionDelay: 1,
|
||||
}
|
||||
}
|
||||
@@ -70,7 +71,7 @@ func TestAttestationDeltaPrecompute(t *testing.T) {
|
||||
},
|
||||
BeaconBlockRoot: emptyRoot[:],
|
||||
},
|
||||
AggregationBits: bitfield.Bitlist{0xC0, 0xC0, 0xC0, 0xC0, 0x01},
|
||||
AggregationBits: bitfield.Bitlist{0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x01},
|
||||
InclusionDelay: 1,
|
||||
}
|
||||
}
|
||||
@@ -91,7 +92,7 @@ func TestAttestationDeltaPrecompute(t *testing.T) {
|
||||
|
||||
// Add some variances to target and head balances.
|
||||
// See: https://github.com/prysmaticlabs/prysm/issues/5593
|
||||
bp.PrevEpochTargetAttested = bp.PrevEpochTargetAttested / 2
|
||||
bp.PrevEpochTargetAttested /= 2
|
||||
bp.PrevEpochHeadAttested = bp.PrevEpochHeadAttested * 2 / 3
|
||||
rewards, penalties, err := AttestationsDelta(beaconState, bp, vp)
|
||||
require.NoError(t, err)
|
||||
@@ -112,7 +113,7 @@ func TestAttestationDeltaPrecompute(t *testing.T) {
|
||||
// Base rewards for proposer and attesters working together getting attestation
|
||||
// on chain in the fatest manner
|
||||
proposerReward := base / params.BeaconConfig().ProposerRewardQuotient
|
||||
wanted += (base-proposerReward)*params.BeaconConfig().MinAttestationInclusionDelay - 1
|
||||
wanted += (base-proposerReward)*uint64(params.BeaconConfig().MinAttestationInclusionDelay) - 1
|
||||
assert.Equal(t, wanted, rewards[i], "Unexpected reward balance for validator with index %d", i)
|
||||
// Since all these validators attested, they shouldn't get penalized.
|
||||
assert.Equal(t, uint64(0), penalties[i], "Unexpected penalty balance")
|
||||
@@ -154,7 +155,7 @@ func TestAttestationDeltas_ZeroEpoch(t *testing.T) {
|
||||
},
|
||||
BeaconBlockRoot: emptyRoot[:],
|
||||
},
|
||||
AggregationBits: bitfield.Bitlist{0xC0, 0xC0, 0xC0, 0xC0, 0x01},
|
||||
AggregationBits: bitfield.Bitlist{0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0x01},
|
||||
InclusionDelay: 1,
|
||||
}
|
||||
}
|
||||
@@ -217,7 +218,7 @@ func TestProcessRewardsAndPenaltiesPrecompute_SlashedInactivePenalty(t *testing.
|
||||
Target: ðpb.Checkpoint{Root: make([]byte, 32)},
|
||||
Source: ðpb.Checkpoint{Root: make([]byte, 32)},
|
||||
},
|
||||
AggregationBits: bitfield.Bitlist{0xC0, 0xC0, 0xC0, 0xC0, 0x01},
|
||||
AggregationBits: bitfield.Bitlist{0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0x01},
|
||||
InclusionDelay: 1,
|
||||
}
|
||||
}
|
||||
@@ -248,13 +249,13 @@ func TestProcessRewardsAndPenaltiesPrecompute_SlashedInactivePenalty(t *testing.
|
||||
penalty := 3 * base
|
||||
proposerReward := base / params.BeaconConfig().ProposerRewardQuotient
|
||||
penalty += params.BeaconConfig().BaseRewardsPerEpoch*base - proposerReward
|
||||
penalty += vp[i].CurrentEpochEffectiveBalance * finalityDelay / params.BeaconConfig().InactivityPenaltyQuotient
|
||||
penalty += vp[i].CurrentEpochEffectiveBalance * uint64(finalityDelay) / params.BeaconConfig().InactivityPenaltyQuotient
|
||||
assert.Equal(t, penalty, penalties[i], "Unexpected slashed indices penalty balance")
|
||||
assert.Equal(t, uint64(0), rewards[i], "Unexpected slashed indices reward balance")
|
||||
}
|
||||
}
|
||||
|
||||
func buildState(slot, validatorCount uint64) *pb.BeaconState {
|
||||
func buildState(slot types.Slot, validatorCount uint64) *pb.BeaconState {
|
||||
validators := make([]*ethpb.Validator, validatorCount)
|
||||
for i := 0; i < len(validators); i++ {
|
||||
validators[i] = ðpb.Validator{
|
||||
@@ -353,8 +354,8 @@ func TestFinalityDelay(t *testing.T) {
|
||||
base.FinalizedCheckpoint = ðpb.Checkpoint{Epoch: 3}
|
||||
beaconState, err := state.InitializeFromProto(base)
|
||||
require.NoError(t, err)
|
||||
prevEpoch := uint64(0)
|
||||
finalizedEpoch := uint64(0)
|
||||
prevEpoch := types.Epoch(0)
|
||||
finalizedEpoch := types.Epoch(0)
|
||||
// Set values for each test case
|
||||
setVal := func() {
|
||||
prevEpoch = helpers.PrevEpoch(beaconState)
|
||||
@@ -383,8 +384,8 @@ func TestIsInInactivityLeak(t *testing.T) {
|
||||
base.FinalizedCheckpoint = ðpb.Checkpoint{Epoch: 3}
|
||||
beaconState, err := state.InitializeFromProto(base)
|
||||
require.NoError(t, err)
|
||||
prevEpoch := uint64(0)
|
||||
finalizedEpoch := uint64(0)
|
||||
prevEpoch := types.Epoch(0)
|
||||
finalizedEpoch := types.Epoch(0)
|
||||
// Set values for each test case
|
||||
setVal := func() {
|
||||
prevEpoch = helpers.PrevEpoch(beaconState)
|
||||
|
||||
@@ -42,17 +42,17 @@ func ProcessSlashingsPrecompute(state *stateTrie.BeaconState, pBal *Balance) err
|
||||
}
|
||||
|
||||
increment := params.BeaconConfig().EffectiveBalanceIncrement
|
||||
validatorFunc := func(idx int, val *ethpb.Validator) (bool, error) {
|
||||
validatorFunc := func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error) {
|
||||
correctEpoch := epochToWithdraw == val.WithdrawableEpoch
|
||||
if val.Slashed && correctEpoch {
|
||||
penaltyNumerator := val.EffectiveBalance / increment * minSlashing
|
||||
penalty := penaltyNumerator / pBal.ActiveCurrentEpoch * increment
|
||||
if err := helpers.DecreaseBalance(state, uint64(idx), penalty); err != nil {
|
||||
return false, err
|
||||
return false, val, err
|
||||
}
|
||||
return true, nil
|
||||
return true, val, nil
|
||||
}
|
||||
return false, nil
|
||||
return false, val, nil
|
||||
}
|
||||
|
||||
return state.ApplyToEveryValidator(validatorFunc)
|
||||
|
||||
@@ -37,7 +37,6 @@ go_test(
|
||||
"//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",
|
||||
],
|
||||
@@ -71,7 +70,6 @@ go_test(
|
||||
"//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",
|
||||
],
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package precompute
|
||||
|
||||
import types "github.com/prysmaticlabs/eth2-types"
|
||||
|
||||
// Validator stores the pre computation of individual validator's attesting records these records
|
||||
// consist of attestation votes, block inclusion record. Pre computing and storing such record
|
||||
// is essential for process epoch optimizations.
|
||||
@@ -26,9 +28,9 @@ type Validator struct {
|
||||
// CurrentEpochEffectiveBalance is how much effective balance this validator validator has current epoch.
|
||||
CurrentEpochEffectiveBalance uint64
|
||||
// InclusionSlot is the slot of when the attestation gets included in the chain.
|
||||
InclusionSlot uint64
|
||||
InclusionSlot types.Slot
|
||||
// InclusionDistance is the distance between the assigned slot and this validator's attestation was included in block.
|
||||
InclusionDistance uint64
|
||||
InclusionDistance types.Slot
|
||||
// ProposerIndex is the index of proposer at slot where this validator's attestation was included.
|
||||
ProposerIndex uint64
|
||||
// BeforeEpochTransitionBalance is the validator balance prior to epoch transition.
|
||||
|
||||
@@ -35,7 +35,6 @@ go_test(
|
||||
"//shared/testutil:go_default_library",
|
||||
"//shared/testutil/require: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",
|
||||
],
|
||||
|
||||
@@ -10,6 +10,7 @@ go_library(
|
||||
visibility = ["//beacon-chain:__subpackages__"],
|
||||
deps = [
|
||||
"//shared/event:go_default_library",
|
||||
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
|
||||
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -6,6 +6,7 @@ package state
|
||||
import (
|
||||
"time"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
)
|
||||
|
||||
@@ -26,7 +27,7 @@ const (
|
||||
// BlockProcessedData is the data sent with BlockProcessed events.
|
||||
type BlockProcessedData struct {
|
||||
// Slot is the slot of the processed block.
|
||||
Slot uint64
|
||||
Slot types.Slot
|
||||
// BlockRoot of the processed block.
|
||||
BlockRoot [32]byte
|
||||
// SignedBlock is the physical processed block.
|
||||
@@ -58,7 +59,7 @@ type InitializedData struct {
|
||||
// ReorgData is the data alongside a reorg event.
|
||||
type ReorgData struct {
|
||||
// NewSlot is the slot of new state after the reorg.
|
||||
NewSlot uint64
|
||||
NewSlot types.Slot
|
||||
// OldSlot is the slot of the head state before the reorg.
|
||||
OldSlot uint64
|
||||
OldSlot types.Slot
|
||||
}
|
||||
|
||||
@@ -43,9 +43,9 @@ go_library(
|
||||
"//shared/timeutils:go_default_library",
|
||||
"@com_github_ferranbt_fastssz//:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
|
||||
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -79,6 +79,7 @@ go_test(
|
||||
"//shared/testutil/require:go_default_library",
|
||||
"//shared/timeutils:go_default_library",
|
||||
"@com_github_google_gofuzz//:go_default_library",
|
||||
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
|
||||
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
|
||||
],
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bls"
|
||||
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
||||
@@ -35,6 +36,15 @@ func ValidateNilAttestation(attestation *ethpb.Attestation) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateSlotTargetEpoch checks if attestation data's epoch matches target checkpoint's epoch.
|
||||
// It is recommended to run `ValidateNilAttestation` first to ensure `data.Target` can't be nil.
|
||||
func ValidateSlotTargetEpoch(data *ethpb.AttestationData) error {
|
||||
if SlotToEpoch(data.Slot) != data.Target.Epoch {
|
||||
return fmt.Errorf("slot %d does not match target epoch %d", data.Slot, data.Target.Epoch)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsAggregator returns true if the signature is from the input validator. The committee
|
||||
// count is provided as an argument rather than imported implementation from spec. Having
|
||||
// committee count as an argument allows cheaper computation at run time.
|
||||
@@ -107,10 +117,10 @@ func ComputeSubnetForAttestation(activeValCount uint64, att *ethpb.Attestation)
|
||||
// slots_since_epoch_start = attestation.data.slot % SLOTS_PER_EPOCH
|
||||
// committees_since_epoch_start = get_committee_count_at_slot(state, attestation.data.slot) * slots_since_epoch_start
|
||||
// return (committees_since_epoch_start + attestation.data.index) % ATTESTATION_SUBNET_COUNT
|
||||
func ComputeSubnetFromCommitteeAndSlot(activeValCount, comIdx, attSlot uint64) uint64 {
|
||||
func ComputeSubnetFromCommitteeAndSlot(activeValCount, comIdx uint64, attSlot types.Slot) uint64 {
|
||||
slotSinceStart := SlotsSinceEpochStarts(attSlot)
|
||||
comCount := SlotCommitteeCount(activeValCount)
|
||||
commsSinceStart := comCount * slotSinceStart
|
||||
commsSinceStart := uint64(slotSinceStart.Mul(comCount))
|
||||
computedSubnet := (commsSinceStart + comIdx) % params.BeaconNetworkConfig().AttestationSubnetCount
|
||||
return computedSubnet
|
||||
}
|
||||
@@ -126,7 +136,7 @@ func ComputeSubnetFromCommitteeAndSlot(activeValCount, comIdx, attSlot uint64) u
|
||||
// invalid_attestation_slot = 101
|
||||
// valid_attestation_slot = 98
|
||||
// In the attestation must be within the range of 95 to 100 in the example above.
|
||||
func ValidateAttestationTime(attSlot uint64, genesisTime time.Time) error {
|
||||
func ValidateAttestationTime(attSlot types.Slot, genesisTime time.Time) error {
|
||||
if err := ValidateSlotClock(attSlot, uint64(genesisTime.Unix())); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -146,7 +156,7 @@ func ValidateAttestationTime(attSlot uint64, genesisTime time.Time) error {
|
||||
|
||||
// An attestation cannot be older than the current slot - attestation propagation slot range
|
||||
// with a minor tolerance for peer clock disparity.
|
||||
lowerBoundsSlot := uint64(0)
|
||||
lowerBoundsSlot := types.Slot(0)
|
||||
if currentSlot > params.BeaconNetworkConfig().AttestationPropagationSlotRange {
|
||||
lowerBoundsSlot = currentSlot - params.BeaconNetworkConfig().AttestationPropagationSlotRange
|
||||
}
|
||||
@@ -173,10 +183,10 @@ func ValidateAttestationTime(attSlot uint64, genesisTime time.Time) error {
|
||||
func VerifyCheckpointEpoch(c *ethpb.Checkpoint, genesis time.Time) bool {
|
||||
now := uint64(timeutils.Now().Unix())
|
||||
genesisTime := uint64(genesis.Unix())
|
||||
currentSlot := (now - genesisTime) / params.BeaconConfig().SecondsPerSlot
|
||||
currentSlot := types.Slot((now - genesisTime) / params.BeaconConfig().SecondsPerSlot)
|
||||
currentEpoch := SlotToEpoch(currentSlot)
|
||||
|
||||
var prevEpoch uint64
|
||||
var prevEpoch types.Epoch
|
||||
if currentEpoch > 1 {
|
||||
prevEpoch = currentEpoch - 1
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
@@ -131,7 +132,7 @@ func Test_ValidateAttestationTime(t *testing.T) {
|
||||
}
|
||||
|
||||
type args struct {
|
||||
attSlot uint64
|
||||
attSlot types.Slot
|
||||
genesisTime time.Time
|
||||
}
|
||||
tests := []struct {
|
||||
@@ -219,7 +220,8 @@ func Test_ValidateAttestationTime(t *testing.T) {
|
||||
|
||||
func TestVerifyCheckpointEpoch_Ok(t *testing.T) {
|
||||
// Genesis was 6 epochs ago exactly.
|
||||
genesis := time.Now().Add(-1 * time.Second * time.Duration(params.BeaconConfig().SecondsPerSlot*params.BeaconConfig().SlotsPerEpoch*6))
|
||||
offset := params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().SecondsPerSlot * 6)
|
||||
genesis := time.Now().Add(-1 * time.Second * time.Duration(offset))
|
||||
assert.Equal(t, true, helpers.VerifyCheckpointEpoch(ðpb.Checkpoint{Epoch: 6}, genesis))
|
||||
assert.Equal(t, true, helpers.VerifyCheckpointEpoch(ðpb.Checkpoint{Epoch: 5}, genesis))
|
||||
assert.Equal(t, false, helpers.VerifyCheckpointEpoch(ðpb.Checkpoint{Epoch: 4}, genesis))
|
||||
@@ -294,3 +296,44 @@ func TestValidateNilAttestation(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateSlotTargetEpoch(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
attestation *ethpb.Attestation
|
||||
errString string
|
||||
}{
|
||||
{
|
||||
name: "incorrect slot",
|
||||
attestation: ðpb.Attestation{
|
||||
Data: ðpb.AttestationData{
|
||||
Target: ðpb.Checkpoint{Epoch: 1},
|
||||
Source: ðpb.Checkpoint{},
|
||||
},
|
||||
AggregationBits: []byte{},
|
||||
},
|
||||
errString: "slot 0 does not match target epoch 1",
|
||||
},
|
||||
{
|
||||
name: "good attestation",
|
||||
attestation: ðpb.Attestation{
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 2 * params.BeaconConfig().SlotsPerEpoch,
|
||||
Target: ðpb.Checkpoint{Epoch: 2},
|
||||
Source: ðpb.Checkpoint{},
|
||||
},
|
||||
AggregationBits: []byte{},
|
||||
},
|
||||
errString: "",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.errString != "" {
|
||||
require.ErrorContains(t, tt.errString, helpers.ValidateSlotTargetEpoch(tt.attestation.Data))
|
||||
} else {
|
||||
require.NoError(t, helpers.ValidateSlotTargetEpoch(tt.attestation.Data))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,31 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"math"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
|
||||
// VerifyNilBeaconBlock checks if any composite field of input signed beacon block is nil.
|
||||
// Access to these nil fields will result in run time panic,
|
||||
// it is recommended to run these checks as first line of defense.
|
||||
func VerifyNilBeaconBlock(b *ethpb.SignedBeaconBlock) error {
|
||||
if b == nil {
|
||||
return errors.New("signed beacon block can't be nil")
|
||||
}
|
||||
if b.Block == nil {
|
||||
return errors.New("beacon block can't be nil")
|
||||
}
|
||||
if b.Block.Body == nil {
|
||||
return errors.New("beacon block body can't be nil")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// BlockRootAtSlot returns the block root stored in the BeaconState for a recent slot.
|
||||
// It returns an error if the requested block root is not within the slot range.
|
||||
//
|
||||
@@ -18,23 +36,23 @@ 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) {
|
||||
func BlockRootAtSlot(state *stateTrie.BeaconState, slot types.Slot) ([]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)
|
||||
}
|
||||
return state.BlockRootAtIndex(slot % params.BeaconConfig().SlotsPerHistoricalRoot)
|
||||
return state.BlockRootAtIndex(uint64(slot % params.BeaconConfig().SlotsPerHistoricalRoot))
|
||||
}
|
||||
|
||||
// StateRootAtSlot returns the cached state root at that particular slot. If no state
|
||||
// root has been cached it will return a zero-hash.
|
||||
func StateRootAtSlot(state *stateTrie.BeaconState, slot uint64) ([]byte, error) {
|
||||
func StateRootAtSlot(state *stateTrie.BeaconState, slot types.Slot) ([]byte, error) {
|
||||
if slot >= state.Slot() || state.Slot() > slot+params.BeaconConfig().SlotsPerHistoricalRoot {
|
||||
return []byte{}, errors.Errorf("slot %d out of bounds", slot)
|
||||
}
|
||||
return state.StateRootAtIndex(slot % params.BeaconConfig().SlotsPerHistoricalRoot)
|
||||
return state.StateRootAtIndex(uint64(slot % params.BeaconConfig().SlotsPerHistoricalRoot))
|
||||
}
|
||||
|
||||
// BlockRoot returns the block root stored in the BeaconState for epoch start slot.
|
||||
@@ -45,7 +63,7 @@ func StateRootAtSlot(state *stateTrie.BeaconState, slot uint64) ([]byte, error)
|
||||
// Return the block root at the start of a recent ``epoch``.
|
||||
// """
|
||||
// return get_block_root_at_slot(state, compute_start_slot_at_epoch(epoch))
|
||||
func BlockRoot(state *stateTrie.BeaconState, epoch uint64) ([]byte, error) {
|
||||
func BlockRoot(state *stateTrie.BeaconState, epoch types.Epoch) ([]byte, error) {
|
||||
s, err := StartSlot(epoch)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"math"
|
||||
"testing"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
@@ -16,7 +17,7 @@ import (
|
||||
func TestBlockRootAtSlot_CorrectBlockRoot(t *testing.T) {
|
||||
var blockRoots [][]byte
|
||||
|
||||
for i := uint64(0); i < params.BeaconConfig().SlotsPerHistoricalRoot; i++ {
|
||||
for i := uint64(0); i < uint64(params.BeaconConfig().SlotsPerHistoricalRoot); i++ {
|
||||
blockRoots = append(blockRoots, []byte{byte(i)})
|
||||
}
|
||||
s := &pb.BeaconState{
|
||||
@@ -24,8 +25,8 @@ func TestBlockRootAtSlot_CorrectBlockRoot(t *testing.T) {
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
slot uint64
|
||||
stateSlot uint64
|
||||
slot types.Slot
|
||||
stateSlot types.Slot
|
||||
expectedRoot [32]byte
|
||||
}{
|
||||
{
|
||||
@@ -73,7 +74,7 @@ func TestBlockRootAtSlot_CorrectBlockRoot(t *testing.T) {
|
||||
func TestBlockRootAtSlot_OutOfBounds(t *testing.T) {
|
||||
var blockRoots [][]byte
|
||||
|
||||
for i := uint64(0); i < params.BeaconConfig().SlotsPerHistoricalRoot; i++ {
|
||||
for i := uint64(0); i < uint64(params.BeaconConfig().SlotsPerHistoricalRoot); i++ {
|
||||
blockRoots = append(blockRoots, []byte{byte(i)})
|
||||
}
|
||||
state := &pb.BeaconState{
|
||||
@@ -81,8 +82,8 @@ func TestBlockRootAtSlot_OutOfBounds(t *testing.T) {
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
slot uint64
|
||||
stateSlot uint64
|
||||
slot types.Slot
|
||||
stateSlot types.Slot
|
||||
expectedErr string
|
||||
}{
|
||||
{
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"sort"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||
@@ -38,7 +39,7 @@ var proposerIndicesCache = cache.NewProposerIndicesCache()
|
||||
// len(get_active_validator_indices(state, epoch)) // SLOTS_PER_EPOCH // TARGET_COMMITTEE_SIZE,
|
||||
// ))
|
||||
func SlotCommitteeCount(activeValidatorCount uint64) uint64 {
|
||||
var committeePerSlot = activeValidatorCount / params.BeaconConfig().SlotsPerEpoch / params.BeaconConfig().TargetCommitteeSize
|
||||
var committeePerSlot = activeValidatorCount / uint64(params.BeaconConfig().SlotsPerEpoch) / params.BeaconConfig().TargetCommitteeSize
|
||||
|
||||
if committeePerSlot > params.BeaconConfig().MaxCommitteesPerSlot {
|
||||
return params.BeaconConfig().MaxCommitteesPerSlot
|
||||
@@ -67,7 +68,7 @@ func SlotCommitteeCount(activeValidatorCount uint64) uint64 {
|
||||
// index=(slot % SLOTS_PER_EPOCH) * committees_per_slot + index,
|
||||
// count=committees_per_slot * SLOTS_PER_EPOCH,
|
||||
// )
|
||||
func BeaconCommitteeFromState(state *stateTrie.BeaconState, slot, committeeIndex uint64) ([]uint64, error) {
|
||||
func BeaconCommitteeFromState(state *stateTrie.BeaconState, slot types.Slot, committeeIndex uint64) ([]uint64, error) {
|
||||
epoch := SlotToEpoch(slot)
|
||||
seed, err := Seed(state, epoch, params.BeaconConfig().DomainBeaconAttester)
|
||||
if err != nil {
|
||||
@@ -93,7 +94,7 @@ func BeaconCommitteeFromState(state *stateTrie.BeaconState, slot, committeeIndex
|
||||
// BeaconCommittee returns the crosslink committee of a given slot and committee index. The
|
||||
// validator indices and seed are provided as an argument rather than a imported implementation
|
||||
// from the spec definition. Having them as an argument allows for cheaper computation run time.
|
||||
func BeaconCommittee(validatorIndices []uint64, seed [32]byte, slot, committeeIndex uint64) ([]uint64, error) {
|
||||
func BeaconCommittee(validatorIndices []uint64, seed [32]byte, slot types.Slot, committeeIndex uint64) ([]uint64, error) {
|
||||
indices, err := committeeCache.Committee(slot, seed, committeeIndex)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not interface with committee cache")
|
||||
@@ -104,8 +105,8 @@ func BeaconCommittee(validatorIndices []uint64, seed [32]byte, slot, committeeIn
|
||||
|
||||
committeesPerSlot := SlotCommitteeCount(uint64(len(validatorIndices)))
|
||||
|
||||
epochOffset := committeeIndex + (slot%params.BeaconConfig().SlotsPerEpoch)*committeesPerSlot
|
||||
count := committeesPerSlot * params.BeaconConfig().SlotsPerEpoch
|
||||
epochOffset := committeeIndex + uint64(slot.ModSlot(params.BeaconConfig().SlotsPerEpoch).Mul(committeesPerSlot))
|
||||
count := committeesPerSlot * uint64(params.BeaconConfig().SlotsPerEpoch)
|
||||
|
||||
return ComputeCommittee(validatorIndices, seed, epochOffset, count)
|
||||
}
|
||||
@@ -154,7 +155,7 @@ func ComputeCommittee(
|
||||
// CommitteeAssignmentContainer represents a committee, index, and attester slot for a given epoch.
|
||||
type CommitteeAssignmentContainer struct {
|
||||
Committee []uint64
|
||||
AttesterSlot uint64
|
||||
AttesterSlot types.Slot
|
||||
CommitteeIndex uint64
|
||||
}
|
||||
|
||||
@@ -167,8 +168,8 @@ type CommitteeAssignmentContainer struct {
|
||||
// 4. Construct a map of validator indices pointing to the respective committees.
|
||||
func CommitteeAssignments(
|
||||
state *stateTrie.BeaconState,
|
||||
epoch uint64,
|
||||
) (map[uint64]*CommitteeAssignmentContainer, map[uint64][]uint64, error) {
|
||||
epoch types.Epoch,
|
||||
) (map[uint64]*CommitteeAssignmentContainer, map[uint64][]types.Slot, error) {
|
||||
nextEpoch := NextEpoch(state)
|
||||
if epoch > nextEpoch {
|
||||
return nil, nil, fmt.Errorf(
|
||||
@@ -185,7 +186,7 @@ func CommitteeAssignments(
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
proposerIndexToSlots := make(map[uint64][]uint64, params.BeaconConfig().SlotsPerEpoch)
|
||||
proposerIndexToSlots := make(map[uint64][]types.Slot, params.BeaconConfig().SlotsPerEpoch)
|
||||
// Proposal epochs do not have a look ahead, so we skip them over here.
|
||||
validProposalEpoch := epoch < nextEpoch
|
||||
for slot := startSlot; slot < startSlot+params.BeaconConfig().SlotsPerEpoch && validProposalEpoch; slot++ {
|
||||
@@ -210,10 +211,10 @@ func CommitteeAssignments(
|
||||
// Each slot in an epoch has a different set of committees. This value is derived from the
|
||||
// active validator set, which does not change.
|
||||
numCommitteesPerSlot := SlotCommitteeCount(uint64(len(activeValidatorIndices)))
|
||||
validatorIndexToCommittee := make(map[uint64]*CommitteeAssignmentContainer, numCommitteesPerSlot*params.BeaconConfig().SlotsPerEpoch)
|
||||
validatorIndexToCommittee := make(map[uint64]*CommitteeAssignmentContainer, params.BeaconConfig().SlotsPerEpoch.Mul(numCommitteesPerSlot))
|
||||
|
||||
// Compute all committees for all slots.
|
||||
for i := uint64(0); i < params.BeaconConfig().SlotsPerEpoch; i++ {
|
||||
for i := types.Slot(0); i < params.BeaconConfig().SlotsPerEpoch; i++ {
|
||||
// Compute committees.
|
||||
for j := uint64(0); j < numCommitteesPerSlot; j++ {
|
||||
slot := startSlot + i
|
||||
@@ -267,7 +268,7 @@ func VerifyAttestationBitfieldLengths(state *stateTrie.BeaconState, att *ethpb.A
|
||||
|
||||
// ShuffledIndices uses input beacon state and returns the shuffled indices of the input epoch,
|
||||
// the shuffled indices then can be used to break up into committees.
|
||||
func ShuffledIndices(state *stateTrie.BeaconState, epoch uint64) ([]uint64, error) {
|
||||
func ShuffledIndices(state *stateTrie.BeaconState, epoch types.Epoch) ([]uint64, error) {
|
||||
seed, err := Seed(state, epoch, params.BeaconConfig().DomainBeaconAttester)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get seed for epoch %d", epoch)
|
||||
@@ -289,8 +290,8 @@ func ShuffledIndices(state *stateTrie.BeaconState, epoch uint64) ([]uint64, erro
|
||||
|
||||
// UpdateCommitteeCache gets called at the beginning of every epoch to cache the committee shuffled indices
|
||||
// list with committee index and epoch number. It caches the shuffled indices for current epoch and next epoch.
|
||||
func UpdateCommitteeCache(state *stateTrie.BeaconState, epoch uint64) error {
|
||||
for _, e := range []uint64{epoch, epoch + 1} {
|
||||
func UpdateCommitteeCache(state *stateTrie.BeaconState, epoch types.Epoch) error {
|
||||
for _, e := range []types.Epoch{epoch, epoch + 1} {
|
||||
seed, err := Seed(state, e, params.BeaconConfig().DomainBeaconAttester)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -318,7 +319,7 @@ func UpdateCommitteeCache(state *stateTrie.BeaconState, epoch uint64) error {
|
||||
|
||||
if err := committeeCache.AddCommitteeShuffledList(&cache.Committees{
|
||||
ShuffledIndices: shuffledIndices,
|
||||
CommitteeCount: count * params.BeaconConfig().SlotsPerEpoch,
|
||||
CommitteeCount: uint64(params.BeaconConfig().SlotsPerEpoch.Mul(count)),
|
||||
Seed: seed,
|
||||
SortedIndices: sortedIndices,
|
||||
}); err != nil {
|
||||
@@ -330,15 +331,15 @@ func UpdateCommitteeCache(state *stateTrie.BeaconState, epoch uint64) error {
|
||||
}
|
||||
|
||||
// UpdateProposerIndicesInCache updates proposer indices entry of the committee cache.
|
||||
func UpdateProposerIndicesInCache(state *stateTrie.BeaconState, epoch uint64) error {
|
||||
func UpdateProposerIndicesInCache(state *stateTrie.BeaconState) error {
|
||||
// The cache uses the state root at the (current epoch - 2)'s slot as key. (e.g. for epoch 2, the key is root at slot 31)
|
||||
// Which is the reason why we skip genesis epoch.
|
||||
if epoch <= params.BeaconConfig().GenesisEpoch+params.BeaconConfig().MinSeedLookahead {
|
||||
if CurrentEpoch(state) <= params.BeaconConfig().GenesisEpoch+params.BeaconConfig().MinSeedLookahead {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Use state root from (current_epoch - 1 - lookahead))
|
||||
wantedEpoch := PrevEpoch(state)
|
||||
wantedEpoch := CurrentEpoch(state) - 1
|
||||
if wantedEpoch >= params.BeaconConfig().MinSeedLookahead {
|
||||
wantedEpoch -= params.BeaconConfig().MinSeedLookahead
|
||||
}
|
||||
@@ -363,7 +364,7 @@ func UpdateProposerIndicesInCache(state *stateTrie.BeaconState, epoch uint64) er
|
||||
return nil
|
||||
}
|
||||
|
||||
indices, err := ActiveValidatorIndices(state, epoch)
|
||||
indices, err := ActiveValidatorIndices(state, CurrentEpoch(state))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -398,8 +399,8 @@ func precomputeProposerIndices(state *stateTrie.BeaconState, activeIndices []uin
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := uint64(0); i < params.BeaconConfig().SlotsPerEpoch; i++ {
|
||||
seedWithSlot := append(seed[:], bytesutil.Bytes8(slot+i)...)
|
||||
for i := uint64(0); i < uint64(params.BeaconConfig().SlotsPerEpoch); i++ {
|
||||
seedWithSlot := append(seed[:], bytesutil.Bytes8(uint64(slot)+i)...)
|
||||
seedWithSlotHash := hashFunc(seedWithSlot)
|
||||
index, err := ComputeProposerIndex(state, activeIndices, seedWithSlotHash)
|
||||
if err != nil {
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
@@ -89,7 +90,7 @@ func TestVerifyBitfieldLength_OK(t *testing.T) {
|
||||
|
||||
func TestCommitteeAssignments_CannotRetrieveFutureEpoch(t *testing.T) {
|
||||
ClearCache()
|
||||
epoch := uint64(1)
|
||||
epoch := types.Epoch(1)
|
||||
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
Slot: 0, // Epoch 0.
|
||||
})
|
||||
@@ -101,7 +102,7 @@ func TestCommitteeAssignments_CannotRetrieveFutureEpoch(t *testing.T) {
|
||||
func TestCommitteeAssignments_NoProposerForSlot0(t *testing.T) {
|
||||
validators := make([]*ethpb.Validator, 4*params.BeaconConfig().SlotsPerEpoch)
|
||||
for i := 0; i < len(validators); i++ {
|
||||
var activationEpoch uint64
|
||||
var activationEpoch types.Epoch
|
||||
if i >= len(validators)/2 {
|
||||
activationEpoch = 3
|
||||
}
|
||||
@@ -131,7 +132,7 @@ func TestCommitteeAssignments_CanRetrieve(t *testing.T) {
|
||||
validators := make([]*ethpb.Validator, 4*params.BeaconConfig().SlotsPerEpoch)
|
||||
for i := 0; i < len(validators); i++ {
|
||||
// First 2 epochs only half validators are activated.
|
||||
var activationEpoch uint64
|
||||
var activationEpoch types.Epoch
|
||||
if i >= len(validators)/2 {
|
||||
activationEpoch = 3
|
||||
}
|
||||
@@ -150,11 +151,11 @@ func TestCommitteeAssignments_CanRetrieve(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
index uint64
|
||||
slot uint64
|
||||
slot types.Slot
|
||||
committee []uint64
|
||||
committeeIndex uint64
|
||||
isProposer bool
|
||||
proposerSlot uint64
|
||||
proposerSlot types.Slot
|
||||
}{
|
||||
{
|
||||
index: 0,
|
||||
@@ -208,7 +209,7 @@ func TestCommitteeAssignments_CannotRetrieveFuture(t *testing.T) {
|
||||
validators := make([]*ethpb.Validator, 4*params.BeaconConfig().SlotsPerEpoch)
|
||||
for i := 0; i < len(validators); i++ {
|
||||
// First 2 epochs only half validators are activated.
|
||||
var activationEpoch uint64
|
||||
var activationEpoch types.Epoch
|
||||
if i >= len(validators)/2 {
|
||||
activationEpoch = 3
|
||||
}
|
||||
@@ -249,17 +250,17 @@ func TestCommitteeAssignments_EverySlotHasMin1Proposer(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
ClearCache()
|
||||
epoch := uint64(1)
|
||||
epoch := types.Epoch(1)
|
||||
_, proposerIndexToSlots, err := CommitteeAssignments(state, epoch)
|
||||
require.NoError(t, err, "Failed to determine CommitteeAssignments")
|
||||
|
||||
slotsWithProposers := make(map[uint64]bool)
|
||||
slotsWithProposers := make(map[types.Slot]bool)
|
||||
for _, proposerSlots := range proposerIndexToSlots {
|
||||
for _, slot := range proposerSlots {
|
||||
slotsWithProposers[slot] = true
|
||||
}
|
||||
}
|
||||
assert.Equal(t, params.BeaconConfig().SlotsPerEpoch, uint64(len(slotsWithProposers)), "Unexpected slots")
|
||||
assert.Equal(t, uint64(params.BeaconConfig().SlotsPerEpoch), uint64(len(slotsWithProposers)), "Unexpected slots")
|
||||
startSlot, err := StartSlot(epoch)
|
||||
require.NoError(t, err)
|
||||
endSlot, err := StartSlot(epoch + 1)
|
||||
@@ -287,7 +288,7 @@ func TestVerifyAttestationBitfieldLengths_OK(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
attestation *ethpb.Attestation
|
||||
stateSlot uint64
|
||||
stateSlot types.Slot
|
||||
verificationFailure bool
|
||||
}{
|
||||
{
|
||||
@@ -417,12 +418,12 @@ func TestUpdateCommitteeCache_CanUpdate(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, UpdateCommitteeCache(state, CurrentEpoch(state)))
|
||||
|
||||
epoch := uint64(1)
|
||||
epoch := types.Epoch(1)
|
||||
idx := uint64(1)
|
||||
seed, err := Seed(state, epoch, params.BeaconConfig().DomainBeaconAttester)
|
||||
require.NoError(t, err)
|
||||
|
||||
indices, err = committeeCache.Committee(epoch*params.BeaconConfig().SlotsPerEpoch, seed, idx)
|
||||
indices, err = committeeCache.Committee(params.BeaconConfig().SlotsPerEpoch.Mul(uint64(epoch)), seed, idx)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, params.BeaconConfig().TargetCommitteeSize, uint64(len(indices)), "Did not save correct indices lengths")
|
||||
}
|
||||
@@ -602,7 +603,7 @@ func BenchmarkComputeCommittee4000000_WithOutCache(b *testing.B) {
|
||||
|
||||
func TestBeaconCommitteeFromState_UpdateCacheForPreviousEpoch(t *testing.T) {
|
||||
committeeSize := uint64(16)
|
||||
validators := make([]*ethpb.Validator, committeeSize*params.BeaconConfig().SlotsPerEpoch)
|
||||
validators := make([]*ethpb.Validator, params.BeaconConfig().SlotsPerEpoch.Mul(committeeSize))
|
||||
for i := 0; i < len(validators); i++ {
|
||||
validators[i] = ðpb.Validator{
|
||||
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
|
||||
@@ -649,7 +650,7 @@ func TestPrecomputeProposerIndices_Ok(t *testing.T) {
|
||||
var wantedProposerIndices []uint64
|
||||
seed, err := Seed(state, 0, params.BeaconConfig().DomainBeaconProposer)
|
||||
require.NoError(t, err)
|
||||
for i := uint64(0); i < params.BeaconConfig().SlotsPerEpoch; i++ {
|
||||
for i := uint64(0); i < uint64(params.BeaconConfig().SlotsPerEpoch); i++ {
|
||||
seedWithSlot := append(seed[:], bytesutil.Bytes8(i)...)
|
||||
seedWithSlotHash := hashutil.Hash(seedWithSlot)
|
||||
index, err := ComputeProposerIndex(state, indices, seedWithSlotHash)
|
||||
@@ -658,9 +659,3 @@ func TestPrecomputeProposerIndices_Ok(t *testing.T) {
|
||||
}
|
||||
assert.DeepEqual(t, wantedProposerIndices, proposerIndices, "Did not precompute proposer indices correctly")
|
||||
}
|
||||
|
||||
func TestUpdateProposerIndicesInCache_SlotOutOfBound(t *testing.T) {
|
||||
err := UpdateProposerIndicesInCache(&beaconstate.BeaconState{}, 2)
|
||||
want := "out of bound"
|
||||
require.ErrorContains(t, want, err)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/shared/bls"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
@@ -17,7 +18,7 @@ import (
|
||||
// """
|
||||
// mix = get_randao_mix(state, Epoch(epoch + EPOCHS_PER_HISTORICAL_VECTOR - MIN_SEED_LOOKAHEAD - 1)) # Avoid underflow
|
||||
// return hash(domain_type + int_to_bytes(epoch, length=8) + mix)
|
||||
func Seed(state *stateTrie.BeaconState, epoch uint64, domain [bls.DomainByteLength]byte) ([32]byte, error) {
|
||||
func Seed(state *stateTrie.BeaconState, epoch types.Epoch, domain [bls.DomainByteLength]byte) ([32]byte, error) {
|
||||
// See https://github.com/ethereum/eth2.0-specs/pull/1296 for
|
||||
// rationale on why offset has to look down by 1.
|
||||
lookAheadEpoch := epoch + params.BeaconConfig().EpochsPerHistoricalVector -
|
||||
@@ -27,7 +28,7 @@ func Seed(state *stateTrie.BeaconState, epoch uint64, domain [bls.DomainByteLeng
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
seed := append(domain[:], bytesutil.Bytes8(epoch)...)
|
||||
seed := append(domain[:], bytesutil.Bytes8(uint64(epoch))...)
|
||||
seed = append(seed, randaoMix...)
|
||||
|
||||
seed32 := hashutil.Hash(seed)
|
||||
@@ -44,6 +45,6 @@ func Seed(state *stateTrie.BeaconState, epoch uint64, domain [bls.DomainByteLeng
|
||||
// Return the randao mix at a recent ``epoch``.
|
||||
// """
|
||||
// return state.randao_mixes[epoch % EPOCHS_PER_HISTORICAL_VECTOR]
|
||||
func RandaoMix(state *stateTrie.BeaconState, epoch uint64) ([]byte, error) {
|
||||
return state.RandaoMixAtIndex(epoch % params.BeaconConfig().EpochsPerHistoricalVector)
|
||||
func RandaoMix(state *stateTrie.BeaconState, epoch types.Epoch) ([]byte, error) {
|
||||
return state.RandaoMixAtIndex(uint64(epoch % params.BeaconConfig().EpochsPerHistoricalVector))
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"encoding/binary"
|
||||
"testing"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
@@ -22,7 +23,7 @@ func TestRandaoMix_OK(t *testing.T) {
|
||||
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{RandaoMixes: randaoMixes})
|
||||
require.NoError(t, err)
|
||||
tests := []struct {
|
||||
epoch uint64
|
||||
epoch types.Epoch
|
||||
randaoMix []byte
|
||||
}{
|
||||
{
|
||||
@@ -39,7 +40,7 @@ func TestRandaoMix_OK(t *testing.T) {
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
require.NoError(t, state.SetSlot((test.epoch+1)*params.BeaconConfig().SlotsPerEpoch))
|
||||
require.NoError(t, state.SetSlot(params.BeaconConfig().SlotsPerEpoch.Mul(uint64(test.epoch+1))))
|
||||
mix, err := RandaoMix(state, test.epoch)
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, test.randaoMix, mix, "Incorrect randao mix")
|
||||
@@ -56,7 +57,7 @@ func TestRandaoMix_CopyOK(t *testing.T) {
|
||||
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{RandaoMixes: randaoMixes})
|
||||
require.NoError(t, err)
|
||||
tests := []struct {
|
||||
epoch uint64
|
||||
epoch types.Epoch
|
||||
randaoMix []byte
|
||||
}{
|
||||
{
|
||||
@@ -73,10 +74,10 @@ func TestRandaoMix_CopyOK(t *testing.T) {
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
require.NoError(t, state.SetSlot((test.epoch+1)*params.BeaconConfig().SlotsPerEpoch))
|
||||
require.NoError(t, state.SetSlot(params.BeaconConfig().SlotsPerEpoch.Mul(uint64(test.epoch+1))))
|
||||
mix, err := RandaoMix(state, test.epoch)
|
||||
require.NoError(t, err)
|
||||
uniqueNumber := params.BeaconConfig().EpochsPerHistoricalVector + 1000
|
||||
uniqueNumber := uint64(params.BeaconConfig().EpochsPerHistoricalVector.Add(1000))
|
||||
binary.LittleEndian.PutUint64(mix, uniqueNumber)
|
||||
|
||||
for _, mx := range randaoMixes {
|
||||
@@ -93,7 +94,7 @@ func TestGenerateSeed_OK(t *testing.T) {
|
||||
binary.LittleEndian.PutUint64(intInBytes, uint64(i))
|
||||
randaoMixes[i] = intInBytes
|
||||
}
|
||||
slot := 10 * params.BeaconConfig().MinSeedLookahead * params.BeaconConfig().SlotsPerEpoch
|
||||
slot := params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().MinSeedLookahead * 10))
|
||||
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{
|
||||
RandaoMixes: randaoMixes,
|
||||
Slot: slot,
|
||||
|
||||
@@ -51,11 +51,11 @@ func TestSplitIndices_OK(t *testing.T) {
|
||||
for i := uint64(0); i < numValidators; i++ {
|
||||
l = append(l, i)
|
||||
}
|
||||
split := SplitIndices(l, params.BeaconConfig().SlotsPerEpoch)
|
||||
assert.Equal(t, params.BeaconConfig().SlotsPerEpoch, uint64(len(split)), "Split list failed due to incorrect length")
|
||||
split := SplitIndices(l, uint64(params.BeaconConfig().SlotsPerEpoch))
|
||||
assert.Equal(t, uint64(params.BeaconConfig().SlotsPerEpoch), uint64(len(split)), "Split list failed due to incorrect length")
|
||||
|
||||
for _, s := range split {
|
||||
assert.Equal(t, numValidators/params.BeaconConfig().SlotsPerEpoch, uint64(len(s)), "Split list failed due to incorrect length")
|
||||
assert.Equal(t, numValidators/uint64(params.BeaconConfig().SlotsPerEpoch), uint64(len(s)), "Split list failed due to incorrect length")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@ package helpers
|
||||
import (
|
||||
fssz "github.com/ferranbt/fastssz"
|
||||
"github.com/pkg/errors"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/go-ssz"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bls"
|
||||
@@ -23,7 +23,7 @@ const DomainByteLength = 4
|
||||
var ErrSigFailedToVerify = errors.New("signature did not verify")
|
||||
|
||||
// ComputeDomainAndSign computes the domain and signing root and sign it using the passed in private key.
|
||||
func ComputeDomainAndSign(st *state.BeaconState, epoch uint64, obj interface{}, domain [4]byte, key bls.SecretKey) ([]byte, error) {
|
||||
func ComputeDomainAndSign(st *state.BeaconState, epoch types.Epoch, obj fssz.HashRoot, domain [4]byte, key bls.SecretKey) ([]byte, error) {
|
||||
d, err := Domain(st.Fork(), epoch, domain, st.GenesisValidatorRoot())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -46,16 +46,8 @@ func ComputeDomainAndSign(st *state.BeaconState, epoch uint64, obj interface{},
|
||||
// object_root=hash_tree_root(ssz_object),
|
||||
// domain=domain,
|
||||
// ))
|
||||
func ComputeSigningRoot(object interface{}, domain []byte) ([32]byte, error) {
|
||||
if object == nil {
|
||||
return [32]byte{}, errors.New("cannot compute signing root of nil")
|
||||
}
|
||||
return signingData(func() ([32]byte, error) {
|
||||
if v, ok := object.(fssz.HashRoot); ok {
|
||||
return v.HashTreeRoot()
|
||||
}
|
||||
return ssz.HashTreeRoot(object)
|
||||
}, domain)
|
||||
func ComputeSigningRoot(object fssz.HashRoot, domain []byte) ([32]byte, error) {
|
||||
return signingData(object.HashTreeRoot, domain)
|
||||
}
|
||||
|
||||
// Computes the signing data by utilising the provided root function and then
|
||||
@@ -73,7 +65,7 @@ func signingData(rootFunc func() ([32]byte, error), domain []byte) ([32]byte, er
|
||||
}
|
||||
|
||||
// ComputeDomainVerifySigningRoot computes domain and verifies signing root of an object given the beacon state, validator index and signature.
|
||||
func ComputeDomainVerifySigningRoot(st *state.BeaconState, index, epoch uint64, obj interface{}, domain [4]byte, sig []byte) error {
|
||||
func ComputeDomainVerifySigningRoot(st *state.BeaconState, index uint64, epoch types.Epoch, obj fssz.HashRoot, domain [4]byte, sig []byte) error {
|
||||
v, err := st.ValidatorAtIndex(index)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -86,7 +78,7 @@ func ComputeDomainVerifySigningRoot(st *state.BeaconState, index, epoch uint64,
|
||||
}
|
||||
|
||||
// VerifySigningRoot verifies the signing root of an object given it's public key, signature and domain.
|
||||
func VerifySigningRoot(obj interface{}, pub, signature, domain []byte) error {
|
||||
func VerifySigningRoot(obj fssz.HashRoot, pub, signature, domain []byte) error {
|
||||
publicKey, err := bls.PublicKeyFromBytes(pub)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not convert bytes to public key")
|
||||
@@ -107,7 +99,7 @@ func VerifySigningRoot(obj interface{}, pub, signature, domain []byte) error {
|
||||
|
||||
// VerifyBlockSigningRoot verifies the signing root of a block given it's public key, signature and domain.
|
||||
func VerifyBlockSigningRoot(blk *ethpb.BeaconBlock, pub, signature, domain []byte) error {
|
||||
set, err := RetrieveBlockSignatureSet(blk, pub, signature, domain)
|
||||
set, err := BlockSignatureSet(blk, pub, signature, domain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -126,9 +118,9 @@ func VerifyBlockSigningRoot(blk *ethpb.BeaconBlock, pub, signature, domain []byt
|
||||
return nil
|
||||
}
|
||||
|
||||
// RetrieveBlockSignatureSet retrieves the relevant signature, message and pubkey data from a block and collating it
|
||||
// BlockSignatureSet retrieves the relevant signature, message and pubkey data from a block and collating it
|
||||
// into a signature set object.
|
||||
func RetrieveBlockSignatureSet(blk *ethpb.BeaconBlock, pub, signature, domain []byte) (*bls.SignatureSet, error) {
|
||||
func BlockSignatureSet(blk *ethpb.BeaconBlock, pub, signature, domain []byte) (*bls.SignatureSet, error) {
|
||||
publicKey, err := bls.PublicKeyFromBytes(pub)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not convert bytes to public key")
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/shared/mathutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
@@ -24,8 +25,8 @@ const MaxSlotBuffer = uint64(1 << 7)
|
||||
// Return the epoch number of ``slot``.
|
||||
// """
|
||||
// return Epoch(slot // SLOTS_PER_EPOCH)
|
||||
func SlotToEpoch(slot uint64) uint64 {
|
||||
return slot / params.BeaconConfig().SlotsPerEpoch
|
||||
func SlotToEpoch(slot types.Slot) types.Epoch {
|
||||
return types.Epoch(slot.DivSlot(params.BeaconConfig().SlotsPerEpoch))
|
||||
}
|
||||
|
||||
// CurrentEpoch returns the current epoch number calculated from
|
||||
@@ -37,7 +38,7 @@ func SlotToEpoch(slot uint64) uint64 {
|
||||
// Return the current epoch.
|
||||
// """
|
||||
// return compute_epoch_of_slot(state.slot)
|
||||
func CurrentEpoch(state *stateTrie.BeaconState) uint64 {
|
||||
func CurrentEpoch(state *stateTrie.BeaconState) types.Epoch {
|
||||
return SlotToEpoch(state.Slot())
|
||||
}
|
||||
|
||||
@@ -52,7 +53,7 @@ func CurrentEpoch(state *stateTrie.BeaconState) uint64 {
|
||||
// """
|
||||
// current_epoch = get_current_epoch(state)
|
||||
// return GENESIS_EPOCH if current_epoch == GENESIS_EPOCH else Epoch(current_epoch - 1)
|
||||
func PrevEpoch(state *stateTrie.BeaconState) uint64 {
|
||||
func PrevEpoch(state *stateTrie.BeaconState) types.Epoch {
|
||||
currentEpoch := CurrentEpoch(state)
|
||||
if currentEpoch == 0 {
|
||||
return 0
|
||||
@@ -62,7 +63,7 @@ func PrevEpoch(state *stateTrie.BeaconState) uint64 {
|
||||
|
||||
// NextEpoch returns the next epoch number calculated from
|
||||
// the slot number stored in beacon state.
|
||||
func NextEpoch(state *stateTrie.BeaconState) uint64 {
|
||||
func NextEpoch(state *stateTrie.BeaconState) types.Epoch {
|
||||
return SlotToEpoch(state.Slot()) + 1
|
||||
}
|
||||
|
||||
@@ -75,8 +76,8 @@ func NextEpoch(state *stateTrie.BeaconState) uint64 {
|
||||
// Return the start slot of ``epoch``.
|
||||
// """
|
||||
// return Slot(epoch * SLOTS_PER_EPOCH)
|
||||
func StartSlot(epoch uint64) (uint64, error) {
|
||||
slot, err := mathutil.Mul64(epoch, params.BeaconConfig().SlotsPerEpoch)
|
||||
func StartSlot(epoch types.Epoch) (types.Slot, error) {
|
||||
slot, err := params.BeaconConfig().SlotsPerEpoch.SafeMul(uint64(epoch))
|
||||
if err != nil {
|
||||
return slot, errors.Errorf("start slot calculation overflows: %v", err)
|
||||
}
|
||||
@@ -85,7 +86,7 @@ func StartSlot(epoch uint64) (uint64, error) {
|
||||
|
||||
// EndSlot returns the last slot number of the
|
||||
// current epoch.
|
||||
func EndSlot(epoch uint64) (uint64, error) {
|
||||
func EndSlot(epoch types.Epoch) (types.Slot, error) {
|
||||
if epoch == math.MaxUint64 {
|
||||
return 0, errors.New("start slot calculation overflows")
|
||||
}
|
||||
@@ -98,23 +99,23 @@ func EndSlot(epoch uint64) (uint64, error) {
|
||||
|
||||
// IsEpochStart returns true if the given slot number is an epoch starting slot
|
||||
// number.
|
||||
func IsEpochStart(slot uint64) bool {
|
||||
func IsEpochStart(slot types.Slot) bool {
|
||||
return slot%params.BeaconConfig().SlotsPerEpoch == 0
|
||||
}
|
||||
|
||||
// IsEpochEnd returns true if the given slot number is an epoch ending slot
|
||||
// number.
|
||||
func IsEpochEnd(slot uint64) bool {
|
||||
func IsEpochEnd(slot types.Slot) bool {
|
||||
return IsEpochStart(slot + 1)
|
||||
}
|
||||
|
||||
// SlotsSinceEpochStarts returns number of slots since the start of the epoch.
|
||||
func SlotsSinceEpochStarts(slot uint64) uint64 {
|
||||
func SlotsSinceEpochStarts(slot types.Slot) types.Slot {
|
||||
return slot % params.BeaconConfig().SlotsPerEpoch
|
||||
}
|
||||
|
||||
// VerifySlotTime validates the input slot is not from the future.
|
||||
func VerifySlotTime(genesisTime, slot uint64, timeTolerance time.Duration) error {
|
||||
func VerifySlotTime(genesisTime uint64, slot types.Slot, timeTolerance time.Duration) error {
|
||||
slotTime, err := SlotToTime(genesisTime, slot)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -136,12 +137,12 @@ func VerifySlotTime(genesisTime, slot uint64, timeTolerance time.Duration) error
|
||||
}
|
||||
|
||||
// SlotToTime takes the given slot and genesis time to determine the start time of the slot.
|
||||
func SlotToTime(genesisTimeSec, slot uint64) (time.Time, error) {
|
||||
timeSinceGenesis, err := mathutil.Mul64(slot, params.BeaconConfig().SecondsPerSlot)
|
||||
func SlotToTime(genesisTimeSec uint64, slot types.Slot) (time.Time, error) {
|
||||
timeSinceGenesis, err := slot.SafeMul(params.BeaconConfig().SecondsPerSlot)
|
||||
if err != nil {
|
||||
return time.Unix(0, 0), fmt.Errorf("slot (%d) is in the far distant future: %w", slot, err)
|
||||
}
|
||||
sTime, err := mathutil.Add64(genesisTimeSec, timeSinceGenesis)
|
||||
sTime, err := timeSinceGenesis.SafeAdd(genesisTimeSec)
|
||||
if err != nil {
|
||||
return time.Unix(0, 0), fmt.Errorf("slot (%d) is in the far distant future: %w", slot, err)
|
||||
}
|
||||
@@ -149,26 +150,26 @@ func SlotToTime(genesisTimeSec, slot uint64) (time.Time, error) {
|
||||
}
|
||||
|
||||
// SlotsSince computes the number of time slots that have occurred since the given timestamp.
|
||||
func SlotsSince(time time.Time) uint64 {
|
||||
func SlotsSince(time time.Time) types.Slot {
|
||||
return CurrentSlot(uint64(time.Unix()))
|
||||
}
|
||||
|
||||
// CurrentSlot returns the current slot as determined by the local clock and
|
||||
// provided genesis time.
|
||||
func CurrentSlot(genesisTimeSec uint64) uint64 {
|
||||
func CurrentSlot(genesisTimeSec uint64) types.Slot {
|
||||
now := timeutils.Now().Unix()
|
||||
genesis := int64(genesisTimeSec)
|
||||
if now < genesis {
|
||||
return 0
|
||||
}
|
||||
return uint64(now-genesis) / params.BeaconConfig().SecondsPerSlot
|
||||
return types.Slot(uint64(now-genesis) / params.BeaconConfig().SecondsPerSlot)
|
||||
}
|
||||
|
||||
// ValidateSlotClock validates a provided slot against the local
|
||||
// clock to ensure slots that are unreasonable are returned with
|
||||
// an error.
|
||||
func ValidateSlotClock(slot, genesisTimeSec uint64) error {
|
||||
maxPossibleSlot := CurrentSlot(genesisTimeSec) + MaxSlotBuffer
|
||||
func ValidateSlotClock(slot types.Slot, genesisTimeSec uint64) error {
|
||||
maxPossibleSlot := CurrentSlot(genesisTimeSec).Add(MaxSlotBuffer)
|
||||
// Defensive check to ensure that we only process slots up to a hard limit
|
||||
// from our local clock.
|
||||
if slot > maxPossibleSlot {
|
||||
@@ -178,7 +179,7 @@ func ValidateSlotClock(slot, genesisTimeSec uint64) error {
|
||||
}
|
||||
|
||||
// RoundUpToNearestEpoch rounds up the provided slot value to the nearest epoch.
|
||||
func RoundUpToNearestEpoch(slot uint64) uint64 {
|
||||
func RoundUpToNearestEpoch(slot types.Slot) types.Slot {
|
||||
if slot%params.BeaconConfig().SlotsPerEpoch != 0 {
|
||||
slot -= slot % params.BeaconConfig().SlotsPerEpoch
|
||||
slot += params.BeaconConfig().SlotsPerEpoch
|
||||
@@ -199,7 +200,7 @@ func RoundUpToNearestEpoch(slot uint64) uint64 {
|
||||
// else:
|
||||
// weak_subjectivity_period += SAFETY_DECAY*val_count/(2*100*MIN_PER_EPOCH_CHURN_LIMIT)
|
||||
// return weak_subjectivity_period
|
||||
func WeakSubjectivityCheckptEpoch(valCount uint64) (uint64, error) {
|
||||
func WeakSubjectivityCheckptEpoch(valCount uint64) (types.Epoch, error) {
|
||||
wsp := params.BeaconConfig().MinValidatorWithdrawabilityDelay
|
||||
|
||||
m := params.BeaconConfig().MinPerEpochChurnLimit
|
||||
@@ -207,24 +208,22 @@ func WeakSubjectivityCheckptEpoch(valCount uint64) (uint64, error) {
|
||||
d := params.BeaconConfig().SafetyDecay
|
||||
if valCount >= m*q {
|
||||
v := d * q / (2 * 100)
|
||||
wsp += v
|
||||
wsp += types.Epoch(v)
|
||||
} else {
|
||||
v, err := mathutil.Mul64(d, valCount)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
v = v / (2 * 100 * m)
|
||||
wsp += v
|
||||
v /= 2 * 100 * m
|
||||
wsp += types.Epoch(v)
|
||||
}
|
||||
return wsp, nil
|
||||
}
|
||||
|
||||
// VotingPeriodStartTime returns the current voting period's start time
|
||||
// depending on the provided genesis and current slot.
|
||||
func VotingPeriodStartTime(genesis, slot uint64) uint64 {
|
||||
startTime := genesis
|
||||
startTime +=
|
||||
(slot - (slot % (params.BeaconConfig().EpochsPerEth1VotingPeriod * params.BeaconConfig().SlotsPerEpoch))) *
|
||||
params.BeaconConfig().SecondsPerSlot
|
||||
return startTime
|
||||
func VotingPeriodStartTime(genesis uint64, slot types.Slot) uint64 {
|
||||
slots := params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().EpochsPerEth1VotingPeriod))
|
||||
startTime := uint64((slot - slot.ModSlot(slots)).Mul(params.BeaconConfig().SecondsPerSlot))
|
||||
return genesis + startTime
|
||||
}
|
||||
|
||||
@@ -5,19 +5,19 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
"github.com/prysmaticlabs/prysm/shared/timeutils"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
"github.com/prysmaticlabs/prysm/shared/timeutils"
|
||||
)
|
||||
|
||||
func TestSlotToEpoch_OK(t *testing.T) {
|
||||
tests := []struct {
|
||||
slot uint64
|
||||
epoch uint64
|
||||
slot types.Slot
|
||||
epoch types.Epoch
|
||||
}{
|
||||
{slot: 0, epoch: 0},
|
||||
{slot: 50, epoch: 1},
|
||||
@@ -32,8 +32,8 @@ func TestSlotToEpoch_OK(t *testing.T) {
|
||||
|
||||
func TestCurrentEpoch_OK(t *testing.T) {
|
||||
tests := []struct {
|
||||
slot uint64
|
||||
epoch uint64
|
||||
slot types.Slot
|
||||
epoch types.Epoch
|
||||
}{
|
||||
{slot: 0, epoch: 0},
|
||||
{slot: 50, epoch: 1},
|
||||
@@ -50,8 +50,8 @@ func TestCurrentEpoch_OK(t *testing.T) {
|
||||
|
||||
func TestPrevEpoch_OK(t *testing.T) {
|
||||
tests := []struct {
|
||||
slot uint64
|
||||
epoch uint64
|
||||
slot types.Slot
|
||||
epoch types.Epoch
|
||||
}{
|
||||
{slot: 0, epoch: 0},
|
||||
{slot: 0 + params.BeaconConfig().SlotsPerEpoch + 1, epoch: 0},
|
||||
@@ -66,14 +66,14 @@ func TestPrevEpoch_OK(t *testing.T) {
|
||||
|
||||
func TestNextEpoch_OK(t *testing.T) {
|
||||
tests := []struct {
|
||||
slot uint64
|
||||
epoch uint64
|
||||
slot types.Slot
|
||||
epoch types.Epoch
|
||||
}{
|
||||
{slot: 0, epoch: 0/params.BeaconConfig().SlotsPerEpoch + 1},
|
||||
{slot: 50, epoch: 0/params.BeaconConfig().SlotsPerEpoch + 2},
|
||||
{slot: 64, epoch: 64/params.BeaconConfig().SlotsPerEpoch + 1},
|
||||
{slot: 128, epoch: 128/params.BeaconConfig().SlotsPerEpoch + 1},
|
||||
{slot: 200, epoch: 200/params.BeaconConfig().SlotsPerEpoch + 1},
|
||||
{slot: 0, epoch: types.Epoch(0/params.BeaconConfig().SlotsPerEpoch + 1)},
|
||||
{slot: 50, epoch: types.Epoch(0/params.BeaconConfig().SlotsPerEpoch + 2)},
|
||||
{slot: 64, epoch: types.Epoch(64/params.BeaconConfig().SlotsPerEpoch + 1)},
|
||||
{slot: 128, epoch: types.Epoch(128/params.BeaconConfig().SlotsPerEpoch + 1)},
|
||||
{slot: 200, epoch: types.Epoch(200/params.BeaconConfig().SlotsPerEpoch + 1)},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{Slot: tt.slot})
|
||||
@@ -84,8 +84,8 @@ func TestNextEpoch_OK(t *testing.T) {
|
||||
|
||||
func TestEpochStartSlot_OK(t *testing.T) {
|
||||
tests := []struct {
|
||||
epoch uint64
|
||||
startSlot uint64
|
||||
epoch types.Epoch
|
||||
startSlot types.Slot
|
||||
error bool
|
||||
}{
|
||||
{epoch: 0, startSlot: 0 * params.BeaconConfig().SlotsPerEpoch, error: false},
|
||||
@@ -108,8 +108,8 @@ func TestEpochStartSlot_OK(t *testing.T) {
|
||||
|
||||
func TestEpochEndSlot_OK(t *testing.T) {
|
||||
tests := []struct {
|
||||
epoch uint64
|
||||
startSlot uint64
|
||||
epoch types.Epoch
|
||||
startSlot types.Slot
|
||||
error bool
|
||||
}{
|
||||
{epoch: 0, startSlot: 1*params.BeaconConfig().SlotsPerEpoch - 1, error: false},
|
||||
@@ -134,7 +134,7 @@ func TestIsEpochStart(t *testing.T) {
|
||||
epochLength := params.BeaconConfig().SlotsPerEpoch
|
||||
|
||||
tests := []struct {
|
||||
slot uint64
|
||||
slot types.Slot
|
||||
result bool
|
||||
}{
|
||||
{
|
||||
@@ -164,7 +164,7 @@ func TestIsEpochEnd(t *testing.T) {
|
||||
epochLength := params.BeaconConfig().SlotsPerEpoch
|
||||
|
||||
tests := []struct {
|
||||
slot uint64
|
||||
slot types.Slot
|
||||
result bool
|
||||
}{
|
||||
{
|
||||
@@ -188,8 +188,8 @@ func TestIsEpochEnd(t *testing.T) {
|
||||
|
||||
func TestSlotsSinceEpochStarts(t *testing.T) {
|
||||
tests := []struct {
|
||||
slots uint64
|
||||
wantedSlots uint64
|
||||
slots types.Slot
|
||||
wantedSlots types.Slot
|
||||
}{
|
||||
{slots: 0, wantedSlots: 0},
|
||||
{slots: 1, wantedSlots: 1},
|
||||
@@ -204,8 +204,8 @@ func TestSlotsSinceEpochStarts(t *testing.T) {
|
||||
|
||||
func TestRoundUpToNearestEpoch_OK(t *testing.T) {
|
||||
tests := []struct {
|
||||
startSlot uint64
|
||||
roundedUpSlot uint64
|
||||
startSlot types.Slot
|
||||
roundedUpSlot types.Slot
|
||||
}{
|
||||
{startSlot: 0 * params.BeaconConfig().SlotsPerEpoch, roundedUpSlot: 0},
|
||||
{startSlot: 1*params.BeaconConfig().SlotsPerEpoch - 10, roundedUpSlot: 1 * params.BeaconConfig().SlotsPerEpoch},
|
||||
@@ -219,7 +219,7 @@ func TestRoundUpToNearestEpoch_OK(t *testing.T) {
|
||||
func TestSlotToTime(t *testing.T) {
|
||||
type args struct {
|
||||
genesisTimeSec uint64
|
||||
slot uint64
|
||||
slot types.Slot
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -276,7 +276,7 @@ func TestSlotToTime(t *testing.T) {
|
||||
func TestVerifySlotTime(t *testing.T) {
|
||||
type args struct {
|
||||
genesisTime int64
|
||||
slot uint64
|
||||
slot types.Slot
|
||||
timeTolerance time.Duration
|
||||
}
|
||||
tests := []struct {
|
||||
@@ -310,7 +310,7 @@ func TestVerifySlotTime(t *testing.T) {
|
||||
name: "max future slot",
|
||||
args: args{
|
||||
genesisTime: timeutils.Now().Add(-1 * 5 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second).Unix(),
|
||||
slot: MaxSlotBuffer + 6,
|
||||
slot: types.Slot(MaxSlotBuffer + 6),
|
||||
},
|
||||
wantedErr: "exceeds max allowed value relative to the local clock",
|
||||
},
|
||||
@@ -320,7 +320,7 @@ func TestVerifySlotTime(t *testing.T) {
|
||||
genesisTime: timeutils.Now().Add(-1 * 24 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second).Unix(), // 24 slots in the past
|
||||
// Gets multiplied with slot duration, and results in an overflow. Wraps around to a valid time.
|
||||
// Lower than max signed int. And chosen specifically to wrap to a valid slot 24
|
||||
slot: ((^uint64(0)) / params.BeaconConfig().SecondsPerSlot) + 24,
|
||||
slot: types.Slot((^uint64(0))/params.BeaconConfig().SecondsPerSlot) + 24,
|
||||
},
|
||||
wantedErr: "is in the far distant future",
|
||||
},
|
||||
@@ -340,16 +340,16 @@ func TestVerifySlotTime(t *testing.T) {
|
||||
func TestValidateSlotClock_HandlesBadSlot(t *testing.T) {
|
||||
genTime := timeutils.Now().Add(-1 * time.Duration(MaxSlotBuffer) * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second).Unix()
|
||||
|
||||
assert.NoError(t, ValidateSlotClock(MaxSlotBuffer, uint64(genTime)), "unexpected error validating slot")
|
||||
assert.NoError(t, ValidateSlotClock(2*MaxSlotBuffer, uint64(genTime)), "unexpected error validating slot")
|
||||
assert.ErrorContains(t, "which exceeds max allowed value relative to the local clock", ValidateSlotClock(2*MaxSlotBuffer+1, uint64(genTime)), "no error from bad slot")
|
||||
assert.NoError(t, ValidateSlotClock(types.Slot(MaxSlotBuffer), uint64(genTime)), "unexpected error validating slot")
|
||||
assert.NoError(t, ValidateSlotClock(types.Slot(2*MaxSlotBuffer), uint64(genTime)), "unexpected error validating slot")
|
||||
assert.ErrorContains(t, "which exceeds max allowed value relative to the local clock", ValidateSlotClock(types.Slot(2*MaxSlotBuffer+1), uint64(genTime)), "no error from bad slot")
|
||||
assert.ErrorContains(t, "which exceeds max allowed value relative to the local clock", ValidateSlotClock(1<<63, uint64(genTime)), "no error from bad slot")
|
||||
}
|
||||
|
||||
func TestWeakSubjectivityCheckptEpoch(t *testing.T) {
|
||||
tests := []struct {
|
||||
valCount uint64
|
||||
want uint64
|
||||
want types.Epoch
|
||||
}{
|
||||
// Verifying these numbers aligned with the reference table defined:
|
||||
// https://github.com/ethereum/eth2.0-specs/blob/weak-subjectivity-guide/specs/phase0/weak-subjectivity.md#calculating-the-weak-subjectivity-period
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
@@ -22,16 +23,16 @@ import (
|
||||
// Check if ``validator`` is active.
|
||||
// """
|
||||
// return validator.activation_epoch <= epoch < validator.exit_epoch
|
||||
func IsActiveValidator(validator *ethpb.Validator, epoch uint64) bool {
|
||||
func IsActiveValidator(validator *ethpb.Validator, epoch types.Epoch) bool {
|
||||
return checkValidatorActiveStatus(validator.ActivationEpoch, validator.ExitEpoch, epoch)
|
||||
}
|
||||
|
||||
// IsActiveValidatorUsingTrie checks if a read only validator is active.
|
||||
func IsActiveValidatorUsingTrie(validator stateTrie.ReadOnlyValidator, epoch uint64) bool {
|
||||
func IsActiveValidatorUsingTrie(validator stateTrie.ReadOnlyValidator, epoch types.Epoch) bool {
|
||||
return checkValidatorActiveStatus(validator.ActivationEpoch(), validator.ExitEpoch(), epoch)
|
||||
}
|
||||
|
||||
func checkValidatorActiveStatus(activationEpoch, exitEpoch, epoch uint64) bool {
|
||||
func checkValidatorActiveStatus(activationEpoch, exitEpoch, epoch types.Epoch) bool {
|
||||
return activationEpoch <= epoch && epoch < exitEpoch
|
||||
}
|
||||
|
||||
@@ -44,16 +45,16 @@ func checkValidatorActiveStatus(activationEpoch, exitEpoch, epoch uint64) bool {
|
||||
// Check if ``validator`` is slashable.
|
||||
// """
|
||||
// return (not validator.slashed) and (validator.activation_epoch <= epoch < validator.withdrawable_epoch)
|
||||
func IsSlashableValidator(activationEpoch, withdrawableEpoch uint64, slashed bool, epoch uint64) bool {
|
||||
func IsSlashableValidator(activationEpoch, withdrawableEpoch types.Epoch, slashed bool, epoch types.Epoch) bool {
|
||||
return checkValidatorSlashable(activationEpoch, withdrawableEpoch, slashed, epoch)
|
||||
}
|
||||
|
||||
// IsSlashableValidatorUsingTrie checks if a read only validator is slashable.
|
||||
func IsSlashableValidatorUsingTrie(val stateTrie.ReadOnlyValidator, epoch uint64) bool {
|
||||
func IsSlashableValidatorUsingTrie(val stateTrie.ReadOnlyValidator, epoch types.Epoch) bool {
|
||||
return checkValidatorSlashable(val.ActivationEpoch(), val.WithdrawableEpoch(), val.Slashed(), epoch)
|
||||
}
|
||||
|
||||
func checkValidatorSlashable(activationEpoch, withdrawableEpoch uint64, slashed bool, epoch uint64) bool {
|
||||
func checkValidatorSlashable(activationEpoch, withdrawableEpoch types.Epoch, slashed bool, epoch types.Epoch) bool {
|
||||
active := activationEpoch <= epoch
|
||||
beforeWithdrawable := epoch < withdrawableEpoch
|
||||
return beforeWithdrawable && active && !slashed
|
||||
@@ -72,7 +73,7 @@ func checkValidatorSlashable(activationEpoch, withdrawableEpoch uint64, slashed
|
||||
// Return the sequence of active validator indices at ``epoch``.
|
||||
// """
|
||||
// return [ValidatorIndex(i) for i, v in enumerate(state.validators) if is_active_validator(v, epoch)]
|
||||
func ActiveValidatorIndices(state *stateTrie.BeaconState, epoch uint64) ([]uint64, error) {
|
||||
func ActiveValidatorIndices(state *stateTrie.BeaconState, epoch types.Epoch) ([]uint64, error) {
|
||||
seed, err := Seed(state, epoch, params.BeaconConfig().DomainBeaconAttester)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get seed")
|
||||
@@ -103,7 +104,7 @@ func ActiveValidatorIndices(state *stateTrie.BeaconState, epoch uint64) ([]uint6
|
||||
|
||||
// ActiveValidatorCount returns the number of active validators in the state
|
||||
// at the given epoch.
|
||||
func ActiveValidatorCount(state *stateTrie.BeaconState, epoch uint64) (uint64, error) {
|
||||
func ActiveValidatorCount(state *stateTrie.BeaconState, epoch types.Epoch) (uint64, error) {
|
||||
seed, err := Seed(state, epoch, params.BeaconConfig().DomainBeaconAttester)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "could not get seed")
|
||||
@@ -142,7 +143,7 @@ func ActiveValidatorCount(state *stateTrie.BeaconState, epoch uint64) (uint64, e
|
||||
// Return the epoch during which validator activations and exits initiated in ``epoch`` take effect.
|
||||
// """
|
||||
// return Epoch(epoch + 1 + MAX_SEED_LOOKAHEAD)
|
||||
func ActivationExitEpoch(epoch uint64) uint64 {
|
||||
func ActivationExitEpoch(epoch types.Epoch) types.Epoch {
|
||||
return epoch + 1 + params.BeaconConfig().MaxSeedLookahead
|
||||
}
|
||||
|
||||
@@ -203,7 +204,7 @@ func BeaconProposerIndex(state *stateTrie.BeaconState) (uint64, error) {
|
||||
}
|
||||
return proposerIndices[state.Slot()%params.BeaconConfig().SlotsPerEpoch], nil
|
||||
}
|
||||
if err := UpdateProposerIndicesInCache(state, e); err != nil {
|
||||
if err := UpdateProposerIndicesInCache(state); err != nil {
|
||||
return 0, errors.Wrap(err, "could not update committee cache")
|
||||
}
|
||||
}
|
||||
@@ -214,7 +215,7 @@ func BeaconProposerIndex(state *stateTrie.BeaconState) (uint64, error) {
|
||||
return 0, errors.Wrap(err, "could not generate seed")
|
||||
}
|
||||
|
||||
seedWithSlot := append(seed[:], bytesutil.Bytes8(state.Slot())...)
|
||||
seedWithSlot := append(seed[:], bytesutil.Bytes8(uint64(state.Slot()))...)
|
||||
seedWithSlotHash := hashutil.Hash(seedWithSlot)
|
||||
|
||||
indices, err := ActiveValidatorIndices(state, e)
|
||||
@@ -283,7 +284,7 @@ func ComputeProposerIndex(bState *stateTrie.BeaconState, activeIndices []uint64,
|
||||
// epoch = get_current_epoch(state) if epoch is None else epoch
|
||||
// fork_version = state.fork.previous_version if epoch < state.fork.epoch else state.fork.current_version
|
||||
// return compute_domain(domain_type, fork_version, state.genesis_validators_root)
|
||||
func Domain(fork *pb.Fork, epoch uint64, domainType [bls.DomainByteLength]byte, genesisRoot []byte) ([]byte, error) {
|
||||
func Domain(fork *pb.Fork, epoch types.Epoch, domainType [bls.DomainByteLength]byte, genesisRoot []byte) ([]byte, error) {
|
||||
if fork == nil {
|
||||
return []byte{}, errors.New("nil fork or domain type")
|
||||
}
|
||||
@@ -324,7 +325,7 @@ func IsEligibleForActivationQueueUsingTrie(validator stateTrie.ReadOnlyValidator
|
||||
}
|
||||
|
||||
// isEligibleForActivationQueue carries out the logic for IsEligibleForActivationQueue*
|
||||
func isEligibileForActivationQueue(activationEligibilityEpoch, effectiveBalance uint64) bool {
|
||||
func isEligibileForActivationQueue(activationEligibilityEpoch types.Epoch, effectiveBalance uint64) bool {
|
||||
return activationEligibilityEpoch == params.BeaconConfig().FarFutureEpoch &&
|
||||
effectiveBalance == params.BeaconConfig().MaxEffectiveBalance
|
||||
}
|
||||
@@ -357,7 +358,7 @@ func IsEligibleForActivationUsingTrie(state *stateTrie.BeaconState, validator st
|
||||
}
|
||||
|
||||
// isEligibleForActivation carries out the logic for IsEligibleForActivation*
|
||||
func isEligibleForActivation(activationEligibilityEpoch, activationEpoch, finalizedEpoch uint64) bool {
|
||||
func isEligibleForActivation(activationEligibilityEpoch, activationEpoch, finalizedEpoch types.Epoch) bool {
|
||||
return activationEligibilityEpoch <= finalizedEpoch &&
|
||||
activationEpoch == params.BeaconConfig().FarFutureEpoch
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
@@ -17,7 +18,7 @@ import (
|
||||
|
||||
func TestIsActiveValidator_OK(t *testing.T) {
|
||||
tests := []struct {
|
||||
a uint64
|
||||
a types.Epoch
|
||||
b bool
|
||||
}{
|
||||
{a: 0, b: false},
|
||||
@@ -34,7 +35,7 @@ func TestIsActiveValidator_OK(t *testing.T) {
|
||||
|
||||
func TestIsActiveValidatorUsingTrie_OK(t *testing.T) {
|
||||
tests := []struct {
|
||||
a uint64
|
||||
a types.Epoch
|
||||
b bool
|
||||
}{
|
||||
{a: 0, b: false},
|
||||
@@ -57,7 +58,7 @@ func TestIsSlashableValidator_OK(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
validator *ethpb.Validator
|
||||
epoch uint64
|
||||
epoch types.Epoch
|
||||
slashable bool
|
||||
}{
|
||||
{
|
||||
@@ -139,7 +140,7 @@ func TestIsSlashableValidatorUsingTrie_OK(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
validator *ethpb.Validator
|
||||
epoch uint64
|
||||
epoch types.Epoch
|
||||
slashable bool
|
||||
}{
|
||||
{
|
||||
@@ -241,7 +242,7 @@ func TestBeaconProposerIndex_OK(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
tests := []struct {
|
||||
slot uint64
|
||||
slot types.Slot
|
||||
index uint64
|
||||
}{
|
||||
{
|
||||
@@ -288,7 +289,7 @@ func TestBeaconProposerIndex_BadState(t *testing.T) {
|
||||
}
|
||||
}
|
||||
roots := make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot)
|
||||
for i := uint64(0); i < params.BeaconConfig().SlotsPerHistoricalRoot; i++ {
|
||||
for i := uint64(0); i < uint64(params.BeaconConfig().SlotsPerHistoricalRoot); i++ {
|
||||
roots[i] = make([]byte, 32)
|
||||
}
|
||||
|
||||
@@ -328,7 +329,7 @@ func TestComputeProposerIndex_Compatibility(t *testing.T) {
|
||||
var proposerIndices []uint64
|
||||
seed, err := Seed(state, 0, params.BeaconConfig().DomainBeaconProposer)
|
||||
require.NoError(t, err)
|
||||
for i := uint64(0); i < params.BeaconConfig().SlotsPerEpoch; i++ {
|
||||
for i := uint64(0); i < uint64(params.BeaconConfig().SlotsPerEpoch); i++ {
|
||||
seedWithSlot := append(seed[:], bytesutil.Bytes8(i)...)
|
||||
seedWithSlotHash := hashutil.Hash(seedWithSlot)
|
||||
index, err := ComputeProposerIndex(state, indices, seedWithSlotHash)
|
||||
@@ -339,7 +340,7 @@ func TestComputeProposerIndex_Compatibility(t *testing.T) {
|
||||
var wantedProposerIndices []uint64
|
||||
seed, err = Seed(state, 0, params.BeaconConfig().DomainBeaconProposer)
|
||||
require.NoError(t, err)
|
||||
for i := uint64(0); i < params.BeaconConfig().SlotsPerEpoch; i++ {
|
||||
for i := uint64(0); i < uint64(params.BeaconConfig().SlotsPerEpoch); i++ {
|
||||
seedWithSlot := append(seed[:], bytesutil.Bytes8(i)...)
|
||||
seedWithSlotHash := hashutil.Hash(seedWithSlot)
|
||||
index, err := computeProposerIndexWithValidators(state.Validators(), indices, seedWithSlotHash)
|
||||
@@ -350,7 +351,7 @@ func TestComputeProposerIndex_Compatibility(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDelayedActivationExitEpoch_OK(t *testing.T) {
|
||||
epoch := uint64(9999)
|
||||
epoch := types.Epoch(9999)
|
||||
wanted := epoch + 1 + params.BeaconConfig().MaxSeedLookahead
|
||||
assert.Equal(t, wanted, ActivationExitEpoch(epoch))
|
||||
}
|
||||
@@ -422,7 +423,7 @@ func TestDomain_OK(t *testing.T) {
|
||||
},
|
||||
}
|
||||
tests := []struct {
|
||||
epoch uint64
|
||||
epoch types.Epoch
|
||||
domainType [4]byte
|
||||
result []byte
|
||||
}{
|
||||
@@ -445,7 +446,7 @@ func TestActiveValidatorIndices(t *testing.T) {
|
||||
farFutureEpoch := params.BeaconConfig().FarFutureEpoch
|
||||
type args struct {
|
||||
state *pb.BeaconState
|
||||
epoch uint64
|
||||
epoch types.Epoch
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
|
||||
@@ -9,6 +9,7 @@ go_library(
|
||||
"log.go",
|
||||
"skip_slot_cache.go",
|
||||
"state.go",
|
||||
"trailing_slot_state_cache.go",
|
||||
"transition.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/core/state",
|
||||
@@ -34,12 +35,16 @@ go_library(
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/bls:go_default_library",
|
||||
"//shared/bytesutil:go_default_library",
|
||||
"//shared/featureconfig:go_default_library",
|
||||
"//shared/hashutil:go_default_library",
|
||||
"//shared/mathutil:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"//shared/traceutil:go_default_library",
|
||||
"//shared/trieutil:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_prometheus_client_golang//prometheus:go_default_library",
|
||||
"@com_github_prometheus_client_golang//prometheus/promauto:go_default_library",
|
||||
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
|
||||
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@io_opencensus_go//trace:go_default_library",
|
||||
@@ -54,6 +59,7 @@ go_test(
|
||||
"skip_slot_cache_test.go",
|
||||
"state_fuzz_test.go",
|
||||
"state_test.go",
|
||||
"trailing_slot_state_cache_test.go",
|
||||
"transition_fuzz_test.go",
|
||||
"transition_test.go",
|
||||
],
|
||||
@@ -74,13 +80,13 @@ go_test(
|
||||
"//shared/bytesutil:go_default_library",
|
||||
"//shared/hashutil:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"//shared/sszutil:go_default_library",
|
||||
"//shared/testutil:go_default_library",
|
||||
"//shared/testutil/assert:go_default_library",
|
||||
"//shared/testutil/require:go_default_library",
|
||||
"//shared/trieutil:go_default_library",
|
||||
"@com_github_gogo_protobuf//proto:go_default_library",
|
||||
"@com_github_google_gofuzz//:go_default_library",
|
||||
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
|
||||
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
@@ -112,6 +118,5 @@ go_test(
|
||||
"//shared/params:go_default_library",
|
||||
"//shared/testutil/require:go_default_library",
|
||||
"@com_github_gogo_protobuf//proto:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -2,6 +2,7 @@ package state
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
@@ -19,9 +20,13 @@ var SkipSlotCache = cache.NewSkipSlotCache()
|
||||
// state root is in the mix to defend against different forks with same skip slots
|
||||
// to hit the same cache. We don't want beacon states mixed up between different chains.
|
||||
func cacheKey(ctx context.Context, state *beaconstate.BeaconState) ([32]byte, error) {
|
||||
r, err := state.HashTreeRoot(ctx)
|
||||
bh := state.LatestBlockHeader()
|
||||
if bh == nil {
|
||||
return [32]byte{}, errors.New("block head in state can't be nil")
|
||||
}
|
||||
r, err := bh.HashTreeRoot()
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
return hashutil.Hash(append(bytesutil.Bytes32(state.Slot()), r[:]...)), nil
|
||||
return hashutil.Hash(append(bytesutil.Bytes32(uint64(state.Slot())), r[:]...)), nil
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package state_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"sync"
|
||||
"testing"
|
||||
@@ -9,8 +8,8 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
|
||||
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/sszutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
)
|
||||
|
||||
@@ -34,9 +33,7 @@ func TestSkipSlotCache_OK(t *testing.T) {
|
||||
bState, err = state.ExecuteStateTransition(context.Background(), bState, blk)
|
||||
require.NoError(t, err, "Could not process state transition")
|
||||
|
||||
if !sszutil.DeepEqual(originalState.CloneInnerState(), bState.CloneInnerState()) {
|
||||
t.Fatal("Skipped slots cache leads to different states")
|
||||
}
|
||||
assert.DeepEqual(t, originalState.CloneInnerState(), bState.CloneInnerState(), "Skipped slots cache leads to different states")
|
||||
}
|
||||
|
||||
func TestSkipSlotCache_ConcurrentMixup(t *testing.T) {
|
||||
@@ -113,9 +110,8 @@ func TestSkipSlotCache_ConcurrentMixup(t *testing.T) {
|
||||
|
||||
tmp1, err := state.ProcessSlots(context.Background(), expected1.Copy(), problemSlot+1)
|
||||
require.NoError(t, err)
|
||||
if gotRoot := tmp1.StateRoots()[problemSlot]; !bytes.Equal(gotRoot, expectedRoot1[:]) {
|
||||
t.Fatalf("state roots for chain 1 are bad, expected root doesn't match: %x <> %x", gotRoot, expectedRoot1[:])
|
||||
}
|
||||
gotRoot := tmp1.StateRoots()[problemSlot]
|
||||
require.DeepEqual(t, expectedRoot1[:], gotRoot, "State roots for chain 1 are bad, expected root doesn't match")
|
||||
|
||||
expected2, err := state.ProcessSlots(context.Background(), state2.Copy(), problemSlot)
|
||||
require.NoError(t, err)
|
||||
@@ -125,27 +121,22 @@ func TestSkipSlotCache_ConcurrentMixup(t *testing.T) {
|
||||
|
||||
tmp2, err := state.ProcessSlots(context.Background(), expected2.Copy(), problemSlot+1)
|
||||
require.NoError(t, err)
|
||||
if gotRoot := tmp2.StateRoots()[problemSlot]; !bytes.Equal(gotRoot, expectedRoot2[:]) {
|
||||
t.Fatalf("state roots for chain 2 are bad, expected root doesn't match %x <> %x", gotRoot, expectedRoot2[:])
|
||||
}
|
||||
gotRoot = tmp2.StateRoots()[problemSlot]
|
||||
require.DeepEqual(t, expectedRoot2[:], gotRoot, "State roots for chain 2 are bad, expected root doesn't match")
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(len(setups))
|
||||
|
||||
step := func(i int, setup *beaconstate.BeaconState) {
|
||||
// go at least 1 past problemSlot, to ensure problem slot state root is available
|
||||
outState, err := state.ProcessSlots(context.Background(), setup, problemSlot+1+uint64(i)) // keep increasing, to hit and extend the cache
|
||||
outState, err := state.ProcessSlots(context.Background(), setup, problemSlot.Add(1+uint64(i))) // keep increasing, to hit and extend the cache
|
||||
require.NoError(t, err, "Could not process state transition")
|
||||
roots := outState.StateRoots()
|
||||
gotRoot := roots[problemSlot]
|
||||
if i%2 == 0 {
|
||||
if !bytes.Equal(gotRoot, expectedRoot1[:]) {
|
||||
t.Errorf("unexpected root on chain 1, item %3d: %x", i, gotRoot)
|
||||
}
|
||||
assert.DeepEqual(t, expectedRoot1[:], gotRoot, "Unexpected root on chain 1")
|
||||
} else {
|
||||
if !bytes.Equal(gotRoot, expectedRoot2[:]) {
|
||||
t.Errorf("unexpected root on chain 2, item %3d: %x", i, gotRoot)
|
||||
}
|
||||
assert.DeepEqual(t, expectedRoot2[:], gotRoot, "Unexpected root on chain 2")
|
||||
}
|
||||
wg.Done()
|
||||
}
|
||||
|
||||
@@ -34,7 +34,6 @@ go_test(
|
||||
"//shared/testutil/require:go_default_library",
|
||||
"@com_github_gogo_protobuf//proto:go_default_library",
|
||||
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
|
||||
"@com_github_urfave_cli_v2//:go_default_library",
|
||||
"@in_gopkg_d4l3k_messagediff_v1//:go_default_library",
|
||||
"@io_bazel_rules_go//go/tools/bazel:go_default_library",
|
||||
@@ -69,7 +68,6 @@ go_test(
|
||||
"//shared/testutil/require:go_default_library",
|
||||
"@com_github_gogo_protobuf//proto:go_default_library",
|
||||
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
|
||||
"@com_github_urfave_cli_v2//:go_default_library",
|
||||
"@in_gopkg_d4l3k_messagediff_v1//:go_default_library",
|
||||
"@io_bazel_rules_go//go/tools/bazel:go_default_library",
|
||||
|
||||
@@ -43,7 +43,7 @@ func runSlotProcessingTests(t *testing.T, config string) {
|
||||
require.NoError(t, err)
|
||||
postBeaconState := &pb.BeaconState{}
|
||||
require.NoError(t, postBeaconState.UnmarshalSSZ(postBeaconStateFile), "Failed to unmarshal")
|
||||
postState, err := state.ProcessSlots(context.Background(), beaconState, beaconState.Slot()+uint64(slotsCount))
|
||||
postState, err := state.ProcessSlots(context.Background(), beaconState, beaconState.Slot().Add(uint64(slotsCount)))
|
||||
require.NoError(t, err)
|
||||
|
||||
if !proto.Equal(postState.CloneInnerState(), postBeaconState) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
@@ -15,19 +16,19 @@ import (
|
||||
)
|
||||
|
||||
func TestGenesisBeaconState_OK(t *testing.T) {
|
||||
genesisEpochNumber := uint64(0)
|
||||
genesisEpoch := types.Epoch(0)
|
||||
|
||||
assert.DeepEqual(t, []byte{0, 0, 0, 0}, params.BeaconConfig().GenesisForkVersion, "GenesisSlot( should be {0,0,0,0} for these tests to pass")
|
||||
genesisForkVersion := params.BeaconConfig().GenesisForkVersion
|
||||
|
||||
assert.Equal(t, [32]byte{}, params.BeaconConfig().ZeroHash, "ZeroHash should be all 0s for these tests to pass")
|
||||
assert.Equal(t, uint64(65536), params.BeaconConfig().EpochsPerHistoricalVector, "EpochsPerHistoricalVector should be 8192 for these tests to pass")
|
||||
assert.Equal(t, types.Epoch(65536), params.BeaconConfig().EpochsPerHistoricalVector, "EpochsPerHistoricalVector should be 8192 for these tests to pass")
|
||||
|
||||
latestRandaoMixesLength := params.BeaconConfig().EpochsPerHistoricalVector
|
||||
assert.Equal(t, uint64(16777216), params.BeaconConfig().HistoricalRootsLimit, "HistoricalRootsLimit should be 16777216 for these tests to pass")
|
||||
|
||||
depositsForChainStart := 100
|
||||
assert.Equal(t, uint64(8192), params.BeaconConfig().EpochsPerSlashingsVector, "EpochsPerSlashingsVector should be 8192 for these tests to pass")
|
||||
assert.Equal(t, types.Epoch(8192), params.BeaconConfig().EpochsPerSlashingsVector, "EpochsPerSlashingsVector should be 8192 for these tests to pass")
|
||||
|
||||
genesisTime := uint64(99999)
|
||||
deposits, _, err := testutil.DeterministicDepositsAndKeys(uint64(depositsForChainStart))
|
||||
@@ -38,11 +39,11 @@ func TestGenesisBeaconState_OK(t *testing.T) {
|
||||
require.NoError(t, err, "Could not execute GenesisBeaconState")
|
||||
|
||||
// Misc fields checks.
|
||||
assert.Equal(t, uint64(0), newState.Slot(), "Slot was not correctly initialized")
|
||||
assert.Equal(t, types.Slot(0), newState.Slot(), "Slot was not correctly initialized")
|
||||
if !proto.Equal(newState.Fork(), &pb.Fork{
|
||||
PreviousVersion: genesisForkVersion,
|
||||
CurrentVersion: genesisForkVersion,
|
||||
Epoch: genesisEpochNumber,
|
||||
Epoch: genesisEpoch,
|
||||
}) {
|
||||
t.Error("Fork was not correctly initialized")
|
||||
}
|
||||
@@ -51,28 +52,28 @@ func TestGenesisBeaconState_OK(t *testing.T) {
|
||||
assert.Equal(t, depositsForChainStart, len(newState.Validators()), "Validators was not correctly initialized")
|
||||
v, err := newState.ValidatorAtIndex(0)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, uint64(0), v.ActivationEpoch, "Validators was not correctly initialized")
|
||||
assert.Equal(t, types.Epoch(0), v.ActivationEpoch, "Validators was not correctly initialized")
|
||||
v, err = newState.ValidatorAtIndex(0)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, uint64(0), v.ActivationEligibilityEpoch, "Validators was not correctly initialized")
|
||||
assert.Equal(t, types.Epoch(0), v.ActivationEligibilityEpoch, "Validators was not correctly initialized")
|
||||
assert.Equal(t, depositsForChainStart, len(newState.Balances()), "Balances was not correctly initialized")
|
||||
|
||||
// Randomness and committees fields checks.
|
||||
assert.Equal(t, latestRandaoMixesLength, uint64(len(newState.RandaoMixes())), "Length of RandaoMixes was not correctly initialized")
|
||||
assert.Equal(t, latestRandaoMixesLength, types.Epoch(len(newState.RandaoMixes())), "Length of RandaoMixes was not correctly initialized")
|
||||
mix, err := newState.RandaoMixAtIndex(0)
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, eth1Data.BlockHash, mix, "RandaoMixes was not correctly initialized")
|
||||
|
||||
// Finality fields checks.
|
||||
assert.Equal(t, genesisEpochNumber, newState.PreviousJustifiedCheckpoint().Epoch, "PreviousJustifiedCheckpoint.Epoch was not correctly initialized")
|
||||
assert.Equal(t, genesisEpochNumber, newState.CurrentJustifiedCheckpoint().Epoch, "JustifiedEpoch was not correctly initialized")
|
||||
assert.Equal(t, genesisEpochNumber, newState.FinalizedCheckpointEpoch(), "FinalizedSlot was not correctly initialized")
|
||||
assert.Equal(t, genesisEpoch, newState.PreviousJustifiedCheckpoint().Epoch, "PreviousJustifiedCheckpoint.Epoch was not correctly initialized")
|
||||
assert.Equal(t, genesisEpoch, newState.CurrentJustifiedCheckpoint().Epoch, "JustifiedEpoch was not correctly initialized")
|
||||
assert.Equal(t, genesisEpoch, newState.FinalizedCheckpointEpoch(), "FinalizedSlot was not correctly initialized")
|
||||
assert.Equal(t, uint8(0x00), newState.JustificationBits()[0], "JustificationBits was not correctly initialized")
|
||||
|
||||
// Recent state checks.
|
||||
assert.DeepEqual(t, make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector), newState.Slashings(), "Slashings was not correctly initialized")
|
||||
assert.DeepEqual(t, []*pb.PendingAttestation{}, newState.CurrentEpochAttestations(), "CurrentEpochAttestations was not correctly initialized")
|
||||
assert.DeepEqual(t, []*pb.PendingAttestation{}, newState.PreviousEpochAttestations(), "PreviousEpochAttestations was not correctly initialized")
|
||||
assert.DeepSSZEqual(t, []*pb.PendingAttestation{}, newState.CurrentEpochAttestations(), "CurrentEpochAttestations was not correctly initialized")
|
||||
assert.DeepSSZEqual(t, []*pb.PendingAttestation{}, newState.PreviousEpochAttestations(), "PreviousEpochAttestations was not correctly initialized")
|
||||
|
||||
zeroHash := params.BeaconConfig().ZeroHash[:]
|
||||
// History root checks.
|
||||
@@ -81,7 +82,7 @@ func TestGenesisBeaconState_OK(t *testing.T) {
|
||||
|
||||
// Deposit root checks.
|
||||
assert.DeepEqual(t, eth1Data.DepositRoot, newState.Eth1Data().DepositRoot, "Eth1Data DepositRoot was not correctly initialized")
|
||||
assert.DeepEqual(t, []*ethpb.Eth1Data{}, newState.Eth1DataVotes(), "Eth1DataVotes was not correctly initialized")
|
||||
assert.DeepSSZEqual(t, []*ethpb.Eth1Data{}, newState.Eth1DataVotes(), "Eth1DataVotes was not correctly initialized")
|
||||
}
|
||||
|
||||
func TestGenesisState_HashEquality(t *testing.T) {
|
||||
@@ -104,7 +105,7 @@ func TestGenesisState_HashEquality(t *testing.T) {
|
||||
func TestGenesisState_InitializesLatestBlockHashes(t *testing.T) {
|
||||
s, err := state.GenesisBeaconState(nil, 0, ðpb.Eth1Data{})
|
||||
require.NoError(t, err)
|
||||
got, want := uint64(len(s.BlockRoots())), params.BeaconConfig().SlotsPerHistoricalRoot
|
||||
got, want := uint64(len(s.BlockRoots())), uint64(params.BeaconConfig().SlotsPerHistoricalRoot)
|
||||
assert.Equal(t, want, got, "Wrong number of recent block hashes")
|
||||
|
||||
got = uint64(cap(s.BlockRoots()))
|
||||
|
||||
64
beacon-chain/core/state/trailing_slot_state_cache.go
Normal file
64
beacon-chain/core/state/trailing_slot_state_cache.go
Normal file
@@ -0,0 +1,64 @@
|
||||
package state
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
)
|
||||
|
||||
type nextSlotCache struct {
|
||||
sync.RWMutex
|
||||
root []byte
|
||||
state *state.BeaconState
|
||||
}
|
||||
|
||||
var (
|
||||
nsc nextSlotCache
|
||||
// Metrics for the validator cache.
|
||||
nextSlotCacheHit = promauto.NewCounter(prometheus.CounterOpts{
|
||||
Name: "next_slot_cache_hit",
|
||||
Help: "The total number of cache hits on the next slot state cache.",
|
||||
})
|
||||
nextSlotCacheMiss = promauto.NewCounter(prometheus.CounterOpts{
|
||||
Name: "next_slot_cache_miss",
|
||||
Help: "The total number of cache misses on the next slot state cache.",
|
||||
})
|
||||
)
|
||||
|
||||
// NextSlotState returns the saved state if the input root matches the root in `nextSlotCache`. Returns nil otherwise.
|
||||
// This is useful to check before processing slots. With a cache hit, it will return last processed state with slot plus
|
||||
// one advancement.
|
||||
func NextSlotState(ctx context.Context, root []byte) (*state.BeaconState, error) {
|
||||
nsc.RLock()
|
||||
defer nsc.RUnlock()
|
||||
if !bytes.Equal(root, nsc.root) {
|
||||
nextSlotCacheMiss.Inc()
|
||||
return nil, nil
|
||||
}
|
||||
nextSlotCacheHit.Inc()
|
||||
// Returning copied state.
|
||||
return nsc.state.Copy(), nil
|
||||
}
|
||||
|
||||
// UpdateNextSlotCache updates the `nextSlotCache`. It saves the input state after advancing the state slot by 1
|
||||
// by calling `ProcessSlots`, it also saves the input root for later look up.
|
||||
// This is useful to call after successfully processing a block.
|
||||
func UpdateNextSlotCache(ctx context.Context, root []byte, state *state.BeaconState) error {
|
||||
// Advancing one slot by using a copied state.
|
||||
copied := state.Copy()
|
||||
copied, err := ProcessSlots(ctx, copied, copied.Slot()+1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nsc.Lock()
|
||||
defer nsc.Unlock()
|
||||
|
||||
nsc.root = root
|
||||
nsc.state = copied
|
||||
return nil
|
||||
}
|
||||
31
beacon-chain/core/state/trailing_slot_state_cache_test.go
Normal file
31
beacon-chain/core/state/trailing_slot_state_cache_test.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package state_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
|
||||
st "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
)
|
||||
|
||||
func TestTrailingSlotState_RoundTrip(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
r := []byte{'a'}
|
||||
s, err := state.NextSlotState(ctx, r)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, (*st.BeaconState)(nil), s)
|
||||
|
||||
s, _ = testutil.DeterministicGenesisState(t, 1)
|
||||
require.NoError(t, state.UpdateNextSlotCache(ctx, r, s))
|
||||
s, err = state.NextSlotState(ctx, r)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, types.Slot(1), s.Slot())
|
||||
|
||||
require.NoError(t, state.UpdateNextSlotCache(ctx, r, s))
|
||||
s, err = state.NextSlotState(ctx, r)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, types.Slot(2), s.Slot())
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||
b "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
@@ -18,6 +19,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/state/interop"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/shared/bls"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/mathutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/traceutil"
|
||||
@@ -70,7 +72,7 @@ func ExecuteStateTransition(
|
||||
return nil, errors.New("nil block")
|
||||
}
|
||||
|
||||
ctx, span := trace.StartSpan(ctx, "beacon-chain.ChainService.ExecuteStateTransition")
|
||||
ctx, span := trace.StartSpan(ctx, "core.state.ExecuteStateTransition")
|
||||
defer span.End()
|
||||
var err error
|
||||
// Execute per slots transition.
|
||||
@@ -126,14 +128,20 @@ func ExecuteStateTransitionNoVerifyAnySig(
|
||||
return nil, nil, errors.New("nil block")
|
||||
}
|
||||
|
||||
ctx, span := trace.StartSpan(ctx, "beacon-chain.ChainService.ExecuteStateTransitionNoVerifyAttSigs")
|
||||
ctx, span := trace.StartSpan(ctx, "core.state.ExecuteStateTransitionNoVerifyAttSigs")
|
||||
defer span.End()
|
||||
var err error
|
||||
|
||||
// Execute per slots transition.
|
||||
state, err = ProcessSlots(ctx, state, signed.Block.Slot)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "could not process slot")
|
||||
if featureconfig.Get().EnableNextSlotStateCache {
|
||||
state, err = ProcessSlotsUsingNextSlotCache(ctx, state, signed.Block.ParentRoot, signed.Block.Slot)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "could not process slots")
|
||||
}
|
||||
} else {
|
||||
state, err = ProcessSlots(ctx, state, signed.Block.Slot)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "could not process slot")
|
||||
}
|
||||
}
|
||||
|
||||
// Execute per block transition.
|
||||
@@ -166,7 +174,7 @@ func CalculateStateRoot(
|
||||
state *stateTrie.BeaconState,
|
||||
signed *ethpb.SignedBeaconBlock,
|
||||
) ([32]byte, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "beacon-chain.ChainService.CalculateStateRoot")
|
||||
ctx, span := trace.StartSpan(ctx, "core.state.CalculateStateRoot")
|
||||
defer span.End()
|
||||
if ctx.Err() != nil {
|
||||
traceutil.AnnotateError(span, ctx.Err())
|
||||
@@ -183,9 +191,17 @@ func CalculateStateRoot(
|
||||
state = state.Copy()
|
||||
|
||||
// Execute per slots transition.
|
||||
state, err := ProcessSlots(ctx, state, signed.Block.Slot)
|
||||
if err != nil {
|
||||
return [32]byte{}, errors.Wrap(err, "could not process slot")
|
||||
var err error
|
||||
if featureconfig.Get().EnableNextSlotStateCache {
|
||||
state, err = ProcessSlotsUsingNextSlotCache(ctx, state, signed.Block.ParentRoot, signed.Block.Slot)
|
||||
if err != nil {
|
||||
return [32]byte{}, errors.Wrap(err, "could not process slots")
|
||||
}
|
||||
} else {
|
||||
state, err = ProcessSlots(ctx, state, signed.Block.Slot)
|
||||
if err != nil {
|
||||
return [32]byte{}, errors.Wrap(err, "could not process slot")
|
||||
}
|
||||
}
|
||||
|
||||
// Execute per block transition.
|
||||
@@ -214,7 +230,7 @@ func CalculateStateRoot(
|
||||
// previous_block_root = hash_tree_root(state.latest_block_header)
|
||||
// state.block_roots[state.slot % SLOTS_PER_HISTORICAL_ROOT] = previous_block_root
|
||||
func ProcessSlot(ctx context.Context, state *stateTrie.BeaconState) (*stateTrie.BeaconState, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "beacon-chain.ChainService.state.ProcessSlot")
|
||||
ctx, span := trace.StartSpan(ctx, "core.state.ProcessSlot")
|
||||
defer span.End()
|
||||
span.AddAttributes(trace.Int64Attribute("slot", int64(state.Slot())))
|
||||
|
||||
@@ -223,7 +239,7 @@ func ProcessSlot(ctx context.Context, state *stateTrie.BeaconState) (*stateTrie.
|
||||
return nil, err
|
||||
}
|
||||
if err := state.UpdateStateRootAtIndex(
|
||||
state.Slot()%params.BeaconConfig().SlotsPerHistoricalRoot,
|
||||
uint64(state.Slot()%params.BeaconConfig().SlotsPerHistoricalRoot),
|
||||
prevStateRoot,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
@@ -245,7 +261,7 @@ func ProcessSlot(ctx context.Context, state *stateTrie.BeaconState) (*stateTrie.
|
||||
}
|
||||
// Cache the block root.
|
||||
if err := state.UpdateBlockRootAtIndex(
|
||||
state.Slot()%params.BeaconConfig().SlotsPerHistoricalRoot,
|
||||
uint64(state.Slot()%params.BeaconConfig().SlotsPerHistoricalRoot),
|
||||
prevBlockRoot,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
@@ -253,6 +269,37 @@ func ProcessSlot(ctx context.Context, state *stateTrie.BeaconState) (*stateTrie.
|
||||
return state, nil
|
||||
}
|
||||
|
||||
// ProcessSlotsUsingNextSlotCache processes slots by using next slot cache for higher efficiency.
|
||||
func ProcessSlotsUsingNextSlotCache(
|
||||
ctx context.Context,
|
||||
parentState *stateTrie.BeaconState,
|
||||
parentRoot []byte,
|
||||
slot types.Slot) (*stateTrie.BeaconState, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "core.state.ProcessSlotsUsingNextSlotCache")
|
||||
defer span.End()
|
||||
|
||||
// Check whether the parent state has been advanced by 1 slot in next slot cache.
|
||||
nextSlotState, err := NextSlotState(ctx, parentRoot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// If the next slot state is not nil (i.e. cache hit).
|
||||
// We replace next slot state with parent state.
|
||||
if nextSlotState != nil {
|
||||
parentState = nextSlotState
|
||||
}
|
||||
|
||||
// Since next slot cache only advances state by 1 slot,
|
||||
// we check if there's more slots that need to process.
|
||||
if slot > parentState.Slot() {
|
||||
parentState, err = ProcessSlots(ctx, parentState, slot)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not process slots")
|
||||
}
|
||||
}
|
||||
return parentState, nil
|
||||
}
|
||||
|
||||
// ProcessSlots process through skip slots and apply epoch transition when it's needed
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
@@ -265,8 +312,8 @@ func ProcessSlot(ctx context.Context, state *stateTrie.BeaconState) (*stateTrie.
|
||||
// process_epoch(state)
|
||||
// state.slot += 1
|
||||
// ]
|
||||
func ProcessSlots(ctx context.Context, state *stateTrie.BeaconState, slot uint64) (*stateTrie.BeaconState, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "beacon-chain.ChainService.ProcessSlots")
|
||||
func ProcessSlots(ctx context.Context, state *stateTrie.BeaconState, slot types.Slot) (*stateTrie.BeaconState, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "core.state.ProcessSlots")
|
||||
defer span.End()
|
||||
if state == nil {
|
||||
return nil, errors.New("nil state")
|
||||
@@ -370,7 +417,7 @@ func ProcessBlock(
|
||||
state *stateTrie.BeaconState,
|
||||
signed *ethpb.SignedBeaconBlock,
|
||||
) (*stateTrie.BeaconState, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "beacon-chain.ChainService.state.ProcessBlock")
|
||||
ctx, span := trace.StartSpan(ctx, "core.state.ProcessBlock")
|
||||
defer span.End()
|
||||
|
||||
var err error
|
||||
@@ -401,7 +448,7 @@ func ProcessBlockNoVerifyAnySig(
|
||||
state *stateTrie.BeaconState,
|
||||
signed *ethpb.SignedBeaconBlock,
|
||||
) (*bls.SignatureSet, *stateTrie.BeaconState, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "beacon-chain.ChainService.state.ProcessBlockNoVerifyAnySig")
|
||||
ctx, span := trace.StartSpan(ctx, "core.state.ProcessBlockNoVerifyAnySig")
|
||||
defer span.End()
|
||||
|
||||
state, err := b.ProcessBlockHeaderNoVerify(state, signed.Block)
|
||||
@@ -477,7 +524,7 @@ func ProcessOperationsNoVerifyAttsSigs(
|
||||
ctx context.Context,
|
||||
state *stateTrie.BeaconState,
|
||||
signedBeaconBlock *ethpb.SignedBeaconBlock) (*stateTrie.BeaconState, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "beacon-chain.ChainService.state.ProcessOperationsNoVerifyAttsSigs")
|
||||
ctx, span := trace.StartSpan(ctx, "core.state.ProcessOperationsNoVerifyAttsSigs")
|
||||
defer span.End()
|
||||
|
||||
if _, err := VerifyOperationLengths(ctx, state, signedBeaconBlock); err != nil {
|
||||
@@ -510,8 +557,8 @@ func ProcessOperationsNoVerifyAttsSigs(
|
||||
|
||||
// VerifyOperationLengths verifies that block operation lengths are valid.
|
||||
func VerifyOperationLengths(_ context.Context, state *stateTrie.BeaconState, b *ethpb.SignedBeaconBlock) (*stateTrie.BeaconState, error) {
|
||||
if b.Block == nil || b.Block.Body == nil {
|
||||
return nil, errors.New("block and block body can't be nil")
|
||||
if err := helpers.VerifyNilBeaconBlock(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
body := b.Block.Body
|
||||
|
||||
@@ -575,7 +622,7 @@ func CanProcessEpoch(state *stateTrie.BeaconState) bool {
|
||||
// ProcessEpochPrecompute describes the per epoch operations that are performed on the beacon state.
|
||||
// It's optimized by pre computing validator attested info and epoch total/attested balances upfront.
|
||||
func ProcessEpochPrecompute(ctx context.Context, state *stateTrie.BeaconState) (*stateTrie.BeaconState, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "beacon-chain.ChainService.state.ProcessEpochPrecompute")
|
||||
ctx, span := trace.StartSpan(ctx, "core.state.ProcessEpochPrecompute")
|
||||
defer span.End()
|
||||
span.AddAttributes(trace.Int64Attribute("epoch", int64(helpers.CurrentEpoch(state))))
|
||||
|
||||
@@ -625,7 +672,7 @@ func ProcessBlockForStateRoot(
|
||||
state *stateTrie.BeaconState,
|
||||
signed *ethpb.SignedBeaconBlock,
|
||||
) (*stateTrie.BeaconState, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "beacon-chain.ChainService.state.ProcessBlockForStateRoot")
|
||||
ctx, span := trace.StartSpan(ctx, "core.state.ProcessBlockForStateRoot")
|
||||
defer span.End()
|
||||
|
||||
state, err := b.ProcessBlockHeaderNoVerify(state, signed.Block)
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"testing"
|
||||
|
||||
fuzz "github.com/google/gofuzz"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
)
|
||||
@@ -66,7 +67,7 @@ func TestFuzzProcessSlots_1000(t *testing.T) {
|
||||
defer SkipSlotCache.Enable()
|
||||
ctx := context.Background()
|
||||
state := &stateTrie.BeaconState{}
|
||||
slot := uint64(0)
|
||||
slot := types.Slot(0)
|
||||
fuzzer := fuzz.NewWithSeed(0)
|
||||
fuzzer.NilChance(0.1)
|
||||
for i := 0; i < 1000; i++ {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package state_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
@@ -101,9 +101,7 @@ func TestExecuteStateTransition_FullProcess(t *testing.T) {
|
||||
|
||||
mix, err := beaconState.RandaoMixAtIndex(1)
|
||||
require.NoError(t, err)
|
||||
if bytes.Equal(mix, oldMix) {
|
||||
t.Errorf("Did not expect new and old randao mix to equal, %#x == %#x", mix, oldMix)
|
||||
}
|
||||
assert.DeepNotEqual(t, oldMix, mix, "Did not expect new and old randao mix to equal")
|
||||
}
|
||||
|
||||
func TestExecuteStateTransitionNoVerify_FullProcess(t *testing.T) {
|
||||
@@ -254,7 +252,7 @@ func TestProcessBlock_IncorrectProcessExits(t *testing.T) {
|
||||
},
|
||||
}
|
||||
var blockRoots [][]byte
|
||||
for i := uint64(0); i < params.BeaconConfig().SlotsPerHistoricalRoot; i++ {
|
||||
for i := uint64(0); i < uint64(params.BeaconConfig().SlotsPerHistoricalRoot); i++ {
|
||||
blockRoots = append(blockRoots, []byte{byte(i)})
|
||||
}
|
||||
require.NoError(t, beaconState.SetBlockRoots(blockRoots))
|
||||
@@ -324,7 +322,7 @@ func createFullBlockWithOperations(t *testing.T) (*beaconstate.BeaconState,
|
||||
|
||||
proposerSlashIdx := uint64(3)
|
||||
slotsPerEpoch := params.BeaconConfig().SlotsPerEpoch
|
||||
err = beaconState.SetSlot((params.BeaconConfig().ShardCommitteePeriod * slotsPerEpoch) + params.BeaconConfig().MinAttestationInclusionDelay)
|
||||
err = beaconState.SetSlot(slotsPerEpoch.Mul(uint64(params.BeaconConfig().ShardCommitteePeriod)) + params.BeaconConfig().MinAttestationInclusionDelay)
|
||||
require.NoError(t, err)
|
||||
|
||||
currentEpoch := helpers.CurrentEpoch(beaconState)
|
||||
@@ -398,7 +396,7 @@ func createFullBlockWithOperations(t *testing.T) (*beaconstate.BeaconState,
|
||||
}
|
||||
|
||||
var blockRoots [][]byte
|
||||
for i := uint64(0); i < params.BeaconConfig().SlotsPerHistoricalRoot; i++ {
|
||||
for i := uint64(0); i < uint64(params.BeaconConfig().SlotsPerHistoricalRoot); i++ {
|
||||
blockRoots = append(blockRoots, []byte{byte(i)})
|
||||
}
|
||||
require.NoError(t, beaconState.SetBlockRoots(blockRoots))
|
||||
@@ -415,7 +413,8 @@ func createFullBlockWithOperations(t *testing.T) (*beaconstate.BeaconState,
|
||||
|
||||
committee, err := helpers.BeaconCommitteeFromState(beaconState, blockAtt.Data.Slot, blockAtt.Data.CommitteeIndex)
|
||||
assert.NoError(t, err)
|
||||
attestingIndices := attestationutil.AttestingIndices(blockAtt.AggregationBits, committee)
|
||||
attestingIndices, err := attestationutil.AttestingIndices(blockAtt.AggregationBits, committee)
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, err)
|
||||
hashTreeRoot, err = helpers.ComputeSigningRoot(blockAtt.Data, domain)
|
||||
assert.NoError(t, err)
|
||||
@@ -503,12 +502,12 @@ func TestProcessBlockNoVerify_PassesProcessingConditions(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestProcessEpochPrecompute_CanProcess(t *testing.T) {
|
||||
epoch := uint64(1)
|
||||
epoch := types.Epoch(1)
|
||||
|
||||
atts := []*pb.PendingAttestation{{Data: ðpb.AttestationData{Target: ðpb.Checkpoint{Root: make([]byte, 32)}}, InclusionDelay: 1}}
|
||||
slashing := make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector)
|
||||
base := &pb.BeaconState{
|
||||
Slot: epoch*params.BeaconConfig().SlotsPerEpoch + 1,
|
||||
Slot: params.BeaconConfig().SlotsPerEpoch.Mul(uint64(epoch)) + 1,
|
||||
BlockRoots: make([][]byte, 128),
|
||||
Slashings: slashing,
|
||||
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
|
||||
@@ -697,7 +696,7 @@ func TestProcessBlk_AttsBasedOnValidatorCount(t *testing.T) {
|
||||
s, privKeys := testutil.DeterministicGenesisState(t, validatorCount)
|
||||
require.NoError(t, s.SetSlot(params.BeaconConfig().SlotsPerEpoch))
|
||||
|
||||
bitCount := validatorCount / params.BeaconConfig().SlotsPerEpoch
|
||||
bitCount := validatorCount / uint64(params.BeaconConfig().SlotsPerEpoch)
|
||||
aggBits := bitfield.NewBitlist(bitCount)
|
||||
for i := uint64(1); i < bitCount; i++ {
|
||||
aggBits.SetBitAt(i, true)
|
||||
@@ -712,7 +711,8 @@ func TestProcessBlk_AttsBasedOnValidatorCount(t *testing.T) {
|
||||
|
||||
committee, err := helpers.BeaconCommitteeFromState(s, att.Data.Slot, att.Data.CommitteeIndex)
|
||||
assert.NoError(t, err)
|
||||
attestingIndices := attestationutil.AttestingIndices(att.AggregationBits, committee)
|
||||
attestingIndices, err := attestationutil.AttestingIndices(att.AggregationBits, committee)
|
||||
require.NoError(t, err)
|
||||
domain, err := helpers.Domain(s.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, s.GenesisValidatorRoot())
|
||||
require.NoError(t, err)
|
||||
sigs := make([]bls.Signature, len(attestingIndices))
|
||||
@@ -765,7 +765,7 @@ func TestProcessBlk_AttsBasedOnValidatorCount(t *testing.T) {
|
||||
|
||||
func TestCanProcessEpoch_TrueOnEpochs(t *testing.T) {
|
||||
tests := []struct {
|
||||
slot uint64
|
||||
slot types.Slot
|
||||
canProcessEpoch bool
|
||||
}{
|
||||
{
|
||||
@@ -875,7 +875,7 @@ func TestProcessBlock_IncorrectDeposits(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestProcessSlots_SameSlotAsParentState(t *testing.T) {
|
||||
slot := uint64(2)
|
||||
slot := types.Slot(2)
|
||||
parentState, err := beaconstate.InitializeFromProto(&pb.BeaconState{Slot: slot})
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -884,10 +884,19 @@ func TestProcessSlots_SameSlotAsParentState(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestProcessSlots_LowerSlotAsParentState(t *testing.T) {
|
||||
slot := uint64(2)
|
||||
slot := types.Slot(2)
|
||||
parentState, err := beaconstate.InitializeFromProto(&pb.BeaconState{Slot: slot})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = state.ProcessSlots(context.Background(), parentState, slot-1)
|
||||
assert.ErrorContains(t, "expected state.slot 2 < slot 1", err)
|
||||
}
|
||||
|
||||
func TestProcessSlotsUsingNextSlotCache(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
s, _ := testutil.DeterministicGenesisState(t, 1)
|
||||
r := []byte{'a'}
|
||||
s, err := state.ProcessSlotsUsingNextSlotCache(ctx, s, r, 5)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, types.Slot(5), s.Slot())
|
||||
}
|
||||
|
||||
@@ -9,9 +9,9 @@ go_library(
|
||||
deps = [
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//shared/mathutil:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
|
||||
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
|
||||
],
|
||||
)
|
||||
@@ -28,6 +28,7 @@ go_test(
|
||||
"//shared/params:go_default_library",
|
||||
"//shared/testutil/assert:go_default_library",
|
||||
"//shared/testutil/require:go_default_library",
|
||||
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
|
||||
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -6,10 +6,10 @@ package validators
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/shared/mathutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
|
||||
@@ -44,7 +44,7 @@ func InitiateValidatorExit(state *stateTrie.BeaconState, idx uint64) (*stateTrie
|
||||
if validator.ExitEpoch != params.BeaconConfig().FarFutureEpoch {
|
||||
return state, nil
|
||||
}
|
||||
var exitEpochs []uint64
|
||||
var exitEpochs []types.Epoch
|
||||
err = state.ReadFromEveryValidator(func(idx int, val stateTrie.ReadOnlyValidator) error {
|
||||
if val.ExitEpoch() != params.BeaconConfig().FarFutureEpoch {
|
||||
exitEpochs = append(exitEpochs, val.ExitEpoch())
|
||||
@@ -57,7 +57,7 @@ func InitiateValidatorExit(state *stateTrie.BeaconState, idx uint64) (*stateTrie
|
||||
exitEpochs = append(exitEpochs, helpers.ActivationExitEpoch(helpers.CurrentEpoch(state)))
|
||||
|
||||
// Obtain the exit queue epoch as the maximum number in the exit epochs array.
|
||||
exitQueueEpoch := uint64(0)
|
||||
exitQueueEpoch := types.Epoch(0)
|
||||
for _, i := range exitEpochs {
|
||||
if exitQueueEpoch < i {
|
||||
exitQueueEpoch = i
|
||||
@@ -132,7 +132,7 @@ func SlashValidator(state *stateTrie.BeaconState, slashedIdx uint64) (*stateTrie
|
||||
return nil, err
|
||||
}
|
||||
validator.Slashed = true
|
||||
maxWithdrawableEpoch := mathutil.Max(validator.WithdrawableEpoch, currentEpoch+params.BeaconConfig().EpochsPerSlashingsVector)
|
||||
maxWithdrawableEpoch := types.MaxEpoch(validator.WithdrawableEpoch, currentEpoch+params.BeaconConfig().EpochsPerSlashingsVector)
|
||||
validator.WithdrawableEpoch = maxWithdrawableEpoch
|
||||
|
||||
if err := state.UpdateValidatorAtIndex(slashedIdx, validator); err != nil {
|
||||
@@ -143,7 +143,7 @@ func SlashValidator(state *stateTrie.BeaconState, slashedIdx uint64) (*stateTrie
|
||||
slashings := state.Slashings()
|
||||
currentSlashing := slashings[currentEpoch%params.BeaconConfig().EpochsPerSlashingsVector]
|
||||
if err := state.UpdateSlashingsAtIndex(
|
||||
currentEpoch%params.BeaconConfig().EpochsPerSlashingsVector,
|
||||
uint64(currentEpoch%params.BeaconConfig().EpochsPerSlashingsVector),
|
||||
currentSlashing+validator.EffectiveBalance,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
@@ -172,7 +172,7 @@ func SlashValidator(state *stateTrie.BeaconState, slashedIdx uint64) (*stateTrie
|
||||
}
|
||||
|
||||
// ActivatedValidatorIndices determines the indices activated during the given epoch.
|
||||
func ActivatedValidatorIndices(epoch uint64, validators []*ethpb.Validator) []uint64 {
|
||||
func ActivatedValidatorIndices(epoch types.Epoch, validators []*ethpb.Validator) []uint64 {
|
||||
activations := make([]uint64, 0)
|
||||
for i := 0; i < len(validators); i++ {
|
||||
val := validators[i]
|
||||
@@ -184,11 +184,11 @@ func ActivatedValidatorIndices(epoch uint64, validators []*ethpb.Validator) []ui
|
||||
}
|
||||
|
||||
// SlashedValidatorIndices determines the indices slashed during the given epoch.
|
||||
func SlashedValidatorIndices(epoch uint64, validators []*ethpb.Validator) []uint64 {
|
||||
func SlashedValidatorIndices(epoch types.Epoch, validators []*ethpb.Validator) []uint64 {
|
||||
slashed := make([]uint64, 0)
|
||||
for i := 0; i < len(validators); i++ {
|
||||
val := validators[i]
|
||||
maxWithdrawableEpoch := mathutil.Max(val.WithdrawableEpoch, epoch+params.BeaconConfig().EpochsPerSlashingsVector)
|
||||
maxWithdrawableEpoch := types.MaxEpoch(val.WithdrawableEpoch, epoch+params.BeaconConfig().EpochsPerSlashingsVector)
|
||||
if val.WithdrawableEpoch == maxWithdrawableEpoch && val.Slashed {
|
||||
slashed = append(slashed, uint64(i))
|
||||
}
|
||||
@@ -197,16 +197,16 @@ func SlashedValidatorIndices(epoch uint64, validators []*ethpb.Validator) []uint
|
||||
}
|
||||
|
||||
// ExitedValidatorIndices determines the indices exited during the current epoch.
|
||||
func ExitedValidatorIndices(epoch uint64, validators []*ethpb.Validator, activeValidatorCount uint64) ([]uint64, error) {
|
||||
func ExitedValidatorIndices(epoch types.Epoch, validators []*ethpb.Validator, activeValidatorCount uint64) ([]uint64, error) {
|
||||
exited := make([]uint64, 0)
|
||||
exitEpochs := make([]uint64, 0)
|
||||
exitEpochs := make([]types.Epoch, 0)
|
||||
for i := 0; i < len(validators); i++ {
|
||||
val := validators[i]
|
||||
if val.ExitEpoch != params.BeaconConfig().FarFutureEpoch {
|
||||
exitEpochs = append(exitEpochs, val.ExitEpoch)
|
||||
}
|
||||
}
|
||||
exitQueueEpoch := uint64(0)
|
||||
exitQueueEpoch := types.Epoch(0)
|
||||
for _, i := range exitEpochs {
|
||||
if exitQueueEpoch < i {
|
||||
exitQueueEpoch = i
|
||||
@@ -238,16 +238,16 @@ func ExitedValidatorIndices(epoch uint64, validators []*ethpb.Validator, activeV
|
||||
}
|
||||
|
||||
// EjectedValidatorIndices determines the indices ejected during the given epoch.
|
||||
func EjectedValidatorIndices(epoch uint64, validators []*ethpb.Validator, activeValidatorCount uint64) ([]uint64, error) {
|
||||
func EjectedValidatorIndices(epoch types.Epoch, validators []*ethpb.Validator, activeValidatorCount uint64) ([]uint64, error) {
|
||||
ejected := make([]uint64, 0)
|
||||
exitEpochs := make([]uint64, 0)
|
||||
exitEpochs := make([]types.Epoch, 0)
|
||||
for i := 0; i < len(validators); i++ {
|
||||
val := validators[i]
|
||||
if val.ExitEpoch != params.BeaconConfig().FarFutureEpoch {
|
||||
exitEpochs = append(exitEpochs, val.ExitEpoch)
|
||||
}
|
||||
}
|
||||
exitQueueEpoch := uint64(0)
|
||||
exitQueueEpoch := types.Epoch(0)
|
||||
for _, i := range exitEpochs {
|
||||
if exitQueueEpoch < i {
|
||||
exitQueueEpoch = i
|
||||
|
||||
@@ -3,6 +3,7 @@ package validators
|
||||
import (
|
||||
"testing"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
@@ -39,7 +40,7 @@ func TestHasVoted_OK(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestInitiateValidatorExit_AlreadyExited(t *testing.T) {
|
||||
exitEpoch := uint64(199)
|
||||
exitEpoch := types.Epoch(199)
|
||||
base := &pb.BeaconState{Validators: []*ethpb.Validator{{
|
||||
ExitEpoch: exitEpoch},
|
||||
}}
|
||||
@@ -53,7 +54,7 @@ func TestInitiateValidatorExit_AlreadyExited(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestInitiateValidatorExit_ProperExit(t *testing.T) {
|
||||
exitedEpoch := uint64(100)
|
||||
exitedEpoch := types.Epoch(100)
|
||||
idx := uint64(3)
|
||||
base := &pb.BeaconState{Validators: []*ethpb.Validator{
|
||||
{ExitEpoch: exitedEpoch},
|
||||
@@ -71,7 +72,7 @@ func TestInitiateValidatorExit_ProperExit(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestInitiateValidatorExit_ChurnOverflow(t *testing.T) {
|
||||
exitedEpoch := uint64(100)
|
||||
exitedEpoch := types.Epoch(100)
|
||||
idx := uint64(4)
|
||||
base := &pb.BeaconState{Validators: []*ethpb.Validator{
|
||||
{ExitEpoch: exitedEpoch + 2},
|
||||
@@ -133,7 +134,7 @@ func TestSlashValidator_OK(t *testing.T) {
|
||||
assert.Equal(t, helpers.CurrentEpoch(state)+params.BeaconConfig().EpochsPerSlashingsVector, v.WithdrawableEpoch, "Withdrawable epoch not the expected value")
|
||||
|
||||
maxBalance := params.BeaconConfig().MaxEffectiveBalance
|
||||
slashedBalance := state.Slashings()[state.Slot()%params.BeaconConfig().EpochsPerSlashingsVector]
|
||||
slashedBalance := state.Slashings()[state.Slot().Mod(uint64(params.BeaconConfig().EpochsPerSlashingsVector))]
|
||||
assert.Equal(t, maxBalance, slashedBalance, "Slashed balance isnt the expected amount")
|
||||
|
||||
whistleblowerReward := slashedBalance / params.BeaconConfig().WhistleBlowerRewardQuotient
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user