mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 15:37:56 -05:00
Merge From Master (#2392)
This commit is contained in:
committed by
terence tsao
parent
6cdf27c356
commit
4318d21872
69
.golangci.yml
Normal file
69
.golangci.yml
Normal file
@@ -0,0 +1,69 @@
|
||||
linters-settings:
|
||||
govet:
|
||||
check-shadowing: true
|
||||
settings:
|
||||
printf:
|
||||
funcs:
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf
|
||||
golint:
|
||||
min-confidence: 0
|
||||
gocyclo:
|
||||
min-complexity: 10
|
||||
maligned:
|
||||
suggest-new: true
|
||||
dupl:
|
||||
threshold: 100
|
||||
goconst:
|
||||
min-len: 2
|
||||
min-occurrences: 2
|
||||
depguard:
|
||||
list-type: blacklist
|
||||
packages:
|
||||
# logging is allowed only by logutils.Log, logrus
|
||||
# is allowed to use only in logutils package
|
||||
- github.com/sirupsen/logrus
|
||||
misspell:
|
||||
locale: US
|
||||
lll:
|
||||
line-length: 140
|
||||
goimports:
|
||||
local-prefixes: github.com/golangci/golangci-lint
|
||||
gocritic:
|
||||
enabled-tags:
|
||||
- performance
|
||||
- style
|
||||
- experimental
|
||||
disabled-checks:
|
||||
- wrapperFunc
|
||||
|
||||
linters:
|
||||
enable:
|
||||
- deadcode
|
||||
- goconst
|
||||
- goimports
|
||||
- golint
|
||||
- gosec
|
||||
- misspell
|
||||
- structcheck
|
||||
- typecheck
|
||||
- unparam
|
||||
- varcheck
|
||||
- gofmt
|
||||
- unused
|
||||
disable-all: true
|
||||
|
||||
run:
|
||||
skip-dirs:
|
||||
- proto/
|
||||
- ^contracts/
|
||||
deadline: 10m
|
||||
|
||||
# golangci.com configuration
|
||||
# https://github.com/golangci/golangci/wiki/Configuration
|
||||
service:
|
||||
golangci-lint-version: 1.15.0 # use the fixed version to not introduce new linters unexpectedly
|
||||
prepare:
|
||||
- echo "here I can run custom commands, but no preparation needed for this repo"
|
||||
@@ -1,20 +0,0 @@
|
||||
{
|
||||
"Deadline": "10m",
|
||||
"Exclude": [
|
||||
"^proto/",
|
||||
"^contracts/"
|
||||
],
|
||||
"DisableAll": true,
|
||||
"Enable": [
|
||||
"deadcode",
|
||||
"goconst",
|
||||
"goimports",
|
||||
"golint",
|
||||
"gosec",
|
||||
"gotype",
|
||||
"misspell",
|
||||
"structcheck",
|
||||
"unparam",
|
||||
"varcheck"
|
||||
]
|
||||
}
|
||||
@@ -10,8 +10,9 @@ matrix:
|
||||
- lint
|
||||
install:
|
||||
- go get ${gobuild_args} -t ./...
|
||||
- go get ${gobuild_args} github.com/golangci/golangci-lint/cmd/golangci-lint
|
||||
script:
|
||||
- go get ${gobuild_args} github.com/alecthomas/gometalinter && gometalinter --install && gometalinter ./...
|
||||
- golangci-lint run
|
||||
email: false
|
||||
after_success:
|
||||
- wget https://raw.githubusercontent.com/k3rn31p4nic/travis-ci-discord-webhook/master/send.sh
|
||||
|
||||
@@ -170,10 +170,10 @@ To run the unit tests of our system do:
|
||||
bazel test //...
|
||||
```
|
||||
|
||||
To run our linter, make sure you have [gometalinter](https://github.com/alecthomas/gometalinter) installed and then run:
|
||||
To run our linter, make sure you have [golangci-lint](https://https://github.com/golangci/golangci-lint) installed and then run:
|
||||
|
||||
```
|
||||
gometalinter ./...
|
||||
golangci-lint run
|
||||
```
|
||||
|
||||
# Contributing
|
||||
|
||||
36
WORKSPACE
36
WORKSPACE
@@ -21,9 +21,9 @@ http_archive(
|
||||
|
||||
http_archive(
|
||||
name = "com_github_atlassian_bazel_tools",
|
||||
sha256 = "f4d370dec7316e668c015be86b05593a0a71fa3047108c445b6643cb954193f7",
|
||||
strip_prefix = "bazel-tools-e31d79dc72434fe064b7df4efb51875b2c201e84",
|
||||
urls = ["https://github.com/atlassian/bazel-tools/archive/e31d79dc72434fe064b7df4efb51875b2c201e84.tar.gz"],
|
||||
sha256 = "af4908ea16b43e0c88007742a5c54997ee068fc393f9850ade2d59b1d5f49f55",
|
||||
strip_prefix = "bazel-tools-31382b2267b0bc3d9771085e3503473a061593e1",
|
||||
urls = ["https://github.com/atlassian/bazel-tools/archive/31382b2267b0bc3d9771085e3503473a061593e1.tar.gz"],
|
||||
)
|
||||
|
||||
http_archive(
|
||||
@@ -41,9 +41,9 @@ http_archive(
|
||||
|
||||
http_archive(
|
||||
name = "io_bazel_rules_k8s",
|
||||
sha256 = "f0a66b29bb6705da233899b61723d3fcc1b68d1e6414189a6f9c82795d407f27",
|
||||
strip_prefix = "rules_k8s-50fb3c2f868fcd0b5c3f223ac19ba72db1f6eb7d",
|
||||
url = "https://github.com/bazelbuild/rules_k8s/archive/50fb3c2f868fcd0b5c3f223ac19ba72db1f6eb7d.tar.gz",
|
||||
sha256 = "b4aabc3f931a67b4970076ae9490afc18caa1690360c952fba9681225739f6d5",
|
||||
strip_prefix = "rules_k8s-e7b408f07785e3b660ee7e99173b0e4328c7b65e",
|
||||
url = "https://github.com/bazelbuild/rules_k8s/archive/e7b408f07785e3b660ee7e99173b0e4328c7b65e.tar.gz",
|
||||
)
|
||||
|
||||
load(
|
||||
@@ -182,7 +182,7 @@ go_repository(
|
||||
|
||||
go_repository(
|
||||
name = "com_github_libp2p_go_libp2p",
|
||||
commit = "f106bf7f74f573d33505b7173ef2f7f0596b5d67", # v0.0.13
|
||||
commit = "5bce62bbecc0c07087af4cae2490b764afe1c594", # v0.0.15
|
||||
importpath = "github.com/libp2p/go-libp2p",
|
||||
)
|
||||
|
||||
@@ -213,7 +213,7 @@ go_repository(
|
||||
|
||||
go_repository(
|
||||
name = "com_github_multiformats_go_multihash",
|
||||
commit = "6b439b7c6e3c44c112171540500be697ba235235", # v0.0.1
|
||||
commit = "922cbd7915f407488e3f4413ada76400a1b29b49", # v0.0.3
|
||||
importpath = "github.com/multiformats/go-multihash",
|
||||
)
|
||||
|
||||
@@ -632,6 +632,14 @@ go_repository(
|
||||
importpath = "go.opencensus.io",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "io_opencensus_go_contrib_exporter_jaeger",
|
||||
commit = "5b8293c22f362562285c2acbc52f4a1870a47a33",
|
||||
importpath = "contrib.go.opencensus.io/exporter/jaeger",
|
||||
remote = "http://github.com/census-ecosystem/opencensus-go-exporter-jaeger",
|
||||
vcs = "git",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "org_golang_google_api",
|
||||
commit = "0cbcb99a9ea0c8023c794b2693cbe1def82ed4d7", # v0.3.2
|
||||
@@ -750,13 +758,13 @@ go_repository(
|
||||
go_repository(
|
||||
name = "com_github_libp2p_go_libp2p_kad_dht",
|
||||
build_file_proto_mode = "disable_global",
|
||||
commit = "b99a6ee931a8331ccfb8292bee6d3e5c03edf5e1", # v0.0.8
|
||||
commit = "b220ac23e82c0df788178e806b1fefa92e936766", # v0.0.9
|
||||
importpath = "github.com/libp2p/go-libp2p-kad-dht",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_ipfs_go_datastore",
|
||||
commit = "80940bb93587a19603a74ea07f9e5c921bae3b07", # v0.0.4
|
||||
commit = "f8bd98feaffb64c335ac5e74f0a3d3aedbfd13ba", # v0.0.5
|
||||
importpath = "github.com/ipfs/go-datastore",
|
||||
)
|
||||
|
||||
@@ -829,7 +837,7 @@ go_repository(
|
||||
|
||||
go_repository(
|
||||
name = "com_github_libp2p_go_libp2p_discovery",
|
||||
commit = "d4ef632c52ff995d94eaed926529eede8faa3965", # v0.0.1
|
||||
commit = "4cb4193d603389a75bccd07336de74d54bea6b00", # v0.0.2
|
||||
importpath = "github.com/libp2p/go-libp2p-discovery",
|
||||
)
|
||||
|
||||
@@ -1064,3 +1072,9 @@ go_repository(
|
||||
commit = "502116f1a0a0c1140aab04fd3787489209b357d3", # v1.2.0
|
||||
importpath = "github.com/grpc-ecosystem/go-grpc-prometheus",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_karlseguin_ccache",
|
||||
commit = "ec06cd93a07565b373789b0078ba88fe697fddd9",
|
||||
importpath = "github.com/karlseguin/ccache",
|
||||
)
|
||||
|
||||
@@ -38,6 +38,8 @@ go_test(
|
||||
"//shared/bytesutil:go_default_library",
|
||||
"//shared/hashutil:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"//shared/testutil:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -4,6 +4,7 @@ package attestation
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
@@ -86,55 +87,36 @@ func (a *Service) IncomingAttestationFeed() *event.Feed {
|
||||
return a.incomingFeed
|
||||
}
|
||||
|
||||
// LatestAttestation returns the latest attestation from validator index, the highest
|
||||
// slotNumber attestation from the attestation pool gets returned.
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
// Let `get_latest_attestation(store: Store, validator_index: ValidatorIndex) ->
|
||||
// Attestation` be the attestation with the highest slot number in `store`
|
||||
// from the validator with the given `validator_index`
|
||||
func (a *Service) LatestAttestation(ctx context.Context, index uint64) (*pb.Attestation, error) {
|
||||
validatorRegistry, err := a.beaconDB.ValidatorRegistry(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// return error if it's an invalid validator index.
|
||||
if index >= uint64(len(validatorRegistry)) {
|
||||
return nil, fmt.Errorf("invalid validator index %d", index)
|
||||
}
|
||||
pubKey := bytesutil.ToBytes48(validatorRegistry[index].Pubkey)
|
||||
|
||||
a.store.RLock()
|
||||
defer a.store.RUnlock()
|
||||
if _, exists := a.store.m[pubKey]; !exists {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return a.store.m[pubKey], nil
|
||||
}
|
||||
|
||||
// LatestAttestationTarget returns the target block the validator index attested to,
|
||||
// LatestAttestationTarget returns the target block that the validator index attested to,
|
||||
// the highest slotNumber attestation in attestation pool gets returned.
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
// Let `get_latest_attestation_target(store: Store, validator_index: ValidatorIndex) ->
|
||||
// BeaconBlock` be the target block in the attestation
|
||||
// `get_latest_attestation(store, validator_index)`.
|
||||
func (a *Service) LatestAttestationTarget(ctx context.Context, index uint64) (*pb.BeaconBlock, error) {
|
||||
attestation, err := a.LatestAttestation(ctx, index)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get attestation: %v", err)
|
||||
func (a *Service) LatestAttestationTarget(beaconState *pb.BeaconState, index uint64) (*pb.AttestationTarget, error) {
|
||||
if index >= uint64(len(beaconState.ValidatorRegistry)) {
|
||||
return nil, fmt.Errorf("invalid validator index %d", index)
|
||||
}
|
||||
validator := beaconState.ValidatorRegistry[index]
|
||||
|
||||
pubKey := bytesutil.ToBytes48(validator.Pubkey)
|
||||
a.store.RLock()
|
||||
defer a.store.RUnlock()
|
||||
if _, exists := a.store.m[pubKey]; !exists {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
attestation := a.store.m[pubKey]
|
||||
if attestation == nil {
|
||||
return nil, nil
|
||||
}
|
||||
targetBlockHash := bytesutil.ToBytes32(attestation.Data.BeaconBlockRootHash32)
|
||||
targetBlock, err := a.beaconDB.Block(targetBlockHash)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get target block: %v", err)
|
||||
targetRoot := bytesutil.ToBytes32(attestation.Data.BeaconBlockRootHash32)
|
||||
if !a.beaconDB.HasBlock(targetRoot) {
|
||||
return nil, nil
|
||||
}
|
||||
return targetBlock, nil
|
||||
|
||||
return a.beaconDB.AttestationTarget(targetRoot)
|
||||
}
|
||||
|
||||
// attestationPool takes an newly received attestation from sync service
|
||||
@@ -148,8 +130,8 @@ func (a *Service) attestationPool() {
|
||||
log.Debug("Attestation pool closed, exiting goroutine")
|
||||
return
|
||||
// Listen for a newly received incoming attestation from the sync service.
|
||||
case attestation := <-a.incomingChan:
|
||||
handler.SafelyHandleMessage(a.ctx, a.handleAttestation, attestation)
|
||||
case attestations := <-a.incomingChan:
|
||||
handler.SafelyHandleMessage(a.ctx, a.handleAttestation, attestations)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -183,10 +165,58 @@ func (a *Service) UpdateLatestAttestation(ctx context.Context, attestation *pb.A
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return a.updateAttestation(ctx, headRoot, beaconState, attestation)
|
||||
}
|
||||
|
||||
// BatchUpdateLatestAttestation updates multiple attestations and adds them into the attestation store
|
||||
// if they are valid.
|
||||
func (a *Service) BatchUpdateLatestAttestation(ctx context.Context, attestations []*pb.Attestation) error {
|
||||
|
||||
if attestations == nil {
|
||||
return nil
|
||||
}
|
||||
// Potential improvement, instead of getting the state,
|
||||
// we could get a mapping of validator index to public key.
|
||||
beaconState, err := a.beaconDB.HeadState(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
head, err := a.beaconDB.ChainHead()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
headRoot, err := hashutil.HashBeaconBlock(head)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
attestations = a.sortAttestations(attestations)
|
||||
|
||||
for _, attestation := range attestations {
|
||||
if err := a.updateAttestation(ctx, headRoot, beaconState, attestation); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// InsertAttestationIntoStore locks the store, inserts the attestation, then
|
||||
// unlocks the store again. This method may be used by external services
|
||||
// in testing to populate the attestation store.
|
||||
func (a *Service) InsertAttestationIntoStore(pubkey [48]byte, att *pb.Attestation) {
|
||||
a.store.Lock()
|
||||
defer a.store.Unlock()
|
||||
a.store.m[pubkey] = att
|
||||
}
|
||||
|
||||
func (a *Service) updateAttestation(ctx context.Context, headRoot [32]byte, beaconState *pb.BeaconState,
|
||||
attestation *pb.Attestation) error {
|
||||
totalAttestationSeen.Inc()
|
||||
|
||||
slot := attestation.Data.Slot
|
||||
var committee []uint64
|
||||
var cachedCommittees *cache.CommitteesInSlot
|
||||
var err error
|
||||
|
||||
for beaconState.Slot < slot {
|
||||
beaconState, err = state.ExecuteStateTransition(
|
||||
@@ -245,6 +275,15 @@ func (a *Service) UpdateLatestAttestation(ctx context.Context, attestation *pb.A
|
||||
continue
|
||||
}
|
||||
|
||||
if i >= len(committee) {
|
||||
log.Errorf("Bitfield points to an invalid index in the committee: bitfield %08b", bitfield)
|
||||
continue
|
||||
}
|
||||
|
||||
if int(committee[i]) >= len(beaconState.ValidatorRegistry) {
|
||||
log.Errorf("Index doesn't exist in validator registry: index %d", committee[i])
|
||||
}
|
||||
|
||||
// If the attestation came from this attester. We use the slot committee to find the
|
||||
// validator's actual index.
|
||||
pubkey := bytesutil.ToBytes48(beaconState.ValidatorRegistry[committee[i]].Pubkey)
|
||||
@@ -277,11 +316,11 @@ func (a *Service) UpdateLatestAttestation(ctx context.Context, attestation *pb.A
|
||||
return nil
|
||||
}
|
||||
|
||||
// InsertAttestationIntoStore locks the store, inserts the attestation, then
|
||||
// unlocks the store again. This method may be used by external services
|
||||
// in testing to populate the attestation store.
|
||||
func (a *Service) InsertAttestationIntoStore(pubkey [48]byte, att *pb.Attestation) {
|
||||
a.store.Lock()
|
||||
defer a.store.Unlock()
|
||||
a.store.m[pubkey] = att
|
||||
// sortAttestations sorts attestations by their slot number in ascending order.
|
||||
func (a *Service) sortAttestations(attestations []*pb.Attestation) []*pb.Attestation {
|
||||
sort.SliceStable(attestations, func(i, j int) bool {
|
||||
return attestations[i].Data.Slot < attestations[j].Data.Slot
|
||||
})
|
||||
|
||||
return attestations
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package attestation
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"reflect"
|
||||
@@ -13,7 +14,9 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
"github.com/sirupsen/logrus"
|
||||
logTest "github.com/sirupsen/logrus/hooks/test"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -128,73 +131,6 @@ func TestAttestationPool_UpdatesAttestationPool(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestLatestAttestation_ReturnsLatestAttestation(t *testing.T) {
|
||||
beaconDB := internal.SetupDB(t)
|
||||
defer internal.TeardownDB(t, beaconDB)
|
||||
ctx := context.Background()
|
||||
|
||||
pubKey := []byte{'A'}
|
||||
if err := beaconDB.SaveState(ctx, &pb.BeaconState{
|
||||
ValidatorRegistry: []*pb.Validator{{Pubkey: pubKey}},
|
||||
}); err != nil {
|
||||
t.Fatalf("could not save state: %v", err)
|
||||
}
|
||||
|
||||
service := NewAttestationService(context.Background(), &Config{BeaconDB: beaconDB})
|
||||
pubKey48 := bytesutil.ToBytes48(pubKey)
|
||||
attestation := &pb.Attestation{AggregationBitfield: []byte{'B'}}
|
||||
service.store.m[pubKey48] = attestation
|
||||
|
||||
latestAttestation, err := service.LatestAttestation(ctx, 0)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not get latest attestation: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(attestation, latestAttestation) {
|
||||
t.Errorf("Wanted: %v, got: %v", attestation, latestAttestation)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLatestAttestation_InvalidIndex(t *testing.T) {
|
||||
beaconDB := internal.SetupDB(t)
|
||||
defer internal.TeardownDB(t, beaconDB)
|
||||
ctx := context.Background()
|
||||
|
||||
if err := beaconDB.SaveState(ctx, &pb.BeaconState{
|
||||
ValidatorRegistry: []*pb.Validator{},
|
||||
}); err != nil {
|
||||
t.Fatalf("could not save state: %v", err)
|
||||
}
|
||||
service := NewAttestationService(context.Background(), &Config{BeaconDB: beaconDB})
|
||||
|
||||
index := uint64(0)
|
||||
want := fmt.Sprintf("invalid validator index %d", index)
|
||||
if _, err := service.LatestAttestation(ctx, index); !strings.Contains(err.Error(), want) {
|
||||
t.Errorf("Wanted error to contain %s, received %v", want, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLatestAttestation_NoAttestation(t *testing.T) {
|
||||
beaconDB := internal.SetupDB(t)
|
||||
defer internal.TeardownDB(t, beaconDB)
|
||||
ctx := context.Background()
|
||||
|
||||
if err := beaconDB.SaveState(ctx, &pb.BeaconState{
|
||||
ValidatorRegistry: []*pb.Validator{{}},
|
||||
}); err != nil {
|
||||
t.Fatalf("could not save state: %v", err)
|
||||
}
|
||||
service := NewAttestationService(context.Background(), &Config{BeaconDB: beaconDB})
|
||||
|
||||
index := 0
|
||||
a, err := service.LatestAttestation(ctx, uint64(index))
|
||||
if err != nil {
|
||||
t.Fatalf("could not run latest attestation: %v", err)
|
||||
}
|
||||
if a != nil {
|
||||
t.Errorf("Wanted attesstation %v, received %v", nil, a)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLatestAttestationTarget_CantGetAttestation(t *testing.T) {
|
||||
beaconDB := internal.SetupDB(t)
|
||||
defer internal.TeardownDB(t, beaconDB)
|
||||
@@ -206,10 +142,14 @@ func TestLatestAttestationTarget_CantGetAttestation(t *testing.T) {
|
||||
t.Fatalf("could not save state: %v", err)
|
||||
}
|
||||
service := NewAttestationService(context.Background(), &Config{BeaconDB: beaconDB})
|
||||
headState, err := beaconDB.HeadState(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
index := uint64(100)
|
||||
want := fmt.Sprintf("could not get attestation: invalid validator index %d", index)
|
||||
if _, err := service.LatestAttestationTarget(ctx, index); !strings.Contains(err.Error(), want) {
|
||||
want := fmt.Sprintf("invalid validator index %d", index)
|
||||
if _, err := service.LatestAttestationTarget(headState, index); !strings.Contains(err.Error(), want) {
|
||||
t.Errorf("Wanted error to contain %s, received %v", want, err)
|
||||
}
|
||||
}
|
||||
@@ -234,6 +174,13 @@ func TestLatestAttestationTarget_ReturnsLatestAttestedBlock(t *testing.T) {
|
||||
if err != nil {
|
||||
log.Fatalf("could not hash block: %v", err)
|
||||
}
|
||||
if err := beaconDB.SaveAttestationTarget(ctx, &pb.AttestationTarget{
|
||||
Slot: block.Slot,
|
||||
BlockRoot: blockRoot[:],
|
||||
ParentRoot: []byte{},
|
||||
}); err != nil {
|
||||
log.Fatalf("could not save att target: %v", err)
|
||||
}
|
||||
|
||||
service := NewAttestationService(context.Background(), &Config{BeaconDB: beaconDB})
|
||||
|
||||
@@ -244,12 +191,18 @@ func TestLatestAttestationTarget_ReturnsLatestAttestedBlock(t *testing.T) {
|
||||
pubKey48 := bytesutil.ToBytes48(pubKey)
|
||||
service.store.m[pubKey48] = attestation
|
||||
|
||||
latestAttestedBlock, err := service.LatestAttestationTarget(ctx, 0)
|
||||
headState, err := beaconDB.HeadState(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
latestAttestedTarget, err := service.LatestAttestationTarget(headState, 0)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not get latest attestation: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(block, latestAttestedBlock) {
|
||||
t.Errorf("Wanted: %v, got: %v", block, latestAttestedBlock)
|
||||
|
||||
if !bytes.Equal(blockRoot[:], latestAttestedTarget.BlockRoot) {
|
||||
t.Errorf("Wanted: %v, got: %v", blockRoot[:], latestAttestedTarget.BlockRoot)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -402,3 +355,90 @@ func TestUpdateLatestAttestation_CacheEnabledAndHit(t *testing.T) {
|
||||
attestation.Data.Slot, service.store.m[pubkey].Data.Slot)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateLatestAttestation_InvalidIndex(t *testing.T) {
|
||||
beaconDB := internal.SetupDB(t)
|
||||
hook := logTest.NewGlobal()
|
||||
defer internal.TeardownDB(t, beaconDB)
|
||||
ctx := context.Background()
|
||||
|
||||
var validators []*pb.Validator
|
||||
for i := 0; i < 64; i++ {
|
||||
validators = append(validators, &pb.Validator{
|
||||
Pubkey: []byte{byte(i)},
|
||||
ActivationEpoch: params.BeaconConfig().GenesisEpoch,
|
||||
ExitEpoch: params.BeaconConfig().GenesisEpoch + 10,
|
||||
})
|
||||
}
|
||||
|
||||
beaconState := &pb.BeaconState{
|
||||
Slot: params.BeaconConfig().GenesisSlot + 1,
|
||||
ValidatorRegistry: validators,
|
||||
}
|
||||
block := &pb.BeaconBlock{
|
||||
Slot: params.BeaconConfig().GenesisSlot + 1,
|
||||
}
|
||||
if err := beaconDB.SaveBlock(block); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := beaconDB.UpdateChainHead(ctx, block, beaconState); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
service := NewAttestationService(context.Background(), &Config{BeaconDB: beaconDB})
|
||||
attestation := &pb.Attestation{
|
||||
AggregationBitfield: []byte{0xC0},
|
||||
Data: &pb.AttestationData{
|
||||
Slot: params.BeaconConfig().GenesisSlot + 1,
|
||||
Shard: 1,
|
||||
},
|
||||
}
|
||||
|
||||
if err := service.UpdateLatestAttestation(ctx, attestation); err != nil {
|
||||
t.Fatalf("could not update latest attestation: %v", err)
|
||||
}
|
||||
testutil.AssertLogsContain(t, hook, "Bitfield points to an invalid index in the committee")
|
||||
}
|
||||
|
||||
func TestUpdateLatestAttestation_BatchUpdate(t *testing.T) {
|
||||
beaconDB := internal.SetupDB(t)
|
||||
defer internal.TeardownDB(t, beaconDB)
|
||||
ctx := context.Background()
|
||||
|
||||
var validators []*pb.Validator
|
||||
for i := 0; i < 64; i++ {
|
||||
validators = append(validators, &pb.Validator{
|
||||
Pubkey: []byte{byte(i)},
|
||||
ActivationEpoch: params.BeaconConfig().GenesisEpoch,
|
||||
ExitEpoch: params.BeaconConfig().GenesisEpoch + 10,
|
||||
})
|
||||
}
|
||||
|
||||
beaconState := &pb.BeaconState{
|
||||
Slot: params.BeaconConfig().GenesisSlot + 1,
|
||||
ValidatorRegistry: validators,
|
||||
}
|
||||
block := &pb.BeaconBlock{
|
||||
Slot: params.BeaconConfig().GenesisSlot + 1,
|
||||
}
|
||||
if err := beaconDB.SaveBlock(block); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := beaconDB.UpdateChainHead(ctx, block, beaconState); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
service := NewAttestationService(context.Background(), &Config{BeaconDB: beaconDB})
|
||||
attestations := make([]*pb.Attestation, 0)
|
||||
for i := 0; i < 10; i++ {
|
||||
attestations = append(attestations, &pb.Attestation{
|
||||
AggregationBitfield: []byte{0x80},
|
||||
Data: &pb.AttestationData{
|
||||
Slot: params.BeaconConfig().GenesisSlot + 1,
|
||||
Shard: 1,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
if err := service.BatchUpdateLatestAttestation(ctx, attestations); err != nil {
|
||||
t.Fatalf("could not update latest attestation: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ go_library(
|
||||
"//shared/hashutil:go_default_library",
|
||||
"//shared/p2p:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"@com_github_gogo_protobuf//proto:go_default_library",
|
||||
"@com_github_prometheus_client_golang//prometheus:go_default_library",
|
||||
"@com_github_prometheus_client_golang//prometheus/promauto:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
|
||||
@@ -54,6 +54,8 @@ func (b *BlockFailedProcessingErr) Error() string {
|
||||
// 4. Process and cleanup any block operations, such as attestations and deposits, which would need to be
|
||||
// either included or flushed from the beacon node's runtime.
|
||||
func (c *ChainService) ReceiveBlock(ctx context.Context, block *pb.BeaconBlock) (*pb.BeaconState, error) {
|
||||
c.receiveBlockLock.Lock()
|
||||
defer c.receiveBlockLock.Unlock()
|
||||
ctx, span := trace.StartSpan(ctx, "beacon-chain.blockchain.ReceiveBlock")
|
||||
defer span.End()
|
||||
parentRoot := bytesutil.ToBytes32(block.ParentRootHash32)
|
||||
@@ -215,6 +217,13 @@ func (c *ChainService) SaveAndBroadcastBlock(ctx context.Context, block *pb.Beac
|
||||
if err := c.beaconDB.SaveBlock(block); err != nil {
|
||||
return fmt.Errorf("failed to save block: %v", err)
|
||||
}
|
||||
if err := c.beaconDB.SaveAttestationTarget(ctx, &pb.AttestationTarget{
|
||||
Slot: block.Slot,
|
||||
BlockRoot: blockRoot[:],
|
||||
ParentRoot: block.ParentRootHash32,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("failed to save attestation target: %v", err)
|
||||
}
|
||||
// Announce the new block to the network.
|
||||
c.p2p.Broadcast(ctx, &pb.BeaconBlockAnnounce{
|
||||
Hash: blockRoot[:],
|
||||
@@ -233,11 +242,8 @@ func (c *ChainService) CleanupBlockOperations(ctx context.Context, block *pb.Bea
|
||||
log.Error("Sent processed block to no subscribers")
|
||||
}
|
||||
|
||||
// Update attestation store with latest attestation target.
|
||||
for _, att := range block.Body.Attestations {
|
||||
if err := c.attsService.UpdateLatestAttestation(ctx, att); err != nil {
|
||||
return fmt.Errorf("failed to update latest attestation for store: %v", err)
|
||||
}
|
||||
if err := c.attsService.BatchUpdateLatestAttestation(ctx, block.Body.Attestations); err != nil {
|
||||
return fmt.Errorf("failed to update latest attestation for store: %v", err)
|
||||
}
|
||||
|
||||
// Remove pending deposits from the deposit queue.
|
||||
|
||||
@@ -192,7 +192,7 @@ func TestReceiveBlock_UsesParentBlockState(t *testing.T) {
|
||||
t.Fatalf("Could not tree hash state: %v", err)
|
||||
}
|
||||
|
||||
parentHash, genesisBlock := setupGenesisBlock(t, chainService, beaconState)
|
||||
parentHash, genesisBlock := setupGenesisBlock(t, chainService)
|
||||
if err := chainService.beaconDB.UpdateChainHead(ctx, genesisBlock, beaconState); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -247,7 +247,7 @@ func TestReceiveBlock_DeletesBadBlock(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
parentHash, genesisBlock := setupGenesisBlock(t, chainService, beaconState)
|
||||
parentHash, genesisBlock := setupGenesisBlock(t, chainService)
|
||||
if err := chainService.beaconDB.UpdateChainHead(ctx, genesisBlock, beaconState); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -325,7 +325,7 @@ func TestReceiveBlock_CheckBlockStateRoot_GoodState(t *testing.T) {
|
||||
if err := chainService.beaconDB.SaveHistoricalState(ctx, beaconState); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
parentHash, genesisBlock := setupGenesisBlock(t, chainService, beaconState)
|
||||
parentHash, genesisBlock := setupGenesisBlock(t, chainService)
|
||||
beaconState.Slot++
|
||||
if err := chainService.beaconDB.UpdateChainHead(ctx, genesisBlock, beaconState); err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -370,7 +370,7 @@ func TestReceiveBlock_CheckBlockStateRoot_BadState(t *testing.T) {
|
||||
if err := chainService.beaconDB.SaveHistoricalState(ctx, beaconState); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
parentHash, genesisBlock := setupGenesisBlock(t, chainService, beaconState)
|
||||
parentHash, genesisBlock := setupGenesisBlock(t, chainService)
|
||||
beaconState.Slot++
|
||||
if err := chainService.beaconDB.UpdateChainHead(ctx, genesisBlock, beaconState); err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -426,7 +426,7 @@ func TestReceiveBlock_RemovesPendingDeposits(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Could not tree hash state: %v", err)
|
||||
}
|
||||
parentHash, genesisBlock := setupGenesisBlock(t, chainService, beaconState)
|
||||
parentHash, genesisBlock := setupGenesisBlock(t, chainService)
|
||||
beaconState.Slot++
|
||||
if err := chainService.beaconDB.UpdateChainHead(ctx, genesisBlock, beaconState); err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -581,7 +581,7 @@ func TestReceiveBlock_OnChainSplit(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Could not tree hash state: %v", err)
|
||||
}
|
||||
parentHash, genesisBlock := setupGenesisBlock(t, chainService, beaconState)
|
||||
parentHash, genesisBlock := setupGenesisBlock(t, chainService)
|
||||
if err := db.UpdateChainHead(ctx, genesisBlock, beaconState); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package blockchain
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||
@@ -12,9 +12,9 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/sirupsen/logrus"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
@@ -132,7 +132,7 @@ func (c *ChainService) ApplyForkChoiceRule(
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not retrieve justified state: %v", err)
|
||||
}
|
||||
attestationTargets, err := c.attestationTargets(ctx, justifiedState)
|
||||
attestationTargets, err := c.attestationTargets(justifiedState)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not retrieve attestation target: %v", err)
|
||||
}
|
||||
@@ -181,7 +181,9 @@ func (c *ChainService) ApplyForkChoiceRule(
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not hash head: %v", err)
|
||||
}
|
||||
log.WithField("headRoot", fmt.Sprintf("0x%x", h)).Info("Chain head block and state updated")
|
||||
log.WithFields(logrus.Fields{
|
||||
"headRoot": fmt.Sprintf("0x%x", h),
|
||||
}).Info("Chain head block and state updated")
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -217,10 +219,9 @@ func (c *ChainService) lmdGhost(
|
||||
ctx context.Context,
|
||||
startBlock *pb.BeaconBlock,
|
||||
startState *pb.BeaconState,
|
||||
voteTargets map[uint64]*pb.BeaconBlock,
|
||||
voteTargets map[uint64]*pb.AttestationTarget,
|
||||
) (*pb.BeaconBlock, error) {
|
||||
highestSlot := c.beaconDB.HighestBlockSlot()
|
||||
|
||||
head := startBlock
|
||||
for {
|
||||
children, err := c.blockChildren(ctx, head, highestSlot)
|
||||
@@ -290,18 +291,18 @@ func (c *ChainService) blockChildren(ctx context.Context, block *pb.BeaconBlock,
|
||||
// attestationTargets retrieves the list of attestation targets since last finalized epoch,
|
||||
// each attestation target consists of validator index and its attestation target (i.e. the block
|
||||
// which the validator attested to)
|
||||
func (c *ChainService) attestationTargets(ctx context.Context, state *pb.BeaconState) (map[uint64]*pb.BeaconBlock, error) {
|
||||
func (c *ChainService) attestationTargets(state *pb.BeaconState) (map[uint64]*pb.AttestationTarget, error) {
|
||||
indices := helpers.ActiveValidatorIndices(state, helpers.CurrentEpoch(state))
|
||||
attestationTargets := make(map[uint64]*pb.BeaconBlock)
|
||||
attestationTargets := make(map[uint64]*pb.AttestationTarget)
|
||||
for i, index := range indices {
|
||||
block, err := c.attsService.LatestAttestationTarget(ctx, index)
|
||||
target, err := c.attsService.LatestAttestationTarget(state, index)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not retrieve attestation target: %v", err)
|
||||
}
|
||||
if block == nil {
|
||||
if target == nil {
|
||||
continue
|
||||
}
|
||||
attestationTargets[uint64(i)] = block
|
||||
attestationTargets[uint64(i)] = target
|
||||
}
|
||||
return attestationTargets, nil
|
||||
}
|
||||
@@ -316,34 +317,31 @@ func (c *ChainService) attestationTargets(ctx context.Context, state *pb.BeaconS
|
||||
// for validator_index, target in attestation_targets
|
||||
// if get_ancestor(store, target, block.slot) == block
|
||||
// )
|
||||
func VoteCount(block *pb.BeaconBlock, state *pb.BeaconState, targets map[uint64]*pb.BeaconBlock, beaconDB *db.BeaconDB) (int, error) {
|
||||
func VoteCount(block *pb.BeaconBlock, state *pb.BeaconState, targets map[uint64]*pb.AttestationTarget, beaconDB *db.BeaconDB) (int, error) {
|
||||
balances := 0
|
||||
var ancestor *pb.BeaconBlock
|
||||
var ancestorRoot []byte
|
||||
var err error
|
||||
|
||||
for validatorIndex, targetBlock := range targets {
|
||||
if featureconfig.FeatureConfig().EnableBlockAncestorCache {
|
||||
ancestor, err = cachedAncestorBlock(targetBlock, block.Slot, beaconDB)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
} else {
|
||||
// if block ancestor cache was not enabled, retrieve the ancestor recursively.
|
||||
ancestor, err = BlockAncestor(targetBlock, block.Slot, beaconDB)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
blockRoot, err := hashutil.HashBeaconBlock(block)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
for validatorIndex, target := range targets {
|
||||
ancestorRoot, err = cachedAncestor(target, block.Slot, beaconDB)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
// This covers the following case, we start at B5, and want to process B6 and B7
|
||||
// B6 can be processed, B7 can not be processed because it's pointed to the
|
||||
// block older than current block 5.
|
||||
// B4 - B5 - B6
|
||||
// \ - - - - - B7
|
||||
if ancestor == nil {
|
||||
if ancestorRoot == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if proto.Equal(ancestor, block) {
|
||||
if bytes.Equal(blockRoot[:], ancestorRoot) {
|
||||
balances += int(helpers.EffectiveBalance(state, validatorIndex))
|
||||
}
|
||||
}
|
||||
@@ -363,53 +361,63 @@ func VoteCount(block *pb.BeaconBlock, state *pb.BeaconState, targets map[uint64]
|
||||
// return None
|
||||
// else:
|
||||
// return get_ancestor(store, store.get_parent(block), slot)
|
||||
func BlockAncestor(block *pb.BeaconBlock, slot uint64, beaconDB *db.BeaconDB) (*pb.BeaconBlock, error) {
|
||||
if block.Slot == slot {
|
||||
return block, nil
|
||||
func BlockAncestor(targetBlock *pb.AttestationTarget, slot uint64, beaconDB *db.BeaconDB) ([]byte, error) {
|
||||
if targetBlock.Slot == slot {
|
||||
return targetBlock.BlockRoot[:], nil
|
||||
}
|
||||
if block.Slot < slot {
|
||||
if targetBlock.Slot < slot {
|
||||
return nil, nil
|
||||
}
|
||||
parentHash := bytesutil.ToBytes32(block.ParentRootHash32)
|
||||
parent, err := beaconDB.Block(parentHash)
|
||||
parentRoot := bytesutil.ToBytes32(targetBlock.ParentRoot)
|
||||
parent, err := beaconDB.Block(parentRoot)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get parent block: %v", err)
|
||||
}
|
||||
if parent == nil {
|
||||
return nil, fmt.Errorf("parent block does not exist: %v", err)
|
||||
}
|
||||
return BlockAncestor(parent, slot, beaconDB)
|
||||
newTarget := &pb.AttestationTarget{
|
||||
Slot: parent.Slot,
|
||||
BlockRoot: parentRoot[:],
|
||||
ParentRoot: parent.ParentRootHash32,
|
||||
}
|
||||
return BlockAncestor(newTarget, slot, beaconDB)
|
||||
}
|
||||
|
||||
// cachedAncestorBlock retrieves the cached ancestor block from block ancestor cache,
|
||||
// cachedAncestor retrieves the cached ancestor target from block ancestor cache,
|
||||
// if it's not there it looks up the block tree get it and cache it.
|
||||
func cachedAncestorBlock(targetBlk *pb.BeaconBlock, height uint64, beaconDB *db.BeaconDB) (*pb.BeaconBlock, error) {
|
||||
var ancestor *pb.BeaconBlock
|
||||
|
||||
func cachedAncestor(target *pb.AttestationTarget, height uint64, beaconDB *db.BeaconDB) ([]byte, error) {
|
||||
// check if the ancestor block of from a given block height was cached.
|
||||
targetHash, err := hashutil.HashBeaconBlock(targetBlk)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cachedAncestorBlock, err := blkAncestorCache.AncestorBySlot(targetHash[:], height)
|
||||
cachedAncestorInfo, err := blkAncestorCache.AncestorBySlot(target.BlockRoot, height)
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
if cachedAncestorBlock != nil {
|
||||
return cachedAncestorBlock.Block, nil
|
||||
if cachedAncestorInfo != nil {
|
||||
return cachedAncestorInfo.Target.BlockRoot, nil
|
||||
}
|
||||
|
||||
// add the ancestor to the cache if it was not cached.
|
||||
ancestor, err = BlockAncestor(targetBlk, height, beaconDB)
|
||||
ancestorRoot, err := BlockAncestor(target, height, beaconDB)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ancestor, err := beaconDB.Block(bytesutil.ToBytes32(ancestorRoot))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if ancestor == nil {
|
||||
return nil, nil
|
||||
}
|
||||
ancestorTarget := &pb.AttestationTarget{
|
||||
Slot: ancestor.Slot,
|
||||
BlockRoot: ancestorRoot,
|
||||
ParentRoot: ancestor.ParentRootHash32,
|
||||
}
|
||||
if err := blkAncestorCache.AddBlockAncestor(&cache.AncestorInfo{
|
||||
Hash: targetHash[:],
|
||||
Height: height,
|
||||
Block: ancestor,
|
||||
Hash: target.BlockRoot,
|
||||
Target: ancestorTarget,
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ancestor, nil
|
||||
return ancestorRoot, nil
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import (
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bls"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/forkutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
@@ -30,6 +29,7 @@ import (
|
||||
|
||||
// Ensure ChainService implements interfaces.
|
||||
var _ = ForkChoice(&ChainService{})
|
||||
var endpoint = "ws://127.0.0.1"
|
||||
|
||||
func TestApplyForkChoice_SetsCanonicalHead(t *testing.T) {
|
||||
deposits, _ := setupInitialDeposits(t, 5)
|
||||
@@ -140,9 +140,17 @@ func TestVoteCount_ParentDoesNotExistNoVoteCount(t *testing.T) {
|
||||
if err := beaconDB.SaveBlock(potentialHead); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
headRoot, err := hashutil.HashBeaconBlock(potentialHead)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
voteTargets := make(map[uint64]*pb.BeaconBlock)
|
||||
voteTargets[0] = potentialHead
|
||||
voteTargets := make(map[uint64]*pb.AttestationTarget)
|
||||
voteTargets[0] = &pb.AttestationTarget{
|
||||
Slot: potentialHead.Slot,
|
||||
BlockRoot: headRoot[:],
|
||||
ParentRoot: potentialHead.ParentRootHash32,
|
||||
}
|
||||
count, err := VoteCount(genesisBlock, &pb.BeaconState{}, voteTargets, beaconDB)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not get vote count: %v", err)
|
||||
@@ -168,10 +176,19 @@ func TestVoteCount_IncreaseCountCorrectly(t *testing.T) {
|
||||
Slot: params.BeaconConfig().GenesisSlot + 5,
|
||||
ParentRootHash32: genesisRoot[:],
|
||||
}
|
||||
headRoot1, err := hashutil.HashBeaconBlock(potentialHead)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
potentialHead2 := &pb.BeaconBlock{
|
||||
Slot: params.BeaconConfig().GenesisSlot + 6,
|
||||
ParentRootHash32: genesisRoot[:],
|
||||
}
|
||||
headRoot2, err := hashutil.HashBeaconBlock(potentialHead2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// We store these potential heads in the DB.
|
||||
if err := beaconDB.SaveBlock(potentialHead); err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -180,9 +197,17 @@ func TestVoteCount_IncreaseCountCorrectly(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
beaconState := &pb.BeaconState{Balances: []uint64{1e9, 1e9}}
|
||||
voteTargets := make(map[uint64]*pb.BeaconBlock)
|
||||
voteTargets[0] = potentialHead
|
||||
voteTargets[1] = potentialHead2
|
||||
voteTargets := make(map[uint64]*pb.AttestationTarget)
|
||||
voteTargets[0] = &pb.AttestationTarget{
|
||||
Slot: potentialHead.Slot,
|
||||
BlockRoot: headRoot1[:],
|
||||
ParentRoot: potentialHead.ParentRootHash32,
|
||||
}
|
||||
voteTargets[1] = &pb.AttestationTarget{
|
||||
Slot: potentialHead2.Slot,
|
||||
BlockRoot: headRoot2[:],
|
||||
ParentRoot: potentialHead2.ParentRootHash32,
|
||||
}
|
||||
count, err := VoteCount(genesisBlock, beaconState, voteTargets, beaconDB)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not fetch vote balances: %v", err)
|
||||
@@ -216,6 +241,13 @@ func TestAttestationTargets_RetrieveWorks(t *testing.T) {
|
||||
if err != nil {
|
||||
log.Fatalf("could not hash block: %v", err)
|
||||
}
|
||||
if err := beaconDB.SaveAttestationTarget(ctx, &pb.AttestationTarget{
|
||||
Slot: block.Slot,
|
||||
BlockRoot: blockRoot[:],
|
||||
ParentRoot: []byte{},
|
||||
}); err != nil {
|
||||
log.Fatalf("could not save att tgt: %v", err)
|
||||
}
|
||||
|
||||
attsService := attestation.NewAttestationService(
|
||||
context.Background(),
|
||||
@@ -229,7 +261,7 @@ func TestAttestationTargets_RetrieveWorks(t *testing.T) {
|
||||
attsService.InsertAttestationIntoStore(pubKey48, att)
|
||||
|
||||
chainService := setupBeaconChain(t, beaconDB, attsService)
|
||||
attestationTargets, err := chainService.attestationTargets(ctx, beaconState)
|
||||
attestationTargets, err := chainService.attestationTargets(beaconState)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not get attestation targets: %v", err)
|
||||
}
|
||||
@@ -479,6 +511,10 @@ func TestLMDGhost_TrivialHeadUpdate(t *testing.T) {
|
||||
Slot: 2,
|
||||
ParentRootHash32: root1[:],
|
||||
}
|
||||
block2Root, err := hashutil.HashBeaconBlock(block2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err = chainService.beaconDB.SaveBlock(block2); err != nil {
|
||||
t.Fatalf("Could not save block: %v", err)
|
||||
}
|
||||
@@ -487,8 +523,12 @@ func TestLMDGhost_TrivialHeadUpdate(t *testing.T) {
|
||||
}
|
||||
|
||||
// The only vote is on block 2.
|
||||
voteTargets := make(map[uint64]*pb.BeaconBlock)
|
||||
voteTargets[0] = block2
|
||||
voteTargets := make(map[uint64]*pb.AttestationTarget)
|
||||
voteTargets[0] = &pb.AttestationTarget{
|
||||
Slot: block2.Slot,
|
||||
BlockRoot: block2Root[:],
|
||||
ParentRoot: block2.ParentRootHash32,
|
||||
}
|
||||
|
||||
// LMDGhost should pick block 2.
|
||||
head, err := chainService.lmdGhost(ctx, block1, beaconState, voteTargets)
|
||||
@@ -540,6 +580,10 @@ func TestLMDGhost_3WayChainSplitsSameHeight(t *testing.T) {
|
||||
Slot: 2,
|
||||
ParentRootHash32: root1[:],
|
||||
}
|
||||
root2, err := hashutil.HashBeaconBlock(block2)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not hash block: %v", err)
|
||||
}
|
||||
if err = chainService.beaconDB.SaveBlock(block2); err != nil {
|
||||
t.Fatalf("Could not save block: %v", err)
|
||||
}
|
||||
@@ -551,6 +595,10 @@ func TestLMDGhost_3WayChainSplitsSameHeight(t *testing.T) {
|
||||
Slot: 3,
|
||||
ParentRootHash32: root1[:],
|
||||
}
|
||||
root3, err := hashutil.HashBeaconBlock(block3)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not hash block: %v", err)
|
||||
}
|
||||
if err = chainService.beaconDB.SaveBlock(block3); err != nil {
|
||||
t.Fatalf("Could not save block: %v", err)
|
||||
}
|
||||
@@ -562,6 +610,10 @@ func TestLMDGhost_3WayChainSplitsSameHeight(t *testing.T) {
|
||||
Slot: 4,
|
||||
ParentRootHash32: root1[:],
|
||||
}
|
||||
root4, err := hashutil.HashBeaconBlock(block4)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not hash block: %v", err)
|
||||
}
|
||||
if err = chainService.beaconDB.SaveBlock(block4); err != nil {
|
||||
t.Fatalf("Could not save block: %v", err)
|
||||
}
|
||||
@@ -570,11 +622,27 @@ func TestLMDGhost_3WayChainSplitsSameHeight(t *testing.T) {
|
||||
}
|
||||
|
||||
// Give block 4 the most votes (2).
|
||||
voteTargets := make(map[uint64]*pb.BeaconBlock)
|
||||
voteTargets[0] = block2
|
||||
voteTargets[1] = block3
|
||||
voteTargets[2] = block4
|
||||
voteTargets[3] = block4
|
||||
voteTargets := make(map[uint64]*pb.AttestationTarget)
|
||||
voteTargets[0] = &pb.AttestationTarget{
|
||||
Slot: block2.Slot,
|
||||
BlockRoot: root2[:],
|
||||
ParentRoot: block2.ParentRootHash32,
|
||||
}
|
||||
voteTargets[1] = &pb.AttestationTarget{
|
||||
Slot: block3.Slot,
|
||||
BlockRoot: root3[:],
|
||||
ParentRoot: block3.ParentRootHash32,
|
||||
}
|
||||
voteTargets[2] = &pb.AttestationTarget{
|
||||
Slot: block4.Slot,
|
||||
BlockRoot: root4[:],
|
||||
ParentRoot: block4.ParentRootHash32,
|
||||
}
|
||||
voteTargets[3] = &pb.AttestationTarget{
|
||||
Slot: block4.Slot,
|
||||
BlockRoot: root4[:],
|
||||
ParentRoot: block4.ParentRootHash32,
|
||||
}
|
||||
// LMDGhost should pick block 4.
|
||||
head, err := chainService.lmdGhost(ctx, block1, beaconState, voteTargets)
|
||||
if err != nil {
|
||||
@@ -669,6 +737,10 @@ func TestLMDGhost_2WayChainSplitsDiffHeight(t *testing.T) {
|
||||
Slot: 5,
|
||||
ParentRootHash32: root3[:],
|
||||
}
|
||||
root5, err := hashutil.HashBeaconBlock(block5)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not hash block: %v", err)
|
||||
}
|
||||
if err = chainService.beaconDB.SaveBlock(block5); err != nil {
|
||||
t.Fatalf("Could not save block: %v", err)
|
||||
}
|
||||
@@ -680,6 +752,10 @@ func TestLMDGhost_2WayChainSplitsDiffHeight(t *testing.T) {
|
||||
Slot: 6,
|
||||
ParentRootHash32: root4[:],
|
||||
}
|
||||
root6, err := hashutil.HashBeaconBlock(block6)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not hash block: %v", err)
|
||||
}
|
||||
if err = chainService.beaconDB.SaveBlock(block6); err != nil {
|
||||
t.Fatalf("Could not save block: %v", err)
|
||||
}
|
||||
@@ -688,10 +764,22 @@ func TestLMDGhost_2WayChainSplitsDiffHeight(t *testing.T) {
|
||||
}
|
||||
|
||||
// Give block 5 the most votes (2).
|
||||
voteTargets := make(map[uint64]*pb.BeaconBlock)
|
||||
voteTargets[0] = block6
|
||||
voteTargets[1] = block5
|
||||
voteTargets[2] = block5
|
||||
voteTargets := make(map[uint64]*pb.AttestationTarget)
|
||||
voteTargets[0] = &pb.AttestationTarget{
|
||||
Slot: block6.Slot,
|
||||
BlockRoot: root6[:],
|
||||
ParentRoot: block6.ParentRootHash32,
|
||||
}
|
||||
voteTargets[1] = &pb.AttestationTarget{
|
||||
Slot: block5.Slot,
|
||||
BlockRoot: root5[:],
|
||||
ParentRoot: block5.ParentRootHash32,
|
||||
}
|
||||
voteTargets[2] = &pb.AttestationTarget{
|
||||
Slot: block5.Slot,
|
||||
BlockRoot: root5[:],
|
||||
ParentRoot: block5.ParentRootHash32,
|
||||
}
|
||||
// LMDGhost should pick block 5.
|
||||
head, err := chainService.lmdGhost(ctx, block1, beaconState, voteTargets)
|
||||
if err != nil {
|
||||
@@ -717,7 +805,7 @@ func BenchmarkLMDGhost_8Slots_8Validators(b *testing.B) {
|
||||
balances[i] = params.BeaconConfig().MaxDepositAmount
|
||||
}
|
||||
|
||||
chainService := setupBeaconChainBenchmark(b, false, beaconDB, true, nil)
|
||||
chainService := setupBeaconChainBenchmark(b, beaconDB)
|
||||
|
||||
// Construct 8 blocks. (Epoch length = 8)
|
||||
epochLength := uint64(8)
|
||||
@@ -758,9 +846,19 @@ func BenchmarkLMDGhost_8Slots_8Validators(b *testing.B) {
|
||||
}
|
||||
}
|
||||
|
||||
voteTargets := make(map[uint64]*pb.BeaconBlock)
|
||||
blockRoot, err := hashutil.HashBeaconBlock(block)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
voteTargets := make(map[uint64]*pb.AttestationTarget)
|
||||
target := &pb.AttestationTarget{
|
||||
Slot: block.Slot,
|
||||
BlockRoot: blockRoot[:],
|
||||
ParentRoot: block.ParentRootHash32,
|
||||
}
|
||||
for i := 0; i < validatorCount; i++ {
|
||||
voteTargets[uint64(i)] = block
|
||||
voteTargets[uint64(i)] = target
|
||||
}
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
@@ -788,7 +886,7 @@ func BenchmarkLMDGhost_32Slots_8Validators(b *testing.B) {
|
||||
balances[i] = params.BeaconConfig().MaxDepositAmount
|
||||
}
|
||||
|
||||
chainService := setupBeaconChainBenchmark(b, false, beaconDB, true, nil)
|
||||
chainService := setupBeaconChainBenchmark(b, beaconDB)
|
||||
|
||||
// Construct 8 blocks. (Epoch length = 8)
|
||||
epochLength := uint64(8)
|
||||
@@ -829,9 +927,19 @@ func BenchmarkLMDGhost_32Slots_8Validators(b *testing.B) {
|
||||
}
|
||||
}
|
||||
|
||||
voteTargets := make(map[uint64]*pb.BeaconBlock)
|
||||
blockRoot, err := hashutil.HashBeaconBlock(block)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
voteTargets := make(map[uint64]*pb.AttestationTarget)
|
||||
target := &pb.AttestationTarget{
|
||||
Slot: block.Slot,
|
||||
BlockRoot: blockRoot[:],
|
||||
ParentRoot: block.ParentRootHash32,
|
||||
}
|
||||
for i := 0; i < validatorCount; i++ {
|
||||
voteTargets[uint64(i)] = block
|
||||
voteTargets[uint64(i)] = target
|
||||
}
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
@@ -857,7 +965,7 @@ func BenchmarkLMDGhost_32Slots_64Validators(b *testing.B) {
|
||||
balances[i] = params.BeaconConfig().MaxDepositAmount
|
||||
}
|
||||
|
||||
chainService := setupBeaconChainBenchmark(b, false, beaconDB, true, nil)
|
||||
chainService := setupBeaconChainBenchmark(b, beaconDB)
|
||||
|
||||
// Construct 64 blocks. (Epoch length = 64)
|
||||
epochLength := uint64(32)
|
||||
@@ -898,9 +1006,19 @@ func BenchmarkLMDGhost_32Slots_64Validators(b *testing.B) {
|
||||
}
|
||||
}
|
||||
|
||||
voteTargets := make(map[uint64]*pb.BeaconBlock)
|
||||
blockRoot, err := hashutil.HashBeaconBlock(block)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
voteTargets := make(map[uint64]*pb.AttestationTarget)
|
||||
target := &pb.AttestationTarget{
|
||||
Slot: block.Slot,
|
||||
BlockRoot: blockRoot[:],
|
||||
ParentRoot: block.ParentRootHash32,
|
||||
}
|
||||
for i := 0; i < validatorCount; i++ {
|
||||
voteTargets[uint64(i)] = block
|
||||
voteTargets[uint64(i)] = target
|
||||
}
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
@@ -926,7 +1044,7 @@ func BenchmarkLMDGhost_64Slots_16384Validators(b *testing.B) {
|
||||
balances[i] = params.BeaconConfig().MaxDepositAmount
|
||||
}
|
||||
|
||||
chainService := setupBeaconChainBenchmark(b, false, beaconDB, true, nil)
|
||||
chainService := setupBeaconChainBenchmark(b, beaconDB)
|
||||
|
||||
// Construct 64 blocks. (Epoch length = 64)
|
||||
epochLength := uint64(64)
|
||||
@@ -967,9 +1085,19 @@ func BenchmarkLMDGhost_64Slots_16384Validators(b *testing.B) {
|
||||
}
|
||||
}
|
||||
|
||||
voteTargets := make(map[uint64]*pb.BeaconBlock)
|
||||
blockRoot, err := hashutil.HashBeaconBlock(block)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
voteTargets := make(map[uint64]*pb.AttestationTarget)
|
||||
target := &pb.AttestationTarget{
|
||||
Slot: block.Slot,
|
||||
BlockRoot: blockRoot[:],
|
||||
ParentRoot: block.ParentRootHash32,
|
||||
}
|
||||
for i := 0; i < validatorCount; i++ {
|
||||
voteTargets[uint64(i)] = block
|
||||
voteTargets[uint64(i)] = target
|
||||
}
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
@@ -980,32 +1108,19 @@ func BenchmarkLMDGhost_64Slots_16384Validators(b *testing.B) {
|
||||
}
|
||||
}
|
||||
|
||||
func setupBeaconChainBenchmark(b *testing.B, faultyPoWClient bool, beaconDB *db.BeaconDB, enablePOWChain bool, attsService *attestation.Service) *ChainService {
|
||||
endpoint := "ws://127.0.0.1"
|
||||
func setupBeaconChainBenchmark(b *testing.B, beaconDB *db.BeaconDB) *ChainService {
|
||||
ctx := context.Background()
|
||||
var web3Service *powchain.Web3Service
|
||||
var err error
|
||||
if enablePOWChain {
|
||||
if faultyPoWClient {
|
||||
client := &faultyClient{}
|
||||
web3Service, err = powchain.NewWeb3Service(ctx, &powchain.Web3ServiceConfig{
|
||||
Endpoint: endpoint,
|
||||
DepositContract: common.Address{},
|
||||
Reader: client,
|
||||
Client: client,
|
||||
Logger: client,
|
||||
})
|
||||
} else {
|
||||
client := &mockClient{}
|
||||
web3Service, err = powchain.NewWeb3Service(ctx, &powchain.Web3ServiceConfig{
|
||||
Endpoint: endpoint,
|
||||
DepositContract: common.Address{},
|
||||
Reader: client,
|
||||
Client: client,
|
||||
Logger: client,
|
||||
})
|
||||
}
|
||||
}
|
||||
client := &faultyClient{}
|
||||
web3Service, err = powchain.NewWeb3Service(ctx, &powchain.Web3ServiceConfig{
|
||||
Endpoint: endpoint,
|
||||
DepositContract: common.Address{},
|
||||
Reader: client,
|
||||
Client: client,
|
||||
Logger: client,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
b.Fatalf("unable to set up web3 service: %v", err)
|
||||
}
|
||||
@@ -1015,7 +1130,7 @@ func setupBeaconChainBenchmark(b *testing.B, faultyPoWClient bool, beaconDB *db.
|
||||
BeaconDB: beaconDB,
|
||||
Web3Service: web3Service,
|
||||
OpsPoolService: &mockOperationService{},
|
||||
AttsService: attsService,
|
||||
AttsService: nil,
|
||||
}
|
||||
if err != nil {
|
||||
b.Fatalf("could not register blockchain service: %v", err)
|
||||
@@ -1325,10 +1440,6 @@ func setupFFGTest(t *testing.T) ([32]byte, *pb.BeaconBlock, *pb.BeaconState, []*
|
||||
}
|
||||
|
||||
func TestVoteCount_CacheEnabledAndMiss(t *testing.T) {
|
||||
featureconfig.InitFeatureConfig(&featureconfig.FeatureFlagConfig{
|
||||
EnableBlockAncestorCache: true,
|
||||
})
|
||||
|
||||
beaconDB := internal.SetupDB(t)
|
||||
defer internal.TeardownDB(t, beaconDB)
|
||||
genesisBlock := b.NewGenesisBlock([]byte("stateroot"))
|
||||
@@ -1344,10 +1455,18 @@ func TestVoteCount_CacheEnabledAndMiss(t *testing.T) {
|
||||
Slot: params.BeaconConfig().GenesisSlot + 5,
|
||||
ParentRootHash32: genesisRoot[:],
|
||||
}
|
||||
pHeadHash, err := hashutil.HashBeaconBlock(potentialHead)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
potentialHead2 := &pb.BeaconBlock{
|
||||
Slot: params.BeaconConfig().GenesisSlot + 6,
|
||||
ParentRootHash32: genesisRoot[:],
|
||||
}
|
||||
pHeadHash2, err := hashutil.HashBeaconBlock(potentialHead2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// We store these potential heads in the DB.
|
||||
if err := beaconDB.SaveBlock(potentialHead); err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -1356,9 +1475,17 @@ func TestVoteCount_CacheEnabledAndMiss(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
beaconState := &pb.BeaconState{Balances: []uint64{1e9, 1e9}}
|
||||
voteTargets := make(map[uint64]*pb.BeaconBlock)
|
||||
voteTargets[0] = potentialHead
|
||||
voteTargets[1] = potentialHead2
|
||||
voteTargets := make(map[uint64]*pb.AttestationTarget)
|
||||
voteTargets[0] = &pb.AttestationTarget{
|
||||
Slot: potentialHead.Slot,
|
||||
BlockRoot: pHeadHash[:],
|
||||
ParentRoot: potentialHead.ParentRootHash32,
|
||||
}
|
||||
voteTargets[1] = &pb.AttestationTarget{
|
||||
Slot: potentialHead2.Slot,
|
||||
BlockRoot: pHeadHash2[:],
|
||||
ParentRoot: potentialHead2.ParentRootHash32,
|
||||
}
|
||||
count, err := VoteCount(genesisBlock, beaconState, voteTargets, beaconDB)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not fetch vote balances: %v", err)
|
||||
@@ -1374,17 +1501,12 @@ func TestVoteCount_CacheEnabledAndMiss(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// Verify the cached block ancestor is genesis block.
|
||||
h, _ = hashutil.HashBeaconBlock(cachedInfo.Block)
|
||||
if h != genesisRoot {
|
||||
if bytesutil.ToBytes32(cachedInfo.Target.BlockRoot) != genesisRoot {
|
||||
t.Error("could not retrieve the correct ancestor block")
|
||||
}
|
||||
}
|
||||
|
||||
func TestVoteCount_CacheEnabledAndHit(t *testing.T) {
|
||||
featureconfig.InitFeatureConfig(&featureconfig.FeatureFlagConfig{
|
||||
EnableBlockAncestorCache: true,
|
||||
})
|
||||
|
||||
genesisBlock := b.NewGenesisBlock([]byte("stateroot"))
|
||||
genesisRoot, err := hashutil.HashBeaconBlock(genesisBlock)
|
||||
if err != nil {
|
||||
@@ -1403,20 +1525,30 @@ func TestVoteCount_CacheEnabledAndHit(t *testing.T) {
|
||||
pHeadHash2, _ := hashutil.HashBeaconBlock(potentialHead2)
|
||||
|
||||
beaconState := &pb.BeaconState{Balances: []uint64{1e9, 1e9}}
|
||||
voteTargets := make(map[uint64]*pb.BeaconBlock)
|
||||
voteTargets[0] = potentialHead
|
||||
voteTargets[1] = potentialHead2
|
||||
voteTargets := make(map[uint64]*pb.AttestationTarget)
|
||||
voteTargets[0] = &pb.AttestationTarget{
|
||||
Slot: potentialHead.Slot,
|
||||
BlockRoot: pHeadHash[:],
|
||||
ParentRoot: potentialHead.ParentRootHash32,
|
||||
}
|
||||
voteTargets[1] = &pb.AttestationTarget{
|
||||
Slot: potentialHead2.Slot,
|
||||
BlockRoot: pHeadHash2[:],
|
||||
ParentRoot: potentialHead2.ParentRootHash32,
|
||||
}
|
||||
|
||||
aInfo := &cache.AncestorInfo{
|
||||
Height: genesisBlock.Slot,
|
||||
Hash: pHeadHash[:],
|
||||
Block: genesisBlock,
|
||||
Target: &pb.AttestationTarget{
|
||||
Slot: genesisBlock.Slot,
|
||||
BlockRoot: genesisRoot[:],
|
||||
ParentRoot: genesisBlock.ParentRootHash32,
|
||||
},
|
||||
}
|
||||
// Presave cached ancestor blocks before running vote count.
|
||||
if err := blkAncestorCache.AddBlockAncestor(aInfo); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
aInfo.Hash = pHeadHash2[:]
|
||||
aInfo.Target.BlockRoot = pHeadHash2[:]
|
||||
if err := blkAncestorCache.AddBlockAncestor(aInfo); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ type ChainService struct {
|
||||
p2p p2p.Broadcaster
|
||||
canonicalBlocks map[uint64][]byte
|
||||
canonicalBlocksLock sync.RWMutex
|
||||
receiveBlockLock sync.Mutex
|
||||
}
|
||||
|
||||
// Config options for the service.
|
||||
@@ -147,12 +148,24 @@ func (c *ChainService) initializeBeaconChain(genesisTime time.Time, deposits []*
|
||||
return nil, fmt.Errorf("could not hash beacon state: %v", err)
|
||||
}
|
||||
genBlock := b.NewGenesisBlock(stateRoot[:])
|
||||
genBlockRoot, err := hashutil.HashBeaconBlock(genBlock)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not hash beacon block: %v", err)
|
||||
}
|
||||
|
||||
// TODO(#2011): Remove this in state caching.
|
||||
beaconState.LatestBlock = genBlock
|
||||
|
||||
if err := c.beaconDB.SaveBlock(genBlock); err != nil {
|
||||
return nil, fmt.Errorf("could not save genesis block to disk: %v", err)
|
||||
}
|
||||
if err := c.beaconDB.SaveAttestationTarget(ctx, &pb.AttestationTarget{
|
||||
Slot: genBlock.Slot,
|
||||
BlockRoot: genBlockRoot[:],
|
||||
ParentRoot: genBlock.ParentRootHash32,
|
||||
}); err != nil {
|
||||
return nil, fmt.Errorf("failed to save attestation target: %v", err)
|
||||
}
|
||||
if err := c.beaconDB.UpdateChainHead(ctx, genBlock, beaconState); err != nil {
|
||||
return nil, fmt.Errorf("could not set chain head, %v", err)
|
||||
}
|
||||
|
||||
@@ -206,7 +206,7 @@ func createRandaoReveal(t *testing.T, beaconState *pb.BeaconState, privKeys []*b
|
||||
return epochSignature.Marshal()
|
||||
}
|
||||
|
||||
func setupGenesisBlock(t *testing.T, cs *ChainService, beaconState *pb.BeaconState) ([32]byte, *pb.BeaconBlock) {
|
||||
func setupGenesisBlock(t *testing.T, cs *ChainService) ([32]byte, *pb.BeaconBlock) {
|
||||
genesis := b.NewGenesisBlock([]byte{})
|
||||
if err := cs.beaconDB.SaveBlock(genesis); err != nil {
|
||||
t.Fatalf("could not save block to db: %v", err)
|
||||
@@ -307,7 +307,6 @@ func TestChainStartStop_Initialized(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
db := internal.SetupDB(t)
|
||||
defer internal.TeardownDB(t, db)
|
||||
ctx := context.Background()
|
||||
|
||||
chainService := setupBeaconChain(t, db, nil)
|
||||
|
||||
@@ -316,11 +315,7 @@ func TestChainStartStop_Initialized(t *testing.T) {
|
||||
if err := db.InitializeState(context.Background(), unixTime, deposits, &pb.Eth1Data{}); err != nil {
|
||||
t.Fatalf("Could not initialize beacon state to disk: %v", err)
|
||||
}
|
||||
beaconState, err := db.HeadState(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not fetch beacon state: %v", err)
|
||||
}
|
||||
setupGenesisBlock(t, chainService, beaconState)
|
||||
setupGenesisBlock(t, chainService)
|
||||
// Test the start function.
|
||||
chainService.Start()
|
||||
|
||||
|
||||
@@ -15,9 +15,10 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
featureconfig.InitFeatureConfig(&featureconfig.FeatureFlagConfig{})
|
||||
featureconfig.InitFeatureConfig(&featureconfig.FeatureFlagConfig{
|
||||
CacheTreeHash: false,
|
||||
})
|
||||
}
|
||||
|
||||
func TestGenerateState_OK(t *testing.T) {
|
||||
b, err := backend.NewSimulatedBackend()
|
||||
if err != nil {
|
||||
|
||||
4
beacon-chain/cache/block.go
vendored
4
beacon-chain/cache/block.go
vendored
@@ -32,9 +32,9 @@ var (
|
||||
|
||||
// AncestorInfo defines the cached ancestor block object for height.
|
||||
type AncestorInfo struct {
|
||||
Hash []byte
|
||||
Height uint64
|
||||
Block *pb.BeaconBlock
|
||||
Hash []byte
|
||||
Target *pb.AttestationTarget
|
||||
}
|
||||
|
||||
// AncestorBlockCache structs with 1 queue for looking up block ancestor by height.
|
||||
|
||||
24
beacon-chain/cache/block_test.go
vendored
24
beacon-chain/cache/block_test.go
vendored
@@ -14,6 +14,10 @@ func TestHeightHeightFn_OK(t *testing.T) {
|
||||
aInfo := &AncestorInfo{
|
||||
Height: height,
|
||||
Hash: hash,
|
||||
Target: &pb.AttestationTarget{
|
||||
Slot: height,
|
||||
BlockRoot: hash,
|
||||
},
|
||||
}
|
||||
|
||||
key, err := heightKeyFn(aInfo)
|
||||
@@ -21,7 +25,7 @@ func TestHeightHeightFn_OK(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
strHeightKey := string(aInfo.Hash) + strconv.Itoa(int(aInfo.Height))
|
||||
strHeightKey := string(aInfo.Target.BlockRoot) + strconv.Itoa(int(aInfo.Target.Slot))
|
||||
if key != strHeightKey {
|
||||
t.Errorf("Incorrect hash key: %s, expected %s", key, strHeightKey)
|
||||
}
|
||||
@@ -42,7 +46,10 @@ func TestAncestorCache_AncestorInfoByHeight(t *testing.T) {
|
||||
aInfo := &AncestorInfo{
|
||||
Height: height,
|
||||
Hash: hash,
|
||||
Block: &pb.BeaconBlock{Slot: height},
|
||||
Target: &pb.AttestationTarget{
|
||||
Slot: height,
|
||||
BlockRoot: hash,
|
||||
},
|
||||
}
|
||||
|
||||
fetchedInfo, err := cache.AncestorBySlot(hash, height)
|
||||
@@ -66,15 +73,15 @@ func TestAncestorCache_AncestorInfoByHeight(t *testing.T) {
|
||||
if fetchedInfo.Height != height {
|
||||
t.Errorf(
|
||||
"Expected fetched slot number to be %d, got %d",
|
||||
aInfo.Height,
|
||||
fetchedInfo.Height,
|
||||
aInfo.Target.Slot,
|
||||
fetchedInfo.Target.Slot,
|
||||
)
|
||||
}
|
||||
if !reflect.DeepEqual(fetchedInfo.Block, aInfo.Block) {
|
||||
if !reflect.DeepEqual(fetchedInfo.Target, aInfo.Target) {
|
||||
t.Errorf(
|
||||
"Expected fetched info committee to be %v, got %v",
|
||||
aInfo.Block,
|
||||
fetchedInfo.Block,
|
||||
aInfo.Target,
|
||||
fetchedInfo.Target,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -85,6 +92,9 @@ func TestBlockAncestor_maxSize(t *testing.T) {
|
||||
for i := 0; i < maxCacheSize+10; i++ {
|
||||
aInfo := &AncestorInfo{
|
||||
Height: uint64(i),
|
||||
Target: &pb.AttestationTarget{
|
||||
Slot: uint64(i),
|
||||
},
|
||||
}
|
||||
if err := cache.AddBlockAncestor(aInfo); err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
@@ -6,7 +6,6 @@ go_library(
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/core/balances",
|
||||
visibility = ["//beacon-chain:__subpackages__"],
|
||||
deps = [
|
||||
"//beacon-chain/core/blocks:go_default_library",
|
||||
"//beacon-chain/core/epoch:go_default_library",
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
@@ -42,7 +41,7 @@ func ExpectedFFGSource(
|
||||
totalBalance
|
||||
}
|
||||
activeValidatorIndices := helpers.ActiveValidatorIndices(state, helpers.CurrentEpoch(state))
|
||||
didNotAttestIndices := sliceutil.Not(justifiedAttesterIndices, activeValidatorIndices)
|
||||
didNotAttestIndices := sliceutil.NotUint64(justifiedAttesterIndices, activeValidatorIndices)
|
||||
|
||||
for _, index := range didNotAttestIndices {
|
||||
state.Balances[index] -=
|
||||
@@ -78,7 +77,7 @@ func ExpectedFFGTarget(
|
||||
totalBalance
|
||||
}
|
||||
activeValidatorIndices := helpers.ActiveValidatorIndices(state, helpers.CurrentEpoch(state))
|
||||
didNotAttestIndices := sliceutil.Not(boundaryAttesterIndices, activeValidatorIndices)
|
||||
didNotAttestIndices := sliceutil.NotUint64(boundaryAttesterIndices, activeValidatorIndices)
|
||||
|
||||
for _, index := range didNotAttestIndices {
|
||||
state.Balances[index] -=
|
||||
@@ -114,7 +113,7 @@ func ExpectedBeaconChainHead(
|
||||
totalBalance
|
||||
}
|
||||
activeValidatorIndices := helpers.ActiveValidatorIndices(state, helpers.CurrentEpoch(state))
|
||||
didNotAttestIndices := sliceutil.Not(headAttesterIndices, activeValidatorIndices)
|
||||
didNotAttestIndices := sliceutil.NotUint64(headAttesterIndices, activeValidatorIndices)
|
||||
|
||||
for _, index := range didNotAttestIndices {
|
||||
state.Balances[index] -=
|
||||
@@ -134,14 +133,15 @@ func ExpectedBeaconChainHead(
|
||||
func InclusionDistance(
|
||||
state *pb.BeaconState,
|
||||
attesterIndices []uint64,
|
||||
totalBalance uint64) (*pb.BeaconState, error) {
|
||||
totalBalance uint64,
|
||||
inclusionDistanceByAttester map[uint64]uint64) (*pb.BeaconState, error) {
|
||||
|
||||
baseRewardQuotient := helpers.BaseRewardQuotient(totalBalance)
|
||||
|
||||
for _, index := range attesterIndices {
|
||||
inclusionDistance, err := epoch.InclusionDistance(state, index)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get inclusion distance: %v", err)
|
||||
inclusionDistance, ok := inclusionDistanceByAttester[index]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("could not get inclusion distance for attester: %d", index)
|
||||
}
|
||||
if inclusionDistance == 0 {
|
||||
return nil, errors.New("could not process inclusion distance: 0")
|
||||
@@ -169,7 +169,7 @@ func InactivityFFGSource(
|
||||
|
||||
baseRewardQuotient := helpers.BaseRewardQuotient(totalBalance)
|
||||
activeValidatorIndices := helpers.ActiveValidatorIndices(state, helpers.CurrentEpoch(state))
|
||||
didNotAttestIndices := sliceutil.Not(justifiedAttesterIndices, activeValidatorIndices)
|
||||
didNotAttestIndices := sliceutil.NotUint64(justifiedAttesterIndices, activeValidatorIndices)
|
||||
|
||||
for _, index := range didNotAttestIndices {
|
||||
state.Balances[index] -=
|
||||
@@ -193,7 +193,7 @@ func InactivityFFGTarget(
|
||||
|
||||
baseRewardQuotient := helpers.BaseRewardQuotient(totalBalance)
|
||||
activeValidatorIndices := helpers.ActiveValidatorIndices(state, helpers.CurrentEpoch(state))
|
||||
didNotAttestIndices := sliceutil.Not(boundaryAttesterIndices, activeValidatorIndices)
|
||||
didNotAttestIndices := sliceutil.NotUint64(boundaryAttesterIndices, activeValidatorIndices)
|
||||
|
||||
for _, index := range didNotAttestIndices {
|
||||
state.Balances[index] -=
|
||||
@@ -216,7 +216,7 @@ func InactivityChainHead(
|
||||
|
||||
baseRewardQuotient := helpers.BaseRewardQuotient(totalBalance)
|
||||
activeValidatorIndices := helpers.ActiveValidatorIndices(state, helpers.CurrentEpoch(state))
|
||||
didNotAttestIndices := sliceutil.Not(headAttesterIndices, activeValidatorIndices)
|
||||
didNotAttestIndices := sliceutil.NotUint64(headAttesterIndices, activeValidatorIndices)
|
||||
|
||||
for _, index := range didNotAttestIndices {
|
||||
state.Balances[index] -=
|
||||
@@ -261,14 +261,14 @@ func InactivityExitedPenalties(
|
||||
func InactivityInclusionDistance(
|
||||
state *pb.BeaconState,
|
||||
attesterIndices []uint64,
|
||||
totalBalance uint64) (*pb.BeaconState, error) {
|
||||
|
||||
totalBalance uint64,
|
||||
inclusionDistanceByAttester map[uint64]uint64) (*pb.BeaconState, error) {
|
||||
baseRewardQuotient := helpers.BaseRewardQuotient(totalBalance)
|
||||
|
||||
for _, index := range attesterIndices {
|
||||
inclusionDistance, err := epoch.InclusionDistance(state, index)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get inclusion distance: %v", err)
|
||||
inclusionDistance, ok := inclusionDistanceByAttester[index]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("could not get inclusion distance for attester: %d", index)
|
||||
}
|
||||
baseReward := helpers.BaseReward(state, index, baseRewardQuotient)
|
||||
state.Balances[index] -= baseReward -
|
||||
@@ -290,18 +290,19 @@ func InactivityInclusionDistance(
|
||||
func AttestationInclusion(
|
||||
state *pb.BeaconState,
|
||||
totalBalance uint64,
|
||||
prevEpochAttesterIndices []uint64) (*pb.BeaconState, error) {
|
||||
prevEpochAttesterIndices []uint64,
|
||||
inclusionSlotByAttester map[uint64]uint64) (*pb.BeaconState, error) {
|
||||
|
||||
baseRewardQuotient := helpers.BaseRewardQuotient(totalBalance)
|
||||
for _, index := range prevEpochAttesterIndices {
|
||||
// Get the attestation's inclusion slot using the attestor's index.
|
||||
slot, err := blocks.AttsInclusionSlot(index)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get inclusion slot: %v", err)
|
||||
slot, ok := inclusionSlotByAttester[index]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("could not get inclusion slot for attester: %d", index)
|
||||
}
|
||||
proposerIndex, err := helpers.BeaconProposerIndex(state, slot)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get propoer index: %v", err)
|
||||
return nil, fmt.Errorf("could not get proposer index: %v", err)
|
||||
}
|
||||
state.Balances[proposerIndex] +=
|
||||
helpers.BaseReward(state, proposerIndex, baseRewardQuotient) /
|
||||
@@ -365,7 +366,7 @@ func Crosslinks(
|
||||
}
|
||||
for _, index := range committee {
|
||||
baseReward := helpers.BaseReward(state, index, baseRewardQuotient)
|
||||
if sliceutil.IsIn(index, attestingIndices) {
|
||||
if sliceutil.IsInUint64(index, attestingIndices) {
|
||||
state.Balances[index] +=
|
||||
baseReward * totalAttestingBalance / totalBalance
|
||||
} else {
|
||||
|
||||
@@ -140,10 +140,16 @@ func TestInclusionDistRewards_AccurateRewards(t *testing.T) {
|
||||
participationBitfield = append(participationBitfield, byte(0xff))
|
||||
}
|
||||
|
||||
attestation := []*pb.PendingAttestation{
|
||||
{Data: &pb.AttestationData{Slot: params.BeaconConfig().GenesisSlot},
|
||||
attestations := []*pb.PendingAttestation{
|
||||
{Data: &pb.AttestationData{
|
||||
Slot: params.BeaconConfig().GenesisSlot,
|
||||
JustifiedBlockRootHash32: []byte{},
|
||||
Shard: 0,
|
||||
CrosslinkDataRootHash32: params.BeaconConfig().ZeroHash[:],
|
||||
},
|
||||
AggregationBitfield: participationBitfield,
|
||||
InclusionSlot: params.BeaconConfig().GenesisSlot + 5},
|
||||
InclusionSlot: params.BeaconConfig().GenesisSlot + 5,
|
||||
},
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
@@ -158,15 +164,39 @@ func TestInclusionDistRewards_AccurateRewards(t *testing.T) {
|
||||
validatorBalances[i] = params.BeaconConfig().MaxDepositAmount
|
||||
}
|
||||
state := &pb.BeaconState{
|
||||
Slot: params.BeaconConfig().GenesisSlot,
|
||||
ValidatorRegistry: validators,
|
||||
Balances: validatorBalances,
|
||||
LatestAttestations: attestation,
|
||||
Slot: params.BeaconConfig().GenesisSlot + 5,
|
||||
ValidatorRegistry: validators,
|
||||
Balances: validatorBalances,
|
||||
LatestAttestations: attestations,
|
||||
PreviousJustifiedRoot: []byte{},
|
||||
LatestCrosslinks: []*pb.Crosslink{
|
||||
{
|
||||
CrosslinkDataRootHash32: params.BeaconConfig().ZeroHash[:],
|
||||
Epoch: params.BeaconConfig().GenesisEpoch,
|
||||
},
|
||||
},
|
||||
}
|
||||
block := &pb.BeaconBlock{
|
||||
Body: &pb.BeaconBlockBody{
|
||||
Attestations: []*pb.Attestation{
|
||||
{
|
||||
Data: attestations[0].Data,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
if _, err := blocks.ProcessBlockAttestations(state, block, false /* verify sig */); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
inclusionMap := make(map[uint64]uint64)
|
||||
for _, voted := range tt.voted {
|
||||
inclusionMap[voted] = state.Slot
|
||||
}
|
||||
state, err := InclusionDistance(
|
||||
state,
|
||||
tt.voted,
|
||||
uint64(len(validatorBalances))*params.BeaconConfig().MaxDepositAmount)
|
||||
uint64(len(validatorBalances))*params.BeaconConfig().MaxDepositAmount,
|
||||
inclusionMap)
|
||||
if err != nil {
|
||||
t.Fatalf("could not execute InclusionDistRewards:%v", err)
|
||||
}
|
||||
@@ -206,7 +236,8 @@ func TestInclusionDistRewards_OutOfBounds(t *testing.T) {
|
||||
ValidatorRegistry: validators,
|
||||
LatestAttestations: attestation,
|
||||
}
|
||||
_, err := InclusionDistance(state, tt.voted, 0)
|
||||
inclusionMap := make(map[uint64]uint64)
|
||||
_, err := InclusionDistance(state, tt.voted, 0, inclusionMap)
|
||||
if err == nil {
|
||||
t.Fatal("InclusionDistRewards should have failed")
|
||||
}
|
||||
@@ -397,10 +428,15 @@ func TestInactivityInclusionPenalty_AccuratePenalties(t *testing.T) {
|
||||
Balances: validatorBalances,
|
||||
LatestAttestations: attestation,
|
||||
}
|
||||
inclusionMap := make(map[uint64]uint64)
|
||||
for _, voted := range tt.voted {
|
||||
inclusionMap[voted] = state.Slot + 1
|
||||
}
|
||||
state, err := InactivityInclusionDistance(
|
||||
state,
|
||||
tt.voted,
|
||||
uint64(len(validatorBalances))*params.BeaconConfig().MaxDepositAmount)
|
||||
uint64(len(validatorBalances))*params.BeaconConfig().MaxDepositAmount,
|
||||
inclusionMap)
|
||||
|
||||
for _, i := range tt.voted {
|
||||
validatorBalances[i] = 32000055555
|
||||
@@ -439,7 +475,8 @@ func TestInactivityInclusionPenalty_OutOfBounds(t *testing.T) {
|
||||
ValidatorRegistry: validators,
|
||||
LatestAttestations: attestation,
|
||||
}
|
||||
_, err := InactivityInclusionDistance(state, tt.voted, 0)
|
||||
inclusionMap := make(map[uint64]uint64)
|
||||
_, err := InactivityInclusionDistance(state, tt.voted, 0, inclusionMap)
|
||||
if err == nil {
|
||||
t.Fatal("InclusionDistRewards should have failed")
|
||||
}
|
||||
@@ -497,10 +534,16 @@ func TestAttestationInclusionRewards_AccurateRewards(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
inclusionMap := make(map[uint64]uint64)
|
||||
for _, voted := range tt.voted {
|
||||
inclusionMap[voted] = state.Slot
|
||||
}
|
||||
|
||||
state, err = AttestationInclusion(
|
||||
state,
|
||||
uint64(len(validatorBalances))*params.BeaconConfig().MaxDepositAmount,
|
||||
tt.voted)
|
||||
tt.voted,
|
||||
inclusionMap)
|
||||
|
||||
for _, i := range tt.voted {
|
||||
validatorBalances[i] = 32000008680
|
||||
@@ -539,7 +582,8 @@ func TestAttestationInclusionRewards_NoInclusionSlot(t *testing.T) {
|
||||
ValidatorRegistry: validators,
|
||||
Balances: validatorBalances,
|
||||
}
|
||||
if _, err := AttestationInclusion(state, 0, tt.voted); err == nil {
|
||||
inclusionMap := make(map[uint64]uint64)
|
||||
if _, err := AttestationInclusion(state, 0, tt.voted, inclusionMap); err == nil {
|
||||
t.Fatal("AttestationInclusionRewards should have failed with no inclusion slot")
|
||||
}
|
||||
}
|
||||
@@ -575,7 +619,8 @@ func TestAttestationInclusionRewards_NoProposerIndex(t *testing.T) {
|
||||
Balances: validatorBalances,
|
||||
LatestAttestations: attestation,
|
||||
}
|
||||
if _, err := AttestationInclusion(state, 0, tt.voted); err == nil {
|
||||
inclusionMap := make(map[uint64]uint64)
|
||||
if _, err := AttestationInclusion(state, 0, tt.voted, inclusionMap); err == nil {
|
||||
t.Fatal("AttestationInclusionRewards should have failed with no proposer index")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ go_library(
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks",
|
||||
visibility = ["//beacon-chain:__subpackages__"],
|
||||
deps = [
|
||||
"//beacon-chain/cache:go_default_library",
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/core/state/stateutils:go_default_library",
|
||||
"//beacon-chain/core/validators:go_default_library",
|
||||
@@ -42,6 +41,7 @@ go_test(
|
||||
"//beacon-chain/core/state:go_default_library",
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/bls:go_default_library",
|
||||
"//shared/featureconfig:go_default_library",
|
||||
"//shared/forkutil:go_default_library",
|
||||
"//shared/hashutil:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
|
||||
@@ -9,10 +9,8 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/state/stateutils"
|
||||
v "github.com/prysmaticlabs/prysm/beacon-chain/core/validators"
|
||||
@@ -25,24 +23,6 @@ import (
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var committeeCache = cache.NewCommitteesCache()
|
||||
|
||||
type attesterInclusionStore struct {
|
||||
slotLock sync.RWMutex
|
||||
distLock sync.RWMutex
|
||||
// attesterInclusion is a mapping that tracks when an attester's attestation
|
||||
// last get included in beacon chain.
|
||||
attesterInclusionSlot map[uint64]uint64
|
||||
// attesterInclusion is a mapping that tracks the difference in slot number
|
||||
// of when attestation gets submitted and when it gets included.
|
||||
attesterInclusionDist map[uint64]uint64
|
||||
}
|
||||
|
||||
var attsInclStore = attesterInclusionStore{
|
||||
attesterInclusionSlot: make(map[uint64]uint64),
|
||||
attesterInclusionDist: make(map[uint64]uint64),
|
||||
}
|
||||
|
||||
// VerifyProposerSignature uses BLS signature verification to ensure
|
||||
// the correct proposer created an incoming beacon block during state
|
||||
// transition processing.
|
||||
@@ -437,38 +417,6 @@ func ProcessBlockAttestations(
|
||||
return nil, fmt.Errorf("could not verify attestation at index %d in block: %v", idx, err)
|
||||
}
|
||||
|
||||
var IndicesInCommittee []uint64
|
||||
// get the validator indices from the attestation using committees info cache.
|
||||
cachedCommittees, err := committeeCache.CommitteesInfoBySlot(attestation.Data.Slot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if cachedCommittees == nil {
|
||||
crosslinkCommittees, err := helpers.CrosslinkCommitteesAtSlot(beaconState, attestation.Data.Slot, false /* registryChange */)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cachedCommittees = helpers.ToCommitteeCache(attestation.Data.Slot, crosslinkCommittees)
|
||||
if err := committeeCache.AddCommittees(cachedCommittees); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
for _, v := range cachedCommittees.Committees {
|
||||
if v.Shard == attestation.Data.Shard {
|
||||
IndicesInCommittee = v.Committee
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
attsInclStore.slotLock.Lock()
|
||||
attsInclStore.distLock.Lock()
|
||||
defer attsInclStore.slotLock.Unlock()
|
||||
defer attsInclStore.distLock.Unlock()
|
||||
for _, index := range IndicesInCommittee {
|
||||
attsInclStore.attesterInclusionSlot[index] = beaconState.Slot
|
||||
attsInclStore.attesterInclusionDist[index] = beaconState.Slot - attestation.Data.Slot
|
||||
}
|
||||
|
||||
beaconState.LatestAttestations = append(beaconState.LatestAttestations, &pb.PendingAttestation{
|
||||
Data: attestation.Data,
|
||||
AggregationBitfield: attestation.AggregationBitfield,
|
||||
@@ -759,25 +707,3 @@ func verifyExit(beaconState *pb.BeaconState, exit *pb.VoluntaryExit, verifySigna
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AttsInclusionSlot returns the slot of when an attestator's attestation last gets included
|
||||
// in the beacon chain by a proposer.
|
||||
func AttsInclusionSlot(index uint64) (uint64, error) {
|
||||
attsInclStore.slotLock.RLock()
|
||||
attsInclStore.slotLock.RUnlock()
|
||||
if slot, ok := attsInclStore.attesterInclusionSlot[index]; ok {
|
||||
return slot, nil
|
||||
}
|
||||
return 0, fmt.Errorf("no inclusion slot for attestor %d", index)
|
||||
}
|
||||
|
||||
// AttsInclusionDistance returns diff in slot of when an attestator's attestation gets submitted
|
||||
// and included.
|
||||
func AttsInclusionDistance(index uint64) (uint64, error) {
|
||||
attsInclStore.distLock.RLock()
|
||||
attsInclStore.distLock.RUnlock()
|
||||
if slot, ok := attsInclStore.attesterInclusionDist[index]; ok {
|
||||
return slot, nil
|
||||
}
|
||||
return 0, fmt.Errorf("no inclusion distance for attestor %d", index)
|
||||
}
|
||||
|
||||
@@ -15,12 +15,19 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bls"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/forkutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/ssz"
|
||||
"github.com/prysmaticlabs/prysm/shared/trieutil"
|
||||
)
|
||||
|
||||
func init() {
|
||||
featureconfig.InitFeatureConfig(&featureconfig.FeatureFlagConfig{
|
||||
CacheTreeHash: false,
|
||||
})
|
||||
}
|
||||
|
||||
func setupInitialDeposits(t *testing.T, numDeposits int) ([]*pb.Deposit, []*bls.SecretKey) {
|
||||
privKeys := make([]*bls.SecretKey, numDeposits)
|
||||
deposits := make([]*pb.Deposit, numDeposits)
|
||||
|
||||
@@ -65,29 +65,6 @@ func InclusionSlot(state *pb.BeaconState, validatorIndex uint64) (uint64, error)
|
||||
return lowestSlotIncluded, nil
|
||||
}
|
||||
|
||||
// InclusionDistance returns the difference in slot number of when attestation
|
||||
// gets submitted and when it gets included.
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
// Let inclusion_distance(state, index) =
|
||||
// a.slot_included - a.data.slot where a is the above attestation same as
|
||||
// inclusion_slot.
|
||||
func InclusionDistance(state *pb.BeaconState, validatorIndex uint64) (uint64, error) {
|
||||
|
||||
for _, attestation := range state.LatestAttestations {
|
||||
participatedValidators, err := helpers.AttestationParticipants(state, attestation.Data, attestation.AggregationBitfield)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("could not get attestation participants: %v", err)
|
||||
}
|
||||
for _, index := range participatedValidators {
|
||||
if index == validatorIndex {
|
||||
return attestation.InclusionSlot - attestation.Data.Slot, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0, fmt.Errorf("could not find inclusion distance for validator index %d", validatorIndex)
|
||||
}
|
||||
|
||||
// AttestingValidators returns the validators of the winning root.
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
|
||||
@@ -254,53 +254,3 @@ func TestInclusionSlot_SlotNotFound(t *testing.T) {
|
||||
t.Errorf("Expected %s, received %v", want, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInclusionDistance_CorrectDistance(t *testing.T) {
|
||||
state := buildState(params.BeaconConfig().GenesisSlot, params.BeaconConfig().DepositsForChainStart)
|
||||
var participationBitfield []byte
|
||||
for i := 0; i < 16; i++ {
|
||||
participationBitfield = append(participationBitfield, byte(0xff))
|
||||
}
|
||||
|
||||
state.LatestAttestations = []*pb.PendingAttestation{
|
||||
{Data: &pb.AttestationData{Slot: params.BeaconConfig().GenesisSlot},
|
||||
AggregationBitfield: participationBitfield,
|
||||
InclusionSlot: params.BeaconConfig().GenesisSlot + 100},
|
||||
}
|
||||
distance, err := InclusionDistance(state, 251)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not execute InclusionDistance: %v", err)
|
||||
}
|
||||
|
||||
// Inclusion distance is 100 because input validator index is 45,
|
||||
// validator 45's attested slot 0 and got included slot 100.
|
||||
if distance != 100 {
|
||||
t.Errorf("Incorrect distance. Wanted: %d, got: %d",
|
||||
100, distance)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInclusionDistance_InvalidBitfield(t *testing.T) {
|
||||
state := buildState(params.BeaconConfig().GenesisSlot, params.BeaconConfig().DepositsForChainStart)
|
||||
|
||||
state.LatestAttestations = []*pb.PendingAttestation{
|
||||
{Data: &pb.AttestationData{Slot: params.BeaconConfig().GenesisSlot},
|
||||
AggregationBitfield: []byte{},
|
||||
InclusionSlot: 100},
|
||||
}
|
||||
|
||||
want := fmt.Sprintf("wanted participants bitfield length %d, got: %d", 16, 0)
|
||||
if _, err := InclusionDistance(state, 0); !strings.Contains(err.Error(), want) {
|
||||
t.Errorf("Expected %s, received %v", want, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInclusionDistance_NotFound(t *testing.T) {
|
||||
state := buildState(0, params.BeaconConfig().SlotsPerEpoch)
|
||||
|
||||
badIndex := uint64(10000)
|
||||
want := fmt.Sprintf("could not find inclusion distance for validator index %d", badIndex)
|
||||
if _, err := InclusionDistance(state, badIndex); !strings.Contains(err.Error(), want) {
|
||||
t.Errorf("Expected %s, received %v", want, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ go_test(
|
||||
deps = [
|
||||
"//beacon-chain/cache:go_default_library",
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/featureconfig:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"@com_github_gogo_protobuf//proto:go_default_library",
|
||||
"@org_golang_google_grpc//codes:go_default_library",
|
||||
|
||||
@@ -363,7 +363,7 @@ func VerifyBitfield(bitfield []byte, committeeSize int) (bool, error) {
|
||||
// * ``assignment[0]`` is the list of validators in the committee
|
||||
// * ``assignment[1]`` is the shard to which the committee is assigned
|
||||
// * ``assignment[2]`` is the slot at which the committee is assigned
|
||||
// * ``assignment[3]`` is a bool signalling if the validator is expected to propose
|
||||
// * ``assignment[3]`` is a bool signaling if the validator is expected to propose
|
||||
// a beacon block at the assigned slot.
|
||||
// """
|
||||
// previous_epoch = get_previous_epoch(state)
|
||||
|
||||
@@ -6,9 +6,16 @@ import (
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
|
||||
func init() {
|
||||
featureconfig.InitFeatureConfig(&featureconfig.FeatureFlagConfig{
|
||||
CacheTreeHash: false,
|
||||
})
|
||||
}
|
||||
|
||||
func TestEncodeDecodeDepositInput_Ok(t *testing.T) {
|
||||
input := &pb.DepositInput{
|
||||
Pubkey: []byte("key"),
|
||||
|
||||
@@ -8,14 +8,20 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
|
||||
func init() {
|
||||
featureconfig.InitFeatureConfig(&featureconfig.FeatureFlagConfig{
|
||||
CacheTreeHash: false,
|
||||
})
|
||||
}
|
||||
|
||||
func TestGenesisBeaconState_OK(t *testing.T) {
|
||||
if params.BeaconConfig().SlotsPerEpoch != 64 {
|
||||
t.Errorf("SlotsPerEpoch should be 64 for these tests to pass")
|
||||
|
||||
@@ -223,6 +223,9 @@ func ProcessEpoch(ctx context.Context, state *pb.BeaconState, block *pb.BeaconBl
|
||||
prevEpochHeadAttestations := []*pb.PendingAttestation{}
|
||||
prevEpochHeadAttesterIndices := []uint64{}
|
||||
|
||||
inclusionSlotByAttester := make(map[uint64]uint64)
|
||||
inclusionDistanceByAttester := make(map[uint64]uint64)
|
||||
|
||||
for _, attestation := range state.LatestAttestations {
|
||||
|
||||
// We determine the attestation participants.
|
||||
@@ -234,6 +237,11 @@ func ProcessEpoch(ctx context.Context, state *pb.BeaconState, block *pb.BeaconBl
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, participant := range attesterIndices {
|
||||
inclusionDistanceByAttester[participant] = state.Slot - attestation.Data.Slot
|
||||
inclusionSlotByAttester[participant] = attestation.InclusionSlot
|
||||
}
|
||||
|
||||
// We extract the attestations from the current epoch.
|
||||
if currentEpoch == helpers.SlotToEpoch(attestation.Data.Slot) {
|
||||
currentEpochAttestations = append(currentEpochAttestations, attestation)
|
||||
@@ -248,14 +256,14 @@ func ProcessEpoch(ctx context.Context, state *pb.BeaconState, block *pb.BeaconBl
|
||||
sameRoot := bytes.Equal(attestationData.EpochBoundaryRootHash32, boundaryBlockRoot)
|
||||
if sameRoot {
|
||||
currentEpochBoundaryAttestations = append(currentEpochBoundaryAttestations, attestation)
|
||||
currentBoundaryAttesterIndices = sliceutil.Union(currentBoundaryAttesterIndices, attesterIndices)
|
||||
currentBoundaryAttesterIndices = sliceutil.UnionUint64(currentBoundaryAttesterIndices, attesterIndices)
|
||||
}
|
||||
}
|
||||
|
||||
// We extract the attestations from the previous epoch.
|
||||
if prevEpoch == helpers.SlotToEpoch(attestation.Data.Slot) {
|
||||
prevEpochAttestations = append(prevEpochAttestations, attestation)
|
||||
prevEpochAttesterIndices = sliceutil.Union(prevEpochAttesterIndices, attesterIndices)
|
||||
prevEpochAttesterIndices = sliceutil.UnionUint64(prevEpochAttesterIndices, attesterIndices)
|
||||
|
||||
// We extract the previous epoch boundary attestations.
|
||||
prevBoundaryBlockRoot, err := b.BlockRoot(state,
|
||||
@@ -265,7 +273,7 @@ func ProcessEpoch(ctx context.Context, state *pb.BeaconState, block *pb.BeaconBl
|
||||
}
|
||||
if bytes.Equal(attestation.Data.EpochBoundaryRootHash32, prevBoundaryBlockRoot) {
|
||||
prevEpochBoundaryAttestations = append(prevEpochBoundaryAttestations, attestation)
|
||||
prevEpochBoundaryAttesterIndices = sliceutil.Union(prevEpochBoundaryAttesterIndices, attesterIndices)
|
||||
prevEpochBoundaryAttesterIndices = sliceutil.UnionUint64(prevEpochBoundaryAttesterIndices, attesterIndices)
|
||||
}
|
||||
|
||||
// We extract the previous epoch head attestations.
|
||||
@@ -277,7 +285,7 @@ func ProcessEpoch(ctx context.Context, state *pb.BeaconState, block *pb.BeaconBl
|
||||
attestationData := attestation.Data
|
||||
if bytes.Equal(attestationData.BeaconBlockRootHash32, canonicalBlockRoot) {
|
||||
prevEpochHeadAttestations = append(prevEpochHeadAttestations, attestation)
|
||||
prevEpochHeadAttesterIndices = sliceutil.Union(prevEpochHeadAttesterIndices, attesterIndices)
|
||||
prevEpochHeadAttesterIndices = sliceutil.UnionUint64(prevEpochHeadAttesterIndices, attesterIndices)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -358,7 +366,8 @@ func ProcessEpoch(ctx context.Context, state *pb.BeaconState, block *pb.BeaconBl
|
||||
state, err = bal.InclusionDistance(
|
||||
state,
|
||||
prevEpochAttesterIndices,
|
||||
totalBalance)
|
||||
totalBalance,
|
||||
inclusionDistanceByAttester)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not calculate inclusion dist rewards: %v", err)
|
||||
}
|
||||
@@ -367,7 +376,9 @@ func ProcessEpoch(ctx context.Context, state *pb.BeaconState, block *pb.BeaconBl
|
||||
}
|
||||
|
||||
case epochsSinceFinality > 4:
|
||||
log.WithField("epochSinceFinality", epochsSinceFinality).Info("Applying quadratic leak penalties")
|
||||
if config.Logging {
|
||||
log.WithField("epochSinceFinality", epochsSinceFinality).Info("Applying quadratic leak penalties")
|
||||
}
|
||||
// Apply penalties for long inactive FFG source participants.
|
||||
state = bal.InactivityFFGSource(
|
||||
state,
|
||||
@@ -397,7 +408,8 @@ func ProcessEpoch(ctx context.Context, state *pb.BeaconState, block *pb.BeaconBl
|
||||
state, err = bal.InactivityInclusionDistance(
|
||||
state,
|
||||
prevEpochAttesterIndices,
|
||||
totalBalance)
|
||||
totalBalance,
|
||||
inclusionDistanceByAttester)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not calculate inclusion penalties: %v", err)
|
||||
}
|
||||
@@ -407,7 +419,8 @@ func ProcessEpoch(ctx context.Context, state *pb.BeaconState, block *pb.BeaconBl
|
||||
state, err = bal.AttestationInclusion(
|
||||
state,
|
||||
totalBalance,
|
||||
prevEpochAttesterIndices)
|
||||
prevEpochAttesterIndices,
|
||||
inclusionSlotByAttester)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not process attestation inclusion rewards: %v", err)
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ func ValidatorIndices(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
attesterIndicesIntersection = sliceutil.Union(attesterIndicesIntersection, attesterIndices)
|
||||
attesterIndicesIntersection = sliceutil.UnionUint64(attesterIndicesIntersection, attesterIndices)
|
||||
}
|
||||
|
||||
return attesterIndicesIntersection, nil
|
||||
@@ -87,7 +87,7 @@ func AttestingValidatorIndices(
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get attester indices: %v", err)
|
||||
}
|
||||
validatorIndicesCommittees = sliceutil.Union(validatorIndicesCommittees, validatorIndicesCommittee)
|
||||
validatorIndicesCommittees = sliceutil.UnionUint64(validatorIndicesCommittees, validatorIndicesCommittee)
|
||||
}
|
||||
}
|
||||
return validatorIndicesCommittees, nil
|
||||
|
||||
@@ -16,16 +16,33 @@ func (db *BeaconDB) SaveAttestation(ctx context.Context, attestation *pb.Attesta
|
||||
ctx, span := trace.StartSpan(ctx, "beaconDB.SaveAttestation")
|
||||
defer span.End()
|
||||
|
||||
encodedState, err := proto.Marshal(attestation)
|
||||
encodedAtt, err := proto.Marshal(attestation)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hash := hashutil.Hash(encodedState)
|
||||
hash := hashutil.Hash(encodedAtt)
|
||||
|
||||
return db.update(func(tx *bolt.Tx) error {
|
||||
a := tx.Bucket(attestationBucket)
|
||||
|
||||
return a.Put(hash[:], encodedState)
|
||||
return a.Put(hash[:], encodedAtt)
|
||||
})
|
||||
}
|
||||
|
||||
// SaveAttestationTarget puts the attestation target record into the beacon chain db.
|
||||
func (db *BeaconDB) SaveAttestationTarget(ctx context.Context, attTarget *pb.AttestationTarget) error {
|
||||
ctx, span := trace.StartSpan(ctx, "beaconDB.SaveAttestationTarget")
|
||||
defer span.End()
|
||||
|
||||
encodedAttTgt, err := proto.Marshal(attTarget)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return db.update(func(tx *bolt.Tx) error {
|
||||
a := tx.Bucket(attestationTargetBucket)
|
||||
|
||||
return a.Put(attTarget.BlockRoot, encodedAttTgt)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -85,6 +102,25 @@ func (db *BeaconDB) Attestations() ([]*pb.Attestation, error) {
|
||||
return attestations, err
|
||||
}
|
||||
|
||||
// AttestationTarget retrieves an attestation target record from the db using its hash.
|
||||
func (db *BeaconDB) AttestationTarget(hash [32]byte) (*pb.AttestationTarget, error) {
|
||||
var attTgt *pb.AttestationTarget
|
||||
err := db.view(func(tx *bolt.Tx) error {
|
||||
a := tx.Bucket(attestationTargetBucket)
|
||||
|
||||
enc := a.Get(hash[:])
|
||||
if enc == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var err error
|
||||
attTgt, err = createAttestationTarget(enc)
|
||||
return err
|
||||
})
|
||||
|
||||
return attTgt, err
|
||||
}
|
||||
|
||||
// HasAttestation checks if the attestation exists.
|
||||
func (db *BeaconDB) HasAttestation(hash [32]byte) bool {
|
||||
exists := false
|
||||
@@ -105,3 +141,11 @@ func createAttestation(enc []byte) (*pb.Attestation, error) {
|
||||
}
|
||||
return protoAttestation, nil
|
||||
}
|
||||
|
||||
func createAttestationTarget(enc []byte) (*pb.AttestationTarget, error) {
|
||||
protoAttTgt := &pb.AttestationTarget{}
|
||||
if err := proto.Unmarshal(enc, protoAttTgt); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal encoding: %v", err)
|
||||
}
|
||||
return protoAttTgt, nil
|
||||
}
|
||||
|
||||
@@ -8,10 +8,17 @@ import (
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
|
||||
func init() {
|
||||
featureconfig.InitFeatureConfig(&featureconfig.FeatureFlagConfig{
|
||||
CacheTreeHash: false,
|
||||
})
|
||||
}
|
||||
|
||||
func TestNilDB_OK(t *testing.T) {
|
||||
db := setupDB(t)
|
||||
defer teardownDB(t, db)
|
||||
|
||||
@@ -20,11 +20,14 @@ var log = logrus.WithField("prefix", "beacondb")
|
||||
// For example, instead of defining get, put, remove
|
||||
// This defines methods such as getBlock, saveBlocksAndAttestations, etc.
|
||||
type BeaconDB struct {
|
||||
stateLock sync.RWMutex
|
||||
currentState *pb.BeaconState
|
||||
stateHash [32]byte
|
||||
db *bolt.DB
|
||||
DatabasePath string
|
||||
// state objects and caches
|
||||
stateLock sync.RWMutex
|
||||
serializedState []byte
|
||||
stateHash [32]byte
|
||||
validatorRegistry []*pb.Validator
|
||||
validatorBalances []uint64
|
||||
db *bolt.DB
|
||||
DatabasePath string
|
||||
|
||||
// Beacon block info in memory.
|
||||
highestBlockSlot uint64
|
||||
@@ -82,8 +85,8 @@ func NewDB(dirPath string) (*BeaconDB, error) {
|
||||
db := &BeaconDB{db: boltDB, DatabasePath: dirPath}
|
||||
|
||||
if err := db.update(func(tx *bolt.Tx) error {
|
||||
return createBuckets(tx, blockBucket, attestationBucket, mainChainBucket, histStateBucket,
|
||||
chainInfoBucket, cleanupHistoryBucket, blockOperationsBucket, validatorBucket)
|
||||
return createBuckets(tx, blockBucket, attestationBucket, attestationTargetBucket, mainChainBucket,
|
||||
histStateBucket, chainInfoBucket, cleanupHistoryBucket, blockOperationsBucket, validatorBucket)
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -15,13 +15,14 @@ import (
|
||||
|
||||
// The fields below define the suffix of keys in the db.
|
||||
var (
|
||||
attestationBucket = []byte("attestation-bucket")
|
||||
blockOperationsBucket = []byte("block-operations-bucket")
|
||||
blockBucket = []byte("block-bucket")
|
||||
mainChainBucket = []byte("main-chain-bucket")
|
||||
histStateBucket = []byte("historical-state-bucket")
|
||||
chainInfoBucket = []byte("chain-info")
|
||||
validatorBucket = []byte("validator")
|
||||
attestationBucket = []byte("attestation-bucket")
|
||||
attestationTargetBucket = []byte("attestation-target-bucket")
|
||||
blockOperationsBucket = []byte("block-operations-bucket")
|
||||
blockBucket = []byte("block-bucket")
|
||||
mainChainBucket = []byte("main-chain-bucket")
|
||||
histStateBucket = []byte("historical-state-bucket")
|
||||
chainInfoBucket = []byte("chain-info")
|
||||
validatorBucket = []byte("validator")
|
||||
|
||||
mainChainHeightKey = []byte("chain-height")
|
||||
stateLookupKey = []byte("state")
|
||||
|
||||
@@ -46,7 +46,7 @@ func (db *BeaconDB) InitializeState(ctx context.Context, genesisTime uint64, dep
|
||||
blockEnc, _ := proto.Marshal(genesisBlock)
|
||||
zeroBinary := encodeSlotNumber(0)
|
||||
|
||||
db.currentState = beaconState
|
||||
db.serializedState = stateEnc
|
||||
db.stateHash = stateHash
|
||||
|
||||
if err := db.SaveState(ctx, beaconState); err != nil {
|
||||
@@ -100,11 +100,15 @@ func (db *BeaconDB) HeadState(ctx context.Context) (*pb.BeaconState, error) {
|
||||
lockSpan.End()
|
||||
|
||||
// Return in-memory cached state, if available.
|
||||
if db.currentState != nil {
|
||||
_, span := trace.StartSpan(ctx, "proto.Clone")
|
||||
if db.serializedState != nil {
|
||||
_, span := trace.StartSpan(ctx, "proto.Marshal")
|
||||
defer span.End()
|
||||
cachedState := proto.Clone(db.currentState).(*pb.BeaconState)
|
||||
return cachedState, nil
|
||||
newState := &pb.BeaconState{}
|
||||
// For each READ we unmarshal the serialized state into a new state struct and return that.
|
||||
if err := proto.Unmarshal(db.serializedState, newState); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return newState, nil
|
||||
}
|
||||
|
||||
var beaconState *pb.BeaconState
|
||||
@@ -117,9 +121,13 @@ func (db *BeaconDB) HeadState(ctx context.Context) (*pb.BeaconState, error) {
|
||||
|
||||
var err error
|
||||
beaconState, err = createState(enc)
|
||||
|
||||
if beaconState != nil && beaconState.Slot > db.highestBlockSlot {
|
||||
db.highestBlockSlot = beaconState.Slot
|
||||
}
|
||||
db.serializedState = enc
|
||||
db.stateHash = hashutil.Hash(enc)
|
||||
|
||||
return err
|
||||
})
|
||||
|
||||
@@ -141,21 +149,19 @@ func (db *BeaconDB) SaveState(ctx context.Context, beaconState *pb.BeaconState)
|
||||
defer db.stateLock.Unlock()
|
||||
lockSpan.End()
|
||||
|
||||
// Clone to prevent mutations of the cached copy
|
||||
ctx, cloneSpan := trace.StartSpan(ctx, "proto.Clone")
|
||||
currentState, ok := proto.Clone(beaconState).(*pb.BeaconState)
|
||||
if !ok {
|
||||
cloneSpan.End()
|
||||
return errors.New("could not clone beacon state")
|
||||
}
|
||||
db.currentState = currentState
|
||||
cloneSpan.End()
|
||||
|
||||
stateHash, err := hashutil.HashProto(beaconState)
|
||||
// For each WRITE of the state, we serialize the inputted state and save it in memory,
|
||||
// and then the state is saved to disk.
|
||||
enc, err := proto.Marshal(beaconState)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
stateHash := hashutil.Hash(enc)
|
||||
tempState := &pb.BeaconState{}
|
||||
tempState.ValidatorRegistry = beaconState.ValidatorRegistry
|
||||
|
||||
copy(db.validatorBalances, beaconState.Balances)
|
||||
db.validatorRegistry = proto.Clone(tempState).(*pb.BeaconState).ValidatorRegistry
|
||||
db.serializedState = enc
|
||||
db.stateHash = stateHash
|
||||
|
||||
if err := db.SaveHistoricalState(ctx, beaconState); err != nil {
|
||||
@@ -165,16 +171,9 @@ func (db *BeaconDB) SaveState(ctx context.Context, beaconState *pb.BeaconState)
|
||||
return db.update(func(tx *bolt.Tx) error {
|
||||
chainInfo := tx.Bucket(chainInfoBucket)
|
||||
|
||||
_, marshalSpan := trace.StartSpan(ctx, "proto.Marshal")
|
||||
beaconStateEnc, err := proto.Marshal(beaconState)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
marshalSpan.End()
|
||||
|
||||
stateBytes.Set(float64(len(beaconStateEnc)))
|
||||
stateBytes.Set(float64(len(enc)))
|
||||
reportStateMetrics(beaconState)
|
||||
return chainInfo.Put(stateLookupKey, beaconStateEnc)
|
||||
return chainInfo.Put(stateLookupKey, enc)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -330,14 +329,14 @@ func (db *BeaconDB) ValidatorRegistry(ctx context.Context) ([]*pb.Validator, err
|
||||
defer db.stateLock.RUnlock()
|
||||
|
||||
// Return in-memory cached state, if available.
|
||||
if db.currentState != nil {
|
||||
if db.validatorRegistry != nil {
|
||||
_, span := trace.StartSpan(ctx, "proto.Clone.ValidatorRegistry")
|
||||
defer span.End()
|
||||
newRegistry := make([]*pb.Validator, len(db.currentState.ValidatorRegistry))
|
||||
for i, v := range db.currentState.ValidatorRegistry {
|
||||
newRegistry[i] = proto.Clone(v).(*pb.Validator)
|
||||
tempState := &pb.BeaconState{
|
||||
ValidatorRegistry: db.validatorRegistry,
|
||||
}
|
||||
return newRegistry, nil
|
||||
newState := proto.Clone(tempState).(*pb.BeaconState)
|
||||
return newState.ValidatorRegistry, nil
|
||||
}
|
||||
|
||||
var beaconState *pb.BeaconState
|
||||
@@ -359,20 +358,61 @@ func (db *BeaconDB) ValidatorRegistry(ctx context.Context) ([]*pb.Validator, err
|
||||
return beaconState.ValidatorRegistry, err
|
||||
}
|
||||
|
||||
// ValidatorFromState fetches the validator with the desired index from the cached registry.
|
||||
func (db *BeaconDB) ValidatorFromState(ctx context.Context, index uint64) (*pb.Validator, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "BeaconDB.ValidatorFromState")
|
||||
defer span.End()
|
||||
|
||||
db.stateLock.RLock()
|
||||
defer db.stateLock.RUnlock()
|
||||
|
||||
if db.validatorRegistry != nil {
|
||||
// return error if it's an invalid validator index.
|
||||
if index >= uint64(len(db.validatorRegistry)) {
|
||||
return nil, fmt.Errorf("invalid validator index %d", index)
|
||||
}
|
||||
validator := proto.Clone(db.validatorRegistry[index]).(*pb.Validator)
|
||||
return validator, nil
|
||||
}
|
||||
|
||||
var beaconState *pb.BeaconState
|
||||
err := db.view(func(tx *bolt.Tx) error {
|
||||
chainInfo := tx.Bucket(chainInfoBucket)
|
||||
enc := chainInfo.Get(stateLookupKey)
|
||||
if enc == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var err error
|
||||
beaconState, err = createState(enc)
|
||||
if beaconState != nil && beaconState.Slot > db.highestBlockSlot {
|
||||
db.highestBlockSlot = beaconState.Slot
|
||||
}
|
||||
return err
|
||||
})
|
||||
|
||||
// return error if it's an invalid validator index.
|
||||
if index >= uint64(len(db.validatorRegistry)) {
|
||||
return nil, fmt.Errorf("invalid validator index %d", index)
|
||||
}
|
||||
|
||||
return beaconState.ValidatorRegistry[index], err
|
||||
}
|
||||
|
||||
// ValidatorBalances fetches the current validator balances stored in state.
|
||||
func (db *BeaconDB) ValidatorBalances(ctx context.Context) ([]uint64, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "BeaconDB.ValidatorRegistry")
|
||||
ctx, span := trace.StartSpan(ctx, "BeaconDB.ValidatorBalances")
|
||||
defer span.End()
|
||||
|
||||
db.stateLock.RLock()
|
||||
defer db.stateLock.RUnlock()
|
||||
|
||||
// Return in-memory cached state, if available.
|
||||
if db.currentState != nil {
|
||||
_, span := trace.StartSpan(ctx, "proto.Clone.ValidatorRegistry")
|
||||
if db.validatorBalances != nil {
|
||||
_, span := trace.StartSpan(ctx, "BeaconDB.Copy.Balances")
|
||||
defer span.End()
|
||||
newBalances := make([]uint64, len(db.currentState.Balances))
|
||||
copy(newBalances, db.currentState.Balances)
|
||||
newBalances := make([]uint64, len(db.validatorBalances))
|
||||
copy(newBalances, db.validatorBalances)
|
||||
return newBalances, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ func TestFinalizeState_OK(t *testing.T) {
|
||||
defer teardownDB(t, db)
|
||||
|
||||
genesisTime := uint64(time.Now().Unix())
|
||||
deposits, _ := setupInitialDeposits(t, 10)
|
||||
deposits, _ := setupInitialDeposits(t, 20)
|
||||
if err := db.InitializeState(context.Background(), genesisTime, deposits, &pb.Eth1Data{}); err != nil {
|
||||
t.Fatalf("Failed to initialize state: %v", err)
|
||||
}
|
||||
@@ -138,7 +138,10 @@ func BenchmarkState_ReadingFromCache(b *testing.B) {
|
||||
b.Fatalf("Could not save beacon state to cache from DB: %v", err)
|
||||
}
|
||||
|
||||
if db.currentState.Slot != params.BeaconConfig().GenesisSlot+1 {
|
||||
savedState := &pb.BeaconState{}
|
||||
savedState.Unmarshal(db.serializedState)
|
||||
|
||||
if savedState.Slot != params.BeaconConfig().GenesisSlot+1 {
|
||||
b.Fatal("cache should be prepared on state after saving to DB")
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package db
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
|
||||
@@ -37,13 +38,28 @@ func (db *BeaconDB) SaveValidatorIndexBatch(pubKey []byte, index int) error {
|
||||
}
|
||||
|
||||
// ValidatorIndex accepts a public key and returns the corresponding validator index.
|
||||
// If the validator index is not found in DB, as a fail over, it searches the state and
|
||||
// saves it to the DB when found.
|
||||
func (db *BeaconDB) ValidatorIndex(pubKey []byte) (uint64, error) {
|
||||
if !db.HasValidator(pubKey) {
|
||||
state, err := db.HeadState(context.Background())
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
for i := 0; i < len(state.ValidatorRegistry); i++ {
|
||||
v := state.ValidatorRegistry[i]
|
||||
if bytes.Equal(v.Pubkey, pubKey) {
|
||||
if err := db.SaveValidatorIndex(pubKey, i); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint64(i), nil
|
||||
}
|
||||
}
|
||||
return 0, fmt.Errorf("validator %#x does not exist", pubKey)
|
||||
}
|
||||
|
||||
var index uint64
|
||||
h := hashutil.Hash(pubKey)
|
||||
|
||||
err := db.view(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(validatorBucket)
|
||||
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/boltdb/bolt"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
||||
)
|
||||
|
||||
@@ -47,11 +49,14 @@ func TestSaveAndDeleteValidatorIndex_OK(t *testing.T) {
|
||||
p1 := []byte{'1', '2', '3'}
|
||||
|
||||
if err := db.SaveValidatorIndex(p1, 3); err != nil {
|
||||
t.Fatalf("Failed to save vallidator index: %v", err)
|
||||
t.Fatalf("Failed to save validator index: %v", err)
|
||||
}
|
||||
if err := db.SaveState(context.Background(), &pb.BeaconState{}); err != nil {
|
||||
t.Fatalf("Failed to save state: %v", err)
|
||||
}
|
||||
index, err := db.ValidatorIndex(p1)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to call Attestation: %v", err)
|
||||
t.Fatalf("Failed to call validator Index: %v", err)
|
||||
}
|
||||
if index != 3 {
|
||||
t.Fatalf("Saved index and retrieved index are not equal: %#x and %#x", 3, index)
|
||||
|
||||
@@ -29,7 +29,7 @@ func (db *BeaconDB) VerifyContractAddress(ctx context.Context, addr common.Addre
|
||||
}
|
||||
|
||||
if !bytes.Equal(expectedAddress, addr.Bytes()) {
|
||||
return fmt.Errorf("invalid deposit contract address, expected %#x", expectedAddress)
|
||||
return fmt.Errorf("invalid deposit contract address, expected %#x - try running with --clear-db", expectedAddress)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -63,7 +63,7 @@ func main() {
|
||||
cmd.TraceSampleFractionFlag,
|
||||
cmd.MonitoringPortFlag,
|
||||
cmd.DisableMonitoringFlag,
|
||||
cmd.ClearDBFlag,
|
||||
cmd.ClearDB,
|
||||
debug.PProfFlag,
|
||||
debug.PProfAddrFlag,
|
||||
debug.PProfPortFlag,
|
||||
|
||||
@@ -4,6 +4,8 @@ package node
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path"
|
||||
@@ -168,7 +170,7 @@ func (b *BeaconNode) Close() {
|
||||
func (b *BeaconNode) startDB(ctx *cli.Context) error {
|
||||
baseDir := ctx.GlobalString(cmd.DataDirFlag.Name)
|
||||
dbPath := path.Join(baseDir, beaconChainDBName)
|
||||
if b.ctx.GlobalBool(cmd.ClearDBFlag.Name) {
|
||||
if b.ctx.GlobalBool(cmd.ClearDB.Name) {
|
||||
if err := db.ClearDB(dbPath); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -246,7 +248,22 @@ func (b *BeaconNode) registerPOWChainService(cliCtx *cli.Context) error {
|
||||
depAddress := cliCtx.GlobalString(utils.DepositContractFlag.Name)
|
||||
|
||||
if depAddress == "" {
|
||||
log.Fatal("No deposit contract specified. Add --deposit-contract with a valid deposit contract address to start.")
|
||||
log.Infof("Fetching testnet cluster address from %s...", params.BeaconConfig().TestnetContractEndpoint)
|
||||
resp, err := http.Get(params.BeaconConfig().TestnetContractEndpoint)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not get latest deposit contract address: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
if err := resp.Body.Close(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}()
|
||||
|
||||
contractResponse, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
depAddress = string(contractResponse)
|
||||
}
|
||||
|
||||
if !common.IsHexAddress(depAddress) {
|
||||
@@ -344,6 +361,11 @@ func (b *BeaconNode) registerRPCService(ctx *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
var syncService *rbcsync.Service
|
||||
if err := b.services.FetchService(&syncService); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
port := ctx.GlobalString(utils.RPCPort.Name)
|
||||
cert := ctx.GlobalString(utils.CertFlag.Name)
|
||||
key := ctx.GlobalString(utils.KeyFlag.Name)
|
||||
@@ -355,6 +377,7 @@ func (b *BeaconNode) registerRPCService(ctx *cli.Context) error {
|
||||
ChainService: chainService,
|
||||
OperationService: operationService,
|
||||
POWChainService: web3Service,
|
||||
SyncService: syncService,
|
||||
})
|
||||
|
||||
return b.services.RegisterService(rpcService)
|
||||
|
||||
@@ -28,6 +28,7 @@ var topicMappings = map[pb.Topic]proto.Message{
|
||||
|
||||
func configureP2P(ctx *cli.Context) (*p2p.Server, error) {
|
||||
s, err := p2p.NewServer(&p2p.ServerConfig{
|
||||
NoDiscovery: ctx.GlobalBool(cmd.NoDiscovery.Name),
|
||||
BootstrapNodeAddr: ctx.GlobalString(cmd.BootstrapNode.Name),
|
||||
RelayNodeAddr: ctx.GlobalString(cmd.RelayNode.Name),
|
||||
Port: ctx.GlobalInt(cmd.P2PPort.Name),
|
||||
|
||||
@@ -72,11 +72,11 @@ func TestRoutineContextClosing_Ok(t *testing.T) {
|
||||
s := NewOpsPoolService(context.Background(), &Config{BeaconDB: db})
|
||||
|
||||
exitRoutine := make(chan bool)
|
||||
go func(tt *testing.T) {
|
||||
go func() {
|
||||
s.removeOperations()
|
||||
s.saveOperations()
|
||||
<-exitRoutine
|
||||
}(t)
|
||||
}()
|
||||
s.cancel()
|
||||
exitRoutine <- true
|
||||
testutil.AssertLogsContain(t, hook, "operations service context closed, exiting remove goroutine")
|
||||
|
||||
@@ -46,6 +46,7 @@ go_test(
|
||||
"//contracts/deposit-contract:go_default_library",
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/event:go_default_library",
|
||||
"//shared/featureconfig:go_default_library",
|
||||
"//shared/ssz:go_default_library",
|
||||
"//shared/testutil:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//:go_default_library",
|
||||
|
||||
@@ -13,8 +13,9 @@ import (
|
||||
gethTypes "github.com/ethereum/go-ethereum/core/types"
|
||||
)
|
||||
|
||||
var endpoint = "ws://127.0.0.1"
|
||||
|
||||
func TestLatestMainchainInfo_OK(t *testing.T) {
|
||||
endpoint := "ws://127.0.0.1"
|
||||
testAcc, err := setup()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to set up simulated backend %v", err)
|
||||
@@ -84,7 +85,6 @@ func TestLatestMainchainInfo_OK(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBlockHashByHeight_ReturnsHash(t *testing.T) {
|
||||
endpoint := "ws://127.0.0.1"
|
||||
web3Service, err := NewWeb3Service(context.Background(), &Web3ServiceConfig{
|
||||
Endpoint: endpoint,
|
||||
BlockFetcher: &goodFetcher{},
|
||||
@@ -123,7 +123,6 @@ func TestBlockHashByHeight_ReturnsHash(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBlockExists_ValidHash(t *testing.T) {
|
||||
endpoint := "ws://127.0.0.1"
|
||||
web3Service, err := NewWeb3Service(context.Background(), &Web3ServiceConfig{
|
||||
Endpoint: endpoint,
|
||||
BlockFetcher: &goodFetcher{},
|
||||
@@ -163,7 +162,6 @@ func TestBlockExists_ValidHash(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBlockExists_InvalidHash(t *testing.T) {
|
||||
endpoint := "ws://127.0.0.1"
|
||||
web3Service, err := NewWeb3Service(context.Background(), &Web3ServiceConfig{
|
||||
Endpoint: endpoint,
|
||||
BlockFetcher: &goodFetcher{},
|
||||
@@ -179,7 +177,6 @@ func TestBlockExists_InvalidHash(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBlockExists_UsesCachedBlockInfo(t *testing.T) {
|
||||
endpoint := "ws://127.0.0.1"
|
||||
web3Service, err := NewWeb3Service(context.Background(), &Web3ServiceConfig{
|
||||
Endpoint: endpoint,
|
||||
BlockFetcher: nil, // nil blockFetcher would panic if cached value not used
|
||||
|
||||
@@ -189,7 +189,7 @@ func (w *Web3Service) processPastLogs() error {
|
||||
// last polled to now.
|
||||
func (w *Web3Service) requestBatchedLogs() error {
|
||||
// We request for the nth block behind the current head, in order to have
|
||||
// stabilised logs when we retrieve it from the 1.0 chain.
|
||||
// stabilized logs when we retrieve it from the 1.0 chain.
|
||||
requestedBlock := big.NewInt(0).Sub(w.blockHeight, big.NewInt(params.BeaconConfig().LogBlockDelay))
|
||||
query := ethereum.FilterQuery{
|
||||
Addresses: []common.Address{
|
||||
|
||||
@@ -14,14 +14,20 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db"
|
||||
contracts "github.com/prysmaticlabs/prysm/contracts/deposit-contract"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/ssz"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
logTest "github.com/sirupsen/logrus/hooks/test"
|
||||
)
|
||||
|
||||
func init() {
|
||||
featureconfig.InitFeatureConfig(&featureconfig.FeatureFlagConfig{
|
||||
CacheTreeHash: false,
|
||||
})
|
||||
}
|
||||
|
||||
func TestProcessDepositLog_OK(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
endpoint := "ws://127.0.0.1"
|
||||
testAcc, err := setup()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to set up simulated backend %v", err)
|
||||
@@ -84,7 +90,6 @@ func TestProcessDepositLog_OK(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestProcessDepositLog_InsertsPendingDeposit(t *testing.T) {
|
||||
endpoint := "ws://127.0.0.1"
|
||||
testAcc, err := setup()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to set up simulated backend %v", err)
|
||||
@@ -146,7 +151,6 @@ func TestProcessDepositLog_InsertsPendingDeposit(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUnpackDepositLogData_OK(t *testing.T) {
|
||||
endpoint := "ws://127.0.0.1"
|
||||
testAcc, err := setup()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to set up simulated backend %v", err)
|
||||
@@ -230,7 +234,6 @@ func TestUnpackDepositLogData_OK(t *testing.T) {
|
||||
|
||||
func TestProcessChainStartLog_8DuplicatePubkeys(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
endpoint := "ws://127.0.0.1"
|
||||
testAcc, err := setup()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to set up simulated backend %v", err)
|
||||
@@ -316,7 +319,6 @@ func TestProcessChainStartLog_8DuplicatePubkeys(t *testing.T) {
|
||||
|
||||
func TestProcessChainStartLog_8UniquePubkeys(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
endpoint := "ws://127.0.0.1"
|
||||
testAcc, err := setup()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to set up simulated backend %v", err)
|
||||
@@ -401,7 +403,6 @@ func TestProcessChainStartLog_8UniquePubkeys(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUnpackChainStartLogData_OK(t *testing.T) {
|
||||
endpoint := "ws://127.0.0.1"
|
||||
testAcc, err := setup()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to set up simulated backend %v", err)
|
||||
@@ -470,7 +471,6 @@ func TestUnpackChainStartLogData_OK(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestHasChainStartLogOccurred_OK(t *testing.T) {
|
||||
endpoint := "ws://127.0.0.1"
|
||||
testAcc, err := setup()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to set up simulated backend %v", err)
|
||||
@@ -531,7 +531,6 @@ func TestHasChainStartLogOccurred_OK(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestETH1DataGenesis_OK(t *testing.T) {
|
||||
endpoint := "ws://127.0.0.1"
|
||||
testAcc, err := setup()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to set up simulated backend %v", err)
|
||||
|
||||
@@ -38,16 +38,6 @@ func (g *goodReader) SubscribeNewHead(ctx context.Context, ch chan<- *gethTypes.
|
||||
return new(event.Feed).Subscribe(ch), nil
|
||||
}
|
||||
|
||||
type badLogger struct{}
|
||||
|
||||
func (b *badLogger) FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]gethTypes.Log, error) {
|
||||
return nil, errors.New("unable to retrieve logs")
|
||||
}
|
||||
|
||||
func (b *badLogger) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- gethTypes.Log) (ethereum.Subscription, error) {
|
||||
return nil, errors.New("subscription has failed")
|
||||
}
|
||||
|
||||
type goodLogger struct{}
|
||||
|
||||
func (g *goodLogger) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- gethTypes.Log) (ethereum.Subscription, error) {
|
||||
@@ -198,7 +188,6 @@ func TestNewWeb3Service_OK(t *testing.T) {
|
||||
func TestStart_OK(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
|
||||
endpoint := "ws://127.0.0.1"
|
||||
testAcc, err := setup()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to set up simulated backend %v", err)
|
||||
@@ -237,7 +226,6 @@ func TestStart_OK(t *testing.T) {
|
||||
func TestStop_OK(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
|
||||
endpoint := "ws://127.0.0.1"
|
||||
testAcc, err := setup()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to set up simulated backend %v", err)
|
||||
@@ -274,7 +262,7 @@ func TestStop_OK(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestInitDataFromContract_OK(t *testing.T) {
|
||||
endpoint := "ws://127.0.0.1"
|
||||
|
||||
testAcc, err := setup()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to set up simulated backend %v", err)
|
||||
@@ -304,7 +292,7 @@ func TestInitDataFromContract_OK(t *testing.T) {
|
||||
|
||||
func TestWeb3Service_BadReader(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
endpoint := "ws://127.0.0.1"
|
||||
|
||||
testAcc, err := setup()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to set up simulated backend %v", err)
|
||||
@@ -367,7 +355,7 @@ func TestStatus(t *testing.T) {
|
||||
|
||||
func TestHandlePanic_OK(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
endpoint := "ws://127.0.0.1"
|
||||
|
||||
web3Service, err := NewWeb3Service(context.Background(), &Web3ServiceConfig{
|
||||
Endpoint: endpoint,
|
||||
BlockFetcher: nil, // nil blockFetcher would panic if cached value not used
|
||||
|
||||
@@ -24,6 +24,8 @@ import (
|
||||
logTest "github.com/sirupsen/logrus/hooks/test"
|
||||
)
|
||||
|
||||
var closedContext = "context closed"
|
||||
|
||||
type faultyPOWChainService struct {
|
||||
chainStartFeed *event.Feed
|
||||
hashesByHeight map[int][]byte
|
||||
@@ -129,8 +131,7 @@ func TestWaitForChainStart_ContextClosed(t *testing.T) {
|
||||
defer ctrl.Finish()
|
||||
mockStream := internal.NewMockBeaconService_WaitForChainStartServer(ctrl)
|
||||
go func(tt *testing.T) {
|
||||
want := "context closed"
|
||||
if err := beaconServer.WaitForChainStart(&ptypes.Empty{}, mockStream); !strings.Contains(err.Error(), want) {
|
||||
if err := beaconServer.WaitForChainStart(&ptypes.Empty{}, mockStream); !strings.Contains(err.Error(), closedContext) {
|
||||
tt.Errorf("Could not call RPC method: %v", err)
|
||||
}
|
||||
<-exitRoutine
|
||||
|
||||
@@ -55,6 +55,10 @@ type powChainService interface {
|
||||
ChainStartDeposits() [][]byte
|
||||
}
|
||||
|
||||
type syncService interface {
|
||||
Status() error
|
||||
}
|
||||
|
||||
// Service defining an RPC server for a beacon node.
|
||||
type Service struct {
|
||||
ctx context.Context
|
||||
@@ -63,6 +67,7 @@ type Service struct {
|
||||
chainService chainService
|
||||
powChainService powChainService
|
||||
operationService operationService
|
||||
syncService syncService
|
||||
port string
|
||||
listener net.Listener
|
||||
withCert string
|
||||
@@ -82,6 +87,7 @@ type Config struct {
|
||||
ChainService chainService
|
||||
POWChainService powChainService
|
||||
OperationService operationService
|
||||
SyncService syncService
|
||||
}
|
||||
|
||||
// NewRPCService creates a new instance of a struct implementing the BeaconServiceServer
|
||||
@@ -95,6 +101,7 @@ func NewRPCService(ctx context.Context, cfg *Config) *Service {
|
||||
chainService: cfg.ChainService,
|
||||
powChainService: cfg.POWChainService,
|
||||
operationService: cfg.OperationService,
|
||||
syncService: cfg.SyncService,
|
||||
port: cfg.Port,
|
||||
withCert: cfg.CertFlag,
|
||||
withKey: cfg.KeyFlag,
|
||||
@@ -174,6 +181,9 @@ func (s *Service) Start() {
|
||||
reflection.Register(s.grpcServer)
|
||||
|
||||
go func() {
|
||||
for s.syncService.Status() != nil {
|
||||
time.Sleep(time.Second * params.BeaconConfig().RPCSyncCheck)
|
||||
}
|
||||
if s.listener != nil {
|
||||
if err := s.grpcServer.Serve(s.listener); err != nil {
|
||||
log.Errorf("Could not serve gRPC: %v", err)
|
||||
|
||||
@@ -121,12 +121,20 @@ func newMockChainService() *mockChainService {
|
||||
}
|
||||
}
|
||||
|
||||
type mockSyncService struct {
|
||||
}
|
||||
|
||||
func (ms *mockSyncService) Status() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestLifecycle_OK(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
rpcService := NewRPCService(context.Background(), &Config{
|
||||
Port: "7348",
|
||||
CertFlag: "alice.crt",
|
||||
KeyFlag: "alice.key",
|
||||
Port: "7348",
|
||||
CertFlag: "alice.crt",
|
||||
KeyFlag: "alice.key",
|
||||
SyncService: &mockSyncService{},
|
||||
})
|
||||
|
||||
rpcService.Start()
|
||||
@@ -150,7 +158,8 @@ func TestRPC_BadEndpoint(t *testing.T) {
|
||||
hook := logTest.NewLocal(fl.Logger)
|
||||
|
||||
rpcService := NewRPCService(context.Background(), &Config{
|
||||
Port: "ralph merkle!!!",
|
||||
Port: "ralph merkle!!!",
|
||||
SyncService: &mockSyncService{},
|
||||
})
|
||||
|
||||
if val, ok := log.(*TestLogger).testMap["error"]; ok {
|
||||
@@ -179,7 +188,8 @@ func TestStatus_CredentialError(t *testing.T) {
|
||||
func TestRPC_InsecureEndpoint(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
rpcService := NewRPCService(context.Background(), &Config{
|
||||
Port: "7777",
|
||||
Port: "7777",
|
||||
SyncService: &mockSyncService{},
|
||||
})
|
||||
|
||||
rpcService.Start()
|
||||
|
||||
@@ -110,7 +110,7 @@ func (vs *ValidatorServer) ValidatorPerformance(
|
||||
// 1.) The list of validators in the committee.
|
||||
// 2.) The shard to which the committee is assigned.
|
||||
// 3.) The slot at which the committee is assigned.
|
||||
// 4.) The bool signalling if the validator is expected to propose a block at the assigned slot.
|
||||
// 4.) The bool signaling if the validator is expected to propose a block at the assigned slot.
|
||||
func (vs *ValidatorServer) CommitteeAssignment(
|
||||
ctx context.Context,
|
||||
req *pb.CommitteeAssignmentsRequest) (*pb.CommitteeAssignmentResponse, error) {
|
||||
|
||||
@@ -64,6 +64,48 @@ func TestValidatorIndex_OK(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidatorIndex_InStateNotInDB(t *testing.T) {
|
||||
db := internal.SetupDB(t)
|
||||
defer internal.TeardownDB(t, db)
|
||||
|
||||
pubKey := []byte{'A'}
|
||||
|
||||
// Wanted validator with public key 'A' is in index '1'.
|
||||
s := &pbp2p.BeaconState{
|
||||
ValidatorRegistry: []*pbp2p.Validator{{Pubkey: []byte{0}}, {Pubkey: []byte{'A'}}, {Pubkey: []byte{'B'}}},
|
||||
}
|
||||
|
||||
if err := db.SaveState(context.Background(), s); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
validatorServer := &ValidatorServer{
|
||||
beaconDB: db,
|
||||
}
|
||||
|
||||
req := &pb.ValidatorIndexRequest{
|
||||
PublicKey: pubKey,
|
||||
}
|
||||
|
||||
// Verify index can be retrieved from state when it's not saved in DB.
|
||||
res, err := validatorServer.ValidatorIndex(context.Background(), req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if res.Index != 1 {
|
||||
t.Errorf("Wanted index 1 got %d", res.Index)
|
||||
}
|
||||
|
||||
// Verify index is also saved in DB.
|
||||
idx, err := validatorServer.beaconDB.ValidatorIndex(pubKey)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if idx != 1 {
|
||||
t.Errorf("Wanted index 1 in DB got %d", res.Index)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNextEpochCommitteeAssignment_WrongPubkeyLength(t *testing.T) {
|
||||
db := internal.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
@@ -691,7 +733,9 @@ func TestAddNonActivePublicKeysAssignmentStatus(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if err := db.SaveState(context.Background(), beaconState); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
vs := &ValidatorServer{
|
||||
beaconDB: db,
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@ import (
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
const noMsgData = "message contains no data"
|
||||
|
||||
func (s *InitialSync) checkBlockValidity(ctx context.Context, block *pb.BeaconBlock) error {
|
||||
ctx, span := trace.StartSpan(ctx, "beacon-chain.sync.initial-sync.checkBlockValidity")
|
||||
defer span.End()
|
||||
@@ -41,7 +43,7 @@ func (s *InitialSync) doesParentExist(block *pb.BeaconBlock) bool {
|
||||
func safelyHandleMessage(fn func(p2p.Message), msg p2p.Message) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
printedMsg := "message contains no data"
|
||||
printedMsg := noMsgData
|
||||
if msg.Data != nil {
|
||||
printedMsg = proto.MarshalTextString(msg.Data)
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
|
||||
@@ -203,6 +205,17 @@ func (s *InitialSync) exitInitialSync(ctx context.Context, block *pb.BeaconBlock
|
||||
if err := s.db.SaveBlock(block); err != nil {
|
||||
return err
|
||||
}
|
||||
root, err := hashutil.HashBeaconBlock(block)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to tree hash block: %v", err)
|
||||
}
|
||||
if err := s.db.SaveAttestationTarget(ctx, &pb.AttestationTarget{
|
||||
Slot: block.Slot,
|
||||
BlockRoot: root[:],
|
||||
ParentRoot: block.ParentRootHash32,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("failed to save attestation target: %v", err)
|
||||
}
|
||||
state, err = s.chainService.ApplyBlockStateTransition(ctx, block, state)
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
|
||||
@@ -165,6 +165,13 @@ func (s *InitialSync) validateAndSaveNextBlock(ctx context.Context, block *pb.Be
|
||||
if err := s.db.SaveBlock(block); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.db.SaveAttestationTarget(ctx, &pb.AttestationTarget{
|
||||
Slot: block.Slot,
|
||||
BlockRoot: root[:],
|
||||
ParentRoot: block.ParentRootHash32,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("could not to save attestation target: %v", err)
|
||||
}
|
||||
state, err = s.chainService.ApplyBlockStateTransition(ctx, block, state)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not apply block state transition: %v", err)
|
||||
|
||||
@@ -3,6 +3,8 @@ package initialsync
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/validators"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
@@ -38,6 +40,20 @@ func (s *InitialSync) processState(msg p2p.Message) {
|
||||
return
|
||||
}
|
||||
|
||||
root, err := hashutil.HashBeaconBlock(finalizedState.LatestBlock)
|
||||
if err != nil {
|
||||
log.Errorf("Could not hash finalized block %v", err)
|
||||
return
|
||||
}
|
||||
if err := s.db.SaveAttestationTarget(ctx, &pb.AttestationTarget{
|
||||
Slot: finalizedState.LatestBlock.Slot,
|
||||
BlockRoot: root[:],
|
||||
ParentRoot: finalizedState.LatestBlock.ParentRootHash32,
|
||||
}); err != nil {
|
||||
log.Errorf("Could not to save attestation target: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := s.db.SaveJustifiedState(finalizedState); err != nil {
|
||||
log.Errorf("Could not set beacon state for initial sync %v", err)
|
||||
return
|
||||
|
||||
@@ -24,6 +24,10 @@ var (
|
||||
Name: "regsync_received_blocks",
|
||||
Help: "The number of received blocks",
|
||||
})
|
||||
forkedBlock = promauto.NewCounter(prometheus.CounterOpts{
|
||||
Name: "regsync_received_forked_blocks",
|
||||
Help: "The number of received forked blocks",
|
||||
})
|
||||
recBlockAnnounce = promauto.NewCounter(prometheus.CounterOpts{
|
||||
Name: "regsync_received_block_announce",
|
||||
Help: "The number of received block announcements",
|
||||
|
||||
@@ -191,6 +191,9 @@ func (rs *RegularSync) validateAndProcessBlock(
|
||||
span.AddAttributes(trace.BoolAttribute("invalidBlock", true))
|
||||
return nil, nil, false, err
|
||||
}
|
||||
} else {
|
||||
forkedBlock.Inc()
|
||||
log.Warnf("Received Block from a Forked Chain with root %#x and slot %d", blockRoot, block.Slot)
|
||||
}
|
||||
|
||||
sentBlocks.Inc()
|
||||
|
||||
@@ -433,20 +433,16 @@ func (rs *RegularSync) receiveAttestation(msg p2p.Message) error {
|
||||
}
|
||||
|
||||
// Skip if attestation slot is older than last finalized slot in state.
|
||||
beaconState, err := rs.db.HeadState(ctx)
|
||||
if err != nil {
|
||||
log.Errorf("Failed to get beacon state: %v", err)
|
||||
return err
|
||||
}
|
||||
highestSlot := rs.db.HighestBlockSlot()
|
||||
|
||||
span.AddAttributes(
|
||||
trace.Int64Attribute("attestation.Data.Slot", int64(attestation.Data.Slot)),
|
||||
trace.Int64Attribute("finalized state slot", int64(beaconState.Slot-params.BeaconConfig().SlotsPerEpoch)),
|
||||
trace.Int64Attribute("finalized state slot", int64(highestSlot-params.BeaconConfig().SlotsPerEpoch)),
|
||||
)
|
||||
if attestation.Data.Slot < beaconState.Slot-params.BeaconConfig().SlotsPerEpoch {
|
||||
if attestation.Data.Slot < highestSlot-params.BeaconConfig().SlotsPerEpoch {
|
||||
log.WithFields(logrus.Fields{
|
||||
"receivedSlot": attestation.Data.Slot,
|
||||
"epochSlot": beaconState.Slot - params.BeaconConfig().SlotsPerEpoch},
|
||||
"epochSlot": highestSlot - params.BeaconConfig().SlotsPerEpoch},
|
||||
).Debug("Skipping received attestation with slot smaller than one epoch ago")
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/event"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/p2p"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
@@ -25,6 +26,9 @@ import (
|
||||
func init() {
|
||||
logrus.SetLevel(logrus.DebugLevel)
|
||||
logrus.SetOutput(ioutil.Discard)
|
||||
featureconfig.InitFeatureConfig(&featureconfig.FeatureFlagConfig{
|
||||
CacheTreeHash: false,
|
||||
})
|
||||
}
|
||||
|
||||
type mockP2P struct {
|
||||
@@ -116,7 +120,7 @@ func (ma *mockAttestationService) IncomingAttestationFeed() *event.Feed {
|
||||
return new(event.Feed)
|
||||
}
|
||||
|
||||
func setupService(t *testing.T, db *db.BeaconDB) *RegularSync {
|
||||
func setupService(db *db.BeaconDB) *RegularSync {
|
||||
cfg := &RegularSyncConfig{
|
||||
BlockAnnounceBufferSize: 0,
|
||||
BlockBufferSize: 0,
|
||||
@@ -174,7 +178,7 @@ func TestProcessBlock_OK(t *testing.T) {
|
||||
}
|
||||
}
|
||||
genesisTime := uint64(time.Now().Unix())
|
||||
deposits, _ := setupInitialDeposits(t, 10)
|
||||
deposits, _ := setupInitialDeposits(t)
|
||||
if err := db.InitializeState(context.Background(), genesisTime, deposits, &pb.Eth1Data{}); err != nil {
|
||||
t.Fatalf("Failed to initialize state: %v", err)
|
||||
}
|
||||
@@ -249,7 +253,7 @@ func TestProcessBlock_MultipleBlocksProcessedOK(t *testing.T) {
|
||||
}
|
||||
}
|
||||
genesisTime := uint64(time.Now().Unix())
|
||||
deposits, _ := setupInitialDeposits(t, 10)
|
||||
deposits, _ := setupInitialDeposits(t)
|
||||
if err := db.InitializeState(context.Background(), genesisTime, deposits, &pb.Eth1Data{}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -343,7 +347,7 @@ func TestBlockRequest_InvalidMsg(t *testing.T) {
|
||||
|
||||
db := internal.SetupDB(t)
|
||||
defer internal.TeardownDB(t, db)
|
||||
ss := setupService(t, db)
|
||||
ss := setupService(db)
|
||||
|
||||
malformedRequest := &pb.BeaconBlockAnnounce{
|
||||
Hash: []byte{'t', 'e', 's', 't'},
|
||||
@@ -366,7 +370,7 @@ func TestBlockRequest_OK(t *testing.T) {
|
||||
|
||||
db := internal.SetupDB(t)
|
||||
defer internal.TeardownDB(t, db)
|
||||
ss := setupService(t, db)
|
||||
ss := setupService(db)
|
||||
|
||||
request1 := &pb.BeaconBlockRequestBySlotNumber{
|
||||
SlotNumber: 20,
|
||||
@@ -396,11 +400,21 @@ func TestReceiveAttestation_OK(t *testing.T) {
|
||||
|
||||
db := internal.SetupDB(t)
|
||||
defer internal.TeardownDB(t, db)
|
||||
if err := db.SaveState(ctx, &pb.BeaconState{
|
||||
beaconState := &pb.BeaconState{
|
||||
Slot: params.BeaconConfig().GenesisSlot + 2,
|
||||
}); err != nil {
|
||||
}
|
||||
if err := db.SaveState(ctx, beaconState); err != nil {
|
||||
t.Fatalf("Could not save state: %v", err)
|
||||
}
|
||||
beaconBlock := &pb.BeaconBlock{
|
||||
Slot: beaconState.Slot,
|
||||
}
|
||||
if err := db.SaveBlock(beaconBlock); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := db.UpdateChainHead(ctx, beaconBlock, beaconState); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cfg := &RegularSyncConfig{
|
||||
ChainService: ms,
|
||||
AttsService: &mockAttestationService{},
|
||||
@@ -656,10 +670,10 @@ func TestHandleStateReq_NOState(t *testing.T) {
|
||||
db := internal.SetupDB(t)
|
||||
defer internal.TeardownDB(t, db)
|
||||
|
||||
ss := setupService(t, db)
|
||||
ss := setupService(db)
|
||||
|
||||
genesisTime := uint64(time.Now().Unix())
|
||||
deposits, _ := setupInitialDeposits(t, 10)
|
||||
deposits, _ := setupInitialDeposits(t)
|
||||
if err := db.InitializeState(context.Background(), genesisTime, deposits, &pb.Eth1Data{}); err != nil {
|
||||
t.Fatalf("Failed to initialize state: %v", err)
|
||||
}
|
||||
@@ -708,7 +722,7 @@ func TestHandleStateReq_OK(t *testing.T) {
|
||||
t.Fatalf("could not hash beacon state: %v", err)
|
||||
}
|
||||
|
||||
ss := setupService(t, db)
|
||||
ss := setupService(db)
|
||||
|
||||
request1 := &pb.BeaconStateRequest{
|
||||
FinalizedStateRootHash32S: stateRoot[:],
|
||||
|
||||
@@ -2,6 +2,7 @@ package sync
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db"
|
||||
@@ -16,9 +17,10 @@ var slog = logrus.WithField("prefix", "sync")
|
||||
|
||||
// Service defines the main routines used in the sync service.
|
||||
type Service struct {
|
||||
RegularSync *RegularSync
|
||||
InitialSync *initialsync.InitialSync
|
||||
Querier *Querier
|
||||
RegularSync *RegularSync
|
||||
InitialSync *initialsync.InitialSync
|
||||
Querier *Querier
|
||||
querierFinished bool
|
||||
}
|
||||
|
||||
// Config defines the configured services required for sync to work.
|
||||
@@ -60,9 +62,10 @@ func NewSyncService(ctx context.Context, cfg *Config) *Service {
|
||||
is := initialsync.NewInitialSyncService(ctx, isCfg)
|
||||
|
||||
return &Service{
|
||||
RegularSync: rs,
|
||||
InitialSync: is,
|
||||
Querier: sq,
|
||||
RegularSync: rs,
|
||||
InitialSync: is,
|
||||
Querier: sq,
|
||||
querierFinished: false,
|
||||
}
|
||||
|
||||
}
|
||||
@@ -91,9 +94,14 @@ func (ss *Service) Stop() error {
|
||||
// Status checks the status of the node. It returns nil if it's synced
|
||||
// with the rest of the network and no errors occurred. Otherwise, it returns an error.
|
||||
func (ss *Service) Status() error {
|
||||
if !ss.querierFinished {
|
||||
return errors.New("querier is still running")
|
||||
}
|
||||
|
||||
if !ss.Querier.chainStarted {
|
||||
return nil
|
||||
}
|
||||
|
||||
if ss.Querier.atGenesis {
|
||||
return nil
|
||||
}
|
||||
@@ -102,6 +110,9 @@ func (ss *Service) Status() error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not retrieve chain head %v", err)
|
||||
}
|
||||
if blk == nil {
|
||||
return errors.New("no chain head exists in db")
|
||||
}
|
||||
if blk.Slot < ss.InitialSync.HighestObservedSlot() {
|
||||
return fmt.Errorf("node is not synced as the current chain head is at slot %d", blk.Slot-params.BeaconConfig().GenesisSlot)
|
||||
}
|
||||
@@ -114,6 +125,7 @@ func (ss *Service) run() {
|
||||
if err != nil {
|
||||
slog.Fatalf("Unable to retrieve result from sync querier %v", err)
|
||||
}
|
||||
ss.querierFinished = true
|
||||
|
||||
// Sets the highest observed slot from querier.
|
||||
ss.InitialSync.InitializeObservedSlot(ss.Querier.currentHeadSlot)
|
||||
|
||||
@@ -45,9 +45,10 @@ func initializeTestSyncService(ctx context.Context, cfg *Config, synced bool) *S
|
||||
return services
|
||||
}
|
||||
|
||||
func setupInitialDeposits(t *testing.T, numDeposits int) ([]*pb.Deposit, []*bls.SecretKey) {
|
||||
privKeys := make([]*bls.SecretKey, numDeposits)
|
||||
deposits := make([]*pb.Deposit, numDeposits)
|
||||
func setupInitialDeposits(t *testing.T) ([]*pb.Deposit, []*bls.SecretKey) {
|
||||
numOfDeposits := 10
|
||||
privKeys := make([]*bls.SecretKey, numOfDeposits)
|
||||
deposits := make([]*pb.Deposit, numOfDeposits)
|
||||
for i := 0; i < len(deposits); i++ {
|
||||
priv, err := bls.RandKey(rand.Reader)
|
||||
if err != nil {
|
||||
@@ -71,7 +72,7 @@ func setupTestSyncService(t *testing.T, synced bool) (*Service, *db.BeaconDB) {
|
||||
db := internal.SetupDB(t)
|
||||
|
||||
unixTime := uint64(time.Now().Unix())
|
||||
deposits, _ := setupInitialDeposits(t, 10)
|
||||
deposits, _ := setupInitialDeposits(t)
|
||||
if err := db.InitializeState(context.Background(), unixTime, deposits, &pb.Eth1Data{}); err != nil {
|
||||
t.Fatalf("Failed to initialize state: %v", err)
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ var appHelpFlagGroups = []flagGroup{
|
||||
{
|
||||
Name: "cmd",
|
||||
Flags: []cli.Flag{
|
||||
cmd.NoDiscovery,
|
||||
cmd.BootstrapNode,
|
||||
cmd.RelayNode,
|
||||
cmd.P2PPort,
|
||||
|
||||
@@ -44,6 +44,7 @@ spec:
|
||||
image: gcr.io/prysmaticlabs/prysm/beacon-chain:latest
|
||||
args:
|
||||
- --web3provider=wss://goerli.infura.io/ws/v3/be3fb7ed377c418087602876a40affa1
|
||||
- --http-web3provider=https://goerli.infura.io/v3/be3fb7ed377c418087602876a40affa1
|
||||
#- --verbosity=debug
|
||||
- --deposit-contract=$(DEPOSIT_CONTRACT_ADDRESS)
|
||||
- --rpc-port=4000
|
||||
|
||||
@@ -72,3 +72,9 @@ spec:
|
||||
port:
|
||||
number: 8080
|
||||
host: contract-address-http.beacon-chain.svc.cluster.local
|
||||
corsPolicy:
|
||||
allowOrigin:
|
||||
- '*'
|
||||
allowMethods:
|
||||
- GET
|
||||
maxAge: '24h'
|
||||
|
||||
665
proto/beacon/p2p/v1/types.pb.go
generated
665
proto/beacon/p2p/v1/types.pb.go
generated
@@ -48,7 +48,7 @@ func (x Validator_StatusFlags) String() string {
|
||||
}
|
||||
|
||||
func (Validator_StatusFlags) EnumDescriptor() ([]byte, []int) {
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{7, 0}
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{8, 0}
|
||||
}
|
||||
|
||||
type BeaconState struct {
|
||||
@@ -803,6 +803,69 @@ func (m *AttestationData) GetCrosslinkDataRootHash32() []byte {
|
||||
return nil
|
||||
}
|
||||
|
||||
type AttestationTarget struct {
|
||||
Slot uint64 `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty"`
|
||||
BlockRoot []byte `protobuf:"bytes,2,opt,name=block_root,json=blockRoot,proto3" json:"block_root,omitempty"`
|
||||
ParentRoot []byte `protobuf:"bytes,3,opt,name=parent_root,json=parentRoot,proto3" json:"parent_root,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *AttestationTarget) Reset() { *m = AttestationTarget{} }
|
||||
func (m *AttestationTarget) String() string { return proto.CompactTextString(m) }
|
||||
func (*AttestationTarget) ProtoMessage() {}
|
||||
func (*AttestationTarget) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{5}
|
||||
}
|
||||
func (m *AttestationTarget) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *AttestationTarget) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_AttestationTarget.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalTo(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *AttestationTarget) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_AttestationTarget.Merge(m, src)
|
||||
}
|
||||
func (m *AttestationTarget) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *AttestationTarget) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_AttestationTarget.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_AttestationTarget proto.InternalMessageInfo
|
||||
|
||||
func (m *AttestationTarget) GetSlot() uint64 {
|
||||
if m != nil {
|
||||
return m.Slot
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *AttestationTarget) GetBlockRoot() []byte {
|
||||
if m != nil {
|
||||
return m.BlockRoot
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *AttestationTarget) GetParentRoot() []byte {
|
||||
if m != nil {
|
||||
return m.ParentRoot
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type AttestationDataAndCustodyBit struct {
|
||||
Data *AttestationData `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
|
||||
CustodyBit bool `protobuf:"varint,2,opt,name=custody_bit,json=custodyBit,proto3" json:"custody_bit,omitempty"`
|
||||
@@ -815,7 +878,7 @@ func (m *AttestationDataAndCustodyBit) Reset() { *m = AttestationDataAnd
|
||||
func (m *AttestationDataAndCustodyBit) String() string { return proto.CompactTextString(m) }
|
||||
func (*AttestationDataAndCustodyBit) ProtoMessage() {}
|
||||
func (*AttestationDataAndCustodyBit) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{5}
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{6}
|
||||
}
|
||||
func (m *AttestationDataAndCustodyBit) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -872,7 +935,7 @@ func (m *IndexedAttestation) Reset() { *m = IndexedAttestation{} }
|
||||
func (m *IndexedAttestation) String() string { return proto.CompactTextString(m) }
|
||||
func (*IndexedAttestation) ProtoMessage() {}
|
||||
func (*IndexedAttestation) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{6}
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{7}
|
||||
}
|
||||
func (m *IndexedAttestation) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -951,7 +1014,7 @@ func (m *Validator) Reset() { *m = Validator{} }
|
||||
func (m *Validator) String() string { return proto.CompactTextString(m) }
|
||||
func (*Validator) ProtoMessage() {}
|
||||
func (*Validator) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{7}
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{8}
|
||||
}
|
||||
func (m *Validator) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -1081,7 +1144,7 @@ func (m *ShardReassignmentRecord) Reset() { *m = ShardReassignmentRecord
|
||||
func (m *ShardReassignmentRecord) String() string { return proto.CompactTextString(m) }
|
||||
func (*ShardReassignmentRecord) ProtoMessage() {}
|
||||
func (*ShardReassignmentRecord) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{8}
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{9}
|
||||
}
|
||||
func (m *ShardReassignmentRecord) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -1144,7 +1207,7 @@ func (m *Crosslink) Reset() { *m = Crosslink{} }
|
||||
func (m *Crosslink) String() string { return proto.CompactTextString(m) }
|
||||
func (*Crosslink) ProtoMessage() {}
|
||||
func (*Crosslink) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{9}
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{10}
|
||||
}
|
||||
func (m *Crosslink) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -1213,7 +1276,7 @@ func (m *BeaconBlock) Reset() { *m = BeaconBlock{} }
|
||||
func (m *BeaconBlock) String() string { return proto.CompactTextString(m) }
|
||||
func (*BeaconBlock) ProtoMessage() {}
|
||||
func (*BeaconBlock) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{10}
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{11}
|
||||
}
|
||||
func (m *BeaconBlock) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -1323,7 +1386,7 @@ func (m *BeaconBlockBody) Reset() { *m = BeaconBlockBody{} }
|
||||
func (m *BeaconBlockBody) String() string { return proto.CompactTextString(m) }
|
||||
func (*BeaconBlockBody) ProtoMessage() {}
|
||||
func (*BeaconBlockBody) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{11}
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{12}
|
||||
}
|
||||
func (m *BeaconBlockBody) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -1421,7 +1484,7 @@ func (m *DepositInput) Reset() { *m = DepositInput{} }
|
||||
func (m *DepositInput) String() string { return proto.CompactTextString(m) }
|
||||
func (*DepositInput) ProtoMessage() {}
|
||||
func (*DepositInput) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{12}
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{13}
|
||||
}
|
||||
func (m *DepositInput) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -1484,7 +1547,7 @@ func (m *ProposalSignedData) Reset() { *m = ProposalSignedData{} }
|
||||
func (m *ProposalSignedData) String() string { return proto.CompactTextString(m) }
|
||||
func (*ProposalSignedData) ProtoMessage() {}
|
||||
func (*ProposalSignedData) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{13}
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{14}
|
||||
}
|
||||
func (m *ProposalSignedData) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -1548,7 +1611,7 @@ func (m *SlashableAttestation) Reset() { *m = SlashableAttestation{} }
|
||||
func (m *SlashableAttestation) String() string { return proto.CompactTextString(m) }
|
||||
func (*SlashableAttestation) ProtoMessage() {}
|
||||
func (*SlashableAttestation) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{14}
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{15}
|
||||
}
|
||||
func (m *SlashableAttestation) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -1621,7 +1684,7 @@ func (m *DepositData) Reset() { *m = DepositData{} }
|
||||
func (m *DepositData) String() string { return proto.CompactTextString(m) }
|
||||
func (*DepositData) ProtoMessage() {}
|
||||
func (*DepositData) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{15}
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{16}
|
||||
}
|
||||
func (m *DepositData) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -1711,7 +1774,7 @@ func (m *ProposerSlashing) Reset() { *m = ProposerSlashing{} }
|
||||
func (m *ProposerSlashing) String() string { return proto.CompactTextString(m) }
|
||||
func (*ProposerSlashing) ProtoMessage() {}
|
||||
func (*ProposerSlashing) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{16}
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{17}
|
||||
}
|
||||
func (m *ProposerSlashing) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -1807,7 +1870,7 @@ func (m *AttesterSlashing) Reset() { *m = AttesterSlashing{} }
|
||||
func (m *AttesterSlashing) String() string { return proto.CompactTextString(m) }
|
||||
func (*AttesterSlashing) ProtoMessage() {}
|
||||
func (*AttesterSlashing) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{17}
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{18}
|
||||
}
|
||||
func (m *AttesterSlashing) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -1882,7 +1945,7 @@ func (m *Deposit) Reset() { *m = Deposit{} }
|
||||
func (m *Deposit) String() string { return proto.CompactTextString(m) }
|
||||
func (*Deposit) ProtoMessage() {}
|
||||
func (*Deposit) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{18}
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{19}
|
||||
}
|
||||
func (m *Deposit) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -1969,7 +2032,7 @@ func (m *VoluntaryExit) Reset() { *m = VoluntaryExit{} }
|
||||
func (m *VoluntaryExit) String() string { return proto.CompactTextString(m) }
|
||||
func (*VoluntaryExit) ProtoMessage() {}
|
||||
func (*VoluntaryExit) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{19}
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{20}
|
||||
}
|
||||
func (m *VoluntaryExit) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -2036,7 +2099,7 @@ func (m *Transfer) Reset() { *m = Transfer{} }
|
||||
func (m *Transfer) String() string { return proto.CompactTextString(m) }
|
||||
func (*Transfer) ProtoMessage() {}
|
||||
func (*Transfer) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{20}
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{21}
|
||||
}
|
||||
func (m *Transfer) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -2129,7 +2192,7 @@ func (m *Eth1Data) Reset() { *m = Eth1Data{} }
|
||||
func (m *Eth1Data) String() string { return proto.CompactTextString(m) }
|
||||
func (*Eth1Data) ProtoMessage() {}
|
||||
func (*Eth1Data) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{21}
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{22}
|
||||
}
|
||||
func (m *Eth1Data) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -2207,7 +2270,7 @@ func (m *Eth1DataVote) Reset() { *m = Eth1DataVote{} }
|
||||
func (m *Eth1DataVote) String() string { return proto.CompactTextString(m) }
|
||||
func (*Eth1DataVote) ProtoMessage() {}
|
||||
func (*Eth1DataVote) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{22}
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{23}
|
||||
}
|
||||
func (m *Eth1DataVote) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -2262,7 +2325,7 @@ func (m *HistoricalBatch) Reset() { *m = HistoricalBatch{} }
|
||||
func (m *HistoricalBatch) String() string { return proto.CompactTextString(m) }
|
||||
func (*HistoricalBatch) ProtoMessage() {}
|
||||
func (*HistoricalBatch) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{23}
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{24}
|
||||
}
|
||||
func (m *HistoricalBatch) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -2320,7 +2383,7 @@ func (m *BeaconBlockHeader) Reset() { *m = BeaconBlockHeader{} }
|
||||
func (m *BeaconBlockHeader) String() string { return proto.CompactTextString(m) }
|
||||
func (*BeaconBlockHeader) ProtoMessage() {}
|
||||
func (*BeaconBlockHeader) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{24}
|
||||
return fileDescriptor_e719e7d82cfa7b0d, []int{25}
|
||||
}
|
||||
func (m *BeaconBlockHeader) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -2391,6 +2454,7 @@ func init() {
|
||||
proto.RegisterType((*PendingAttestation)(nil), "ethereum.beacon.p2p.v1.PendingAttestation")
|
||||
proto.RegisterType((*Attestation)(nil), "ethereum.beacon.p2p.v1.Attestation")
|
||||
proto.RegisterType((*AttestationData)(nil), "ethereum.beacon.p2p.v1.AttestationData")
|
||||
proto.RegisterType((*AttestationTarget)(nil), "ethereum.beacon.p2p.v1.AttestationTarget")
|
||||
proto.RegisterType((*AttestationDataAndCustodyBit)(nil), "ethereum.beacon.p2p.v1.AttestationDataAndCustodyBit")
|
||||
proto.RegisterType((*IndexedAttestation)(nil), "ethereum.beacon.p2p.v1.IndexedAttestation")
|
||||
proto.RegisterType((*Validator)(nil), "ethereum.beacon.p2p.v1.Validator")
|
||||
@@ -2416,186 +2480,187 @@ func init() {
|
||||
func init() { proto.RegisterFile("proto/beacon/p2p/v1/types.proto", fileDescriptor_e719e7d82cfa7b0d) }
|
||||
|
||||
var fileDescriptor_e719e7d82cfa7b0d = []byte{
|
||||
// 2850 bytes of a gzipped FileDescriptorProto
|
||||
// 2880 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x5a, 0x49, 0x6c, 0x23, 0xc7,
|
||||
0xd5, 0xfe, 0x49, 0x49, 0x23, 0xe9, 0x89, 0x12, 0xc9, 0xd2, 0xd6, 0xd6, 0x2c, 0x9a, 0xe1, 0x8c,
|
||||
0xd5, 0xfe, 0x49, 0x4a, 0x23, 0xe9, 0x91, 0x12, 0xc9, 0xd2, 0xd6, 0xd6, 0x2c, 0x9a, 0xe1, 0x8c,
|
||||
0x67, 0xb3, 0x4d, 0x99, 0x34, 0x6c, 0xe3, 0xff, 0xfd, 0x5b, 0x18, 0x69, 0x46, 0xf6, 0xc8, 0xbb,
|
||||
0x5b, 0xb2, 0xe7, 0xc7, 0x7f, 0xe9, 0x34, 0xd9, 0x45, 0xaa, 0x47, 0x54, 0x37, 0xd1, 0xd5, 0x94,
|
||||
0x47, 0x41, 0xae, 0x39, 0xd8, 0x59, 0xcf, 0xb9, 0x25, 0x76, 0xb6, 0x7b, 0x2e, 0xd9, 0x0e, 0x41,
|
||||
0x36, 0x67, 0x73, 0x9c, 0x00, 0x09, 0x10, 0x20, 0x07, 0xc3, 0x40, 0x80, 0x8c, 0xe3, 0x1c, 0x92,
|
||||
0xdc, 0x83, 0xa0, 0xea, 0x55, 0x75, 0x55, 0x37, 0x49, 0x8d, 0x64, 0xfb, 0xa6, 0x7e, 0x5b, 0xbd,
|
||||
0x57, 0x55, 0xef, 0x7b, 0xef, 0x15, 0x05, 0xcb, 0xdd, 0x28, 0x8c, 0xc3, 0x95, 0x06, 0x75, 0x9b,
|
||||
0x61, 0xb0, 0xd2, 0xad, 0x77, 0x57, 0xf6, 0x6b, 0x2b, 0xf1, 0x41, 0x97, 0xb2, 0xaa, 0xe0, 0x90,
|
||||
0x05, 0x1a, 0xef, 0xd0, 0x88, 0xf6, 0xf6, 0xaa, 0x28, 0x53, 0xed, 0xd6, 0xbb, 0xd5, 0xfd, 0xda,
|
||||
0xd2, 0x49, 0x54, 0x6c, 0x86, 0x7b, 0x7b, 0x61, 0xb0, 0xb2, 0x47, 0x19, 0x73, 0xdb, 0x4a, 0xa9,
|
||||
0xf2, 0xde, 0x1c, 0x4c, 0xad, 0x0b, 0xf1, 0xad, 0xd8, 0x8d, 0x29, 0xa9, 0x40, 0xa1, 0x4d, 0x03,
|
||||
0xca, 0x7c, 0xe6, 0xc4, 0xfe, 0x1e, 0xb5, 0xee, 0x8e, 0x9f, 0xcd, 0x5d, 0x1e, 0xb5, 0xa7, 0x24,
|
||||
0x71, 0xdb, 0xdf, 0xa3, 0xa4, 0x06, 0xa3, 0xad, 0x30, 0xda, 0xb5, 0x3e, 0xe0, 0xbc, 0xa9, 0xfa,
|
||||
0xa9, 0xea, 0xe0, 0x85, 0xab, 0x4f, 0x85, 0xd1, 0xae, 0x2d, 0x44, 0xc9, 0x2c, 0x8c, 0xb2, 0x4e,
|
||||
0x18, 0x5b, 0x7f, 0x43, 0x73, 0xe2, 0x83, 0xbc, 0x0c, 0x64, 0xdf, 0xed, 0xf8, 0x9e, 0x1b, 0x87,
|
||||
0x91, 0x13, 0xd1, 0xb6, 0xcf, 0xe2, 0xe8, 0xc0, 0xfa, 0x5d, 0xf1, 0xec, 0xc8, 0xe5, 0xa9, 0xfa,
|
||||
0xb9, 0x61, 0x56, 0x5f, 0x55, 0x2a, 0x76, 0x39, 0xd1, 0xb6, 0xa5, 0x32, 0x39, 0x09, 0x13, 0x0d,
|
||||
0xb7, 0xe3, 0x06, 0x4d, 0xca, 0xac, 0xdf, 0x73, 0x43, 0xa3, 0x76, 0x42, 0x20, 0x2b, 0x30, 0xdb,
|
||||
0x71, 0x63, 0xca, 0x62, 0x27, 0x72, 0x03, 0xcf, 0x0d, 0x9d, 0x3d, 0xff, 0x0e, 0x65, 0xd6, 0x77,
|
||||
0x17, 0xcf, 0x8e, 0x5c, 0x2e, 0xd8, 0x65, 0xe4, 0xd9, 0x82, 0xf5, 0x3c, 0xe7, 0x90, 0x87, 0x80,
|
||||
0x48, 0x05, 0x16, 0xbb, 0x51, 0xec, 0xb0, 0x1d, 0x37, 0xf2, 0xac, 0xef, 0x2d, 0x8a, 0x18, 0x4a,
|
||||
0xc8, 0xda, 0xe2, 0x9c, 0x2d, 0xce, 0x20, 0xbb, 0x70, 0xb2, 0x1b, 0xd1, 0x7d, 0x3f, 0xec, 0x31,
|
||||
0x87, 0x76, 0xc3, 0xe6, 0x8e, 0xe3, 0xc6, 0x5c, 0xc4, 0x8d, 0xfd, 0x30, 0x60, 0xd6, 0x57, 0x97,
|
||||
0x45, 0x60, 0x57, 0x87, 0x05, 0xf6, 0x12, 0x0d, 0x3c, 0x3f, 0x68, 0xaf, 0x69, 0x1d, 0xfb, 0x3e,
|
||||
0x65, 0x6f, 0x83, 0x9b, 0x33, 0x38, 0x8c, 0xf8, 0xb0, 0xd4, 0xec, 0x45, 0x11, 0x0d, 0xe2, 0x41,
|
||||
0x6b, 0x7d, 0xed, 0xf8, 0x6b, 0x59, 0xd2, 0x5c, 0xff, 0x52, 0xff, 0x0d, 0x56, 0x12, 0xd7, 0xed,
|
||||
0x1e, 0x8b, 0xfd, 0x96, 0x4f, 0x3d, 0x5c, 0xd5, 0x7a, 0x73, 0x59, 0x6c, 0xc6, 0x82, 0x12, 0x78,
|
||||
0x46, 0xf1, 0x85, 0x19, 0xf2, 0x38, 0x2c, 0x2a, 0x2f, 0xb3, 0x9a, 0x6f, 0xa1, 0xe6, 0xbc, 0xe4,
|
||||
0xf7, 0x2b, 0x0e, 0x58, 0x33, 0x0a, 0xc3, 0xd8, 0xfa, 0x3a, 0x57, 0x2c, 0xd8, 0xf3, 0x7d, 0x4b,
|
||||
0xda, 0x61, 0x18, 0x93, 0x47, 0x61, 0xa1, 0x7f, 0x45, 0xa1, 0xf7, 0x0d, 0xd4, 0x9b, 0xcb, 0x2e,
|
||||
0x28, 0xd4, 0x1e, 0x83, 0x05, 0x29, 0xde, 0x14, 0x51, 0x3b, 0x0d, 0x3f, 0x6e, 0xf9, 0xb4, 0xe3,
|
||||
0x59, 0xdf, 0x94, 0x7e, 0xa6, 0xd8, 0xeb, 0x92, 0x4b, 0x2e, 0x43, 0xb1, 0xe5, 0x07, 0x6e, 0xc7,
|
||||
0xff, 0x74, 0x12, 0xd8, 0xb7, 0x50, 0x61, 0x26, 0xa1, 0x63, 0x44, 0x17, 0x41, 0x53, 0xd0, 0xa1,
|
||||
0x6f, 0xa3, 0x43, 0xd3, 0x09, 0x59, 0x78, 0xf2, 0x32, 0x10, 0x15, 0x40, 0x33, 0x0a, 0x19, 0xeb,
|
||||
0xf8, 0xc1, 0x2e, 0xb3, 0x5e, 0xbf, 0x74, 0x78, 0x56, 0x5c, 0x57, 0xa2, 0x76, 0x59, 0x6a, 0x27,
|
||||
0x14, 0x46, 0xb6, 0x60, 0x36, 0xd9, 0x4c, 0xc3, 0xe6, 0x1b, 0x47, 0xb6, 0x49, 0x94, 0xba, 0x61,
|
||||
0x54, 0x27, 0x47, 0xa3, 0x13, 0x36, 0x77, 0x45, 0x48, 0xcc, 0xfa, 0xdc, 0x25, 0x91, 0x4c, 0x32,
|
||||
0x39, 0xd6, 0x39, 0x87, 0x47, 0x95, 0xc9, 0xa5, 0x98, 0x4a, 0xf1, 0xcf, 0xa7, 0xc4, 0x05, 0x04,
|
||||
0xa1, 0xf8, 0xff, 0xc0, 0x7d, 0x52, 0xdc, 0x6d, 0xc6, 0xfe, 0x3e, 0x75, 0xfc, 0xc0, 0xa3, 0x77,
|
||||
0xa4, 0xd6, 0x17, 0x50, 0x6b, 0x01, 0x25, 0xd6, 0x84, 0xc0, 0x26, 0xe7, 0xa3, 0xee, 0xe3, 0xb0,
|
||||
0xa8, 0x96, 0xea, 0xb8, 0x6c, 0x87, 0x7a, 0x4e, 0x82, 0x09, 0x5f, 0xbc, 0x24, 0x30, 0x61, 0x5e,
|
||||
0xae, 0x87, 0xec, 0x75, 0x05, 0x10, 0xff, 0x9f, 0x00, 0x04, 0x86, 0xb4, 0x43, 0x5d, 0x8f, 0x46,
|
||||
0xd6, 0x97, 0x2e, 0x09, 0x9c, 0xbb, 0x32, 0x6c, 0x9f, 0x10, 0x3f, 0x45, 0xac, 0x37, 0x85, 0x86,
|
||||
0xc2, 0x12, 0x83, 0x44, 0xae, 0x42, 0x69, 0xc7, 0x67, 0x71, 0x18, 0xf9, 0x4d, 0xb7, 0x23, 0xe3,
|
||||
0xf8, 0x32, 0xc6, 0x51, 0xd4, 0x0c, 0x0c, 0xe0, 0x59, 0x90, 0x1b, 0xe2, 0xd0, 0x78, 0xa7, 0xe6,
|
||||
0x78, 0x6e, 0xec, 0x5a, 0xff, 0xa8, 0x0a, 0x27, 0xce, 0x0e, 0x73, 0x62, 0x23, 0xde, 0xa9, 0xdd,
|
||||
0x70, 0x63, 0xd7, 0x9e, 0x41, 0x55, 0xf5, 0x4d, 0x9e, 0x87, 0x62, 0x62, 0xc5, 0xd9, 0x0f, 0x63,
|
||||
0xca, 0xac, 0x7f, 0x56, 0xc5, 0xc1, 0x5f, 0xb8, 0x97, 0xad, 0x57, 0xc3, 0x98, 0xda, 0xd3, 0xd4,
|
||||
0xf8, 0x62, 0xe4, 0x02, 0x4c, 0x7b, 0xb4, 0x1b, 0x32, 0x3f, 0xc6, 0x23, 0xb1, 0xfe, 0x55, 0x15,
|
||||
0xd7, 0xbd, 0x20, 0xa9, 0xe2, 0x1c, 0xc8, 0x33, 0xb0, 0xdc, 0x0f, 0xed, 0x4e, 0xaf, 0xeb, 0xf1,
|
||||
0xa3, 0xc7, 0x34, 0xf9, 0xd1, 0x2a, 0xd7, 0x5b, 0xcf, 0x5b, 0x39, 0xfb, 0x54, 0x1f, 0x90, 0xbf,
|
||||
0x22, 0x24, 0x31, 0x71, 0x6e, 0xc2, 0x99, 0xe4, 0xf6, 0xb2, 0x9d, 0x5e, 0xab, 0xd5, 0xf1, 0x83,
|
||||
0x76, 0x0a, 0x91, 0x7f, 0xac, 0x4d, 0x25, 0x08, 0xbc, 0xa5, 0x24, 0x0d, 0x80, 0x7e, 0x0a, 0x4e,
|
||||
0xab, 0xd4, 0x1a, 0x6c, 0xe8, 0x27, 0xda, 0x90, 0x42, 0xd7, 0x41, 0x76, 0x9e, 0x34, 0x00, 0x51,
|
||||
0x1b, 0xc2, 0xb0, 0x7e, 0xaa, 0x4d, 0x2c, 0xf4, 0xf9, 0x82, 0x01, 0x3d, 0xa1, 0x41, 0x31, 0xab,
|
||||
0xfd, 0x33, 0xad, 0x3d, 0x9f, 0x75, 0xe0, 0xd0, 0xdd, 0xa0, 0xd4, 0x73, 0x76, 0x5c, 0xb6, 0xf3,
|
||||
0x48, 0xdd, 0xfa, 0x39, 0xb7, 0x51, 0x18, 0xb6, 0x1b, 0x94, 0x7a, 0x37, 0x85, 0xdc, 0x90, 0xdd,
|
||||
0x30, 0x0c, 0xbd, 0xad, 0x0d, 0xf5, 0xef, 0x86, 0xb6, 0xf3, 0x20, 0x14, 0xb3, 0xd8, 0xfe, 0x0b,
|
||||
0x1d, 0xc6, 0xcc, 0xed, 0x34, 0xb0, 0x5f, 0x85, 0x99, 0x0c, 0x2e, 0xff, 0x52, 0x2f, 0x33, 0x7d,
|
||||
0x3b, 0x05, 0xca, 0xab, 0x09, 0x08, 0xe8, 0xec, 0x97, 0xce, 0x31, 0xeb, 0x57, 0xab, 0x3c, 0x79,
|
||||
0x70, 0xa3, 0x51, 0x2a, 0x81, 0x00, 0x74, 0x8c, 0x19, 0xfa, 0x1a, 0xa2, 0x12, 0xfd, 0x5f, 0xf7,
|
||||
0xe9, 0x27, 0x68, 0xa5, 0xf4, 0xaf, 0xc1, 0x52, 0xc3, 0x8d, 0x9b, 0x02, 0x41, 0xfa, 0x0d, 0xfc,
|
||||
0x46, 0x1b, 0x58, 0x94, 0x62, 0x7d, 0x16, 0xb6, 0x40, 0x42, 0x81, 0x89, 0xbb, 0xef, 0xac, 0x1e,
|
||||
0x11, 0x77, 0x85, 0x6d, 0x09, 0x05, 0x06, 0xf2, 0x7e, 0x2a, 0x81, 0xa9, 0x54, 0xcd, 0xff, 0xed,
|
||||
0xea, 0x71, 0x6b, 0xbe, 0xb0, 0x2f, 0x61, 0x39, 0x55, 0xf1, 0x9f, 0x85, 0x82, 0xb9, 0x71, 0xd6,
|
||||
0xbb, 0xab, 0x02, 0x7c, 0xce, 0x1f, 0x01, 0x01, 0x85, 0xcd, 0x29, 0x63, 0x43, 0x2b, 0x5d, 0x18,
|
||||
0xe5, 0x9d, 0x20, 0xb9, 0x02, 0xa5, 0xe4, 0xe6, 0xee, 0xd3, 0x88, 0xf9, 0x61, 0x60, 0xe5, 0x04,
|
||||
0x76, 0x14, 0x15, 0xfd, 0x55, 0x24, 0x93, 0x4b, 0x50, 0x54, 0x57, 0x53, 0x49, 0xe6, 0xb1, 0xa8,
|
||||
0x4a, 0xb2, 0x12, 0x9c, 0x83, 0x31, 0xbc, 0x71, 0x23, 0x82, 0x8d, 0x1f, 0x95, 0x3f, 0xe6, 0x80,
|
||||
0xf4, 0x47, 0x4b, 0x6a, 0x30, 0xe7, 0xb6, 0xdb, 0x11, 0x6d, 0x67, 0x2a, 0x7c, 0x4e, 0x94, 0xe1,
|
||||
0x59, 0x83, 0x97, 0x94, 0xf7, 0x27, 0x60, 0x54, 0xa0, 0x6f, 0x5e, 0xc4, 0x7f, 0x69, 0x58, 0xfc,
|
||||
0xc6, 0x2a, 0x02, 0x83, 0x85, 0x12, 0xb9, 0x1f, 0x66, 0xfc, 0xa0, 0xd9, 0xe9, 0x71, 0x4f, 0x1d,
|
||||
0xd1, 0xfe, 0xa2, 0x97, 0xd3, 0x09, 0x75, 0x8b, 0xb7, 0xc1, 0x57, 0xa0, 0xd4, 0xec, 0xb1, 0x38,
|
||||
0xf4, 0x0e, 0xb4, 0x4b, 0xa3, 0xc2, 0xa5, 0xa2, 0xa4, 0x2b, 0x77, 0x2a, 0x7f, 0xca, 0xc1, 0x94,
|
||||
0x19, 0x91, 0x72, 0x2f, 0xf7, 0x51, 0xdc, 0x1b, 0xb6, 0x1d, 0xf9, 0xe1, 0xdb, 0x31, 0xc8, 0xd5,
|
||||
0x91, 0x81, 0xae, 0xf2, 0x66, 0x5b, 0x59, 0xa0, 0x0e, 0xf3, 0xdb, 0x81, 0x1b, 0xf7, 0x22, 0x2a,
|
||||
0x03, 0x23, 0x09, 0x6b, 0x4b, 0x71, 0x2a, 0xdf, 0x1f, 0x83, 0x62, 0xc6, 0x51, 0x42, 0xe4, 0xd8,
|
||||
0x90, 0x33, 0xa6, 0x86, 0xab, 0x50, 0xc6, 0xe8, 0x8c, 0x9c, 0x94, 0x3e, 0x17, 0x1b, 0xfa, 0x1e,
|
||||
0x0a, 0x00, 0x39, 0x07, 0x05, 0x16, 0xf6, 0xa2, 0xa6, 0xaa, 0x39, 0xb8, 0xff, 0x53, 0x48, 0x43,
|
||||
0x3c, 0x5a, 0x06, 0xf9, 0x89, 0x86, 0x46, 0x85, 0x04, 0x20, 0x49, 0xd8, 0x58, 0x86, 0xa9, 0xd8,
|
||||
0x8d, 0xda, 0x34, 0x46, 0x81, 0x31, 0x14, 0x40, 0x92, 0x10, 0x98, 0x83, 0x31, 0xac, 0x1e, 0x27,
|
||||
0xf0, 0x0e, 0x8a, 0x0f, 0xf2, 0x98, 0xd1, 0xc0, 0x26, 0xb9, 0x8f, 0x26, 0xc6, 0xd3, 0xfd, 0xab,
|
||||
0x6e, 0xb3, 0xb8, 0xb5, 0x2a, 0xcc, 0x6a, 0x71, 0x51, 0xb3, 0x85, 0xce, 0x84, 0xd0, 0x29, 0x27,
|
||||
0x2c, 0x71, 0x8e, 0x5c, 0xfe, 0x1a, 0x2c, 0x61, 0xff, 0xdf, 0x08, 0x7b, 0x81, 0xe7, 0x46, 0x07,
|
||||
0x26, 0x48, 0x59, 0x7f, 0x1d, 0x4f, 0xb0, 0x75, 0x51, 0x88, 0xad, 0x4b, 0x29, 0x0d, 0x52, 0xe4,
|
||||
0xe5, 0xa4, 0xdb, 0x48, 0xac, 0xe3, 0xd8, 0x77, 0x64, 0x88, 0x2a, 0x66, 0x20, 0x6a, 0x50, 0x49,
|
||||
0x10, 0xc3, 0xe2, 0xe0, 0x92, 0xb0, 0x0e, 0x27, 0xb5, 0x74, 0x1f, 0xd0, 0xe2, 0xcc, 0x88, 0x31,
|
||||
0x58, 0x89, 0x5c, 0x06, 0x69, 0xc9, 0xff, 0x82, 0xd5, 0x77, 0x2b, 0x94, 0x81, 0x0f, 0xb5, 0x81,
|
||||
0xf9, 0xcc, 0x0d, 0x91, 0xda, 0xd7, 0x60, 0x69, 0xc0, 0xa6, 0x2b, 0xfd, 0xbf, 0x1b, 0x9b, 0xd8,
|
||||
0x77, 0x00, 0x68, 0xa1, 0xf2, 0x19, 0x38, 0x95, 0xb9, 0xbc, 0x6b, 0x81, 0x77, 0x3d, 0xc9, 0x89,
|
||||
0x8f, 0x97, 0xa9, 0xcb, 0x30, 0x65, 0xa4, 0x9d, 0xb8, 0xec, 0x13, 0x36, 0xe8, 0x8c, 0xab, 0xfc,
|
||||
0x21, 0x07, 0x44, 0x54, 0x3f, 0xea, 0xa5, 0x01, 0x6f, 0xde, 0xd0, 0x73, 0x1e, 0xe6, 0x65, 0xd4,
|
||||
0xe7, 0x6d, 0x70, 0x4e, 0x74, 0xc1, 0x44, 0x5b, 0x78, 0x78, 0x13, 0x39, 0x59, 0x95, 0x5a, 0xa2,
|
||||
0x92, 0xcf, 0xaa, 0xd4, 0x94, 0x8a, 0x0a, 0x6d, 0xe4, 0xa3, 0x84, 0x76, 0x0a, 0x26, 0xb3, 0xe0,
|
||||
0xa0, 0x09, 0x95, 0xb7, 0xc6, 0x60, 0x32, 0x99, 0xf7, 0xc9, 0x02, 0x9c, 0xe8, 0xf6, 0x1a, 0xbb,
|
||||
0xf4, 0x40, 0x22, 0xb6, 0xfc, 0xe2, 0x23, 0xdf, 0x6b, 0x7e, 0xbc, 0xe3, 0x45, 0xee, 0x6b, 0x6e,
|
||||
0xc7, 0x69, 0x46, 0xd4, 0xa3, 0x41, 0xec, 0xbb, 0x1d, 0x26, 0x61, 0x61, 0x5e, 0x73, 0xaf, 0x6b,
|
||||
0x26, 0xb9, 0x06, 0xa7, 0xc4, 0x6c, 0x81, 0xf0, 0x47, 0x3b, 0x7e, 0xdb, 0x6f, 0xf8, 0x1d, 0x3f,
|
||||
0x3e, 0x48, 0x81, 0xc5, 0x92, 0x96, 0xd9, 0xd0, 0x22, 0x78, 0x71, 0xaf, 0x40, 0xc9, 0xb4, 0x20,
|
||||
0xb4, 0x10, 0x40, 0x8a, 0x86, 0x96, 0x10, 0x3d, 0x0d, 0x40, 0xef, 0xf8, 0x72, 0x56, 0x97, 0x20,
|
||||
0x32, 0xc9, 0x29, 0xc8, 0x7e, 0x08, 0x48, 0xe2, 0x64, 0xa3, 0xa3, 0xe0, 0x0a, 0x01, 0xa5, 0x6c,
|
||||
0x72, 0x50, 0xdc, 0x82, 0x71, 0x39, 0xda, 0x08, 0x30, 0x99, 0xb0, 0xd5, 0x27, 0x79, 0x00, 0xca,
|
||||
0xb4, 0xd5, 0xa2, 0x38, 0x33, 0xc9, 0xb1, 0x47, 0x80, 0xc7, 0xa8, 0x5d, 0x4a, 0x18, 0x72, 0xe0,
|
||||
0x21, 0x55, 0x28, 0x19, 0x1b, 0x87, 0x6b, 0xde, 0xd5, 0x79, 0x5a, 0xd4, 0x4c, 0x5c, 0xf6, 0x32,
|
||||
0x4c, 0xab, 0x89, 0xaa, 0x2f, 0xa9, 0x0b, 0x92, 0x83, 0x92, 0xaf, 0x40, 0x81, 0x9f, 0x75, 0x8f,
|
||||
0x39, 0xad, 0x8e, 0xdb, 0x66, 0x98, 0xc3, 0x33, 0xf5, 0x87, 0xee, 0xf9, 0xa8, 0x53, 0xdd, 0x12,
|
||||
0x6a, 0x4f, 0x71, 0x2d, 0x6c, 0x25, 0x98, 0x26, 0x90, 0xa7, 0xe1, 0xf4, 0xe0, 0x93, 0x1e, 0x90,
|
||||
0xea, 0x27, 0x07, 0x9e, 0xba, 0x4c, 0xd7, 0xe7, 0x60, 0xca, 0x58, 0x88, 0x14, 0x61, 0x7c, 0xf3,
|
||||
0x85, 0xcd, 0xed, 0xcd, 0xb5, 0xe7, 0x4a, 0xff, 0xb5, 0x94, 0x9f, 0xc8, 0x91, 0x05, 0x98, 0x41,
|
||||
0xc2, 0xf6, 0xc6, 0x0d, 0x67, 0xe3, 0xff, 0x36, 0xb7, 0x4b, 0x39, 0x41, 0x9f, 0x83, 0xc2, 0xad,
|
||||
0xcd, 0xed, 0x9b, 0x37, 0xec, 0xb5, 0x5b, 0x6b, 0xeb, 0xcf, 0x6d, 0x94, 0xf2, 0x9c, 0x5a, 0xe9,
|
||||
0xc0, 0xa2, 0x18, 0x0c, 0x6c, 0xea, 0x32, 0x7e, 0x79, 0xf7, 0x68, 0x10, 0xdb, 0xb4, 0x19, 0x46,
|
||||
0x1e, 0xef, 0x64, 0xf4, 0x20, 0x84, 0x03, 0x13, 0x16, 0xb3, 0x99, 0x84, 0x8c, 0x13, 0x53, 0x52,
|
||||
0x45, 0xf2, 0x66, 0x15, 0x51, 0x05, 0x70, 0x44, 0x17, 0xc0, 0xca, 0x9b, 0x39, 0x98, 0xd4, 0x50,
|
||||
0x9b, 0x74, 0x40, 0x39, 0xa3, 0x03, 0x22, 0xd7, 0x8d, 0x29, 0x21, 0x5d, 0x7d, 0xd4, 0x4e, 0x61,
|
||||
0x6a, 0x9c, 0x1c, 0x58, 0x84, 0x24, 0x2a, 0x3e, 0x71, 0x28, 0x2a, 0x62, 0xdd, 0x1f, 0x0a, 0x88,
|
||||
0xaf, 0x8f, 0xa8, 0x87, 0x45, 0x01, 0xb6, 0xc3, 0x4a, 0x79, 0xd7, 0x15, 0x5d, 0x5e, 0x7f, 0x29,
|
||||
0x47, 0x86, 0x2e, 0xe5, 0xa7, 0x01, 0xf4, 0xc3, 0x81, 0x5c, 0x7c, 0x92, 0xa9, 0x07, 0x03, 0x0e,
|
||||
0x42, 0x8d, 0xd0, 0x3b, 0x10, 0xe9, 0x77, 0x08, 0x08, 0x99, 0x8d, 0x6a, 0xe8, 0x1d, 0xd8, 0x42,
|
||||
0x29, 0x0d, 0x42, 0x63, 0x19, 0x10, 0xe2, 0xb9, 0x29, 0xbd, 0x34, 0xc3, 0xbf, 0x8b, 0x55, 0xbc,
|
||||
0x84, 0x2c, 0x63, 0xd7, 0x1e, 0x80, 0xb2, 0x76, 0x54, 0x49, 0x7f, 0x80, 0xd2, 0xc5, 0xc4, 0x61,
|
||||
0x29, 0x7c, 0x01, 0xa6, 0xe5, 0x5b, 0x64, 0x44, 0xf7, 0xa9, 0xdb, 0x91, 0xc5, 0xce, 0x2e, 0x20,
|
||||
0xd5, 0x16, 0x44, 0xb2, 0x0a, 0x93, 0xfa, 0x21, 0xe0, 0xc3, 0xf1, 0x23, 0x3e, 0x04, 0x4c, 0xa8,
|
||||
0xc1, 0xbd, 0xf2, 0xc3, 0x51, 0x28, 0x66, 0x22, 0x27, 0xe7, 0xb3, 0x2b, 0xe7, 0x06, 0x2c, 0xfc,
|
||||
0xa4, 0xb9, 0x70, 0xfe, 0xb8, 0xeb, 0x92, 0xa7, 0xa1, 0x90, 0x9a, 0x50, 0x46, 0xc4, 0x80, 0x72,
|
||||
0xfe, 0x08, 0x15, 0xc2, 0x4e, 0x29, 0x92, 0x5b, 0x40, 0xba, 0x51, 0xd8, 0x0d, 0x19, 0x8d, 0xf0,
|
||||
0x4d, 0xc7, 0x0f, 0xda, 0xcc, 0x1a, 0x15, 0xe6, 0x2e, 0x0f, 0x9d, 0x77, 0xa4, 0xc6, 0x96, 0x54,
|
||||
0xb0, 0xcb, 0xdd, 0x0c, 0x45, 0x18, 0xc6, 0x85, 0x52, 0x86, 0xc7, 0x0e, 0x37, 0xbc, 0x26, 0x35,
|
||||
0xb4, 0x61, 0x37, 0x43, 0xe1, 0x45, 0x71, 0x42, 0x3e, 0x88, 0x30, 0xeb, 0x84, 0x30, 0xb7, 0x3c,
|
||||
0xcc, 0xdc, 0x0d, 0x94, 0xb3, 0x13, 0x05, 0xf2, 0x02, 0x14, 0xf7, 0xc3, 0x4e, 0x2f, 0x88, 0x79,
|
||||
0x3b, 0xc7, 0x8b, 0x04, 0xb3, 0xc6, 0x85, 0x8d, 0xfb, 0x87, 0xe2, 0xa7, 0x12, 0xdf, 0xb8, 0xe3,
|
||||
0xc7, 0xf6, 0xcc, 0xbe, 0xf9, 0xc9, 0xe7, 0xe0, 0xc9, 0x38, 0x72, 0x03, 0xd6, 0xa2, 0x11, 0xb3,
|
||||
0x26, 0x84, 0xa5, 0xa1, 0xc7, 0xb8, 0x2d, 0x05, 0x6d, 0xad, 0x52, 0xf9, 0x4a, 0x0e, 0x0a, 0x37,
|
||||
0xd4, 0xf3, 0x4e, 0xb7, 0x17, 0x0f, 0xad, 0xc4, 0x55, 0x98, 0xed, 0x46, 0x61, 0xd8, 0x72, 0xc2,
|
||||
0x96, 0xd3, 0x0d, 0x19, 0xa3, 0x2c, 0x99, 0xdd, 0x0a, 0x62, 0xfb, 0xc3, 0xd6, 0x8b, 0xad, 0x97,
|
||||
0x12, 0x06, 0x59, 0xbf, 0x17, 0x9e, 0x63, 0x9e, 0x1f, 0x0a, 0xe5, 0xb7, 0x81, 0xe0, 0x49, 0xbb,
|
||||
0x1d, 0x3e, 0x4c, 0x50, 0x6f, 0xe8, 0xe4, 0x30, 0x18, 0x62, 0xf9, 0x3c, 0xd1, 0xd7, 0x32, 0xca,
|
||||
0xa1, 0xa6, 0x91, 0xee, 0x13, 0x2b, 0x7f, 0xce, 0xc1, 0x9c, 0x38, 0x63, 0x5e, 0x8a, 0xcd, 0x4e,
|
||||
0xeb, 0x01, 0x28, 0xa7, 0x60, 0xde, 0xe8, 0xb2, 0x4a, 0x26, 0xd0, 0x8b, 0x86, 0x69, 0xd0, 0x14,
|
||||
0x95, 0x1f, 0x3c, 0x45, 0x7d, 0xac, 0xde, 0xea, 0xd8, 0x23, 0xd8, 0x67, 0xf3, 0x30, 0x25, 0xcf,
|
||||
0x59, 0x6c, 0xe2, 0x27, 0xdc, 0x70, 0x2d, 0xc0, 0x09, 0x77, 0x2f, 0xec, 0x05, 0xaa, 0x9c, 0xc9,
|
||||
0xaf, 0xc3, 0x7b, 0x40, 0xf2, 0x82, 0xf9, 0xe0, 0xd8, 0xed, 0xc5, 0x6a, 0x36, 0xb9, 0x70, 0x8f,
|
||||
0x7c, 0x12, 0x37, 0x15, 0x5b, 0x13, 0xcf, 0xbc, 0xbb, 0xe7, 0x60, 0x32, 0xf6, 0xf7, 0xf8, 0x76,
|
||||
0xed, 0x75, 0xcd, 0x06, 0x46, 0x53, 0x2b, 0x7f, 0x19, 0x81, 0x52, 0x16, 0x3d, 0xf8, 0x34, 0x9f,
|
||||
0x60, 0x90, 0x59, 0xc8, 0xa7, 0x15, 0x15, 0xeb, 0xf8, 0x0d, 0x98, 0xc0, 0x67, 0x63, 0xa7, 0x26,
|
||||
0x11, 0xf3, 0x18, 0xef, 0xc6, 0xe3, 0xa8, 0x5a, 0x33, 0xac, 0xd4, 0xe5, 0xd9, 0x1f, 0xdf, 0x4a,
|
||||
0x9d, 0xdc, 0x82, 0x62, 0x57, 0xa6, 0x06, 0xd6, 0xef, 0x9a, 0xda, 0xbc, 0xab, 0x87, 0x83, 0xa6,
|
||||
0x99, 0x4a, 0xf8, 0x30, 0xa7, 0xec, 0x70, 0x4a, 0x8d, 0x3c, 0x0a, 0x73, 0x89, 0xe1, 0xe4, 0xa4,
|
||||
0x9c, 0x9a, 0x2c, 0x73, 0xf8, 0xac, 0xd4, 0x35, 0x2c, 0x09, 0x7e, 0xad, 0xdf, 0x1f, 0x39, 0xdc,
|
||||
0x7d, 0x4c, 0x7f, 0xea, 0x43, 0xfc, 0x49, 0xb5, 0x83, 0xfd, 0xfe, 0xd4, 0x2b, 0x6f, 0x8c, 0x40,
|
||||
0x29, 0x0b, 0xe6, 0xe4, 0x45, 0x98, 0x36, 0x6a, 0x8f, 0x53, 0x93, 0x23, 0xdb, 0x50, 0x0f, 0xfb,
|
||||
0xe7, 0xae, 0x54, 0xf1, 0xaa, 0x65, 0x0d, 0xd6, 0xe5, 0xb5, 0xf8, 0xa8, 0x06, 0xeb, 0xc4, 0x87,
|
||||
0x45, 0xa6, 0x40, 0xc8, 0x49, 0xfb, 0x2a, 0x8f, 0xf7, 0xc1, 0x61, 0xb6, 0x07, 0x81, 0x17, 0x0e,
|
||||
0xc6, 0x6c, 0x00, 0xa7, 0x36, 0x7c, 0xa9, 0xba, 0xfa, 0xf5, 0xf7, 0x13, 0x5a, 0xaa, 0x5e, 0xf9,
|
||||
0x77, 0x0e, 0xc6, 0x65, 0xea, 0x72, 0xa4, 0x16, 0xc5, 0x42, 0x40, 0x68, 0xc1, 0xc6, 0x0f, 0x4e,
|
||||
0xc5, 0xc4, 0x93, 0xf8, 0x2d, 0x3e, 0xc8, 0xe3, 0x29, 0x88, 0x3c, 0x7f, 0x0f, 0x54, 0x30, 0xe0,
|
||||
0xf1, 0x51, 0x98, 0xdb, 0xa3, 0xd1, 0x6e, 0x87, 0x3a, 0x58, 0xb3, 0xd4, 0xbb, 0xee, 0xdd, 0xf1,
|
||||
0xe4, 0x5d, 0x97, 0xa0, 0xc0, 0x4b, 0x9c, 0xaf, 0x9e, 0x74, 0x57, 0xa0, 0x2c, 0xd5, 0xe2, 0x88,
|
||||
0xca, 0xdf, 0xa5, 0x4c, 0x1c, 0x29, 0x22, 0x77, 0x3b, 0xa2, 0xf8, 0x9b, 0x14, 0xb9, 0x08, 0x0a,
|
||||
0x80, 0xb0, 0x8f, 0x32, 0xde, 0x33, 0xa6, 0x3c, 0xed, 0x55, 0xa5, 0x03, 0xd3, 0xa9, 0x32, 0x3e,
|
||||
0xa4, 0xb5, 0x1f, 0x30, 0x51, 0xe4, 0x07, 0x4e, 0x14, 0x29, 0x58, 0x1d, 0xc9, 0x8e, 0xd6, 0xdf,
|
||||
0xc9, 0xc1, 0x84, 0xaa, 0xf5, 0x1c, 0x99, 0x19, 0x0d, 0x3c, 0x1a, 0xc9, 0xa5, 0xe4, 0x17, 0x37,
|
||||
0x11, 0xd1, 0xa6, 0xdf, 0xf5, 0x69, 0x10, 0xcb, 0x55, 0x34, 0x61, 0x28, 0x9e, 0x97, 0x60, 0xa4,
|
||||
0x45, 0xa9, 0x9c, 0x84, 0xf9, 0x9f, 0x49, 0x35, 0x1e, 0x33, 0xaa, 0xb1, 0x2e, 0x2e, 0x27, 0x52,
|
||||
0xc5, 0x25, 0xe5, 0xf6, 0x78, 0xd6, 0xed, 0x77, 0x72, 0x30, 0x91, 0xfc, 0xb4, 0x75, 0x4e, 0xef,
|
||||
0xac, 0x98, 0x0a, 0xb0, 0x4a, 0xa9, 0x4d, 0x15, 0x73, 0xc1, 0x79, 0x5d, 0x3d, 0x9a, 0xc2, 0xd5,
|
||||
0x7c, 0xea, 0xd7, 0xaa, 0xeb, 0xc2, 0xe1, 0xd3, 0x00, 0xc6, 0x00, 0x22, 0xb7, 0x2a, 0xa9, 0xfd,
|
||||
0xe4, 0x11, 0x98, 0x35, 0x97, 0x19, 0xf0, 0xb6, 0x56, 0x36, 0x96, 0x94, 0x9d, 0xfd, 0x45, 0x28,
|
||||
0xc8, 0x1f, 0x11, 0xcd, 0x79, 0x01, 0x4f, 0x5d, 0x30, 0x64, 0x4b, 0xd1, 0x81, 0x82, 0xf9, 0x73,
|
||||
0x5b, 0xba, 0xe5, 0xce, 0x1d, 0xbb, 0xe5, 0x3e, 0x0d, 0xb0, 0x1f, 0xc6, 0x34, 0x15, 0xec, 0x24,
|
||||
0xa7, 0x88, 0x48, 0x2b, 0x5b, 0x50, 0xbc, 0x99, 0xfc, 0xd8, 0xb8, 0xee, 0xc6, 0xf8, 0x00, 0x6a,
|
||||
0xfe, 0x80, 0x8b, 0x19, 0x07, 0x0d, 0xfd, 0xcb, 0xed, 0x32, 0x4c, 0x99, 0x3f, 0xd9, 0xe6, 0x51,
|
||||
0x20, 0x99, 0x64, 0x58, 0xe5, 0x07, 0x39, 0x28, 0xf7, 0x55, 0xa1, 0x81, 0x1d, 0x58, 0xd5, 0xf8,
|
||||
0x21, 0xba, 0x6f, 0xe4, 0x2b, 0x2b, 0xd6, 0x91, 0x87, 0xbe, 0x8b, 0x80, 0x1d, 0x9a, 0xc3, 0xa7,
|
||||
0x38, 0xfd, 0x7e, 0x5b, 0xb0, 0xa7, 0x1b, 0xc9, 0x84, 0xc7, 0xe5, 0x0e, 0x9d, 0xef, 0xd6, 0x0b,
|
||||
0x6f, 0xbf, 0x7f, 0x26, 0xf7, 0xee, 0xfb, 0x67, 0x72, 0xef, 0xbd, 0x7f, 0x26, 0xd7, 0x38, 0x21,
|
||||
0xfe, 0x2f, 0xe6, 0x91, 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, 0xe3, 0x5d, 0xa4, 0xca, 0x6f, 0x23,
|
||||
0x00, 0x00,
|
||||
0x5b, 0xb2, 0xe7, 0xc7, 0x7f, 0xe9, 0x34, 0xd9, 0x45, 0xaa, 0x47, 0x14, 0x9b, 0xe8, 0x6a, 0xca,
|
||||
0xa3, 0x20, 0xd7, 0x1c, 0xec, 0xac, 0xe7, 0xdc, 0x12, 0x3b, 0xdb, 0x3d, 0x97, 0x6c, 0x87, 0x20,
|
||||
0x9b, 0xb3, 0x39, 0x4e, 0x80, 0x04, 0x08, 0x90, 0x83, 0x61, 0x20, 0x40, 0xc6, 0x71, 0x0e, 0x49,
|
||||
0xee, 0x41, 0x50, 0xf5, 0xaa, 0xba, 0xaa, 0x9b, 0xa4, 0x46, 0xb2, 0x7d, 0x53, 0xbf, 0xad, 0xde,
|
||||
0xab, 0xaa, 0xf7, 0xbd, 0xf7, 0x8a, 0x82, 0xe5, 0x5e, 0x18, 0x44, 0xc1, 0x4a, 0x83, 0xba, 0xcd,
|
||||
0xa0, 0xbb, 0xd2, 0xab, 0xf7, 0x56, 0xf6, 0x6b, 0x2b, 0xd1, 0x41, 0x8f, 0xb2, 0xaa, 0xe0, 0x90,
|
||||
0x05, 0x1a, 0xed, 0xd0, 0x90, 0xf6, 0xf7, 0xaa, 0x28, 0x53, 0xed, 0xd5, 0x7b, 0xd5, 0xfd, 0xda,
|
||||
0xd2, 0x49, 0x54, 0x6c, 0x06, 0x7b, 0x7b, 0x41, 0x77, 0x65, 0x8f, 0x32, 0xe6, 0xb6, 0x95, 0x52,
|
||||
0xe5, 0xbd, 0x39, 0xc8, 0xaf, 0x0b, 0xf1, 0xad, 0xc8, 0x8d, 0x28, 0xa9, 0x40, 0xa1, 0x4d, 0xbb,
|
||||
0x94, 0xf9, 0xcc, 0x89, 0xfc, 0x3d, 0x6a, 0xdd, 0x9d, 0x38, 0x9b, 0xb9, 0x3c, 0x66, 0xe7, 0x25,
|
||||
0x71, 0xdb, 0xdf, 0xa3, 0xa4, 0x06, 0x63, 0xad, 0x20, 0xdc, 0xb5, 0x3e, 0xe0, 0xbc, 0x7c, 0xfd,
|
||||
0x54, 0x75, 0xf8, 0xc2, 0xd5, 0xa7, 0x82, 0x70, 0xd7, 0x16, 0xa2, 0x64, 0x16, 0xc6, 0x58, 0x27,
|
||||
0x88, 0xac, 0xbf, 0xa1, 0x39, 0xf1, 0x41, 0x5e, 0x06, 0xb2, 0xef, 0x76, 0x7c, 0xcf, 0x8d, 0x82,
|
||||
0xd0, 0x09, 0x69, 0xdb, 0x67, 0x51, 0x78, 0x60, 0xfd, 0xae, 0x78, 0x36, 0x77, 0x39, 0x5f, 0x3f,
|
||||
0x37, 0xca, 0xea, 0xab, 0x4a, 0xc5, 0x2e, 0xc7, 0xda, 0xb6, 0x54, 0x26, 0x27, 0x61, 0xb2, 0xe1,
|
||||
0x76, 0xdc, 0x6e, 0x93, 0x32, 0xeb, 0xf7, 0xdc, 0xd0, 0x98, 0x1d, 0x13, 0xc8, 0x0a, 0xcc, 0x76,
|
||||
0xdc, 0x88, 0xb2, 0xc8, 0x09, 0xdd, 0xae, 0xe7, 0x06, 0xce, 0x9e, 0x7f, 0x87, 0x32, 0xeb, 0xbb,
|
||||
0x8b, 0x67, 0x73, 0x97, 0x0b, 0x76, 0x19, 0x79, 0xb6, 0x60, 0x3d, 0xcf, 0x39, 0xe4, 0x21, 0x20,
|
||||
0x52, 0x81, 0x45, 0x6e, 0x18, 0x39, 0x6c, 0xc7, 0x0d, 0x3d, 0xeb, 0x7b, 0x8b, 0x22, 0x86, 0x12,
|
||||
0xb2, 0xb6, 0x38, 0x67, 0x8b, 0x33, 0xc8, 0x2e, 0x9c, 0xec, 0x85, 0x74, 0xdf, 0x0f, 0xfa, 0xcc,
|
||||
0xa1, 0xbd, 0xa0, 0xb9, 0xe3, 0xb8, 0x11, 0x17, 0x71, 0x23, 0x3f, 0xe8, 0x32, 0xeb, 0xab, 0xcb,
|
||||
0x22, 0xb0, 0xab, 0xa3, 0x02, 0x7b, 0x89, 0x76, 0x3d, 0xbf, 0xdb, 0x5e, 0xd3, 0x3a, 0xf6, 0x7d,
|
||||
0xca, 0xde, 0x06, 0x37, 0x67, 0x70, 0x18, 0xf1, 0x61, 0xa9, 0xd9, 0x0f, 0x43, 0xda, 0x8d, 0x86,
|
||||
0xad, 0xf5, 0xb5, 0xe3, 0xaf, 0x65, 0x49, 0x73, 0x83, 0x4b, 0xfd, 0x37, 0x58, 0x71, 0x5c, 0xb7,
|
||||
0xfb, 0x2c, 0xf2, 0x5b, 0x3e, 0xf5, 0x70, 0x55, 0xeb, 0xcd, 0x65, 0xb1, 0x19, 0x0b, 0x4a, 0xe0,
|
||||
0x19, 0xc5, 0x17, 0x66, 0xc8, 0xe3, 0xb0, 0xa8, 0xbc, 0x4c, 0x6b, 0xbe, 0x85, 0x9a, 0xf3, 0x92,
|
||||
0x3f, 0xa8, 0x38, 0x64, 0xcd, 0x30, 0x08, 0x22, 0xeb, 0xeb, 0x5c, 0xb1, 0x60, 0xcf, 0x0f, 0x2c,
|
||||
0x69, 0x07, 0x41, 0x44, 0x1e, 0x85, 0x85, 0xc1, 0x15, 0x85, 0xde, 0x37, 0x50, 0x6f, 0x2e, 0xbd,
|
||||
0xa0, 0x50, 0x7b, 0x0c, 0x16, 0xa4, 0x78, 0x53, 0x44, 0xed, 0x34, 0xfc, 0xa8, 0xe5, 0xd3, 0x8e,
|
||||
0x67, 0x7d, 0x53, 0xfa, 0x99, 0x60, 0xaf, 0x4b, 0x2e, 0xb9, 0x0c, 0xc5, 0x96, 0xdf, 0x75, 0x3b,
|
||||
0xfe, 0xa7, 0xe3, 0xc0, 0xbe, 0x85, 0x0a, 0x33, 0x31, 0x1d, 0x23, 0xba, 0x08, 0x9a, 0x82, 0x0e,
|
||||
0x7d, 0x1b, 0x1d, 0x9a, 0x8e, 0xc9, 0xc2, 0x93, 0x97, 0x81, 0xa8, 0x00, 0x9a, 0x61, 0xc0, 0x58,
|
||||
0xc7, 0xef, 0xee, 0x32, 0xeb, 0xf5, 0x4b, 0x87, 0x67, 0xc5, 0x75, 0x25, 0x6a, 0x97, 0xa5, 0x76,
|
||||
0x4c, 0x61, 0x64, 0x0b, 0x66, 0xe3, 0xcd, 0x34, 0x6c, 0xbe, 0x71, 0x64, 0x9b, 0x44, 0xa9, 0x1b,
|
||||
0x46, 0x75, 0x72, 0x34, 0x3a, 0x41, 0x73, 0x57, 0x84, 0xc4, 0xac, 0xcf, 0x5d, 0x12, 0xc9, 0x24,
|
||||
0x93, 0x63, 0x9d, 0x73, 0x78, 0x54, 0xa9, 0x5c, 0x8a, 0xa8, 0x14, 0xff, 0x7c, 0x42, 0x5c, 0x40,
|
||||
0x10, 0x8a, 0xff, 0x0f, 0xdc, 0x27, 0xc5, 0xdd, 0x66, 0xe4, 0xef, 0x53, 0xc7, 0xef, 0x7a, 0xf4,
|
||||
0x8e, 0xd4, 0xfa, 0x02, 0x6a, 0x2d, 0xa0, 0xc4, 0x9a, 0x10, 0xd8, 0xe4, 0x7c, 0xd4, 0x7d, 0x1c,
|
||||
0x16, 0xd5, 0x52, 0x1d, 0x97, 0xed, 0x50, 0xcf, 0x89, 0x31, 0xe1, 0x8b, 0x97, 0x04, 0x26, 0xcc,
|
||||
0xcb, 0xf5, 0x90, 0xbd, 0xae, 0x00, 0xe2, 0xff, 0x63, 0x80, 0xc0, 0x90, 0x76, 0xa8, 0xeb, 0xd1,
|
||||
0xd0, 0xfa, 0xd2, 0x25, 0x81, 0x73, 0x57, 0x46, 0xed, 0x13, 0xe2, 0xa7, 0x88, 0xf5, 0xa6, 0xd0,
|
||||
0x50, 0x58, 0x62, 0x90, 0xc8, 0x55, 0x28, 0xed, 0xf8, 0x2c, 0x0a, 0x42, 0xbf, 0xe9, 0x76, 0x64,
|
||||
0x1c, 0x5f, 0xc6, 0x38, 0x8a, 0x9a, 0x81, 0x01, 0x3c, 0x0b, 0x72, 0x43, 0x1c, 0x1a, 0xed, 0xd4,
|
||||
0x1c, 0xcf, 0x8d, 0x5c, 0xeb, 0x1f, 0x55, 0xe1, 0xc4, 0xd9, 0x51, 0x4e, 0x6c, 0x44, 0x3b, 0xb5,
|
||||
0x1b, 0x6e, 0xe4, 0xda, 0x33, 0xa8, 0xaa, 0xbe, 0xc9, 0xf3, 0x50, 0x8c, 0xad, 0x38, 0xfb, 0x41,
|
||||
0x44, 0x99, 0xf5, 0xcf, 0xaa, 0x38, 0xf8, 0x0b, 0xf7, 0xb2, 0xf5, 0x6a, 0x10, 0x51, 0x7b, 0x9a,
|
||||
0x1a, 0x5f, 0x8c, 0x5c, 0x80, 0x69, 0x8f, 0xf6, 0x02, 0xe6, 0x47, 0x78, 0x24, 0xd6, 0xbf, 0xaa,
|
||||
0xe2, 0xba, 0x17, 0x24, 0x55, 0x9c, 0x03, 0x79, 0x06, 0x96, 0x07, 0xa1, 0xdd, 0xe9, 0xf7, 0x3c,
|
||||
0x7e, 0xf4, 0x98, 0x26, 0x3f, 0x5a, 0xe5, 0x7a, 0xeb, 0x59, 0x2b, 0x63, 0x9f, 0x1a, 0x00, 0xf2,
|
||||
0x57, 0x84, 0x24, 0x26, 0xce, 0x4d, 0x38, 0x13, 0xdf, 0x5e, 0xb6, 0xd3, 0x6f, 0xb5, 0x3a, 0x7e,
|
||||
0xb7, 0x9d, 0x40, 0xe4, 0x1f, 0x6b, 0x53, 0x31, 0x02, 0x6f, 0x29, 0x49, 0x03, 0xa0, 0x9f, 0x82,
|
||||
0xd3, 0x2a, 0xb5, 0x86, 0x1b, 0xfa, 0x89, 0x36, 0xa4, 0xd0, 0x75, 0x98, 0x9d, 0x27, 0x0d, 0x40,
|
||||
0xd4, 0x86, 0x30, 0xac, 0x9f, 0x6a, 0x13, 0x0b, 0x03, 0xbe, 0x60, 0x40, 0x4f, 0x68, 0x50, 0x4c,
|
||||
0x6b, 0xff, 0x4c, 0x6b, 0xcf, 0xa7, 0x1d, 0x38, 0x74, 0x37, 0x28, 0xf5, 0x9c, 0x1d, 0x97, 0xed,
|
||||
0x3c, 0x52, 0xb7, 0x7e, 0xce, 0x6d, 0x14, 0x46, 0xed, 0x06, 0xa5, 0xde, 0x4d, 0x21, 0x37, 0x62,
|
||||
0x37, 0x0c, 0x43, 0x6f, 0x6b, 0x43, 0x83, 0xbb, 0xa1, 0xed, 0x3c, 0x08, 0xc5, 0x34, 0xb6, 0xff,
|
||||
0x42, 0x87, 0x31, 0x73, 0x3b, 0x09, 0xec, 0x57, 0x61, 0x26, 0x85, 0xcb, 0xbf, 0xd4, 0xcb, 0x4c,
|
||||
0xdf, 0x4e, 0x80, 0xf2, 0x6a, 0x0c, 0x02, 0x3a, 0xfb, 0xa5, 0x73, 0xcc, 0xfa, 0xd5, 0x2a, 0x4f,
|
||||
0x1e, 0xdc, 0x68, 0x94, 0x8a, 0x21, 0x00, 0x1d, 0x63, 0x86, 0xbe, 0x86, 0xa8, 0x58, 0xff, 0xd7,
|
||||
0x03, 0xfa, 0x31, 0x5a, 0x29, 0xfd, 0x6b, 0xb0, 0xd4, 0x70, 0xa3, 0xa6, 0x40, 0x90, 0x41, 0x03,
|
||||
0xbf, 0xd1, 0x06, 0x16, 0xa5, 0xd8, 0x80, 0x85, 0x2d, 0x90, 0x50, 0x60, 0xe2, 0xee, 0x3b, 0xab,
|
||||
0x47, 0xc4, 0x5d, 0x61, 0x5b, 0x42, 0x81, 0x81, 0xbc, 0x9f, 0x8a, 0x61, 0x2a, 0x51, 0xf3, 0x7f,
|
||||
0xbb, 0x7a, 0xdc, 0x9a, 0x2f, 0xec, 0x4b, 0x58, 0x4e, 0x54, 0xfc, 0x67, 0xa1, 0x60, 0x6e, 0x9c,
|
||||
0xf5, 0xee, 0xaa, 0x00, 0x9f, 0xf3, 0x47, 0x40, 0x40, 0x61, 0x33, 0x6f, 0x6c, 0x68, 0xa5, 0x07,
|
||||
0x63, 0xbc, 0x13, 0x24, 0x57, 0xa0, 0x14, 0xdf, 0xdc, 0x7d, 0x1a, 0x32, 0x3f, 0xe8, 0x5a, 0x19,
|
||||
0x81, 0x1d, 0x45, 0x45, 0x7f, 0x15, 0xc9, 0xe4, 0x12, 0x14, 0xd5, 0xd5, 0x54, 0x92, 0x59, 0x2c,
|
||||
0xaa, 0x92, 0xac, 0x04, 0xe7, 0x60, 0x1c, 0x6f, 0x5c, 0x4e, 0xb0, 0xf1, 0xa3, 0xf2, 0xc7, 0x0c,
|
||||
0x90, 0xc1, 0x68, 0x49, 0x0d, 0xe6, 0xdc, 0x76, 0x3b, 0xa4, 0xed, 0x54, 0x85, 0xcf, 0x88, 0x32,
|
||||
0x3c, 0x6b, 0xf0, 0xe2, 0xf2, 0xfe, 0x04, 0x8c, 0x09, 0xf4, 0xcd, 0x8a, 0xf8, 0x2f, 0x8d, 0x8a,
|
||||
0xdf, 0x58, 0x45, 0x60, 0xb0, 0x50, 0x22, 0xf7, 0xc3, 0x8c, 0xdf, 0x6d, 0x76, 0xfa, 0xdc, 0x53,
|
||||
0x47, 0xb4, 0xbf, 0xe8, 0xe5, 0x74, 0x4c, 0xdd, 0xe2, 0x6d, 0xf0, 0x15, 0x28, 0x35, 0xfb, 0x2c,
|
||||
0x0a, 0xbc, 0x03, 0xed, 0xd2, 0x98, 0x70, 0xa9, 0x28, 0xe9, 0xca, 0x9d, 0xca, 0x9f, 0x32, 0x90,
|
||||
0x37, 0x23, 0x52, 0xee, 0x65, 0x3e, 0x8a, 0x7b, 0xa3, 0xb6, 0x23, 0x3b, 0x7a, 0x3b, 0x86, 0xb9,
|
||||
0x9a, 0x1b, 0xea, 0x2a, 0x6f, 0xb6, 0x95, 0x05, 0xea, 0x30, 0xbf, 0xdd, 0x75, 0xa3, 0x7e, 0x48,
|
||||
0x65, 0x60, 0x24, 0x66, 0x6d, 0x29, 0x4e, 0xe5, 0xfb, 0xe3, 0x50, 0x4c, 0x39, 0x4a, 0x88, 0x1c,
|
||||
0x1b, 0x32, 0xc6, 0xd4, 0x70, 0x15, 0xca, 0x18, 0x9d, 0x91, 0x93, 0xd2, 0xe7, 0x62, 0x43, 0xdf,
|
||||
0x43, 0x01, 0x20, 0xe7, 0xa0, 0xc0, 0x82, 0x7e, 0xd8, 0x54, 0x35, 0x07, 0xf7, 0x3f, 0x8f, 0x34,
|
||||
0xc4, 0xa3, 0x65, 0x90, 0x9f, 0x68, 0x68, 0x4c, 0x48, 0x00, 0x92, 0x84, 0x8d, 0x65, 0xc8, 0x47,
|
||||
0x6e, 0xd8, 0xa6, 0x11, 0x0a, 0x8c, 0xa3, 0x00, 0x92, 0x84, 0xc0, 0x1c, 0x8c, 0x63, 0xf5, 0x38,
|
||||
0x81, 0x77, 0x50, 0x7c, 0x90, 0xc7, 0x8c, 0x06, 0x36, 0xce, 0x7d, 0x34, 0x31, 0x91, 0xec, 0x5f,
|
||||
0x75, 0x9b, 0xc5, 0xad, 0x55, 0x61, 0x56, 0x8b, 0x8b, 0x9a, 0x2d, 0x74, 0x26, 0x85, 0x4e, 0x39,
|
||||
0x66, 0x89, 0x73, 0xe4, 0xf2, 0xd7, 0x60, 0x09, 0xfb, 0xff, 0x46, 0xd0, 0xef, 0x7a, 0x6e, 0x78,
|
||||
0x60, 0x82, 0x94, 0xf5, 0xd7, 0x89, 0x18, 0x5b, 0x17, 0x85, 0xd8, 0xba, 0x94, 0xd2, 0x20, 0x45,
|
||||
0x5e, 0x8e, 0xbb, 0x8d, 0xd8, 0x3a, 0x8e, 0x7d, 0x47, 0x86, 0xa8, 0x62, 0x0a, 0xa2, 0x86, 0x95,
|
||||
0x04, 0x31, 0x2c, 0x0e, 0x2f, 0x09, 0xeb, 0x70, 0x52, 0x4b, 0x0f, 0x00, 0x2d, 0xce, 0x8c, 0x18,
|
||||
0x83, 0x15, 0xcb, 0xa5, 0x90, 0x96, 0xfc, 0x2f, 0x58, 0x03, 0xb7, 0x42, 0x19, 0xf8, 0x50, 0x1b,
|
||||
0x98, 0x4f, 0xdd, 0x10, 0xa9, 0x7d, 0x0d, 0x96, 0x86, 0x6c, 0xba, 0xd2, 0xff, 0xbb, 0xb1, 0x89,
|
||||
0x03, 0x07, 0x80, 0x16, 0x2a, 0x6d, 0x28, 0x1b, 0x97, 0x77, 0x5b, 0xdc, 0x8e, 0xa1, 0xd7, 0xf7,
|
||||
0x34, 0xc0, 0xc0, 0xbd, 0x9d, 0x6a, 0xc4, 0x37, 0x76, 0x19, 0xf2, 0x3d, 0x57, 0x00, 0x9f, 0xe0,
|
||||
0x63, 0x72, 0x01, 0x92, 0xb8, 0x40, 0xe5, 0x33, 0x70, 0x2a, 0x95, 0x25, 0x6b, 0x5d, 0xef, 0x7a,
|
||||
0x9c, 0x7c, 0x1f, 0x0f, 0x12, 0x96, 0x21, 0x6f, 0xe4, 0xb7, 0xf0, 0x6e, 0xd2, 0x06, 0x9d, 0xda,
|
||||
0x95, 0x3f, 0x64, 0x80, 0x88, 0x32, 0x4b, 0xbd, 0x24, 0xb2, 0xce, 0x1b, 0x7a, 0xce, 0xc3, 0xbc,
|
||||
0x5e, 0xfb, 0xbc, 0xdf, 0xce, 0x88, 0x76, 0x9b, 0x68, 0x0b, 0x0f, 0x6f, 0x22, 0x27, 0xad, 0x52,
|
||||
0x8b, 0x55, 0xb2, 0x69, 0x95, 0x9a, 0x52, 0x51, 0xa1, 0xe5, 0x3e, 0x4a, 0x68, 0xa7, 0x60, 0x2a,
|
||||
0x8d, 0x42, 0x9a, 0x50, 0x79, 0x6b, 0x1c, 0xa6, 0xe2, 0x87, 0x05, 0xb2, 0x00, 0x27, 0x7a, 0xfd,
|
||||
0xc6, 0x2e, 0x3d, 0x90, 0xa5, 0x41, 0x7e, 0xf1, 0xd9, 0xf2, 0x35, 0x3f, 0xda, 0xf1, 0x42, 0xf7,
|
||||
0x35, 0xb7, 0xe3, 0x34, 0x43, 0xea, 0xd1, 0x6e, 0xe4, 0xbb, 0x1d, 0x26, 0xcf, 0x71, 0x5e, 0x73,
|
||||
0xaf, 0x6b, 0x26, 0xb9, 0x06, 0xa7, 0xc4, 0x10, 0x83, 0x38, 0x4b, 0x3b, 0x7e, 0xdb, 0x6f, 0xf8,
|
||||
0x1d, 0x3f, 0x3a, 0x48, 0xa0, 0xd2, 0x92, 0x96, 0xd9, 0xd0, 0x22, 0x98, 0x21, 0x57, 0xa0, 0x64,
|
||||
0x5a, 0x10, 0x5a, 0x88, 0x54, 0x45, 0x43, 0x4b, 0x88, 0x9e, 0x06, 0xa0, 0x77, 0x7c, 0xf9, 0x28,
|
||||
0x20, 0xd1, 0x6a, 0x8a, 0x53, 0x90, 0xfd, 0x10, 0x90, 0xd8, 0xc9, 0x46, 0x47, 0xe1, 0x22, 0x22,
|
||||
0x57, 0xd9, 0xe4, 0xa0, 0xb8, 0x05, 0x13, 0x72, 0x86, 0x12, 0xa8, 0x35, 0x69, 0xab, 0x4f, 0xf2,
|
||||
0x00, 0x94, 0x69, 0xab, 0x45, 0x71, 0x38, 0x93, 0xf3, 0x95, 0x40, 0xa9, 0x31, 0xbb, 0x14, 0x33,
|
||||
0xe4, 0x64, 0x45, 0xaa, 0x50, 0x32, 0x36, 0x0e, 0xd7, 0xbc, 0xab, 0x01, 0xa1, 0xa8, 0x99, 0xb8,
|
||||
0xec, 0x65, 0x98, 0x56, 0xa3, 0xdb, 0x00, 0x7a, 0x14, 0x24, 0x07, 0x25, 0x5f, 0x81, 0x02, 0x3f,
|
||||
0xeb, 0x3e, 0x73, 0x5a, 0x1d, 0xb7, 0xcd, 0x10, 0x2c, 0x66, 0xea, 0x0f, 0xdd, 0xf3, 0xf5, 0xa8,
|
||||
0xba, 0x25, 0xd4, 0x9e, 0xe2, 0x5a, 0xd8, 0xb3, 0x30, 0x4d, 0x20, 0x4f, 0xc3, 0xe9, 0xe1, 0x27,
|
||||
0x3d, 0x04, 0x53, 0x4e, 0x0e, 0x3d, 0x75, 0x89, 0x0b, 0xcf, 0x41, 0xde, 0x58, 0x88, 0x14, 0x61,
|
||||
0x62, 0xf3, 0x85, 0xcd, 0xed, 0xcd, 0xb5, 0xe7, 0x4a, 0xff, 0xb5, 0x94, 0x9d, 0xcc, 0x90, 0x05,
|
||||
0x98, 0x41, 0xc2, 0xf6, 0xc6, 0x0d, 0x67, 0xe3, 0xff, 0x36, 0xb7, 0x4b, 0x19, 0x41, 0x9f, 0x83,
|
||||
0xc2, 0xad, 0xcd, 0xed, 0x9b, 0x37, 0xec, 0xb5, 0x5b, 0x6b, 0xeb, 0xcf, 0x6d, 0x94, 0xb2, 0x9c,
|
||||
0x5a, 0xe9, 0xc0, 0xa2, 0x98, 0x40, 0x6c, 0xea, 0x32, 0x7e, 0x79, 0xf7, 0x38, 0x2a, 0xd0, 0x66,
|
||||
0x10, 0x7a, 0xbc, 0x65, 0xd2, 0x13, 0x17, 0x4e, 0x66, 0x08, 0x3b, 0x33, 0x31, 0x19, 0x47, 0xb3,
|
||||
0xb8, 0x5c, 0x65, 0xcd, 0x72, 0xa5, 0xa0, 0x2a, 0xa7, 0xa1, 0xaa, 0xf2, 0x66, 0x06, 0xa6, 0x34,
|
||||
0xa6, 0xc7, 0xad, 0x56, 0xc6, 0x68, 0xb5, 0xc8, 0x75, 0x63, 0x1c, 0x49, 0x96, 0x39, 0xb5, 0x53,
|
||||
0x98, 0x1a, 0x27, 0x87, 0x56, 0x3b, 0x09, 0xbf, 0x4f, 0x1c, 0x0a, 0xbf, 0x88, 0x81, 0x23, 0x91,
|
||||
0xf7, 0xf5, 0x9c, 0x7a, 0xc1, 0x14, 0xa8, 0x3e, 0xaa, 0x67, 0x90, 0xa8, 0x3a, 0xd8, 0x33, 0x20,
|
||||
0x43, 0xf7, 0x0c, 0xa7, 0x01, 0xf4, 0x0b, 0x85, 0x5c, 0x7c, 0x8a, 0xa9, 0x97, 0x09, 0x0e, 0x42,
|
||||
0x8d, 0xc0, 0x3b, 0x10, 0xe9, 0x77, 0x08, 0x08, 0x99, 0x1d, 0x71, 0xe0, 0x1d, 0xd8, 0x42, 0x29,
|
||||
0x09, 0x42, 0xe3, 0x29, 0x10, 0xe2, 0xb9, 0x69, 0x60, 0xbf, 0x0a, 0xff, 0x2e, 0xb6, 0x0b, 0x25,
|
||||
0x5d, 0x03, 0xe4, 0xae, 0x3d, 0x00, 0x65, 0xed, 0xa8, 0x92, 0xfe, 0x00, 0xa5, 0x8b, 0xb1, 0xc3,
|
||||
0x52, 0xf8, 0x02, 0x4c, 0xcb, 0x47, 0xcf, 0x90, 0xee, 0x53, 0xb7, 0x23, 0xab, 0xaa, 0x5d, 0x40,
|
||||
0xaa, 0x2d, 0x88, 0x64, 0x15, 0xa6, 0xf4, 0x8b, 0xc3, 0x87, 0x13, 0x47, 0x7c, 0x71, 0x98, 0x54,
|
||||
0x2f, 0x04, 0x95, 0x1f, 0x8e, 0x41, 0x31, 0x15, 0x39, 0x39, 0x9f, 0x5e, 0x39, 0x33, 0x64, 0xe1,
|
||||
0x27, 0xcd, 0x85, 0xb3, 0xc7, 0x5d, 0x97, 0x3c, 0x0d, 0x85, 0xc4, 0x28, 0x94, 0x13, 0x93, 0xd0,
|
||||
0xf9, 0x23, 0x54, 0x08, 0x3b, 0xa1, 0x48, 0x6e, 0x01, 0xe9, 0x85, 0x41, 0x2f, 0x60, 0x34, 0xc4,
|
||||
0xc7, 0x23, 0xbf, 0xdb, 0x66, 0xd6, 0x98, 0x30, 0x77, 0x79, 0xe4, 0x60, 0x25, 0x35, 0xb6, 0xa4,
|
||||
0x82, 0x5d, 0xee, 0xa5, 0x28, 0xc2, 0x30, 0x2e, 0x94, 0x30, 0x3c, 0x7e, 0xb8, 0xe1, 0x35, 0xa9,
|
||||
0xa1, 0x0d, 0xbb, 0x29, 0x0a, 0x2f, 0x8a, 0x93, 0xf2, 0xe5, 0x85, 0x59, 0x27, 0x84, 0xb9, 0xe5,
|
||||
0x51, 0xe6, 0x6e, 0xa0, 0x9c, 0x1d, 0x2b, 0x90, 0x17, 0xa0, 0xb8, 0x1f, 0x74, 0xfa, 0xdd, 0x88,
|
||||
0xf7, 0x8d, 0xbc, 0x48, 0x30, 0x6b, 0x42, 0xd8, 0xb8, 0x7f, 0x24, 0x7e, 0x2a, 0xf1, 0x8d, 0x3b,
|
||||
0x7e, 0x64, 0xcf, 0xec, 0x9b, 0x9f, 0x7c, 0xe0, 0x9e, 0x8a, 0x42, 0xb7, 0xcb, 0x5a, 0x34, 0x64,
|
||||
0xd6, 0xa4, 0xb0, 0x34, 0xf2, 0x18, 0xb7, 0xa5, 0xa0, 0xad, 0x55, 0x2a, 0x5f, 0xc9, 0x40, 0xe1,
|
||||
0x86, 0x7a, 0x47, 0xea, 0xf5, 0xa3, 0x91, 0x95, 0xb8, 0x0a, 0xb3, 0xbd, 0x30, 0x08, 0x5a, 0x4e,
|
||||
0xd0, 0x72, 0x7a, 0x01, 0x63, 0x94, 0xc5, 0x43, 0x62, 0x41, 0x6c, 0x7f, 0xd0, 0x7a, 0xb1, 0xf5,
|
||||
0x52, 0xcc, 0x20, 0xeb, 0xf7, 0xc2, 0x73, 0xcc, 0xf3, 0x43, 0xa1, 0xfc, 0x36, 0x10, 0x3c, 0x69,
|
||||
0xb7, 0xc3, 0xa7, 0x16, 0xea, 0x8d, 0x1c, 0x51, 0x86, 0x43, 0x2c, 0x1f, 0x5c, 0x06, 0x7a, 0x53,
|
||||
0x39, 0x3d, 0x35, 0x92, 0x0d, 0x69, 0xe5, 0xcf, 0x19, 0x98, 0x13, 0x67, 0xcc, 0x4b, 0xb1, 0xd9,
|
||||
0x69, 0x3d, 0x00, 0xe5, 0x04, 0xcc, 0x1b, 0x5d, 0x56, 0xc9, 0x04, 0x7a, 0xd1, 0x30, 0x0d, 0x1b,
|
||||
0xd7, 0xb2, 0xc3, 0xc7, 0xb5, 0x8f, 0xd5, 0x5b, 0x1d, 0x7b, 0xd6, 0xfb, 0x6c, 0x16, 0xf2, 0xf2,
|
||||
0x9c, 0xc5, 0x26, 0x7e, 0xc2, 0x0d, 0xd7, 0x02, 0x9c, 0x70, 0xf7, 0x82, 0x7e, 0x57, 0x95, 0x33,
|
||||
0xf9, 0x75, 0x78, 0x0f, 0x48, 0x5e, 0x30, 0x5f, 0x36, 0x7b, 0xfd, 0x48, 0x0d, 0x41, 0x17, 0xee,
|
||||
0x91, 0x4f, 0xe2, 0xa6, 0x62, 0x6b, 0xe2, 0x99, 0x77, 0xf7, 0x1c, 0x4c, 0x45, 0xfe, 0x1e, 0xdf,
|
||||
0xae, 0xbd, 0x9e, 0xd9, 0xc0, 0x68, 0x6a, 0xe5, 0x2f, 0x39, 0x28, 0xa5, 0xd1, 0x83, 0xdc, 0x0f,
|
||||
0x33, 0x31, 0x06, 0x99, 0x85, 0x7c, 0x5a, 0x51, 0xb1, 0x8e, 0xdf, 0x80, 0x49, 0x7c, 0x9f, 0x76,
|
||||
0x6a, 0x12, 0x31, 0x8f, 0xf1, 0x40, 0x3d, 0x81, 0xaa, 0x35, 0xc3, 0x4a, 0x5d, 0x9e, 0xfd, 0xf1,
|
||||
0xad, 0xd4, 0xc9, 0x2d, 0x28, 0xf6, 0x64, 0x6a, 0x60, 0xfd, 0xae, 0xa9, 0xcd, 0xbb, 0x7a, 0x38,
|
||||
0x68, 0x9a, 0xa9, 0x84, 0x2f, 0x80, 0xca, 0x0e, 0xa7, 0xd4, 0xc8, 0xa3, 0x30, 0x17, 0x1b, 0x8e,
|
||||
0x4f, 0xca, 0xa9, 0xc9, 0x32, 0x87, 0xef, 0x57, 0x3d, 0xc3, 0x92, 0xe0, 0xd7, 0x06, 0xfd, 0x91,
|
||||
0x53, 0xe4, 0xc7, 0xf4, 0xa7, 0x3e, 0xc2, 0x9f, 0x44, 0x3b, 0x38, 0xe8, 0x4f, 0xbd, 0xf2, 0x46,
|
||||
0x0e, 0x4a, 0x69, 0x30, 0x27, 0x2f, 0xc2, 0xb4, 0x51, 0x7b, 0x9c, 0x9a, 0x1c, 0xd9, 0x46, 0x7a,
|
||||
0x38, 0x38, 0x77, 0x25, 0x8a, 0x57, 0x2d, 0x6d, 0xb0, 0x2e, 0xaf, 0xc5, 0x47, 0x35, 0x58, 0x27,
|
||||
0x3e, 0x2c, 0x32, 0x05, 0x42, 0x4e, 0xd2, 0x57, 0x79, 0xbc, 0x0f, 0x8e, 0xb2, 0x3d, 0x0c, 0xbc,
|
||||
0x70, 0x02, 0x67, 0x43, 0x38, 0xb5, 0xd1, 0x4b, 0xd5, 0xd5, 0xcf, 0xcc, 0x9f, 0xd0, 0x52, 0xf5,
|
||||
0xca, 0xbf, 0x33, 0x30, 0x21, 0x53, 0x97, 0x23, 0xb5, 0x28, 0x16, 0x02, 0x42, 0x0b, 0x36, 0x7e,
|
||||
0x70, 0x2a, 0x26, 0x9e, 0xc4, 0x6f, 0xf1, 0x41, 0x1e, 0x4f, 0x40, 0xe4, 0xf9, 0x7b, 0xa0, 0x82,
|
||||
0x01, 0x8f, 0x8f, 0xc2, 0xdc, 0x1e, 0x0d, 0x77, 0x3b, 0xd4, 0xc1, 0x9a, 0xa5, 0x1e, 0x90, 0xef,
|
||||
0x4e, 0xc4, 0x0f, 0xc8, 0x04, 0x05, 0x5e, 0xe2, 0x7c, 0xf5, 0x76, 0xbc, 0x02, 0x65, 0xa9, 0x16,
|
||||
0x85, 0x54, 0xfe, 0x00, 0x66, 0xe2, 0x48, 0x11, 0xb9, 0xdb, 0x21, 0xc5, 0x1f, 0xbf, 0xc8, 0x45,
|
||||
0x50, 0x00, 0x84, 0x7d, 0x94, 0xf1, 0x70, 0x92, 0xf7, 0xb4, 0x57, 0x95, 0x0e, 0x4c, 0x27, 0xca,
|
||||
0xf8, 0x88, 0xd6, 0x7e, 0xc8, 0x44, 0x91, 0x1d, 0x3a, 0x51, 0x24, 0x60, 0x35, 0x97, 0x1e, 0xad,
|
||||
0xbf, 0x93, 0x81, 0x49, 0x55, 0xeb, 0x39, 0x32, 0x33, 0xda, 0xf5, 0x68, 0x28, 0x97, 0x92, 0x5f,
|
||||
0xdc, 0x44, 0x48, 0x9b, 0x7e, 0xcf, 0xa7, 0xdd, 0x48, 0xae, 0xa2, 0x09, 0x23, 0xf1, 0xbc, 0x04,
|
||||
0xb9, 0x16, 0xa5, 0x72, 0x12, 0xe6, 0x7f, 0xc6, 0xd5, 0x78, 0xdc, 0xa8, 0xc6, 0xba, 0xb8, 0x9c,
|
||||
0x48, 0x14, 0x97, 0x84, 0xdb, 0x13, 0x69, 0xb7, 0xdf, 0xc9, 0xc0, 0x64, 0xfc, 0x1b, 0xda, 0x39,
|
||||
0xbd, 0xb3, 0x62, 0x2a, 0xc0, 0x2a, 0xa5, 0x36, 0x55, 0xcc, 0x05, 0xe7, 0x75, 0xf5, 0x68, 0x0a,
|
||||
0x57, 0xb3, 0x89, 0x9f, 0xc5, 0xae, 0x0b, 0x87, 0x93, 0x8f, 0x3f, 0xb9, 0xf4, 0xe3, 0xcf, 0x23,
|
||||
0x30, 0x6b, 0x2e, 0x33, 0xe4, 0x11, 0xaf, 0x6c, 0x2c, 0x29, 0x3b, 0xfb, 0x8b, 0x50, 0x90, 0xbf,
|
||||
0x56, 0x9a, 0xf3, 0x02, 0x9e, 0xba, 0x60, 0xc8, 0x96, 0xa2, 0x03, 0x05, 0xf3, 0x77, 0xbd, 0x64,
|
||||
0xcb, 0x9d, 0x39, 0x76, 0xcb, 0x7d, 0x1a, 0x60, 0x3f, 0x88, 0x68, 0x22, 0xd8, 0x29, 0x4e, 0x11,
|
||||
0x91, 0x56, 0xb6, 0xa0, 0x78, 0x33, 0xfe, 0x55, 0x73, 0xdd, 0x8d, 0xf0, 0xa5, 0xd5, 0xfc, 0xa5,
|
||||
0x18, 0x33, 0x0e, 0x1a, 0xfa, 0x27, 0xe2, 0x65, 0xc8, 0x9b, 0xbf, 0x0d, 0x67, 0x51, 0x20, 0x9e,
|
||||
0x64, 0x58, 0xe5, 0x07, 0x19, 0x28, 0x0f, 0x54, 0xa1, 0xa1, 0x1d, 0x58, 0xd5, 0xf8, 0xc5, 0x7b,
|
||||
0x60, 0xe4, 0x2b, 0x2b, 0xd6, 0x91, 0x87, 0xbe, 0x8b, 0x80, 0x1d, 0x9a, 0xc3, 0xa7, 0x38, 0xfd,
|
||||
0x50, 0x5c, 0xb0, 0xa7, 0x1b, 0xf1, 0x84, 0xc7, 0xe5, 0x0e, 0x9d, 0xef, 0xd6, 0x0b, 0x6f, 0xbf,
|
||||
0x7f, 0x26, 0xf3, 0xee, 0xfb, 0x67, 0x32, 0xef, 0xbd, 0x7f, 0x26, 0xd3, 0x38, 0x21, 0xfe, 0x01,
|
||||
0xe7, 0x91, 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, 0xee, 0x27, 0x24, 0x41, 0xd8, 0x23, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *BeaconState) Marshal() (dAtA []byte, err error) {
|
||||
@@ -3365,6 +3430,44 @@ func (m *AttestationData) MarshalTo(dAtA []byte) (int, error) {
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (m *AttestationTarget) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalTo(dAtA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *AttestationTarget) MarshalTo(dAtA []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.Slot != 0 {
|
||||
dAtA[i] = 0x8
|
||||
i++
|
||||
i = encodeVarintTypes(dAtA, i, uint64(m.Slot))
|
||||
}
|
||||
if len(m.BlockRoot) > 0 {
|
||||
dAtA[i] = 0x12
|
||||
i++
|
||||
i = encodeVarintTypes(dAtA, i, uint64(len(m.BlockRoot)))
|
||||
i += copy(dAtA[i:], m.BlockRoot)
|
||||
}
|
||||
if len(m.ParentRoot) > 0 {
|
||||
dAtA[i] = 0x1a
|
||||
i++
|
||||
i = encodeVarintTypes(dAtA, i, uint64(len(m.ParentRoot)))
|
||||
i += copy(dAtA[i:], m.ParentRoot)
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
i += copy(dAtA[i:], m.XXX_unrecognized)
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (m *AttestationDataAndCustodyBit) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
@@ -4889,6 +4992,29 @@ func (m *AttestationData) Size() (n int) {
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *AttestationTarget) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
if m.Slot != 0 {
|
||||
n += 1 + sovTypes(uint64(m.Slot))
|
||||
}
|
||||
l = len(m.BlockRoot)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovTypes(uint64(l))
|
||||
}
|
||||
l = len(m.ParentRoot)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovTypes(uint64(l))
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
n += len(m.XXX_unrecognized)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *AttestationDataAndCustodyBit) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
@@ -7801,6 +7927,147 @@ func (m *AttestationData) Unmarshal(dAtA []byte) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *AttestationTarget) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowTypes
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: AttestationTarget: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: AttestationTarget: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Slot", wireType)
|
||||
}
|
||||
m.Slot = 0
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowTypes
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.Slot |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field BlockRoot", wireType)
|
||||
}
|
||||
var byteLen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowTypes
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
byteLen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if byteLen < 0 {
|
||||
return ErrInvalidLengthTypes
|
||||
}
|
||||
postIndex := iNdEx + byteLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthTypes
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.BlockRoot = append(m.BlockRoot[:0], dAtA[iNdEx:postIndex]...)
|
||||
if m.BlockRoot == nil {
|
||||
m.BlockRoot = []byte{}
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field ParentRoot", wireType)
|
||||
}
|
||||
var byteLen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowTypes
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
byteLen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if byteLen < 0 {
|
||||
return ErrInvalidLengthTypes
|
||||
}
|
||||
postIndex := iNdEx + byteLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthTypes
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.ParentRoot = append(m.ParentRoot[:0], dAtA[iNdEx:postIndex]...)
|
||||
if m.ParentRoot == nil {
|
||||
m.ParentRoot = []byte{}
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipTypes(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthTypes
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
return ErrInvalidLengthTypes
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *AttestationDataAndCustodyBit) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
|
||||
@@ -108,6 +108,12 @@ message AttestationData {
|
||||
bytes crosslink_data_root_hash32 = 1005 [deprecated=true];
|
||||
}
|
||||
|
||||
message AttestationTarget {
|
||||
uint64 slot = 1;
|
||||
bytes block_root = 2;
|
||||
bytes parent_root = 3;
|
||||
}
|
||||
|
||||
message AttestationDataAndCustodyBit {
|
||||
AttestationData data = 1;
|
||||
bool custody_bit = 2;
|
||||
|
||||
@@ -47,16 +47,24 @@ var (
|
||||
Usage: "Port used to listening and respond metrics for prometheus.",
|
||||
Value: 8080,
|
||||
}
|
||||
// NoDiscovery specifies whether we are running a local network and have no need for connecting
|
||||
// to the bootstrap nodes in the cloud
|
||||
NoDiscovery = cli.BoolFlag{
|
||||
Name: "no-discovery",
|
||||
Usage: "Enable only local network p2p and do not connect to cloud bootstrap nodes.",
|
||||
}
|
||||
// BootstrapNode tells the beacon node which bootstrap node to connect to
|
||||
BootstrapNode = cli.StringFlag{
|
||||
Name: "bootstrap-node",
|
||||
Usage: "The address of bootstrap node. Beacon node will connect for peer discovery via DHT",
|
||||
Value: "/ip4/35.224.249.2/tcp/30001/p2p/QmQEe7o6hKJdGdSkJRh7WJzS6xrex5f4w2SPR6oWbJNriw",
|
||||
}
|
||||
// RelayNode tells the beacon node which relay node to connect to.
|
||||
RelayNode = cli.StringFlag{
|
||||
Name: "relay-node",
|
||||
Usage: "The address of relay node. The beacon node will connect to the " +
|
||||
"relay node and advertise their address via the relay node to other peers",
|
||||
Value: "",
|
||||
}
|
||||
// P2PPort defines the port to be used by libp2p.
|
||||
P2PPort = cli.IntFlag{
|
||||
@@ -64,8 +72,8 @@ var (
|
||||
Usage: "The port used by libp2p.",
|
||||
Value: 12000,
|
||||
}
|
||||
// ClearDBFlag tells the beacon node to remove any previously stored data at the data directory.
|
||||
ClearDBFlag = cli.BoolFlag{
|
||||
// ClearDB tells the beacon node to remove any previously stored data at the data directory.
|
||||
ClearDB = cli.BoolFlag{
|
||||
Name: "clear-db",
|
||||
Usage: "Clears any previously stored data at the data directory",
|
||||
}
|
||||
|
||||
@@ -30,8 +30,9 @@ type FeatureFlagConfig struct {
|
||||
EnableCrosslinks bool // EnableCrosslinks in epoch processing.
|
||||
EnableCheckBlockStateRoot bool // EnableCheckBlockStateRoot in block processing.
|
||||
EnableHistoricalStatePruning bool // EnableHistoricalStatePruning when updating finalized states.
|
||||
EnableBlockAncestorCache bool //EnableBlockAncestorCache for fork choice optimization.
|
||||
DisableGossipSub bool // DisableGossipSub in p2p messaging.
|
||||
EnableCommitteesCache bool // EnableCommitteesCache for state transition.
|
||||
CacheTreeHash bool // CacheTreeHash determent whether tree hashes will be cached.
|
||||
}
|
||||
|
||||
var featureConfig *FeatureFlagConfig
|
||||
@@ -69,14 +70,14 @@ func ConfigureBeaconFeatures(ctx *cli.Context) {
|
||||
log.Info("Enabled check block state root")
|
||||
cfg.EnableCheckBlockStateRoot = true
|
||||
}
|
||||
if ctx.GlobalBool(CacheTreeHashFlag.Name) {
|
||||
log.Info("Cache tree hashes for ssz")
|
||||
cfg.CacheTreeHash = true
|
||||
}
|
||||
if ctx.GlobalBool(EnableHistoricalStatePruningFlag.Name) {
|
||||
log.Info("Enabled historical state pruning")
|
||||
cfg.EnableHistoricalStatePruning = true
|
||||
}
|
||||
if ctx.GlobalBool(EnableBlockAncestorCacheFlag.Name) {
|
||||
log.Info("Enabled block ancestor cache")
|
||||
cfg.EnableBlockAncestorCache = true
|
||||
}
|
||||
if ctx.GlobalBool(DisableGossipSubFlag.Name) {
|
||||
log.Info("Disabled gossipsub, using floodsub")
|
||||
cfg.DisableGossipSub = true
|
||||
@@ -93,6 +94,10 @@ func ConfigureValidatorFeatures(ctx *cli.Context) {
|
||||
log.Info("Verifying signatures for attestations")
|
||||
cfg.VerifyAttestationSigs = true
|
||||
}
|
||||
if ctx.GlobalBool(CacheTreeHashFlag.Name) {
|
||||
log.Info("Cache tree hashes for ssz")
|
||||
cfg.CacheTreeHash = true
|
||||
}
|
||||
|
||||
InitFeatureConfig(cfg)
|
||||
}
|
||||
|
||||
@@ -5,6 +5,11 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
// CacheTreeHashFlag determines whether to cache tree hashes for ssz.
|
||||
CacheTreeHashFlag = cli.BoolFlag{
|
||||
Name: "enable-cache-tree-hash",
|
||||
Usage: "Cache tree hashes for ssz",
|
||||
}
|
||||
// VerifyAttestationSigsFlag determines whether to verify signatures for attestations.
|
||||
VerifyAttestationSigsFlag = cli.BoolFlag{
|
||||
Name: "enable-attestation-signature-verification",
|
||||
@@ -25,12 +30,6 @@ var (
|
||||
Name: "enable-crosslinks",
|
||||
Usage: "Enable crosslinks in epoch processing, default is disabled.",
|
||||
}
|
||||
// EnableBlockAncestorCacheFlag enables block ancestor cache for LMD GHOST fork choice optimization. I
|
||||
// it is disabled by default.
|
||||
EnableBlockAncestorCacheFlag = cli.BoolFlag{
|
||||
Name: "enable-block-ancestor-cache",
|
||||
Usage: "Enable block ancestor cache for fork choice optimization, default is disabled.",
|
||||
}
|
||||
// EnableCheckBlockStateRootFlag check block state root in block processing. It is disabled by default.
|
||||
EnableCheckBlockStateRootFlag = cli.BoolFlag{
|
||||
Name: "enable-check-block-state-root",
|
||||
@@ -49,7 +48,9 @@ var (
|
||||
)
|
||||
|
||||
// ValidatorFlags contains a list of all the feature flags that apply to the validator client.
|
||||
var ValidatorFlags = []cli.Flag{}
|
||||
var ValidatorFlags = []cli.Flag{
|
||||
CacheTreeHashFlag,
|
||||
}
|
||||
|
||||
// BeaconChainFlags contains a list of all the feature flags that apply to the beacon-chain client.
|
||||
var BeaconChainFlags = []cli.Flag{
|
||||
@@ -57,6 +58,6 @@ var BeaconChainFlags = []cli.Flag{
|
||||
EnableCrosslinksFlag,
|
||||
EnableCheckBlockStateRootFlag,
|
||||
EnableHistoricalStatePruningFlag,
|
||||
EnableBlockAncestorCacheFlag,
|
||||
DisableGossipSubFlag,
|
||||
CacheTreeHashFlag,
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ go_test(
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/bls:go_default_library",
|
||||
"//shared/bytesutil:go_default_library",
|
||||
"//shared/featureconfig:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"//shared/ssz:go_default_library",
|
||||
"//shared/testutil:go_default_library",
|
||||
|
||||
@@ -8,11 +8,18 @@ import (
|
||||
"github.com/gogo/protobuf/proto"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bls"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/keystore"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/ssz"
|
||||
)
|
||||
|
||||
func init() {
|
||||
featureconfig.InitFeatureConfig(&featureconfig.FeatureFlagConfig{
|
||||
CacheTreeHash: false,
|
||||
})
|
||||
}
|
||||
|
||||
func TestDepositInput_GeneratesPb(t *testing.T) {
|
||||
k1, err := keystore.NewKey(rand.Reader)
|
||||
if err != nil {
|
||||
|
||||
@@ -10,6 +10,8 @@ import (
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
const noMsgData = "message contains no data"
|
||||
|
||||
var log = logrus.WithField("prefix", "message-handler")
|
||||
|
||||
// SafelyHandleMessage will recover and log any panic that occurs from the
|
||||
@@ -17,7 +19,7 @@ var log = logrus.WithField("prefix", "message-handler")
|
||||
func SafelyHandleMessage(ctx context.Context, fn func(ctx context.Context, message proto.Message) error, msg proto.Message) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
printedMsg := "message contains no data"
|
||||
printedMsg := noMsgData
|
||||
if msg != nil {
|
||||
printedMsg = proto.MarshalTextString(msg)
|
||||
}
|
||||
|
||||
@@ -55,10 +55,12 @@ type Server struct {
|
||||
topicMapping map[reflect.Type]string
|
||||
bootstrapNode string
|
||||
relayNodeAddr string
|
||||
noDiscovery bool
|
||||
}
|
||||
|
||||
// ServerConfig for peer to peer networking.
|
||||
type ServerConfig struct {
|
||||
NoDiscovery bool
|
||||
BootstrapNodeAddr string
|
||||
RelayNodeAddr string
|
||||
Port int
|
||||
@@ -112,6 +114,7 @@ func NewServer(cfg *ServerConfig) (*Server, error) {
|
||||
topicMapping: make(map[reflect.Type]string),
|
||||
bootstrapNode: cfg.BootstrapNodeAddr,
|
||||
relayNodeAddr: cfg.RelayNodeAddr,
|
||||
noDiscovery: cfg.NoDiscovery,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -139,7 +142,7 @@ func (s *Server) Start() {
|
||||
defer span.End()
|
||||
log.Info("Starting service")
|
||||
|
||||
if s.bootstrapNode != "" {
|
||||
if !s.noDiscovery && s.bootstrapNode != "" {
|
||||
if err := startDHTDiscovery(ctx, s.host, s.bootstrapNode); err != nil {
|
||||
log.Errorf("Could not start peer discovery via DHT: %v", err)
|
||||
}
|
||||
@@ -149,8 +152,7 @@ func (s *Server) Start() {
|
||||
log.Errorf("Failed to bootstrap DHT: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if s.relayNodeAddr != "" {
|
||||
if !s.noDiscovery && s.relayNodeAddr != "" {
|
||||
if err := dialRelayNode(ctx, s.host, s.relayNodeAddr); err != nil {
|
||||
log.Errorf("Could not dial relay node: %v", err)
|
||||
}
|
||||
@@ -161,7 +163,9 @@ func (s *Server) Start() {
|
||||
return
|
||||
}
|
||||
|
||||
startPeerWatcher(ctx, s.host, s.bootstrapNode, s.relayNodeAddr)
|
||||
if !s.noDiscovery {
|
||||
startPeerWatcher(ctx, s.host, s.bootstrapNode, s.relayNodeAddr)
|
||||
}
|
||||
}
|
||||
|
||||
// Stop the main p2p loop.
|
||||
|
||||
@@ -28,7 +28,7 @@ func TestLifecycle(t *testing.T) {
|
||||
t.Errorf("incorrect log. wanted: %s. got: %v", want, msg)
|
||||
}
|
||||
|
||||
// The context should have been cancelled.
|
||||
// The context should have been canceled.
|
||||
if s.ctx.Err() == nil {
|
||||
t.Error("Context was not cancelled")
|
||||
}
|
||||
|
||||
@@ -32,6 +32,9 @@ var _ = shared.Service(&Server{})
|
||||
var _ = Broadcaster(&Server{})
|
||||
var _ = Sender(&Server{})
|
||||
|
||||
const bar = "bar"
|
||||
const testTopic = "test_topic"
|
||||
|
||||
func init() {
|
||||
logrus.SetLevel(logrus.DebugLevel)
|
||||
}
|
||||
@@ -84,7 +87,7 @@ func TestBroadcast_OK(t *testing.T) {
|
||||
|
||||
func TestEmit_OK(t *testing.T) {
|
||||
s, _ := NewServer(&ServerConfig{})
|
||||
p := &testpb.TestMessage{Foo: "bar"}
|
||||
p := &testpb.TestMessage{Foo: bar}
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
@@ -302,8 +305,8 @@ func TestRegisterTopic_WithoutAdapters(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create new server: %v", err)
|
||||
}
|
||||
topic := "test_topic"
|
||||
testMessage := &testpb.TestMessage{Foo: "bar"}
|
||||
topic := testTopic
|
||||
testMessage := &testpb.TestMessage{Foo: bar}
|
||||
|
||||
s.RegisterTopic(topic, testMessage)
|
||||
|
||||
@@ -316,8 +319,8 @@ func TestRegisterTopic_WithoutAdapters(t *testing.T) {
|
||||
defer close(wait)
|
||||
msg := <-ch
|
||||
tmsg := msg.Data.(*testpb.TestMessage)
|
||||
if tmsg.Foo != "bar" {
|
||||
t.Errorf("Expected test message Foo: \"bar\". Got: %v", tmsg)
|
||||
if tmsg.Foo != bar {
|
||||
t.Errorf("Expected test message foo:\"bar\". Got: %v", tmsg)
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -338,8 +341,8 @@ func TestRegisterTopic_WithAdapters(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create new server: %v", err)
|
||||
}
|
||||
topic := "test_topic"
|
||||
testMessage := &testpb.TestMessage{Foo: "bar"}
|
||||
topic := testTopic
|
||||
testMessage := &testpb.TestMessage{Foo: bar}
|
||||
|
||||
i := 0
|
||||
var testAdapter Adapter = func(next Handler) Handler {
|
||||
@@ -368,7 +371,7 @@ func TestRegisterTopic_WithAdapters(t *testing.T) {
|
||||
defer close(wait)
|
||||
msg := <-ch
|
||||
tmsg := msg.Data.(*testpb.TestMessage)
|
||||
if tmsg.Foo != "bar" {
|
||||
if tmsg.Foo != bar {
|
||||
t.Errorf("Expected test message Foo: \"bar\". Got: %v", tmsg)
|
||||
}
|
||||
}()
|
||||
@@ -395,8 +398,8 @@ func TestRegisterTopic_HandlesPanic(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create new server: %v", err)
|
||||
}
|
||||
topic := "test_topic"
|
||||
testMessage := &testpb.TestMessage{Foo: "bar"}
|
||||
topic := testTopic
|
||||
testMessage := &testpb.TestMessage{Foo: bar}
|
||||
|
||||
var panicAdapter Adapter = func(next Handler) Handler {
|
||||
return func(msg Message) {
|
||||
|
||||
@@ -4,6 +4,7 @@ package params
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"time"
|
||||
)
|
||||
|
||||
// BeaconChainConfig contains constant configs for node to participate in beacon chain.
|
||||
@@ -105,18 +106,21 @@ type BeaconChainConfig struct {
|
||||
DomainTransfer uint64 // DomainTransfer defines the BLS signature domain for transfer verification.
|
||||
|
||||
// Prysm constants.
|
||||
GweiPerEth uint64 // GweiPerEth is the amount of gwei corresponding to 1 eth.
|
||||
DepositsForChainStart uint64 // DepositsForChainStart defines how many validator deposits needed to kick off beacon chain.
|
||||
RandBytes uint64 // RandBytes is the number of bytes used as entropy to shuffle validators.
|
||||
BatchBlockLimit uint64 // BatchBlockLimit is maximum number of blocks that can be requested for initial sync.
|
||||
SyncEpochLimit uint64 // SyncEpochLimit is the number of epochs the current node can be behind before it requests for the latest state.
|
||||
MaxNumLog2Validators uint64 // MaxNumLog2Validators is the Max number of validators in Log2 exists given total ETH supply.
|
||||
SyncPollingInterval int64 // SyncPollingInterval queries network nodes for sync status.
|
||||
LogBlockDelay int64 // Number of blocks to wait from the current head before processing logs from the deposit contract.
|
||||
BLSPubkeyLength int // BLSPubkeyLength defines the expected length of BLS public keys in bytes.
|
||||
DefaultBufferSize int // DefaultBufferSize for channels across the Prysm repository.
|
||||
ValidatorPrivkeyFileName string // ValidatorPrivKeyFileName specifies the string name of a validator private key file.
|
||||
WithdrawalPrivkeyFileName string // WithdrawalPrivKeyFileName specifies the string name of a withdrawal private key file.
|
||||
GweiPerEth uint64 // GweiPerEth is the amount of gwei corresponding to 1 eth.
|
||||
DepositsForChainStart uint64 // DepositsForChainStart defines how many validator deposits needed to kick off beacon chain.
|
||||
RandBytes uint64 // RandBytes is the number of bytes used as entropy to shuffle validators.
|
||||
BatchBlockLimit uint64 // BatchBlockLimit is maximum number of blocks that can be requested for initial sync.
|
||||
SyncEpochLimit uint64 // SyncEpochLimit is the number of epochs the current node can be behind before it requests for the latest state.
|
||||
MaxNumLog2Validators uint64 // MaxNumLog2Validators is the Max number of validators in Log2 exists given total ETH supply.
|
||||
SyncPollingInterval int64 // SyncPollingInterval queries network nodes for sync status.
|
||||
LogBlockDelay int64 // Number of blocks to wait from the current head before processing logs from the deposit contract.
|
||||
BLSPubkeyLength int // BLSPubkeyLength defines the expected length of BLS public keys in bytes.
|
||||
DefaultBufferSize int // DefaultBufferSize for channels across the Prysm repository.
|
||||
ValidatorPrivkeyFileName string // ValidatorPrivKeyFileName specifies the string name of a validator private key file.
|
||||
WithdrawalPrivkeyFileName string // WithdrawalPrivKeyFileName specifies the string name of a withdrawal private key file.
|
||||
HashCacheSize int64 // HashCacheSize defines the size of object hashes that are cached.
|
||||
RPCSyncCheck time.Duration // Number of seconds to query the sync service, to find out if the node is synced or not.
|
||||
TestnetContractEndpoint string // TestnetContractEndpoint to fetch the contract address of the Prysmatic Labs testnet.
|
||||
}
|
||||
|
||||
// DepositContractConfig contains the deposits for
|
||||
@@ -228,8 +232,13 @@ var defaultBeaconConfig = &BeaconChainConfig{
|
||||
LogBlockDelay: 2,
|
||||
BLSPubkeyLength: 96,
|
||||
DefaultBufferSize: 10000,
|
||||
HashCacheSize: 100000,
|
||||
WithdrawalPrivkeyFileName: "/shardwithdrawalkey",
|
||||
ValidatorPrivkeyFileName: "/validatorprivatekey",
|
||||
RPCSyncCheck: 1,
|
||||
|
||||
// Testnet misc values.
|
||||
TestnetContractEndpoint: "https://beta.prylabs.net/contract", // defines an http endpoint to fetch the testnet contract addr.
|
||||
}
|
||||
|
||||
var defaultShardConfig = &ShardChainConfig{
|
||||
|
||||
@@ -18,12 +18,8 @@ go_test(
|
||||
"slice_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = ["//shared/ssz:go_default_library"],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_generic_test",
|
||||
srcs = ["slice_generic_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = ["//shared/ssz:go_default_library"],
|
||||
deps = [
|
||||
"//shared/featureconfig:go_default_library",
|
||||
"//shared/ssz:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -1,73 +1,5 @@
|
||||
package sliceutil
|
||||
|
||||
// Intersection of two uint64 slices with time
|
||||
// complexity of approximately O(n) leveraging a map to
|
||||
// check for element existence off by a constant factor
|
||||
// of underlying map efficiency.
|
||||
func Intersection(a []uint64, b []uint64) []uint64 {
|
||||
set := make([]uint64, 0)
|
||||
m := make(map[uint64]bool)
|
||||
|
||||
for i := 0; i < len(a); i++ {
|
||||
m[a[i]] = true
|
||||
}
|
||||
for i := 0; i < len(b); i++ {
|
||||
if _, found := m[b[i]]; found {
|
||||
set = append(set, b[i])
|
||||
}
|
||||
}
|
||||
return set
|
||||
}
|
||||
|
||||
// Union of two uint64 slices with time
|
||||
// complexity of approximately O(n) leveraging a map to
|
||||
// check for element existence off by a constant factor
|
||||
// of underlying map efficiency.
|
||||
func Union(a []uint64, b []uint64) []uint64 {
|
||||
set := make([]uint64, 0)
|
||||
m := make(map[uint64]bool)
|
||||
|
||||
for i := 0; i < len(a); i++ {
|
||||
m[a[i]] = true
|
||||
set = append(set, a[i])
|
||||
}
|
||||
for i := 0; i < len(b); i++ {
|
||||
if _, found := m[b[i]]; !found {
|
||||
set = append(set, b[i])
|
||||
}
|
||||
}
|
||||
return set
|
||||
}
|
||||
|
||||
// Not returns the uint64 in slice a that are
|
||||
// not in slice b with time complexity of approximately
|
||||
// O(n) leveraging a map to check for element existence
|
||||
// off by a constant factor of underlying map efficiency.
|
||||
func Not(a []uint64, b []uint64) []uint64 {
|
||||
set := make([]uint64, 0)
|
||||
m := make(map[uint64]bool)
|
||||
|
||||
for i := 0; i < len(a); i++ {
|
||||
m[a[i]] = true
|
||||
}
|
||||
for i := 0; i < len(b); i++ {
|
||||
if _, found := m[b[i]]; !found {
|
||||
set = append(set, b[i])
|
||||
}
|
||||
}
|
||||
return set
|
||||
}
|
||||
|
||||
// IsIn returns true if a is in b and False otherwise.
|
||||
func IsIn(a uint64, b []uint64) bool {
|
||||
for _, v := range b {
|
||||
if a == v {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IntersectionUint64 of two uint64 slices with time
|
||||
// complexity of approximately O(n) leveraging a map to
|
||||
// check for element existence off by a constant factor
|
||||
@@ -136,74 +68,6 @@ func IsInUint64(a uint64, b []uint64) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Intersectionint64 of two int64 slices with time
|
||||
// complexity of approximately O(n) leveraging a map to
|
||||
// check for element existence off by a constant factor
|
||||
// of underlying map efficiency.
|
||||
func Intersectionint64(a []int64, b []int64) []int64 {
|
||||
set := make([]int64, 0)
|
||||
m := make(map[int64]bool)
|
||||
|
||||
for i := 0; i < len(a); i++ {
|
||||
m[a[i]] = true
|
||||
}
|
||||
for i := 0; i < len(b); i++ {
|
||||
if _, found := m[b[i]]; found {
|
||||
set = append(set, b[i])
|
||||
}
|
||||
}
|
||||
return set
|
||||
}
|
||||
|
||||
// Unionint64 of two int64 slices with time
|
||||
// complexity of approximately O(n) leveraging a map to
|
||||
// check for element existence off by a constant factor
|
||||
// of underlying map efficiency.
|
||||
func Unionint64(a []int64, b []int64) []int64 {
|
||||
set := make([]int64, 0)
|
||||
m := make(map[int64]bool)
|
||||
|
||||
for i := 0; i < len(a); i++ {
|
||||
m[a[i]] = true
|
||||
set = append(set, a[i])
|
||||
}
|
||||
for i := 0; i < len(b); i++ {
|
||||
if _, found := m[b[i]]; !found {
|
||||
set = append(set, b[i])
|
||||
}
|
||||
}
|
||||
return set
|
||||
}
|
||||
|
||||
// Notint64 returns the int64 in slice a that are
|
||||
// not in slice b with time complexity of approximately
|
||||
// O(n) leveraging a map to check for element existence
|
||||
// off by a constant factor of underlying map efficiency.
|
||||
func Notint64(a []int64, b []int64) []int64 {
|
||||
set := make([]int64, 0)
|
||||
m := make(map[int64]bool)
|
||||
|
||||
for i := 0; i < len(a); i++ {
|
||||
m[a[i]] = true
|
||||
}
|
||||
for i := 0; i < len(b); i++ {
|
||||
if _, found := m[b[i]]; !found {
|
||||
set = append(set, b[i])
|
||||
}
|
||||
}
|
||||
return set
|
||||
}
|
||||
|
||||
// IsInint64 returns true if a is in b and False otherwise.
|
||||
func IsInint64(a int64, b []int64) bool {
|
||||
for _, v := range b {
|
||||
if a == v {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IntersectionInt64 of two int64 slices with time
|
||||
// complexity of approximately O(n) leveraging a map to
|
||||
// check for element existence off by a constant factor
|
||||
|
||||
@@ -5,9 +5,16 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/ssz"
|
||||
)
|
||||
|
||||
func init() {
|
||||
featureconfig.InitFeatureConfig(&featureconfig.FeatureFlagConfig{
|
||||
CacheTreeHash: false,
|
||||
})
|
||||
}
|
||||
|
||||
func TestGenericIntersection(t *testing.T) {
|
||||
testCases := []struct {
|
||||
setA []uint64
|
||||
@@ -363,7 +370,7 @@ func BenchmarkIntersection(b *testing.B) {
|
||||
{[]uint64{1}, []uint64{1}, []uint64{1}},
|
||||
}
|
||||
for _, tt := range testCases {
|
||||
Intersection(tt.setA, tt.setB)
|
||||
IntersectionUint64(tt.setA, tt.setB)
|
||||
|
||||
}
|
||||
}
|
||||
@@ -386,7 +393,7 @@ func BenchmarkUnion(b *testing.B) {
|
||||
{[]uint64{1}, []uint64{1}, []uint64{1}},
|
||||
}
|
||||
for _, tt := range testCases {
|
||||
Union(tt.setA, tt.setB)
|
||||
UnionUint64(tt.setA, tt.setB)
|
||||
|
||||
}
|
||||
|
||||
@@ -436,7 +443,7 @@ func BenchmarkNot(b *testing.B) {
|
||||
{[]uint64{1}, []uint64{1}, []uint64{1}},
|
||||
}
|
||||
for _, tt := range testCases {
|
||||
Not(tt.setA, tt.setB)
|
||||
NotUint64(tt.setA, tt.setB)
|
||||
|
||||
}
|
||||
|
||||
@@ -483,7 +490,7 @@ func BenchmarkIsIn(b *testing.B) {
|
||||
{100, []uint64{2, 3, 5, 4, 6}, false},
|
||||
}
|
||||
for _, tt := range testCases {
|
||||
IsIn(tt.a, tt.b)
|
||||
IsInUint64(tt.a, tt.b)
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -5,93 +5,6 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestIntersection(t *testing.T) {
|
||||
testCases := []struct {
|
||||
setA []uint64
|
||||
setB []uint64
|
||||
out []uint64
|
||||
}{
|
||||
{[]uint64{2, 3, 5}, []uint64{3}, []uint64{3}},
|
||||
{[]uint64{2, 3, 5}, []uint64{3, 5}, []uint64{3, 5}},
|
||||
{[]uint64{2, 3, 5}, []uint64{5, 3, 2}, []uint64{5, 3, 2}},
|
||||
{[]uint64{2, 3, 5}, []uint64{2, 3, 5}, []uint64{2, 3, 5}},
|
||||
{[]uint64{2, 3, 5}, []uint64{}, []uint64{}},
|
||||
{[]uint64{}, []uint64{2, 3, 5}, []uint64{}},
|
||||
{[]uint64{}, []uint64{}, []uint64{}},
|
||||
{[]uint64{1}, []uint64{1}, []uint64{1}},
|
||||
}
|
||||
for _, tt := range testCases {
|
||||
result := Intersection(tt.setA, tt.setB)
|
||||
if !reflect.DeepEqual(result, tt.out) {
|
||||
t.Errorf("got %d, want %d", result, tt.out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnion(t *testing.T) {
|
||||
testCases := []struct {
|
||||
setA []uint64
|
||||
setB []uint64
|
||||
out []uint64
|
||||
}{
|
||||
{[]uint64{2, 3, 5}, []uint64{4, 6}, []uint64{2, 3, 5, 4, 6}},
|
||||
{[]uint64{2, 3, 5}, []uint64{3, 5}, []uint64{2, 3, 5}},
|
||||
{[]uint64{2, 3, 5}, []uint64{2, 3, 5}, []uint64{2, 3, 5}},
|
||||
{[]uint64{2, 3, 5}, []uint64{}, []uint64{2, 3, 5}},
|
||||
{[]uint64{}, []uint64{2, 3, 5}, []uint64{2, 3, 5}},
|
||||
{[]uint64{}, []uint64{}, []uint64{}},
|
||||
{[]uint64{1}, []uint64{1}, []uint64{1}},
|
||||
}
|
||||
for _, tt := range testCases {
|
||||
result := Union(tt.setA, tt.setB)
|
||||
if !reflect.DeepEqual(result, tt.out) {
|
||||
t.Errorf("got %d, want %d", result, tt.out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNot(t *testing.T) {
|
||||
testCases := []struct {
|
||||
setA []uint64
|
||||
setB []uint64
|
||||
out []uint64
|
||||
}{
|
||||
{[]uint64{4, 6}, []uint64{2, 3, 5, 4, 6}, []uint64{2, 3, 5}},
|
||||
{[]uint64{3, 5}, []uint64{2, 3, 5}, []uint64{2}},
|
||||
{[]uint64{2, 3, 5}, []uint64{2, 3, 5}, []uint64{}},
|
||||
{[]uint64{2}, []uint64{2, 3, 5}, []uint64{3, 5}},
|
||||
{[]uint64{}, []uint64{2, 3, 5}, []uint64{2, 3, 5}},
|
||||
{[]uint64{}, []uint64{}, []uint64{}},
|
||||
{[]uint64{1}, []uint64{1}, []uint64{}},
|
||||
}
|
||||
for _, tt := range testCases {
|
||||
result := Not(tt.setA, tt.setB)
|
||||
if !reflect.DeepEqual(result, tt.out) {
|
||||
t.Errorf("got %d, want %d", result, tt.out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsIn(t *testing.T) {
|
||||
testCases := []struct {
|
||||
a uint64
|
||||
b []uint64
|
||||
result bool
|
||||
}{
|
||||
{0, []uint64{}, false},
|
||||
{0, []uint64{0}, true},
|
||||
{4, []uint64{2, 3, 5, 4, 6}, true},
|
||||
{100, []uint64{2, 3, 5, 4, 6}, false},
|
||||
}
|
||||
for _, tt := range testCases {
|
||||
result := IsIn(tt.a, tt.b)
|
||||
if result != tt.result {
|
||||
t.Errorf("IsIn(%d, %v)=%v, wanted: %v",
|
||||
tt.a, tt.b, result, tt.result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIntersectionUint64(t *testing.T) {
|
||||
testCases := []struct {
|
||||
setA []uint64
|
||||
@@ -116,31 +29,6 @@ func TestIntersectionUint64(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestIntersectionint64(t *testing.T) {
|
||||
testCases := []struct {
|
||||
setA []int64
|
||||
setB []int64
|
||||
out []int64
|
||||
}{
|
||||
{[]int64{2, 3, 5}, []int64{3}, []int64{3}},
|
||||
{[]int64{2, 3, 5}, []int64{3, 5}, []int64{3, 5}},
|
||||
{[]int64{2, 3, 5}, []int64{5, 3, 2}, []int64{5, 3, 2}},
|
||||
{[]int64{2, 3, 5}, []int64{2, 3, 5}, []int64{2, 3, 5}},
|
||||
{[]int64{2, 3, 5}, []int64{}, []int64{}},
|
||||
{[]int64{}, []int64{2, 3, 5}, []int64{}},
|
||||
{[]int64{}, []int64{}, []int64{}},
|
||||
{[]int64{1}, []int64{1}, []int64{1}},
|
||||
}
|
||||
for _, tt := range testCases {
|
||||
result := Intersectionint64(tt.setA, tt.setB)
|
||||
if !reflect.DeepEqual(result, tt.out) {
|
||||
t.Errorf("got %d, want %d", result, tt.out)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestIntersectionInt64(t *testing.T) {
|
||||
testCases := []struct {
|
||||
setA []int64
|
||||
@@ -189,30 +77,6 @@ func TestUnionUint64(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnionint64(t *testing.T) {
|
||||
testCases := []struct {
|
||||
setA []int64
|
||||
setB []int64
|
||||
out []int64
|
||||
}{
|
||||
{[]int64{2, 3, 5}, []int64{4, 6}, []int64{2, 3, 5, 4, 6}},
|
||||
{[]int64{2, 3, 5}, []int64{3, 5}, []int64{2, 3, 5}},
|
||||
{[]int64{2, 3, 5}, []int64{2, 3, 5}, []int64{2, 3, 5}},
|
||||
{[]int64{2, 3, 5}, []int64{}, []int64{2, 3, 5}},
|
||||
{[]int64{}, []int64{2, 3, 5}, []int64{2, 3, 5}},
|
||||
{[]int64{}, []int64{}, []int64{}},
|
||||
{[]int64{1}, []int64{1}, []int64{1}},
|
||||
}
|
||||
for _, tt := range testCases {
|
||||
result := Unionint64(tt.setA, tt.setB)
|
||||
if !reflect.DeepEqual(result, tt.out) {
|
||||
t.Errorf("got %d, want %d", result, tt.out)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestUnionInt64(t *testing.T) {
|
||||
testCases := []struct {
|
||||
setA []int64
|
||||
@@ -234,6 +98,7 @@ func TestUnionInt64(t *testing.T) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestNotUint64(t *testing.T) {
|
||||
@@ -280,28 +145,6 @@ func TestNotInt64(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestNotint64(t *testing.T) {
|
||||
testCases := []struct {
|
||||
setA []int64
|
||||
setB []int64
|
||||
out []int64
|
||||
}{
|
||||
{[]int64{4, 6}, []int64{2, 3, 5, 4, 6}, []int64{2, 3, 5}},
|
||||
{[]int64{3, 5}, []int64{2, 3, 5}, []int64{2}},
|
||||
{[]int64{2, 3, 5}, []int64{2, 3, 5}, []int64{}},
|
||||
{[]int64{2}, []int64{2, 3, 5}, []int64{3, 5}},
|
||||
{[]int64{}, []int64{2, 3, 5}, []int64{2, 3, 5}},
|
||||
{[]int64{}, []int64{}, []int64{}},
|
||||
{[]int64{1}, []int64{1}, []int64{}},
|
||||
}
|
||||
for _, tt := range testCases {
|
||||
result := Notint64(tt.setA, tt.setB)
|
||||
if !reflect.DeepEqual(result, tt.out) {
|
||||
t.Errorf("got %d, want %d", result, tt.out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsInUint64(t *testing.T) {
|
||||
testCases := []struct {
|
||||
a uint64
|
||||
@@ -322,26 +165,6 @@ func TestIsInUint64(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsInint64(t *testing.T) {
|
||||
testCases := []struct {
|
||||
a int64
|
||||
b []int64
|
||||
result bool
|
||||
}{
|
||||
{0, []int64{}, false},
|
||||
{0, []int64{0}, true},
|
||||
{4, []int64{2, 3, 5, 4, 6}, true},
|
||||
{100, []int64{2, 3, 5, 4, 6}, false},
|
||||
}
|
||||
for _, tt := range testCases {
|
||||
result := IsInint64(tt.a, tt.b)
|
||||
if result != tt.result {
|
||||
t.Errorf("IsIn(%d, %v)=%v, wanted: %v",
|
||||
tt.a, tt.b, result, tt.result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsInInt64(t *testing.T) {
|
||||
testCases := []struct {
|
||||
a int64
|
||||
|
||||
@@ -7,13 +7,20 @@ go_library(
|
||||
"doc.go",
|
||||
"encode.go",
|
||||
"hash.go",
|
||||
"hash_cache.go",
|
||||
"ssz_utils_cache.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/shared/ssz",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//shared/bytesutil:go_default_library",
|
||||
"//shared/featureconfig:go_default_library",
|
||||
"//shared/hashutil:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common:go_default_library",
|
||||
"@com_github_karlseguin_ccache//:go_default_library",
|
||||
"@com_github_prometheus_client_golang//prometheus:go_default_library",
|
||||
"@com_github_prometheus_client_golang//prometheus/promauto:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -24,7 +31,12 @@ go_test(
|
||||
"encode_test.go",
|
||||
"example_and_test.go",
|
||||
"example_encode_test.go",
|
||||
"hash_cache_test.go",
|
||||
"hash_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//shared/bytesutil:go_default_library",
|
||||
"//shared/featureconfig:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -6,6 +6,8 @@ import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
)
|
||||
|
||||
type decodeTest struct {
|
||||
@@ -184,6 +186,12 @@ var decodeTests = []decodeTest{
|
||||
{input: "04000000 0200 01 01", ptr: new(simpleStruct), error: "decode error: input is too long for output type ssz.simpleStruct"},
|
||||
}
|
||||
|
||||
func init() {
|
||||
featureconfig.InitFeatureConfig(&featureconfig.FeatureFlagConfig{
|
||||
CacheTreeHash: false,
|
||||
})
|
||||
}
|
||||
|
||||
func runTests(t *testing.T, decode func([]byte, interface{}) error) {
|
||||
for i, test := range decodeTests {
|
||||
input, err := hex.DecodeString(stripSpace(test.input))
|
||||
|
||||
@@ -7,12 +7,15 @@ import (
|
||||
"reflect"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
||||
)
|
||||
|
||||
const hashLengthBytes = 32
|
||||
const sszChunkSize = 128
|
||||
|
||||
var useCache bool
|
||||
|
||||
// Hashable defines the interface for supporting tree-hash function.
|
||||
type Hashable interface {
|
||||
TreeHashSSZ() ([32]byte, error)
|
||||
@@ -51,6 +54,7 @@ func newHashError(msg string, typ reflect.Type) *hashError {
|
||||
}
|
||||
|
||||
func makeHasher(typ reflect.Type) (hasher, error) {
|
||||
useCache = featureconfig.FeatureConfig().CacheTreeHash
|
||||
kind := typ.Kind()
|
||||
switch {
|
||||
case kind == reflect.Bool ||
|
||||
@@ -64,8 +68,14 @@ func makeHasher(typ reflect.Type) (hasher, error) {
|
||||
kind == reflect.Array && typ.Elem().Kind() == reflect.Uint8:
|
||||
return hashedEncoding, nil
|
||||
case kind == reflect.Slice || kind == reflect.Array:
|
||||
if useCache {
|
||||
return makeSliceHasherCache(typ)
|
||||
}
|
||||
return makeSliceHasher(typ)
|
||||
case kind == reflect.Struct:
|
||||
if useCache {
|
||||
return makeStructHasherCache(typ)
|
||||
}
|
||||
return makeStructHasher(typ)
|
||||
case kind == reflect.Ptr:
|
||||
return makePtrHasher(typ)
|
||||
|
||||
234
shared/ssz/hash_cache.go
Normal file
234
shared/ssz/hash_cache.go
Normal file
@@ -0,0 +1,234 @@
|
||||
package ssz
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/karlseguin/ccache"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrNotMerkleRoot will be returned when a cache object is not a merkle root.
|
||||
ErrNotMerkleRoot = errors.New("object is not a merkle root")
|
||||
// maxCacheSize is 2x of the follow distance for additional cache padding.
|
||||
// Requests should be only accessing blocks within recent blocks within the
|
||||
// Eth1FollowDistance.
|
||||
maxCacheSize = params.BeaconConfig().HashCacheSize
|
||||
// Metrics
|
||||
hashCacheMiss = promauto.NewCounter(prometheus.CounterOpts{
|
||||
Name: "hash_cache_miss",
|
||||
Help: "The number of hash requests that aren't present in the cache.",
|
||||
})
|
||||
hashCacheHit = promauto.NewCounter(prometheus.CounterOpts{
|
||||
Name: "hash_cache_hit",
|
||||
Help: "The number of hash requests that are present in the cache.",
|
||||
})
|
||||
hashCacheSize = promauto.NewGauge(prometheus.GaugeOpts{
|
||||
Name: "hash_cache_size",
|
||||
Help: "The number of hashes in the block cache",
|
||||
})
|
||||
)
|
||||
|
||||
// hashCacheS struct with one queue for looking up by hash.
|
||||
type hashCacheS struct {
|
||||
hashCache *ccache.Cache
|
||||
}
|
||||
|
||||
// root specifies the hash of data in a struct
|
||||
type root struct {
|
||||
Hash common.Hash
|
||||
MerkleRoot []byte
|
||||
}
|
||||
|
||||
// newHashCache creates a new hash cache for storing/accessing root hashes from
|
||||
// memory.
|
||||
func newHashCache() *hashCacheS {
|
||||
return &hashCacheS{
|
||||
hashCache: ccache.New(ccache.Configure().MaxSize(maxCacheSize)),
|
||||
}
|
||||
}
|
||||
|
||||
// RootByEncodedHash fetches Root by the encoded hash of the object. Returns true with a
|
||||
// reference to the root if exists. Otherwise returns false, nil.
|
||||
func (b *hashCacheS) RootByEncodedHash(h common.Hash) (bool, *root, error) {
|
||||
item := b.hashCache.Get(h.Hex())
|
||||
if item == nil {
|
||||
hashCacheMiss.Inc()
|
||||
return false, nil, nil
|
||||
}
|
||||
hashCacheHit.Inc()
|
||||
hInfo, ok := item.Value().(*root)
|
||||
if !ok {
|
||||
return false, nil, ErrNotMerkleRoot
|
||||
}
|
||||
|
||||
return true, hInfo, nil
|
||||
}
|
||||
|
||||
// TrieRootCached computes a trie root and add it to the cache.
|
||||
// if the encoded hash of the object is in cache, it will be retrieved from cache.
|
||||
// This method also trims the least recently added root info. if the cache size
|
||||
// has reached the max cache size limit.
|
||||
func (b *hashCacheS) TrieRootCached(val interface{}) ([32]byte, error) {
|
||||
if val == nil {
|
||||
return [32]byte{}, newHashError("untyped nil is not supported", nil)
|
||||
}
|
||||
rval := reflect.ValueOf(val)
|
||||
hs, err := hashedEncoding(rval)
|
||||
if err != nil {
|
||||
return [32]byte{}, newHashError(fmt.Sprint(err), rval.Type())
|
||||
}
|
||||
exists, fetchedInfo, err := b.RootByEncodedHash(bytesutil.ToBytes32(hs))
|
||||
if err != nil {
|
||||
return [32]byte{}, newHashError(fmt.Sprint(err), rval.Type())
|
||||
}
|
||||
var paddedOutput [32]byte
|
||||
if exists {
|
||||
paddedOutput = bytesutil.ToBytes32(fetchedInfo.MerkleRoot)
|
||||
} else {
|
||||
sszUtils, err := cachedSSZUtils(rval.Type())
|
||||
if err != nil {
|
||||
return [32]byte{}, newHashError(fmt.Sprint(err), rval.Type())
|
||||
}
|
||||
output, err := sszUtils.hasher(rval)
|
||||
if err != nil {
|
||||
return [32]byte{}, newHashError(fmt.Sprint(err), rval.Type())
|
||||
}
|
||||
// Right-pad with 0 to make 32 bytes long, if necessary.
|
||||
paddedOutput = bytesutil.ToBytes32(output)
|
||||
err = b.AddRoot(bytesutil.ToBytes32(hs), paddedOutput[:])
|
||||
if err != nil {
|
||||
return [32]byte{}, newHashError(fmt.Sprint(err), rval.Type())
|
||||
}
|
||||
}
|
||||
return paddedOutput, nil
|
||||
}
|
||||
|
||||
// MerkleHashCached adds a merkle object to the cache. This method also trims the
|
||||
// least recently added root info if the cache size has reached the max cache
|
||||
// size limit.
|
||||
func (b *hashCacheS) MerkleHashCached(byteSlice [][]byte) ([]byte, error) {
|
||||
mh := []byte{}
|
||||
hs, err := hashedEncoding(reflect.ValueOf(byteSlice))
|
||||
if err != nil {
|
||||
return mh, newHashError(fmt.Sprint(err), reflect.TypeOf(byteSlice))
|
||||
}
|
||||
exists, fetchedInfo, err := b.RootByEncodedHash(bytesutil.ToBytes32(hs))
|
||||
if err != nil {
|
||||
return mh, newHashError(fmt.Sprint(err), reflect.TypeOf(byteSlice))
|
||||
}
|
||||
if exists {
|
||||
mh = fetchedInfo.MerkleRoot
|
||||
} else {
|
||||
mh, err = merkleHash(byteSlice)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mr := &root{
|
||||
Hash: bytesutil.ToBytes32(hs),
|
||||
MerkleRoot: mh,
|
||||
}
|
||||
b.hashCache.Set(mr.Hash.Hex(), mr, time.Hour)
|
||||
hashCacheSize.Set(float64(b.hashCache.ItemCount()))
|
||||
}
|
||||
|
||||
return mh, nil
|
||||
}
|
||||
|
||||
// AddRoot adds an encodedhash of the object as key and a rootHash object to the cache.
|
||||
// This method also trims the
|
||||
// least recently added root info if the cache size has reached the max cache
|
||||
// size limit.
|
||||
func (b *hashCacheS) AddRoot(h common.Hash, rootB []byte) error {
|
||||
mr := &root{
|
||||
Hash: h,
|
||||
MerkleRoot: rootB,
|
||||
}
|
||||
b.hashCache.Set(mr.Hash.Hex(), mr, time.Hour)
|
||||
return nil
|
||||
}
|
||||
|
||||
// MakeSliceHasherCache add caching mechanism to slice hasher.
|
||||
func makeSliceHasherCache(typ reflect.Type) (hasher, error) {
|
||||
elemSSZUtils, err := cachedSSZUtilsNoAcquireLock(typ.Elem())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get ssz utils: %v", err)
|
||||
}
|
||||
hasher := func(val reflect.Value) ([]byte, error) {
|
||||
hs, err := hashedEncoding(val)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to encode element of slice/array: %v", err)
|
||||
}
|
||||
exists, fetchedInfo, err := hashCache.RootByEncodedHash(bytesutil.ToBytes32(hs))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to encode element of slice/array: %v", err)
|
||||
}
|
||||
var output []byte
|
||||
if exists {
|
||||
output = fetchedInfo.MerkleRoot
|
||||
} else {
|
||||
var elemHashList [][]byte
|
||||
for i := 0; i < val.Len(); i++ {
|
||||
elemHash, err := elemSSZUtils.hasher(val.Index(i))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to hash element of slice/array: %v", err)
|
||||
}
|
||||
elemHashList = append(elemHashList, elemHash)
|
||||
}
|
||||
output, err = hashCache.MerkleHashCached(elemHashList)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to calculate merkle hash of element hash list: %v", err)
|
||||
}
|
||||
err := hashCache.AddRoot(bytesutil.ToBytes32(hs), output)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to add root to cache: %v", err)
|
||||
}
|
||||
hashCacheSize.Set(float64(hashCache.hashCache.ItemCount()))
|
||||
|
||||
}
|
||||
|
||||
return output, nil
|
||||
}
|
||||
return hasher, nil
|
||||
}
|
||||
|
||||
func makeStructHasherCache(typ reflect.Type) (hasher, error) {
|
||||
fields, err := structFields(typ)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hasher := func(val reflect.Value) ([]byte, error) {
|
||||
hs, err := hashedEncoding(val)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to encode element of slice/array: %v", err)
|
||||
}
|
||||
exists, fetchedInfo, err := hashCache.RootByEncodedHash(bytesutil.ToBytes32(hs))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to encode element of slice/array: %v", err)
|
||||
}
|
||||
var result [32]byte
|
||||
if exists {
|
||||
result = bytesutil.ToBytes32(fetchedInfo.MerkleRoot)
|
||||
return result[:], nil
|
||||
}
|
||||
concatElemHash := make([]byte, 0)
|
||||
for _, f := range fields {
|
||||
elemHash, err := f.sszUtils.hasher(val.Field(f.index))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to hash field of struct: %v", err)
|
||||
}
|
||||
concatElemHash = append(concatElemHash, elemHash...)
|
||||
}
|
||||
result = hashutil.Hash(concatElemHash)
|
||||
return result[:], nil
|
||||
}
|
||||
return hasher, nil
|
||||
}
|
||||
148
shared/ssz/hash_cache_test.go
Normal file
148
shared/ssz/hash_cache_test.go
Normal file
@@ -0,0 +1,148 @@
|
||||
package ssz
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"log"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
)
|
||||
|
||||
type junkObject struct {
|
||||
D2Int64Slice [][]uint64
|
||||
Uint uint64
|
||||
Int64Slice []uint64
|
||||
}
|
||||
|
||||
type tree struct {
|
||||
First []*junkObject
|
||||
Second []*junkObject
|
||||
}
|
||||
|
||||
func generateJunkObject(size uint64) []*junkObject {
|
||||
object := make([]*junkObject, size)
|
||||
for i := uint64(0); i < uint64(len(object)); i++ {
|
||||
d2Int64Slice := make([][]uint64, size)
|
||||
is := make([]uint64, size)
|
||||
uInt := uint64(time.Now().UnixNano())
|
||||
is[i] = i
|
||||
d2Int64Slice[i] = make([]uint64, size)
|
||||
for j := uint64(0); j < uint64(len(object)); j++ {
|
||||
d2Int64Slice[i][j] = i + j
|
||||
}
|
||||
object[i] = &junkObject{
|
||||
D2Int64Slice: d2Int64Slice,
|
||||
Uint: uInt,
|
||||
Int64Slice: is,
|
||||
}
|
||||
|
||||
}
|
||||
return object
|
||||
}
|
||||
|
||||
func TestObjCache_byHash(t *testing.T) {
|
||||
cache := newHashCache()
|
||||
byteSl := [][]byte{{0, 0}, {1, 1}}
|
||||
mr, err := merkleHash(byteSl)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
hs, err := hashedEncoding(reflect.ValueOf(byteSl))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
exists, _, err := cache.RootByEncodedHash(bytesutil.ToBytes32(hs))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if exists {
|
||||
t.Error("Expected block info not to exist in empty cache")
|
||||
}
|
||||
if _, err := cache.MerkleHashCached(byteSl); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
exists, fetchedInfo, err := cache.RootByEncodedHash(bytesutil.ToBytes32(hs))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !exists {
|
||||
t.Error("Expected blockInfo to exist")
|
||||
}
|
||||
if !bytes.Equal(mr, fetchedInfo.MerkleRoot) {
|
||||
t.Errorf(
|
||||
"Expected fetched info number to be %v, got %v",
|
||||
mr,
|
||||
fetchedInfo.MerkleRoot,
|
||||
)
|
||||
}
|
||||
if fetchedInfo.Hash != bytesutil.ToBytes32(hs) {
|
||||
t.Errorf(
|
||||
"Expected fetched info hash to be %v, got %v",
|
||||
hs,
|
||||
fetchedInfo.Hash,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMerkleHashWithCache(t *testing.T) {
|
||||
cache := newHashCache()
|
||||
for i := 0; i < 200; i++ {
|
||||
runMerkleHashTests(t, func(val [][]byte) ([]byte, error) {
|
||||
return merkleHash(val)
|
||||
})
|
||||
}
|
||||
for i := 0; i < 200; i++ {
|
||||
runMerkleHashTests(t, func(val [][]byte) ([]byte, error) {
|
||||
return cache.MerkleHashCached(val)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkHashWithoutCache(b *testing.B) {
|
||||
featureconfig.FeatureConfig().CacheTreeHash = false
|
||||
First := generateJunkObject(100)
|
||||
TreeHash(&tree{First: First, Second: First})
|
||||
for n := 0; n < b.N; n++ {
|
||||
TreeHash(&tree{First: First, Second: First})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkHashWithCache(b *testing.B) {
|
||||
featureconfig.FeatureConfig().CacheTreeHash = true
|
||||
First := generateJunkObject(100)
|
||||
type tree struct {
|
||||
First []*junkObject
|
||||
Second []*junkObject
|
||||
}
|
||||
TreeHash(&tree{First: First, Second: First})
|
||||
for n := 0; n < b.N; n++ {
|
||||
TreeHash(&tree{First: First, Second: First})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlockCache_maxSize(t *testing.T) {
|
||||
maxCacheSize = 10000
|
||||
cache := newHashCache()
|
||||
for i := uint64(0); i < uint64(maxCacheSize+1025); i++ {
|
||||
|
||||
if err := cache.AddRoot(bytesutil.ToBytes32(bytesutil.Bytes4(i)), []byte{1}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
log.Printf(
|
||||
"hash cache key size is %d, itemcount is %d",
|
||||
maxCacheSize,
|
||||
cache.hashCache.ItemCount(),
|
||||
)
|
||||
time.Sleep(1 * time.Second)
|
||||
if int64(cache.hashCache.ItemCount()) > maxCacheSize {
|
||||
t.Errorf(
|
||||
"Expected hash cache key size to be %d, got %d",
|
||||
maxCacheSize,
|
||||
cache.hashCache.ItemCount(),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,7 @@ type sszUtils struct {
|
||||
var (
|
||||
sszUtilsCacheMutex sync.RWMutex
|
||||
sszUtilsCache = make(map[reflect.Type]*sszUtils)
|
||||
hashCache = newHashCache()
|
||||
)
|
||||
|
||||
// Get cached encoder, encodeSizer and decoder implementation for a specified type.
|
||||
|
||||
@@ -7,7 +7,7 @@ go_library(
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@io_opencensus_go//exporter/jaeger:go_default_library",
|
||||
"@io_opencensus_go//trace:go_default_library",
|
||||
"@io_opencensus_go_contrib_exporter_jaeger//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -3,8 +3,8 @@ package tracing
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"contrib.go.opencensus.io/exporter/jaeger"
|
||||
"github.com/sirupsen/logrus"
|
||||
"go.opencensus.io/exporter/jaeger"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ go_library(
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@com_github_urfave_cli//:go_default_library",
|
||||
"@com_github_x_cray_logrus_prefixed_formatter//:go_default_library",
|
||||
"@org_golang_x_crypto//ssh/terminal:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -49,6 +50,7 @@ go_image(
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@com_github_urfave_cli//:go_default_library",
|
||||
"@com_github_x_cray_logrus_prefixed_formatter//:go_default_library",
|
||||
"@org_golang_x_crypto//ssh/terminal:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ go_test(
|
||||
srcs = ["account_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//shared/featureconfig:go_default_library",
|
||||
"//shared/keystore:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"//shared/testutil:go_default_library",
|
||||
|
||||
@@ -6,6 +6,8 @@ import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/shared/keystore"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
@@ -87,3 +89,23 @@ func NewValidatorAccount(directory string, password string) error {
|
||||
`, serializedData)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Exists checks if a validator account at a given keystore path exists.
|
||||
func Exists(keystorePath string) (bool, error) {
|
||||
/* #nosec */
|
||||
f, err := os.Open(keystorePath)
|
||||
if err != nil {
|
||||
return false, nil
|
||||
}
|
||||
defer func() {
|
||||
if err := f.Close(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}()
|
||||
|
||||
_, err = f.Readdirnames(1) // Or f.Readdir(1)
|
||||
if err == io.EOF {
|
||||
return false, nil
|
||||
}
|
||||
return true, err
|
||||
}
|
||||
|
||||
@@ -6,11 +6,18 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/keystore"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
)
|
||||
|
||||
func init() {
|
||||
featureconfig.InitFeatureConfig(&featureconfig.FeatureFlagConfig{
|
||||
CacheTreeHash: false,
|
||||
})
|
||||
}
|
||||
|
||||
func TestNewValidatorAccount_AccountExists(t *testing.T) {
|
||||
directory := testutil.TempDir() + "/testkeystore"
|
||||
defer os.RemoveAll(directory)
|
||||
|
||||
@@ -51,6 +51,7 @@ go_test(
|
||||
"//proto/beacon/rpc/v1:go_default_library",
|
||||
"//shared:go_default_library",
|
||||
"//shared/bitutil:go_default_library",
|
||||
"//shared/featureconfig:go_default_library",
|
||||
"//shared/keystore:go_default_library",
|
||||
"//shared/mathutil:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
|
||||
@@ -28,7 +28,7 @@ type Validator interface {
|
||||
}
|
||||
|
||||
// Run the main validator routine. This routine exits if the context is
|
||||
// cancelled.
|
||||
// canceled.
|
||||
//
|
||||
// Order of operations:
|
||||
// 1 - Initialize validator data
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/shared"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/keystore"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil"
|
||||
"github.com/prysmaticlabs/prysm/validator/accounts"
|
||||
@@ -34,6 +35,12 @@ func keySetup() {
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
featureconfig.InitFeatureConfig(&featureconfig.FeatureFlagConfig{
|
||||
CacheTreeHash: false,
|
||||
})
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
dir := testutil.TempDir() + "/keystore1"
|
||||
defer os.RemoveAll(dir)
|
||||
@@ -62,7 +69,7 @@ func TestStop_CancelsContext(t *testing.T) {
|
||||
|
||||
func TestLifecycle(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
// Use cancelled context so that the run function exits immediately..
|
||||
// Use canceled context so that the run function exits immediately..
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
cancel()
|
||||
validatorService := &ValidatorService{
|
||||
@@ -81,7 +88,7 @@ func TestLifecycle(t *testing.T) {
|
||||
|
||||
func TestLifecycle_Insecure(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
// Use cancelled context so that the run function exits immediately.
|
||||
// Use canceled context so that the run function exits immediately.
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
cancel()
|
||||
validatorService := &ValidatorService{
|
||||
|
||||
@@ -67,7 +67,7 @@ func (v *validator) WaitForChainStart(ctx context.Context) error {
|
||||
// Once the ChainStart log is received, we update the genesis time of the validator client
|
||||
// and begin a slot ticker used to track the current slot the beacon node is in.
|
||||
v.ticker = slotutil.GetSlotTicker(time.Unix(int64(v.genesisTime), 0), params.BeaconConfig().SecondsPerSlot)
|
||||
log.Infof("Beacon chain initialized at unix time: %v", time.Unix(int64(v.genesisTime), 0))
|
||||
log.WithField("genesisTime", time.Unix(int64(v.genesisTime), 0)).Info("Beacon chain initialized")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user