Update run time to v0.9 (#3935)

* Update seed domains (#3872)

* Remove Transfers (#3870)

* Remove active index roots and compact committee roots (#3869)

* Update inclusion reward (#3886)

* Alter proposer selection logic (#3884)

* Fix early committee bias (#3888)

* Remove shards and committees (#3896)

* Epoch spec tests v0.9 (#3907)

* Block spec test v0.9 (#3905)

* rm'ed in protobuf

* build proto

* build proto

* build proto

* fix core package

* Gazelle

* Fixed all the tests

* Fixed static test

* Comment out spec test for now

* One more skip

* fix-roundRobinSync (#3862)

* Starting but need new seed function

* Revert initial sync

* Updated Proposer Slashing

* Fixed all tests

* Lint

* Update inclusion reward

* Fill randao mixes with eth1 data hash

* Test

* Fixing test part1

* All tests passing

* One last test

* Updated config

* Build proto

* Proper skip message

* Conflict and fmt

* Removed crosslinks and shards. Built

* Format and gazelle

* Fixed all the block package tests

* Fixed all the helper tests

* All epoch package tests pass

* All core package tests pass

* Fixed operation tests

* Started fixing rpc test

* RPC tests passed!

* Fixed all init sync tests

* All tests pass

* Fixed blockchain tests

* Lint

* Lint

* Preston's feedback

* Starting

* Remove container

* Fixed block spec tests

* All passing except for block_processing test

* Failing block processing test

* Starting

* Add AggregateAndProof

* All mainnet test passes

* Update deposit contract (#3906)

* Proto spec tests v0.9 (#3908)

* Starting

* Add AggregateAndProof

* Unskip block util tests (#3910)

* rm'ed in protobuf

* build proto

* build proto

* build proto

* fix core package

* Gazelle

* Fixed all the tests

* Fixed static test

* Comment out spec test for now

* One more skip

* fix-roundRobinSync (#3862)

* Starting but need new seed function

* Revert initial sync

* Updated Proposer Slashing

* Fixed all tests

* Lint

* Update inclusion reward

* Fill randao mixes with eth1 data hash

* Test

* Fixing test part1

* All tests passing

* One last test

* Updated config

* Build proto

* Proper skip message

* Conflict and fmt

* Removed crosslinks and shards. Built

* Format and gazelle

* Fixed all the block package tests

* Fixed all the helper tests

* All epoch package tests pass

* All core package tests pass

* Fixed operation tests

* Started fixing rpc test

* RPC tests passed!

* Fixed all init sync tests

* All tests pass

* Fixed blockchain tests

* Lint

* Lint

* Preston's feedback

* Starting

* Remove container

* Fixed block spec tests

* All passing except for block_processing test

* Failing block processing test

* Starting

* Add AggregateAndProof

* All mainnet test passes

* Unskip block util tests

* Slot processing spec test V0.9 (#3912)

* Starting

* Add AggregateAndProof

* Unskip slot processing mainnet test

* Unskip minimal spec test for finalization (#3920)

* Remove outdated interop tests (#3922)

* Rm outdated interop tests

* Rm test runner

* Gazelle

* Update validator to use proposer slot (#3919)

* Fix committee assignment (#3931)

* Replace shard with committee index (#3930)

* Conflict

* Clean up (#3933)

* Remove shard filter in db (#3936)

* Remove lightouse compatibility test (#3939)

* Update Committee Cache for v0.9 (#3948)

* Updated committee cache

* Removed shuffled indices cache

* Started testing run time

* Lint

* Fixed test

* Safeguard against nil head state

* address edge case

* add test

* Fixed TestRoundRobinSync by doubling the epochs

* Unskip TestProtoCompatability (#3958)

* Unskip TestProtoCompatability

* Update WORKSPACE

* Fix minimal config (#3959)

* fix minimal configs

* fix hardcoded value in test

* Simplify verify att time (#3961)

* update readme for deposit contract, regen bindings for vyper 0.1.0b12 (#3963)

* update readme for deposit contract, regen bindings

* medium

* Check nil base state (#3964)

* Copy Block When Receiving it From Sync (#3966)

* copy block

* clone for other service methods too

* Change logging of Bitfield  (#3956)

* change logging of bits

* preston's review

* Unskip Beacon Server Test (#3962)

* run test till the end

* fix up proto message types

* fmt

* resolve broken tests

* better error handling

* fixing new logic to use archived proposer info

* fix up logic

* clip using the max effective balance

* broken build fix with num arg mismatch

* amend archive

* archival logic changed

* rename test

* archive both proposer and attester seeds

* page size 100

* further experiments

* further experimentation, archivedProposerIndex seems wrong

* test passes

* rem log

* fix broken test

* fix test

* gaz

* fix imports

* ethapis
This commit is contained in:
terence tsao
2019-11-11 14:03:44 -08:00
committed by Preston Van Loon
parent 62aaec1e20
commit 81c53c26fb
145 changed files with 2580 additions and 7199 deletions

106
WORKSPACE
View File

@@ -128,9 +128,8 @@ filegroup(
visibility = ["//visibility:public"],
)
""",
sha256 = "386335fc3b055fad37088bd821929ff684bc00bb1a74e044e4b377ebd6e88fce",
# File names are normally too long, see: https://github.com/ethereum/eth2.0-spec-tests/issues/15
url = "https://prysmaticlabs.com/uploads/v0.8.3_general_spectests.tar.gz",
sha256 = "5c5b65a961b5e7251435efc9548648b45142a07993ad3e100850c240cb76e9af",
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.9.0/general.tar.gz",
)
http_archive(
@@ -145,8 +144,8 @@ filegroup(
visibility = ["//visibility:public"],
)
""",
sha256 = "7ab89a364796e3f8a9af84750c241e9c9e2170a34c1a4e160fdfa2cee5b03fb7",
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.8.3/minimal.tar.gz",
sha256 = "3b5f0168af4331d09da52bebc26609def9d11be3e6c784ce7c3df3596617808d",
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.9.0/minimal.tar.gz",
)
http_archive(
@@ -161,8 +160,8 @@ filegroup(
visibility = ["//visibility:public"],
)
""",
sha256 = "6274e3b77f393faf7b17cef10e93244c16316d3b7ae9c6b844501b12f432a7c3",
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.8.3/mainnet.tar.gz",
sha256 = "f3ff68508dfe9696f23506daf0ca895cda955e30398741e00cffa33a01b0565c",
url = "https://github.com/ethereum/eth2.0-spec-tests/releases/download/v0.9.0/mainnet.tar.gz",
)
http_archive(
@@ -1202,7 +1201,7 @@ go_repository(
go_repository(
name = "com_github_prysmaticlabs_ethereumapis",
commit = "1205871db17ccc2fb824fc6dfa40d01c48fb6a7e",
commit = "c7f1fd03716c94dcc287a0d35905ed35b8a0afe1",
importpath = "github.com/prysmaticlabs/ethereumapis",
)
@@ -1259,3 +1258,94 @@ go_repository(
sum = "h1:n9HxLrNxWWtEb1cA950nuEEj3QnKbtsCJ6KjcgisNUs=",
version = "v0.0.0-20191002040644-a1355ae1e2c3",
)
go_repository(
name = "com_github_naoina_toml",
importpath = "github.com/naoina/toml",
sum = "h1:PT/lllxVVN0gzzSqSlHEmP8MJB4MY2U7STGxiouV4X8=",
version = "v0.1.1",
)
go_repository(
name = "com_github_elastic_gosigar",
importpath = "github.com/elastic/gosigar",
sum = "h1:GzPQ+78RaAb4J63unidA/JavQRKrB6s8IOzN6Ib59jo=",
version = "v0.10.5",
)
go_repository(
name = "in_gopkg_urfave_cli_v1",
importpath = "gopkg.in/urfave/cli.v1",
sum = "h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0=",
version = "v1.20.0",
)
go_repository(
name = "com_github_naoina_go_stringutil",
importpath = "github.com/naoina/go-stringutil",
sum = "h1:rCUeRUHjBjGTSHl0VC00jUPLz8/F9dDzYI70Hzifhks=",
version = "v0.1.0",
)
go_repository(
name = "com_github_influxdata_influxdb",
importpath = "github.com/influxdata/influxdb",
sum = "h1:uSeBTNO4rBkbp1Be5FKRsAmglM9nlx25TzVQRQt1An4=",
version = "v1.7.9",
)
go_repository(
name = "com_github_robertkrimen_otto",
importpath = "github.com/robertkrimen/otto",
sum = "h1:1VUlQbCfkoSGv7qP7Y+ro3ap1P1pPZxgdGVqiTVy5C4=",
version = "v0.0.0-20180617131154-15f95af6e78d",
)
go_repository(
name = "com_github_peterh_liner",
importpath = "github.com/peterh/liner",
sum = "h1:f+aAedNJA6uk7+6rXsYBnhdo4Xux7ESLe+kcuVUF5os=",
version = "v1.1.0",
)
go_repository(
name = "com_github_graph_gophers_graphql_go",
importpath = "github.com/graph-gophers/graphql-go",
sum = "h1:HwRCZlPXN00r58jaIPE11HXn7EvhheQrE+Cxw0vkrH0=",
version = "v0.0.0-20191031232829-adde0d0f76a3",
)
go_repository(
name = "com_github_rjeczalik_notify",
importpath = "github.com/rjeczalik/notify",
sum = "h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8=",
version = "v0.9.2",
)
go_repository(
name = "com_github_mohae_deepcopy",
importpath = "github.com/mohae/deepcopy",
sum = "h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=",
version = "v0.0.0-20170929034955-c48cc78d4826",
)
go_repository(
name = "in_gopkg_olebedev_go_duktape_v3",
importpath = "gopkg.in/olebedev/go-duktape.v3",
sum = "h1:uuol9OUzSvZntY1v963NAbVd7A+PHLMz1FlCe3Lorcs=",
version = "v3.0.0-20190709231704-1e4459ed25ff",
)
go_repository(
name = "in_gopkg_sourcemap_v1",
importpath = "gopkg.in/sourcemap.v1",
sum = "h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI=",
version = "v1.0.5",
)
go_repository(
name = "com_github_fatih_color",
importpath = "github.com/fatih/color",
sum = "h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=",
version = "v1.7.0",
)

View File

@@ -13,6 +13,7 @@ go_library(
"//beacon-chain/db:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//proto/eth/v1alpha1:go_default_library",
"//shared/params:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
],

View File

@@ -12,6 +12,7 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/db"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/sirupsen/logrus"
)
@@ -68,27 +69,23 @@ func (s *Service) Status() error {
// We archive committee information pertaining to the head state's epoch.
func (s *Service) archiveCommitteeInfo(ctx context.Context, headState *pb.BeaconState) error {
currentEpoch := helpers.SlotToEpoch(headState.Slot)
committeeCount, err := helpers.CommitteeCount(headState, currentEpoch)
committeeCount, err := helpers.CommitteeCountAtSlot(headState, helpers.StartSlot(currentEpoch))
if err != nil {
return errors.Wrap(err, "could not get committee count")
}
seed, err := helpers.Seed(headState, currentEpoch)
proposerSeed, err := helpers.Seed(headState, currentEpoch, params.BeaconConfig().DomainBeaconProposer)
if err != nil {
return errors.Wrap(err, "could not generate seed")
}
startShard, err := helpers.StartShard(headState, currentEpoch)
attesterSeed, err := helpers.Seed(headState, currentEpoch, params.BeaconConfig().DomainBeaconAttester)
if err != nil {
return errors.Wrap(err, "could not get start shard")
}
proposerIndex, err := helpers.BeaconProposerIndex(headState)
if err != nil {
return errors.Wrap(err, "could not get beacon proposer index")
return errors.Wrap(err, "could not generate seed")
}
info := &ethpb.ArchivedCommitteeInfo{
Seed: seed[:],
StartShard: startShard,
CommitteeCount: committeeCount,
ProposerIndex: proposerIndex,
ProposerSeed: proposerSeed[:],
AttesterSeed: attesterSeed[:],
CommitteeCount: committeeCount * params.BeaconConfig().SlotsPerEpoch,
}
if err := s.beaconDB.SaveArchivedCommitteeInfo(ctx, currentEpoch, info); err != nil {
return errors.Wrap(err, "could not archive committee info")

View File

@@ -128,27 +128,22 @@ func TestArchiverService_SavesCommitteeInfo(t *testing.T) {
triggerNewHeadEvent(t, svc, [32]byte{})
currentEpoch := helpers.CurrentEpoch(headState)
startShard, err := helpers.StartShard(headState, currentEpoch)
committeeCount, err := helpers.CommitteeCountAtSlot(headState, helpers.StartSlot(currentEpoch))
if err != nil {
t.Fatal(err)
}
committeeCount, err := helpers.CommitteeCount(headState, currentEpoch)
proposerSeed, err := helpers.Seed(headState, currentEpoch, params.BeaconConfig().DomainBeaconProposer)
if err != nil {
t.Fatal(err)
}
seed, err := helpers.Seed(headState, currentEpoch)
if err != nil {
t.Fatal(err)
}
propIdx, err := helpers.BeaconProposerIndex(headState)
attesterSeed, err := helpers.Seed(headState, currentEpoch, params.BeaconConfig().DomainBeaconAttester)
if err != nil {
t.Fatal(err)
}
wanted := &ethpb.ArchivedCommitteeInfo{
Seed: seed[:],
StartShard: startShard,
CommitteeCount: committeeCount,
ProposerIndex: propIdx,
ProposerSeed: proposerSeed[:],
AttesterSeed: attesterSeed[:],
CommitteeCount: committeeCount * params.BeaconConfig().SlotsPerEpoch,
}
retrieved, err := svc.beaconDB.ArchivedCommitteeInfo(svc.ctx, helpers.CurrentEpoch(headState))
@@ -251,14 +246,7 @@ func setupState(t *testing.T, validatorCount uint64) *pb.BeaconState {
balances[i] = params.BeaconConfig().MaxEffectiveBalance
}
atts := []*pb.PendingAttestation{{Data: &ethpb.AttestationData{Crosslink: &ethpb.Crosslink{Shard: 0}, Target: &ethpb.Checkpoint{}}}}
var crosslinks []*ethpb.Crosslink
for i := uint64(0); i < params.BeaconConfig().ShardCount; i++ {
crosslinks = append(crosslinks, &ethpb.Crosslink{
StartEpoch: 0,
DataRoot: []byte{'A'},
})
}
atts := []*pb.PendingAttestation{{Data: &ethpb.AttestationData{Target: &ethpb.Checkpoint{}}}}
// We initialize a head state that has attestations from participated
// validators in a simulated fashion.
@@ -269,9 +257,6 @@ func setupState(t *testing.T, validatorCount uint64) *pb.BeaconState {
BlockRoots: make([][]byte, 128),
Slashings: []uint64{0, 1e9, 1e9},
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
CompactCommitteesRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
CurrentCrosslinks: crosslinks,
CurrentEpochAttestations: atts,
FinalizedCheckpoint: &ethpb.Checkpoint{},
JustificationBits: bitfield.Bitvector4{0x00},

View File

@@ -89,7 +89,7 @@ func (s *Store) OnAttestation(ctx context.Context, a *ethpb.Attestation) (uint64
}
// Verify attestations can only affect the fork choice of subsequent slots.
if err := s.verifyAttSlotTime(ctx, baseState, a.Data); err != nil {
if err := helpers.VerifySlotTime(baseState.GenesisTime, a.Data.Slot+1); err != nil {
return 0, err
}
@@ -185,12 +185,7 @@ func (s *Store) waitForAttInclDelay(ctx context.Context, a *ethpb.Attestation, t
ctx, span := trace.StartSpan(ctx, "beacon-chain.forkchoice.waitForAttInclDelay")
defer span.End()
slot, err := helpers.AttestationDataSlot(targetState, a.Data)
if err != nil {
return errors.Wrap(err, "could not get attestation slot")
}
nextSlot := slot + 1
nextSlot := a.Data.Slot + 1
duration := time.Duration(nextSlot*params.BeaconConfig().SecondsPerSlot) * time.Second
timeToInclude := time.Unix(int64(targetState.GenesisTime), 0).Add(duration)
@@ -210,7 +205,6 @@ func (s *Store) aggregateAttestation(ctx context.Context, att *ethpb.Attestation
if err != nil {
return err
}
if a, ok := s.attsQueue[root]; ok {
a, err := helpers.AggregateAttestation(a, att)
if err != nil {
@@ -223,15 +217,6 @@ func (s *Store) aggregateAttestation(ctx context.Context, att *ethpb.Attestation
return nil
}
// verifyAttSlotTime validates input attestation is not from the future.
func (s *Store) verifyAttSlotTime(ctx context.Context, baseState *pb.BeaconState, d *ethpb.AttestationData) error {
aSlot, err := helpers.AttestationDataSlot(baseState, d)
if err != nil {
return errors.Wrap(err, "could not get attestation slot")
}
return helpers.VerifySlotTime(baseState.GenesisTime, aSlot+1)
}
// verifyAttestation validates input attestation is valid.
func (s *Store) verifyAttestation(ctx context.Context, baseState *pb.BeaconState, a *ethpb.Attestation) (*ethpb.IndexedAttestation, error) {
indexedAtt, err := blocks.ConvertToIndexed(ctx, baseState, a)

View File

@@ -55,8 +55,7 @@ func TestStore_OnAttestation(t *testing.T) {
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
},
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
}, BlkWithValidStateRoot); err != nil {
t.Fatal(err)
}
@@ -118,30 +117,19 @@ func TestStore_SaveCheckpointState(t *testing.T) {
store := NewForkChoiceService(ctx, db)
crosslinks := make([]*ethpb.Crosslink, params.BeaconConfig().ShardCount)
for i := 0; i < len(crosslinks); i++ {
crosslinks[i] = &ethpb.Crosslink{
ParentRoot: make([]byte, 32),
DataRoot: make([]byte, 32),
}
}
s := &pb.BeaconState{
Fork: &pb.Fork{
Epoch: 0,
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
},
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
StateRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
BlockRoots: make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot),
LatestBlockHeader: &ethpb.BeaconBlockHeader{},
JustificationBits: []byte{0},
CurrentJustifiedCheckpoint: &ethpb.Checkpoint{},
CurrentCrosslinks: crosslinks,
CompactCommitteesRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
Slashings: make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector),
FinalizedCheckpoint: &ethpb.Checkpoint{},
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
StateRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
BlockRoots: make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot),
LatestBlockHeader: &ethpb.BeaconBlockHeader{},
JustificationBits: []byte{0},
Slashings: make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector),
FinalizedCheckpoint: &ethpb.Checkpoint{},
}
if err := store.GenesisStore(ctx, &ethpb.Checkpoint{}, &ethpb.Checkpoint{}); err != nil {
t.Fatal(err)
@@ -210,7 +198,7 @@ func TestStore_AggregateAttestation(t *testing.T) {
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
Epoch: 0,
}
domain := helpers.Domain(f, 0, params.BeaconConfig().DomainAttestation)
domain := helpers.Domain(f, 0, params.BeaconConfig().DomainBeaconAttester)
sig := privKeys[0].Sign([]byte{}, domain)
store := &Store{attsQueue: make(map[[32]byte]*ethpb.Attestation)}

View File

@@ -73,7 +73,6 @@ func (s *Store) OnBlock(ctx context.Context, b *ethpb.BeaconBlock) error {
"slot": b.Slot,
"root": fmt.Sprintf("0x%s...", hex.EncodeToString(root[:])[:8]),
}).Info("Executing state transition on block")
postState, err := state.ExecuteStateTransition(ctx, preState, b)
if err != nil {
return errors.Wrap(err, "could not execute state transition")
@@ -215,6 +214,13 @@ func (s *Store) OnBlockNoVerifyStateTransition(ctx context.Context, b *ethpb.Bea
// Epoch boundary bookkeeping such as logging epoch summaries.
if helpers.IsEpochStart(postState.Slot) {
reportEpochMetrics(postState)
// Update committee shuffled indices at the end of every epoch
if featureconfig.Get().EnableNewCache {
if err := helpers.UpdateCommitteeCache(postState); err != nil {
return err
}
}
}
return nil
@@ -281,6 +287,9 @@ func (s *Store) updateBlockAttestationVote(ctx context.Context, att *ethpb.Attes
if err != nil {
return errors.Wrap(err, "could not get state for attestation tgt root")
}
if baseState == nil {
return errors.New("no state found in db with attestation tgt root")
}
indexedAtt, err := blocks.ConvertToIndexed(ctx, baseState, att)
if err != nil {
return errors.Wrap(err, "could not convert attestation to indexed attestation")

View File

@@ -133,7 +133,7 @@ func TestStore_UpdateBlockAttestationVote(t *testing.T) {
params.UseMinimalConfig()
deposits, _, _ := testutil.SetupInitialDeposits(t, 100)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{})
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Fatal(err)
}
@@ -144,10 +144,6 @@ func TestStore_UpdateBlockAttestationVote(t *testing.T) {
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0, Root: params.BeaconConfig().ZeroHash[:]},
Target: &ethpb.Checkpoint{Epoch: 0, Root: r[:]},
Crosslink: &ethpb.Crosslink{
Shard: 0,
StartEpoch: 0,
},
},
AggregationBits: []byte{255},
CustodyBits: []byte{255},
@@ -187,7 +183,7 @@ func TestStore_UpdateBlockAttestationsVote(t *testing.T) {
params.UseMinimalConfig()
deposits, _, _ := testutil.SetupInitialDeposits(t, 100)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{})
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Fatal(err)
}
@@ -201,10 +197,6 @@ func TestStore_UpdateBlockAttestationsVote(t *testing.T) {
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0, Root: params.BeaconConfig().ZeroHash[:]},
Target: &ethpb.Checkpoint{Epoch: 0, Root: r[:]},
Crosslink: &ethpb.Crosslink{
Shard: uint64(i),
StartEpoch: 0,
},
},
AggregationBits: []byte{255},
CustodyBits: []byte{255},

View File

@@ -35,8 +35,7 @@ func TestReceiveAttestation_ProcessCorrectly(t *testing.T) {
}
a := &ethpb.Attestation{Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Root: root[:]},
Crosslink: &ethpb.Crosslink{},
Target: &ethpb.Checkpoint{Root: root[:]},
}}
if err := chainService.ReceiveAttestation(ctx, a); err != nil {
t.Fatal(err)
@@ -70,8 +69,7 @@ func TestReceiveAttestation_SameHead(t *testing.T) {
}
a := &ethpb.Attestation{Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Root: root[:]},
Crosslink: &ethpb.Crosslink{},
Target: &ethpb.Checkpoint{Root: root[:]},
}}
if err := chainService.ReceiveAttestation(ctx, a); err != nil {
t.Fatal(err)
@@ -104,8 +102,7 @@ func TestReceiveAttestationNoPubsub_ProcessCorrectly(t *testing.T) {
}
a := &ethpb.Attestation{Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Root: root[:]},
Crosslink: &ethpb.Crosslink{},
Target: &ethpb.Checkpoint{Root: root[:]},
}}
if err := chainService.ReceiveAttestationNoPubsub(ctx, a); err != nil {
t.Fatal(err)

View File

@@ -5,6 +5,7 @@ import (
"context"
"encoding/hex"
"github.com/gogo/protobuf/proto"
"github.com/pkg/errors"
"github.com/prysmaticlabs/go-ssz"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
@@ -61,14 +62,15 @@ func (s *Service) ReceiveBlock(ctx context.Context, block *ethpb.BeaconBlock) er
func (s *Service) ReceiveBlockNoPubsub(ctx context.Context, block *ethpb.BeaconBlock) error {
ctx, span := trace.StartSpan(ctx, "beacon-chain.blockchain.ReceiveBlockNoPubsub")
defer span.End()
blockCopy := proto.Clone(block).(*ethpb.BeaconBlock)
// Apply state transition on the new block.
if err := s.forkChoiceStore.OnBlock(ctx, block); err != nil {
if err := s.forkChoiceStore.OnBlock(ctx, blockCopy); err != nil {
err := errors.Wrap(err, "could not process block from fork choice service")
traceutil.AnnotateError(span, err)
return err
}
root, err := ssz.SigningRoot(block)
root, err := ssz.SigningRoot(blockCopy)
if err != nil {
return errors.Wrap(err, "could not get signing root on received block")
}
@@ -91,18 +93,18 @@ func (s *Service) ReceiveBlockNoPubsub(ctx context.Context, block *ethpb.BeaconB
}
// Remove block's contained deposits, attestations, and other operations from persistent storage.
if err := s.cleanupBlockOperations(ctx, block); err != nil {
if err := s.cleanupBlockOperations(ctx, blockCopy); err != nil {
return errors.Wrap(err, "could not clean up block deposits, attestations, and other operations")
}
// Reports on block and fork choice metrics.
s.reportSlotMetrics(block.Slot)
s.reportSlotMetrics(blockCopy.Slot)
// Log if block is a competing block.
isCompetingBlock(root[:], block.Slot, headRoot, headBlk.Slot)
isCompetingBlock(root[:], blockCopy.Slot, headRoot, headBlk.Slot)
// Log state transition data.
logStateTransitionData(block, root[:])
logStateTransitionData(blockCopy, root[:])
processedBlkNoPubsub.Inc()
@@ -118,34 +120,35 @@ func (s *Service) ReceiveBlockNoPubsub(ctx context.Context, block *ethpb.BeaconB
func (s *Service) ReceiveBlockNoPubsubForkchoice(ctx context.Context, block *ethpb.BeaconBlock) error {
ctx, span := trace.StartSpan(ctx, "beacon-chain.blockchain.ReceiveBlockNoForkchoice")
defer span.End()
blockCopy := proto.Clone(block).(*ethpb.BeaconBlock)
// Apply state transition on the incoming newly received block.
if err := s.forkChoiceStore.OnBlock(ctx, block); err != nil {
if err := s.forkChoiceStore.OnBlock(ctx, blockCopy); err != nil {
err := errors.Wrap(err, "could not process block from fork choice service")
traceutil.AnnotateError(span, err)
return err
}
root, err := ssz.SigningRoot(block)
root, err := ssz.SigningRoot(blockCopy)
if err != nil {
return errors.Wrap(err, "could not get signing root on received block")
}
if !bytes.Equal(root[:], s.HeadRoot()) {
if err := s.saveHead(ctx, block, root); err != nil {
if err := s.saveHead(ctx, blockCopy, root); err != nil {
return errors.Wrap(err, "could not save head")
}
}
// Remove block's contained deposits, attestations, and other operations from persistent storage.
if err := s.cleanupBlockOperations(ctx, block); err != nil {
if err := s.cleanupBlockOperations(ctx, blockCopy); err != nil {
return errors.Wrap(err, "could not clean up block deposits, attestations, and other operations")
}
// Reports on block and fork choice metrics.
s.reportSlotMetrics(block.Slot)
s.reportSlotMetrics(blockCopy.Slot)
// Log state transition data.
logStateTransitionData(block, root[:])
logStateTransitionData(blockCopy, root[:])
// We write the latest saved head root to a feed for consumption by other services.
s.headUpdatedFeed.Send(root)
@@ -159,32 +162,33 @@ func (s *Service) ReceiveBlockNoPubsubForkchoice(ctx context.Context, block *eth
func (s *Service) ReceiveBlockNoVerify(ctx context.Context, block *ethpb.BeaconBlock) error {
ctx, span := trace.StartSpan(ctx, "beacon-chain.blockchain.ReceiveBlockNoVerify")
defer span.End()
blockCopy := proto.Clone(block).(*ethpb.BeaconBlock)
// Apply state transition on the incoming newly received block without verifying its BLS contents.
if err := s.forkChoiceStore.OnBlockNoVerifyStateTransition(ctx, block); err != nil {
return errors.Wrap(err, "could not process block from fork choice service")
// Apply state transition on the incoming newly received blockCopy without verifying its BLS contents.
if err := s.forkChoiceStore.OnBlockNoVerifyStateTransition(ctx, blockCopy); err != nil {
return errors.Wrap(err, "could not process blockCopy from fork choice service")
}
root, err := ssz.SigningRoot(block)
root, err := ssz.SigningRoot(blockCopy)
if err != nil {
return errors.Wrap(err, "could not get signing root on received block")
return errors.Wrap(err, "could not get signing root on received blockCopy")
}
if !bytes.Equal(root[:], s.HeadRoot()) {
if err := s.saveHead(ctx, block, root); err != nil {
if err := s.saveHead(ctx, blockCopy, root); err != nil {
err := errors.Wrap(err, "could not save head")
traceutil.AnnotateError(span, err)
return err
}
}
// Reports on block and fork choice metrics.
s.reportSlotMetrics(block.Slot)
// Reports on blockCopy and fork choice metrics.
s.reportSlotMetrics(blockCopy.Slot)
// Log state transition data.
log.WithFields(logrus.Fields{
"slot": block.Slot,
"attestations": len(block.Body.Attestations),
"deposits": len(block.Body.Deposits),
"slot": blockCopy.Slot,
"attestations": len(blockCopy.Body.Attestations),
"deposits": len(blockCopy.Body.Deposits),
}).Debug("Finished applying state transition")
// We write the latest saved head root to a feed for consumption by other services.

View File

@@ -24,16 +24,16 @@ func TestReceiveBlock_ProcessCorrectly(t *testing.T) {
chainService := setupBeaconChain(t, db)
deposits, _, privKeys := testutil.SetupInitialDeposits(t, 100)
beaconState, err := state.GenesisBeaconState(deposits, 0, &ethpb.Eth1Data{})
beaconState, err := state.GenesisBeaconState(deposits, 0, &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Fatal(err)
}
beaconState.Eth1Data.BlockHash = nil
beaconState.Eth1DepositIndex = 100
stateRoot, err := ssz.HashTreeRoot(beaconState)
if err != nil {
t.Fatal(err)
}
genesis := b.NewGenesisBlock(stateRoot[:])
bodyRoot, err := ssz.HashTreeRoot(genesis.Body)
if err != nil {
@@ -188,7 +188,7 @@ func TestReceiveBlockNoPubsubForkchoice_ProcessCorrectly(t *testing.T) {
chainService := setupBeaconChain(t, db)
deposits, _, privKeys := testutil.SetupInitialDeposits(t, 100)
beaconState, err := state.GenesisBeaconState(deposits, 0, &ethpb.Eth1Data{})
beaconState, err := state.GenesisBeaconState(deposits, 0, &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Fatal(err)
}

View File

@@ -10,7 +10,6 @@ go_library(
"committee.go",
"common.go",
"eth1_data.go",
"shuffled_indices.go",
],
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/cache",
visibility = ["//beacon-chain:__subpackages__"],
@@ -41,7 +40,6 @@ go_test(
"committee_test.go",
"eth1_data_test.go",
"feature_flag_test.go",
"shuffled_indices_test.go",
],
embed = [":go_default_library"],
race = "on",

View File

@@ -181,7 +181,7 @@ func wrapperToKey(i interface{}) (string, error) {
}
func reqToKey(req *pb.AttestationRequest) (string, error) {
return fmt.Sprintf("%d-%d", req.Shard, req.Slot), nil
return fmt.Sprintf("%d-%d", req.CommitteeIndex, req.Slot), nil
}
type attestationReqResWrapper struct {

View File

@@ -15,8 +15,8 @@ func TestAttestationCache_RoundTrip(t *testing.T) {
c := cache.NewAttestationCache()
req := &pb.AttestationRequest{
Shard: 0,
Slot: 1,
CommitteeIndex: 0,
Slot: 1,
}
response, err := c.Get(ctx, req)

View File

@@ -34,15 +34,14 @@ var (
})
)
// Committee defines the committee per epoch and shard.
// Committee defines the committee per epoch and index.
type Committee struct {
StartShard uint64
CommitteeCount uint64
Epoch uint64
Committee []uint64
}
// CommitteeCache is a struct with 1 queue for looking up shuffled indices list by epoch and shard.
// CommitteeCache is a struct with 1 queue for looking up shuffled indices list by epoch and committee index.
type CommitteeCache struct {
CommitteeCache *cache.FIFO
lock sync.RWMutex
@@ -65,15 +64,17 @@ func NewCommitteeCache() *CommitteeCache {
}
}
// ShuffledIndices fetches the shuffled indices by epoch and shard. Every list of indices
// represent one committee. Returns true if the list exists with epoch and shard. Otherwise returns false, nil.
func (c *CommitteeCache) ShuffledIndices(epoch uint64, shard uint64) ([]uint64, error) {
// ShuffledIndices fetches the shuffled indices by slot and committee index. Every list of indices
// represent one committee. Returns true if the list exists with slot and committee index. Otherwise returns false, nil.
func (c *CommitteeCache) ShuffledIndices(slot uint64, index uint64) ([]uint64, error) {
if !featureconfig.Get().EnableShuffledIndexCache && !featureconfig.Get().EnableNewCache {
return nil, nil
}
c.lock.RLock()
defer c.lock.RUnlock()
obj, exists, err := c.CommitteeCache.GetByKey(strconv.Itoa(int(epoch)))
epoch := int(slot / params.BeaconConfig().SlotsPerEpoch)
obj, exists, err := c.CommitteeCache.GetByKey(strconv.Itoa(epoch))
if err != nil {
return nil, err
}
@@ -90,8 +91,13 @@ func (c *CommitteeCache) ShuffledIndices(epoch uint64, shard uint64) ([]uint64,
return nil, ErrNotCommittee
}
start, end := startEndIndices(item, shard)
committeeCountPerSlot := uint64(1)
if item.CommitteeCount/params.BeaconConfig().SlotsPerEpoch > 1 {
committeeCountPerSlot = item.CommitteeCount / params.BeaconConfig().SlotsPerEpoch
}
indexOffSet := index + (slot%params.BeaconConfig().SlotsPerEpoch)*committeeCountPerSlot
start, end := startEndIndices(item, indexOffSet)
return item.Committee[start:end], nil
}
@@ -149,13 +155,14 @@ func (c *CommitteeCache) EpochInCache(wantedEpoch uint64) (bool, error) {
return false, nil
}
// CommitteeCount returns the total number of committees in a given epoch as stored in cache.
func (c *CommitteeCache) CommitteeCount(epoch uint64) (uint64, bool, error) {
// CommitteeCountPerSlot returns the number of committees in a given slot as stored in cache.
func (c *CommitteeCache) CommitteeCountPerSlot(slot uint64) (uint64, bool, error) {
if !featureconfig.Get().EnableShuffledIndexCache && !featureconfig.Get().EnableNewCache {
return 0, false, nil
}
c.lock.RLock()
defer c.lock.RUnlock()
epoch := int(slot / params.BeaconConfig().SlotsPerEpoch)
obj, exists, err := c.CommitteeCache.GetByKey(strconv.Itoa(int(epoch)))
if err != nil {
return 0, false, err
@@ -173,34 +180,7 @@ func (c *CommitteeCache) CommitteeCount(epoch uint64) (uint64, bool, error) {
return 0, false, ErrNotCommittee
}
return item.CommitteeCount, true, nil
}
// StartShard returns the start shard number in a given epoch as stored in cache.
func (c *CommitteeCache) StartShard(epoch uint64) (uint64, bool, error) {
if !featureconfig.Get().EnableShuffledIndexCache && !featureconfig.Get().EnableNewCache {
return 0, false, nil
}
c.lock.RLock()
defer c.lock.RUnlock()
obj, exists, err := c.CommitteeCache.GetByKey(strconv.Itoa(int(epoch)))
if err != nil {
return 0, false, err
}
if exists {
CommitteeCacheHit.Inc()
} else {
CommitteeCacheMiss.Inc()
return 0, false, nil
}
item, ok := obj.(*Committee)
if !ok {
return 0, false, ErrNotCommittee
}
return item.StartShard, true, nil
return item.CommitteeCount / params.BeaconConfig().SlotsPerEpoch, true, nil
}
// ActiveIndices returns the active indices of a given epoch stored in cache.
@@ -231,12 +211,10 @@ func (c *CommitteeCache) ActiveIndices(epoch uint64) ([]uint64, error) {
return item.Committee, nil
}
func startEndIndices(c *Committee, wantedShard uint64) (uint64, uint64) {
shardCount := params.BeaconConfig().ShardCount
currentShard := (wantedShard + shardCount - c.StartShard) % shardCount
func startEndIndices(c *Committee, index uint64) (uint64, uint64) {
validatorCount := uint64(len(c.Committee))
start := sliceutil.SplitOffset(validatorCount, c.CommitteeCount, currentShard)
end := sliceutil.SplitOffset(validatorCount, c.CommitteeCount, currentShard+1)
start := sliceutil.SplitOffset(validatorCount, c.CommitteeCount, index)
end := sliceutil.SplitOffset(validatorCount, c.CommitteeCount, index+1)
return start, end
}

View File

@@ -4,6 +4,8 @@ import (
"reflect"
"strconv"
"testing"
"github.com/prysmaticlabs/prysm/shared/params"
)
func TestCommitteeKeyFn_OK(t *testing.T) {
@@ -36,12 +38,11 @@ func TestCommitteeCache_CommitteesByEpoch(t *testing.T) {
Epoch: 1,
Committee: []uint64{1, 2, 3, 4, 5, 6},
CommitteeCount: 3,
StartShard: 1,
}
epoch := uint64(1)
startShard := uint64(1)
indices, err := cache.ShuffledIndices(epoch, startShard)
slot := uint64(item.Epoch * params.BeaconConfig().SlotsPerEpoch)
committeeIndex := uint64(1)
indices, err := cache.ShuffledIndices(slot, committeeIndex)
if err != nil {
t.Fatal(err)
}
@@ -52,12 +53,13 @@ func TestCommitteeCache_CommitteesByEpoch(t *testing.T) {
if err := cache.AddCommitteeShuffledList(item); err != nil {
t.Fatal(err)
}
wantedShard := uint64(2)
indices, err = cache.ShuffledIndices(epoch, wantedShard)
wantedIndex := uint64(0)
indices, err = cache.ShuffledIndices(slot, wantedIndex)
if err != nil {
t.Fatal(err)
}
start, end := startEndIndices(item, wantedShard)
start, end := startEndIndices(item, wantedIndex)
if !reflect.DeepEqual(indices, item.Committee[start:end]) {
t.Errorf(
"Expected fetched active indices to be %v, got %v",
@@ -143,68 +145,6 @@ func TestCommitteeCache_EpochInCache(t *testing.T) {
}
}
func TestCommitteeCache_CommitteesCount(t *testing.T) {
cache := NewCommitteeCache()
committeeCount := uint64(3)
epoch := uint64(10)
item := &Committee{Epoch: epoch, CommitteeCount: committeeCount}
_, exists, err := cache.CommitteeCount(1)
if err != nil {
t.Fatal(err)
}
if exists {
t.Error("Expected committee count not to exist in empty cache")
}
if err := cache.AddCommitteeShuffledList(item); err != nil {
t.Fatal(err)
}
count, exists, err := cache.CommitteeCount(epoch)
if err != nil {
t.Fatal(err)
}
if !exists {
t.Error("Expected committee count to be in cache")
}
if count != committeeCount {
t.Errorf("wanted: %d, got: %d", committeeCount, count)
}
}
func TestCommitteeCache_ShardCount(t *testing.T) {
cache := NewCommitteeCache()
startShard := uint64(7)
epoch := uint64(3)
item := &Committee{Epoch: epoch, StartShard: startShard}
_, exists, err := cache.StartShard(1)
if err != nil {
t.Fatal(err)
}
if exists {
t.Error("Expected start shard not to exist in empty cache")
}
if err := cache.AddCommitteeShuffledList(item); err != nil {
t.Fatal(err)
}
shard, exists, err := cache.StartShard(epoch)
if err != nil {
t.Fatal(err)
}
if !exists {
t.Error("Expected start shard to be in cache")
}
if shard != startShard {
t.Errorf("wanted: %d, got: %d", startShard, shard)
}
}
func TestCommitteeCache_ActiveIndices(t *testing.T) {
cache := NewCommitteeCache()

View File

@@ -1,106 +0,0 @@
package cache
import (
"errors"
"strconv"
"sync"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/prysmaticlabs/prysm/shared/featureconfig"
"k8s.io/client-go/tools/cache"
)
var (
// ErrNotValidatorListInfo will be returned when a cache object is not a pointer to
// a ValidatorList struct.
ErrNotValidatorListInfo = errors.New("object is not a shuffled validator list")
// maxShuffledListSize defines the max number of shuffled list can cache.
maxShuffledListSize = 1000
// Metrics.
shuffledIndicesCacheMiss = promauto.NewCounter(prometheus.CounterOpts{
Name: "shuffled_validators_cache_miss",
Help: "The number of shuffled validators requests that aren't present in the cache.",
})
shuffledIndicesCacheHit = promauto.NewCounter(prometheus.CounterOpts{
Name: "shuffled_validators_cache_hit",
Help: "The number of shuffled validators requests that are present in the cache.",
})
)
// IndicesByIndexSeed defines the shuffled validator indices per randao seed.
type IndicesByIndexSeed struct {
Index uint64
Seed []byte
ShuffledIndices []uint64
}
// ShuffledIndicesCache is a struct with 1 queue for looking up shuffled validators by seed.
type ShuffledIndicesCache struct {
shuffledIndicesCache *cache.FIFO
lock sync.RWMutex
}
// slotKeyFn takes the randao seed as the key for the shuffled validators of a given epoch.
func shuffleKeyFn(obj interface{}) (string, error) {
sInfo, ok := obj.(*IndicesByIndexSeed)
if !ok {
return "", ErrNotValidatorListInfo
}
return string(sInfo.Seed) + strconv.Itoa(int(sInfo.Index)), nil
}
// NewShuffledIndicesCache creates a new shuffled validators cache for storing/accessing shuffled validator indices
func NewShuffledIndicesCache() *ShuffledIndicesCache {
return &ShuffledIndicesCache{
shuffledIndicesCache: cache.NewFIFO(shuffleKeyFn),
}
}
// IndicesByIndexSeed fetches IndicesByIndexSeed by epoch and seed. Returns true with a
// reference to the ShuffledIndicesInEpoch info, if exists. Otherwise returns false, nil.
func (c *ShuffledIndicesCache) IndicesByIndexSeed(index uint64, seed []byte) ([]uint64, error) {
if !featureconfig.Get().EnableShuffledIndexCache {
return nil, nil
}
c.lock.RLock()
defer c.lock.RUnlock()
key := string(seed) + strconv.Itoa(int(index))
obj, exists, err := c.shuffledIndicesCache.GetByKey(key)
if err != nil {
return nil, err
}
if exists {
shuffledIndicesCacheHit.Inc()
} else {
shuffledIndicesCacheMiss.Inc()
return nil, nil
}
cInfo, ok := obj.(*IndicesByIndexSeed)
if !ok {
return nil, ErrNotValidatorListInfo
}
return cInfo.ShuffledIndices, nil
}
// AddShuffledValidatorList adds IndicesByIndexSeed object to the cache. This method also trims the least
// recently added IndicesByIndexSeed object if the cache size has ready the max cache size limit.
func (c *ShuffledIndicesCache) AddShuffledValidatorList(shuffledIndices *IndicesByIndexSeed) error {
if !featureconfig.Get().EnableShuffledIndexCache {
return nil
}
c.lock.Lock()
defer c.lock.Unlock()
if err := c.shuffledIndicesCache.AddIfNotPresent(shuffledIndices); err != nil {
return err
}
trim(c.shuffledIndicesCache, maxShuffledListSize)
return nil
}

View File

@@ -1,93 +0,0 @@
package cache
import (
"reflect"
"strconv"
"testing"
"github.com/prysmaticlabs/prysm/shared/featureconfig"
)
func init() {
fc := featureconfig.Get()
fc.EnableShuffledIndexCache = true
featureconfig.Init(fc)
}
func TestShuffleKeyFn_OK(t *testing.T) {
sInfo := &IndicesByIndexSeed{
Index: 999,
Seed: []byte{'A'},
ShuffledIndices: []uint64{1, 2, 3, 4, 5},
}
key, err := shuffleKeyFn(sInfo)
if err != nil {
t.Fatal(err)
}
if key != string(sInfo.Seed)+strconv.Itoa(int(sInfo.Index)) {
t.Errorf("Incorrect hash key: %s, expected %s", key, string(sInfo.Seed)+strconv.Itoa(int(sInfo.Index)))
}
}
func TestShuffleKeyFn_InvalidObj(t *testing.T) {
_, err := shuffleKeyFn("bad")
if err != ErrNotValidatorListInfo {
t.Errorf("Expected error %v, got %v", ErrNotValidatorListInfo, err)
}
}
func TestShuffledIndicesCache_ShuffledIndicesBySeed2(t *testing.T) {
cache := NewShuffledIndicesCache()
sInfo := &IndicesByIndexSeed{
Index: 99,
Seed: []byte{'A'},
ShuffledIndices: []uint64{1, 2, 3, 4},
}
shuffledIndices, err := cache.IndicesByIndexSeed(sInfo.Index, sInfo.Seed)
if err != nil {
t.Fatal(err)
}
if shuffledIndices != nil {
t.Error("Expected shuffled indices not to exist in empty cache")
}
if err := cache.AddShuffledValidatorList(sInfo); err != nil {
t.Fatal(err)
}
shuffledIndices, err = cache.IndicesByIndexSeed(sInfo.Index, sInfo.Seed)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(shuffledIndices, sInfo.ShuffledIndices) {
t.Errorf(
"Expected fetched info committee to be %v, got %v",
sInfo.ShuffledIndices,
shuffledIndices,
)
}
}
func TestShuffledIndices_MaxSize(t *testing.T) {
cache := NewShuffledIndicesCache()
for i := uint64(0); i < 1001; i++ {
sInfo := &IndicesByIndexSeed{
Index: i,
Seed: []byte{byte(i)},
}
if err := cache.AddShuffledValidatorList(sInfo); err != nil {
t.Fatal(err)
}
}
if len(cache.shuffledIndicesCache.ListKeys()) != maxShuffledListSize {
t.Errorf(
"Expected hash cache key size to be %d, got %d",
maxShuffledListSize,
len(cache.shuffledIndicesCache.ListKeys()),
)
}
}

View File

@@ -50,7 +50,6 @@ go_test(
"//proto/eth/v1alpha1:go_default_library",
"//shared/bls:go_default_library",
"//shared/bytesutil:go_default_library",
"//shared/hashutil:go_default_library",
"//shared/params:go_default_library",
"//shared/testutil:go_default_library",
"//shared/trieutil:go_default_library",

View File

@@ -161,7 +161,7 @@ func ProcessBlockHeader(
) (*pb.BeaconState, error) {
beaconState, err := ProcessBlockHeaderNoVerify(beaconState, block)
if err != nil {
return nil, errors.Wrap(err, "could not process block header")
return nil, err
}
idx, err := helpers.BeaconProposerIndex(beaconState)
@@ -320,8 +320,8 @@ func ProcessRandaoNoVerify(
// Process ``ProposerSlashing`` operation.
// """
// proposer = state.validator_registry[proposer_slashing.proposer_index]
// # Verify that the epoch is the same
// assert slot_to_epoch(proposer_slashing.header_1.slot) == slot_to_epoch(proposer_slashing.header_2.slot)
// # Verify slots match
// assert proposer_slashing.header_1.slot == proposer_slashing.header_2.slot
// # But the headers are different
// assert proposer_slashing.header_1 != proposer_slashing.header_2
// # Check proposer is slashable
@@ -356,12 +356,10 @@ func VerifyProposerSlashing(
beaconState *pb.BeaconState,
slashing *ethpb.ProposerSlashing,
) error {
headerEpoch1 := helpers.SlotToEpoch(slashing.Header_1.Slot)
headerEpoch2 := helpers.SlotToEpoch(slashing.Header_2.Slot)
proposer := beaconState.Validators[slashing.ProposerIndex]
if headerEpoch1 != headerEpoch2 {
return fmt.Errorf("mismatched header epochs, received %d == %d", headerEpoch1, headerEpoch2)
if slashing.Header_1.Slot != slashing.Header_2.Slot {
return fmt.Errorf("mismatched header slots, received %d == %d", slashing.Header_1.Slot, slashing.Header_2.Slot)
}
if proto.Equal(slashing.Header_1, slashing.Header_2) {
return errors.New("expected slashing headers to differ")
@@ -370,7 +368,7 @@ func VerifyProposerSlashing(
return fmt.Errorf("validator with key %#x is not slashable", proposer.PublicKey)
}
// Using headerEpoch1 here because both of the headers should have the same epoch.
domain := helpers.Domain(beaconState.Fork, headerEpoch1, params.BeaconConfig().DomainBeaconProposer)
domain := helpers.Domain(beaconState.Fork, helpers.StartSlot(slashing.Header_1.Slot), params.BeaconConfig().DomainBeaconProposer)
headers := append([]*ethpb.BeaconBlockHeader{slashing.Header_1}, slashing.Header_2)
for _, header := range headers {
if err := verifySigningRoot(header, proposer.PublicKey, header.Signature, domain); err != nil {
@@ -508,40 +506,27 @@ func ProcessAttestationsNoVerify(ctx context.Context, beaconState *pb.BeaconStat
//
// Spec pseudocode definition:
// def process_attestation(state: BeaconState, attestation: Attestation) -> None:
// """
// Process ``Attestation`` operation.
// """
// data = attestation.data
// assert data.crosslink.shard < SHARD_COUNT
// assert data.index < get_committee_count_at_slot(state, data.slot)
// assert data.target.epoch in (get_previous_epoch(state), get_current_epoch(state))
// assert data.slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot <= data.slot + SLOTS_PER_EPOCH
//
// attestation_slot = get_attestation_data_slot(state, data)
// assert attestation_slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot <= attestation_slot + SLOTS_PER_EPOCH
//
// committee = get_crosslink_committee(state, data.target.epoch, data.crosslink.shard)
// committee = get_beacon_committee(state, data.slot, data.index)
// assert len(attestation.aggregation_bits) == len(attestation.custody_bits) == len(committee)
//
// pending_attestation = PendingAttestation(
// data=data,
// aggregation_bitfield=attestation.aggregation_bitfield,
// inclusion_delay=state.slot - attestation_slot,
// aggregation_bits=attestation.aggregation_bits,
// inclusion_delay=state.slot - data.slot,
// proposer_index=get_beacon_proposer_index(state),
// )
//
// if data.target_epoch == get_current_epoch(state):
// assert data.source == state.current_justified_checkpoint
// parent_crosslink = state.current_crosslinks[data.crosslink.shard]
// state.current_epoch_attestations.append(pending_attestation)
// if data.target.epoch == get_current_epoch(state):
// assert data.source == state.current_justified_checkpoint
// state.current_epoch_attestations.append(pending_attestation)
// else:
// assert data.source == state.previous_justified_checkpoint
// parent_crosslink = state.previous_crosslinks[data.crosslink.shard]
// state.previous_epoch_attestations.append(pending_attestation)
//
// # Check crosslink against expected parent crosslink
// assert data.crosslink.parent_root == hash_tree_root(parent_crosslink)
// assert data.crosslink.start_epoch == parent_crosslink.end_epoch
// assert data.crosslink.end_epoch == min(data.target.epoch, parent_crosslink.end_epoch + MAX_EPOCHS_PER_CROSSLINK)
// assert data.crosslink.data_root == Bytes32() # [to be removed in phase 1]
// assert data.source == state.previous_justified_checkpoint
// state.previous_epoch_attestations.append(pending_attestation)
//
// # Check signature
// assert is_valid_indexed_attestation(state, get_indexed_attestation(state, attestation))
@@ -560,15 +545,6 @@ func ProcessAttestationNoVerify(ctx context.Context, beaconState *pb.BeaconState
defer span.End()
data := att.Data
if data.Crosslink.Shard > params.BeaconConfig().ShardCount {
return nil, fmt.Errorf(
"expected crosslink shard %d to be less than SHARD_COUNT %d",
data.Crosslink.Shard,
params.BeaconConfig().ShardCount,
)
}
if data.Target.Epoch != helpers.PrevEpoch(beaconState) && data.Target.Epoch != helpers.CurrentEpoch(beaconState) {
return nil, fmt.Errorf(
"expected target epoch (%d) to be the previous epoch (%d) or the current epoch (%d)",
@@ -578,16 +554,13 @@ func ProcessAttestationNoVerify(ctx context.Context, beaconState *pb.BeaconState
)
}
attestationSlot, err := helpers.AttestationDataSlot(beaconState, data)
if err != nil {
return nil, errors.Wrap(err, "could not get attestation slot")
}
minInclusionCheck := attestationSlot+params.BeaconConfig().MinAttestationInclusionDelay <= beaconState.Slot
epochInclusionCheck := beaconState.Slot <= attestationSlot+params.BeaconConfig().SlotsPerEpoch
s := att.Data.Slot
minInclusionCheck := s+params.BeaconConfig().MinAttestationInclusionDelay <= beaconState.Slot
epochInclusionCheck := beaconState.Slot <= s+params.BeaconConfig().SlotsPerEpoch
if !minInclusionCheck {
return nil, fmt.Errorf(
"attestation slot %d + inclusion delay %d > state slot %d",
attestationSlot,
s,
params.BeaconConfig().MinAttestationInclusionDelay,
beaconState.Slot,
)
@@ -596,7 +569,7 @@ func ProcessAttestationNoVerify(ctx context.Context, beaconState *pb.BeaconState
return nil, fmt.Errorf(
"state slot %d > attestation slot %d + SLOTS_PER_EPOCH %d",
beaconState.Slot,
attestationSlot,
s,
params.BeaconConfig().SlotsPerEpoch,
)
}
@@ -612,34 +585,22 @@ func ProcessAttestationNoVerify(ctx context.Context, beaconState *pb.BeaconState
pendingAtt := &pb.PendingAttestation{
Data: data,
AggregationBits: att.AggregationBits,
InclusionDelay: beaconState.Slot - attestationSlot,
InclusionDelay: beaconState.Slot - s,
ProposerIndex: proposerIndex,
}
var ffgSourceEpoch uint64
var ffgSourceRoot []byte
var ffgTargetEpoch uint64
var parentCrosslink *ethpb.Crosslink
if data.Target.Epoch == helpers.CurrentEpoch(beaconState) {
ffgSourceEpoch = beaconState.CurrentJustifiedCheckpoint.Epoch
ffgSourceRoot = beaconState.CurrentJustifiedCheckpoint.Root
ffgTargetEpoch = helpers.CurrentEpoch(beaconState)
crosslinkShard := data.Crosslink.Shard
if int(crosslinkShard) >= len(beaconState.CurrentCrosslinks) {
return nil, fmt.Errorf("invalid shard given in attestation: %d", crosslinkShard)
}
parentCrosslink = beaconState.CurrentCrosslinks[crosslinkShard]
beaconState.CurrentEpochAttestations = append(beaconState.CurrentEpochAttestations, pendingAtt)
} else {
ffgSourceEpoch = beaconState.PreviousJustifiedCheckpoint.Epoch
ffgSourceRoot = beaconState.PreviousJustifiedCheckpoint.Root
ffgTargetEpoch = helpers.PrevEpoch(beaconState)
crosslinkShard := data.Crosslink.Shard
if int(crosslinkShard) >= len(beaconState.PreviousCrosslinks) {
return nil, fmt.Errorf("invalid shard given in attestation: %d", crosslinkShard)
}
parentCrosslink = beaconState.PreviousCrosslinks[crosslinkShard]
beaconState.PreviousEpochAttestations = append(beaconState.PreviousEpochAttestations, pendingAtt)
}
if data.Source.Epoch != ffgSourceEpoch {
@@ -651,34 +612,7 @@ func ProcessAttestationNoVerify(ctx context.Context, beaconState *pb.BeaconState
if data.Target.Epoch != ffgTargetEpoch {
return nil, fmt.Errorf("expected target epoch %d, received %d", ffgTargetEpoch, data.Target.Epoch)
}
endEpoch := parentCrosslink.EndEpoch + params.BeaconConfig().MaxEpochsPerCrosslink
if data.Target.Epoch < endEpoch {
endEpoch = data.Target.Epoch
}
if data.Crosslink.StartEpoch != parentCrosslink.EndEpoch {
return nil, fmt.Errorf("expected crosslink start epoch %d, received %d",
parentCrosslink.EndEpoch, data.Crosslink.StartEpoch)
}
if data.Crosslink.EndEpoch != endEpoch {
return nil, fmt.Errorf("expected crosslink end epoch %d, received %d",
endEpoch, data.Crosslink.EndEpoch)
}
crosslinkParentRoot, err := ssz.HashTreeRoot(parentCrosslink)
if err != nil {
return nil, errors.Wrap(err, "could not tree hash parent crosslink")
}
if !bytes.Equal(data.Crosslink.ParentRoot, crosslinkParentRoot[:]) {
return nil, fmt.Errorf(
"mismatched parent crosslink root, expected %#x, received %#x",
crosslinkParentRoot,
data.Crosslink.ParentRoot,
)
}
// To be removed in Phase 1
if !bytes.Equal(data.Crosslink.DataRoot, params.BeaconConfig().ZeroHash[:]) {
return nil, fmt.Errorf("expected data root %#x == ZERO_HASH", data.Crosslink.DataRoot)
}
return beaconState, nil
}
@@ -708,6 +642,7 @@ func ConvertToIndexed(ctx context.Context, state *pb.BeaconState, attestation *e
if err != nil {
return nil, errors.Wrap(err, "could not get attesting indices")
}
cb1i, err := helpers.AttestingIndices(state, attestation.Data, attestation.CustodyBits)
if err != nil {
return nil, err
@@ -816,7 +751,7 @@ func VerifyIndexedAttestation(ctx context.Context, beaconState *pb.BeaconState,
return fmt.Errorf("custody Bit1 indices are not sorted, got %v", custodyBit1Indices)
}
domain := helpers.Domain(beaconState.Fork, indexedAtt.Data.Target.Epoch, params.BeaconConfig().DomainAttestation)
domain := helpers.Domain(beaconState.Fork, indexedAtt.Data.Target.Epoch, params.BeaconConfig().DomainBeaconAttester)
var pubkeys []*bls.PublicKey
if len(custodyBit0Indices) > 0 {
pubkey, err := bls.PublicKeyFromBytes(beaconState.Validators[custodyBit0Indices[0]].PublicKey)
@@ -1121,130 +1056,6 @@ func VerifyExit(beaconState *pb.BeaconState, exit *ethpb.VoluntaryExit) error {
return nil
}
// ProcessTransfers is one of the operations performed
// on each processed beacon block to determine transfers between beacon chain balances.
//
// Spec pseudocode definition:
// def process_transfer(state: BeaconState, transfer: Transfer) -> None:
// """
// Process ``Transfer`` operation.
// """
// # Verify the balance the covers amount and fee (with overflow protection)
// assert state.balances[transfer.sender] >= max(transfer.amount + transfer.fee, transfer.amount, transfer.fee)
// # A transfer is valid in only one slot
// assert state.slot == transfer.slot
// # SenderIndex must satisfy at least one of the following conditions in the parenthesis:
// assert (
// # * Has not been activated
// state.validator_registry[transfer.sender].activation_eligibility_epoch == FAR_FUTURE_EPOCH or
// # * Is withdrawable
// get_current_epoch(state) >= state.validator_registry[transfer.sender].withdrawable_epoch or
// # * Balance after transfer is more than the effective balance threshold
// transfer.amount + transfer.fee + MAX_EFFECTIVE_BALANCE <= state.balances[transfer.sender]
// )
// # Verify that the pubkey is valid
// assert (
// state.validator_registry[transfer.sender].withdrawal_credentials ==
// int_to_bytes(BLS_WITHDRAWAL_PREFIX, length=1) + hash(transfer.pubkey)[1:]
// )
// # Verify that the signature is valid
// assert bls_verify(transfer.pubkey, signing_root(transfer), transfer.signature, get_domain(state, DOMAIN_TRANSFER))
// # Process the transfer
// decrease_balance(state, transfer.sender, transfer.amount + transfer.fee)
// increase_balance(state, transfer.recipient, transfer.amount)
// increase_balance(state, get_beacon_proposer_index(state), transfer.fee)
// # Verify balances are not dust
// assert not (0 < state.balances[transfer.sender] < MIN_DEPOSIT_AMOUNT)
// assert not (0 < state.balances[transfer.recipient] < MIN_DEPOSIT_AMOUNT)
func ProcessTransfers(
beaconState *pb.BeaconState,
body *ethpb.BeaconBlockBody,
) (*pb.BeaconState, error) {
transfers := body.Transfers
for idx, transfer := range transfers {
if err := verifyTransfer(beaconState, transfer); err != nil {
return nil, errors.Wrapf(err, "could not verify transfer %d", idx)
}
// Process the transfer between accounts.
beaconState = helpers.DecreaseBalance(beaconState, transfer.SenderIndex, transfer.Amount+transfer.Fee)
beaconState = helpers.IncreaseBalance(beaconState, transfer.RecipientIndex, transfer.Amount)
proposerIndex, err := helpers.BeaconProposerIndex(beaconState)
if err != nil {
return nil, errors.Wrap(err, "could not determine beacon proposer index")
}
beaconState = helpers.IncreaseBalance(beaconState, proposerIndex, transfer.Fee)
// Finally, we verify balances will not go below the mininum.
if beaconState.Balances[transfer.SenderIndex] < params.BeaconConfig().MinDepositAmount &&
0 < beaconState.Balances[transfer.SenderIndex] {
return nil, fmt.Errorf(
"sender balance below critical level: %v",
beaconState.Balances[transfer.SenderIndex],
)
}
if beaconState.Balances[transfer.RecipientIndex] < params.BeaconConfig().MinDepositAmount &&
0 < beaconState.Balances[transfer.RecipientIndex] {
return nil, fmt.Errorf(
"recipient balance below critical level: %v",
beaconState.Balances[transfer.RecipientIndex],
)
}
}
return beaconState, nil
}
func verifyTransfer(beaconState *pb.BeaconState, transfer *ethpb.Transfer) error {
if transfer.SenderIndex > uint64(len(beaconState.Validators)) {
return errors.New("transfer sender index out of bounds in validator registry")
}
maxVal := transfer.Fee
if transfer.Amount > maxVal {
maxVal = transfer.Amount
}
if transfer.Amount+transfer.Fee > maxVal {
maxVal = transfer.Amount + transfer.Fee
}
sender := beaconState.Validators[transfer.SenderIndex]
senderBalance := beaconState.Balances[transfer.SenderIndex]
// Verify the balance the covers amount and fee (with overflow protection).
if senderBalance < maxVal {
return fmt.Errorf("expected sender balance %d >= %d", senderBalance, maxVal)
}
// A transfer is valid in only one slot.
if beaconState.Slot != transfer.Slot {
return fmt.Errorf("expected beacon state slot %d == transfer slot %d", beaconState.Slot, transfer.Slot)
}
// Sender must be not yet eligible for activation, withdrawn, or transfer balance over MAX_EFFECTIVE_BALANCE.
senderNotActivationEligible := sender.ActivationEligibilityEpoch == params.BeaconConfig().FarFutureEpoch
senderNotWithdrawn := helpers.CurrentEpoch(beaconState) >= sender.WithdrawableEpoch
underMaxTransfer := transfer.Amount+transfer.Fee+params.BeaconConfig().MaxEffectiveBalance <= senderBalance
if !(senderNotActivationEligible || senderNotWithdrawn || underMaxTransfer) {
return fmt.Errorf(
"expected activation eligiblity: false or withdrawn: false or over max transfer: false, received %v %v %v",
senderNotActivationEligible,
senderNotWithdrawn,
underMaxTransfer,
)
}
// Verify that the pubkey is valid.
buf := []byte{params.BeaconConfig().BLSWithdrawalPrefixByte}
hashed := hashutil.Hash(transfer.SenderWithdrawalPublicKey)
buf = append(buf, hashed[:][1:]...)
if !bytes.Equal(sender.WithdrawalCredentials, buf) {
return fmt.Errorf("invalid public key, expected %v, received %v", buf, sender.WithdrawalCredentials)
}
domain := helpers.Domain(beaconState.Fork, helpers.CurrentEpoch(beaconState), params.BeaconConfig().DomainTransfer)
if err := verifySigningRoot(transfer, transfer.SenderWithdrawalPublicKey, transfer.Signature, domain); err != nil {
return errors.Wrap(err, "could not verify transfer signature")
}
return nil
}
// ClearEth1DataVoteCache clears the eth1 data vote count cache.
func ClearEth1DataVoteCache() {
eth1DataCache = cache.NewEth1DataVoteCache()

View File

@@ -23,7 +23,6 @@ import (
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/bls"
"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/prysmaticlabs/prysm/shared/trieutil"
@@ -36,12 +35,8 @@ func init() {
}
func TestProcessBlockHeader_WrongProposerSig(t *testing.T) {
if params.BeaconConfig().SlotsPerEpoch != 64 {
t.Errorf("SlotsPerEpoch should be 64 for these tests to pass")
}
deposits, _, privKeys := testutil.SetupInitialDeposits(t, 100)
beaconState, err := state.GenesisBeaconState(deposits, 0, &ethpb.Eth1Data{})
beaconState, err := state.GenesisBeaconState(deposits, 0, &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Error(err)
}
@@ -81,10 +76,6 @@ func TestProcessBlockHeader_WrongProposerSig(t *testing.T) {
}
func TestProcessBlockHeader_DifferentSlots(t *testing.T) {
if params.BeaconConfig().SlotsPerEpoch != 64 {
t.Errorf("SlotsPerEpoch should be 64 for these tests to pass")
}
validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount)
for i := 0; i < len(validators); i++ {
validators[i] = &ethpb.Validator{
@@ -101,8 +92,7 @@ func TestProcessBlockHeader_DifferentSlots(t *testing.T) {
PreviousVersion: []byte{0, 0, 0, 0},
CurrentVersion: []byte{0, 0, 0, 0},
},
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
}
lbhsr, err := ssz.HashTreeRoot(state.LatestBlockHeader)
@@ -134,10 +124,6 @@ func TestProcessBlockHeader_DifferentSlots(t *testing.T) {
}
func TestProcessBlockHeader_PreviousBlockRootNotSignedRoot(t *testing.T) {
if params.BeaconConfig().SlotsPerEpoch != 64 {
t.Errorf("SlotsPerEpoch should be 64 for these tests to pass")
}
validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount)
for i := 0; i < len(validators); i++ {
validators[i] = &ethpb.Validator{
@@ -154,8 +140,7 @@ func TestProcessBlockHeader_PreviousBlockRootNotSignedRoot(t *testing.T) {
PreviousVersion: []byte{0, 0, 0, 0},
CurrentVersion: []byte{0, 0, 0, 0},
},
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
}
currentEpoch := helpers.CurrentEpoch(state)
@@ -183,10 +168,6 @@ func TestProcessBlockHeader_PreviousBlockRootNotSignedRoot(t *testing.T) {
}
func TestProcessBlockHeader_SlashedProposer(t *testing.T) {
if params.BeaconConfig().SlotsPerEpoch != 64 {
t.Errorf("SlotsPerEpoch should be 64 for these tests to pass")
}
validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount)
for i := 0; i < len(validators); i++ {
validators[i] = &ethpb.Validator{
@@ -203,8 +184,7 @@ func TestProcessBlockHeader_SlashedProposer(t *testing.T) {
PreviousVersion: []byte{0, 0, 0, 0},
CurrentVersion: []byte{0, 0, 0, 0},
},
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
}
parentRoot, err := ssz.SigningRoot(state.LatestBlockHeader)
@@ -238,10 +218,6 @@ func TestProcessBlockHeader_SlashedProposer(t *testing.T) {
func TestProcessBlockHeader_OK(t *testing.T) {
helpers.ClearAllCaches()
if params.BeaconConfig().SlotsPerEpoch != 64 {
t.Fatalf("SlotsPerEpoch should be 64 for these tests to pass")
}
validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount)
for i := 0; i < len(validators); i++ {
validators[i] = &ethpb.Validator{
@@ -258,8 +234,7 @@ func TestProcessBlockHeader_OK(t *testing.T) {
PreviousVersion: []byte{0, 0, 0, 0},
CurrentVersion: []byte{0, 0, 0, 0},
},
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
}
latestBlockSignedRoot, err := ssz.SigningRoot(state.LatestBlockHeader)
@@ -320,7 +295,7 @@ func TestProcessRandao_IncorrectProposerFailsVerification(t *testing.T) {
helpers.ClearAllCaches()
deposits, _, privKeys := testutil.SetupInitialDeposits(t, 100)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{})
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Fatal(err)
}
@@ -353,7 +328,7 @@ func TestProcessRandao_IncorrectProposerFailsVerification(t *testing.T) {
func TestProcessRandao_SignatureVerifiesAndUpdatesLatestStateMixes(t *testing.T) {
deposits, _, privKeys := testutil.SetupInitialDeposits(t, 100)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{})
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Fatal(err)
}
@@ -421,7 +396,7 @@ func TestProcessEth1Data_SetsCorrectly(t *testing.T) {
)
}
}
func TestProcessProposerSlashings_UnmatchedHeaderEpochs(t *testing.T) {
func TestProcessProposerSlashings_UnmatchedHeaderSlots(t *testing.T) {
registry := make([]*ethpb.Validator, 2)
currentSlot := uint64(0)
slashings := []*ethpb.ProposerSlashing{
@@ -445,7 +420,7 @@ func TestProcessProposerSlashings_UnmatchedHeaderEpochs(t *testing.T) {
ProposerSlashings: slashings,
},
}
want := "mismatched header epochs"
want := "mismatched header slots"
if _, err := blocks.ProcessProposerSlashings(context.Background(), beaconState, block.Body); !strings.Contains(err.Error(), want) {
t.Errorf("Expected %s, received %v", want, err)
}
@@ -527,7 +502,6 @@ func TestProcessProposerSlashings_ValidatorNotSlashable(t *testing.T) {
func TestProcessProposerSlashings_AppliesCorrectStatus(t *testing.T) {
// We test the case when data is correct and verify the validator
// registry has been updated.
helpers.ClearShuffledValidatorCache()
validators := make([]*ethpb.Validator, 100)
for i := 0; i < len(validators); i++ {
validators[i] = &ethpb.Validator{
@@ -553,9 +527,8 @@ func TestProcessProposerSlashings_AppliesCorrectStatus(t *testing.T) {
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
Epoch: 0,
},
Slashings: make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector),
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
Slashings: make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector),
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
}
domain := helpers.Domain(
@@ -643,18 +616,12 @@ func TestProcessAttesterSlashings_DataNotSlashable(t *testing.T) {
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0},
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{
Shard: 4,
},
},
},
Attestation_2: &ethpb.IndexedAttestation{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 1},
Target: &ethpb.Checkpoint{Epoch: 1},
Crosslink: &ethpb.Crosslink{
Shard: 3,
},
},
},
},
@@ -685,9 +652,6 @@ func TestProcessAttesterSlashings_IndexedAttestationFailedToVerify(t *testing.T)
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 1},
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{
Shard: 4,
},
},
CustodyBit_0Indices: []uint64{0, 1, 2},
CustodyBit_1Indices: []uint64{0, 1, 2},
@@ -696,9 +660,6 @@ func TestProcessAttesterSlashings_IndexedAttestationFailedToVerify(t *testing.T)
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0},
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{
Shard: 4,
},
},
CustodyBit_0Indices: []uint64{0, 1, 2},
CustodyBit_1Indices: []uint64{0, 1, 2},
@@ -729,9 +690,6 @@ func TestProcessAttesterSlashings_IndexedAttestationFailedToVerify(t *testing.T)
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 1},
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{
Shard: 4,
},
},
CustodyBit_0Indices: make([]uint64, params.BeaconConfig().MaxValidatorsPerCommittee+1),
},
@@ -739,9 +697,6 @@ func TestProcessAttesterSlashings_IndexedAttestationFailedToVerify(t *testing.T)
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0},
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{
Shard: 4,
},
},
CustodyBit_0Indices: make([]uint64, params.BeaconConfig().MaxValidatorsPerCommittee+1),
},
@@ -758,7 +713,7 @@ func TestProcessAttesterSlashings_IndexedAttestationFailedToVerify(t *testing.T)
func TestProcessAttesterSlashings_AppliesCorrectStatus(t *testing.T) {
deposits, _, privKeys := testutil.SetupInitialDeposits(t, 100)
beaconState, err := state.GenesisBeaconState(deposits, 0, &ethpb.Eth1Data{})
beaconState, err := state.GenesisBeaconState(deposits, 0, &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
for _, vv := range beaconState.Validators {
vv.WithdrawableEpoch = 1 * params.BeaconConfig().SlotsPerEpoch
}
@@ -767,9 +722,6 @@ func TestProcessAttesterSlashings_AppliesCorrectStatus(t *testing.T) {
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 1},
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{
Shard: 4,
},
},
CustodyBit_0Indices: []uint64{0, 1},
}
@@ -781,7 +733,7 @@ func TestProcessAttesterSlashings_AppliesCorrectStatus(t *testing.T) {
if err != nil {
t.Error(err)
}
domain := helpers.Domain(beaconState.Fork, 0, params.BeaconConfig().DomainAttestation)
domain := helpers.Domain(beaconState.Fork, 0, params.BeaconConfig().DomainBeaconAttester)
sig0 := privKeys[0].Sign(hashTreeRoot[:], domain)
sig1 := privKeys[1].Sign(hashTreeRoot[:], domain)
aggregateSig := bls.AggregateSignatures([]*bls.Signature{sig0, sig1})
@@ -791,9 +743,6 @@ func TestProcessAttesterSlashings_AppliesCorrectStatus(t *testing.T) {
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0},
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{
Shard: 4,
},
},
CustodyBit_0Indices: []uint64{0, 1},
}
@@ -851,9 +800,7 @@ func TestProcessAttestations_InclusionDelayFailure(t *testing.T) {
{
Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{
Shard: 0,
},
Slot: 5,
},
},
}
@@ -863,19 +810,14 @@ func TestProcessAttestations_InclusionDelayFailure(t *testing.T) {
},
}
deposits, _, _ := testutil.SetupInitialDeposits(t, 100)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{})
if err != nil {
t.Fatal(err)
}
attestationSlot, err := helpers.AttestationDataSlot(beaconState, attestations[0].Data)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Fatal(err)
}
want := fmt.Sprintf(
"attestation slot %d + inclusion delay %d > state slot %d",
attestationSlot,
attestations[0].Data.Slot,
params.BeaconConfig().MinAttestationInclusionDelay,
beaconState.Slot,
)
@@ -891,13 +833,7 @@ func TestProcessAttestations_NeitherCurrentNorPrevEpoch(t *testing.T) {
att := &ethpb.Attestation{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{
Shard: 0,
StartEpoch: 0,
},
},
}
Target: &ethpb.Checkpoint{Epoch: 0}}}
block := &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
@@ -905,17 +841,12 @@ func TestProcessAttestations_NeitherCurrentNorPrevEpoch(t *testing.T) {
},
}
deposits, _, _ := testutil.SetupInitialDeposits(t, 100)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{})
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Fatal(err)
}
helpers.ClearAllCaches()
beaconState.Slot += params.BeaconConfig().SlotsPerEpoch*4 + params.BeaconConfig().MinAttestationInclusionDelay
beaconState.PreviousCrosslinks = []*ethpb.Crosslink{
{
Shard: 0,
},
}
beaconState.PreviousJustifiedCheckpoint.Root = []byte("hello-world")
beaconState.PreviousEpochAttestations = []*pb.PendingAttestation{}
@@ -933,17 +864,13 @@ func TestProcessAttestations_NeitherCurrentNorPrevEpoch(t *testing.T) {
func TestProcessAttestations_CurrentEpochFFGDataMismatches(t *testing.T) {
helpers.ClearAllCaches()
aggBits := bitfield.NewBitlist(1)
custodyBits := bitfield.NewBitlist(1)
aggBits := bitfield.NewBitlist(3)
custodyBits := bitfield.NewBitlist(3)
attestations := []*ethpb.Attestation{
{
Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 0},
Source: &ethpb.Checkpoint{Epoch: 1},
Crosslink: &ethpb.Crosslink{
Shard: 0,
StartEpoch: 0,
},
},
AggregationBits: aggBits,
CustodyBits: custodyBits,
@@ -955,16 +882,11 @@ func TestProcessAttestations_CurrentEpochFFGDataMismatches(t *testing.T) {
},
}
deposits, _, _ := testutil.SetupInitialDeposits(t, 100)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{})
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Fatal(err)
}
beaconState.Slot += params.BeaconConfig().MinAttestationInclusionDelay
beaconState.CurrentCrosslinks = []*ethpb.Crosslink{
{
Shard: 0,
},
}
beaconState.CurrentJustifiedCheckpoint.Root = []byte("hello-world")
beaconState.CurrentEpochAttestations = []*pb.PendingAttestation{}
@@ -994,22 +916,20 @@ func TestProcessAttestations_PrevEpochFFGDataMismatches(t *testing.T) {
helpers.ClearAllCaches()
deposits, _, _ := testutil.SetupInitialDeposits(t, 100)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{})
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Fatal(err)
}
aggBits := bitfield.NewBitlist(1)
aggBits := bitfield.NewBitlist(3)
aggBits.SetBitAt(0, true)
custodyBits := bitfield.NewBitlist(1)
custodyBits := bitfield.NewBitlist(3)
attestations := []*ethpb.Attestation{
{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 1},
Target: &ethpb.Checkpoint{Epoch: 1},
Crosslink: &ethpb.Crosslink{
Shard: 0,
},
Slot: 1,
},
AggregationBits: aggBits,
CustodyBits: custodyBits,
@@ -1023,11 +943,6 @@ func TestProcessAttestations_PrevEpochFFGDataMismatches(t *testing.T) {
helpers.ClearAllCaches()
beaconState.Slot += params.BeaconConfig().SlotsPerEpoch + params.BeaconConfig().MinAttestationInclusionDelay
beaconState.PreviousCrosslinks = []*ethpb.Crosslink{
{
Shard: 0,
},
}
beaconState.PreviousJustifiedCheckpoint.Root = []byte("hello-world")
beaconState.PreviousEpochAttestations = []*pb.PendingAttestation{}
@@ -1055,86 +970,20 @@ func TestProcessAttestations_PrevEpochFFGDataMismatches(t *testing.T) {
}
}
func TestProcessAttestations_CrosslinkMismatches(t *testing.T) {
helpers.ClearAllCaches()
aggBits := bitfield.NewBitlist(1)
aggBits.SetBitAt(0, true)
custodyBits := bitfield.NewBitlist(1)
attestations := []*ethpb.Attestation{
{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{
Shard: 0,
},
},
AggregationBits: aggBits,
CustodyBits: custodyBits,
},
}
block := &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
Attestations: attestations,
},
}
deposits, _, _ := testutil.SetupInitialDeposits(t, 100)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{})
if err != nil {
t.Fatal(err)
}
beaconState.Slot += params.BeaconConfig().MinAttestationInclusionDelay
beaconState.CurrentCrosslinks = []*ethpb.Crosslink{
{
Shard: 0,
StartEpoch: 0,
},
}
beaconState.CurrentJustifiedCheckpoint.Root = []byte("hello-world")
beaconState.CurrentEpochAttestations = []*pb.PendingAttestation{}
want := "mismatched parent crosslink root"
if _, err := blocks.ProcessAttestations(context.Background(), beaconState, block.Body); !strings.Contains(err.Error(), want) {
t.Errorf("Expected %s, received %v", want, err)
}
block.Body.Attestations[0].Data.Crosslink.StartEpoch = 0
if _, err := blocks.ProcessAttestations(context.Background(), beaconState, block.Body); !strings.Contains(err.Error(), want) {
t.Errorf("Expected %s, received %v", want, err)
}
encoded, err := ssz.HashTreeRoot(beaconState.CurrentCrosslinks[0])
if err != nil {
t.Fatal(err)
}
block.Body.Attestations[0].Data.Crosslink.ParentRoot = encoded[:]
block.Body.Attestations[0].Data.Crosslink.DataRoot = encoded[:]
want = fmt.Sprintf("expected data root %#x == ZERO_HASH", encoded)
if _, err := blocks.ProcessAttestations(context.Background(), beaconState, block.Body); !strings.Contains(err.Error(), want) {
t.Errorf("Expected %s, received %v", want, err)
}
}
func TestProcessAttestations_InvalidAggregationBitsLength(t *testing.T) {
helpers.ClearAllCaches()
deposits, _, _ := testutil.SetupInitialDeposits(t, 100)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{})
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Fatal(err)
}
aggBits := bitfield.NewBitlist(2)
custodyBits := bitfield.NewBitlist(2)
aggBits := bitfield.NewBitlist(4)
custodyBits := bitfield.NewBitlist(4)
att := &ethpb.Attestation{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{
Shard: 0,
StartEpoch: 0,
},
},
Target: &ethpb.Checkpoint{Epoch: 0}},
AggregationBits: aggBits,
CustodyBits: custodyBits,
}
@@ -1146,67 +995,39 @@ func TestProcessAttestations_InvalidAggregationBitsLength(t *testing.T) {
}
beaconState.Slot += params.BeaconConfig().MinAttestationInclusionDelay
beaconState.CurrentCrosslinks = []*ethpb.Crosslink{
{
Shard: 0,
StartEpoch: 0,
},
}
beaconState.CurrentJustifiedCheckpoint.Root = []byte("hello-world")
beaconState.CurrentEpochAttestations = []*pb.PendingAttestation{}
encoded, err := ssz.HashTreeRoot(beaconState.CurrentCrosslinks[0])
if err != nil {
t.Fatal(err)
}
block.Body.Attestations[0].Data.Crosslink.ParentRoot = encoded[:]
block.Body.Attestations[0].Data.Crosslink.DataRoot = params.BeaconConfig().ZeroHash[:]
expected := "failed to verify aggregation bitfield: wanted participants bitfield length 1, got: 2"
expected := "failed to verify aggregation bitfield: wanted participants bitfield length 3, got: 4"
_, err = blocks.ProcessAttestations(context.Background(), beaconState, block.Body)
if !strings.Contains(err.Error(), expected) {
t.Errorf("Expected error checking aggregation and custody bit length, received: %v", err)
t.Errorf("Did not receive wanted error")
}
}
func TestProcessAttestations_OK(t *testing.T) {
helpers.ClearAllCaches()
deposits, _, privKeys := testutil.SetupInitialDeposits(t, 100)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{})
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Fatal(err)
}
aggBits := bitfield.NewBitlist(1)
aggBits := bitfield.NewBitlist(3)
aggBits.SetBitAt(0, true)
custodyBits := bitfield.NewBitlist(1)
custodyBits := bitfield.NewBitlist(3)
att := &ethpb.Attestation{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
Target: &ethpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
Crosslink: &ethpb.Crosslink{
Shard: 0,
StartEpoch: 0,
},
},
AggregationBits: aggBits,
CustodyBits: custodyBits,
}
beaconState.CurrentCrosslinks = []*ethpb.Crosslink{
{
Shard: 0,
StartEpoch: 0,
},
}
beaconState.CurrentJustifiedCheckpoint.Root = []byte("hello-world")
beaconState.CurrentEpochAttestations = []*pb.PendingAttestation{}
encoded, err := ssz.HashTreeRoot(beaconState.CurrentCrosslinks[0])
if err != nil {
t.Fatal(err)
}
att.Data.Crosslink.ParentRoot = encoded[:]
att.Data.Crosslink.DataRoot = params.BeaconConfig().ZeroHash[:]
attestingIndices, err := helpers.AttestingIndices(beaconState, att.Data, att.AggregationBits)
if err != nil {
@@ -1220,7 +1041,7 @@ func TestProcessAttestations_OK(t *testing.T) {
if err != nil {
t.Error(err)
}
domain := helpers.Domain(beaconState.Fork, 0, params.BeaconConfig().DomainAttestation)
domain := helpers.Domain(beaconState.Fork, 0, params.BeaconConfig().DomainBeaconAttester)
sigs := make([]*bls.Signature, len(attestingIndices))
for i, indice := range attestingIndices {
sig := privKeys[indice].Sign(hashTreeRoot[:], domain)
@@ -1244,19 +1065,15 @@ func TestProcessAttestations_OK(t *testing.T) {
func TestProcessAggregatedAttestation_OverlappingBits(t *testing.T) {
helpers.ClearAllCaches()
deposits, _, privKeys := testutil.SetupInitialDeposits(t, 300)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{})
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Fatal(err)
}
domain := helpers.Domain(beaconState.Fork, 0, params.BeaconConfig().DomainAttestation)
domain := helpers.Domain(beaconState.Fork, 0, params.BeaconConfig().DomainBeaconAttester)
data := &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
Target: &ethpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
Crosslink: &ethpb.Crosslink{
Shard: 0,
StartEpoch: 0,
},
}
aggBits1 := bitfield.NewBitlist(4)
aggBits1.SetBitAt(0, true)
@@ -1269,15 +1086,8 @@ func TestProcessAggregatedAttestation_OverlappingBits(t *testing.T) {
CustodyBits: custodyBits1,
}
beaconState.CurrentCrosslinks = []*ethpb.Crosslink{{Shard: 0, StartEpoch: 0}}
beaconState.CurrentJustifiedCheckpoint.Root = []byte("hello-world")
beaconState.CurrentEpochAttestations = []*pb.PendingAttestation{}
encoded, err := ssz.HashTreeRoot(beaconState.CurrentCrosslinks[0])
if err != nil {
t.Fatal(err)
}
att1.Data.Crosslink.ParentRoot = encoded[:]
att1.Data.Crosslink.DataRoot = params.BeaconConfig().ZeroHash[:]
attestingIndices1, err := helpers.AttestingIndices(beaconState, att1.Data, att1.AggregationBits)
if err != nil {
@@ -1309,9 +1119,6 @@ func TestProcessAggregatedAttestation_OverlappingBits(t *testing.T) {
CustodyBits: custodyBits2,
}
att2.Data.Crosslink.ParentRoot = encoded[:]
att2.Data.Crosslink.DataRoot = params.BeaconConfig().ZeroHash[:]
attestingIndices2, err := helpers.AttestingIndices(beaconState, att2.Data, att2.AggregationBits)
if err != nil {
t.Fatal(err)
@@ -1339,39 +1146,28 @@ func TestProcessAggregatedAttestation_OverlappingBits(t *testing.T) {
func TestProcessAggregatedAttestation_NoOverlappingBits(t *testing.T) {
helpers.ClearAllCaches()
deposits, _, privKeys := testutil.SetupInitialDeposits(t, 300)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{})
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Fatal(err)
}
domain := helpers.Domain(beaconState.Fork, 0, params.BeaconConfig().DomainAttestation)
domain := helpers.Domain(beaconState.Fork, 0, params.BeaconConfig().DomainBeaconAttester)
data := &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
Target: &ethpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
Crosslink: &ethpb.Crosslink{
Shard: 0,
StartEpoch: 0,
},
}
aggBits1 := bitfield.NewBitlist(4)
aggBits1 := bitfield.NewBitlist(9)
aggBits1.SetBitAt(0, true)
aggBits1.SetBitAt(1, true)
custodyBits1 := bitfield.NewBitlist(4)
custodyBits1 := bitfield.NewBitlist(9)
att1 := &ethpb.Attestation{
Data: data,
AggregationBits: aggBits1,
CustodyBits: custodyBits1,
}
beaconState.CurrentCrosslinks = []*ethpb.Crosslink{{Shard: 0, StartEpoch: 0}}
beaconState.CurrentJustifiedCheckpoint.Root = []byte("hello-world")
beaconState.CurrentEpochAttestations = []*pb.PendingAttestation{}
encoded, err := ssz.HashTreeRoot(beaconState.CurrentCrosslinks[0])
if err != nil {
t.Fatal(err)
}
att1.Data.Crosslink.ParentRoot = encoded[:]
att1.Data.Crosslink.DataRoot = params.BeaconConfig().ZeroHash[:]
attestingIndices1, err := helpers.AttestingIndices(beaconState, att1.Data, att1.AggregationBits)
if err != nil {
@@ -1392,19 +1188,16 @@ func TestProcessAggregatedAttestation_NoOverlappingBits(t *testing.T) {
}
att1.Signature = bls.AggregateSignatures(sigs).Marshal()[:]
aggBits2 := bitfield.NewBitlist(4)
aggBits2 := bitfield.NewBitlist(9)
aggBits2.SetBitAt(2, true)
aggBits2.SetBitAt(3, true)
custodyBits2 := bitfield.NewBitlist(4)
custodyBits2 := bitfield.NewBitlist(9)
att2 := &ethpb.Attestation{
Data: data,
AggregationBits: aggBits2,
CustodyBits: custodyBits2,
}
att2.Data.Crosslink.ParentRoot = encoded[:]
att2.Data.Crosslink.DataRoot = params.BeaconConfig().ZeroHash[:]
attestingIndices2, err := helpers.AttestingIndices(beaconState, att2.Data, att2.AggregationBits)
if err != nil {
t.Fatal(err)
@@ -1445,22 +1238,18 @@ func TestProcessAttestationsNoVerify_OK(t *testing.T) {
// Attestation with an empty signature
helpers.ClearAllCaches()
deposits, _, _ := testutil.SetupInitialDeposits(t, 100)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{})
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Fatal(err)
}
aggBits := bitfield.NewBitlist(1)
aggBits := bitfield.NewBitlist(3)
aggBits.SetBitAt(1, true)
custodyBits := bitfield.NewBitlist(1)
custodyBits := bitfield.NewBitlist(3)
att := &ethpb.Attestation{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{
Shard: 0,
StartEpoch: 0,
},
},
AggregationBits: aggBits,
CustodyBits: custodyBits,
@@ -1470,22 +1259,9 @@ func TestProcessAttestationsNoVerify_OK(t *testing.T) {
att.Signature = zeroSig[:]
beaconState.Slot += params.BeaconConfig().MinAttestationInclusionDelay
beaconState.CurrentCrosslinks = []*ethpb.Crosslink{
{
Shard: 0,
StartEpoch: 0,
},
}
beaconState.CurrentJustifiedCheckpoint.Root = []byte("hello-world")
beaconState.CurrentEpochAttestations = []*pb.PendingAttestation{}
encoded, err := ssz.HashTreeRoot(beaconState.CurrentCrosslinks[0])
if err != nil {
t.Fatal(err)
}
att.Data.Crosslink.ParentRoot = encoded[:]
att.Data.Crosslink.DataRoot = params.BeaconConfig().ZeroHash[:]
if _, err := blocks.ProcessAttestationNoVerify(context.TODO(), beaconState, att); err != nil {
t.Errorf("Unexpected error: %v", err)
}
@@ -1493,9 +1269,6 @@ func TestProcessAttestationsNoVerify_OK(t *testing.T) {
func TestConvertToIndexed_OK(t *testing.T) {
helpers.ClearAllCaches()
if params.BeaconConfig().SlotsPerEpoch != 64 {
t.Errorf("SlotsPerEpoch should be 64 for these tests to pass")
}
validators := make([]*ethpb.Validator, 2*params.BeaconConfig().SlotsPerEpoch)
for i := 0; i < len(validators); i++ {
@@ -1505,10 +1278,9 @@ func TestConvertToIndexed_OK(t *testing.T) {
}
state := &pb.BeaconState{
Slot: 5,
Validators: validators,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
Slot: 5,
Validators: validators,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
}
tests := []struct {
aggregationBitfield bitfield.Bitlist
@@ -1519,20 +1291,20 @@ func TestConvertToIndexed_OK(t *testing.T) {
{
aggregationBitfield: bitfield.Bitlist{0x07},
custodyBitfield: bitfield.Bitlist{0x05},
wantedCustodyBit0Indices: []uint64{71},
wantedCustodyBit1Indices: []uint64{127},
wantedCustodyBit0Indices: []uint64{4},
wantedCustodyBit1Indices: []uint64{30},
},
{
aggregationBitfield: bitfield.Bitlist{0x07},
custodyBitfield: bitfield.Bitlist{0x06},
wantedCustodyBit0Indices: []uint64{127},
wantedCustodyBit1Indices: []uint64{71},
wantedCustodyBit0Indices: []uint64{30},
wantedCustodyBit1Indices: []uint64{4},
},
{
aggregationBitfield: bitfield.Bitlist{0x07},
custodyBitfield: bitfield.Bitlist{0x07},
wantedCustodyBit0Indices: []uint64{},
wantedCustodyBit1Indices: []uint64{71, 127},
wantedCustodyBit1Indices: []uint64{4, 30},
},
}
@@ -1541,9 +1313,6 @@ func TestConvertToIndexed_OK(t *testing.T) {
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0},
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{
Shard: 3,
},
},
}
for _, tt := range tests {
@@ -1571,10 +1340,8 @@ func TestConvertToIndexed_OK(t *testing.T) {
func TestVerifyIndexedAttestation_OK(t *testing.T) {
helpers.ClearAllCaches()
if params.BeaconConfig().SlotsPerEpoch != 64 {
t.Errorf("SlotsPerEpoch should be 64 for these tests to pass")
}
numOfValidators := 2 * params.BeaconConfig().SlotsPerEpoch
numOfValidators := 4 * params.BeaconConfig().SlotsPerEpoch
validators := make([]*ethpb.Validator, numOfValidators)
_, _, keys := testutil.SetupInitialDeposits(t, numOfValidators)
for i := 0; i < len(validators); i++ {
@@ -1592,8 +1359,7 @@ func TestVerifyIndexedAttestation_OK(t *testing.T) {
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
},
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
}
tests := []struct {
attestation *ethpb.IndexedAttestation
@@ -1640,7 +1406,7 @@ func TestVerifyIndexedAttestation_OK(t *testing.T) {
CustodyBit: false,
}
domain := helpers.Domain(state.Fork, tt.attestation.Data.Target.Epoch, params.BeaconConfig().DomainAttestation)
domain := helpers.Domain(state.Fork, tt.attestation.Data.Target.Epoch, params.BeaconConfig().DomainBeaconAttester)
root, err := ssz.HashTreeRoot(attDataAndCustodyBit)
if err != nil {
@@ -2102,203 +1868,3 @@ func TestProcessVoluntaryExits_AppliesCorrectStatus(t *testing.T) {
helpers.DelayedActivationExitEpoch(state.Slot/params.BeaconConfig().SlotsPerEpoch), newRegistry[0].ExitEpoch)
}
}
func TestProcessBeaconTransfers_NotEnoughSenderIndexBalance(t *testing.T) {
registry := []*ethpb.Validator{
{
ActivationEligibilityEpoch: params.BeaconConfig().FarFutureEpoch,
},
}
balances := []uint64{params.BeaconConfig().MaxEffectiveBalance}
state := &pb.BeaconState{
Validators: registry,
Balances: balances,
}
transfers := []*ethpb.Transfer{
{
Fee: params.BeaconConfig().MaxEffectiveBalance,
Amount: params.BeaconConfig().MaxEffectiveBalance,
},
}
block := &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
Transfers: transfers,
},
}
want := fmt.Sprintf(
"expected sender balance %d >= %d",
balances[0],
transfers[0].Fee+transfers[0].Amount,
)
if _, err := blocks.ProcessTransfers(state, block.Body); !strings.Contains(err.Error(), want) {
t.Errorf("Expected %s, received %v", want, err)
}
}
func TestProcessBeaconTransfers_FailsVerification(t *testing.T) {
testConfig := params.BeaconConfig()
testConfig.MaxTransfers = 1
params.OverrideBeaconConfig(testConfig)
registry := []*ethpb.Validator{
{
ActivationEligibilityEpoch: params.BeaconConfig().FarFutureEpoch,
},
{
ActivationEligibilityEpoch: params.BeaconConfig().FarFutureEpoch,
},
}
balances := []uint64{params.BeaconConfig().MaxEffectiveBalance}
state := &pb.BeaconState{
Slot: 0,
Validators: registry,
Balances: balances,
}
transfers := []*ethpb.Transfer{
{
Fee: params.BeaconConfig().MaxEffectiveBalance + 1,
},
}
block := &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
Transfers: transfers,
},
}
want := fmt.Sprintf(
"expected sender balance %d >= %d",
balances[0],
transfers[0].Fee,
)
if _, err := blocks.ProcessTransfers(state, block.Body); !strings.Contains(err.Error(), want) {
t.Errorf("Expected %s, received %v", want, err)
}
block.Body.Transfers = []*ethpb.Transfer{
{
Fee: params.BeaconConfig().MinDepositAmount,
Slot: state.Slot + 1,
},
}
want = fmt.Sprintf(
"expected beacon state slot %d == transfer slot %d",
state.Slot,
block.Body.Transfers[0].Slot,
)
if _, err := blocks.ProcessTransfers(state, block.Body); !strings.Contains(err.Error(), want) {
t.Errorf("Expected %s, received %v", want, err)
}
state.Validators[0].WithdrawableEpoch = params.BeaconConfig().FarFutureEpoch
state.Validators[0].ActivationEligibilityEpoch = 0
state.Balances[0] = params.BeaconConfig().MinDepositAmount + params.BeaconConfig().MaxEffectiveBalance
block.Body.Transfers = []*ethpb.Transfer{
{
Fee: params.BeaconConfig().MinDepositAmount,
Amount: params.BeaconConfig().MaxEffectiveBalance,
Slot: state.Slot,
},
}
want = "over max transfer"
if _, err := blocks.ProcessTransfers(state, block.Body); !strings.Contains(err.Error(), want) {
t.Errorf("Expected %s, received %v", want, err)
}
state.Validators[0].WithdrawableEpoch = 0
state.Validators[0].ActivationEligibilityEpoch = params.BeaconConfig().FarFutureEpoch
buf := []byte{params.BeaconConfig().BLSWithdrawalPrefixByte}
pubKey := []byte("B")
hashed := hashutil.Hash(pubKey)
buf = append(buf, hashed[:]...)
state.Validators[0].WithdrawalCredentials = buf
block.Body.Transfers = []*ethpb.Transfer{
{
Fee: params.BeaconConfig().MinDepositAmount,
Amount: params.BeaconConfig().MinDepositAmount,
Slot: state.Slot,
SenderWithdrawalPublicKey: []byte("A"),
},
}
want = "invalid public key"
if _, err := blocks.ProcessTransfers(state, block.Body); !strings.Contains(err.Error(), want) {
t.Errorf("Expected %s, received %v", want, err)
}
}
func TestProcessBeaconTransfers_OK(t *testing.T) {
helpers.ClearShuffledValidatorCache()
testConfig := params.BeaconConfig()
testConfig.MaxTransfers = 1
params.OverrideBeaconConfig(testConfig)
validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount/32)
for i := 0; i < len(validators); i++ {
validators[i] = &ethpb.Validator{
ActivationEpoch: 0,
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
Slashed: false,
WithdrawableEpoch: 0,
}
}
validatorBalances := make([]uint64, len(validators))
for i := 0; i < len(validatorBalances); i++ {
validatorBalances[i] = params.BeaconConfig().MaxEffectiveBalance
}
state := &pb.BeaconState{
Validators: validators,
Slot: 0,
Balances: validatorBalances,
Fork: &pb.Fork{
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
},
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
Slashings: make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
}
transfer := &ethpb.Transfer{
SenderIndex: 0,
RecipientIndex: 1,
Fee: params.BeaconConfig().MinDepositAmount,
Amount: params.BeaconConfig().MinDepositAmount,
Slot: state.Slot,
}
priv, err := bls.RandKey(rand.Reader)
if err != nil {
t.Fatal(err)
}
pubKey := priv.PublicKey().Marshal()[:]
transfer.SenderWithdrawalPublicKey = pubKey
state.Validators[transfer.SenderIndex].PublicKey = pubKey
signingRoot, err := ssz.SigningRoot(transfer)
if err != nil {
t.Fatalf("Failed to get signing root of block: %v", err)
}
epoch := helpers.CurrentEpoch(state)
dt := helpers.Domain(state.Fork, epoch, params.BeaconConfig().DomainTransfer)
transferSig := priv.Sign(signingRoot[:], dt)
transfer.Signature = transferSig.Marshal()[:]
block := &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
Transfers: []*ethpb.Transfer{transfer},
},
}
buf := []byte{params.BeaconConfig().BLSWithdrawalPrefixByte}
hashed := hashutil.Hash(pubKey)
buf = append(buf, hashed[:][1:]...)
state.Validators[0].WithdrawalCredentials = buf
state.Validators[0].ActivationEligibilityEpoch = params.BeaconConfig().FarFutureEpoch
newState, err := blocks.ProcessTransfers(state, block.Body)
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
expectedRecipientIndex := params.BeaconConfig().MaxEffectiveBalance + block.Body.Transfers[0].Amount
if newState.Balances[1] != expectedRecipientIndex {
t.Errorf("Expected recipient balance %d, received %d", newState.Balances[1], expectedRecipientIndex)
}
expectedSenderIndex := params.BeaconConfig().MaxEffectiveBalance - block.Body.Transfers[0].Amount - block.Body.Transfers[0].Fee
if newState.Balances[0] != expectedSenderIndex {
t.Errorf("Expected sender balance %d, received %d", newState.Balances[0], expectedSenderIndex)
}
}

View File

@@ -60,6 +60,9 @@ func runBlockProcessingTest(t *testing.T, config string) {
t.Fatalf("Failed to unmarshal: %v", err)
}
beaconState, transitionError = state.ExecuteStateTransition(context.Background(), beaconState, block)
if transitionError != nil {
break
}
}
// If the post.ssz is not present, it means the test should fail on our end.
@@ -73,7 +76,7 @@ func runBlockProcessingTest(t *testing.T, config string) {
if postSSZExists {
if transitionError != nil {
t.Fatalf("Unexpected error: %v", transitionError)
t.Errorf("Unexpected error: %v", transitionError)
}
postBeaconStateFile, err := ioutil.ReadFile(postSSZFilepath)

View File

@@ -15,7 +15,6 @@ go_library(
"//proto/eth/v1alpha1:go_default_library",
"//shared/mathutil:go_default_library",
"//shared/params:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
],

View File

@@ -9,7 +9,6 @@ import (
"fmt"
"sort"
"github.com/gogo/protobuf/proto"
"github.com/pkg/errors"
"github.com/prysmaticlabs/go-ssz"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
@@ -79,16 +78,9 @@ func MatchAttestations(state *pb.BeaconState, epoch uint64) (*MatchedAttestation
if bytes.Equal(srcAtt.Data.Target.Root, targetRoot) {
tgtAtts = append(tgtAtts, srcAtt)
}
// If the block root at slot matches attestation's block root at slot,
// then we know this attestation has correctly voted for head.
slot, err := helpers.AttestationDataSlot(state, srcAtt.Data)
headRoot, err := helpers.BlockRootAtSlot(state, srcAtt.Data.Slot)
if err != nil {
return nil, errors.Wrap(err, "could not get attestation slot")
}
headRoot, err := helpers.BlockRootAtSlot(state, slot)
if err != nil {
return nil, errors.Wrapf(err, "could not get block root for slot %d", slot)
return nil, errors.Wrapf(err, "could not get block root for slot %d", srcAtt.Data.Slot)
}
if bytes.Equal(srcAtt.Data.BeaconBlockRoot, headRoot) {
headAtts = append(headAtts, srcAtt)
@@ -229,54 +221,6 @@ func ProcessJustificationAndFinalization(state *pb.BeaconState, prevAttestedBal
return state, nil
}
// ProcessCrosslinks processes crosslink and finds the crosslink
// with enough state to make it canonical in state.
//
// Spec pseudocode definition:
// def process_crosslinks(state: BeaconState) -> None:
// state.previous_crosslinks = [c for c in state.current_crosslinks]
// for epoch in (get_previous_epoch(state), get_current_epoch(state)):
// for offset in range(get_epoch_committee_count(state, epoch)):
// shard = (get_epoch_start_shard(state, epoch) + offset) % SHARD_COUNT
// crosslink_committee = get_crosslink_committee(state, epoch, shard)
// winning_crosslink, attesting_indices = get_winning_crosslink_and_attesting_indices(state, epoch, shard)
// if 3 * get_total_balance(state, attesting_indices) >= 2 * get_total_balance(state, crosslink_committee):
// state.current_crosslinks[shard] = winning_crosslink
func ProcessCrosslinks(state *pb.BeaconState) (*pb.BeaconState, error) {
copy(state.PreviousCrosslinks, state.CurrentCrosslinks)
epochs := []uint64{helpers.PrevEpoch(state), helpers.CurrentEpoch(state)}
for _, e := range epochs {
count, err := helpers.CommitteeCount(state, e)
if err != nil {
return nil, errors.Wrap(err, "could not get epoch committee count")
}
startShard, err := helpers.StartShard(state, e)
if err != nil {
return nil, errors.Wrap(err, "could not get epoch start shards")
}
for offset := uint64(0); offset < count; offset++ {
shard := (startShard + offset) % params.BeaconConfig().ShardCount
committee, err := helpers.CrosslinkCommittee(state, e, shard)
if err != nil {
return nil, errors.Wrap(err, "could not get crosslink committee")
}
crosslink, indices, err := WinningCrosslink(state, shard, e)
if err != nil {
return nil, errors.Wrap(err, "could not get winning crosslink")
}
attestedBalance := helpers.TotalBalance(state, indices)
totalBalance := helpers.TotalBalance(state, committee)
// In order for a crosslink to get included in state, the attesting balance needs to
// be greater than 2/3 of the total balance.
if 3*attestedBalance >= 2*totalBalance {
state.CurrentCrosslinks[shard] = crosslink
}
}
}
return state, nil
}
// ProcessRewardsAndPenalties processes the rewards and penalties of individual validator.
//
// Spec pseudocode definition:
@@ -298,14 +242,10 @@ func ProcessRewardsAndPenalties(state *pb.BeaconState) (*pb.BeaconState, error)
if err != nil {
return nil, errors.Wrap(err, "could not get attestation delta")
}
clRewards, clPenalties, err := crosslinkDelta(state)
if err != nil {
return nil, errors.Wrapf(err, "could not get crosslink delta")
}
for i := 0; i < len(state.Validators); i++ {
state = helpers.IncreaseBalance(state, uint64(i), attsRewards[i]+clRewards[i])
state = helpers.DecreaseBalance(state, uint64(i), attsPenalties[i]+clPenalties[i])
state = helpers.IncreaseBalance(state, uint64(i), attsRewards[i])
state = helpers.DecreaseBalance(state, uint64(i), attsPenalties[i])
}
return state, nil
}
@@ -490,30 +430,6 @@ func ProcessFinalUpdates(state *pb.BeaconState) (*pb.BeaconState, error) {
}
}
// Set active index root.
// index_epoch = Epoch(next_epoch + ACTIVATION_EXIT_DELAY)
// index_root_position = index_epoch % EPOCHS_PER_HISTORICAL_VECTOR
// indices_list = List[ValidatorIndex, VALIDATOR_REGISTRY_LIMIT](get_active_validator_indices(state, index_epoch))
// state.active_index_roots[index_root_position] = hash_tree_root(indices_list)
activationDelay := params.BeaconConfig().ActivationExitDelay
idxRootPosition := (nextEpoch + activationDelay) % params.BeaconConfig().EpochsPerHistoricalVector
activeIndices, err := helpers.ActiveValidatorIndices(state, nextEpoch+activationDelay)
if err != nil {
return nil, errors.Wrap(err, "could not get active indices")
}
idxRoot, err := ssz.HashTreeRootWithCapacity(activeIndices, uint64(1099511627776))
if err != nil {
return nil, errors.Wrap(err, "could not tree hash active indices")
}
state.ActiveIndexRoots[idxRootPosition] = idxRoot[:]
commRootPosition := nextEpoch % params.BeaconConfig().EpochsPerHistoricalVector
comRoot, err := helpers.CompactCommitteesRoot(state, nextEpoch)
if err != nil {
return nil, errors.Wrap(err, "could not get compact committee root")
}
state.CompactCommitteesRoots[commRootPosition] = comRoot[:]
// Set total slashed balances.
slashedExitLength := params.BeaconConfig().EpochsPerSlashingsVector
state.Slashings[nextEpoch%slashedExitLength] = 0
@@ -537,13 +453,6 @@ func ProcessFinalUpdates(state *pb.BeaconState) (*pb.BeaconState, error) {
state.HistoricalRoots = append(state.HistoricalRoots, batchRoot[:])
}
// Update start shard.
delta, err := helpers.ShardDelta(state, currentEpoch)
if err != nil {
return nil, errors.Wrap(err, "could not get shard delta")
}
state.StartShard = (state.StartShard + delta) % params.BeaconConfig().ShardCount
// Rotate current and previous epoch attestations.
state.PreviousEpochAttestations = state.CurrentEpochAttestations
state.CurrentEpochAttestations = []*pb.PendingAttestation{}
@@ -591,93 +500,6 @@ func unslashedAttestingIndices(state *pb.BeaconState, atts []*pb.PendingAttestat
return setIndices, nil
}
// WinningCrosslink returns the most staked balance-wise crosslink of a given shard and epoch.
// It also returns the attesting inaidces of the winning cross link.
//
// Spec pseudocode definition:
// def get_winning_crosslink_and_attesting_indices(state: BeaconState,
// epoch: Epoch,
// shard: Shard) -> Tuple[Crosslink, List[ValidatorIndex]]:
// attestations = [a for a in get_matching_source_attestations(state, epoch) if a.data.crosslink.shard == shard]
// crosslinks = list(filter(
// lambda c: hash_tree_root(state.current_crosslinks[shard]) in (c.parent_root, hash_tree_root(c)),
// [a.data.crosslink for a in attestations]
// ))
// # Winning crosslink has the crosslink data root with the most balance voting for it (ties broken lexicographically)
// winning_crosslink = max(crosslinks, key=lambda c: (
// get_attesting_balance(state, [a for a in attestations if a.data.crosslink == c]), c.data_root
// ), default=Crosslink())
// winning_attestations = [a for a in attestations if a.data.crosslink == winning_crosslink]
// return winning_crosslink, get_unslashed_attesting_indices(state, winning_attestations)
func WinningCrosslink(state *pb.BeaconState, shard uint64, epoch uint64) (*ethpb.Crosslink, []uint64, error) {
var shardAtts []*pb.PendingAttestation
matchedAtts, err := MatchAttestations(state, epoch)
if err != nil {
return nil, nil, errors.Wrap(err, "could not get matching attestations")
}
// Filter out source attestations by shard.
for _, att := range matchedAtts.source {
if att.Data.Crosslink.Shard == shard {
shardAtts = append(shardAtts, att)
}
}
var candidateCrosslinks []*ethpb.Crosslink
// Filter out shard crosslinks with correct current or previous crosslink data.
for _, a := range shardAtts {
stateCrosslink := state.CurrentCrosslinks[shard]
stateCrosslinkRoot, err := ssz.HashTreeRoot(stateCrosslink)
if err != nil {
return nil, nil, errors.Wrap(err, "could not hash tree root crosslink from state")
}
attCrosslinkRoot, err := ssz.HashTreeRoot(a.Data.Crosslink)
if err != nil {
return nil, nil, errors.Wrap(err, "could not hash tree root crosslink from attestation")
}
currCrosslinkMatches := bytes.Equal(stateCrosslinkRoot[:], attCrosslinkRoot[:])
prevCrosslinkMatches := bytes.Equal(stateCrosslinkRoot[:], a.Data.Crosslink.ParentRoot)
if currCrosslinkMatches || prevCrosslinkMatches {
candidateCrosslinks = append(candidateCrosslinks, a.Data.Crosslink)
}
}
if len(candidateCrosslinks) == 0 {
return &ethpb.Crosslink{
DataRoot: params.BeaconConfig().ZeroHash[:],
ParentRoot: params.BeaconConfig().ZeroHash[:],
}, nil, nil
}
var crosslinkAtts []*pb.PendingAttestation
var winnerBalance uint64
var winnerCrosslink *ethpb.Crosslink
// Out of the existing shard crosslinks, pick the one that has the
// most balance staked.
crosslinkAtts = attsForCrosslink(candidateCrosslinks[0], shardAtts)
winnerBalance, err = AttestingBalance(state, crosslinkAtts)
if err != nil {
return nil, nil, err
}
winnerCrosslink = candidateCrosslinks[0]
for _, c := range candidateCrosslinks {
crosslinkAtts = attsForCrosslink(c, shardAtts)
attestingBalance, err := AttestingBalance(state, crosslinkAtts)
if err != nil {
return nil, nil, errors.Wrap(err, "could not get crosslink's attesting balance")
}
if attestingBalance > winnerBalance {
winnerCrosslink = c
}
}
crosslinkIndices, err := unslashedAttestingIndices(state, attsForCrosslink(winnerCrosslink, shardAtts))
if err != nil {
return nil, nil, errors.New("could not get crosslink indices")
}
return winnerCrosslink, crosslinkIndices, nil
}
// BaseReward takes state and validator index and calculate
// individual validator's base reward quotient.
//
@@ -742,11 +564,7 @@ func BaseReward(state *pb.BeaconState, index uint64) (uint64, error) {
// proposer_reward = Gwei(get_base_reward(state, index) // PROPOSER_REWARD_QUOTIENT)
// rewards[attestation.proposer_index] += proposer_reward
// max_attester_reward = get_base_reward(state, index) - proposer_reward
// rewards[index] += Gwei(
// max_attester_reward
// * (SLOTS_PER_EPOCH + MIN_ATTESTATION_INCLUSION_DELAY - attestation.inclusion_delay)
// // SLOTS_PER_EPOCH
// )
// rewards[index] += Gwei(max_attester_reward // attestation.inclusion_delay)
//
// # Inactivity penalty
// finality_delay = previous_epoch - state.finalized_checkpoint.epoch
@@ -845,8 +663,6 @@ func attestationDelta(state *pb.BeaconState) ([]uint64, []uint64, error) {
}
for i, a := range attestersVotedSource {
slotsPerEpoch := params.BeaconConfig().SlotsPerEpoch
baseReward, err := BaseReward(state, i)
if err != nil {
return nil, nil, errors.Wrap(err, "could not get proposer reward")
@@ -854,7 +670,7 @@ func attestationDelta(state *pb.BeaconState) ([]uint64, []uint64, error) {
proposerReward := baseReward / params.BeaconConfig().ProposerRewardQuotient
rewards[a.ProposerIndex] += proposerReward
attesterReward := baseReward - proposerReward
rewards[i] += attesterReward * (slotsPerEpoch + params.BeaconConfig().MinAttestationInclusionDelay - a.InclusionDelay) / slotsPerEpoch
rewards[i] += attesterReward / a.InclusionDelay
}
// Apply penalties for quadratic leaks.
@@ -882,88 +698,6 @@ func attestationDelta(state *pb.BeaconState) ([]uint64, []uint64, error) {
}
}
}
return rewards, penalties, nil
}
// crosslinkDelta calculates the rewards and penalties of individual
// validator for submitting the correct crosslink.
// Individual rewards and penalties are returned in list.
//
// Note: we calculated adjusted quotient outside of base reward because it's too inefficient
// to repeat the same calculation for every validator versus just doing it once.
//
// Spec pseudocode definition:
// def get_crosslink_deltas(state: BeaconState) -> Tuple[List[Gwei], List[Gwei]]:
// rewards = [0 for index in range(len(state.validator_registry))]
// penalties = [0 for index in range(len(state.validator_registry))]
// epoch = get_previous_epoch(state)
// for offset in range(get_epoch_committee_count(state, epoch)):
// shard = (get_epoch_start_shard(state, epoch) + offset) % SHARD_COUNT
// crosslink_committee = get_crosslink_committee(state, epoch, shard)
// winning_crosslink, attesting_indices = get_winning_crosslink_and_attesting_indices(state, epoch, shard)
// attesting_balance = get_total_balance(state, attesting_indices)
// committee_balance = get_total_balance(state, crosslink_committee)
// for index in crosslink_committee:
// base_reward = get_base_reward(state, index)
// if index in attesting_indices:
// rewards[index] += base_reward * attesting_balance // committee_balance
// else:
// penalties[index] += base_reward
// return rewards, penalties
func crosslinkDelta(state *pb.BeaconState) ([]uint64, []uint64, error) {
rewards := make([]uint64, len(state.Validators))
penalties := make([]uint64, len(state.Validators))
epoch := helpers.PrevEpoch(state)
count, err := helpers.CommitteeCount(state, epoch)
if err != nil {
return nil, nil, errors.Wrap(err, "could not get epoch committee count")
}
startShard, err := helpers.StartShard(state, epoch)
if err != nil {
return nil, nil, errors.Wrap(err, "could not get epoch start shard")
}
for i := uint64(0); i < count; i++ {
shard := (startShard + i) % params.BeaconConfig().ShardCount
committee, err := helpers.CrosslinkCommittee(state, epoch, shard)
if err != nil {
return nil, nil, errors.Wrap(err, "could not get crosslink's committee")
}
_, attestingIndices, err := WinningCrosslink(state, shard, epoch)
if err != nil {
return nil, nil, errors.Wrap(err, "could not get winning crosslink")
}
attested := make(map[uint64]bool)
// Construct a map to look up validators that voted for crosslink.
for _, index := range attestingIndices {
attested[index] = true
}
committeeBalance := helpers.TotalBalance(state, committee)
attestingBalance := helpers.TotalBalance(state, attestingIndices)
for _, index := range committee {
base, err := BaseReward(state, index)
if err != nil {
return nil, nil, errors.Wrap(err, "could not get base reward")
}
if _, ok := attested[index]; ok {
rewards[index] += base * attestingBalance / committeeBalance
} else {
penalties[index] += base
}
}
}
return rewards, penalties, nil
}
// attsForCrosslink returns the attestations of the input crosslink.
func attsForCrosslink(crosslink *ethpb.Crosslink, atts []*pb.PendingAttestation) []*pb.PendingAttestation {
var crosslinkAtts []*pb.PendingAttestation
for _, a := range atts {
if proto.Equal(a.Data.Crosslink, crosslink) {
crosslinkAtts = append(crosslinkAtts, a)
}
}
return crosslinkAtts
}

View File

@@ -2,7 +2,6 @@ package epoch
import (
"bytes"
"fmt"
"reflect"
"strings"
"testing"
@@ -16,8 +15,6 @@ import (
)
func init() {
helpers.ClearShuffledValidatorCache()
// TODO(2312): remove this and use the mainnet count.
c := params.BeaconConfig()
c.MinGenesisActiveValidatorCount = 16384
@@ -31,9 +28,6 @@ func TestUnslashedAttestingIndices_CanSortAndFilter(t *testing.T) {
atts[i] = &pb.PendingAttestation{
Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{},
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{
Shard: uint64(i),
},
},
AggregationBits: bitfield.Bitlist{0xFF, 0xFF, 0xFF},
}
@@ -48,9 +42,8 @@ func TestUnslashedAttestingIndices_CanSortAndFilter(t *testing.T) {
}
}
state := &pb.BeaconState{
Validators: validators,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
Validators: validators,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
}
indices, err := unslashedAttestingIndices(state, atts)
@@ -83,9 +76,7 @@ func TestUnslashedAttestingIndices_DuplicatedAttestations(t *testing.T) {
for i := 0; i < len(atts); i++ {
atts[i] = &pb.PendingAttestation{
Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{},
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{},
},
Target: &ethpb.Checkpoint{Epoch: 0}},
AggregationBits: bitfield.Bitlist{0xFF, 0xFF, 0xFF},
}
}
@@ -99,9 +90,8 @@ func TestUnslashedAttestingIndices_DuplicatedAttestations(t *testing.T) {
}
}
state := &pb.BeaconState{
Validators: validators,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
Validators: validators,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
}
indices, err := unslashedAttestingIndices(state, atts)
@@ -124,11 +114,9 @@ func TestAttestingBalance_CorrectBalance(t *testing.T) {
for i := 0; i < len(atts); i++ {
atts[i] = &pb.PendingAttestation{
Data: &ethpb.AttestationData{
Crosslink: &ethpb.Crosslink{
Shard: uint64(i),
},
Target: &ethpb.Checkpoint{},
Source: &ethpb.Checkpoint{},
Slot: uint64(i),
},
AggregationBits: bitfield.Bitlist{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01},
@@ -146,11 +134,11 @@ func TestAttestingBalance_CorrectBalance(t *testing.T) {
balances[i] = params.BeaconConfig().MaxEffectiveBalance
}
state := &pb.BeaconState{
Slot: 0,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
Validators: validators,
Balances: balances,
Slot: 2,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
Validators: validators,
Balances: balances,
}
balance, err := AttestingBalance(state, atts)
@@ -172,20 +160,20 @@ func TestMatchAttestations_PrevEpoch(t *testing.T) {
// The correct vote for target is '1'
// The correct vote for head is '2'
prevAtts := []*pb.PendingAttestation{
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, Target: &ethpb.Checkpoint{}}}, // source
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, Target: &ethpb.Checkpoint{Root: []byte{1}}}}, // source, target
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, Target: &ethpb.Checkpoint{Root: []byte{3}}}}, // source
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, Target: &ethpb.Checkpoint{Root: []byte{1}}}}, // source, target
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{66}, Target: &ethpb.Checkpoint{}}}, // source, head
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{4}, Target: &ethpb.Checkpoint{}}}, // source
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{66}, Target: &ethpb.Checkpoint{Root: []byte{1}}}}, // source, target, head
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{5}, Target: &ethpb.Checkpoint{Root: []byte{1}}}}, // source, target
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{66}, Target: &ethpb.Checkpoint{Root: []byte{6}}}}, // source, head
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Target: &ethpb.Checkpoint{}}}, // source
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Target: &ethpb.Checkpoint{Root: []byte{1}}}}, // source, target
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Target: &ethpb.Checkpoint{Root: []byte{3}}}}, // source
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Target: &ethpb.Checkpoint{Root: []byte{1}}}}, // source, target
{Data: &ethpb.AttestationData{Slot: 33, Source: &ethpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: &ethpb.Checkpoint{}}}, // source, head
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, BeaconBlockRoot: []byte{4}, Target: &ethpb.Checkpoint{}}}, // source
{Data: &ethpb.AttestationData{Slot: 33, Source: &ethpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: &ethpb.Checkpoint{Root: []byte{1}}}}, // source, target, head
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, BeaconBlockRoot: []byte{5}, Target: &ethpb.Checkpoint{Root: []byte{1}}}}, // source, target
{Data: &ethpb.AttestationData{Slot: 33, Source: &ethpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: &ethpb.Checkpoint{Root: []byte{6}}}}, // source, head
}
currentAtts := []*pb.PendingAttestation{
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + e + 1}, Target: &ethpb.Checkpoint{}}}, // none
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + e + 1}, BeaconBlockRoot: []byte{2}, Target: &ethpb.Checkpoint{Root: []byte{1}}}}, // none
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Target: &ethpb.Checkpoint{}}}, // none
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, BeaconBlockRoot: []byte{2}, Target: &ethpb.Checkpoint{Root: []byte{1}}}}, // none
}
blockRoots := make([][]byte, 128)
@@ -198,7 +186,6 @@ func TestMatchAttestations_PrevEpoch(t *testing.T) {
PreviousEpochAttestations: prevAtts,
BlockRoots: blockRoots,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
}
mAtts, err := MatchAttestations(state, 0)
@@ -207,35 +194,36 @@ func TestMatchAttestations_PrevEpoch(t *testing.T) {
}
wantedSrcAtts := []*pb.PendingAttestation{
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, Target: &ethpb.Checkpoint{}}},
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, Target: &ethpb.Checkpoint{Root: []byte{1}}}},
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, Target: &ethpb.Checkpoint{Root: []byte{3}}}},
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, Target: &ethpb.Checkpoint{Root: []byte{1}}}},
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{66}, Target: &ethpb.Checkpoint{}}},
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{4}, Target: &ethpb.Checkpoint{}}},
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{66}, Target: &ethpb.Checkpoint{Root: []byte{1}}}},
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{5}, Target: &ethpb.Checkpoint{Root: []byte{1}}}},
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{66}, Target: &ethpb.Checkpoint{Root: []byte{6}}}},
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Target: &ethpb.Checkpoint{}}},
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Target: &ethpb.Checkpoint{Root: []byte{1}}}},
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Target: &ethpb.Checkpoint{Root: []byte{3}}}},
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Target: &ethpb.Checkpoint{Root: []byte{1}}}},
{Data: &ethpb.AttestationData{Slot: 33, Source: &ethpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: &ethpb.Checkpoint{}}},
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, BeaconBlockRoot: []byte{4}, Target: &ethpb.Checkpoint{}}},
{Data: &ethpb.AttestationData{Slot: 33, Source: &ethpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: &ethpb.Checkpoint{Root: []byte{1}}}},
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, BeaconBlockRoot: []byte{5}, Target: &ethpb.Checkpoint{Root: []byte{1}}}},
{Data: &ethpb.AttestationData{Slot: 33, Source: &ethpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: &ethpb.Checkpoint{Root: []byte{6}}}},
}
if !reflect.DeepEqual(mAtts.source, wantedSrcAtts) {
t.Error("source attestations don't match")
}
wantedTgtAtts := []*pb.PendingAttestation{
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, Target: &ethpb.Checkpoint{Root: []byte{1}}}},
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, Target: &ethpb.Checkpoint{Root: []byte{1}}}},
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{66}, Target: &ethpb.Checkpoint{Root: []byte{1}}}},
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{5}, Target: &ethpb.Checkpoint{Root: []byte{1}}}},
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Target: &ethpb.Checkpoint{Root: []byte{1}}}},
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Target: &ethpb.Checkpoint{Root: []byte{1}}}},
{Data: &ethpb.AttestationData{Slot: 33, Source: &ethpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: &ethpb.Checkpoint{Root: []byte{1}}}},
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, BeaconBlockRoot: []byte{5}, Target: &ethpb.Checkpoint{Root: []byte{1}}}},
}
if !reflect.DeepEqual(mAtts.Target, wantedTgtAtts) {
t.Error("target attestations don't match")
}
wantedHeadAtts := []*pb.PendingAttestation{
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{66}, Target: &ethpb.Checkpoint{}}},
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{66}, Target: &ethpb.Checkpoint{Root: []byte{1}}}},
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{66}, Target: &ethpb.Checkpoint{Root: []byte{6}}}},
{Data: &ethpb.AttestationData{Slot: 33, Source: &ethpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: &ethpb.Checkpoint{}}},
{Data: &ethpb.AttestationData{Slot: 33, Source: &ethpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: &ethpb.Checkpoint{Root: []byte{1}}}},
{Data: &ethpb.AttestationData{Slot: 33, Source: &ethpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: &ethpb.Checkpoint{Root: []byte{6}}}},
}
if !reflect.DeepEqual(mAtts.head, wantedHeadAtts) {
t.Error("head attestations don't match")
}
@@ -247,20 +235,20 @@ func TestMatchAttestations_CurrentEpoch(t *testing.T) {
s := uint64(0) // slot
// The correct epoch for source is the first epoch
// The correct vote for target is '65'
// The correct vote for head is '66'
// The correct vote for target is '33'
// The correct vote for head is '34'
prevAtts := []*pb.PendingAttestation{
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, Target: &ethpb.Checkpoint{}}}, // none
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{2}, Target: &ethpb.Checkpoint{Root: []byte{1}}}}, // none
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{5}, Target: &ethpb.Checkpoint{Root: []byte{1}}}}, // none
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{2}, Target: &ethpb.Checkpoint{Root: []byte{6}}}}, // none
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Target: &ethpb.Checkpoint{}}}, // none
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, BeaconBlockRoot: []byte{2}, Target: &ethpb.Checkpoint{Root: []byte{1}}}}, // none
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, BeaconBlockRoot: []byte{5}, Target: &ethpb.Checkpoint{Root: []byte{1}}}}, // none
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, BeaconBlockRoot: []byte{2}, Target: &ethpb.Checkpoint{Root: []byte{6}}}}, // none
}
currentAtts := []*pb.PendingAttestation{
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, Target: &ethpb.Checkpoint{}}}, // source
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{66}, Target: &ethpb.Checkpoint{Root: []byte{65}}}}, // source, target, head
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{69}, Target: &ethpb.Checkpoint{Root: []byte{65}}}}, // source, target
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{66}, Target: &ethpb.Checkpoint{Root: []byte{68}}}}, // source, head
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Target: &ethpb.Checkpoint{}}}, // source
{Data: &ethpb.AttestationData{Slot: 33, Source: &ethpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: &ethpb.Checkpoint{Root: []byte{33}}}}, // source, target, head
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, BeaconBlockRoot: []byte{69}, Target: &ethpb.Checkpoint{Root: []byte{33}}}}, // source, target
{Data: &ethpb.AttestationData{Slot: 33, Source: &ethpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: &ethpb.Checkpoint{Root: []byte{68}}}}, // source, head
}
blockRoots := make([][]byte, 128)
@@ -280,26 +268,26 @@ func TestMatchAttestations_CurrentEpoch(t *testing.T) {
}
wantedSrcAtts := []*pb.PendingAttestation{
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, Target: &ethpb.Checkpoint{}}},
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{66}, Target: &ethpb.Checkpoint{Root: []byte{65}}}},
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{69}, Target: &ethpb.Checkpoint{Root: []byte{65}}}},
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{66}, Target: &ethpb.Checkpoint{Root: []byte{68}}}},
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Target: &ethpb.Checkpoint{}}},
{Data: &ethpb.AttestationData{Slot: 33, Source: &ethpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: &ethpb.Checkpoint{Root: []byte{33}}}},
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, BeaconBlockRoot: []byte{69}, Target: &ethpb.Checkpoint{Root: []byte{33}}}},
{Data: &ethpb.AttestationData{Slot: 33, Source: &ethpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: &ethpb.Checkpoint{Root: []byte{68}}}},
}
if !reflect.DeepEqual(mAtts.source, wantedSrcAtts) {
t.Error("source attestations don't match")
}
wantedTgtAtts := []*pb.PendingAttestation{
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{66}, Target: &ethpb.Checkpoint{Root: []byte{65}}}},
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{69}, Target: &ethpb.Checkpoint{Root: []byte{65}}}},
{Data: &ethpb.AttestationData{Slot: 33, Source: &ethpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: &ethpb.Checkpoint{Root: []byte{33}}}},
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, BeaconBlockRoot: []byte{69}, Target: &ethpb.Checkpoint{Root: []byte{33}}}},
}
if !reflect.DeepEqual(mAtts.Target, wantedTgtAtts) {
t.Error("target attestations don't match")
}
wantedHeadAtts := []*pb.PendingAttestation{
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{66}, Target: &ethpb.Checkpoint{Root: []byte{65}}}},
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{66}, Target: &ethpb.Checkpoint{Root: []byte{68}}}},
{Data: &ethpb.AttestationData{Slot: 33, Source: &ethpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: &ethpb.Checkpoint{Root: []byte{33}}}},
{Data: &ethpb.AttestationData{Slot: 33, Source: &ethpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: &ethpb.Checkpoint{Root: []byte{68}}}},
}
if !reflect.DeepEqual(mAtts.head, wantedHeadAtts) {
t.Error("head attestations don't match")
@@ -313,245 +301,6 @@ func TestMatchAttestations_EpochOutOfBound(t *testing.T) {
}
}
func TestAttsForCrosslink_CanGetAttestations(t *testing.T) {
c := &ethpb.Crosslink{
DataRoot: []byte{'B'},
}
atts := []*pb.PendingAttestation{
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{DataRoot: []byte{'A'}}, Target: &ethpb.Checkpoint{}}},
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{DataRoot: []byte{'B'}}, Target: &ethpb.Checkpoint{}}}, // Selected
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{DataRoot: []byte{'C'}}, Target: &ethpb.Checkpoint{}}},
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{DataRoot: []byte{'B'}}, Target: &ethpb.Checkpoint{}}}} // Selected
if !reflect.DeepEqual(attsForCrosslink(c, atts), []*pb.PendingAttestation{
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{DataRoot: []byte{'B'}}, Target: &ethpb.Checkpoint{}}},
{Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{}, Crosslink: &ethpb.Crosslink{DataRoot: []byte{'B'}}, Target: &ethpb.Checkpoint{}}}}) {
t.Error("Incorrect attestations for crosslink")
}
}
func TestWinningCrosslink_CantGetMatchingAtts(t *testing.T) {
wanted := fmt.Sprintf("could not get matching attestations: input epoch: %d != current epoch: %d or previous epoch: %d",
100, 0, 0)
_, _, err := WinningCrosslink(&pb.BeaconState{Slot: 0}, 0, 100)
if err.Error() != wanted {
t.Fatal(err)
}
}
func TestWinningCrosslink_ReturnGenesisCrosslink(t *testing.T) {
e := params.BeaconConfig().SlotsPerEpoch
gs := uint64(0) // genesis slot
ge := uint64(0) // genesis epoch
state := &pb.BeaconState{
Slot: gs + e + 2,
PreviousEpochAttestations: []*pb.PendingAttestation{},
BlockRoots: make([][]byte, 128),
CurrentCrosslinks: []*ethpb.Crosslink{{StartEpoch: ge}},
}
gCrosslink := &ethpb.Crosslink{
StartEpoch: 0,
DataRoot: params.BeaconConfig().ZeroHash[:],
ParentRoot: params.BeaconConfig().ZeroHash[:],
}
crosslink, indices, err := WinningCrosslink(state, 0, ge)
if err != nil {
t.Fatal(err)
}
if len(indices) != 0 {
t.Errorf("genesis crosslink indices is not 0, got: %d", len(indices))
}
if !reflect.DeepEqual(crosslink, gCrosslink) {
t.Errorf("Did not get genesis crosslink, got: %v", crosslink)
}
}
func TestWinningCrosslink_CanGetWinningRoot(t *testing.T) {
helpers.ClearAllCaches()
e := params.BeaconConfig().SlotsPerEpoch
gs := uint64(0) // genesis slot
ge := uint64(0) // genesis epoch
atts := []*pb.PendingAttestation{
{
Data: &ethpb.AttestationData{
Crosslink: &ethpb.Crosslink{
Shard: 1,
DataRoot: []byte{'A'},
},
Target: &ethpb.Checkpoint{},
Source: &ethpb.Checkpoint{},
},
},
{
Data: &ethpb.AttestationData{
Crosslink: &ethpb.Crosslink{
Shard: 1,
DataRoot: []byte{'B'}, // Winner
},
Target: &ethpb.Checkpoint{},
Source: &ethpb.Checkpoint{},
},
},
{
Data: &ethpb.AttestationData{
Crosslink: &ethpb.Crosslink{
Shard: 1,
DataRoot: []byte{'C'},
},
Target: &ethpb.Checkpoint{},
Source: &ethpb.Checkpoint{},
},
},
}
blockRoots := make([][]byte, 128)
for i := 0; i < len(blockRoots); i++ {
blockRoots[i] = []byte{byte(i + 1)}
}
crosslinks := make([]*ethpb.Crosslink, params.BeaconConfig().ShardCount)
for i := uint64(0); i < params.BeaconConfig().ShardCount; i++ {
crosslinks[i] = &ethpb.Crosslink{
StartEpoch: ge,
Shard: 1,
DataRoot: []byte{'B'},
}
}
state := &pb.BeaconState{
Slot: gs + e + 2,
PreviousEpochAttestations: atts,
BlockRoots: blockRoots,
CurrentCrosslinks: crosslinks,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
}
winner, indices, err := WinningCrosslink(state, 1, ge)
if err != nil {
t.Fatal(err)
}
if len(indices) != 0 {
t.Errorf("genesis crosslink indices is not 0, got: %d", len(indices))
}
want := &ethpb.Crosslink{StartEpoch: ge, Shard: 1, DataRoot: []byte{'B'}}
if !reflect.DeepEqual(winner, want) {
t.Errorf("Did not get wanted crosslink, got: %v, want %v", winner, want)
}
}
func TestProcessCrosslinks_NoUpdate(t *testing.T) {
helpers.ClearAllCaches()
validatorCount := 128
validators := make([]*ethpb.Validator, validatorCount)
balances := make([]uint64, validatorCount)
for i := 0; i < len(validators); i++ {
validators[i] = &ethpb.Validator{
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
}
balances[i] = params.BeaconConfig().MaxEffectiveBalance
}
blockRoots := make([][]byte, 128)
for i := 0; i < len(blockRoots); i++ {
blockRoots[i] = []byte{byte(i + 1)}
}
var crosslinks []*ethpb.Crosslink
for i := uint64(0); i < params.BeaconConfig().ShardCount; i++ {
crosslinks = append(crosslinks, &ethpb.Crosslink{
StartEpoch: 0,
DataRoot: []byte{'A'},
})
}
state := &pb.BeaconState{
Slot: params.BeaconConfig().SlotsPerEpoch + 1,
Validators: validators,
Balances: balances,
BlockRoots: blockRoots,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
CurrentCrosslinks: crosslinks,
}
newState, err := ProcessCrosslinks(state)
if err != nil {
t.Fatal(err)
}
wanted := &ethpb.Crosslink{
StartEpoch: 0,
DataRoot: []byte{'A'},
}
// Since there has been no attestation, crosslink stayed the same.
if !reflect.DeepEqual(wanted, newState.CurrentCrosslinks[0]) {
t.Errorf("Did not get correct crosslink back")
}
}
func TestProcessCrosslinks_SuccessfulUpdate(t *testing.T) {
e := params.BeaconConfig().SlotsPerEpoch
gs := uint64(0) // genesis slot
ge := uint64(0) // genesis epoch
validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount/8)
balances := make([]uint64, params.BeaconConfig().MinGenesisActiveValidatorCount/8)
for i := 0; i < len(validators); i++ {
validators[i] = &ethpb.Validator{
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
}
balances[i] = params.BeaconConfig().MaxEffectiveBalance
}
blockRoots := make([][]byte, 128)
for i := 0; i < len(blockRoots); i++ {
blockRoots[i] = []byte{byte(i + 1)}
}
crosslinks := make([]*ethpb.Crosslink, params.BeaconConfig().ShardCount)
for i := uint64(0); i < params.BeaconConfig().ShardCount; i++ {
crosslinks[i] = &ethpb.Crosslink{
StartEpoch: ge,
DataRoot: []byte{'B'},
}
}
var atts []*pb.PendingAttestation
startShard := uint64(960)
for s := uint64(0); s < params.BeaconConfig().SlotsPerEpoch; s++ {
atts = append(atts, &pb.PendingAttestation{
Data: &ethpb.AttestationData{Source: &ethpb.Checkpoint{},
Crosslink: &ethpb.Crosslink{
Shard: startShard + s,
DataRoot: []byte{'B'},
},
Target: &ethpb.Checkpoint{Epoch: 0},
},
AggregationBits: bitfield.Bitlist{0xC0, 0xC0, 0xC0, 0xC0, 0x01},
})
}
state := &pb.BeaconState{
Slot: gs + e + 2,
Validators: validators,
PreviousEpochAttestations: atts,
Balances: balances,
BlockRoots: blockRoots,
CurrentCrosslinks: crosslinks,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
}
newState, err := ProcessCrosslinks(state)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(crosslinks[0], newState.CurrentCrosslinks[0]) {
t.Errorf("Crosslink is not the same")
}
}
func TestBaseReward_AccurateRewards(t *testing.T) {
helpers.ClearAllCaches()
@@ -560,10 +309,10 @@ func TestBaseReward_AccurateRewards(t *testing.T) {
b uint64
c uint64
}{
{params.BeaconConfig().MinDepositAmount, params.BeaconConfig().MinDepositAmount, 404781},
{30 * 1e9, 30 * 1e9, 2217026},
{params.BeaconConfig().MaxEffectiveBalance, params.BeaconConfig().MaxEffectiveBalance, 2289739},
{40 * 1e9, params.BeaconConfig().MaxEffectiveBalance, 2289739},
{params.BeaconConfig().MinDepositAmount, params.BeaconConfig().MinDepositAmount, 505976},
{30 * 1e9, 30 * 1e9, 2771282},
{params.BeaconConfig().MaxEffectiveBalance, params.BeaconConfig().MaxEffectiveBalance, 2862174},
{40 * 1e9, params.BeaconConfig().MaxEffectiveBalance, 2862174},
}
for _, tt := range tests {
helpers.ClearAllCaches()
@@ -669,9 +418,9 @@ func TestProcessJustificationAndFinalization_ConsecutiveEpochs(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(newState.CurrentJustifiedCheckpoint.Root, []byte{byte(128)}) {
if !bytes.Equal(newState.CurrentJustifiedCheckpoint.Root, []byte{byte(64)}) {
t.Errorf("Wanted current justified root: %v, got: %v",
[]byte{byte(128)}, newState.CurrentJustifiedCheckpoint.Root)
[]byte{byte(64)}, newState.CurrentJustifiedCheckpoint.Root)
}
if newState.CurrentJustifiedCheckpoint.Epoch != 2 {
t.Errorf("Wanted justified epoch: %d, got: %d",
@@ -718,9 +467,9 @@ func TestProcessJustificationAndFinalization_JustifyCurrentEpoch(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(newState.CurrentJustifiedCheckpoint.Root, []byte{byte(128)}) {
if !bytes.Equal(newState.CurrentJustifiedCheckpoint.Root, []byte{byte(64)}) {
t.Errorf("Wanted current justified root: %v, got: %v",
[]byte{byte(128)}, newState.CurrentJustifiedCheckpoint.Root)
[]byte{byte(64)}, newState.CurrentJustifiedCheckpoint.Root)
}
if newState.CurrentJustifiedCheckpoint.Epoch != 2 {
t.Errorf("Wanted justified epoch: %d, got: %d",
@@ -767,9 +516,9 @@ func TestProcessJustificationAndFinalization_JustifyPrevEpoch(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(newState.CurrentJustifiedCheckpoint.Root, []byte{byte(128)}) {
if !bytes.Equal(newState.CurrentJustifiedCheckpoint.Root, []byte{byte(64)}) {
t.Errorf("Wanted current justified root: %v, got: %v",
[]byte{byte(128)}, newState.CurrentJustifiedCheckpoint.Root)
[]byte{byte(64)}, newState.CurrentJustifiedCheckpoint.Root)
}
if newState.PreviousJustifiedCheckpoint.Epoch != 0 {
t.Errorf("Wanted previous justified epoch: %d, got: %d",
@@ -913,17 +662,6 @@ func TestProcessFinalUpdates_CanProcess(t *testing.T) {
t.Errorf("effective balance incorrectly updated, got %d", s.Validators[0].EffectiveBalance)
}
// Verify start shard is correctly updated.
if newS.StartShard != 64 {
t.Errorf("start shard incorrectly updated, got %d", 64)
}
// Verify latest active index root is correctly updated in the right position.
pos := (ne + params.BeaconConfig().ActivationExitDelay) % params.BeaconConfig().EpochsPerHistoricalVector
if bytes.Equal(newS.ActiveIndexRoots[pos], params.BeaconConfig().ZeroHash[:]) {
t.Error("latest active index roots still zero hashes")
}
// Verify slashed balances correctly updated.
if newS.Slashings[ce] != newS.Slashings[ne] {
t.Errorf("wanted slashed balance %d, got %d",
@@ -946,39 +684,12 @@ func TestProcessFinalUpdates_CanProcess(t *testing.T) {
}
}
func TestCrosslinkDelta_NoOneAttested(t *testing.T) {
e := params.BeaconConfig().SlotsPerEpoch
validatorCount := uint64(128)
state := buildState(e+2, validatorCount)
rewards, penalties, err := crosslinkDelta(state)
if err != nil {
t.Fatal(err)
}
for i := uint64(0); i < validatorCount; i++ {
// Since no one attested, all the validators should gain 0 reward
if rewards[i] != 0 {
t.Errorf("Wanted reward balance 0, got %d", rewards[i])
}
// Since no one attested, all the validators should get penalized the same
base, err := BaseReward(state, i)
if err != nil {
t.Fatal(err)
}
if penalties[i] != base {
t.Errorf("Wanted penalty balance %d, got %d",
base, penalties[i])
}
}
}
func TestProcessRegistryUpdates_NoRotation(t *testing.T) {
state := &pb.BeaconState{
Slot: 5 * params.BeaconConfig().SlotsPerEpoch,
Validators: []*ethpb.Validator{
{ExitEpoch: params.BeaconConfig().ActivationExitDelay},
{ExitEpoch: params.BeaconConfig().ActivationExitDelay},
{ExitEpoch: params.BeaconConfig().MaxSeedLookhead},
{ExitEpoch: params.BeaconConfig().MaxSeedLookhead},
},
Balances: []uint64{
params.BeaconConfig().MaxEffectiveBalance,
@@ -991,88 +702,13 @@ func TestProcessRegistryUpdates_NoRotation(t *testing.T) {
t.Fatal(err)
}
for i, validator := range newState.Validators {
if validator.ExitEpoch != params.BeaconConfig().ActivationExitDelay {
if validator.ExitEpoch != params.BeaconConfig().MaxSeedLookhead {
t.Errorf("Could not update registry %d, wanted exit slot %d got %d",
i, params.BeaconConfig().ActivationExitDelay, validator.ExitEpoch)
i, params.BeaconConfig().MaxSeedLookhead, validator.ExitEpoch)
}
}
}
func TestCrosslinkDelta_SomeAttested(t *testing.T) {
helpers.ClearAllCaches()
e := params.BeaconConfig().SlotsPerEpoch
helpers.ClearShuffledValidatorCache()
state := buildState(e+2, params.BeaconConfig().MinGenesisActiveValidatorCount/8)
startShard := uint64(960)
atts := make([]*pb.PendingAttestation, 2)
for i := 0; i < len(atts); i++ {
atts[i] = &pb.PendingAttestation{
Data: &ethpb.AttestationData{
Crosslink: &ethpb.Crosslink{
Shard: startShard + uint64(i),
DataRoot: []byte{'A'},
},
Target: &ethpb.Checkpoint{},
Source: &ethpb.Checkpoint{},
},
InclusionDelay: uint64(i + 100),
AggregationBits: bitfield.Bitlist{0xC0, 0xC0, 0xC0, 0xC0, 0x01},
}
}
state.PreviousEpochAttestations = atts
state.CurrentCrosslinks[startShard] = &ethpb.Crosslink{
DataRoot: []byte{'A'}, Shard: startShard,
}
state.CurrentCrosslinks[startShard+1] = &ethpb.Crosslink{
DataRoot: []byte{'A'}, Shard: startShard + 1,
}
rewards, penalties, err := crosslinkDelta(state)
if err != nil {
t.Fatal(err)
}
attestedIndices := []uint64{5, 16, 336, 797, 1082, 1450, 1770, 1958}
for _, i := range attestedIndices {
// Since all these validators attested, they should get the same rewards.
want := uint64(12649)
if rewards[i] != want {
t.Errorf("Wanted reward balance %d, got %d", want, rewards[i])
}
// Since all these validators attested, they shouldn't get penalized.
if penalties[i] != 0 {
t.Errorf("Wanted penalty balance 0, got %d", penalties[i])
}
}
nonAttestedIndices := []uint64{12, 23, 45, 79}
for _, i := range nonAttestedIndices {
base, err := BaseReward(state, i)
if err != nil {
t.Errorf("Could not get base reward: %v", err)
}
wanted := base
// Since all these validators did not attest, they shouldn't get rewarded.
if rewards[i] != 0 {
t.Errorf("Wanted reward balance 0, got %d", rewards[i])
}
// Base penalties for not attesting.
if penalties[i] != wanted {
t.Errorf("Wanted penalty balance %d, got %d", wanted, penalties[i])
}
}
}
func TestCrosslinkDelta_CantGetWinningCrosslink(t *testing.T) {
state := buildState(0, 1)
_, _, err := crosslinkDelta(state)
wanted := "could not get winning crosslink: could not get matching attestations"
if !strings.Contains(err.Error(), wanted) {
t.Fatalf("Got: %v, want: %v", err.Error(), wanted)
}
}
func TestAttestationDelta_CantGetBlockRoot(t *testing.T) {
e := params.BeaconConfig().SlotsPerEpoch
@@ -1105,10 +741,6 @@ func TestAttestationDelta_NoOneAttested(t *testing.T) {
for i := 0; i < len(atts); i++ {
atts[i] = &pb.PendingAttestation{
Data: &ethpb.AttestationData{
Crosslink: &ethpb.Crosslink{
Shard: uint64(i),
DataRoot: []byte{'A'},
},
Target: &ethpb.Checkpoint{},
Source: &ethpb.Checkpoint{},
},
@@ -1145,15 +777,10 @@ func TestAttestationDelta_SomeAttested(t *testing.T) {
e := params.BeaconConfig().SlotsPerEpoch
validatorCount := params.BeaconConfig().MinGenesisActiveValidatorCount / 8
state := buildState(e+2, validatorCount)
startShard := uint64(960)
atts := make([]*pb.PendingAttestation, 3)
for i := 0; i < len(atts); i++ {
atts[i] = &pb.PendingAttestation{
Data: &ethpb.AttestationData{
Crosslink: &ethpb.Crosslink{
Shard: startShard + uint64(i),
DataRoot: []byte{'A'},
},
Target: &ethpb.Checkpoint{},
Source: &ethpb.Checkpoint{},
},
@@ -1162,18 +789,11 @@ func TestAttestationDelta_SomeAttested(t *testing.T) {
}
}
state.PreviousEpochAttestations = atts
state.CurrentCrosslinks[startShard] = &ethpb.Crosslink{
DataRoot: []byte{'A'},
}
state.CurrentCrosslinks[startShard+1] = &ethpb.Crosslink{
DataRoot: []byte{'A'},
}
rewards, penalties, err := attestationDelta(state)
if err != nil {
t.Fatal(err)
}
attestedBalance, err := AttestingBalance(state, atts)
if err != nil {
t.Error(err)
@@ -1183,18 +803,20 @@ func TestAttestationDelta_SomeAttested(t *testing.T) {
t.Fatal(err)
}
attestedIndices := []uint64{5, 754, 797, 1637, 1770, 1862, 1192}
attestedIndices := []uint64{100, 106, 196, 641, 654, 1606}
for _, i := range attestedIndices {
base, err := BaseReward(state, i)
if err != nil {
t.Errorf("Could not get base reward: %v", err)
}
// Base rewards for getting source right
wanted := 3 * (base * attestedBalance / totalBalance)
// Base rewards for proposer and attesters working together getting attestation
// on chain in the fatest manner
// on chain in the fastest manner
proposerReward := base / params.BeaconConfig().ProposerRewardQuotient
wanted += (base - proposerReward) * params.BeaconConfig().MinAttestationInclusionDelay
wanted += (base - proposerReward) / params.BeaconConfig().MinAttestationInclusionDelay
if rewards[i] != wanted {
t.Errorf("Wanted reward balance %d, got %d", wanted, rewards[i])
}
@@ -1227,15 +849,10 @@ func TestAttestationDelta_SomeAttestedFinalityDelay(t *testing.T) {
e := params.BeaconConfig().SlotsPerEpoch
validatorCount := params.BeaconConfig().MinGenesisActiveValidatorCount / 8
state := buildState(e+4, validatorCount)
startShard := uint64(960)
atts := make([]*pb.PendingAttestation, 3)
for i := 0; i < len(atts); i++ {
atts[i] = &pb.PendingAttestation{
Data: &ethpb.AttestationData{
Crosslink: &ethpb.Crosslink{
Shard: startShard + uint64(i),
DataRoot: []byte{'A'},
},
Target: &ethpb.Checkpoint{},
Source: &ethpb.Checkpoint{},
},
@@ -1245,18 +862,11 @@ func TestAttestationDelta_SomeAttestedFinalityDelay(t *testing.T) {
}
state.PreviousEpochAttestations = atts
state.FinalizedCheckpoint.Epoch = 0
state.CurrentCrosslinks[startShard] = &ethpb.Crosslink{
DataRoot: []byte{'A'},
}
state.CurrentCrosslinks[startShard+1] = &ethpb.Crosslink{
DataRoot: []byte{'A'},
}
rewards, penalties, err := attestationDelta(state)
if err != nil {
t.Fatal(err)
}
attestedBalance, err := AttestingBalance(state, atts)
if err != nil {
t.Error(err)
@@ -1266,7 +876,7 @@ func TestAttestationDelta_SomeAttestedFinalityDelay(t *testing.T) {
t.Fatal(err)
}
attestedIndices := []uint64{5, 754, 797, 1637, 1770, 1862, 1192}
attestedIndices := []uint64{100, 106, 196, 641, 654, 1606}
for _, i := range attestedIndices {
base, err := BaseReward(state, i)
if err != nil {
@@ -1346,10 +956,10 @@ func TestProcessRegistryUpdates_ActivationCompletes(t *testing.T) {
state := &pb.BeaconState{
Slot: 5 * params.BeaconConfig().SlotsPerEpoch,
Validators: []*ethpb.Validator{
{ExitEpoch: params.BeaconConfig().ActivationExitDelay,
ActivationEpoch: 5 + params.BeaconConfig().ActivationExitDelay + 1},
{ExitEpoch: params.BeaconConfig().ActivationExitDelay,
ActivationEpoch: 5 + params.BeaconConfig().ActivationExitDelay + 1},
{ExitEpoch: params.BeaconConfig().MaxSeedLookhead,
ActivationEpoch: 5 + params.BeaconConfig().MaxSeedLookhead + 1},
{ExitEpoch: params.BeaconConfig().MaxSeedLookhead,
ActivationEpoch: 5 + params.BeaconConfig().MaxSeedLookhead + 1},
},
FinalizedCheckpoint: &ethpb.Checkpoint{},
}
@@ -1358,9 +968,9 @@ func TestProcessRegistryUpdates_ActivationCompletes(t *testing.T) {
t.Error(err)
}
for i, validator := range newState.Validators {
if validator.ExitEpoch != params.BeaconConfig().ActivationExitDelay {
if validator.ExitEpoch != params.BeaconConfig().MaxSeedLookhead {
t.Errorf("Could not update registry %d, wanted exit slot %d got %d",
i, params.BeaconConfig().ActivationExitDelay, validator.ExitEpoch)
i, params.BeaconConfig().MaxSeedLookhead, validator.ExitEpoch)
}
}
}
@@ -1385,9 +995,9 @@ func TestProcessRegistryUpdates_ValidatorsEjected(t *testing.T) {
t.Error(err)
}
for i, validator := range newState.Validators {
if validator.ExitEpoch != params.BeaconConfig().ActivationExitDelay+1 {
if validator.ExitEpoch != params.BeaconConfig().MaxSeedLookhead+1 {
t.Errorf("Could not update registry %d, wanted exit slot %d got %d",
i, params.BeaconConfig().ActivationExitDelay+1, validator.ExitEpoch)
i, params.BeaconConfig().MaxSeedLookhead+1, validator.ExitEpoch)
}
}
}
@@ -1424,7 +1034,7 @@ func TestProcessRegistryUpdates_CanExits(t *testing.T) {
}
func TestProcessRewardsAndPenalties_GenesisEpoch(t *testing.T) {
state := &pb.BeaconState{Slot: params.BeaconConfig().SlotsPerEpoch - 1, StartShard: 999}
state := &pb.BeaconState{Slot: params.BeaconConfig().SlotsPerEpoch - 1}
newState, err := ProcessRewardsAndPenalties(state)
if err != nil {
t.Fatal(err)
@@ -1439,15 +1049,10 @@ func TestProcessRewardsAndPenalties_SomeAttested(t *testing.T) {
e := params.BeaconConfig().SlotsPerEpoch
validatorCount := params.BeaconConfig().MinGenesisActiveValidatorCount / 8
state := buildState(e+2, validatorCount)
startShard := uint64(960)
atts := make([]*pb.PendingAttestation, 3)
for i := 0; i < len(atts); i++ {
atts[i] = &pb.PendingAttestation{
Data: &ethpb.AttestationData{
Crosslink: &ethpb.Crosslink{
Shard: startShard + uint64(i),
DataRoot: []byte{'A'},
},
Target: &ethpb.Checkpoint{},
Source: &ethpb.Checkpoint{},
},
@@ -1456,26 +1061,17 @@ func TestProcessRewardsAndPenalties_SomeAttested(t *testing.T) {
}
}
state.PreviousEpochAttestations = atts
state.CurrentCrosslinks[startShard] = &ethpb.Crosslink{
DataRoot: []byte{'A'},
}
state.CurrentCrosslinks[startShard+1] = &ethpb.Crosslink{
DataRoot: []byte{'A'},
}
state.CurrentCrosslinks[startShard+2] = &ethpb.Crosslink{
DataRoot: []byte{'A'},
}
state, err := ProcessRewardsAndPenalties(state)
if err != nil {
t.Fatal(err)
}
wanted := uint64(31999949392)
wanted := uint64(31999873505)
if state.Balances[0] != wanted {
t.Errorf("wanted balance: %d, got: %d",
wanted, state.Balances[0])
}
wanted = uint64(31999995452)
wanted = uint64(31999810265)
if state.Balances[4] != wanted {
t.Errorf("wanted balance: %d, got: %d",
wanted, state.Balances[1])
@@ -1512,10 +1108,7 @@ func buildState(slot uint64, validatorCount uint64) *pb.BeaconState {
Slot: slot,
Balances: validatorBalances,
Validators: validators,
CurrentCrosslinks: make([]*ethpb.Crosslink, params.BeaconConfig().ShardCount),
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
CompactCommitteesRoots: make([][]byte, params.BeaconConfig().EpochsPerSlashingsVector),
Slashings: make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector),
BlockRoots: make([][]byte, params.BeaconConfig().SlotsPerEpoch*10),
FinalizedCheckpoint: &ethpb.Checkpoint{},

View File

@@ -27,14 +27,7 @@ func TestComputeValidatorParticipation(t *testing.T) {
balances[i] = params.BeaconConfig().MaxEffectiveBalance
}
atts := []*pb.PendingAttestation{{Data: &ethpb.AttestationData{Crosslink: &ethpb.Crosslink{Shard: 0}, Target: &ethpb.Checkpoint{}}}}
var crosslinks []*ethpb.Crosslink
for i := uint64(0); i < params.BeaconConfig().ShardCount; i++ {
crosslinks = append(crosslinks, &ethpb.Crosslink{
StartEpoch: 0,
DataRoot: []byte{'A'},
})
}
atts := []*pb.PendingAttestation{{Data: &ethpb.AttestationData{Target: &ethpb.Checkpoint{}}}}
s := &pb.BeaconState{
Slot: e*params.BeaconConfig().SlotsPerEpoch + 1,
@@ -43,9 +36,6 @@ func TestComputeValidatorParticipation(t *testing.T) {
BlockRoots: make([][]byte, 128),
Slashings: []uint64{0, 1e9, 1e9},
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
CompactCommitteesRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
CurrentCrosslinks: crosslinks,
CurrentEpochAttestations: atts,
FinalizedCheckpoint: &ethpb.Checkpoint{},
JustificationBits: bitfield.Bitvector4{0x00},

View File

@@ -13,7 +13,6 @@ go_library(
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute",
visibility = ["//beacon-chain:__subpackages__"],
deps = [
"//beacon-chain/core/epoch:go_default_library",
"//beacon-chain/core/helpers:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//proto/eth/v1alpha1:go_default_library",

View File

@@ -40,13 +40,7 @@ func ProcessAttestations(
if err != nil {
return nil, nil, err
}
// Get attestation slot to find lowest inclusion delayed attestation for each attested validators.
aSlot, err := helpers.AttestationDataSlot(state, a.Data)
if err != nil {
return nil, nil, err
}
vp = UpdateValidator(vp, v, indices, a, aSlot)
vp = UpdateValidator(vp, v, indices, a, a.Data.Slot)
}
bp = UpdateBalance(vp, bp)
@@ -112,11 +106,7 @@ func SameTarget(state *pb.BeaconState, a *pb.PendingAttestation, e uint64) (bool
// SameHead returns true if attestation `a` attested to the same block by attestation slot in state.
func SameHead(state *pb.BeaconState, a *pb.PendingAttestation) (bool, error) {
aSlot, err := helpers.AttestationDataSlot(state, a.Data)
if err != nil {
return false, err
}
r, err := helpers.BlockRootAtSlot(state, aSlot)
r, err := helpers.BlockRootAtSlot(state, a.Data.Slot)
if err != nil {
return false, err
}

View File

@@ -75,20 +75,15 @@ func TestUpdateBalance(t *testing.T) {
func TestSameHead(t *testing.T) {
helpers.ClearAllCaches()
deposits, _, _ := testutil.SetupInitialDeposits(t, 100)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{})
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Fatal(err)
}
beaconState.Slot = 1
att := &ethpb.Attestation{Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{Shard: 0}}}
attSlot, err := helpers.AttestationDataSlot(beaconState, att.Data)
if err != nil {
t.Fatal(err)
}
Target: &ethpb.Checkpoint{Epoch: 0}}}
r := []byte{'A'}
beaconState.BlockRoots[attSlot] = r
beaconState.BlockRoots[0] = r
att.Data.BeaconBlockRoot = r
same, err := precompute.SameHead(beaconState, &pb.PendingAttestation{Data: att.Data})
if err != nil {
@@ -109,20 +104,15 @@ func TestSameHead(t *testing.T) {
func TestSameTarget(t *testing.T) {
deposits, _, _ := testutil.SetupInitialDeposits(t, 100)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{})
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Fatal(err)
}
beaconState.Slot = 1
att := &ethpb.Attestation{Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{Shard: 0}}}
attSlot, err := helpers.AttestationDataSlot(beaconState, att.Data)
if err != nil {
t.Fatal(err)
}
Target: &ethpb.Checkpoint{Epoch: 0}}}
r := []byte{'A'}
beaconState.BlockRoots[attSlot] = r
beaconState.BlockRoots[0] = r
att.Data.Target.Root = r
same, err := precompute.SameTarget(beaconState, &pb.PendingAttestation{Data: att.Data}, 0)
if err != nil {
@@ -143,20 +133,15 @@ func TestSameTarget(t *testing.T) {
func TestAttestedPrevEpoch(t *testing.T) {
deposits, _, _ := testutil.SetupInitialDeposits(t, 100)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{})
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Fatal(err)
}
beaconState.Slot = params.BeaconConfig().SlotsPerEpoch
att := &ethpb.Attestation{Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{Shard: 960}}}
attSlot, err := helpers.AttestationDataSlot(beaconState, att.Data)
if err != nil {
t.Fatal(err)
}
Target: &ethpb.Checkpoint{Epoch: 0}}}
r := []byte{'A'}
beaconState.BlockRoots[attSlot] = r
beaconState.BlockRoots[0] = r
att.Data.Target.Root = r
att.Data.BeaconBlockRoot = r
votedEpoch, votedTarget, votedHead, err := precompute.AttestedPrevEpoch(beaconState, &pb.PendingAttestation{Data: att.Data})
@@ -176,20 +161,15 @@ func TestAttestedPrevEpoch(t *testing.T) {
func TestAttestedCurrentEpoch(t *testing.T) {
deposits, _, _ := testutil.SetupInitialDeposits(t, 100)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{})
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Fatal(err)
}
beaconState.Slot = params.BeaconConfig().SlotsPerEpoch + 1
att := &ethpb.Attestation{Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 1},
Crosslink: &ethpb.Crosslink{}}}
attSlot, err := helpers.AttestationDataSlot(beaconState, att.Data)
if err != nil {
t.Fatal(err)
}
Target: &ethpb.Checkpoint{Epoch: 1}}}
r := []byte{'A'}
beaconState.BlockRoots[attSlot] = r
beaconState.BlockRoots[params.BeaconConfig().SlotsPerEpoch] = r
att.Data.Target.Root = r
att.Data.BeaconBlockRoot = r
votedEpoch, votedTarget, err := precompute.AttestedCurrentEpoch(beaconState, &pb.PendingAttestation{Data: att.Data})
@@ -212,7 +192,7 @@ func TestProcessAttestations(t *testing.T) {
validators := uint64(64)
deposits, _, _ := testutil.SetupInitialDeposits(t, validators)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{})
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Fatal(err)
}
@@ -220,11 +200,11 @@ func TestProcessAttestations(t *testing.T) {
bf := []byte{0xff}
att1 := &ethpb.Attestation{Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{Shard: 960}}, AggregationBits: bf}
Target: &ethpb.Checkpoint{Epoch: 0}},
AggregationBits: bf}
att2 := &ethpb.Attestation{Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{Shard: 961}}, AggregationBits: bf}
Target: &ethpb.Checkpoint{Epoch: 0}},
AggregationBits: bf}
beaconState.BlockRoots[0] = []byte{'A'}
att1.Data.Target.Root = []byte{'A'}
att1.Data.BeaconBlockRoot = []byte{'A'}

View File

@@ -40,9 +40,9 @@ func TestProcessJustificationAndFinalizationPreCompute_ConsecutiveEpochs(t *test
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(newState.CurrentJustifiedCheckpoint.Root, []byte{byte(128)}) {
if !bytes.Equal(newState.CurrentJustifiedCheckpoint.Root, []byte{byte(64)}) {
t.Errorf("Wanted current justified root: %v, got: %v",
[]byte{byte(128)}, newState.CurrentJustifiedCheckpoint.Root)
[]byte{byte(64)}, newState.CurrentJustifiedCheckpoint.Root)
}
if newState.CurrentJustifiedCheckpoint.Epoch != 2 {
t.Errorf("Wanted justified epoch: %d, got: %d",
@@ -90,9 +90,9 @@ func TestProcessJustificationAndFinalizationPreCompute_JustifyCurrentEpoch(t *te
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(newState.CurrentJustifiedCheckpoint.Root, []byte{byte(128)}) {
if !bytes.Equal(newState.CurrentJustifiedCheckpoint.Root, []byte{byte(64)}) {
t.Errorf("Wanted current justified root: %v, got: %v",
[]byte{byte(128)}, newState.CurrentJustifiedCheckpoint.Root)
[]byte{byte(64)}, newState.CurrentJustifiedCheckpoint.Root)
}
if newState.CurrentJustifiedCheckpoint.Epoch != 2 {
t.Errorf("Wanted justified epoch: %d, got: %d",
@@ -139,9 +139,9 @@ func TestProcessJustificationAndFinalizationPreCompute_JustifyPrevEpoch(t *testi
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(newState.CurrentJustifiedCheckpoint.Root, []byte{byte(128)}) {
if !bytes.Equal(newState.CurrentJustifiedCheckpoint.Root, []byte{byte(64)}) {
t.Errorf("Wanted current justified root: %v, got: %v",
[]byte{byte(128)}, newState.CurrentJustifiedCheckpoint.Root)
[]byte{byte(64)}, newState.CurrentJustifiedCheckpoint.Root)
}
if newState.PreviousJustifiedCheckpoint.Epoch != 0 {
t.Errorf("Wanted previous justified epoch: %d, got: %d",

View File

@@ -2,7 +2,6 @@ package precompute
import (
"github.com/pkg/errors"
"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"
"github.com/prysmaticlabs/prysm/shared/mathutil"
@@ -30,14 +29,9 @@ func ProcessRewardsAndPenaltiesPrecompute(state *pb.BeaconState, bp *Balance, vp
if err != nil {
return nil, errors.Wrap(err, "could not get attestation delta")
}
clRewards, clPenalties, err := crosslinkDeltaPreCompute(state, bp, vp)
if err != nil {
return nil, errors.Wrapf(err, "could not get crosslink delta")
}
for i := 0; i < len(state.Validators); i++ {
state = helpers.IncreaseBalance(state, uint64(i), attsRewards[i]+clRewards[i]+proposerRewards[i])
state = helpers.DecreaseBalance(state, uint64(i), attsPenalties[i]+clPenalties[i])
state = helpers.IncreaseBalance(state, uint64(i), attsRewards[i]+proposerRewards[i])
state = helpers.DecreaseBalance(state, uint64(i), attsPenalties[i])
}
return state, nil
}
@@ -70,8 +64,7 @@ func attestationDelta(state *pb.BeaconState, bp *Balance, v *Validator) (uint64,
r += br * bp.PrevEpochAttesters / bp.CurrentEpoch
proposerReward := br / params.BeaconConfig().ProposerRewardQuotient
maxAtteserReward := br - proposerReward
slotsPerEpoch := params.BeaconConfig().SlotsPerEpoch
r += maxAtteserReward * (slotsPerEpoch + params.BeaconConfig().MinAttestationInclusionDelay - v.InclusionDistance) / slotsPerEpoch
r += maxAtteserReward / v.InclusionDistance
} else {
p += br
}
@@ -118,48 +111,3 @@ func proposerDeltaPrecompute(state *pb.BeaconState, bp *Balance, vp []*Validator
}
return rewards, nil
}
// This computes the rewards and penalties differences for individual validators based on the
// crosslink records.
func crosslinkDeltaPreCompute(state *pb.BeaconState, bp *Balance, vp []*Validator) ([]uint64, []uint64, error) {
rewards := make([]uint64, len(state.Validators))
penalties := make([]uint64, len(state.Validators))
prevEpoch := helpers.PrevEpoch(state)
count, err := helpers.CommitteeCount(state, prevEpoch)
if err != nil {
return nil, nil, errors.Wrap(err, "could not get epoch committee count")
}
startShard, err := helpers.StartShard(state, prevEpoch)
if err != nil {
return nil, nil, errors.Wrap(err, "could not get epoch start shard")
}
for i := uint64(0); i < count; i++ {
shard := (startShard + i) % params.BeaconConfig().ShardCount
committee, err := helpers.CrosslinkCommittee(state, prevEpoch, shard)
if err != nil {
return nil, nil, errors.Wrap(err, "could not get crosslink's committee")
}
_, attestingIndices, err := epoch.WinningCrosslink(state, shard, prevEpoch)
if err != nil {
return nil, nil, errors.Wrap(err, "could not get winning crosslink")
}
attested := make(map[uint64]bool)
// Construct a map to look up validators that voted for crosslink.
for _, index := range attestingIndices {
attested[index] = true
}
committeeBalance := helpers.TotalBalance(state, committee)
attestingBalance := helpers.TotalBalance(state, attestingIndices)
for _, index := range committee {
base := vp[index].CurrentEpochEffectiveBalance * params.BeaconConfig().BaseRewardFactor / mathutil.IntegerSquareRoot(bp.CurrentEpoch) / params.BeaconConfig().BaseRewardsPerEpoch
if _, ok := attested[index]; ok {
rewards[index] += base * attestingBalance / committeeBalance
} else {
penalties[index] += base
}
}
}
return rewards, penalties, nil
}

View File

@@ -17,15 +17,10 @@ func TestProcessRewardsAndPenaltiesPrecompute(t *testing.T) {
e := params.BeaconConfig().SlotsPerEpoch
validatorCount := uint64(2048)
state := buildState(e+3, validatorCount)
startShard := uint64(960)
atts := make([]*pb.PendingAttestation, 3)
for i := 0; i < len(atts); i++ {
atts[i] = &pb.PendingAttestation{
Data: &ethpb.AttestationData{
Crosslink: &ethpb.Crosslink{
Shard: startShard + uint64(i),
DataRoot: []byte{'A'},
},
Target: &ethpb.Checkpoint{},
Source: &ethpb.Checkpoint{},
},
@@ -34,15 +29,6 @@ func TestProcessRewardsAndPenaltiesPrecompute(t *testing.T) {
}
}
state.PreviousEpochAttestations = atts
state.CurrentCrosslinks[startShard] = &ethpb.Crosslink{
DataRoot: []byte{'A'},
}
state.CurrentCrosslinks[startShard+1] = &ethpb.Crosslink{
DataRoot: []byte{'A'},
}
state.CurrentCrosslinks[startShard+2] = &ethpb.Crosslink{
DataRoot: []byte{'A'},
}
vp, bp := New(context.Background(), state)
vp, bp, err := ProcessAttestations(context.Background(), state, vp, bp)
@@ -56,14 +42,14 @@ func TestProcessRewardsAndPenaltiesPrecompute(t *testing.T) {
}
// Indices that voted everything except for head, lost a bit money
wanted := uint64(31999995452)
wanted := uint64(31999810265)
if state.Balances[4] != wanted {
t.Errorf("wanted balance: %d, got: %d",
wanted, state.Balances[4])
}
// Indices that did not vote, lost more money
wanted = uint64(31999949392)
wanted = uint64(31999873505)
if state.Balances[0] != wanted {
t.Errorf("wanted balance: %d, got: %d",
wanted, state.Balances[0])
@@ -75,15 +61,10 @@ func TestAttestationDeltaPrecompute(t *testing.T) {
e := params.BeaconConfig().SlotsPerEpoch
validatorCount := uint64(2048)
state := buildState(e+2, validatorCount)
startShard := uint64(960)
atts := make([]*pb.PendingAttestation, 3)
for i := 0; i < len(atts); i++ {
atts[i] = &pb.PendingAttestation{
Data: &ethpb.AttestationData{
Crosslink: &ethpb.Crosslink{
Shard: startShard + uint64(i),
DataRoot: []byte{'A'},
},
Target: &ethpb.Checkpoint{},
Source: &ethpb.Checkpoint{},
},
@@ -92,12 +73,6 @@ func TestAttestationDeltaPrecompute(t *testing.T) {
}
}
state.PreviousEpochAttestations = atts
state.CurrentCrosslinks[startShard] = &ethpb.Crosslink{
DataRoot: []byte{'A'},
}
state.CurrentCrosslinks[startShard+1] = &ethpb.Crosslink{
DataRoot: []byte{'A'},
}
vp, bp := New(context.Background(), state)
vp, bp, err := ProcessAttestations(context.Background(), state, vp, bp)
@@ -118,7 +93,7 @@ func TestAttestationDeltaPrecompute(t *testing.T) {
t.Fatal(err)
}
attestedIndices := []uint64{5, 754, 797, 1637, 1770, 1862, 1192}
attestedIndices := []uint64{100, 106, 196, 641, 654, 1606}
for _, i := range attestedIndices {
base, err := epoch.BaseReward(state, i)
if err != nil {
@@ -157,78 +132,6 @@ func TestAttestationDeltaPrecompute(t *testing.T) {
}
}
func TestCrosslinkDeltaPrecompute(t *testing.T) {
helpers.ClearAllCaches()
e := params.BeaconConfig().SlotsPerEpoch
helpers.ClearShuffledValidatorCache()
validatorCount := uint64(2048)
state := buildState(e+2, validatorCount)
startShard := uint64(960)
atts := make([]*pb.PendingAttestation, 2)
for i := 0; i < len(atts); i++ {
atts[i] = &pb.PendingAttestation{
Data: &ethpb.AttestationData{
Crosslink: &ethpb.Crosslink{
Shard: startShard + uint64(i),
DataRoot: []byte{'A'},
},
Target: &ethpb.Checkpoint{},
Source: &ethpb.Checkpoint{},
},
InclusionDelay: uint64(i + 100),
AggregationBits: bitfield.Bitlist{0xC0, 0xC0, 0xC0, 0xC0, 0x01},
}
}
state.PreviousEpochAttestations = atts
state.CurrentCrosslinks[startShard] = &ethpb.Crosslink{
DataRoot: []byte{'A'}, Shard: startShard,
}
state.CurrentCrosslinks[startShard+1] = &ethpb.Crosslink{
DataRoot: []byte{'A'}, Shard: startShard + 1,
}
vp, bp := New(context.Background(), state)
vp, bp, err := ProcessAttestations(context.Background(), state, vp, bp)
if err != nil {
t.Fatal(err)
}
rewards, penalties, err := crosslinkDeltaPreCompute(state, bp, vp)
if err != nil {
t.Fatal(err)
}
attestedIndices := []uint64{5, 16, 336, 797, 1082, 1450, 1770, 1958}
for _, i := range attestedIndices {
// Since all these validators attested, they should get the same rewards.
want := uint64(12649)
if rewards[i] != want {
t.Errorf("Wanted reward balance %d, got %d", want, rewards[i])
}
// Since all these validators attested, they shouldn't get penalized.
if penalties[i] != 0 {
t.Errorf("Wanted penalty balance 0, got %d", penalties[i])
}
}
nonAttestedIndices := []uint64{12, 23, 45, 79}
for _, i := range nonAttestedIndices {
base, err := epoch.BaseReward(state, i)
if err != nil {
t.Errorf("Could not get base reward: %v", err)
}
wanted := base
// Since all these validators did not attest, they shouldn't get rewarded.
if rewards[i] != 0 {
t.Errorf("Wanted reward balance 0, got %d", rewards[i])
}
// Base penalties for not attesting.
if penalties[i] != wanted {
t.Errorf("Wanted penalty balance %d, got %d", wanted, penalties[i])
}
}
}
func buildState(slot uint64, validatorCount uint64) *pb.BeaconState {
validators := make([]*ethpb.Validator, validatorCount)
for i := 0; i < len(validators); i++ {
@@ -259,10 +162,7 @@ func buildState(slot uint64, validatorCount uint64) *pb.BeaconState {
Slot: slot,
Balances: validatorBalances,
Validators: validators,
CurrentCrosslinks: make([]*ethpb.Crosslink, params.BeaconConfig().ShardCount),
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
CompactCommitteesRoots: make([][]byte, params.BeaconConfig().EpochsPerSlashingsVector),
Slashings: make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector),
BlockRoots: make([][]byte, params.BeaconConfig().SlotsPerEpoch*10),
FinalizedCheckpoint: &ethpb.Checkpoint{},

View File

@@ -1,9 +0,0 @@
package spectest
import (
"testing"
)
func TestCrosslinksProcessingMainnet(t *testing.T) {
runCrosslinkProcessingTests(t, "mainnet")
}

View File

@@ -1,9 +0,0 @@
package spectest
import (
"testing"
)
func TestCrosslinksProcessingMinimal(t *testing.T) {
runCrosslinkProcessingTests(t, "minimal")
}

View File

@@ -1,33 +0,0 @@
package spectest
import (
"path"
"testing"
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/params/spectest"
"github.com/prysmaticlabs/prysm/shared/testutil"
)
func runCrosslinkProcessingTests(t *testing.T, config string) {
if err := spectest.SetConfig(config); err != nil {
t.Fatal(err)
}
testFolders, testsFolderPath := testutil.TestFolders(t, config, "epoch_processing/crosslinks/pyspec_tests")
for _, folder := range testFolders {
t.Run(folder.Name(), func(t *testing.T) {
folderPath := path.Join(testsFolderPath, folder.Name())
testutil.RunEpochOperationTest(t, folderPath, processCrosslinksWrapper)
})
}
}
func processCrosslinksWrapper(t *testing.T, state *pb.BeaconState) (*pb.BeaconState, error) {
state, err := epoch.ProcessCrosslinks(state)
if err != nil {
t.Fatalf("could not process crosslinks: %v", err)
}
return state, nil
}

View File

@@ -5,6 +5,5 @@ import (
)
func TestJustificationAndFinalizationMinimal(t *testing.T) {
t.Skip("Fails for could not get target atts current epoch")
runJustificationAndFinalizationTests(t, "minimal")
}

View File

@@ -1,7 +1,9 @@
package spectest
import (
"bytes"
"context"
"fmt"
"path"
"testing"
@@ -32,19 +34,19 @@ func runJustificationAndFinalizationTests(t *testing.T, config string) {
// This is a subset of state.ProcessEpoch. The spec test defines input data for
// `justification_and_finalization` only.
func processJustificationAndFinalizationWrapper(t *testing.T, state *pb.BeaconState) (*pb.BeaconState, error) {
prevEpochAtts, err := epoch.MatchAttestations(state, helpers.PrevEpoch(state))
prevEpochAtts, err := targetAtts(state, helpers.PrevEpoch(state))
if err != nil {
t.Fatalf("could not get target atts prev epoch %d: %v", helpers.PrevEpoch(state), err)
}
currentEpochAtts, err := epoch.MatchAttestations(state, helpers.CurrentEpoch(state))
currentEpochAtts, err := targetAtts(state, helpers.CurrentEpoch(state))
if err != nil {
t.Fatalf("could not get target atts current epoch %d: %v", helpers.CurrentEpoch(state), err)
}
prevEpochAttestedBalance, err := epoch.AttestingBalance(state, prevEpochAtts.Target)
prevEpochAttestedBalance, err := epoch.AttestingBalance(state, prevEpochAtts)
if err != nil {
t.Fatalf("could not get attesting balance prev epoch: %v", err)
}
currentEpochAttestedBalance, err := epoch.AttestingBalance(state, currentEpochAtts.Target)
currentEpochAttestedBalance, err := epoch.AttestingBalance(state, currentEpochAtts)
if err != nil {
t.Fatalf("could not get attesting balance current epoch: %v", err)
}
@@ -72,3 +74,36 @@ func processJustificationAndFinalizationPrecomputeWrapper(t *testing.T, state *p
return state, nil
}
func targetAtts(state *pb.BeaconState, epoch uint64) ([]*pb.PendingAttestation, error) {
currentEpoch := helpers.CurrentEpoch(state)
previousEpoch := helpers.PrevEpoch(state)
// Input epoch for matching the source attestations has to be within range
// of current epoch & previous epoch.
if epoch != currentEpoch && epoch != previousEpoch {
return nil, fmt.Errorf("input epoch: %d != current epoch: %d or previous epoch: %d",
epoch, currentEpoch, previousEpoch)
}
// Decide if the source attestations are coming from current or previous epoch.
var srcAtts []*pb.PendingAttestation
if epoch == currentEpoch {
srcAtts = state.CurrentEpochAttestations
} else {
srcAtts = state.PreviousEpochAttestations
}
targetRoot, err := helpers.BlockRoot(state, epoch)
if err != nil {
return nil, err
}
tgtAtts := make([]*pb.PendingAttestation, 0, len(srcAtts))
for _, srcAtt := range srcAtts {
if bytes.Equal(srcAtt.Data.Target.Root, targetRoot) {
tgtAtts = append(tgtAtts, srcAtt)
}
}
return tgtAtts, nil
}

View File

@@ -34,9 +34,6 @@ go_library(
"@com_github_gogo_protobuf//proto:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
"@org_golang_google_grpc//codes:go_default_library",
"@org_golang_google_grpc//status:go_default_library",
],
)
@@ -56,7 +53,6 @@ go_test(
embed = [":go_default_library"],
shard_count = 2,
deps = [
"//beacon-chain/core/state:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//proto/eth/v1alpha1:go_default_library",
"//shared/bls:go_default_library",
@@ -64,11 +60,8 @@ go_test(
"//shared/featureconfig:go_default_library",
"//shared/params:go_default_library",
"//shared/sliceutil:go_default_library",
"//shared/testutil:go_default_library",
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
"@org_golang_google_grpc//codes:go_default_library",
"@org_golang_google_grpc//status:go_default_library",
],
)

View File

@@ -3,11 +3,8 @@ package helpers
import (
"github.com/gogo/protobuf/proto"
"github.com/pkg/errors"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/params"
)
var (
@@ -22,39 +19,6 @@ var (
ErrAttestationAggregationBitsOverlap = errors.New("overlapping aggregation bits")
)
// AttestationDataSlot returns current slot of AttestationData for given state
//
// Spec pseudocode definition:
// def get_attestation_data_slot(state: BeaconState, data: AttestationData) -> Slot:
// """
// Return the slot corresponding to the attestation ``data``.
// """
// committee_count = get_committee_count(state, data.target.epoch)
// offset = (data.crosslink.shard + SHARD_COUNT - get_start_shard(state, data.target.epoch)) % SHARD_COUNT
// return Slot(compute_start_slot_of_epoch(data.target.epoch) + offset // (committee_count // SLOTS_PER_EPOCH))
func AttestationDataSlot(state *pb.BeaconState, data *ethpb.AttestationData) (uint64, error) {
if state == nil {
return 0, ErrAttestationDataSlotNilState
}
if data == nil {
return 0, ErrAttestationDataSlotNilData
}
committeeCount, err := CommitteeCount(state, data.Target.Epoch)
if err != nil {
return 0, err
}
epochStartShardNumber, err := StartShard(state, data.Target.Epoch)
if err != nil { // This should never happen if CommitteeCount was successful
return 0, errors.Wrap(err, "could not determine epoch start shard")
}
offset := (data.Crosslink.Shard + params.BeaconConfig().ShardCount -
epochStartShardNumber) % params.BeaconConfig().ShardCount
return StartSlot(data.Target.Epoch) + (offset / (committeeCount / params.BeaconConfig().SlotsPerEpoch)), nil
}
// AggregateAttestations such that the minimal number of attestations are returned.
// Note: this is currently a naive implementation to the order of O(n^2).
func AggregateAttestations(atts []*ethpb.Attestation) ([]*ethpb.Attestation, error) {

View File

@@ -9,88 +9,10 @@ import (
"github.com/prysmaticlabs/go-bitfield"
"github.com/prysmaticlabs/go-ssz"
"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"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
)
func TestAttestationDataSlot_OK(t *testing.T) {
deposits, _, _ := testutil.SetupInitialDeposits(t, 100)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{})
if err != nil {
t.Fatal(err)
}
offset := uint64(0)
committeeCount, _ := helpers.CommitteeCount(beaconState, 0)
expect := offset / (committeeCount / params.BeaconConfig().SlotsPerEpoch)
attSlot, err := helpers.AttestationDataSlot(beaconState, &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{
Shard: 0,
},
})
if err != nil {
t.Fatal(err)
}
if attSlot != expect {
t.Errorf("Expected %d, received %d", expect, attSlot)
}
}
func TestAttestationDataSlot_ReturnsErrorWithNilState(t *testing.T) {
s, err := helpers.AttestationDataSlot(nil /*state*/, &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{
Shard: 0,
},
})
if err != helpers.ErrAttestationDataSlotNilState {
t.Errorf("Expected an error, but received %v", err)
t.Logf("attestation slot=%v", s)
}
}
func TestAttestationDataSlot_ReturnsErrorWithNilData(t *testing.T) {
s, err := helpers.AttestationDataSlot(&pb.BeaconState{}, nil /*data*/)
if err != helpers.ErrAttestationDataSlotNilData {
t.Errorf("Expected an error, but received %v", err)
t.Logf("attestation slot=%v", s)
}
}
func TestAttestationDataSlot_ReturnsErrorWithErroneousTargetEpoch(t *testing.T) {
deposits, _, _ := testutil.SetupInitialDeposits(t, 100)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{})
if err != nil {
t.Fatal(err)
}
s, err := helpers.AttestationDataSlot(beaconState, &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 1<<63 - 1 /* Far future epoch */},
})
if err == nil {
t.Error("Expected an error, but received nil")
t.Logf("attestation slot=%v", s)
}
}
func TestAttestationDataSlot_ReturnsErrorWhenTargetEpochLessThanCurrentEpoch(t *testing.T) {
deposits, _, _ := testutil.SetupInitialDeposits(t, 100)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{})
if err != nil {
t.Fatal(err)
}
s, err := helpers.AttestationDataSlot(beaconState, &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 2},
})
if err == nil {
t.Error("Expected an error, but received nil")
t.Logf("attestation slot=%v", s)
}
}
func TestAggregateAttestation(t *testing.T) {
tests := []struct {
a1 *ethpb.Attestation
@@ -164,11 +86,11 @@ func TestAggregateAttestations(t *testing.T) {
{
name: "two attestations with no overlap",
inputs: []bitfield.Bitlist{
bitfield.Bitlist{0b00000001, 0b1},
bitfield.Bitlist{0b00000010, 0b1},
{0b00000001, 0b1},
{0b00000010, 0b1},
},
want: []bitfield.Bitlist{
bitfield.Bitlist{0b00000011, 0b1},
{0b00000011, 0b1},
},
},
{
@@ -188,57 +110,57 @@ func TestAggregateAttestations(t *testing.T) {
{
name: "two attestations with overlap",
inputs: []bitfield.Bitlist{
bitfield.Bitlist{0b00000101, 0b1},
bitfield.Bitlist{0b00000110, 0b1},
{0b00000101, 0b1},
{0b00000110, 0b1},
},
want: []bitfield.Bitlist{
bitfield.Bitlist{0b00000101, 0b1},
bitfield.Bitlist{0b00000110, 0b1},
{0b00000101, 0b1},
{0b00000110, 0b1},
},
},
{
name: "some attestations overlap",
inputs: []bitfield.Bitlist{
bitfield.Bitlist{0b00001001, 0b1},
bitfield.Bitlist{0b00010110, 0b1},
bitfield.Bitlist{0b00001010, 0b1},
bitfield.Bitlist{0b00110001, 0b1},
{0b00001001, 0b1},
{0b00010110, 0b1},
{0b00001010, 0b1},
{0b00110001, 0b1},
},
want: []bitfield.Bitlist{
bitfield.Bitlist{0b00111011, 0b1},
bitfield.Bitlist{0b00011111, 0b1},
{0b00111011, 0b1},
{0b00011111, 0b1},
},
},
{
name: "some attestations produce duplicates which are removed",
inputs: []bitfield.Bitlist{
bitfield.Bitlist{0b00000101, 0b1},
bitfield.Bitlist{0b00000110, 0b1},
bitfield.Bitlist{0b00001010, 0b1},
bitfield.Bitlist{0b00001001, 0b1},
{0b00000101, 0b1},
{0b00000110, 0b1},
{0b00001010, 0b1},
{0b00001001, 0b1},
},
want: []bitfield.Bitlist{
bitfield.Bitlist{0b00001111, 0b1}, // both 0&1 and 2&3 produce this bitlist
{0b00001111, 0b1}, // both 0&1 and 2&3 produce this bitlist
},
},
{
name: "two attestations where one is fully contained within the other",
inputs: []bitfield.Bitlist{
bitfield.Bitlist{0b00000001, 0b1},
bitfield.Bitlist{0b00000011, 0b1},
{0b00000001, 0b1},
{0b00000011, 0b1},
},
want: []bitfield.Bitlist{
bitfield.Bitlist{0b00000011, 0b1},
{0b00000011, 0b1},
},
},
{
name: "two attestations where one is fully contained within the other reversed",
inputs: []bitfield.Bitlist{
bitfield.Bitlist{0b00000011, 0b1},
bitfield.Bitlist{0b00000001, 0b1},
{0b00000011, 0b1},
{0b00000001, 0b1},
},
want: []bitfield.Bitlist{
bitfield.Bitlist{0b00000011, 0b1},
{0b00000011, 0b1},
},
},
}

View File

@@ -4,11 +4,6 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
)
// ClearShuffledValidatorCache clears the shuffled indices cache from scratch.
func ClearShuffledValidatorCache() {
shuffledIndicesCache = cache.NewShuffledIndicesCache()
}
// ClearActiveCountCache restarts the active validator count cache from scratch.
func ClearActiveCountCache() {
activeCountCache = cache.NewActiveCountCache()
@@ -28,5 +23,4 @@ func ActiveIndicesKeys() []string {
func ClearAllCaches() {
ClearActiveIndicesCache()
ClearActiveCountCache()
ClearShuffledValidatorCache()
}

View File

@@ -6,82 +6,64 @@ import (
"github.com/pkg/errors"
"github.com/prysmaticlabs/go-bitfield"
"github.com/prysmaticlabs/go-ssz"
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/featureconfig"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/sliceutil"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
var shuffledIndicesCache = cache.NewShuffledIndicesCache()
var committeeCache = cache.NewCommitteeCache()
// CommitteeCount returns the number of crosslink committees of an epoch.
// CommitteeCountAtSlot returns the number of crosslink committees of a slot.
//
// Spec pseudocode definition:
// def get_committee_count(state: BeaconState, epoch: Epoch) -> uint64:
// def get_committee_count_at_slot(state: BeaconState, slot: Slot) -> uint64:
// """
// Return the number of committees at ``epoch``.
// Return the number of committees at ``slot``.
// """
// committees_per_slot = max(1, min(
// SHARD_COUNT // SLOTS_PER_EPOCH,
// epoch = compute_epoch_at_slot(slot)
// return max(1, min(
// MAX_COMMITTEES_PER_SLOT,
// len(get_active_validator_indices(state, epoch)) // SLOTS_PER_EPOCH // TARGET_COMMITTEE_SIZE,
// ))
// return committees_per_slot * SLOTS_PER_EPOCH
func CommitteeCount(state *pb.BeaconState, epoch uint64) (uint64, error) {
if featureconfig.Get().EnableNewCache {
count, exists, err := committeeCache.CommitteeCount(epoch)
if err != nil {
return 0, errors.Wrap(err, "could not interface with committee cache")
}
if exists {
return count, nil
}
}
minCommitteePerSlot := uint64(1)
// Max committee count per slot will be 0 when shard count is less than epoch length, this
// covers the special case to ensure there's always 1 max committee count per slot.
var committeeSizesPerSlot = minCommitteePerSlot
if params.BeaconConfig().ShardCount/params.BeaconConfig().SlotsPerEpoch > minCommitteePerSlot {
committeeSizesPerSlot = params.BeaconConfig().ShardCount / params.BeaconConfig().SlotsPerEpoch
}
func CommitteeCountAtSlot(state *pb.BeaconState, slot uint64) (uint64, error) {
epoch := SlotToEpoch(slot)
count, err := ActiveValidatorCount(state, epoch)
if err != nil {
return 0, errors.Wrap(err, "could not get active count")
}
var currCommitteePerSlot = count / params.BeaconConfig().SlotsPerEpoch / params.BeaconConfig().TargetCommitteeSize
if currCommitteePerSlot > committeeSizesPerSlot {
return committeeSizesPerSlot * params.BeaconConfig().SlotsPerEpoch, nil
var committeePerSlot = count / params.BeaconConfig().SlotsPerEpoch / params.BeaconConfig().TargetCommitteeSize
if committeePerSlot > params.BeaconConfig().MaxCommitteesPerSlot {
return params.BeaconConfig().MaxCommitteesPerSlot, nil
}
if currCommitteePerSlot < 1 {
return minCommitteePerSlot * params.BeaconConfig().SlotsPerEpoch, nil
if committeePerSlot == 0 {
return 1, nil
}
return currCommitteePerSlot * params.BeaconConfig().SlotsPerEpoch, nil
return committeePerSlot, nil
}
// CrosslinkCommittee returns the crosslink committee of a given epoch.
// BeaconCommittee returns the crosslink committee of a given epoch.
//
// Spec pseudocode definition:
// def get_crosslink_committee(state: BeaconState, epoch: Epoch, shard: Shard) -> Sequence[ValidatorIndex]:
// def get_beacon_committee(state: BeaconState, slot: Slot, index: CommitteeIndex) -> Sequence[ValidatorIndex]:
// """
// Return the crosslink committee at ``epoch`` for ``shard``.
// Return the beacon committee at ``slot`` for ``index``.
// """
// epoch = compute_epoch_at_slot(slot)
// committees_per_slot = get_committee_count_at_slot(state, slot)
// epoch_offset = index + (slot % SLOTS_PER_EPOCH) * committees_per_slot
// return compute_committee(
// indices=get_active_validator_indices(state, epoch),
// seed=get_seed(state, epoch),
// index=(shard + SHARD_COUNT - get_start_shard(state, epoch)) % SHARD_COUNT,
// count=get_committee_count(state, epoch),
// seed=get_seed(state, epoch, DOMAIN_BEACON_ATTESTER),
// index=epoch_offset,
// count=committees_per_slot * SLOTS_PER_EPOCH,
// )
func CrosslinkCommittee(state *pb.BeaconState, epoch uint64, shard uint64) ([]uint64, error) {
func BeaconCommittee(state *pb.BeaconState, slot uint64, index uint64) ([]uint64, error) {
epoch := SlotToEpoch(slot)
if featureconfig.Get().EnableNewCache {
indices, err := committeeCache.ShuffledIndices(epoch, shard)
indices, err := committeeCache.ShuffledIndices(slot, index)
if err != nil {
return nil, errors.Wrap(err, "could not interface with committee cache")
}
@@ -90,7 +72,14 @@ func CrosslinkCommittee(state *pb.BeaconState, epoch uint64, shard uint64) ([]ui
}
}
seed, err := Seed(state, epoch)
committeesPerSlot, err := CommitteeCountAtSlot(state, slot)
if err != nil {
return nil, errors.Wrap(err, "could not get committee count at slot")
}
epochOffset := index + (slot%params.BeaconConfig().SlotsPerEpoch)*committeesPerSlot
count := committeesPerSlot * params.BeaconConfig().SlotsPerEpoch
seed, err := Seed(state, epoch, params.BeaconConfig().DomainBeaconAttester)
if err != nil {
return nil, errors.Wrap(err, "could not get seed")
}
@@ -99,20 +88,7 @@ func CrosslinkCommittee(state *pb.BeaconState, epoch uint64, shard uint64) ([]ui
if err != nil {
return nil, errors.Wrap(err, "could not get active indices")
}
startShard, err := StartShard(state, epoch)
if err != nil {
return nil, errors.Wrap(err, "could not get start shard")
}
shardCount := params.BeaconConfig().ShardCount
currentShard := (shard + shardCount - startShard) % shardCount
committeeCount, err := CommitteeCount(state, epoch)
if err != nil {
return nil, errors.Wrap(err, "could not get committee count")
}
return ComputeCommittee(indices, seed, currentShard, committeeCount)
return ComputeCommittee(indices, seed, epochOffset, count)
}
// ComputeCommittee returns the requested shuffled committee out of the total committees using
@@ -130,40 +106,25 @@ func CrosslinkCommittee(state *pb.BeaconState, epoch uint64, shard uint64) ([]ui
// end = (len(indices) * (index + 1)) // count
// return [indices[compute_shuffled_index(ValidatorIndex(i), len(indices), seed)] for i in range(start, end)
func ComputeCommittee(
validatorIndices []uint64,
indices []uint64,
seed [32]byte,
indexShard uint64,
totalCommittees uint64,
index uint64,
count uint64,
) ([]uint64, error) {
validatorCount := uint64(len(validatorIndices))
start := sliceutil.SplitOffset(validatorCount, totalCommittees, indexShard)
end := sliceutil.SplitOffset(validatorCount, totalCommittees, indexShard+1)
validatorCount := uint64(len(indices))
start := sliceutil.SplitOffset(validatorCount, count, index)
end := sliceutil.SplitOffset(validatorCount, count, index+1)
// Use cached shuffled indices list if we have seen the seed before.
cachedShuffledList, err := shuffledIndicesCache.IndicesByIndexSeed(indexShard, seed[:])
if err != nil {
return nil, err
}
if cachedShuffledList != nil {
return cachedShuffledList, nil
}
// Save the shuffled indices in cache, this is only needed once per epoch or once per new shard index.
// Save the shuffled indices in cache, this is only needed once per epoch or once per new committee index.
shuffledIndices := make([]uint64, end-start)
for i := start; i < end; i++ {
permutedIndex, err := ShuffledIndex(i, validatorCount, seed)
if err != nil {
return []uint64{}, errors.Wrapf(err, "could not get shuffled index at index %d", i)
}
shuffledIndices[i-start] = validatorIndices[permutedIndex]
}
if err := shuffledIndicesCache.AddShuffledValidatorList(&cache.IndicesByIndexSeed{
Index: indexShard,
Seed: seed[:],
ShuffledIndices: shuffledIndices,
}); err != nil {
return []uint64{}, errors.Wrap(err, "could not add shuffled indices list to cache")
shuffledIndices[i-start] = indices[permutedIndex]
}
return shuffledIndices, nil
}
@@ -176,10 +137,10 @@ func ComputeCommittee(
// """
// Return the set of attesting indices corresponding to ``data`` and ``bits``.
// """
// committee = get_crosslink_committee(state, data.target.epoch, data.crosslink.shard)
// committee = get_beacon_committee(state, data.slot, data.index)
// return set(index for i, index in enumerate(committee) if bits[i])
func AttestingIndices(state *pb.BeaconState, data *ethpb.AttestationData, bf bitfield.Bitfield) ([]uint64, error) {
committee, err := CrosslinkCommittee(state, data.Target.Epoch, data.Crosslink.Shard)
committee, err := BeaconCommittee(state, data.Slot, data.Index)
if err != nil {
return nil, errors.Wrap(err, "could not get committee")
}
@@ -197,6 +158,77 @@ func AttestingIndices(state *pb.BeaconState, data *ethpb.AttestationData, bf bit
return indices, nil
}
// CommitteeAssignment is used to query committee assignment from
// current and previous epoch.
//
// Spec pseudocode definition:
// def get_committee_assignment(state: BeaconState,
// epoch: Epoch,
// validator_index: ValidatorIndex
// ) -> Optional[Tuple[Sequence[ValidatorIndex], CommitteeIndex, Slot]]:
// """
// Return the committee assignment in the ``epoch`` for ``validator_index``.
// ``assignment`` returned is a tuple of the following form:
// * ``assignment[0]`` is the list of validators in the committee
// * ``assignment[1]`` is the index to which the committee is assigned
// * ``assignment[2]`` is the slot at which the committee is assigned
// Return None if no assignment.
// """
// next_epoch = get_current_epoch(state) + 1
// assert epoch <= next_epoch
//
// start_slot = compute_start_slot_at_epoch(epoch)
// for slot in range(start_slot, start_slot + SLOTS_PER_EPOCH):
// for index in range(get_committee_count_at_slot(state, Slot(slot))):
// committee = get_beacon_committee(state, Slot(slot), CommitteeIndex(index))
// if validator_index in committee:
// return committee, CommitteeIndex(index), Slot(slot)
// return None
func CommitteeAssignment(
state *pb.BeaconState,
epoch uint64,
validatorIndex uint64,
) ([]uint64, uint64, uint64, uint64, error) {
if epoch > NextEpoch(state) {
return nil, 0, 0, 0, fmt.Errorf(
"epoch %d can't be greater than next epoch %d",
epoch, NextEpoch(state))
}
// Track which slot has which proposer.
startSlot := StartSlot(epoch)
proposerIndexToSlot := make(map[uint64]uint64)
for slot := startSlot; slot < startSlot+params.BeaconConfig().SlotsPerEpoch; slot++ {
state.Slot = slot
i, err := BeaconProposerIndex(state)
if err != nil {
return nil, 0, 0, 0, errors.Wrapf(err, "could not check proposer at slot %d", state.Slot)
}
proposerIndexToSlot[i] = slot
}
for slot := startSlot; slot < startSlot+params.BeaconConfig().SlotsPerEpoch; slot++ {
countAtSlot, err := CommitteeCountAtSlot(state, slot)
if err != nil {
return nil, 0, 0, 0, errors.Wrapf(err, "could not get committee count at slot %d", slot)
}
for i := uint64(0); i < countAtSlot; i++ {
committee, err := BeaconCommittee(state, slot, i)
if err != nil {
return nil, 0, 0, 0, errors.Wrapf(err, "could not get crosslink committee at slot %d", slot)
}
for _, v := range committee {
if validatorIndex == v {
proposerSlot, _ := proposerIndexToSlot[v]
return committee, i, slot, proposerSlot, nil
}
}
}
}
return []uint64{}, 0, 0, 0, fmt.Errorf("validator with index %d not found in assignments", validatorIndex)
}
// VerifyBitfieldLength verifies that a bitfield length matches the given committee size.
func VerifyBitfieldLength(bf bitfield.Bitfield, committeeSize uint64) error {
if bf.Len() != committeeSize {
@@ -208,182 +240,16 @@ func VerifyBitfieldLength(bf bitfield.Bitfield, committeeSize uint64) error {
return nil
}
// CommitteeAssignment is used to query committee assignment from
// current and previous epoch.
//
// Spec pseudocode definition:
// def get_committee_assignment(state: BeaconState,
// epoch: Epoch,
// validator_index: ValidatorIndex) -> Optional[Tuple[Sequence[ValidatorIndex], Shard, Slot]]:
// """
// Return the committee assignment in the ``epoch`` for ``validator_index``.
// ``assignment`` returned is a tuple of the following form:
// * ``assignment[0]`` is the list of validators in the committee
// * ``assignment[1]`` is the shard to which the committee is assigned
// * ``assignment[2]`` is the slot at which the committee is assigned
// Return None if no assignment.
// """
// next_epoch = get_current_epoch(state) + 1
// assert epoch <= next_epoch
//
// committees_per_slot = get_committee_count(state, epoch) // SLOTS_PER_EPOCH
// start_slot = compute_start_slot_of_epoch(epoch)
// for slot in range(start_slot, start_slot + SLOTS_PER_EPOCH):
// offset = committees_per_slot * (slot % SLOTS_PER_EPOCH)
// slot_start_shard = (get_start_shard(state, epoch) + offset) % SHARD_COUNT
// for i in range(committees_per_slot):
// shard = Shard((slot_start_shard + i) % SHARD_COUNT)
// committee = get_crosslink_committee(state, epoch, shard)
// if validator_index in committee:
// return committee, shard, Slot(slot)
// return None
func CommitteeAssignment(
state *pb.BeaconState,
epoch uint64,
validatorIndex uint64) ([]uint64, uint64, uint64, bool, error) {
if epoch > NextEpoch(state) {
return nil, 0, 0, false, fmt.Errorf(
"epoch %d can't be greater than next epoch %d",
epoch, NextEpoch(state))
}
committeeCount, err := CommitteeCount(state, epoch)
if err != nil {
return nil, 0, 0, false, errors.Wrap(err, "could not get committee count")
}
committeesPerSlot := committeeCount / params.BeaconConfig().SlotsPerEpoch
epochStartShard, err := StartShard(state, epoch)
if err != nil {
return nil, 0, 0, false, fmt.Errorf(
"could not get epoch start shard: %v", err)
}
startSlot := StartSlot(epoch)
for slot := startSlot; slot < startSlot+params.BeaconConfig().SlotsPerEpoch; slot++ {
offset := committeesPerSlot * (slot % params.BeaconConfig().SlotsPerEpoch)
slotStatShard := (epochStartShard + offset) % params.BeaconConfig().ShardCount
for i := uint64(0); i < committeesPerSlot; i++ {
shard := (slotStatShard + i) % params.BeaconConfig().ShardCount
committee, err := CrosslinkCommittee(state, epoch, shard)
if err != nil {
return nil, 0, 0, false, fmt.Errorf(
"could not get crosslink committee: %v", err)
}
for _, index := range committee {
if validatorIndex == index {
state.Slot = slot
proposerIndex, err := BeaconProposerIndex(state)
if err != nil {
return nil, 0, 0, false, fmt.Errorf(
"could not check proposer index: %v", err)
}
isProposer := proposerIndex == validatorIndex
return committee, shard, slot, isProposer, nil
}
}
}
}
return []uint64{}, 0, 0, false, status.Error(codes.NotFound, "validator not found in assignments")
}
// ShardDelta returns the minimum number of shards get processed in one epoch.
//
// Note: if you already have the committee count,
// use shardDeltaFromCommitteeCount as CommitteeCount (specifically
// ActiveValidatorCount) iterates over the entire validator set.
//
// Spec pseudocode definition:
// def get_shard_delta(state: BeaconState, epoch: Epoch) -> uint64:
// """
// Return the number of shards to increment ``state.start_shard`` at ``epoch``.
// """
// return min(get_committee_count(state, epoch), SHARD_COUNT - SHARD_COUNT // SLOTS_PER_EPOCH)
func ShardDelta(beaconState *pb.BeaconState, epoch uint64) (uint64, error) {
committeeCount, err := CommitteeCount(beaconState, epoch)
if err != nil {
return 0, errors.Wrap(err, "could not get committee count")
}
return shardDeltaFromCommitteeCount(committeeCount), nil
}
// shardDeltaFromCommitteeCount returns the number of shards that get processed
// in one epoch. This method is the inner logic of ShardDelta.
// Returns the minimum of the committeeCount and maximum shard delta which is
// defined as SHARD_COUNT - SHARD_COUNT // SLOTS_PER_EPOCH.
func shardDeltaFromCommitteeCount(committeeCount uint64) uint64 {
shardCount := params.BeaconConfig().ShardCount
maxShardDelta := shardCount - shardCount/params.BeaconConfig().SlotsPerEpoch
if committeeCount < maxShardDelta {
return committeeCount
}
return maxShardDelta
}
// StartShard returns the start shard used to process crosslink
// of a given epoch. The start shard is cached using epoch as key,
// it gets rewritten where there's a reorg or a new finalized block.
//
// Spec pseudocode definition:
// def get_start_shard(state: BeaconState, epoch: Epoch) -> Shard:
// """
// Return the start shard of the 0th committee at ``epoch``.
// """
// assert epoch <= get_current_epoch(state) + 1
// check_epoch = Epoch(get_current_epoch(state) + 1)
// shard = Shard((state.start_shard + get_shard_delta(state, get_current_epoch(state))) % SHARD_COUNT)
// while check_epoch > epoch:
// check_epoch -= Epoch(1)
// shard = Shard((shard + SHARD_COUNT - get_shard_delta(state, check_epoch)) % SHARD_COUNT)
// return shard
func StartShard(state *pb.BeaconState, epoch uint64) (uint64, error) {
if featureconfig.Get().EnableNewCache {
startShard, exists, err := committeeCache.StartShard(epoch)
if err != nil {
return 0, errors.Wrap(err, "could not interface with committee cache")
}
if exists {
return startShard, nil
}
}
currentEpoch := CurrentEpoch(state)
checkEpoch := currentEpoch + 1
if epoch > checkEpoch {
return 0, fmt.Errorf("epoch %d can't be greater than %d",
epoch, checkEpoch)
}
delta, err := ShardDelta(state, currentEpoch)
if err != nil {
return 0, errors.Wrap(err, "could not get shard delta")
}
startShard := (state.StartShard + delta) % params.BeaconConfig().ShardCount
for checkEpoch > epoch {
checkEpoch--
d, err := ShardDelta(state, checkEpoch)
if err != nil {
return 0, errors.Wrap(err, "could not get shard delta")
}
startShard = (startShard + params.BeaconConfig().ShardCount - d) % params.BeaconConfig().ShardCount
}
return startShard, nil
}
// VerifyAttestationBitfieldLengths verifies that an attestations aggregation and custody bitfields are
// a valid length matching the size of the committee.
func VerifyAttestationBitfieldLengths(bState *pb.BeaconState, att *ethpb.Attestation) error {
committee, err := CrosslinkCommittee(bState, att.Data.Target.Epoch, att.Data.Crosslink.Shard)
committee, err := BeaconCommittee(bState, att.Data.Slot, att.Data.Index)
if err != nil {
return errors.Wrap(err, "could not retrieve crosslink committees")
return errors.Wrap(err, "could not retrieve beacon committees")
}
if committee == nil {
return errors.New("no committee exist for shard in the attestation")
return errors.New("no committee exist for this attestation")
}
if err := VerifyBitfieldLength(att.AggregationBits, uint64(len(committee))); err != nil {
@@ -395,95 +261,10 @@ func VerifyAttestationBitfieldLengths(bState *pb.BeaconState, att *ethpb.Attesta
return nil
}
// CompactCommitteesRoot returns the index root of a given epoch.
//
// Spec pseudocode definition:
// def get_compact_committees_root(state: BeaconState, epoch: Epoch) -> Hash:
// """
// Return the compact committee root at ``epoch``.
// """
// committees = [CompactCommittee() for _ in range(SHARD_COUNT)]
// start_shard = get_epoch_start_shard(state, epoch)
// for committee_number in range(get_epoch_committee_count(state, epoch)):
// shard = Shard((start_shard + committee_number) % SHARD_COUNT)
// for index in get_crosslink_committee(state, epoch, shard):
// validator = state.validators[index]
// committees[shard].pubkeys.append(validator.pubkey)
// compact_balance = validator.effective_balance // EFFECTIVE_BALANCE_INCREMENT
// # `index` (top 6 bytes) + `slashed` (16th bit) + `compact_balance` (bottom 15 bits)
// compact_validator = uint64((index << 16) + (validator.slashed << 15) + compact_balance)
// committees[shard].compact_validators.append(compact_validator)
// return hash_tree_root(Vector[CompactCommittee, SHARD_COUNT](committees))
func CompactCommitteesRoot(state *pb.BeaconState, epoch uint64) ([32]byte, error) {
shardCount := params.BeaconConfig().ShardCount
switch shardCount {
case 1024:
compactCommArray := [1024]*pb.CompactCommittee{}
for i := range compactCommArray {
compactCommArray[i] = &pb.CompactCommittee{}
}
comCount, err := CommitteeCount(state, epoch)
if err != nil {
return [32]byte{}, err
}
startShard, err := StartShard(state, epoch)
if err != nil {
return [32]byte{}, err
}
for i := uint64(0); i < comCount; i++ {
shard := (startShard + i) % shardCount
crossComm, err := CrosslinkCommittee(state, epoch, shard)
if err != nil {
return [32]byte{}, err
}
for _, index := range crossComm {
validator := state.Validators[index]
compactCommArray[shard].Pubkeys = append(compactCommArray[shard].Pubkeys, validator.PublicKey)
compactValidator := compressValidator(validator, index)
compactCommArray[shard].CompactValidators = append(compactCommArray[shard].CompactValidators, compactValidator)
}
}
return ssz.HashTreeRoot(compactCommArray)
case 8:
compactCommArray := [8]*pb.CompactCommittee{}
for i := range compactCommArray {
compactCommArray[i] = &pb.CompactCommittee{}
}
comCount, err := CommitteeCount(state, epoch)
if err != nil {
return [32]byte{}, err
}
startShard, err := StartShard(state, epoch)
if err != nil {
return [32]byte{}, err
}
for i := uint64(0); i < comCount; i++ {
shard := (startShard + i) % shardCount
crossComm, err := CrosslinkCommittee(state, epoch, shard)
if err != nil {
return [32]byte{}, err
}
for _, index := range crossComm {
validator := state.Validators[index]
compactCommArray[shard].Pubkeys = append(compactCommArray[shard].Pubkeys, validator.PublicKey)
compactValidator := compressValidator(validator, index)
compactCommArray[shard].CompactValidators = append(compactCommArray[shard].CompactValidators, compactValidator)
}
}
return ssz.HashTreeRoot(compactCommArray)
default:
return [32]byte{}, fmt.Errorf("expected minimal or mainnet config shard count, received %d", shardCount)
}
}
// ShuffledIndices uses input beacon state and returns the shuffled indices of the input epoch,
// the shuffled indices then can be used to break up into committees.
func ShuffledIndices(state *pb.BeaconState, epoch uint64) ([]uint64, error) {
seed, err := Seed(state, epoch)
seed, err := Seed(state, epoch, params.BeaconConfig().DomainBeaconAttester)
if err != nil {
return nil, errors.Wrapf(err, "could not get seed for epoch %d", epoch)
}
@@ -507,7 +288,7 @@ func ShuffledIndices(state *pb.BeaconState, epoch uint64) ([]uint64, error) {
}
// UpdateCommitteeCache gets called at the beginning of every epoch to cache the committee shuffled indices
// list with start shard and epoch number. It caches the shuffled indices for current epoch and next epoch.
// list with committee index and epoch number. It caches the shuffled indices for current epoch and next epoch.
func UpdateCommitteeCache(state *pb.BeaconState) error {
currentEpoch := CurrentEpoch(state)
for _, epoch := range []uint64{currentEpoch, currentEpoch + 1} {
@@ -515,42 +296,17 @@ func UpdateCommitteeCache(state *pb.BeaconState) error {
if err != nil {
return err
}
startShard, err := StartShard(state, epoch)
if err != nil {
return err
}
committeeCount, err := CommitteeCount(state, epoch)
count, err := CommitteeCountAtSlot(state, epoch*params.BeaconConfig().SlotsPerEpoch)
if err != nil {
return err
}
if err := committeeCache.AddCommitteeShuffledList(&cache.Committee{
Epoch: epoch,
Committee: committees,
StartShard: startShard,
CommitteeCount: committeeCount,
CommitteeCount: count * params.BeaconConfig().SlotsPerEpoch,
}); err != nil {
return err
}
}
return nil
}
// compressValidator compacts all the validator data such as validator index, slashing info and balance
// into a single uint64 field.
//
// Spec reference:
// # `index` (top 6 bytes) + `slashed` (16th bit) + `compact_balance` (bottom 15 bits)
// compact_validator = uint64((index << 16) + (validator.slashed << 15) + compact_balance)
func compressValidator(validator *ethpb.Validator, idx uint64) uint64 {
compactBalance := validator.EffectiveBalance / params.BeaconConfig().EffectiveBalanceIncrement
// index (top 6 bytes) + slashed (16th bit) + compact_balance (bottom 15 bits)
compactIndex := idx << 16
var slashedBit uint64
if validator.Slashed {
slashedBit = 1 << 15
}
// Clear all bits except last 15.
compactBalance &= 0x7FFF // 0b01111111 0b11111111
compactValidator := compactIndex | slashedBit | compactBalance
return compactValidator
}

File diff suppressed because it is too large Load Diff

View File

@@ -15,54 +15,28 @@ var ErrInvalidStateLatestActiveIndexRoots = errors.New("state does not have corr
// Seed returns the randao seed used for shuffling of a given epoch.
//
// Spec pseudocode definition:
// def get_seed(state: BeaconState, epoch: Epoch) -> Hash:
// def get_seed(state: BeaconState, epoch: Epoch, domain_type: DomainType) -> Hash:
// """
// Return the seed at ``epoch``.
// """
// mix = get_randao_mix(state, Epoch(epoch + EPOCHS_PER_HISTORICAL_VECTOR - MIN_SEED_LOOKAHEAD - 1)) #Avoid underflow
// active_index_root = state.active_index_roots[epoch % EPOCHS_PER_HISTORICAL_VECTOR]
// return hash(mix + active_index_root + int_to_bytes(epoch, length=32))
func Seed(state *pb.BeaconState, epoch uint64) ([32]byte, error) {
// mix = get_randao_mix(state, Epoch(epoch + EPOCHS_PER_HISTORICAL_VECTOR - MIN_SEED_LOOKAHEAD - 1)) # Avoid underflow
// return hash(domain_type + int_to_bytes(epoch, length=8) + mix)
func Seed(state *pb.BeaconState, epoch uint64, domain []byte) ([32]byte, error) {
// See https://github.com/ethereum/eth2.0-specs/pull/1296 for
// rationale on why offset has to look down by 1.
lookAheadEpoch := epoch + params.BeaconConfig().EpochsPerHistoricalVector -
params.BeaconConfig().MinSeedLookahead - 1
// Check that the state has the correct latest active index roots or
// randao mix may panic for index out of bounds.
if uint64(len(state.ActiveIndexRoots)) != params.BeaconConfig().EpochsPerHistoricalVector {
return [32]byte{}, ErrInvalidStateLatestActiveIndexRoots
}
randaoMix := RandaoMix(state, lookAheadEpoch)
indexRoot := ActiveIndexRoot(state, epoch)
seed := append(domain, bytesutil.Bytes8(epoch)...)
seed = append(seed, randaoMix...)
th := append(randaoMix, indexRoot...)
th = append(th, bytesutil.Bytes32(epoch)...)
seed32 := hashutil.Hash(th)
seed32 := hashutil.Hash(seed)
return seed32, nil
}
// ActiveIndexRoot returns the index root of a given epoch.
//
// Spec pseudocode definition:
// def get_active_index_root(state: BeaconState,
// epoch: Epoch) -> Bytes32:
// """
// Return the index root at a recent ``epoch``.
// ``epoch`` expected to be between
// (current_epoch - LATEST_ACTIVE_INDEX_ROOTS_LENGTH + ACTIVATION_EXIT_DELAY, current_epoch + ACTIVATION_EXIT_DELAY].
// """
// return state.latest_active_index_roots[epoch % LATEST_ACTIVE_INDEX_ROOTS_LENGTH]
func ActiveIndexRoot(state *pb.BeaconState, epoch uint64) []byte {
newRootLength := len(state.ActiveIndexRoots[epoch%params.BeaconConfig().EpochsPerHistoricalVector])
newRoot := make([]byte, newRootLength)
copy(newRoot, state.ActiveIndexRoots[epoch%params.BeaconConfig().EpochsPerHistoricalVector])
return newRoot
}
// RandaoMix returns the randao mix (xor'ed seed)
// of a given slot. It is used to shuffle validators.
//

View File

@@ -87,86 +87,8 @@ func TestRandaoMix_CopyOK(t *testing.T) {
}
}
func TestActiveIndexRoot_OK(t *testing.T) {
activeIndexRoots := make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector)
for i := 0; i < len(activeIndexRoots); i++ {
intInBytes := make([]byte, 32)
binary.LittleEndian.PutUint64(intInBytes, uint64(i))
activeIndexRoots[i] = intInBytes
}
state := &pb.BeaconState{ActiveIndexRoots: activeIndexRoots}
tests := []struct {
epoch uint64
}{
{
epoch: 34,
},
{
epoch: 3444,
},
{
epoch: 999999,
},
}
for _, test := range tests {
state.Slot = (test.epoch) * params.BeaconConfig().SlotsPerEpoch
for i := 0; i <= int(params.BeaconConfig().ActivationExitDelay); i++ {
indexRoot := ActiveIndexRoot(state, test.epoch+uint64(i))
if !bytes.Equal(activeIndexRoots[(test.epoch+uint64(i))%params.BeaconConfig().EpochsPerHistoricalVector], indexRoot) {
t.Errorf("Incorrect index root. Wanted: %#x, got: %#x",
activeIndexRoots[(test.epoch+uint64(i))%params.BeaconConfig().EpochsPerHistoricalVector], indexRoot)
}
}
}
}
func TestActiveIndexRoot_CopyOK(t *testing.T) {
ClearAllCaches()
conf := params.BeaconConfig()
conf.EpochsPerHistoricalVector = 100
params.OverrideBeaconConfig(conf)
activeIndexRoots := make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector)
for i := 0; i < len(activeIndexRoots); i++ {
intInBytes := make([]byte, 32)
binary.LittleEndian.PutUint64(intInBytes, uint64(i))
activeIndexRoots[i] = intInBytes
}
state := &pb.BeaconState{ActiveIndexRoots: activeIndexRoots}
tests := []struct {
epoch uint64
}{
{
epoch: 34,
},
}
for _, test := range tests {
state.Slot = (test.epoch) * params.BeaconConfig().SlotsPerEpoch
indexRoot := ActiveIndexRoot(state, test.epoch)
uniqueNumber := params.BeaconConfig().EpochsPerHistoricalVector + 1000
binary.LittleEndian.PutUint64(indexRoot, uniqueNumber)
for _, root := range activeIndexRoots {
rootNum := bytesutil.FromBytes8(root)
if rootNum == uniqueNumber {
t.Fatalf("two distinct slices which have different representations in memory still contain"+
"the same value: %d", rootNum)
}
}
}
}
func TestGenerateSeed_OK(t *testing.T) {
ClearAllCaches()
activeIndexRoots := make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector)
for i := 0; i < len(activeIndexRoots); i++ {
intInBytes := make([]byte, 32)
binary.LittleEndian.PutUint64(intInBytes, uint64(i))
activeIndexRoots[i] = intInBytes
}
randaoMixes := make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector)
for i := 0; i < len(randaoMixes); i++ {
intInBytes := make([]byte, 32)
@@ -175,17 +97,16 @@ func TestGenerateSeed_OK(t *testing.T) {
}
slot := 10 * params.BeaconConfig().MinSeedLookahead * params.BeaconConfig().SlotsPerEpoch
state := &pb.BeaconState{
ActiveIndexRoots: activeIndexRoots,
RandaoMixes: randaoMixes,
Slot: slot}
RandaoMixes: randaoMixes,
Slot: slot}
got, err := Seed(state, 10)
got, err := Seed(state, 10, params.BeaconConfig().DomainBeaconAttester)
if err != nil {
t.Fatal(err)
}
wanted := [32]byte{141, 205, 112, 76, 60, 173, 127, 10, 1, 214, 151, 41, 69, 40, 108, 88, 247,
210, 88, 5, 150, 112, 64, 93, 208, 110, 194, 137, 234, 180, 40, 245}
wanted := [32]byte{102, 82, 23, 40, 226, 79, 171, 11, 203, 23, 175, 7, 88, 202, 80,
103, 68, 126, 195, 143, 190, 249, 210, 85, 138, 196, 158, 208, 11, 18, 136, 23}
if got != wanted {
t.Errorf("Incorrect generated seeds. Got: %v, wanted: %v",
got, wanted)

View File

@@ -35,15 +35,16 @@ func SplitIndices(l []uint64, n uint64) [][]uint64 {
// constant between iterations instead of reallocating it each iteration as in the spec. This implementation is based
// on the original implementation from protolambda, https://github.com/protolambda/eth2-shuffle
func ShuffledIndex(index uint64, indexCount uint64, seed [32]byte) (uint64, error) {
return innerShuffledIndex(index, indexCount, seed, true /* shuffle */)
return ComputeShuffledIndex(index, indexCount, seed, true /* shuffle */)
}
// UnShuffledIndex returns the inverse of ShuffledIndex. This implementation is based
// on the original implementation from protolambda, https://github.com/protolambda/eth2-shuffle
func UnShuffledIndex(index uint64, indexCount uint64, seed [32]byte) (uint64, error) {
return innerShuffledIndex(index, indexCount, seed, false /* un-shuffle */)
return ComputeShuffledIndex(index, indexCount, seed, false /* un-shuffle */)
}
// ComputeShuffledIndex returns the shuffled validator index corresponding to seed and index count.
// Spec pseudocode definition:
// def compute_shuffled_index(index: ValidatorIndex, index_count: uint64, seed: Hash) -> ValidatorIndex:
// """
@@ -63,7 +64,7 @@ func UnShuffledIndex(index uint64, indexCount uint64, seed [32]byte) (uint64, er
// index = flip if bit else index
//
// return ValidatorIndex(index)
func innerShuffledIndex(index uint64, indexCount uint64, seed [32]byte, shuffle bool) (uint64, error) {
func ComputeShuffledIndex(index uint64, indexCount uint64, seed [32]byte, shuffle bool) (uint64, error) {
if params.BeaconConfig().ShuffleRoundCount == 0 {
return index, nil
}

View File

@@ -13,10 +13,10 @@ func TestSlotToEpoch_OK(t *testing.T) {
epoch uint64
}{
{slot: 0, epoch: 0},
{slot: 50, epoch: 0},
{slot: 64, epoch: 1},
{slot: 128, epoch: 2},
{slot: 200, epoch: 3},
{slot: 50, epoch: 1},
{slot: 64, epoch: 2},
{slot: 128, epoch: 4},
{slot: 200, epoch: 6},
}
for _, tt := range tests {
if tt.epoch != SlotToEpoch(tt.slot) {
@@ -31,10 +31,10 @@ func TestCurrentEpoch_OK(t *testing.T) {
epoch uint64
}{
{slot: 0, epoch: 0},
{slot: 50, epoch: 0},
{slot: 64, epoch: 1},
{slot: 128, epoch: 2},
{slot: 200, epoch: 3},
{slot: 50, epoch: 1},
{slot: 64, epoch: 2},
{slot: 128, epoch: 4},
{slot: 200, epoch: 6},
}
for _, tt := range tests {
state := &pb.BeaconState{Slot: tt.slot}
@@ -67,7 +67,7 @@ func TestNextEpoch_OK(t *testing.T) {
epoch uint64
}{
{slot: 0, epoch: 0/params.BeaconConfig().SlotsPerEpoch + 1},
{slot: 50, epoch: 0/params.BeaconConfig().SlotsPerEpoch + 1},
{slot: 50, epoch: 0/params.BeaconConfig().SlotsPerEpoch + 2},
{slot: 64, epoch: 64/params.BeaconConfig().SlotsPerEpoch + 1},
{slot: 128, epoch: 128/params.BeaconConfig().SlotsPerEpoch + 1},
{slot: 200, epoch: 200/params.BeaconConfig().SlotsPerEpoch + 1},

View File

@@ -1,8 +1,6 @@
package helpers
import (
"fmt"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
@@ -135,7 +133,7 @@ func ActiveValidatorCount(state *pb.BeaconState, epoch uint64) (uint64, error) {
// """
// return Epoch(epoch + 1 + ACTIVATION_EXIT_DELAY)
func DelayedActivationExitEpoch(epoch uint64) uint64 {
return epoch + 1 + params.BeaconConfig().ActivationExitDelay
return epoch + 1 + params.BeaconConfig().MaxSeedLookhead
}
// ValidatorChurnLimit returns the number of validators that are allowed to
@@ -168,59 +166,57 @@ func ValidatorChurnLimit(state *pb.BeaconState) (uint64, error) {
// Return the beacon proposer index at the current slot.
// """
// epoch = get_current_epoch(state)
// committees_per_slot = get_committee_count(state, epoch) // SLOTS_PER_EPOCH
// offset = committees_per_slot * (state.slot % SLOTS_PER_EPOCH)
// shard = Shard((get_start_shard(state, epoch) + offset) % SHARD_COUNT)
// first_committee = get_crosslink_committee(state, epoch, shard)
// seed = hash(get_seed(state, epoch, DOMAIN_BEACON_PROPOSER) + int_to_bytes(state.slot, length=8))
// indices = get_active_validator_indices(state, epoch)
// return compute_proposer_index(state, indices, seed)
func BeaconProposerIndex(state *pb.BeaconState) (uint64, error) {
e := CurrentEpoch(state)
seed, err := Seed(state, e, params.BeaconConfig().DomainBeaconProposer)
if err != nil {
return 0, errors.Wrap(err, "could not generate seed")
}
seedWithSlot := append(seed[:], bytesutil.Bytes8(state.Slot)...)
seedWithSlotHash := hashutil.Hash(seedWithSlot)
indices, err := ActiveValidatorIndices(state, e)
if err != nil {
return 0, errors.Wrap(err, "could not get active indices")
}
return ComputeProposerIndex(state, indices, seedWithSlotHash)
}
// ComputeProposerIndex returns the index sampled by effective balance, which is used to calculate proposer.
//
// Spec pseudocode definition:
// def compute_proposer_index(state: BeaconState, indices: Sequence[ValidatorIndex], seed: Hash) -> ValidatorIndex:
// """
// Return from ``indices`` a random index sampled by effective balance.
// """
// assert len(indices) > 0
// MAX_RANDOM_BYTE = 2**8 - 1
// seed = get_seed(state, epoch)
// i = 0
// while True:
// candidate_index = first_committee[(epoch + i) % len(first_committee)]
// candidate_index = indices[compute_shuffled_index(ValidatorIndex(i % len(indices)), len(indices), seed)]
// random_byte = hash(seed + int_to_bytes(i // 32, length=8))[i % 32]
// effective_balance = state.validators[candidate_index].effective_balance
// if effective_balance * MAX_RANDOM_BYTE >= MAX_EFFECTIVE_BALANCE * random_byte:
// return ValidatorIndex(candidate_index)
// i += 1
func BeaconProposerIndex(state *pb.BeaconState) (uint64, error) {
// Calculate the offset for slot and shard
e := CurrentEpoch(state)
committeeCount, err := CommitteeCount(state, e)
if err != nil {
return 0, err
func ComputeProposerIndex(state *pb.BeaconState, indices []uint64, seed [32]byte) (uint64, error) {
length := uint64(len(indices))
if length == 0 {
return 0, errors.New("empty indices list")
}
committesPerSlot := committeeCount / params.BeaconConfig().SlotsPerEpoch
offSet := committesPerSlot * (state.Slot % params.BeaconConfig().SlotsPerEpoch)
// Calculate which shards get assigned given the epoch start shard
// and the offset
startShard, err := StartShard(state, e)
if err != nil {
return 0, errors.Wrap(err, "could not get start shard")
}
shard := (startShard + offSet) % params.BeaconConfig().ShardCount
// Use the first committee of the given slot and shard
// to select proposer
firstCommittee, err := CrosslinkCommittee(state, e, shard)
if err != nil {
return 0, errors.Wrap(err, "could not get first committee")
}
if len(firstCommittee) == 0 {
return 0, fmt.Errorf("empty first committee at slot %d", state.Slot)
}
// Use the generated seed to select proposer from the first committee
maxRandomByte := uint64(1<<8 - 1)
seed, err := Seed(state, e)
if err != nil {
return 0, errors.Wrap(err, "could not generate seed")
}
// Looping through the committee to select proposer that has enough
// effective balance.
for i := uint64(0); ; i++ {
candidateIndex := firstCommittee[(e+i)%uint64(len(firstCommittee))]
candidateIndex, err := ComputeShuffledIndex(i%length, length, seed, true)
if err != nil {
return 0, err
}
b := append(seed[:], bytesutil.Bytes8(i/32)...)
randomByte := hashutil.Hash(b)[i%32]
effectiveBal := state.Validators[candidateIndex].EffectiveBalance

View File

@@ -1,7 +1,6 @@
package helpers
import (
"fmt"
"testing"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
@@ -31,10 +30,6 @@ func TestIsActiveValidator_OK(t *testing.T) {
}
func TestIsSlashableValidator_Active(t *testing.T) {
if params.BeaconConfig().SlotsPerEpoch != 64 {
t.Errorf("SlotsPerEpoch should be 64 for these tests to pass")
}
activeValidator := &ethpb.Validator{
WithdrawableEpoch: params.BeaconConfig().FarFutureEpoch,
}
@@ -46,10 +41,6 @@ func TestIsSlashableValidator_Active(t *testing.T) {
}
func TestIsSlashableValidator_BeforeWithdrawable(t *testing.T) {
if params.BeaconConfig().SlotsPerEpoch != 64 {
t.Errorf("SlotsPerEpoch should be 64 for these tests to pass")
}
beforeWithdrawableValidator := &ethpb.Validator{
WithdrawableEpoch: 5,
}
@@ -61,10 +52,6 @@ func TestIsSlashableValidator_BeforeWithdrawable(t *testing.T) {
}
func TestIsSlashableValidator_Inactive(t *testing.T) {
if params.BeaconConfig().SlotsPerEpoch != 64 {
t.Errorf("SlotsPerEpoch should be 64 for these tests to pass")
}
inactiveValidator := &ethpb.Validator{
ActivationEpoch: 5,
WithdrawableEpoch: params.BeaconConfig().FarFutureEpoch,
@@ -77,10 +64,6 @@ func TestIsSlashableValidator_Inactive(t *testing.T) {
}
func TestIsSlashableValidator_AfterWithdrawable(t *testing.T) {
if params.BeaconConfig().SlotsPerEpoch != 64 {
t.Errorf("SlotsPerEpoch should be 64 for these tests to pass")
}
afterWithdrawableValidator := &ethpb.Validator{
WithdrawableEpoch: 3,
}
@@ -92,9 +75,6 @@ func TestIsSlashableValidator_AfterWithdrawable(t *testing.T) {
}
func TestIsSlashableValidator_SlashedWithdrawalble(t *testing.T) {
if params.BeaconConfig().SlotsPerEpoch != 64 {
t.Errorf("SlotsPerEpoch should be 64 for these tests to pass")
}
slashedValidator := &ethpb.Validator{
Slashed: true,
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
@@ -108,10 +88,6 @@ func TestIsSlashableValidator_SlashedWithdrawalble(t *testing.T) {
}
func TestIsSlashableValidator_Slashed(t *testing.T) {
if params.BeaconConfig().SlotsPerEpoch != 64 {
t.Errorf("SlotsPerEpoch should be 64 for these tests to pass")
}
slashedValidator2 := &ethpb.Validator{
Slashed: true,
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
@@ -125,10 +101,6 @@ func TestIsSlashableValidator_Slashed(t *testing.T) {
}
func TestIsSlashableValidator_InactiveSlashed(t *testing.T) {
if params.BeaconConfig().SlotsPerEpoch != 64 {
t.Errorf("SlotsPerEpoch should be 64 for these tests to pass")
}
slashedValidator2 := &ethpb.Validator{
Slashed: true,
ActivationEpoch: 4,
@@ -144,11 +116,6 @@ func TestIsSlashableValidator_InactiveSlashed(t *testing.T) {
func TestBeaconProposerIndex_OK(t *testing.T) {
ClearAllCaches()
if params.BeaconConfig().SlotsPerEpoch != 64 {
t.Errorf("SlotsPerEpoch should be 64 for these tests to pass")
}
c := params.BeaconConfig()
c.MinGenesisActiveValidatorCount = 16384
params.OverrideBeaconConfig(c)
@@ -160,10 +127,9 @@ func TestBeaconProposerIndex_OK(t *testing.T) {
}
state := &pb.BeaconState{
Validators: validators,
Slot: 0,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
Validators: validators,
Slot: 0,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
}
tests := []struct {
@@ -172,23 +138,23 @@ func TestBeaconProposerIndex_OK(t *testing.T) {
}{
{
slot: 1,
index: 254,
index: 505,
},
{
slot: 5,
index: 391,
index: 798,
},
{
slot: 19,
index: 204,
index: 1956,
},
{
slot: 30,
index: 1051,
index: 991,
},
{
slot: 43,
index: 1047,
index: 1751,
},
}
@@ -209,24 +175,10 @@ func TestBeaconProposerIndex_OK(t *testing.T) {
}
}
func TestBeaconProposerIndex_EmptyCommittee(t *testing.T) {
ClearAllCaches()
beaconState := &pb.BeaconState{
Slot: 0,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
}
_, err := BeaconProposerIndex(beaconState)
expected := fmt.Sprintf("empty first committee at slot %d", 0)
if err.Error() != expected {
t.Errorf("Unexpected error. got=%v want=%s", err, expected)
}
}
func TestDelayedActivationExitEpoch_OK(t *testing.T) {
epoch := uint64(9999)
got := DelayedActivationExitEpoch(epoch)
wanted := epoch + 1 + params.BeaconConfig().ActivationExitDelay
wanted := epoch + 1 + params.BeaconConfig().MaxSeedLookhead
if wanted != got {
t.Errorf("Wanted: %d, received: %d", wanted, got)
}
@@ -252,10 +204,9 @@ func TestChurnLimit_OK(t *testing.T) {
}
beaconState := &pb.BeaconState{
Slot: 1,
Validators: validators,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
Slot: 1,
Validators: validators,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
}
resultChurn, err := ValidatorChurnLimit(beaconState)
if err != nil {

View File

@@ -25,7 +25,6 @@ go_library(
"//proto/beacon/p2p/v1:go_default_library",
"//proto/eth/v1alpha1:go_default_library",
"//shared/featureconfig:go_default_library",
"//shared/hashutil:go_default_library",
"//shared/mathutil:go_default_library",
"//shared/params:go_default_library",
"//shared/traceutil:go_default_library",
@@ -66,23 +65,3 @@ go_test(
"@com_github_sirupsen_logrus//:go_default_library",
],
)
# Requires ssz=minimal
# gazelle:exclude minimal_config_consensus_test.go
go_test(
name = "go_minimal_test",
size = "small",
srcs = ["minimal_config_consensus_test.go"],
data = glob(["testdata/minimal/**/*.ssz"]),
embed = [":go_default_library"],
tags = [
"manual",
"minimal",
],
deps = [
"//proto/beacon/p2p/v1:go_default_library",
"//proto/eth/v1alpha1:go_default_library",
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
"@in_gopkg_d4l3k_messagediff_v1//:go_default_library",
],
)

View File

@@ -1,95 +0,0 @@
package state
import (
"context"
"io/ioutil"
"testing"
"github.com/prysmaticlabs/go-ssz"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/params"
"gopkg.in/d4l3k/messagediff.v1"
)
func TestConsensusBugs(t *testing.T) {
tests := []struct {
name string
blockPath string
preStatePath string
postStatePath string
}{
{
// This scenario produced a consensus issue between ZCLI, and Artemis.
// The test expects that running a state transition with 0_block 0_prestate would
// output 0_poststate.
//
// Assert ExecuteStateTransition(ctx, 0_block, 0_prestate) == 0_poststate
//
// https://github.com/djrtwo/interop-test-cases/tree/master/tests/artemis_16_crosslinks_and_balances
name: "ZcliArtemisCrosslinks",
blockPath: "testdata/minimal/artemis_crosslink/block.ssz",
preStatePath: "testdata/minimal/artemis_crosslink/pre.ssz",
postStatePath: "testdata/minimal/artemis_crosslink/post.ssz",
},
{
// This scenario produced a consensus issue when running Prysm with Trinity.
// The test expects that running a state transition with 0_block 0_prestate would
// output 0_poststate.
//
// Assert ExecuteStateTransition(ctx, 0_block, 0_prestate) == 0_poststate
//
// https://github.com/djrtwo/interop-test-cases/tree/master/tests/prysm_16_duplicate_attestation_rewards
name: "TrinityPrysmDuplicateRewards",
blockPath: "testdata/minimal/duplicate_rewards/block.ssz",
preStatePath: "testdata/minimal/duplicate_rewards/pre.ssz",
postStatePath: "testdata/minimal/duplicate_rewards/post.ssz",
},
{
// This scenario produced a consensus issue between Trinity, ZCLI, and Lighthouse.
// The test expects that running a state transition with 0_block 0_prestate would
// output 0_poststate.
//
// Assert ExecuteStateTransition(ctx, 0_block, 0_prestate) == 0_poststate
//
// https://github.com/djrtwo/interop-test-cases/tree/master/tests/night_one_16_crosslinks
name: "ZcliTrinityLighthouseCrosslinks",
blockPath: "testdata/minimal/crosslink_mismatch/block.ssz",
preStatePath: "testdata/minimal/crosslink_mismatch/pre.ssz",
postStatePath: "testdata/minimal/crosslink_mismatch/post.ssz",
},
}
for _, test := range tests {
t.Run(test.name, func(tt *testing.T) {
block := &ethpb.BeaconBlock{}
pre := &pb.BeaconState{}
post := &pb.BeaconState{}
params.UseMinimalConfig()
loadSszOrDie(t, test.blockPath, block)
loadSszOrDie(t, test.preStatePath, pre)
loadSszOrDie(t, test.postStatePath, post)
result, err := ExecuteStateTransition(context.Background(), pre, block)
if err != nil {
t.Logf("Could not process state transition %v", err)
}
if !ssz.DeepEqual(result, post) {
diff, _ := messagediff.PrettyDiff(result, post)
t.Log(diff)
t.Fatal("Resulting state is not equal to expected post state")
}
})
}
}
func loadSszOrDie(t *testing.T, filepath string, dst interface{}) {
b, err := ioutil.ReadFile(filepath)
if err != nil {
t.Fatal(err)
}
if err := ssz.Unmarshal(b, dst); err != nil {
t.Fatal(err)
}
}

View File

@@ -7,7 +7,6 @@ import (
"github.com/pkg/errors"
"github.com/prysmaticlabs/go-ssz"
b "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/mathutil"
@@ -26,6 +25,7 @@ import (
// genesis_time=eth1_timestamp - eth1_timestamp % SECONDS_PER_DAY + 2 * SECONDS_PER_DAY,
// eth1_data=Eth1Data(block_hash=eth1_block_hash, deposit_count=len(deposits)),
// latest_block_header=BeaconBlockHeader(body_root=hash_tree_root(BeaconBlockBody())),
// randao_mixes=[eth1_block_hash] * EPOCHS_PER_HISTORICAL_VECTOR, # Seed RANDAO with Eth1 entropy
// )
//
// # Process deposits
@@ -52,9 +52,15 @@ import (
// state.compact_committees_roots[index] = committee_root
// return state
func GenesisBeaconState(deposits []*ethpb.Deposit, genesisTime uint64, eth1Data *ethpb.Eth1Data) (*pb.BeaconState, error) {
if eth1Data == nil {
return nil, errors.New("no eth1data provided for genesis state")
}
randaoMixes := make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector)
for i := 0; i < len(randaoMixes); i++ {
randaoMixes[i] = make([]byte, 32)
h := make([]byte, 32)
copy(h, eth1Data.BlockHash)
randaoMixes[i] = h
}
zeroHash := params.BeaconConfig().ZeroHash[:]
@@ -64,16 +70,6 @@ func GenesisBeaconState(deposits []*ethpb.Deposit, genesisTime uint64, eth1Data
activeIndexRoots[i] = zeroHash
}
compactRoots := make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector)
crosslinks := make([]*ethpb.Crosslink, params.BeaconConfig().ShardCount)
for i := 0; i < len(crosslinks); i++ {
crosslinks[i] = &ethpb.Crosslink{
ParentRoot: make([]byte, 32),
DataRoot: make([]byte, 32),
}
}
blockRoots := make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot)
for i := 0; i < len(blockRoots); i++ {
blockRoots[i] = zeroHash
@@ -86,10 +82,6 @@ func GenesisBeaconState(deposits []*ethpb.Deposit, genesisTime uint64, eth1Data
slashings := make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector)
if eth1Data == nil {
return nil, errors.New("no eth1data provided for genesis state")
}
eth1Data.DepositCount = uint64(len(deposits))
state := &pb.BeaconState{
@@ -125,11 +117,6 @@ func GenesisBeaconState(deposits []*ethpb.Deposit, genesisTime uint64, eth1Data
Root: params.BeaconConfig().ZeroHash[:],
},
// Recent state.
CurrentCrosslinks: crosslinks,
PreviousCrosslinks: crosslinks,
ActiveIndexRoots: activeIndexRoots,
CompactCommitteesRoots: compactRoots,
HistoricalRoots: [][]byte{},
BlockRoots: blockRoots,
StateRoots: stateRoots,
@@ -197,23 +184,6 @@ func GenesisBeaconState(deposits []*ethpb.Deposit, genesisTime uint64, eth1Data
}
}
// Populate latest_active_index_roots
activeIndices, err := helpers.ActiveValidatorIndices(state, 0)
if err != nil {
return nil, errors.Wrap(err, "could not get active validator indices")
}
genesisActiveIndexRoot, err := ssz.HashTreeRootWithCapacity(activeIndices, params.BeaconConfig().ValidatorRegistryLimit)
if err != nil {
return nil, errors.Wrap(err, "could not hash tree root active indices")
}
genesisCompactCommRoot, err := helpers.CompactCommitteesRoot(state, 0)
if err != nil {
return nil, errors.Wrap(err, "could not get compact committee root")
}
for i := uint64(0); i < params.BeaconConfig().EpochsPerHistoricalVector; i++ {
state.ActiveIndexRoots[i] = genesisActiveIndexRoot[:]
state.CompactCommitteesRoots[i] = genesisCompactCommRoot[:]
}
return state, nil
}

View File

@@ -5,7 +5,6 @@ import (
"reflect"
"testing"
"github.com/prysmaticlabs/go-ssz"
"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"
@@ -16,10 +15,6 @@ import (
)
func TestGenesisBeaconState_OK(t *testing.T) {
if params.BeaconConfig().SlotsPerEpoch != 64 {
t.Errorf("SlotsPerEpoch should be 64 for these tests to pass")
}
genesisEpochNumber := uint64(0)
if !bytes.Equal(params.BeaconConfig().GenesisForkVersion, []byte{0, 0, 0, 0}) {
@@ -36,11 +31,6 @@ func TestGenesisBeaconState_OK(t *testing.T) {
}
latestRandaoMixesLength := int(params.BeaconConfig().EpochsPerHistoricalVector)
if params.BeaconConfig().ShardCount != 1024 {
t.Error("ShardCount should be 1024 for these tests to pass")
}
shardCount := int(params.BeaconConfig().ShardCount)
if params.BeaconConfig().HistoricalRootsLimit != 16777216 {
t.Error("HistoricalRootsLimit should be 16777216 for these tests to pass")
}
@@ -54,11 +44,7 @@ func TestGenesisBeaconState_OK(t *testing.T) {
genesisTime := uint64(99999)
deposits, _, _ := testutil.SetupInitialDeposits(t, uint64(depositsForChainStart))
eth1Data := testutil.GenerateEth1Data(t, deposits)
newState, err := state.GenesisBeaconState(
deposits,
genesisTime,
eth1Data,
)
newState, err := state.GenesisBeaconState(deposits, genesisTime, eth1Data)
if err != nil {
t.Fatalf("could not execute GenesisBeaconState: %v", err)
}
@@ -93,7 +79,7 @@ func TestGenesisBeaconState_OK(t *testing.T) {
if len(newState.RandaoMixes) != latestRandaoMixesLength {
t.Error("Length of RandaoMixes was not correctly initialized")
}
if !bytes.Equal(newState.RandaoMixes[0], make([]byte, 32)) {
if !bytes.Equal(newState.RandaoMixes[0], eth1Data.BlockHash) {
t.Error("RandaoMixes was not correctly initialized")
}
@@ -112,12 +98,6 @@ func TestGenesisBeaconState_OK(t *testing.T) {
}
// Recent state checks.
if len(newState.CurrentCrosslinks) != shardCount {
t.Error("Length of CurrentCrosslinks was not correctly initialized")
}
if len(newState.PreviousCrosslinks) != shardCount {
t.Error("Length of PreviousCrosslinks was not correctly initialized")
}
if !reflect.DeepEqual(newState.Slashings, make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector)) {
t.Error("Slashings was not correctly initialized")
}
@@ -128,32 +108,11 @@ func TestGenesisBeaconState_OK(t *testing.T) {
t.Error("PreviousEpochAttestations was not correctly initialized")
}
activeValidators, _ := helpers.ActiveValidatorIndices(newState, 0)
genesisActiveIndexRoot, err := ssz.HashTreeRootWithCapacity(activeValidators, params.BeaconConfig().ValidatorRegistryLimit)
if err != nil {
t.Errorf("could not hash tree root: %v", err)
}
if !bytes.Equal(newState.ActiveIndexRoots[0], genesisActiveIndexRoot[:]) {
t.Errorf(
"Expected index roots to be the tree hash root of active validator indices, received %#x",
newState.ActiveIndexRoots[0],
)
}
if !bytes.Equal(newState.ActiveIndexRoots[0], genesisActiveIndexRoot[:]) {
t.Errorf(
"Expected index roots to be the tree hash root of active validator indices, received %#x",
newState.ActiveIndexRoots[0],
)
}
zeroHash := params.BeaconConfig().ZeroHash[:]
// History root checks.
if !bytes.Equal(newState.StateRoots[0], zeroHash) {
t.Error("StateRoots was not correctly initialized")
}
if bytes.Equal(newState.ActiveIndexRoots[0], zeroHash) || bytes.Equal(newState.ActiveIndexRoots[0], []byte{}) {
t.Error("ActiveIndexRoots was not correctly initialized")
}
if !bytes.Equal(newState.BlockRoots[0], zeroHash) {
t.Error("BlockRoots was not correctly initialized")
}
@@ -170,11 +129,11 @@ func TestGenesisBeaconState_OK(t *testing.T) {
func TestGenesisState_HashEquality(t *testing.T) {
helpers.ClearAllCaches()
deposits, _, _ := testutil.SetupInitialDeposits(t, 100)
state1, err := state.GenesisBeaconState(deposits, 0, &ethpb.Eth1Data{})
state1, err := state.GenesisBeaconState(deposits, 0, &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Error(err)
}
state2, err := state.GenesisBeaconState(deposits, 0, &ethpb.Eth1Data{})
state2, err := state.GenesisBeaconState(deposits, 0, &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Error(err)
}

View File

@@ -19,7 +19,6 @@ import (
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/featureconfig"
"github.com/prysmaticlabs/prysm/shared/hashutil"
"github.com/prysmaticlabs/prysm/shared/mathutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/traceutil"
@@ -62,7 +61,7 @@ func ExecuteStateTransition(
if block != nil {
state, err = ProcessBlock(ctx, state, block)
if err != nil {
return nil, errors.Wrap(err, "could not process block")
return nil, errors.Wrapf(err, "could not process block in slot %d", block.Slot)
}
}
@@ -445,19 +444,6 @@ func ProcessOperations(
return nil, errors.Wrap(err, "could not verify operation lengths")
}
// Verify that there are no duplicate transfers
transferSet := make(map[[32]byte]bool)
for _, transfer := range body.Transfers {
h, err := hashutil.HashProto(transfer)
if err != nil {
return nil, errors.Wrap(err, "could not hash transfer")
}
if transferSet[h] {
return nil, fmt.Errorf("duplicate transfer: %v", transfer)
}
transferSet[h] = true
}
state, err := b.ProcessProposerSlashings(ctx, state, body)
if err != nil {
return nil, errors.Wrap(err, "could not process block proposer slashings")
@@ -478,10 +464,6 @@ func ProcessOperations(
if err != nil {
return nil, errors.Wrap(err, "could not process validator exits")
}
state, err = b.ProcessTransfers(state, body)
if err != nil {
return nil, errors.Wrap(err, "could not process block transfers")
}
return state, nil
}
@@ -522,19 +504,6 @@ func processOperationsNoVerify(
return nil, errors.Wrap(err, "could not verify operation lengths")
}
// Verify that there are no duplicate transfers
transferSet := make(map[[32]byte]bool)
for _, transfer := range body.Transfers {
h, err := hashutil.HashProto(transfer)
if err != nil {
return nil, errors.Wrap(err, "could not hash transfer")
}
if transferSet[h] {
return nil, fmt.Errorf("duplicate transfer: %v", transfer)
}
transferSet[h] = true
}
state, err := b.ProcessProposerSlashings(ctx, state, body)
if err != nil {
return nil, errors.Wrap(err, "could not process block proposer slashings")
@@ -555,10 +524,6 @@ func processOperationsNoVerify(
if err != nil {
return nil, errors.Wrap(err, "could not process validator exits")
}
state, err = b.ProcessTransfers(state, body)
if err != nil {
return nil, errors.Wrap(err, "could not process block transfers")
}
return state, nil
}
@@ -596,14 +561,6 @@ func verifyOperationLengths(state *pb.BeaconState, body *ethpb.BeaconBlockBody)
)
}
if uint64(len(body.Transfers)) > params.BeaconConfig().MaxTransfers {
return fmt.Errorf(
"number of transfers (%d) in block body exceeds allowed threshold of %d",
len(body.Transfers),
params.BeaconConfig().MaxTransfers,
)
}
if state.Eth1DepositIndex > state.Eth1Data.DepositCount {
return fmt.Errorf("expected state.deposit_index %d <= eth1data.deposit_count %d", state.Eth1DepositIndex, state.Eth1Data.DepositCount)
}
@@ -670,11 +627,6 @@ func ProcessEpoch(ctx context.Context, state *pb.BeaconState) (*pb.BeaconState,
return nil, errors.Wrap(err, "could not process justification")
}
state, err = e.ProcessCrosslinks(state)
if err != nil {
return nil, errors.Wrap(err, "could not process crosslink")
}
state, err = e.ProcessRewardsAndPenalties(state)
if err != nil {
return nil, errors.Wrap(err, "could not process rewards and penalties")
@@ -715,11 +667,6 @@ func ProcessEpochPrecompute(ctx context.Context, state *pb.BeaconState) (*pb.Bea
return nil, errors.Wrap(err, "could not process justification")
}
state, err = e.ProcessCrosslinks(state)
if err != nil {
return nil, errors.Wrap(err, "could not process crosslink")
}
state, err = precompute.ProcessRewardsAndPenaltiesPrecompute(state, bp, vp)
if err != nil {
return nil, errors.Wrap(err, "could not process rewards and penalties")

View File

@@ -40,7 +40,7 @@ func TestExecuteStateTransition_IncorrectSlot(t *testing.T) {
func TestExecuteStateTransition_FullProcess(t *testing.T) {
helpers.ClearAllCaches()
deposits, _, privKeys := testutil.SetupInitialDeposits(t, 100)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{})
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Fatal(err)
}
@@ -54,7 +54,6 @@ func TestExecuteStateTransition_FullProcess(t *testing.T) {
beaconState.Eth1DataVotes = []*ethpb.Eth1Data{eth1Data}
oldMix := beaconState.RandaoMixes[1]
oldStartShard := beaconState.StartShard
parentRoot, err := ssz.SigningRoot(beaconState.LatestBlockHeader)
if err != nil {
t.Error(err)
@@ -93,23 +92,19 @@ func TestExecuteStateTransition_FullProcess(t *testing.T) {
t.Error(err)
}
if beaconState.Slot != 64 {
if beaconState.Slot != params.BeaconConfig().SlotsPerEpoch {
t.Errorf("Unexpected Slot number, expected: 64, received: %d", beaconState.Slot)
}
if bytes.Equal(beaconState.RandaoMixes[1], oldMix) {
t.Errorf("Did not expect new and old randao mix to equal, %#x == %#x", beaconState.RandaoMixes[0], oldMix)
}
if beaconState.StartShard == oldStartShard {
t.Errorf("Did not expect new and old start shard to equal, %#x == %#x", beaconState.StartShard, oldStartShard)
}
}
func TestProcessBlock_IncorrectProposerSlashing(t *testing.T) {
helpers.ClearAllCaches()
deposits, _, privKeys := testutil.SetupInitialDeposits(t, 100)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{})
deposits, _, privKeys := testutil.SetupInitialDeposits(t, 34)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Fatal(err)
}
@@ -164,7 +159,7 @@ func TestProcessBlock_IncorrectProposerSlashing(t *testing.T) {
func TestProcessBlock_IncorrectProcessBlockAttestations(t *testing.T) {
deposits, _, privKeys := testutil.SetupInitialDeposits(t, 100)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{})
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Fatal(err)
}
@@ -208,9 +203,6 @@ func TestProcessBlock_IncorrectProcessBlockAttestations(t *testing.T) {
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0},
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{
Shard: 4,
},
},
CustodyBit_0Indices: []uint64{0, 1},
}
@@ -222,7 +214,7 @@ func TestProcessBlock_IncorrectProcessBlockAttestations(t *testing.T) {
if err != nil {
t.Error(err)
}
domain = helpers.Domain(beaconState.Fork, currentEpoch, params.BeaconConfig().DomainAttestation)
domain = helpers.Domain(beaconState.Fork, currentEpoch, params.BeaconConfig().DomainBeaconAttester)
sig0 := privKeys[0].Sign(hashTreeRoot[:], domain)
sig1 := privKeys[1].Sign(hashTreeRoot[:], domain)
aggregateSig := bls.AggregateSignatures([]*bls.Signature{sig0, sig1})
@@ -232,9 +224,6 @@ func TestProcessBlock_IncorrectProcessBlockAttestations(t *testing.T) {
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 1},
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{
Shard: 4,
},
},
CustodyBit_0Indices: []uint64{0, 1},
}
@@ -260,8 +249,7 @@ func TestProcessBlock_IncorrectProcessBlockAttestations(t *testing.T) {
att := &ethpb.Attestation{
Data: &ethpb.AttestationData{
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{},
Target: &ethpb.Checkpoint{Epoch: 0},
},
AggregationBits: bitfield.NewBitlist(0),
CustodyBits: bitfield.NewBitlist(0),
@@ -315,7 +303,7 @@ func TestProcessBlock_IncorrectProcessExits(t *testing.T) {
helpers.ClearAllCaches()
deposits, _, _ := testutil.SetupInitialDeposits(t, 100)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{})
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Fatal(err)
}
@@ -339,18 +327,14 @@ func TestProcessBlock_IncorrectProcessExits(t *testing.T) {
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0},
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{
Shard: 4,
}},
},
CustodyBit_0Indices: []uint64{0, 1},
},
Attestation_2: &ethpb.IndexedAttestation{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 1},
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{
Shard: 4,
}},
},
CustodyBit_0Indices: []uint64{0, 1},
},
},
@@ -360,19 +344,10 @@ func TestProcessBlock_IncorrectProcessExits(t *testing.T) {
blockRoots = append(blockRoots, []byte{byte(i)})
}
beaconState.BlockRoots = blockRoots
beaconState.CurrentCrosslinks = []*ethpb.Crosslink{
{
DataRoot: []byte{1},
},
}
blockAtt := &ethpb.Attestation{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0},
Target: &ethpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
Crosslink: &ethpb.Crosslink{
Shard: 0,
StartEpoch: 0,
},
},
AggregationBits: bitfield.Bitlist{0xC0, 0xC0, 0xC0, 0xC0, 0x01},
CustodyBits: bitfield.Bitlist{0x00, 0x00, 0x00, 0x00, 0x01},
@@ -412,29 +387,16 @@ func TestProcessBlock_IncorrectProcessExits(t *testing.T) {
},
}
beaconState.Slot += params.BeaconConfig().MinAttestationInclusionDelay
beaconState.CurrentCrosslinks = []*ethpb.Crosslink{
{
Shard: 0,
StartEpoch: 0,
},
}
beaconState.CurrentJustifiedCheckpoint.Root = []byte("hello-world")
beaconState.CurrentEpochAttestations = []*pb.PendingAttestation{}
encoded, err := ssz.HashTreeRoot(beaconState.CurrentCrosslinks[0])
if err != nil {
t.Fatal(err)
}
block.Body.Attestations[0].Data.Crosslink.ParentRoot = encoded[:]
block.Body.Attestations[0].Data.Crosslink.DataRoot = params.BeaconConfig().ZeroHash[:]
if _, err := state.ProcessBlock(context.Background(), beaconState, block); err == nil {
t.Error("Expected err, received nil")
}
}
func TestProcessBlock_PassesProcessingConditions(t *testing.T) {
deposits, _, privKeys := testutil.SetupInitialDeposits(t, 100)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{})
deposits, _, privKeys := testutil.SetupInitialDeposits(t, 32)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Fatal(err)
}
@@ -449,19 +411,8 @@ func TestProcessBlock_PassesProcessingConditions(t *testing.T) {
BodyRoot: bodyRoot[:],
}
beaconState.Slashings = make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector)
beaconState.CurrentCrosslinks = []*ethpb.Crosslink{
{
Shard: 0,
StartEpoch: helpers.SlotToEpoch(beaconState.Slot),
DataRoot: []byte{1},
},
}
beaconState.CurrentJustifiedCheckpoint.Root = []byte("hello-world")
beaconState.CurrentEpochAttestations = []*pb.PendingAttestation{}
encoded, err := ssz.HashTreeRoot(beaconState.CurrentCrosslinks[0])
if err != nil {
t.Fatal(err)
}
proposerSlashIdx := uint64(3)
slotsPerEpoch := params.BeaconConfig().SlotsPerEpoch
@@ -506,11 +457,7 @@ func TestProcessBlock_PassesProcessingConditions(t *testing.T) {
att1 := &ethpb.IndexedAttestation{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0, Root: []byte{'A'}},
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{
Shard: 4,
},
},
Target: &ethpb.Checkpoint{Epoch: 0}},
CustodyBit_0Indices: []uint64{0, 1},
}
dataAndCustodyBit := &pb.AttestationDataAndCustodyBit{
@@ -521,7 +468,7 @@ func TestProcessBlock_PassesProcessingConditions(t *testing.T) {
if err != nil {
t.Error(err)
}
domain = helpers.Domain(beaconState.Fork, currentEpoch, params.BeaconConfig().DomainAttestation)
domain = helpers.Domain(beaconState.Fork, currentEpoch, params.BeaconConfig().DomainBeaconAttester)
sig0 := privKeys[0].Sign(hashTreeRoot[:], domain)
sig1 := privKeys[1].Sign(hashTreeRoot[:], domain)
aggregateSig := bls.AggregateSignatures([]*bls.Signature{sig0, sig1})
@@ -530,11 +477,7 @@ func TestProcessBlock_PassesProcessingConditions(t *testing.T) {
att2 := &ethpb.IndexedAttestation{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0, Root: []byte{'B'}},
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{
Shard: 4,
},
},
Target: &ethpb.Checkpoint{Epoch: 0}},
CustodyBit_0Indices: []uint64{0, 1},
}
dataAndCustodyBit = &pb.AttestationDataAndCustodyBit{
@@ -568,18 +511,12 @@ func TestProcessBlock_PassesProcessingConditions(t *testing.T) {
custodyBits := bitfield.NewBitlist(1)
blockAtt := &ethpb.Attestation{
Data: &ethpb.AttestationData{
Slot: beaconState.Slot - 1,
Target: &ethpb.Checkpoint{Epoch: helpers.SlotToEpoch(beaconState.Slot)},
Source: &ethpb.Checkpoint{
Epoch: 0,
Root: []byte("hello-world"),
},
Crosslink: &ethpb.Crosslink{
Shard: 0,
EndEpoch: 64,
DataRoot: params.BeaconConfig().ZeroHash[:],
ParentRoot: encoded[:],
},
},
}},
AggregationBits: aggBits,
CustodyBits: custodyBits,
}
@@ -674,12 +611,11 @@ func TestProcessEpoch_CantGetTgtAttsPrevEpoch(t *testing.T) {
func TestProcessEpoch_CantGetTgtAttsCurrEpoch(t *testing.T) {
epoch := uint64(1)
atts := []*pb.PendingAttestation{{Data: &ethpb.AttestationData{Crosslink: &ethpb.Crosslink{Shard: 100}}}}
atts := []*pb.PendingAttestation{{Data: &ethpb.AttestationData{}}}
_, err := state.ProcessEpoch(context.Background(), &pb.BeaconState{
Slot: epoch * params.BeaconConfig().SlotsPerEpoch,
BlockRoots: make([][]byte, 128),
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
CurrentEpochAttestations: atts})
if !strings.Contains(err.Error(), "could not get target atts current epoch") {
t.Fatal("Did not receive wanted error")
@@ -690,22 +626,12 @@ func TestProcessEpoch_CanProcess(t *testing.T) {
helpers.ClearAllCaches()
epoch := uint64(1)
atts := []*pb.PendingAttestation{{Data: &ethpb.AttestationData{Crosslink: &ethpb.Crosslink{Shard: 0}, Target: &ethpb.Checkpoint{}}}}
var crosslinks []*ethpb.Crosslink
for i := uint64(0); i < params.BeaconConfig().ShardCount; i++ {
crosslinks = append(crosslinks, &ethpb.Crosslink{
StartEpoch: 0,
DataRoot: []byte{'A'},
})
}
atts := []*pb.PendingAttestation{{Data: &ethpb.AttestationData{Target: &ethpb.Checkpoint{}}}}
newState, err := state.ProcessEpoch(context.Background(), &pb.BeaconState{
Slot: epoch*params.BeaconConfig().SlotsPerEpoch + 1,
BlockRoots: make([][]byte, 128),
Slashings: []uint64{0, 1e9, 1e9},
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
CompactCommitteesRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
CurrentCrosslinks: crosslinks,
CurrentEpochAttestations: atts,
FinalizedCheckpoint: &ethpb.Checkpoint{},
JustificationBits: bitfield.Bitvector4{0x00},
@@ -725,22 +651,13 @@ func TestProcessEpochPrecompute_CanProcess(t *testing.T) {
helpers.ClearAllCaches()
epoch := uint64(1)
atts := []*pb.PendingAttestation{{Data: &ethpb.AttestationData{Crosslink: &ethpb.Crosslink{Shard: 0}, Target: &ethpb.Checkpoint{}}}}
var crosslinks []*ethpb.Crosslink
for i := uint64(0); i < params.BeaconConfig().ShardCount; i++ {
crosslinks = append(crosslinks, &ethpb.Crosslink{
StartEpoch: 0,
DataRoot: []byte{'A'},
})
}
atts := []*pb.PendingAttestation{{Data: &ethpb.AttestationData{Target: &ethpb.Checkpoint{}}}}
newState, err := state.ProcessEpochPrecompute(context.Background(), &pb.BeaconState{
Slot: epoch*params.BeaconConfig().SlotsPerEpoch + 1,
BlockRoots: make([][]byte, 128),
Slashings: []uint64{0, 1e9, 1e9},
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
CompactCommitteesRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
CurrentCrosslinks: crosslinks,
CurrentEpochAttestations: atts,
FinalizedCheckpoint: &ethpb.Checkpoint{},
JustificationBits: bitfield.Bitvector4{0x00},
@@ -758,9 +675,8 @@ func TestProcessEpochPrecompute_CanProcess(t *testing.T) {
func TestProcessEpoch_NotPanicOnEmptyActiveValidatorIndices(t *testing.T) {
newState := &pb.BeaconState{
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
Slashings: make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector),
RandaoMixes: make([][]byte, params.BeaconConfig().SlotsPerEpoch),
Slashings: make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector),
RandaoMixes: make([][]byte, params.BeaconConfig().SlotsPerEpoch),
}
state.ProcessEpoch(context.Background(), newState)
@@ -773,7 +689,7 @@ func BenchmarkProcessEpoch65536Validators(b *testing.B) {
epoch := uint64(1)
validatorCount := params.BeaconConfig().MinGenesisActiveValidatorCount * 4
shardCount := validatorCount / params.BeaconConfig().TargetCommitteeSize
comitteeCount := validatorCount / params.BeaconConfig().TargetCommitteeSize
validators := make([]*ethpb.Validator, validatorCount)
balances := make([]uint64, validatorCount)
@@ -786,44 +702,29 @@ func BenchmarkProcessEpoch65536Validators(b *testing.B) {
}
var atts []*pb.PendingAttestation
for i := uint64(0); i < shardCount; i++ {
for i := uint64(0); i < comitteeCount; i++ {
atts = append(atts, &pb.PendingAttestation{
Data: &ethpb.AttestationData{
Crosslink: &ethpb.Crosslink{
Shard: i,
},
},
Data: &ethpb.AttestationData{},
AggregationBits: []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
InclusionDelay: 1,
})
}
var crosslinks []*ethpb.Crosslink
for i := uint64(0); i < params.BeaconConfig().ShardCount; i++ {
crosslinks = append(crosslinks, &ethpb.Crosslink{
StartEpoch: 0,
DataRoot: []byte{'A'},
})
}
s := &pb.BeaconState{
Slot: epoch*params.BeaconConfig().SlotsPerEpoch + 1,
Validators: validators,
Balances: balances,
StartShard: 512,
FinalizedCheckpoint: &ethpb.Checkpoint{},
BlockRoots: make([][]byte, 254),
Slashings: []uint64{0, 1e9, 0},
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
CurrentCrosslinks: crosslinks,
PreviousEpochAttestations: atts,
}
// Precache the shuffled indices
for i := uint64(0); i < shardCount; i++ {
if _, err := helpers.CrosslinkCommittee(s, 0, i); err != nil {
for i := uint64(0); i < comitteeCount; i++ {
if _, err := helpers.BeaconCommittee(s, 0, i); err != nil {
b.Fatal(err)
}
}
@@ -840,11 +741,9 @@ func BenchmarkProcessEpoch65536Validators(b *testing.B) {
func BenchmarkProcessBlk_65536Validators_FullBlock(b *testing.B) {
logrus.SetLevel(logrus.PanicLevel)
helpers.ClearAllCaches()
testConfig := params.BeaconConfig()
testConfig.MaxTransfers = 1
validatorCount := params.BeaconConfig().MinGenesisActiveValidatorCount * 4
shardCount := validatorCount / params.BeaconConfig().TargetCommitteeSize
committeeCount := validatorCount / params.BeaconConfig().TargetCommitteeSize
validators := make([]*ethpb.Validator, validatorCount)
for i := 0; i < len(validators); i++ {
validators[i] = &ethpb.Validator{
@@ -864,14 +763,6 @@ func BenchmarkProcessBlk_65536Validators_FullBlock(b *testing.B) {
randaoMixes[i] = params.BeaconConfig().ZeroHash[:]
}
var crosslinks []*ethpb.Crosslink
for i := uint64(0); i < params.BeaconConfig().ShardCount; i++ {
crosslinks = append(crosslinks, &ethpb.Crosslink{
StartEpoch: 0,
DataRoot: []byte{'A'},
})
}
s := &pb.BeaconState{
Slot: 20,
LatestBlockHeader: &ethpb.BeaconBlockHeader{},
@@ -880,7 +771,6 @@ func BenchmarkProcessBlk_65536Validators_FullBlock(b *testing.B) {
Validators: validators,
Balances: validatorBalances,
Slashings: make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
CurrentJustifiedCheckpoint: &ethpb.Checkpoint{
Root: []byte("hello-world"),
},
@@ -888,7 +778,6 @@ func BenchmarkProcessBlk_65536Validators_FullBlock(b *testing.B) {
PreviousVersion: []byte{0, 0, 0, 0},
CurrentVersion: []byte{0, 0, 0, 0},
},
CurrentCrosslinks: crosslinks,
}
// Set up proposer slashing object for block
@@ -910,19 +799,11 @@ func BenchmarkProcessBlk_65536Validators_FullBlock(b *testing.B) {
attesterSlashings := []*ethpb.AttesterSlashing{
{
Attestation_1: &ethpb.IndexedAttestation{
Data: &ethpb.AttestationData{
Crosslink: &ethpb.Crosslink{
Shard: 5,
},
},
Data: &ethpb.AttestationData{},
CustodyBit_0Indices: []uint64{2, 3},
},
Attestation_2: &ethpb.IndexedAttestation{
Data: &ethpb.AttestationData{
Crosslink: &ethpb.Crosslink{
Shard: 5,
},
},
Data: &ethpb.AttestationData{},
CustodyBit_0Indices: []uint64{2, 3},
},
},
@@ -965,40 +846,17 @@ func BenchmarkProcessBlk_65536Validators_FullBlock(b *testing.B) {
domain := helpers.Domain(s.Fork, 0, params.BeaconConfig().DomainRandao)
epochSignature := priv.Sign(buf, domain)
// Set up transfer object for block
transfers := []*ethpb.Transfer{
{
Slot: s.Slot,
SenderIndex: 3,
RecipientIndex: 4,
Fee: params.BeaconConfig().MinDepositAmount,
Amount: params.BeaconConfig().MinDepositAmount,
SenderWithdrawalPublicKey: []byte("A"),
},
}
buf = []byte{params.BeaconConfig().BLSWithdrawalPrefixByte}
pubKey := []byte("A")
hashed := hashutil.Hash(pubKey)
buf = append(buf, hashed[:]...)
s.Validators[3].WithdrawalCredentials = buf
// Set up attestations obj for block.
encoded, err := ssz.HashTreeRoot(s.CurrentCrosslinks[0])
if err != nil {
b.Fatal(err)
}
attestations := make([]*ethpb.Attestation, 128)
for i := 0; i < len(attestations); i++ {
attestations[i] = &ethpb.Attestation{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Root: []byte("hello-world")},
Crosslink: &ethpb.Crosslink{
Shard: uint64(i),
ParentRoot: encoded[:],
DataRoot: params.BeaconConfig().ZeroHash[:],
},
},
Source: &ethpb.Checkpoint{Root: []byte("hello-world")}},
AggregationBits: bitfield.Bitlist{0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,
0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x01},
CustodyBits: bitfield.NewBitlist(0),
@@ -1016,13 +874,12 @@ func BenchmarkProcessBlk_65536Validators_FullBlock(b *testing.B) {
Attestations: attestations,
ProposerSlashings: proposerSlashings,
AttesterSlashings: attesterSlashings,
Transfers: transfers,
},
}
// Precache the shuffled indices
for i := uint64(0); i < shardCount; i++ {
if _, err := helpers.CrosslinkCommittee(s, 0, i); err != nil {
for i := uint64(0); i < committeeCount; i++ {
if _, err := helpers.BeaconCommittee(s, 0, i); err != nil {
b.Fatal(err)
}
}
@@ -1047,7 +904,7 @@ func TestProcessBlk_AttsBasedOnValidatorCount(t *testing.T) {
// Default at 256 validators, can raise this number with faster BLS.
validatorCount := uint64(256)
deposits, _, privKeys := testutil.SetupInitialDeposits(t, validatorCount)
s, _ := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{})
s, _ := state.GenesisBeaconState(deposits, 0, &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
s.Slot = params.BeaconConfig().SlotsPerEpoch
bitCount := validatorCount / params.BeaconConfig().SlotsPerEpoch
@@ -1056,21 +913,13 @@ func TestProcessBlk_AttsBasedOnValidatorCount(t *testing.T) {
for i := uint64(1); i < bitCount; i++ {
aggBits.SetBitAt(i, true)
}
atts := make([]*ethpb.Attestation, 64)
crosslinkRoot, _ := ssz.HashTreeRoot(s.CurrentCrosslinks[0])
atts := make([]*ethpb.Attestation, 1)
for i := 0; i < len(atts); i++ {
att := &ethpb.Attestation{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0, Root: params.BeaconConfig().ZeroHash[:]},
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{
Shard: uint64(i + 960),
StartEpoch: 0,
ParentRoot: crosslinkRoot[:],
DataRoot: params.BeaconConfig().ZeroHash[:],
},
},
Target: &ethpb.Checkpoint{Epoch: 0}},
AggregationBits: aggBits,
CustodyBits: custodyBits,
}
@@ -1082,7 +931,8 @@ func TestProcessBlk_AttsBasedOnValidatorCount(t *testing.T) {
Data: att.Data,
CustodyBit: false,
}
domain := helpers.Domain(s.Fork, 0, params.BeaconConfig().DomainAttestation)
domain := helpers.Domain(s.Fork, 0, params.BeaconConfig().DomainBeaconAttester)
sigs := make([]*bls.Signature, len(attestingIndices))
for i, indice := range attestingIndices {
hashTreeRoot, err := ssz.HashTreeRoot(dataAndCustodyBit)
@@ -1120,10 +970,6 @@ func TestProcessBlk_AttsBasedOnValidatorCount(t *testing.T) {
}
func TestCanProcessEpoch_TrueOnEpochs(t *testing.T) {
if params.BeaconConfig().SlotsPerEpoch != 64 {
t.Errorf("SlotsPerEpoch should be 64 for these tests to pass")
}
tests := []struct {
slot uint64
canProcessEpoch bool
@@ -1216,24 +1062,6 @@ func TestProcessOperations_OverMaxAttestations(t *testing.T) {
}
}
func TestProcessOperations_OverMaxTransfers(t *testing.T) {
block := &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
Transfers: make([]*ethpb.Transfer, params.BeaconConfig().MaxTransfers+1),
},
}
want := fmt.Sprintf("number of transfers (%d) in block body exceeds allowed threshold of %d",
len(block.Body.Transfers), params.BeaconConfig().MaxTransfers)
if _, err := state.ProcessOperations(
context.Background(),
&pb.BeaconState{},
block.Body,
); !strings.Contains(err.Error(), want) {
t.Errorf("Expected %s, received %v", want, err)
}
}
func TestProcessOperation_OverMaxVoluntaryExits(t *testing.T) {
maxExits := params.BeaconConfig().MaxVoluntaryExits
block := &ethpb.BeaconBlock{
@@ -1274,37 +1102,3 @@ func TestProcessOperations_IncorrectDeposits(t *testing.T) {
t.Errorf("Expected %s, received %v", want, err)
}
}
func TestProcessOperation_DuplicateTransfer(t *testing.T) {
testConfig := params.BeaconConfig()
testConfig.MaxTransfers = 2
transfers := []*ethpb.Transfer{
{
Amount: 1,
},
{
Amount: 1,
},
}
registry := []*ethpb.Validator{}
s := &pb.BeaconState{
Validators: registry,
Eth1Data: &ethpb.Eth1Data{DepositCount: 100},
Eth1DepositIndex: 98,
}
block := &ethpb.BeaconBlock{
Body: &ethpb.BeaconBlockBody{
Transfers: transfers,
Deposits: []*ethpb.Deposit{{}, {}},
},
}
want := "duplicate transfer"
if _, err := state.ProcessOperations(
context.Background(),
s,
block.Body,
); !strings.Contains(err.Error(), want) {
t.Errorf("Expected %s, received %v", want, err)
}
}

View File

@@ -113,12 +113,12 @@ func TestSlashValidator_OK(t *testing.T) {
}
bState := &pb.BeaconState{
Validators: registry,
Slot: 0,
Slashings: make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector),
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
Balances: balances,
Validators: registry,
Slot: 0,
Slashings: make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector),
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
Balances: balances,
}
slashedIdx := uint64(2)

View File

@@ -3,15 +3,13 @@
// For example, one can specify a filter query for data by start epoch + end epoch + shard
// for attestations, build a filter as follows, and respond to it accordingly:
//
// f := filters.NewFilter().SetStartEpoch(3).SetEndEpoch(5).SetShard(5)
// f := filters.NewFilter().SetStartEpoch(3).SetEndEpoch(5)
// for k, v := range f.Filters() {
// switch k {
// case filters.StartEpoch:
// // Verify data matches filter criteria...
// case filters.EndEpoch:
// // Verify data matches filter criteria...
// case filters.Shard:
// // Verify data matches filter criteria...
// }
// }
package filters
@@ -31,18 +29,16 @@ const (
StartEpoch FilterType = 3
// EndEpoch is used for range filters of objects by their epoch (inclusive).
EndEpoch FilterType = 4
// Shard is used for filtering data by shard index.
Shard FilterType = 5
// HeadBlockRoot defines a filter for the head block root attribute of objects.
HeadBlockRoot FilterType = 6
HeadBlockRoot FilterType = 5
// SourceEpoch defines a filter for the source epoch attribute of objects.
SourceEpoch FilterType = 7
SourceEpoch FilterType = 6
// SourceRoot defines a filter for the source root attribute of objects.
SourceRoot FilterType = 8
SourceRoot FilterType = 7
// TargetEpoch defines a filter for the target epoch attribute of objects.
TargetEpoch FilterType = 9
TargetEpoch FilterType = 8
// TargetRoot defines a filter for the target root attribute of objects.
TargetRoot FilterType = 10
TargetRoot FilterType = 9
)
// QueryFilter defines a generic interface for type-asserting
@@ -125,9 +121,3 @@ func (q *QueryFilter) SetEndEpoch(val uint64) *QueryFilter {
q.queries[EndEpoch] = val
return q
}
// SetShard enabled filtering by the Shard attribute of an object.
func (q *QueryFilter) SetShard(val uint64) *QueryFilter {
q.queries[Shard] = val
return q
}

View File

@@ -8,11 +8,11 @@ func TestQueryFilter_ChainsCorrectly(t *testing.T) {
f := NewFilter().
SetStartSlot(2).
SetEndSlot(4).
SetParentRoot([]byte{3, 4, 5}).
SetShard(0)
SetParentRoot([]byte{3, 4, 5})
filterSet := f.Filters()
if len(filterSet) != 4 {
t.Errorf("Expected 4 filters to have been set, received %d", len(filterSet))
if len(filterSet) != 3 {
t.Errorf("Expected 3 filters to have been set, received %d", len(filterSet))
}
for k, v := range filterSet {
switch k {
@@ -22,8 +22,6 @@ func TestQueryFilter_ChainsCorrectly(t *testing.T) {
t.Log(v.(uint64))
case ParentRoot:
t.Log(v.([]byte))
case Shard:
t.Log(v.(uint64))
default:
t.Log("Unknown filter type")
}

View File

@@ -67,13 +67,6 @@ func TestStore_ArchivedActiveValidatorChanges(t *testing.T) {
Epoch: 5,
Root: someRoot[:],
},
Crosslink: &ethpb.Crosslink{
Shard: 3,
ParentRoot: someRoot[:],
StartEpoch: 3,
EndEpoch: 4,
DataRoot: someRoot[:],
},
},
},
Attestation_2: &ethpb.IndexedAttestation{
@@ -87,13 +80,6 @@ func TestStore_ArchivedActiveValidatorChanges(t *testing.T) {
Epoch: 5,
Root: someRoot[:],
},
Crosslink: &ethpb.Crosslink{
Shard: 3,
ParentRoot: someRoot[:],
StartEpoch: 3,
EndEpoch: 4,
DataRoot: someRoot[:],
},
},
},
},
@@ -118,8 +104,8 @@ func TestStore_ArchivedCommitteeInfo(t *testing.T) {
ctx := context.Background()
someSeed := [32]byte{1, 2, 3}
info := &ethpb.ArchivedCommitteeInfo{
Seed: someSeed[:],
StartShard: 10,
ProposerSeed: someSeed[:],
AttesterSeed: someSeed[:],
CommitteeCount: 4096,
}
epoch := uint64(10)

View File

@@ -19,14 +19,7 @@ func TestStore_AttestationCRUD(t *testing.T) {
db := setupDB(t)
defer teardownDB(t, db)
att := &ethpb.Attestation{
Data: &ethpb.AttestationData{
Crosslink: &ethpb.Crosslink{
Shard: 5,
ParentRoot: []byte("parent"),
StartEpoch: 1,
EndEpoch: 2,
},
},
Data: &ethpb.AttestationData{Slot: 10},
AggregationBits: bitfield.Bitlist{0b00000001, 0b1},
CustodyBits: bitfield.NewBitlist(8),
}
@@ -76,12 +69,7 @@ func TestStore_AttestationsBatchDelete(t *testing.T) {
totalAtts[i] = &ethpb.Attestation{
Data: &ethpb.AttestationData{
BeaconBlockRoot: []byte("head"),
Crosslink: &ethpb.Crosslink{
Shard: uint64(i),
ParentRoot: []byte("parent"),
StartEpoch: 1,
EndEpoch: 2,
},
Slot: uint64(i),
},
AggregationBits: bitfield.Bitlist{0b00000001, 0b1},
CustodyBits: bitfield.NewBitlist(8),
@@ -116,7 +104,7 @@ func TestStore_AttestationsBatchDelete(t *testing.T) {
t.Fatal(err)
}
sort.Slice(retrieved, func(i, j int) bool {
return retrieved[i].Data.Crosslink.Shard < retrieved[j].Data.Crosslink.Shard
return retrieved[i].Data.Slot < retrieved[j].Data.Slot
})
if !reflect.DeepEqual(retrieved, oddAtts) {
t.Errorf("Wanted %v, received %v", oddAtts, retrieved)
@@ -130,14 +118,7 @@ func TestStore_BoltDontPanic(t *testing.T) {
for i := 0; i <= 100; i++ {
att := &ethpb.Attestation{
Data: &ethpb.AttestationData{
Crosslink: &ethpb.Crosslink{
Shard: 5,
ParentRoot: []byte("parent"),
StartEpoch: uint64(i + 1),
EndEpoch: 2,
},
},
Data: &ethpb.AttestationData{Slot: uint64(i)},
AggregationBits: bitfield.Bitlist{0b11},
}
ctx := context.Background()
@@ -162,14 +143,7 @@ func TestStore_BoltDontPanic(t *testing.T) {
wg.Add(1)
go func() {
att := &ethpb.Attestation{
Data: &ethpb.AttestationData{
Crosslink: &ethpb.Crosslink{
Shard: 5,
ParentRoot: []byte("parent"),
StartEpoch: uint64(startEpoch),
EndEpoch: 2,
},
},
Data: &ethpb.AttestationData{Slot: uint64(startEpoch)},
AggregationBits: bitfield.Bitlist{0b11},
}
ctx := context.Background()
@@ -292,14 +266,7 @@ func TestStore_Attestations_FiltersCorrectly(t *testing.T) {
}
func TestStore_Attestations_BitfieldLogic(t *testing.T) {
commonData := &ethpb.AttestationData{
Crosslink: &ethpb.Crosslink{
Shard: 5,
ParentRoot: []byte("parent"),
StartEpoch: 1,
EndEpoch: 2,
},
}
commonData := &ethpb.AttestationData{Slot: 10}
tests := []struct {
name string

View File

@@ -56,17 +56,13 @@ func TestStore_AttesterSlashing_CRUD(t *testing.T) {
Attestation_1: &ethpb.IndexedAttestation{
Data: &ethpb.AttestationData{
BeaconBlockRoot: make([]byte, 32),
Crosslink: &ethpb.Crosslink{
Shard: 5,
},
Slot: 5,
},
},
Attestation_2: &ethpb.IndexedAttestation{
Data: &ethpb.AttestationData{
BeaconBlockRoot: make([]byte, 32),
Crosslink: &ethpb.Crosslink{
Shard: 7,
},
Slot: 7,
},
},
}

View File

@@ -46,6 +46,7 @@ func (g *Gateway) Start() {
}
g.conn = conn
gwmux := gwruntime.NewServeMux(gwruntime.WithMarshalerOption(gwruntime.MIMEWildcard, &gwruntime.JSONPb{OrigName: false}))
for _, f := range []func(context.Context, *gwruntime.ServeMux, *grpc.ClientConn) error{
ethpb.RegisterNodeHandler,

View File

@@ -30,7 +30,7 @@ func TestHandleAttestation_Saves_NewAttestation(t *testing.T) {
})
deposits, _, privKeys := testutil.SetupInitialDeposits(t, 100)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{})
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Fatal(err)
}
@@ -40,10 +40,6 @@ func TestHandleAttestation_Saves_NewAttestation(t *testing.T) {
BeaconBlockRoot: []byte("block-root"),
Source: &ethpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
Target: &ethpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
Crosslink: &ethpb.Crosslink{
Shard: 0,
StartEpoch: 0,
},
},
AggregationBits: bitfield.Bitlist{0xC0, 0xC0, 0xC0, 0xC0, 0x01},
CustodyBits: bitfield.Bitlist{0x00, 0x00, 0x00, 0x00, 0x01},
@@ -57,7 +53,7 @@ func TestHandleAttestation_Saves_NewAttestation(t *testing.T) {
Data: att.Data,
CustodyBit: false,
}
domain := helpers.Domain(beaconState.Fork, 0, params.BeaconConfig().DomainAttestation)
domain := helpers.Domain(beaconState.Fork, 0, params.BeaconConfig().DomainBeaconAttester)
sigs := make([]*bls.Signature, len(attestingIndices))
for i, indice := range attestingIndices {
hashTreeRoot, err := ssz.HashTreeRoot(dataAndCustodyBit)
@@ -69,12 +65,6 @@ func TestHandleAttestation_Saves_NewAttestation(t *testing.T) {
}
att.Signature = bls.AggregateSignatures(sigs).Marshal()[:]
beaconState.CurrentCrosslinks = []*ethpb.Crosslink{
{
Shard: 0,
StartEpoch: 0,
},
}
beaconState.CurrentJustifiedCheckpoint.Root = []byte("hello-world")
beaconState.CurrentEpochAttestations = []*pb.PendingAttestation{}
@@ -95,12 +85,6 @@ func TestHandleAttestation_Saves_NewAttestation(t *testing.T) {
t.Fatal(err)
}
beaconState.Slot += params.BeaconConfig().MinAttestationInclusionDelay
encoded, err := ssz.HashTreeRoot(beaconState.CurrentCrosslinks[0])
if err != nil {
t.Fatal(err)
}
att.Data.Crosslink.ParentRoot = encoded[:]
att.Data.Crosslink.DataRoot = params.BeaconConfig().ZeroHash[:]
if err := service.HandleAttestation(context.Background(), att); err != nil {
t.Error(err)
@@ -120,10 +104,6 @@ func TestHandleAttestation_Aggregates_LargeNumValidators(t *testing.T) {
data := &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{
Shard: 1,
StartEpoch: 0,
},
}
dataAndCustodyBit := &pb.AttestationDataAndCustodyBit{
Data: data,
@@ -140,7 +120,7 @@ func TestHandleAttestation_Aggregates_LargeNumValidators(t *testing.T) {
// We setup the genesis state with 256 validators.
deposits, _, privKeys := testutil.SetupInitialDeposits(t, 256)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{})
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Fatal(err)
}
@@ -164,7 +144,7 @@ func TestHandleAttestation_Aggregates_LargeNumValidators(t *testing.T) {
}
// Next up, we compute the committee for the attestation we're testing.
committee, err := helpers.CrosslinkCommittee(beaconState, att.Data.Target.Epoch, att.Data.Crosslink.Shard)
committee, err := helpers.BeaconCommittee(beaconState, att.Data.Slot, att.Data.Index)
if err != nil {
t.Error(err)
}
@@ -173,7 +153,7 @@ func TestHandleAttestation_Aggregates_LargeNumValidators(t *testing.T) {
t.Error(err)
}
totalAggBits := bitfield.NewBitlist(uint64(len(committee)))
domain := helpers.Domain(beaconState.Fork, 0, params.BeaconConfig().DomainAttestation)
domain := helpers.Domain(beaconState.Fork, 0, params.BeaconConfig().DomainBeaconAttester)
// For every single member of the committee, we sign the attestation data and handle
// the attestation through the operations service, which will perform basic aggregation
@@ -229,40 +209,22 @@ func TestHandleAttestation_Skips_PreviouslyAggregatedAttestations(t *testing.T)
service.attestationPool = make(map[[32]byte]*dbpb.AttestationContainer)
deposits, _, privKeys := testutil.SetupInitialDeposits(t, 200)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{})
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Fatal(err)
}
beaconState.CurrentCrosslinks = []*ethpb.Crosslink{
{
Shard: 0,
StartEpoch: 0,
},
}
beaconState.CurrentJustifiedCheckpoint.Root = []byte("hello-world")
beaconState.CurrentEpochAttestations = []*pb.PendingAttestation{}
att1 := &ethpb.Attestation{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{
Shard: 0,
StartEpoch: 0,
},
},
CustodyBits: bitfield.Bitlist{0x00, 0x00, 0x00, 0x00, 0x01},
}
encoded, err := ssz.HashTreeRoot(beaconState.CurrentCrosslinks[0])
if err != nil {
t.Fatal(err)
}
att1.Data.Crosslink.ParentRoot = encoded[:]
att1.Data.Crosslink.DataRoot = params.BeaconConfig().ZeroHash[:]
committee, err := helpers.CrosslinkCommittee(beaconState, att1.Data.Target.Epoch, att1.Data.Crosslink.Shard)
committee, err := helpers.BeaconCommittee(beaconState, att1.Data.Slot, att1.Data.Index)
if err != nil {
t.Error(err)
}
@@ -278,17 +240,13 @@ func TestHandleAttestation_Skips_PreviouslyAggregatedAttestations(t *testing.T)
if err != nil {
t.Error(err)
}
domain := helpers.Domain(beaconState.Fork, 0, params.BeaconConfig().DomainAttestation)
domain := helpers.Domain(beaconState.Fork, 0, params.BeaconConfig().DomainBeaconAttester)
att1.Signature = privKeys[committee[0]].Sign(hashTreeRoot[:], domain).Marshal()
att2 := &ethpb.Attestation{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{
Shard: 0,
StartEpoch: 0,
},
},
CustodyBits: bitfield.Bitlist{0x00, 0x00, 0x00, 0x00, 0x01},
}
@@ -296,18 +254,12 @@ func TestHandleAttestation_Skips_PreviouslyAggregatedAttestations(t *testing.T)
aggregationBits.SetBitAt(1, true)
att2.AggregationBits = aggregationBits
att2.Data.Crosslink.ParentRoot = encoded[:]
att2.Data.Crosslink.DataRoot = params.BeaconConfig().ZeroHash[:]
att2.Signature = privKeys[committee[1]].Sign(hashTreeRoot[:], domain).Marshal()
att3 := &ethpb.Attestation{
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{
Shard: 0,
StartEpoch: 0,
},
},
CustodyBits: bitfield.Bitlist{0x00, 0x00, 0x00, 0x00, 0x01},
}
@@ -316,8 +268,6 @@ func TestHandleAttestation_Skips_PreviouslyAggregatedAttestations(t *testing.T)
aggregationBits.SetBitAt(1, true)
att3.AggregationBits = aggregationBits
att3.Data.Crosslink.ParentRoot = encoded[:]
att3.Data.Crosslink.DataRoot = params.BeaconConfig().ZeroHash[:]
att3Sig1 := privKeys[committee[0]].Sign(hashTreeRoot[:], domain)
att3Sig2 := privKeys[committee[1]].Sign(hashTreeRoot[:], domain)
aggregatedSig := bls.AggregateSignatures([]*bls.Signature{att3Sig1, att3Sig2}).Marshal()
@@ -403,8 +353,8 @@ func TestRetrieveAttestations_OK(t *testing.T) {
service := NewService(context.Background(), &Config{BeaconDB: beaconDB})
service.attestationPool = make(map[[32]byte]*dbpb.AttestationContainer)
deposits, _, privKeys := testutil.SetupInitialDeposits(t, 100)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{})
deposits, _, privKeys := testutil.SetupInitialDeposits(t, 32)
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Fatal(err)
}
@@ -416,10 +366,6 @@ func TestRetrieveAttestations_OK(t *testing.T) {
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0, Root: params.BeaconConfig().ZeroHash[:]},
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{
Shard: 0,
StartEpoch: 0,
},
},
AggregationBits: aggBits,
CustodyBits: custodyBits,
@@ -432,7 +378,7 @@ func TestRetrieveAttestations_OK(t *testing.T) {
Data: att.Data,
CustodyBit: false,
}
domain := helpers.Domain(beaconState.Fork, 0, params.BeaconConfig().DomainAttestation)
domain := helpers.Domain(beaconState.Fork, 0, params.BeaconConfig().DomainBeaconAttester)
sigs := make([]*bls.Signature, len(attestingIndices))
zeroSig := [96]byte{}
@@ -447,23 +393,11 @@ func TestRetrieveAttestations_OK(t *testing.T) {
}
beaconState.Slot += params.BeaconConfig().MinAttestationInclusionDelay
beaconState.CurrentCrosslinks = []*ethpb.Crosslink{
{
Shard: 0,
StartEpoch: 0,
},
}
att.Signature = bls.AggregateSignatures(sigs).Marshal()[:]
beaconState.CurrentEpochAttestations = []*pb.PendingAttestation{}
encoded, err := ssz.HashTreeRoot(beaconState.CurrentCrosslinks[0])
if err != nil {
t.Fatal(err)
}
att.Data.Crosslink.ParentRoot = encoded[:]
att.Data.Crosslink.DataRoot = params.BeaconConfig().ZeroHash[:]
r, _ := ssz.HashTreeRoot(att.Data)
service.attestationPool[r] = dbpb.NewContainerFromAttestations([]*ethpb.Attestation{att})
@@ -475,7 +409,7 @@ func TestRetrieveAttestations_OK(t *testing.T) {
t.Fatal(err)
}
// Test we can retrieve attestations from slot1 - slot61.
attestations, err := service.AttestationPool(context.Background(), 64)
attestations, err := service.AttestationPool(context.Background(), 1)
if err != nil {
t.Fatalf("Could not retrieve attestations: %v", err)
}
@@ -495,9 +429,7 @@ func TestRetrieveAttestations_PruneInvalidAtts(t *testing.T) {
for i := 0; i < len(origAttestations); i++ {
origAttestations[i] = &ethpb.Attestation{
Data: &ethpb.AttestationData{
Crosslink: &ethpb.Crosslink{
Shard: uint64(i),
},
Slot: uint64(i),
Source: &ethpb.Checkpoint{},
Target: &ethpb.Checkpoint{},
},
@@ -513,10 +445,7 @@ func TestRetrieveAttestations_PruneInvalidAtts(t *testing.T) {
t.Fatal(err)
}
if err := beaconDB.SaveState(context.Background(), &pb.BeaconState{
Slot: 200,
CurrentCrosslinks: []*ethpb.Crosslink{{
StartEpoch: 2,
DataRoot: params.BeaconConfig().ZeroHash[:]}}}, headBlockRoot); err != nil {
Slot: 200}, headBlockRoot); err != nil {
t.Fatal(err)
}
attestations, err := service.AttestationPool(context.Background(), 200)
@@ -547,9 +476,7 @@ func TestRemoveProcessedAttestations_Ok(t *testing.T) {
for i := 0; i < len(attestations); i++ {
attestations[i] = &ethpb.Attestation{
Data: &ethpb.AttestationData{
Crosslink: &ethpb.Crosslink{
Shard: uint64(i),
},
Slot: uint64(i),
Source: &ethpb.Checkpoint{},
Target: &ethpb.Checkpoint{},
},
@@ -563,11 +490,7 @@ func TestRemoveProcessedAttestations_Ok(t *testing.T) {
if err := beaconDB.SaveHeadBlockRoot(context.Background(), headBlockRoot); err != nil {
t.Fatal(err)
}
if err := beaconDB.SaveState(context.Background(), &pb.BeaconState{
Slot: 15,
CurrentCrosslinks: []*ethpb.Crosslink{{
StartEpoch: 0,
DataRoot: params.BeaconConfig().ZeroHash[:]}}}, headBlockRoot); err != nil {
if err := beaconDB.SaveState(context.Background(), &pb.BeaconState{Slot: 15}, headBlockRoot); err != nil {
t.Fatal(err)
}

View File

@@ -41,8 +41,8 @@ func (s *Service) handleProcessedBlock(ctx context.Context, message proto.Messag
log.WithFields(logrus.Fields{
"index": i,
"root": fmt.Sprintf("%#x", root),
"aggregation_bits": fmt.Sprintf("%8b", att.AggregationBits.Bytes()),
"shard": att.Data.Crosslink.Shard,
"aggregation_bits": fmt.Sprintf("%08b", att.AggregationBits.Bytes()),
"committeeIndex": att.Data.Index,
}).Debug("block attestation")
}
return nil

View File

@@ -8,7 +8,6 @@ import (
dbutil "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/params"
)
func TestReceiveBlkRemoveOps_Ok(t *testing.T) {
@@ -19,13 +18,9 @@ func TestReceiveBlkRemoveOps_Ok(t *testing.T) {
attestations := make([]*ethpb.Attestation, 10)
for i := 0; i < len(attestations); i++ {
attestations[i] = &ethpb.Attestation{
Data: &ethpb.AttestationData{
Crosslink: &ethpb.Crosslink{
Shard: uint64(i),
},
Data: &ethpb.AttestationData{Slot: uint64(i),
Source: &ethpb.Checkpoint{},
Target: &ethpb.Checkpoint{},
},
Target: &ethpb.Checkpoint{}},
AggregationBits: bitfield.Bitlist{0b11},
}
if err := s.beaconDB.SaveAttestation(context.Background(), attestations[i]); err != nil {
@@ -37,11 +32,7 @@ func TestReceiveBlkRemoveOps_Ok(t *testing.T) {
if err := beaconDB.SaveHeadBlockRoot(context.Background(), headBlockRoot); err != nil {
t.Fatal(err)
}
if err := beaconDB.SaveState(context.Background(), &pb.BeaconState{
Slot: 15,
CurrentCrosslinks: []*ethpb.Crosslink{{
StartEpoch: 0,
DataRoot: params.BeaconConfig().ZeroHash[:]}}}, headBlockRoot); err != nil {
if err := beaconDB.SaveState(context.Background(), &pb.BeaconState{Slot: 15}, headBlockRoot); err != nil {
t.Fatal(err)
}

View File

@@ -17,15 +17,15 @@ func TestRecentAttestationMultiMap_Contains(t *testing.T) {
}{
{
inputs: []bitfield.Bitlist{
bitfield.Bitlist{0b00000001, 0b1},
bitfield.Bitlist{0b00000010, 0b1},
{0b00000001, 0b1},
{0b00000010, 0b1},
},
contains: bitfield.Bitlist{0b00000001, 0b1},
want: true,
}, {
inputs: []bitfield.Bitlist{
bitfield.Bitlist{0b00111000, 0b1},
bitfield.Bitlist{0b00000011, 0b1},
{0b00111000, 0b1},
{0b00000011, 0b1},
},
contains: bitfield.Bitlist{0b00000100, 0b1},
want: false,

View File

@@ -27,7 +27,6 @@ go_test(
],
embed = [":go_default_library"],
deps = [
"//proto/eth/v1alpha1:go_default_library",
"//proto/testing:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
],

View File

@@ -8,7 +8,6 @@ import (
"github.com/gogo/protobuf/proto"
"github.com/prysmaticlabs/prysm/beacon-chain/p2p/encoder"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
testpb "github.com/prysmaticlabs/prysm/proto/testing"
)
@@ -64,16 +63,6 @@ func testRoundTripWithLength(t *testing.T, e *encoder.SszNetworkEncoder) {
}
}
// Regression test to see that a block array response received from Sigma Prime's lighthouse would decode.
func TestLighthouseBeaconBlockResponse(t *testing.T) {
b := []byte{4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 71, 156, 79, 199, 27, 222, 126, 43, 250, 217, 225, 182, 66, 10, 239, 42, 82, 185, 124, 196, 228, 234, 124, 248, 85, 153, 182, 92, 139, 53, 220, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 0, 0, 0, 224, 0, 0, 0, 224, 0, 0, 0, 224, 0, 0, 0, 224, 0, 0, 0, 224, 0, 0, 0}
decoded := make([]ethpb.BeaconBlock, 0)
e := &encoder.SszNetworkEncoder{UseSnappyCompression: false}
if err := e.Decode(b, &decoded); err != nil {
t.Fatal(err)
}
}
func TestSszNetworkEncoder_EncodeWithMaxLength(t *testing.T) {
buf := new(bytes.Buffer)
msg := &testpb.TestSimpleMessage{

View File

@@ -48,12 +48,12 @@ func TestProcessDepositLog_OK(t *testing.T) {
}
testAcc.Backend.Commit()
deposits, _, _ := testutil.SetupInitialDeposits(t, 1)
deposits, depositRoots, _ := testutil.SetupInitialDeposits(t, 1)
data := deposits[0].Data
testAcc.TxOpts.Value = contracts.Amount32Eth()
testAcc.TxOpts.GasLimit = 1000000
if _, err := testAcc.Contract.Deposit(testAcc.TxOpts, data.PublicKey, data.WithdrawalCredentials, data.Signature); err != nil {
if _, err := testAcc.Contract.Deposit(testAcc.TxOpts, data.PublicKey, data.WithdrawalCredentials, data.Signature, depositRoots[0]); err != nil {
t.Fatalf("Could not deposit to deposit contract %v", err)
}
@@ -111,17 +111,17 @@ func TestProcessDepositLog_InsertsPendingDeposit(t *testing.T) {
testAcc.Backend.Commit()
deposits, _, _ := testutil.SetupInitialDeposits(t, 1)
deposits, depositRoots, _ := testutil.SetupInitialDeposits(t, 1)
data := deposits[0].Data
testAcc.TxOpts.Value = contracts.Amount32Eth()
testAcc.TxOpts.GasLimit = 1000000
if _, err := testAcc.Contract.Deposit(testAcc.TxOpts, data.PublicKey, data.WithdrawalCredentials, data.Signature); err != nil {
if _, err := testAcc.Contract.Deposit(testAcc.TxOpts, data.PublicKey, data.WithdrawalCredentials, data.Signature, depositRoots[0]); err != nil {
t.Fatalf("Could not deposit to deposit contract %v", err)
}
if _, err := testAcc.Contract.Deposit(testAcc.TxOpts, data.PublicKey, data.WithdrawalCredentials, data.Signature); err != nil {
if _, err := testAcc.Contract.Deposit(testAcc.TxOpts, data.PublicKey, data.WithdrawalCredentials, data.Signature, depositRoots[0]); err != nil {
t.Fatalf("Could not deposit to deposit contract %v", err)
}
@@ -173,12 +173,12 @@ func TestUnpackDepositLogData_OK(t *testing.T) {
t.Fatalf("Could not init from contract: %v", err)
}
deposits, _, _ := testutil.SetupInitialDeposits(t, 1)
deposits, depositRoots, _ := testutil.SetupInitialDeposits(t, 1)
data := deposits[0].Data
testAcc.TxOpts.Value = contracts.Amount32Eth()
testAcc.TxOpts.GasLimit = 1000000
if _, err := testAcc.Contract.Deposit(testAcc.TxOpts, data.PublicKey, data.WithdrawalCredentials, data.Signature); err != nil {
if _, err := testAcc.Contract.Deposit(testAcc.TxOpts, data.PublicKey, data.WithdrawalCredentials, data.Signature, depositRoots[0]); err != nil {
t.Fatalf("Could not deposit to deposit contract %v", err)
}
testAcc.Backend.Commit()
@@ -245,7 +245,7 @@ func TestProcessETH2GenesisLog_8DuplicatePubkeys(t *testing.T) {
testAcc.Backend.Commit()
testAcc.Backend.AdjustTime(time.Duration(int64(time.Now().Nanosecond())))
deposits, _, _ := testutil.SetupInitialDeposits(t, 1)
deposits, depositRoots, _ := testutil.SetupInitialDeposits(t, 1)
data := deposits[0].Data
testAcc.TxOpts.Value = contracts.Amount32Eth()
@@ -256,7 +256,7 @@ func TestProcessETH2GenesisLog_8DuplicatePubkeys(t *testing.T) {
// is 2**14
for i := 0; i < depositsReqForChainStart; i++ {
testAcc.TxOpts.Value = contracts.Amount32Eth()
if _, err := testAcc.Contract.Deposit(testAcc.TxOpts, data.PublicKey, data.WithdrawalCredentials, data.Signature); err != nil {
if _, err := testAcc.Contract.Deposit(testAcc.TxOpts, data.PublicKey, data.WithdrawalCredentials, data.Signature, depositRoots[0]); err != nil {
t.Fatalf("Could not deposit to deposit contract %v", err)
}
@@ -313,7 +313,7 @@ func TestProcessETH2GenesisLog(t *testing.T) {
testAcc.Backend.Commit()
testAcc.Backend.AdjustTime(time.Duration(int64(time.Now().Nanosecond())))
deposits, _, _ := testutil.SetupInitialDeposits(t, uint64(depositsReqForChainStart))
deposits, depositRoots, _ := testutil.SetupInitialDeposits(t, uint64(depositsReqForChainStart))
// 64 Validators are used as size required for beacon-chain to start. This number
// is defined in the deposit contract as the number required for the testnet. The actual number
@@ -322,7 +322,7 @@ func TestProcessETH2GenesisLog(t *testing.T) {
data := deposits[i].Data
testAcc.TxOpts.Value = contracts.Amount32Eth()
testAcc.TxOpts.GasLimit = 1000000
if _, err := testAcc.Contract.Deposit(testAcc.TxOpts, data.PublicKey, data.WithdrawalCredentials, data.Signature); err != nil {
if _, err := testAcc.Contract.Deposit(testAcc.TxOpts, data.PublicKey, data.WithdrawalCredentials, data.Signature, depositRoots[i]); err != nil {
t.Fatalf("Could not deposit to deposit contract %v", err)
}
@@ -340,6 +340,13 @@ func TestProcessETH2GenesisLog(t *testing.T) {
t.Fatalf("Unable to retrieve logs %v", err)
}
if len(logs) != depositsReqForChainStart {
t.Fatalf(
"Did not receive enough logs, received %d, wanted %d",
len(logs),
depositsReqForChainStart,
)
}
genesisTimeChan := make(chan time.Time, 1)
sub := web3Service.chainStartFeed.Subscribe(genesisTimeChan)
defer sub.Unsubscribe()
@@ -355,7 +362,7 @@ func TestProcessETH2GenesisLog(t *testing.T) {
cachedDeposits := web3Service.ChainStartDeposits()
if len(cachedDeposits) != depositsReqForChainStart {
t.Errorf(
t.Fatalf(
"Did not cache the chain start deposits correctly, received %d, wanted %d",
len(cachedDeposits),
depositsReqForChainStart,
@@ -399,13 +406,13 @@ func TestWeb3ServiceProcessDepositLog_RequestMissedDeposits(t *testing.T) {
testAcc.Backend.Commit()
testAcc.Backend.AdjustTime(time.Duration(int64(time.Now().Nanosecond())))
depositsWanted := 10
deposits, _, _ := testutil.SetupInitialDeposits(t, uint64(depositsWanted))
deposits, depositRoots, _ := testutil.SetupInitialDeposits(t, uint64(depositsWanted))
for i := 0; i < depositsWanted; i++ {
data := deposits[i].Data
testAcc.TxOpts.Value = contracts.Amount32Eth()
testAcc.TxOpts.GasLimit = 1000000
if _, err := testAcc.Contract.Deposit(testAcc.TxOpts, data.PublicKey, data.WithdrawalCredentials, data.Signature); err != nil {
if _, err := testAcc.Contract.Deposit(testAcc.TxOpts, data.PublicKey, data.WithdrawalCredentials, data.Signature, depositRoots[i]); err != nil {
t.Fatalf("Could not deposit to deposit contract %v", err)
}
@@ -423,6 +430,14 @@ func TestWeb3ServiceProcessDepositLog_RequestMissedDeposits(t *testing.T) {
t.Fatalf("Unable to retrieve logs %v", err)
}
if len(logs) != depositsWanted {
t.Fatalf(
"Did not receive enough logs, received %d, wanted %d",
len(logs),
depositsReqForChainStart,
)
}
logsToBeProcessed := append(logs[:depositsWanted-3], logs[depositsWanted-2:]...)
// we purposely miss processing the middle two logs so that the service, re-requests them
for _, log := range logsToBeProcessed {

View File

@@ -374,7 +374,7 @@ func (s *Service) waitForConnection() {
// initDataFromContract calls the deposit contract and finds the deposit count
// and deposit root.
func (s *Service) initDataFromContract() error {
root, err := s.depositContractCaller.GetHashTreeRoot(&bind.CallOpts{})
root, err := s.depositContractCaller.GetDepositRoot(&bind.CallOpts{})
if err != nil {
return errors.Wrap(err, "could not retrieve deposit root")
}

View File

@@ -16,7 +16,6 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/sync"
pb "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/params"
"go.opencensus.io/trace"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
@@ -65,7 +64,7 @@ func (as *AttesterServer) RequestAttestation(ctx context.Context, req *pb.Attest
defer span.End()
span.AddAttributes(
trace.Int64Attribute("slot", int64(req.Slot)),
trace.Int64Attribute("shard", int64(req.Shard)),
trace.Int64Attribute("committeeIndex", int64(req.CommitteeIndex)),
)
if as.syncChecker.Syncing() {
@@ -104,6 +103,14 @@ func (as *AttesterServer) RequestAttestation(ctx context.Context, req *pb.Attest
headState := as.headFetcher.HeadState()
headRoot := as.headFetcher.HeadRoot()
// Safe guard against head state is nil in chain service. This should not happen.
if headState == nil {
headState, err = as.beaconDB.HeadState(ctx)
if err != nil {
return nil, err
}
}
headState, err = state.ProcessSlots(ctx, headState, req.Slot)
if err != nil {
return nil, errors.Wrapf(err, "could not process slots up to %d", req.Slot)
@@ -121,29 +128,15 @@ func (as *AttesterServer) RequestAttestation(ctx context.Context, req *pb.Attest
}
}
startEpoch := headState.CurrentCrosslinks[req.Shard].EndEpoch
endEpoch := startEpoch + params.BeaconConfig().MaxEpochsPerCrosslink
if endEpoch > targetEpoch {
endEpoch = targetEpoch
}
crosslinkRoot, err := ssz.HashTreeRoot(headState.CurrentCrosslinks[req.Shard])
if err != nil {
return nil, errors.Wrapf(err, "could not tree hash crosslink for shard %d", req.Shard)
}
res = &ethpb.AttestationData{
Slot: req.Slot,
Index: req.CommitteeIndex,
BeaconBlockRoot: headRoot[:],
Source: headState.CurrentJustifiedCheckpoint,
Target: &ethpb.Checkpoint{
Epoch: targetEpoch,
Root: targetRoot,
},
Crosslink: &ethpb.Crosslink{
Shard: req.Shard,
StartEpoch: startEpoch,
EndEpoch: endEpoch,
ParentRoot: crosslinkRoot[:],
DataRoot: params.BeaconConfig().ZeroHash[:],
},
}
if err := as.attestationCache.Put(ctx, req, res); err != nil {

View File

@@ -55,10 +55,9 @@ func TestSubmitAttestation_OK(t *testing.T) {
}
state := &pbp2p.BeaconState{
Slot: params.BeaconConfig().SlotsPerEpoch + 1,
Validators: validators,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
Slot: params.BeaconConfig().SlotsPerEpoch + 1,
Validators: validators,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
}
if err := db.SaveHeadBlockRoot(ctx, root); err != nil {
@@ -71,12 +70,8 @@ func TestSubmitAttestation_OK(t *testing.T) {
req := &ethpb.Attestation{
Data: &ethpb.AttestationData{
BeaconBlockRoot: root[:],
Crosslink: &ethpb.Crosslink{
Shard: 935,
DataRoot: []byte{'a'},
},
Source: &ethpb.Checkpoint{},
Target: &ethpb.Checkpoint{},
Source: &ethpb.Checkpoint{},
Target: &ethpb.Checkpoint{},
},
}
if _, err := attesterServer.SubmitAttestation(context.Background(), req); err != nil {
@@ -110,16 +105,6 @@ func TestRequestAttestation_OK(t *testing.T) {
beaconState := &pbp2p.BeaconState{
Slot: 3*params.BeaconConfig().SlotsPerEpoch + 1,
BlockRoots: make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot),
CurrentCrosslinks: []*ethpb.Crosslink{
{
DataRoot: []byte("A"),
},
},
PreviousCrosslinks: []*ethpb.Crosslink{
{
DataRoot: []byte("A"),
},
},
CurrentJustifiedCheckpoint: &ethpb.Checkpoint{
Epoch: 2,
Root: justifiedRoot[:],
@@ -137,20 +122,16 @@ func TestRequestAttestation_OK(t *testing.T) {
}
req := &pb.AttestationRequest{
Shard: 0,
Slot: 3*params.BeaconConfig().SlotsPerEpoch + 1,
CommitteeIndex: 0,
Slot: 3*params.BeaconConfig().SlotsPerEpoch + 1,
}
res, err := attesterServer.RequestAttestation(context.Background(), req)
if err != nil {
t.Fatalf("Could not get attestation info at slot: %v", err)
}
crosslinkRoot, err := ssz.HashTreeRoot(beaconState.CurrentCrosslinks[req.Shard])
if err != nil {
t.Fatal(err)
}
expectedInfo := &ethpb.AttestationData{
Slot: 3*params.BeaconConfig().SlotsPerEpoch + 1,
BeaconBlockRoot: blockRoot[:],
Source: &ethpb.Checkpoint{
Epoch: 2,
@@ -159,11 +140,6 @@ func TestRequestAttestation_OK(t *testing.T) {
Target: &ethpb.Checkpoint{
Epoch: 3,
},
Crosslink: &ethpb.Crosslink{
EndEpoch: 3,
ParentRoot: crosslinkRoot[:],
DataRoot: params.BeaconConfig().ZeroHash[:],
},
}
if !proto.Equal(res, expectedInfo) {
@@ -222,16 +198,6 @@ func TestAttestationDataAtSlot_handlesFarAwayJustifiedEpoch(t *testing.T) {
beaconState := &pbp2p.BeaconState{
Slot: 10000,
BlockRoots: make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot),
PreviousCrosslinks: []*ethpb.Crosslink{
{
DataRoot: []byte("A"),
},
},
CurrentCrosslinks: []*ethpb.Crosslink{
{
DataRoot: []byte("A"),
},
},
CurrentJustifiedCheckpoint: &ethpb.Checkpoint{
Epoch: helpers.SlotToEpoch(1500),
Root: justifiedBlockRoot[:],
@@ -249,32 +215,23 @@ func TestAttestationDataAtSlot_handlesFarAwayJustifiedEpoch(t *testing.T) {
}
req := &pb.AttestationRequest{
Shard: 0,
Slot: 10000,
CommitteeIndex: 0,
Slot: 10000,
}
res, err := attesterServer.RequestAttestation(context.Background(), req)
if err != nil {
t.Fatalf("Could not get attestation info at slot: %v", err)
}
crosslinkRoot, err := ssz.HashTreeRoot(beaconState.CurrentCrosslinks[req.Shard])
if err != nil {
t.Fatal(err)
}
expectedInfo := &ethpb.AttestationData{
Slot: req.Slot,
BeaconBlockRoot: blockRoot[:],
Source: &ethpb.Checkpoint{
Epoch: helpers.SlotToEpoch(1500),
Root: justifiedBlockRoot[:],
},
Target: &ethpb.Checkpoint{
Epoch: 156,
},
Crosslink: &ethpb.Crosslink{
ParentRoot: crosslinkRoot[:],
EndEpoch: params.BeaconConfig().SlotsPerEpoch,
DataRoot: params.BeaconConfig().ZeroHash[:],
Epoch: 312,
},
}
@@ -299,8 +256,8 @@ func TestAttestationDataAtSlot_handlesInProgressRequest(t *testing.T) {
}
req := &pb.AttestationRequest{
Shard: 1,
Slot: 2,
CommitteeIndex: 1,
Slot: 2,
}
res := &ethpb.AttestationData{

View File

@@ -19,6 +19,7 @@ import (
pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/hashutil"
"github.com/prysmaticlabs/prysm/shared/pagination"
"github.com/prysmaticlabs/prysm/shared/params"
"google.golang.org/grpc/codes"
@@ -42,17 +43,17 @@ type BeaconChainServer struct {
}
// sortableAttestations implements the Sort interface to sort attestations
// by shard as the canonical sorting attribute.
// by slot as the canonical sorting attribute.
type sortableAttestations []*ethpb.Attestation
func (s sortableAttestations) Len() int { return len(s) }
func (s sortableAttestations) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s sortableAttestations) Less(i, j int) bool {
return s[i].Data.Crosslink.Shard < s[j].Data.Crosslink.Shard
return s[i].Data.Slot < s[j].Data.Slot
}
// ListAttestations retrieves attestations by block root, slot, or epoch.
// Attestations are sorted by crosslink shard by default.
// Attestations are sorted by data slot by default.
//
// The server may return an empty list when no attestations match the given
// filter criteria. This RPC should not return NOT_FOUND. Only one filter
@@ -611,10 +612,6 @@ func (bs *BeaconChainServer) ListValidatorAssignments(
return nil, status.Errorf(codes.InvalidArgument, "validator index %d >= validator count %d",
index, len(headState.Validators))
}
var committee []uint64
var shard uint64
var slot uint64
var isProposer bool
if shouldFetchFromArchive {
archivedInfo, err := bs.beaconDB.ArchivedCommitteeInfo(ctx, requestedEpoch)
if err != nil {
@@ -631,25 +628,53 @@ func (bs *BeaconChainServer) ListValidatorAssignments(
requestedEpoch,
)
}
committee, shard, slot, err = bs.archivedValidatorCommittee(requestedEpoch, index, archivedInfo, activeIndices)
archivedBalances, err := bs.beaconDB.ArchivedBalances(ctx, requestedEpoch)
if err != nil {
return nil, status.Errorf(codes.Internal, "could not retrieve assignment for validator %d: %v", index, err)
return nil, status.Errorf(
codes.Internal,
"could not retrieve archived balances for epoch %d",
requestedEpoch,
)
}
isProposer = archivedInfo.ProposerIndex == index
} else {
committee, shard, slot, isProposer, err = helpers.CommitteeAssignment(headState, requestedEpoch, index)
if archivedBalances == nil {
return nil, status.Errorf(
codes.NotFound,
"no archival balances found for epoch %d",
requestedEpoch,
)
}
committee, committeeIndex, attesterSlot, proposerSlot, err := archivedValidatorCommittee(
requestedEpoch,
index,
archivedInfo,
activeIndices,
archivedBalances,
)
if err != nil {
return nil, status.Errorf(codes.Internal, "could not retrieve assignment for validator %d: %v", index, err)
return nil, status.Errorf(codes.Internal, "could not retrieve archived assignment for validator %d: %v", index, err)
}
assign := &ethpb.ValidatorAssignments_CommitteeAssignment{
BeaconCommittees: committee,
CommitteeIndex: committeeIndex,
AttesterSlot: attesterSlot,
ProposerSlot: proposerSlot,
PublicKey: headState.Validators[index].PublicKey,
}
res = append(res, assign)
continue
}
res = append(res, &ethpb.ValidatorAssignments_CommitteeAssignment{
CrosslinkCommittees: committee,
Shard: shard,
Slot: slot,
Proposer: isProposer,
PublicKey: headState.Validators[index].PublicKey,
})
committee, committeeIndex, attesterSlot, proposerSlot, err := helpers.CommitteeAssignment(headState, requestedEpoch, index)
if err != nil {
return nil, status.Errorf(codes.Internal, "could not retrieve assignment for validator %d: %v", index, err)
}
assign := &ethpb.ValidatorAssignments_CommitteeAssignment{
BeaconCommittees: committee,
CommitteeIndex: committeeIndex,
AttesterSlot: attesterSlot,
ProposerSlot: proposerSlot,
PublicKey: headState.Validators[index].PublicKey,
}
res = append(res, assign)
}
return &ethpb.ValidatorAssignments{
@@ -661,38 +686,77 @@ func (bs *BeaconChainServer) ListValidatorAssignments(
}
// Computes validator assignments for an epoch and validator index using archived committee
// information and a set of active validators.
func (bs *BeaconChainServer) archivedValidatorCommittee(
// information, archived balances, and a set of active validators.
func archivedValidatorCommittee(
epoch uint64,
validatorIndex uint64,
archivedInfo *ethpb.ArchivedCommitteeInfo,
activeIndices []uint64,
) ([]uint64, uint64, uint64, error) {
startSlot := helpers.StartSlot(epoch)
archivedBalances []uint64,
) ([]uint64, uint64, uint64, uint64, error) {
committeeCount := archivedInfo.CommitteeCount
committeesPerSlot := committeeCount / params.BeaconConfig().SlotsPerEpoch
epochStartShard := archivedInfo.StartShard
seed := bytesutil.ToBytes32(archivedInfo.Seed)
shardCount := params.BeaconConfig().ShardCount
proposerSeed := bytesutil.ToBytes32(archivedInfo.ProposerSeed)
attesterSeed := bytesutil.ToBytes32(archivedInfo.AttesterSeed)
startSlot := helpers.StartSlot(epoch)
proposerIndexToSlot := make(map[uint64]uint64)
for slot := startSlot; slot < startSlot+params.BeaconConfig().SlotsPerEpoch; slot++ {
offset := committeesPerSlot * (slot % params.BeaconConfig().SlotsPerEpoch)
slotStartShard := (epochStartShard + offset) % params.BeaconConfig().ShardCount
for i := uint64(0); i < committeesPerSlot; i++ {
shard := (slotStartShard + i) % params.BeaconConfig().ShardCount
currentShard := (shard + shardCount - epochStartShard) % shardCount
committee, err := helpers.ComputeCommittee(activeIndices, seed, currentShard, committeeCount)
seedWithSlot := append(proposerSeed[:], bytesutil.Bytes8(slot)...)
seedWithSlotHash := hashutil.Hash(seedWithSlot)
i, err := archivedProposerIndex(activeIndices, archivedBalances, seedWithSlotHash)
if err != nil {
return nil, 0, 0, 0, errors.Wrapf(err, "could not check proposer at slot %d", slot)
}
proposerIndexToSlot[i] = slot
}
for slot := startSlot; slot < startSlot+params.BeaconConfig().SlotsPerEpoch; slot++ {
var countAtSlot = uint64(len(activeIndices)) / params.BeaconConfig().SlotsPerEpoch / params.BeaconConfig().TargetCommitteeSize
if countAtSlot > params.BeaconConfig().MaxCommitteesPerSlot {
countAtSlot = params.BeaconConfig().MaxCommitteesPerSlot
}
if countAtSlot == 0 {
countAtSlot = 1
}
for i := uint64(0); i < countAtSlot; i++ {
epochOffset := i + (slot%params.BeaconConfig().SlotsPerEpoch)*countAtSlot
committee, err := helpers.ComputeCommittee(activeIndices, attesterSeed, epochOffset, committeeCount)
if err != nil {
return nil, 0, 0, errors.Wrap(err, "could not compute committee")
return nil, 0, 0, 0, errors.Wrap(err, "could not compute committee")
}
for _, index := range committee {
if validatorIndex == index {
return committee, shard, slot, nil
proposerSlot, _ := proposerIndexToSlot[validatorIndex]
return committee, i, slot, proposerSlot, nil
}
}
}
}
return nil, 0, 0, fmt.Errorf("could not find committee for validator index %d", validatorIndex)
return nil, 0, 0, 0, fmt.Errorf("could not find committee for validator index %d", validatorIndex)
}
func archivedProposerIndex(activeIndices []uint64, activeBalances []uint64, seed [32]byte) (uint64, error) {
length := uint64(len(activeIndices))
if length == 0 {
return 0, errors.New("empty indices list")
}
maxRandomByte := uint64(1<<8 - 1)
for i := uint64(0); ; i++ {
candidateIndex, err := helpers.ComputeShuffledIndex(i%length, length, seed, true)
if err != nil {
return 0, err
}
b := append(seed[:], bytesutil.Bytes8(i/32)...)
randomByte := hashutil.Hash(b)[i%32]
effectiveBalance := activeBalances[candidateIndex]
if effectiveBalance >= params.BeaconConfig().MaxEffectiveBalance {
// if the actual balance is greater than or equal to the max effective balance,
// we just determine the proposer index using config.MaxEffectiveBalance.
effectiveBalance = params.BeaconConfig().MaxEffectiveBalance
}
if effectiveBalance*maxRandomByte >= params.BeaconConfig().MaxEffectiveBalance*uint64(randomByte) {
return candidateIndex, nil
}
}
}
// GetValidatorParticipation retrieves the validator participation information for a given epoch,

View File

@@ -34,9 +34,7 @@ func TestBeaconChainServer_ListAttestationsNoPagination(t *testing.T) {
attExample := &ethpb.Attestation{
Data: &ethpb.AttestationData{
BeaconBlockRoot: []byte("root"),
Crosslink: &ethpb.Crosslink{
Shard: i,
},
Slot: i,
},
AggregationBits: bitfield.Bitlist{0b11},
CustodyBits: bitfield.NewBitlist(1),
@@ -89,9 +87,7 @@ func TestBeaconChainServer_ListAttestations_FiltersCorrectly(t *testing.T) {
Root: targetRoot,
Epoch: targetEpoch,
},
Crosslink: &ethpb.Crosslink{
Shard: 3,
},
Slot: 3,
},
AggregationBits: bitfield.Bitlist{0b11},
},
@@ -106,9 +102,7 @@ func TestBeaconChainServer_ListAttestations_FiltersCorrectly(t *testing.T) {
Root: targetRoot,
Epoch: targetEpoch,
},
Crosslink: &ethpb.Crosslink{
Shard: 4,
},
Slot: 4,
},
AggregationBits: bitfield.Bitlist{0b11},
},
@@ -123,9 +117,7 @@ func TestBeaconChainServer_ListAttestations_FiltersCorrectly(t *testing.T) {
Root: unknownRoot,
Epoch: targetEpoch,
},
Crosslink: &ethpb.Crosslink{
Shard: 5,
},
Slot: 5,
},
AggregationBits: bitfield.Bitlist{0b11},
},
@@ -197,9 +189,7 @@ func TestBeaconChainServer_ListAttestationsPagination(t *testing.T) {
attExample := &ethpb.Attestation{
Data: &ethpb.AttestationData{
BeaconBlockRoot: []byte("root"),
Crosslink: &ethpb.Crosslink{
Shard: i,
},
Slot: i,
},
AggregationBits: bitfield.Bitlist{0b11},
CustodyBits: bitfield.NewBitlist(1),
@@ -230,19 +220,19 @@ func TestBeaconChainServer_ListAttestationsPagination(t *testing.T) {
Attestations: []*ethpb.Attestation{
{Data: &ethpb.AttestationData{
BeaconBlockRoot: []byte("root"),
Crosslink: &ethpb.Crosslink{Shard: 3},
Slot: 3,
},
AggregationBits: bitfield.Bitlist{0b11},
CustodyBits: bitfield.NewBitlist(1)},
{Data: &ethpb.AttestationData{
BeaconBlockRoot: []byte("root"),
Crosslink: &ethpb.Crosslink{Shard: 4},
Slot: 4,
},
AggregationBits: bitfield.Bitlist{0b11},
CustodyBits: bitfield.NewBitlist(1)},
{Data: &ethpb.AttestationData{
BeaconBlockRoot: []byte("root"),
Crosslink: &ethpb.Crosslink{Shard: 5},
Slot: 5,
},
AggregationBits: bitfield.Bitlist{0b11},
CustodyBits: bitfield.NewBitlist(1)},
@@ -261,31 +251,31 @@ func TestBeaconChainServer_ListAttestationsPagination(t *testing.T) {
Attestations: []*ethpb.Attestation{
{Data: &ethpb.AttestationData{
BeaconBlockRoot: []byte("root"),
Crosslink: &ethpb.Crosslink{Shard: 50},
Slot: 50,
},
AggregationBits: bitfield.Bitlist{0b11},
CustodyBits: bitfield.NewBitlist(1)},
{Data: &ethpb.AttestationData{
BeaconBlockRoot: []byte("root"),
Crosslink: &ethpb.Crosslink{Shard: 51},
Slot: 51,
},
AggregationBits: bitfield.Bitlist{0b11},
CustodyBits: bitfield.NewBitlist(1)},
{Data: &ethpb.AttestationData{
BeaconBlockRoot: []byte("root"),
Crosslink: &ethpb.Crosslink{Shard: 52},
Slot: 52,
},
AggregationBits: bitfield.Bitlist{0b11},
CustodyBits: bitfield.NewBitlist(1)},
{Data: &ethpb.AttestationData{
BeaconBlockRoot: []byte("root"),
Crosslink: &ethpb.Crosslink{Shard: 53},
Slot: 53,
},
AggregationBits: bitfield.Bitlist{0b11},
CustodyBits: bitfield.NewBitlist(1)},
{Data: &ethpb.AttestationData{
BeaconBlockRoot: []byte("root"),
Crosslink: &ethpb.Crosslink{Shard: 54},
Slot: 54,
}, AggregationBits: bitfield.Bitlist{0b11},
CustodyBits: bitfield.NewBitlist(1)},
},
@@ -303,7 +293,7 @@ func TestBeaconChainServer_ListAttestationsPagination(t *testing.T) {
Attestations: []*ethpb.Attestation{
{Data: &ethpb.AttestationData{
BeaconBlockRoot: []byte("root"),
Crosslink: &ethpb.Crosslink{Shard: 99},
Slot: 99,
},
AggregationBits: bitfield.Bitlist{0b11},
CustodyBits: bitfield.NewBitlist(1)},
@@ -321,13 +311,12 @@ func TestBeaconChainServer_ListAttestationsPagination(t *testing.T) {
Attestations: []*ethpb.Attestation{
{Data: &ethpb.AttestationData{
BeaconBlockRoot: []byte("root"),
Crosslink: &ethpb.Crosslink{Shard: 0},
},
AggregationBits: bitfield.Bitlist{0b11},
CustodyBits: bitfield.NewBitlist(1)},
{Data: &ethpb.AttestationData{
BeaconBlockRoot: []byte("root"),
Crosslink: &ethpb.Crosslink{Shard: 1},
Slot: 1,
},
AggregationBits: bitfield.Bitlist{0b11},
CustodyBits: bitfield.NewBitlist(1),
@@ -358,9 +347,7 @@ func TestBeaconChainServer_ListAttestationsPaginationOutOfRange(t *testing.T) {
attExample := &ethpb.Attestation{
Data: &ethpb.AttestationData{
BeaconBlockRoot: []byte("root"),
Crosslink: &ethpb.Crosslink{
Shard: i,
},
Slot: i,
},
AggregationBits: bitfield.Bitlist{0b11},
}
@@ -410,9 +397,7 @@ func TestBeaconChainServer_ListAttestationsDefaultPageSize(t *testing.T) {
attExample := &ethpb.Attestation{
Data: &ethpb.AttestationData{
BeaconBlockRoot: []byte("root"),
Crosslink: &ethpb.Crosslink{
Shard: i,
},
Slot: i,
},
AggregationBits: bitfield.Bitlist{0b11},
CustodyBits: bitfield.NewBitlist(1),
@@ -1295,7 +1280,7 @@ func TestBeaconChainServer_ListAssignmentsExceedsMaxPageSize(t *testing.T) {
}
}
func TestBeaconChainServer_ListAssignmentsDefaultPageSize(t *testing.T) {
func TestBeaconChainServer_ListAssignmentsDefaultPageSize_NoArchive(t *testing.T) {
db := dbTest.SetupDB(t)
defer dbTest.TeardownDB(t, db)
@@ -1303,14 +1288,23 @@ func TestBeaconChainServer_ListAssignmentsDefaultPageSize(t *testing.T) {
count := 1000
validators := make([]*ethpb.Validator, 0, count)
for i := 0; i < count; i++ {
if err := db.SaveValidatorIndex(ctx, [48]byte{byte(i)}, uint64(i)); err != nil {
var pubKey [48]byte
copy(pubKey[:], strconv.Itoa(i))
if err := db.SaveValidatorIndex(ctx, pubKey, uint64(i)); err != nil {
t.Fatal(err)
}
// Mark the validators with index divisible by 3 inactive.
if i%3 == 0 {
validators = append(validators, &ethpb.Validator{PublicKey: []byte{byte(i)}, ExitEpoch: 0})
validators = append(validators, &ethpb.Validator{
PublicKey: pubKey[:],
ExitEpoch: 0,
})
} else {
validators = append(validators, &ethpb.Validator{PublicKey: []byte{byte(i)}, ExitEpoch: params.BeaconConfig().FarFutureEpoch})
validators = append(validators, &ethpb.Validator{
PublicKey: pubKey[:],
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
})
}
}
@@ -1326,9 +1320,8 @@ func TestBeaconChainServer_ListAssignmentsDefaultPageSize(t *testing.T) {
}
s := &pbp2p.BeaconState{
Validators: validators,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector)}
Validators: validators,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector)}
if err := db.SaveState(ctx, s, blockRoot); err != nil {
t.Fatal(err)
}
@@ -1347,12 +1340,13 @@ func TestBeaconChainServer_ListAssignmentsDefaultPageSize(t *testing.T) {
res, err := bs.ListValidatorAssignments(context.Background(), &ethpb.ListValidatorAssignmentsRequest{
QueryFilter: &ethpb.ListValidatorAssignmentsRequest_Genesis{Genesis: true},
PublicKeys: [][]byte{[]byte("311")},
})
if err != nil {
t.Fatal(err)
}
// Construct the wanted assignments
// Construct the wanted assignments.
var wanted []*ethpb.ValidatorAssignments_CommitteeAssignment
activeIndices, err := helpers.ActiveValidatorIndices(s, 0)
@@ -1360,20 +1354,20 @@ func TestBeaconChainServer_ListAssignmentsDefaultPageSize(t *testing.T) {
t.Fatal(err)
}
for _, index := range activeIndices[0:params.BeaconConfig().DefaultPageSize] {
committee, shard, slot, isProposer, err := helpers.CommitteeAssignment(s, 0, index)
committee, committeeIndex, attesterSlot, proposerSlot, err := helpers.CommitteeAssignment(s, 0, index)
if err != nil {
t.Fatal(err)
}
wanted = append(wanted, &ethpb.ValidatorAssignments_CommitteeAssignment{
CrosslinkCommittees: committee,
Shard: shard,
Slot: slot,
Proposer: isProposer,
PublicKey: s.Validators[index].PublicKey,
BeaconCommittees: committee,
CommitteeIndex: committeeIndex,
AttesterSlot: attesterSlot,
ProposerSlot: proposerSlot,
PublicKey: s.Validators[index].PublicKey,
})
}
if !reflect.DeepEqual(res.Assignments, wanted) {
if !reflect.DeepEqual(res.Assignments[0], wanted[207]) {
t.Error("Did not receive wanted assignments")
}
}
@@ -1385,16 +1379,28 @@ func TestBeaconChainServer_ListAssignmentsDefaultPageSize_FromArchive(t *testing
ctx := context.Background()
count := 1000
validators := make([]*ethpb.Validator, 0, count)
balances := make([]uint64, count)
for i := 0; i < count; i++ {
if err := db.SaveValidatorIndex(ctx, [48]byte{byte(i)}, uint64(i)); err != nil {
var pubKey [48]byte
copy(pubKey[:], strconv.Itoa(i))
if err := db.SaveValidatorIndex(ctx, pubKey, uint64(i)); err != nil {
t.Fatal(err)
}
// Mark the validators with index divisible by 3 inactive.
if i%3 == 0 {
validators = append(validators, &ethpb.Validator{PublicKey: []byte{byte(i)}, ExitEpoch: 0})
validators = append(validators, &ethpb.Validator{
PublicKey: pubKey[:],
ExitEpoch: 0,
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
})
} else {
validators = append(validators, &ethpb.Validator{PublicKey: []byte{byte(i)}, ExitEpoch: params.BeaconConfig().FarFutureEpoch})
validators = append(validators, &ethpb.Validator{
PublicKey: pubKey[:],
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
})
}
balances[i] = params.BeaconConfig().MaxEffectiveBalance
}
blk := &ethpb.BeaconBlock{
@@ -1409,9 +1415,10 @@ func TestBeaconChainServer_ListAssignmentsDefaultPageSize_FromArchive(t *testing
}
s := &pbp2p.BeaconState{
Validators: validators,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector)}
Validators: validators,
Balances: balances,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
}
if err := db.SaveState(ctx, s, blockRoot); err != nil {
t.Fatal(err)
}
@@ -1432,60 +1439,57 @@ func TestBeaconChainServer_ListAssignmentsDefaultPageSize_FromArchive(t *testing
// We then store archived data into the DB.
currentEpoch := helpers.CurrentEpoch(s)
committeeCount, err := helpers.CommitteeCount(s, currentEpoch)
committeeCount, err := helpers.CommitteeCountAtSlot(s, helpers.StartSlot(currentEpoch))
if err != nil {
t.Fatal(err)
}
seed, err := helpers.Seed(s, currentEpoch)
proposerSeed, err := helpers.Seed(s, currentEpoch, params.BeaconConfig().DomainBeaconProposer)
if err != nil {
t.Fatal(err)
}
startShard, err := helpers.StartShard(s, currentEpoch)
attesterSeed, err := helpers.Seed(s, currentEpoch, params.BeaconConfig().DomainBeaconAttester)
if err != nil {
t.Fatal(err)
}
proposerIndex, err := helpers.BeaconProposerIndex(s)
if err != nil {
if err := db.SaveArchivedCommitteeInfo(context.Background(), 0, &ethpb.ArchivedCommitteeInfo{
ProposerSeed: proposerSeed[:],
AttesterSeed: attesterSeed[:],
CommitteeCount: committeeCount * params.BeaconConfig().SlotsPerEpoch,
}); err != nil {
t.Fatal(err)
}
if err := db.SaveArchivedCommitteeInfo(context.Background(), 0, &ethpb.ArchivedCommitteeInfo{
Seed: seed[:],
StartShard: startShard,
CommitteeCount: committeeCount,
ProposerIndex: proposerIndex,
}); err != nil {
if err := db.SaveArchivedBalances(context.Background(), 0, balances); err != nil {
t.Fatal(err)
}
// Construct the wanted assignments.
var wanted []*ethpb.ValidatorAssignments_CommitteeAssignment
activeIndices, err := helpers.ActiveValidatorIndices(s, 0)
if err != nil {
t.Fatal(err)
}
for _, index := range activeIndices[0:params.BeaconConfig().DefaultPageSize] {
committee, committeeIndex, attesterSlot, proposerSlot, err := helpers.CommitteeAssignment(s, 0, index)
if err != nil {
t.Fatal(err)
}
assign := &ethpb.ValidatorAssignments_CommitteeAssignment{
BeaconCommittees: committee,
CommitteeIndex: committeeIndex,
AttesterSlot: attesterSlot,
ProposerSlot: proposerSlot,
PublicKey: s.Validators[index].PublicKey,
}
wanted = append(wanted, assign)
}
res, err := bs.ListValidatorAssignments(context.Background(), &ethpb.ListValidatorAssignmentsRequest{
QueryFilter: &ethpb.ListValidatorAssignmentsRequest_Genesis{Genesis: true},
})
if err != nil {
t.Fatal(err)
}
// Construct the wanted assignments
var wanted []*ethpb.ValidatorAssignments_CommitteeAssignment
activeIndices, err := helpers.ActiveValidatorIndices(s, 0)
if err != nil {
t.Fatal(err)
}
for _, index := range activeIndices[0:params.BeaconConfig().DefaultPageSize] {
committee, shard, slot, isProposer, err := helpers.CommitteeAssignment(s, 0, index)
if err != nil {
t.Fatal(err)
}
wanted = append(wanted, &ethpb.ValidatorAssignments_CommitteeAssignment{
CrosslinkCommittees: committee,
Shard: shard,
Slot: slot,
Proposer: isProposer,
PublicKey: s.Validators[index].PublicKey,
})
}
if !reflect.DeepEqual(res.Assignments, wanted) {
t.Error("Did not receive wanted assignments")
}
@@ -1518,9 +1522,8 @@ func TestBeaconChainServer_ListAssignmentsFilterPubkeysIndices_NoPagination(t *t
}
s := &pbp2p.BeaconState{
Validators: validators,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector)}
Validators: validators,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector)}
if err := db.SaveState(ctx, s, blockRoot); err != nil {
t.Fatal(err)
}
@@ -1543,7 +1546,7 @@ func TestBeaconChainServer_ListAssignmentsFilterPubkeysIndices_NoPagination(t *t
t.Fatal(err)
}
// Construct the wanted assignments
// Construct the wanted assignments.
var wanted []*ethpb.ValidatorAssignments_CommitteeAssignment
activeIndices, err := helpers.ActiveValidatorIndices(s, 0)
@@ -1551,16 +1554,16 @@ func TestBeaconChainServer_ListAssignmentsFilterPubkeysIndices_NoPagination(t *t
t.Fatal(err)
}
for _, index := range activeIndices[1:4] {
committee, shard, slot, isProposer, err := helpers.CommitteeAssignment(s, 0, index)
committee, committeeIndex, attesterSlot, proposerSlot, err := helpers.CommitteeAssignment(s, 0, index)
if err != nil {
t.Fatal(err)
}
wanted = append(wanted, &ethpb.ValidatorAssignments_CommitteeAssignment{
CrosslinkCommittees: committee,
Shard: shard,
Slot: slot,
Proposer: isProposer,
PublicKey: s.Validators[index].PublicKey,
BeaconCommittees: committee,
CommitteeIndex: committeeIndex,
AttesterSlot: attesterSlot,
ProposerSlot: proposerSlot,
PublicKey: s.Validators[index].PublicKey,
})
}
@@ -1596,9 +1599,8 @@ func TestBeaconChainServer_ListAssignmentsCanFilterPubkeysIndices_WithPagination
}
s := &pbp2p.BeaconState{
Validators: validators,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector)}
Validators: validators,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector)}
if err := db.SaveState(ctx, s, blockRoot); err != nil {
t.Fatal(err)
}
@@ -1621,7 +1623,7 @@ func TestBeaconChainServer_ListAssignmentsCanFilterPubkeysIndices_WithPagination
t.Fatal(err)
}
// Construct the wanted assignments
// Construct the wanted assignments.
var assignments []*ethpb.ValidatorAssignments_CommitteeAssignment
activeIndices, err := helpers.ActiveValidatorIndices(s, 0)
@@ -1629,16 +1631,16 @@ func TestBeaconChainServer_ListAssignmentsCanFilterPubkeysIndices_WithPagination
t.Fatal(err)
}
for _, index := range activeIndices[3:5] {
committee, shard, slot, isProposer, err := helpers.CommitteeAssignment(s, 0, index)
committee, committeeIndex, attesterSlot, proposerSlot, err := helpers.CommitteeAssignment(s, 0, index)
if err != nil {
t.Fatal(err)
}
assignments = append(assignments, &ethpb.ValidatorAssignments_CommitteeAssignment{
CrosslinkCommittees: committee,
Shard: shard,
Slot: slot,
Proposer: isProposer,
PublicKey: s.Validators[index].PublicKey,
BeaconCommittees: committee,
CommitteeIndex: committeeIndex,
AttesterSlot: attesterSlot,
ProposerSlot: proposerSlot,
PublicKey: s.Validators[index].PublicKey,
})
}
@@ -1661,16 +1663,16 @@ func TestBeaconChainServer_ListAssignmentsCanFilterPubkeysIndices_WithPagination
}
for _, index := range activeIndices[6:7] {
committee, shard, slot, isProposer, err := helpers.CommitteeAssignment(s, 0, index)
committee, committeeIndex, attesterSlot, proposerSlot, err := helpers.CommitteeAssignment(s, 0, index)
if err != nil {
t.Fatal(err)
}
assignments = append(assignments, &ethpb.ValidatorAssignments_CommitteeAssignment{
CrosslinkCommittees: committee,
Shard: shard,
Slot: slot,
Proposer: isProposer,
PublicKey: s.Validators[index].PublicKey,
BeaconCommittees: committee,
CommitteeIndex: committeeIndex,
AttesterSlot: attesterSlot,
ProposerSlot: proposerSlot,
PublicKey: s.Validators[index].PublicKey,
})
}
@@ -1764,14 +1766,7 @@ func TestBeaconChainServer_GetValidatorsParticipation_CurrentEpoch(t *testing.T)
balances[i] = params.BeaconConfig().MaxEffectiveBalance
}
atts := []*pbp2p.PendingAttestation{{Data: &ethpb.AttestationData{Crosslink: &ethpb.Crosslink{Shard: 0}, Target: &ethpb.Checkpoint{}}}}
var crosslinks []*ethpb.Crosslink
for i := uint64(0); i < params.BeaconConfig().ShardCount; i++ {
crosslinks = append(crosslinks, &ethpb.Crosslink{
StartEpoch: 0,
DataRoot: []byte{'A'},
})
}
atts := []*pbp2p.PendingAttestation{{Data: &ethpb.AttestationData{Target: &ethpb.Checkpoint{}}}}
s := &pbp2p.BeaconState{
Slot: epoch*params.BeaconConfig().SlotsPerEpoch + 1,
@@ -1780,9 +1775,6 @@ func TestBeaconChainServer_GetValidatorsParticipation_CurrentEpoch(t *testing.T)
BlockRoots: make([][]byte, 128),
Slashings: []uint64{0, 1e9, 1e9},
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
CompactCommitteesRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
CurrentCrosslinks: crosslinks,
CurrentEpochAttestations: atts,
FinalizedCheckpoint: &ethpb.Checkpoint{},
JustificationBits: bitfield.Bitvector4{0x00},

View File

@@ -98,7 +98,6 @@ func (ps *ProposerServer) RequestBlock(ctx context.Context, req *pb.BlockRequest
Attestations: atts,
RandaoReveal: req.RandaoReveal,
// TODO(2766): Implement rest of the retrievals for beacon block operations
Transfers: []*ethpb.Transfer{},
ProposerSlashings: []*ethpb.ProposerSlashing{},
AttesterSlashings: []*ethpb.AttesterSlashing{},
VoluntaryExits: []*ethpb.VoluntaryExit{},

View File

@@ -41,7 +41,7 @@ func TestProposeBlock_OK(t *testing.T) {
numDeposits := params.BeaconConfig().MinGenesisActiveValidatorCount
deposits, _, _ := testutil.SetupInitialDeposits(t, numDeposits)
beaconState, err := state.GenesisBeaconState(deposits, 0, &ethpb.Eth1Data{})
beaconState, err := state.GenesisBeaconState(deposits, 0, &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Fatalf("Could not instantiate genesis state: %v", err)
}
@@ -85,7 +85,7 @@ func TestComputeStateRoot_OK(t *testing.T) {
helpers.ClearAllCaches()
deposits, _, privKeys := testutil.SetupInitialDeposits(t, 100)
beaconState, err := state.GenesisBeaconState(deposits, 0, &ethpb.Eth1Data{})
beaconState, err := state.GenesisBeaconState(deposits, 0, &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Fatalf("Could not instantiate genesis state: %v", err)
}
@@ -946,7 +946,7 @@ func TestEth1Data(t *testing.T) {
p := &mockPOW.POWChain{
BlockNumberByHeight: map[uint64]*big.Int{
60000: big.NewInt(4096),
slot * params.BeaconConfig().SecondsPerSlot: big.NewInt(4096),
},
HashesByHeight: map[int][]byte{
3072: []byte("3072"),

View File

@@ -26,7 +26,7 @@ import (
// ValidatorServer defines a server implementation of the gRPC Validator service,
// providing RPC endpoints for obtaining validator assignments per epoch, the slots
// and shards in which particular validators need to perform their responsibilities,
// and committees in which particular validators need to perform their responsibilities,
// and more.
type ValidatorServer struct {
ctx context.Context
@@ -201,17 +201,17 @@ func (vs *ValidatorServer) CommitteeAssignment(ctx context.Context, req *pb.Assi
}
func (vs *ValidatorServer) assignment(idx uint64, beaconState *pbp2p.BeaconState, epoch uint64) (*pb.AssignmentResponse_ValidatorAssignment, error) {
committee, shard, slot, isProposer, err := helpers.CommitteeAssignment(beaconState, epoch, idx)
committee, committeeIndex, aSlot, pSlot, err := helpers.CommitteeAssignment(beaconState, epoch, idx)
if err != nil {
return nil, err
}
status := vs.assignmentStatus(idx, beaconState)
return &pb.AssignmentResponse_ValidatorAssignment{
Committee: committee,
Shard: shard,
Slot: slot,
IsProposer: isProposer,
Status: status,
Committee: committee,
CommitteeIndex: committeeIndex,
AttesterSlot: aSlot,
ProposerSlot: pSlot,
Status: status,
}, nil
}

View File

@@ -68,7 +68,7 @@ func TestNextEpochCommitteeAssignment_WrongPubkeyLength(t *testing.T) {
helpers.ClearAllCaches()
deposits, _, _ := testutil.SetupInitialDeposits(t, 8)
beaconState, err := state.GenesisBeaconState(deposits, 0, &ethpb.Eth1Data{})
beaconState, err := state.GenesisBeaconState(deposits, 0, &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Fatal(err)
}
@@ -101,7 +101,7 @@ func TestNextEpochCommitteeAssignment_CantFindValidatorIdx(t *testing.T) {
defer dbutil.TeardownDB(t, db)
ctx := context.Background()
deposits, _, _ := testutil.SetupInitialDeposits(t, params.BeaconConfig().MinGenesisActiveValidatorCount)
beaconState, err := state.GenesisBeaconState(deposits, 0, &ethpb.Eth1Data{})
beaconState, err := state.GenesisBeaconState(deposits, 0, &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Fatalf("Could not setup genesis state: %v", err)
}
@@ -138,7 +138,7 @@ func TestCommitteeAssignment_OK(t *testing.T) {
depChainStart := params.BeaconConfig().MinGenesisActiveValidatorCount / 16
deposits, _, _ := testutil.SetupInitialDeposits(t, depChainStart)
state, err := state.GenesisBeaconState(deposits, 0, &ethpb.Eth1Data{})
state, err := state.GenesisBeaconState(deposits, 0, &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Fatalf("Could not setup genesis state: %v", err)
}
@@ -180,13 +180,9 @@ func TestCommitteeAssignment_OK(t *testing.T) {
if err != nil {
t.Fatalf("Could not call epoch committee assignment %v", err)
}
if res.ValidatorAssignment[0].Shard >= params.BeaconConfig().ShardCount {
t.Errorf("Assigned shard %d can't be higher than %d",
res.ValidatorAssignment[0].Shard, params.BeaconConfig().ShardCount)
}
if res.ValidatorAssignment[0].Slot > state.Slot+params.BeaconConfig().SlotsPerEpoch {
if res.ValidatorAssignment[0].AttesterSlot > state.Slot+params.BeaconConfig().SlotsPerEpoch {
t.Errorf("Assigned slot %d can't be higher than %d",
res.ValidatorAssignment[0].Slot, state.Slot+params.BeaconConfig().SlotsPerEpoch)
res.ValidatorAssignment[0].AttesterSlot, state.Slot+params.BeaconConfig().SlotsPerEpoch)
}
// Test the last validator in registry.
@@ -199,13 +195,9 @@ func TestCommitteeAssignment_OK(t *testing.T) {
if err != nil {
t.Fatalf("Could not call epoch committee assignment %v", err)
}
if res.ValidatorAssignment[0].Shard >= params.BeaconConfig().ShardCount {
t.Errorf("Assigned shard %d can't be higher than %d",
res.ValidatorAssignment[0].Shard, params.BeaconConfig().ShardCount)
}
if res.ValidatorAssignment[0].Slot > state.Slot+params.BeaconConfig().SlotsPerEpoch {
if res.ValidatorAssignment[0].AttesterSlot > state.Slot+params.BeaconConfig().SlotsPerEpoch {
t.Errorf("Assigned slot %d can't be higher than %d",
res.ValidatorAssignment[0].Slot, state.Slot+params.BeaconConfig().SlotsPerEpoch)
res.ValidatorAssignment[0].AttesterSlot, state.Slot+params.BeaconConfig().SlotsPerEpoch)
}
}
@@ -219,7 +211,7 @@ func TestCommitteeAssignment_CurrentEpoch_ShouldNotFail(t *testing.T) {
depChainStart := params.BeaconConfig().MinGenesisActiveValidatorCount / 16
deposits, _, _ := testutil.SetupInitialDeposits(t, depChainStart)
state, err := state.GenesisBeaconState(deposits, 0, &ethpb.Eth1Data{})
state, err := state.GenesisBeaconState(deposits, 0, &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Fatalf("Could not setup genesis state: %v", err)
}
@@ -276,7 +268,7 @@ func TestCommitteeAssignment_MultipleKeys_OK(t *testing.T) {
genesis := blk.NewGenesisBlock([]byte{})
depChainStart := params.BeaconConfig().MinGenesisActiveValidatorCount / 16
deposits, _, _ := testutil.SetupInitialDeposits(t, depChainStart)
state, err := state.GenesisBeaconState(deposits, 0, &ethpb.Eth1Data{})
state, err := state.GenesisBeaconState(deposits, 0, &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
if err != nil {
t.Fatalf("Could not setup genesis state: %v", err)
}
@@ -534,7 +526,7 @@ func TestValidatorStatus_Active(t *testing.T) {
expected := &pb.ValidatorStatusResponse{
Status: pb.ValidatorStatus_ACTIVE,
ActivationEpoch: 5,
DepositInclusionSlot: 3413,
DepositInclusionSlot: 2218,
}
if !proto.Equal(resp, expected) {
t.Errorf("Wanted %v, got %v", expected, resp)
@@ -1000,7 +992,7 @@ func TestWaitForActivation_ValidatorOriginallyExists(t *testing.T) {
Status: &pb.ValidatorStatusResponse{
Status: pb.ValidatorStatus_ACTIVE,
Eth1DepositBlockNumber: 10,
DepositInclusionSlot: 3413,
DepositInclusionSlot: 2218,
},
},
{PublicKey: pubKey2,
@@ -1276,13 +1268,6 @@ func BenchmarkAssignment(b *testing.B) {
EpochStart: 0,
}
// Precache the shuffled indices
for i := uint64(0); i < validatorCount/params.BeaconConfig().TargetCommitteeSize; i++ {
if _, err := helpers.CrosslinkCommittee(state, 0, i); err != nil {
b.Fatal(err)
}
}
b.ResetTimer()
for n := 0; n < b.N; n++ {
if _, err := vs.CommitteeAssignment(context.Background(), req); err != nil {

View File

@@ -96,28 +96,28 @@ func TestRoundRobinSync(t *testing.T) {
},
{
name: "Multiple peers with failures",
currentSlot: 320, // 5 epochs
currentSlot: 320, // 10 epochs
expectedBlockSlots: makeSequence(1, 320),
peers: []*peerData{
{
blocks: makeSequence(1, 320),
finalizedEpoch: 4,
finalizedEpoch: 8,
headSlot: 320,
},
{
blocks: makeSequence(1, 320),
finalizedEpoch: 4,
finalizedEpoch: 8,
headSlot: 320,
failureSlots: makeSequence(1, 64), // first epoch
failureSlots: makeSequence(1, 32), // first epoch
},
{
blocks: makeSequence(1, 320),
finalizedEpoch: 4,
finalizedEpoch: 8,
headSlot: 320,
},
{
blocks: makeSequence(1, 320),
finalizedEpoch: 4,
finalizedEpoch: 8,
headSlot: 320,
},
},
@@ -129,17 +129,17 @@ func TestRoundRobinSync(t *testing.T) {
peers: []*peerData{
{
blocks: append(makeSequence(1, 64), makeSequence(500, 640)...),
finalizedEpoch: 9,
finalizedEpoch: 18,
headSlot: 640,
},
{
blocks: append(makeSequence(1, 64), makeSequence(500, 640)...),
finalizedEpoch: 9,
finalizedEpoch: 18,
headSlot: 640,
},
{
blocks: append(makeSequence(1, 64), makeSequence(500, 640)...),
finalizedEpoch: 9,
finalizedEpoch: 18,
headSlot: 640,
},
},
@@ -148,7 +148,7 @@ func TestRoundRobinSync(t *testing.T) {
// TODO(3147): Handle multiple failures.
//{
// name: "Multiple peers with multiple failures",
// currentSlot: 320, // 5 epochs
// currentSlot: 320, // 10 epochs
// expectedBlockSlots: makeSequence(1, 320),
// peers: []*peerData{
// {
@@ -178,7 +178,7 @@ func TestRoundRobinSync(t *testing.T) {
//},
{
name: "Multiple peers with different finalized epoch",
currentSlot: 320, // 5 epochs
currentSlot: 320, // 10 epochs
expectedBlockSlots: makeSequence(1, 320),
peers: []*peerData{
{

View File

@@ -2,6 +2,7 @@ package sync
import (
"context"
"fmt"
"testing"
"github.com/prysmaticlabs/go-ssz"
@@ -39,7 +40,7 @@ func TestRegularSyncBeaconBlockSubscriber_FilterByFinalizedEpoch(t *testing.T) {
if err := r.beaconBlockSubscriber(context.Background(), b); err != nil {
t.Fatal(err)
}
testutil.AssertLogsContain(t, hook, "Received a block older than finalized checkpoint, 1 < 64")
testutil.AssertLogsContain(t, hook, fmt.Sprintf("Received a block older than finalized checkpoint, 1 < %d", params.BeaconConfig().SlotsPerEpoch))
hook.Reset()
b.Slot = params.BeaconConfig().SlotsPerEpoch

View File

@@ -21,7 +21,7 @@ import (
func setupValidAttesterSlashing(t *testing.T) (*ethpb.AttesterSlashing, *pb.BeaconState) {
deposits, _, privKeys := testutil.SetupInitialDeposits(t, 5)
state, err := state.GenesisBeaconState(deposits, 0, &ethpb.Eth1Data{})
state, err := state.GenesisBeaconState(deposits, 0, &ethpb.Eth1Data{BlockHash: make([]byte, 32)})
for _, vv := range state.Validators {
vv.WithdrawableEpoch = 1 * params.BeaconConfig().SlotsPerEpoch
}
@@ -30,9 +30,6 @@ func setupValidAttesterSlashing(t *testing.T) (*ethpb.AttesterSlashing, *pb.Beac
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 1},
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{
Shard: 4,
},
},
CustodyBit_0Indices: []uint64{0, 1},
}
@@ -44,7 +41,7 @@ func setupValidAttesterSlashing(t *testing.T) (*ethpb.AttesterSlashing, *pb.Beac
if err != nil {
t.Error(err)
}
domain := helpers.Domain(state.Fork, 0, params.BeaconConfig().DomainAttestation)
domain := helpers.Domain(state.Fork, 0, params.BeaconConfig().DomainBeaconAttester)
sig0 := privKeys[0].Sign(hashTreeRoot[:], domain)
sig1 := privKeys[1].Sign(hashTreeRoot[:], domain)
aggregateSig := bls.AggregateSignatures([]*bls.Signature{sig0, sig1})
@@ -54,9 +51,6 @@ func setupValidAttesterSlashing(t *testing.T) (*ethpb.AttesterSlashing, *pb.Beac
Data: &ethpb.AttestationData{
Source: &ethpb.Checkpoint{Epoch: 0},
Target: &ethpb.Checkpoint{Epoch: 0},
Crosslink: &ethpb.Crosslink{
Shard: 4,
},
},
CustodyBit_0Indices: []uint64{0, 1},
}

View File

@@ -101,7 +101,6 @@ func TestValidateBeaconBlockPubSub_BlockAlreadyPresentInCache(t *testing.T) {
t.Fatal(err)
}
msg := &ethpb.BeaconBlock{
Slot: 1,
ParentRoot: testutil.Random32Bytes(t),
Signature: sk.Sign([]byte("data"), 0).Marshal(),
}
@@ -160,7 +159,6 @@ func TestValidateBeaconBlockPubSub_ValidSignature(t *testing.T) {
t.Fatal(err)
}
msg := &ethpb.BeaconBlock{
Slot: 1,
ParentRoot: testutil.Random32Bytes(t),
Signature: sk.Sign([]byte("data"), 0).Marshal(),
}
@@ -237,7 +235,6 @@ func TestValidateBeaconBlockPubSub_Syncing(t *testing.T) {
t.Fatal(err)
}
msg := &ethpb.BeaconBlock{
Slot: 1,
ParentRoot: testutil.Random32Bytes(t),
Signature: sk.Sign([]byte("data"), 0).Marshal(),
}

View File

@@ -43,9 +43,9 @@ func setupValidProposerSlashing(t *testing.T) (*ethpb.ProposerSlashing, *pb.Beac
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
Epoch: 0,
},
Slashings: make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector),
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
ActiveIndexRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
Slashings: make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector),
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
StateRoots: make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot),
BlockRoots: make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot),
LatestBlockHeader: &ethpb.BeaconBlockHeader{},

View File

@@ -25,11 +25,19 @@ go_library(
go_test(
name = "go_default_test",
size = "small",
srcs = ["depositContract_test.go"],
size = "medium",
srcs = [
"depositContract_test.go",
"deposit_tree_test.go",
],
embed = [":go_default_library"],
deps = [
"//shared/interop:go_default_library",
"//shared/params:go_default_library",
"//shared/trieutil:go_default_library",
"@com_github_ethereum_go_ethereum//:go_default_library",
"@com_github_ethereum_go_ethereum//accounts/abi/bind:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_prysmaticlabs_go_ssz//:go_default_library",
],
)

View File

@@ -29,7 +29,7 @@ To generate the abi using the vyper compiler, you can use
```
vyper -f abi ./depositContract.v.py > abi.json
docker run -v $(pwd):/code ethereum/vyper:0.1.0b12 -f abi /code/depositContract.v.py > abi.json
```
@@ -39,7 +39,7 @@ To generate the bytecode you can then use
```
vyper ./depositContract.v.py > bytecode.bin
docker run -v $(pwd):/code ethereum/vyper:0.1.0b12 /code/depositContract.v.py > bytecode.bin
```
@@ -47,31 +47,32 @@ and save the bytecode in `bytecode.bin` in the folder. Now with both the abi and
we can generate the go bindings.
```
abigen -bin ./bytecode.bin -abi ./abi.json -out ./depositContract.go --pkg depositcontract --type DepositContract
bazel run @com_github_ethereum_go_ethereum//cmd/abigen -- -bin $(pwd)/bytecode.bin -abi $(pwd)/abi.json -out $(pwd)/depositContract.go --pkg depositcontract --type DepositContract
```
## How to execute tests
```
go test ./...
bazel test //contracts/deposit-contract:go_default_test
```
Run with `-v` option for detailed log output
```
go test ./... -v
=== RUN TestSetupAndContractRegistration
--- PASS: TestSetupAndContractRegistration (0.01s)
=== RUN TestRegisterWithLessThan32Eth
--- PASS: TestRegisterWithLessThan32Eth (0.00s)
=== RUN TestRegisterWithMoreThan32Eth
--- PASS: TestRegisterWithMoreThan32Eth (0.00s)
=== RUN TestRegisterTwice
--- PASS: TestRegisterTwice (0.01s)
=== RUN TestRegister
--- PASS: TestRegister (0.01s)
bazel test //contracts/deposit-contract:go_default_test --test_arg=-test.v --test_output=streamed
=== RUN TestSetupRegistrationContract_OK
--- PASS: TestSetupRegistrationContract_OK (0.07s)
=== RUN TestRegister_Below1ETH
--- PASS: TestRegister_Below1ETH (0.02s)
=== RUN TestRegister_Above32Eth
--- PASS: TestRegister_Above32Eth (0.02s)
=== RUN TestValidatorRegister_OK
--- PASS: TestValidatorRegister_OK (0.08s)
=== RUN TestDrain
--- PASS: TestDrain (0.04s)
PASS
ok beacon-chain/contracts/deposit-contract/ 0.151s
ok contracts/deposit-contract 0.633s
```

View File

@@ -1 +1 @@
[{"name": "DepositEvent", "inputs": [{"type": "bytes", "name": "pubkey", "indexed": false}, {"type": "bytes", "name": "withdrawal_credentials", "indexed": false}, {"type": "bytes", "name": "amount", "indexed": false}, {"type": "bytes", "name": "signature", "indexed": false}, {"type": "bytes", "name": "index", "indexed": false}], "anonymous": false, "type": "event"}, {"outputs": [], "inputs": [{"type": "uint256", "name": "minDeposit"}, {"type": "address", "name": "_drain_address"}], "constant": false, "payable": false, "type": "constructor"}, {"name": "get_hash_tree_root", "outputs": [{"type": "bytes32", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 91734}, {"name": "get_deposit_count", "outputs": [{"type": "bytes", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 10493}, {"name": "deposit", "outputs": [], "inputs": [{"type": "bytes", "name": "pubkey"}, {"type": "bytes", "name": "withdrawal_credentials"}, {"type": "bytes", "name": "signature"}], "constant": false, "payable": true, "type": "function", "gas": 1334707}, {"name": "drain", "outputs": [], "inputs": [], "constant": false, "payable": false, "type": "function", "gas": 35823}, {"name": "MIN_DEPOSIT_AMOUNT", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 663}, {"name": "deposit_count", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 693}, {"name": "drain_address", "outputs": [{"type": "address", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 723}]
[{"name": "DepositEvent", "inputs": [{"type": "bytes", "name": "pubkey", "indexed": false}, {"type": "bytes", "name": "withdrawal_credentials", "indexed": false}, {"type": "bytes", "name": "amount", "indexed": false}, {"type": "bytes", "name": "signature", "indexed": false}, {"type": "bytes", "name": "index", "indexed": false}], "anonymous": false, "type": "event"}, {"outputs": [], "inputs": [{"type": "address", "name": "_drain_address"}], "constant": false, "payable": false, "type": "constructor"}, {"name": "get_deposit_root", "outputs": [{"type": "bytes32", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 95389}, {"name": "get_deposit_count", "outputs": [{"type": "bytes", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 17683}, {"name": "deposit", "outputs": [], "inputs": [{"type": "bytes", "name": "pubkey"}, {"type": "bytes", "name": "withdrawal_credentials"}, {"type": "bytes", "name": "signature"}, {"type": "bytes32", "name": "deposit_data_root"}], "constant": false, "payable": true, "type": "function", "gas": 1754607}, {"name": "drain", "outputs": [], "inputs": [], "constant": false, "payable": false, "type": "function", "gas": 35793}, {"name": "drain_address", "outputs": [{"type": "address", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 663}]

File diff suppressed because one or more lines are too long

View File

@@ -7,7 +7,6 @@ go_library(
visibility = ["//visibility:private"],
deps = [
"//contracts/deposit-contract:go_default_library",
"//shared/params:go_default_library",
"//shared/version:go_default_library",
"@com_github_ethereum_go_ethereum//accounts/abi/bind:go_default_library",
"@com_github_ethereum_go_ethereum//accounts/keystore:go_default_library",

View File

@@ -11,15 +11,11 @@ This is a utility to help users deploy deposit contract for running their own be
deployContract [global options] command [command options] [arguments...]
*Flags:*
- --skipChainstartDelay Whether to skip ChainStart log being fired a day later
- --ipcPath value Filename for IPC socket/pipe within the datadir
- --httpPath value HTTP-RPC server listening interface (default: "http://localhost:8545/")
- --passwordFile value Password file for unlock account (default: "./password.txt")
- --privKey value Private key to unlock account
- --k8sConfig value Name of kubernetes config map to update with the contract address
- --chainStart value Number of validators required for chain start (default: 16384)
- --minDeposit value Minimum deposit value allowed in contract (default: 1000000000)
- --maxDeposit value Maximum deposit value allowed in contract (default: 32000000000)
- --help, -h show help
- --version, -v print the version
@@ -28,7 +24,7 @@ This is a utility to help users deploy deposit contract for running their own be
To use private key with default RPC:
```
bazel run //contracts/deposit-contract/deployContract -- --httpPath=https://goerli.prylabs.net --privKey=$(echo /path/to/private/key/file) --chainStart=8 --minDeposit=100 --maxDeposit=3200
bazel run //contracts/deposit-contract/deployContract -- --httpPath=https://goerli.prylabs.net --privKey=$(echo /path/to/private/key/file)
```

View File

@@ -16,7 +16,6 @@ import (
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/rpc"
contracts "github.com/prysmaticlabs/prysm/contracts/deposit-contract"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/version"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
@@ -33,10 +32,6 @@ func main() {
var httpPath string
var privKeyString string
var k8sConfigMapName string
var depositsForChainStart int64
var minDepositAmount int64
var maxDepositAmount int64
var customChainstartDelay uint64
var drainAddress string
customFormatter := new(prefixed.TextFormatter)
@@ -55,12 +50,6 @@ func main() {
Usage: "Location of keystore",
Destination: &keystoreUTCPath,
},
cli.Uint64Flag{
Name: "customChainstartDelay",
Usage: "Number of seconds to delay the ChainStart genesis timestamp",
Value: 0,
Destination: &customChainstartDelay,
},
cli.StringFlag{
Name: "ipcPath",
Usage: "Filename for IPC socket/pipe within the datadir",
@@ -88,24 +77,6 @@ func main() {
Usage: "Name of kubernetes config map to update with the contract address",
Destination: &k8sConfigMapName,
},
cli.Int64Flag{
Name: "chainStart",
Value: params.ContractConfig().MinGenesisActiveValidatorCount.Int64(),
Usage: "Number of validators required for chain start",
Destination: &depositsForChainStart,
},
cli.Int64Flag{
Name: "minDeposit",
Value: params.ContractConfig().MinDepositAmount.Int64(),
Usage: "Minimum deposit value allowed in contract",
Destination: &minDepositAmount,
},
cli.Int64Flag{
Name: "maxDeposit",
Value: params.ContractConfig().MaxEffectiveBalance.Int64(),
Usage: "Maximum deposit value allowed in contract",
Destination: &maxDepositAmount,
},
cli.StringFlag{
Name: "drainAddress",
Value: "",
@@ -180,7 +151,6 @@ func main() {
addr, tx, _, err := contracts.DeployDepositContract(
txOps,
client,
big.NewInt(minDepositAmount),
drain,
)

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More