mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 21:38:05 -05:00
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:
committed by
Preston Van Loon
parent
62aaec1e20
commit
81c53c26fb
106
WORKSPACE
106
WORKSPACE
@@ -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",
|
||||
)
|
||||
|
||||
@@ -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",
|
||||
],
|
||||
|
||||
@@ -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 := ðpb.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")
|
||||
|
||||
@@ -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 := ðpb.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: ðpb.AttestationData{Crosslink: ðpb.Crosslink{Shard: 0}, Target: ðpb.Checkpoint{}}}}
|
||||
var crosslinks []*ethpb.Crosslink
|
||||
for i := uint64(0); i < params.BeaconConfig().ShardCount; i++ {
|
||||
crosslinks = append(crosslinks, ðpb.Crosslink{
|
||||
StartEpoch: 0,
|
||||
DataRoot: []byte{'A'},
|
||||
})
|
||||
}
|
||||
atts := []*pb.PendingAttestation{{Data: ðpb.AttestationData{Target: ðpb.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: ðpb.Checkpoint{},
|
||||
JustificationBits: bitfield.Bitvector4{0x00},
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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] = ðpb.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: ðpb.BeaconBlockHeader{},
|
||||
JustificationBits: []byte{0},
|
||||
CurrentJustifiedCheckpoint: ðpb.Checkpoint{},
|
||||
CurrentCrosslinks: crosslinks,
|
||||
CompactCommitteesRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
|
||||
Slashings: make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector),
|
||||
FinalizedCheckpoint: ðpb.Checkpoint{},
|
||||
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
|
||||
StateRoots: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
|
||||
BlockRoots: make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot),
|
||||
LatestBlockHeader: ðpb.BeaconBlockHeader{},
|
||||
JustificationBits: []byte{0},
|
||||
Slashings: make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector),
|
||||
FinalizedCheckpoint: ðpb.Checkpoint{},
|
||||
}
|
||||
if err := store.GenesisStore(ctx, ðpb.Checkpoint{}, ðpb.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)}
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -133,7 +133,7 @@ func TestStore_UpdateBlockAttestationVote(t *testing.T) {
|
||||
params.UseMinimalConfig()
|
||||
|
||||
deposits, _, _ := testutil.SetupInitialDeposits(t, 100)
|
||||
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), ðpb.Eth1Data{})
|
||||
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), ðpb.Eth1Data{BlockHash: make([]byte, 32)})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -144,10 +144,6 @@ func TestStore_UpdateBlockAttestationVote(t *testing.T) {
|
||||
Data: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 0, Root: params.BeaconConfig().ZeroHash[:]},
|
||||
Target: ðpb.Checkpoint{Epoch: 0, Root: r[:]},
|
||||
Crosslink: ðpb.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), ðpb.Eth1Data{})
|
||||
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), ðpb.Eth1Data{BlockHash: make([]byte, 32)})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -201,10 +197,6 @@ func TestStore_UpdateBlockAttestationsVote(t *testing.T) {
|
||||
Data: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 0, Root: params.BeaconConfig().ZeroHash[:]},
|
||||
Target: ðpb.Checkpoint{Epoch: 0, Root: r[:]},
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: uint64(i),
|
||||
StartEpoch: 0,
|
||||
},
|
||||
},
|
||||
AggregationBits: []byte{255},
|
||||
CustodyBits: []byte{255},
|
||||
|
||||
@@ -35,8 +35,7 @@ func TestReceiveAttestation_ProcessCorrectly(t *testing.T) {
|
||||
}
|
||||
|
||||
a := ðpb.Attestation{Data: ðpb.AttestationData{
|
||||
Target: ðpb.Checkpoint{Root: root[:]},
|
||||
Crosslink: ðpb.Crosslink{},
|
||||
Target: ðpb.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 := ðpb.Attestation{Data: ðpb.AttestationData{
|
||||
Target: ðpb.Checkpoint{Root: root[:]},
|
||||
Crosslink: ðpb.Crosslink{},
|
||||
Target: ðpb.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 := ðpb.Attestation{Data: ðpb.AttestationData{
|
||||
Target: ðpb.Checkpoint{Root: root[:]},
|
||||
Crosslink: ðpb.Crosslink{},
|
||||
Target: ðpb.Checkpoint{Root: root[:]},
|
||||
}}
|
||||
if err := chainService.ReceiveAttestationNoPubsub(ctx, a); err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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, ðpb.Eth1Data{})
|
||||
beaconState, err := state.GenesisBeaconState(deposits, 0, ðpb.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, ðpb.Eth1Data{})
|
||||
beaconState, err := state.GenesisBeaconState(deposits, 0, ðpb.Eth1Data{BlockHash: make([]byte, 32)})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
2
beacon-chain/cache/BUILD.bazel
vendored
2
beacon-chain/cache/BUILD.bazel
vendored
@@ -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",
|
||||
|
||||
2
beacon-chain/cache/attestation_data.go
vendored
2
beacon-chain/cache/attestation_data.go
vendored
@@ -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 {
|
||||
|
||||
4
beacon-chain/cache/attestation_data_test.go
vendored
4
beacon-chain/cache/attestation_data_test.go
vendored
@@ -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)
|
||||
|
||||
64
beacon-chain/cache/committee.go
vendored
64
beacon-chain/cache/committee.go
vendored
@@ -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
|
||||
}
|
||||
|
||||
78
beacon-chain/cache/committee_test.go
vendored
78
beacon-chain/cache/committee_test.go
vendored
@@ -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()
|
||||
|
||||
|
||||
106
beacon-chain/cache/shuffled_indices.go
vendored
106
beacon-chain/cache/shuffled_indices.go
vendored
@@ -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
|
||||
}
|
||||
93
beacon-chain/cache/shuffled_indices_test.go
vendored
93
beacon-chain/cache/shuffled_indices_test.go
vendored
@@ -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()),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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",
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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, ðpb.Eth1Data{})
|
||||
beaconState, err := state.GenesisBeaconState(deposits, 0, ðpb.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] = ðpb.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] = ðpb.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] = ðpb.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] = ðpb.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), ðpb.Eth1Data{})
|
||||
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), ðpb.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), ðpb.Eth1Data{})
|
||||
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), ðpb.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] = ðpb.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: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 0},
|
||||
Target: ðpb.Checkpoint{Epoch: 0},
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
Attestation_2: ðpb.IndexedAttestation{
|
||||
Data: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 1},
|
||||
Target: ðpb.Checkpoint{Epoch: 1},
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: 3,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -685,9 +652,6 @@ func TestProcessAttesterSlashings_IndexedAttestationFailedToVerify(t *testing.T)
|
||||
Data: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 1},
|
||||
Target: ðpb.Checkpoint{Epoch: 0},
|
||||
Crosslink: ðpb.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: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 0},
|
||||
Target: ðpb.Checkpoint{Epoch: 0},
|
||||
Crosslink: ðpb.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: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 1},
|
||||
Target: ðpb.Checkpoint{Epoch: 0},
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: 4,
|
||||
},
|
||||
},
|
||||
CustodyBit_0Indices: make([]uint64, params.BeaconConfig().MaxValidatorsPerCommittee+1),
|
||||
},
|
||||
@@ -739,9 +697,6 @@ func TestProcessAttesterSlashings_IndexedAttestationFailedToVerify(t *testing.T)
|
||||
Data: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 0},
|
||||
Target: ðpb.Checkpoint{Epoch: 0},
|
||||
Crosslink: ðpb.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, ðpb.Eth1Data{})
|
||||
beaconState, err := state.GenesisBeaconState(deposits, 0, ðpb.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: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 1},
|
||||
Target: ðpb.Checkpoint{Epoch: 0},
|
||||
Crosslink: ðpb.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: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 0},
|
||||
Target: ðpb.Checkpoint{Epoch: 0},
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: 4,
|
||||
},
|
||||
},
|
||||
CustodyBit_0Indices: []uint64{0, 1},
|
||||
}
|
||||
@@ -851,9 +800,7 @@ func TestProcessAttestations_InclusionDelayFailure(t *testing.T) {
|
||||
{
|
||||
Data: ðpb.AttestationData{
|
||||
Target: ðpb.Checkpoint{Epoch: 0},
|
||||
Crosslink: ðpb.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), ðpb.Eth1Data{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
attestationSlot, err := helpers.AttestationDataSlot(beaconState, attestations[0].Data)
|
||||
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), ðpb.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 := ðpb.Attestation{
|
||||
Data: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
|
||||
Target: ðpb.Checkpoint{Epoch: 0},
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: 0,
|
||||
StartEpoch: 0,
|
||||
},
|
||||
},
|
||||
}
|
||||
Target: ðpb.Checkpoint{Epoch: 0}}}
|
||||
|
||||
block := ðpb.BeaconBlock{
|
||||
Body: ðpb.BeaconBlockBody{
|
||||
@@ -905,17 +841,12 @@ func TestProcessAttestations_NeitherCurrentNorPrevEpoch(t *testing.T) {
|
||||
},
|
||||
}
|
||||
deposits, _, _ := testutil.SetupInitialDeposits(t, 100)
|
||||
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), ðpb.Eth1Data{})
|
||||
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), ðpb.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: ðpb.AttestationData{
|
||||
Target: ðpb.Checkpoint{Epoch: 0},
|
||||
Source: ðpb.Checkpoint{Epoch: 1},
|
||||
Crosslink: ðpb.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), ðpb.Eth1Data{})
|
||||
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), ðpb.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), ðpb.Eth1Data{})
|
||||
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), ðpb.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: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 1},
|
||||
Target: ðpb.Checkpoint{Epoch: 1},
|
||||
Crosslink: ðpb.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: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
|
||||
Target: ðpb.Checkpoint{Epoch: 0},
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: 0,
|
||||
},
|
||||
},
|
||||
AggregationBits: aggBits,
|
||||
CustodyBits: custodyBits,
|
||||
},
|
||||
}
|
||||
block := ðpb.BeaconBlock{
|
||||
Body: ðpb.BeaconBlockBody{
|
||||
Attestations: attestations,
|
||||
},
|
||||
}
|
||||
deposits, _, _ := testutil.SetupInitialDeposits(t, 100)
|
||||
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), ðpb.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), ðpb.Eth1Data{})
|
||||
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), ðpb.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 := ðpb.Attestation{
|
||||
Data: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
|
||||
Target: ðpb.Checkpoint{Epoch: 0},
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: 0,
|
||||
StartEpoch: 0,
|
||||
},
|
||||
},
|
||||
Target: ðpb.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), ðpb.Eth1Data{})
|
||||
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), ðpb.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 := ðpb.Attestation{
|
||||
Data: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
|
||||
Target: ðpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
|
||||
Crosslink: ðpb.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), ðpb.Eth1Data{})
|
||||
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), ðpb.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 := ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
|
||||
Target: ðpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
|
||||
Crosslink: ðpb.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), ðpb.Eth1Data{})
|
||||
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), ðpb.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 := ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
|
||||
Target: ðpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
|
||||
Crosslink: ðpb.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 := ðpb.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 := ðpb.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), ðpb.Eth1Data{})
|
||||
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), ðpb.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 := ðpb.Attestation{
|
||||
Data: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
|
||||
Target: ðpb.Checkpoint{Epoch: 0},
|
||||
Crosslink: ðpb.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: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 0},
|
||||
Target: ðpb.Checkpoint{Epoch: 0},
|
||||
Crosslink: ðpb.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 := ðpb.BeaconBlock{
|
||||
Body: ðpb.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 := ðpb.BeaconBlock{
|
||||
Body: ðpb.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] = ðpb.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 := ðpb.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 := ðpb.BeaconBlock{
|
||||
Body: ðpb.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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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",
|
||||
],
|
||||
|
||||
@@ -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 ðpb.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
|
||||
}
|
||||
|
||||
@@ -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: ðpb.AttestationData{Source: ðpb.Checkpoint{},
|
||||
Target: ðpb.Checkpoint{Epoch: 0},
|
||||
Crosslink: ðpb.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: ðpb.AttestationData{Source: ðpb.Checkpoint{},
|
||||
Target: ðpb.Checkpoint{Epoch: 0},
|
||||
Crosslink: ðpb.Crosslink{},
|
||||
},
|
||||
Target: ðpb.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: ðpb.AttestationData{
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: uint64(i),
|
||||
},
|
||||
Target: ðpb.Checkpoint{},
|
||||
Source: ðpb.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: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, Target: ðpb.Checkpoint{}}}, // source
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, Target: ðpb.Checkpoint{Root: []byte{1}}}}, // source, target
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, Target: ðpb.Checkpoint{Root: []byte{3}}}}, // source
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, Target: ðpb.Checkpoint{Root: []byte{1}}}}, // source, target
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{66}, Target: ðpb.Checkpoint{}}}, // source, head
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{4}, Target: ðpb.Checkpoint{}}}, // source
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{66}, Target: ðpb.Checkpoint{Root: []byte{1}}}}, // source, target, head
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{5}, Target: ðpb.Checkpoint{Root: []byte{1}}}}, // source, target
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{66}, Target: ðpb.Checkpoint{Root: []byte{6}}}}, // source, head
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Target: ðpb.Checkpoint{}}}, // source
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Target: ðpb.Checkpoint{Root: []byte{1}}}}, // source, target
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Target: ðpb.Checkpoint{Root: []byte{3}}}}, // source
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Target: ðpb.Checkpoint{Root: []byte{1}}}}, // source, target
|
||||
{Data: ðpb.AttestationData{Slot: 33, Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: ðpb.Checkpoint{}}}, // source, head
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{4}, Target: ðpb.Checkpoint{}}}, // source
|
||||
{Data: ðpb.AttestationData{Slot: 33, Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: ðpb.Checkpoint{Root: []byte{1}}}}, // source, target, head
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{5}, Target: ðpb.Checkpoint{Root: []byte{1}}}}, // source, target
|
||||
{Data: ðpb.AttestationData{Slot: 33, Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: ðpb.Checkpoint{Root: []byte{6}}}}, // source, head
|
||||
}
|
||||
|
||||
currentAtts := []*pb.PendingAttestation{
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + e + 1}, Target: ðpb.Checkpoint{}}}, // none
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + e + 1}, BeaconBlockRoot: []byte{2}, Target: ðpb.Checkpoint{Root: []byte{1}}}}, // none
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Target: ðpb.Checkpoint{}}}, // none
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{2}, Target: ðpb.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: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, Target: ðpb.Checkpoint{}}},
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, Target: ðpb.Checkpoint{Root: []byte{1}}}},
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, Target: ðpb.Checkpoint{Root: []byte{3}}}},
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, Target: ðpb.Checkpoint{Root: []byte{1}}}},
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{66}, Target: ðpb.Checkpoint{}}},
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{4}, Target: ðpb.Checkpoint{}}},
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{66}, Target: ðpb.Checkpoint{Root: []byte{1}}}},
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{5}, Target: ðpb.Checkpoint{Root: []byte{1}}}},
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{66}, Target: ðpb.Checkpoint{Root: []byte{6}}}},
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Target: ðpb.Checkpoint{}}},
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Target: ðpb.Checkpoint{Root: []byte{1}}}},
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Target: ðpb.Checkpoint{Root: []byte{3}}}},
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Target: ðpb.Checkpoint{Root: []byte{1}}}},
|
||||
{Data: ðpb.AttestationData{Slot: 33, Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: ðpb.Checkpoint{}}},
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{4}, Target: ðpb.Checkpoint{}}},
|
||||
{Data: ðpb.AttestationData{Slot: 33, Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: ðpb.Checkpoint{Root: []byte{1}}}},
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{5}, Target: ðpb.Checkpoint{Root: []byte{1}}}},
|
||||
{Data: ðpb.AttestationData{Slot: 33, Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: ðpb.Checkpoint{Root: []byte{6}}}},
|
||||
}
|
||||
if !reflect.DeepEqual(mAtts.source, wantedSrcAtts) {
|
||||
t.Error("source attestations don't match")
|
||||
}
|
||||
|
||||
wantedTgtAtts := []*pb.PendingAttestation{
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, Target: ðpb.Checkpoint{Root: []byte{1}}}},
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, Target: ðpb.Checkpoint{Root: []byte{1}}}},
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{66}, Target: ðpb.Checkpoint{Root: []byte{1}}}},
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{5}, Target: ðpb.Checkpoint{Root: []byte{1}}}},
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Target: ðpb.Checkpoint{Root: []byte{1}}}},
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Target: ðpb.Checkpoint{Root: []byte{1}}}},
|
||||
{Data: ðpb.AttestationData{Slot: 33, Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: ðpb.Checkpoint{Root: []byte{1}}}},
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{5}, Target: ðpb.Checkpoint{Root: []byte{1}}}},
|
||||
}
|
||||
if !reflect.DeepEqual(mAtts.Target, wantedTgtAtts) {
|
||||
t.Error("target attestations don't match")
|
||||
}
|
||||
|
||||
wantedHeadAtts := []*pb.PendingAttestation{
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{66}, Target: ðpb.Checkpoint{}}},
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{66}, Target: ðpb.Checkpoint{Root: []byte{1}}}},
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{66}, Target: ðpb.Checkpoint{Root: []byte{6}}}},
|
||||
{Data: ðpb.AttestationData{Slot: 33, Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: ðpb.Checkpoint{}}},
|
||||
{Data: ðpb.AttestationData{Slot: 33, Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: ðpb.Checkpoint{Root: []byte{1}}}},
|
||||
{Data: ðpb.AttestationData{Slot: 33, Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: ðpb.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: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, Target: ðpb.Checkpoint{}}}, // none
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{2}, Target: ðpb.Checkpoint{Root: []byte{1}}}}, // none
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{5}, Target: ðpb.Checkpoint{Root: []byte{1}}}}, // none
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{2}, Target: ðpb.Checkpoint{Root: []byte{6}}}}, // none
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Target: ðpb.Checkpoint{}}}, // none
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{2}, Target: ðpb.Checkpoint{Root: []byte{1}}}}, // none
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{5}, Target: ðpb.Checkpoint{Root: []byte{1}}}}, // none
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{2}, Target: ðpb.Checkpoint{Root: []byte{6}}}}, // none
|
||||
}
|
||||
|
||||
currentAtts := []*pb.PendingAttestation{
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, Target: ðpb.Checkpoint{}}}, // source
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{66}, Target: ðpb.Checkpoint{Root: []byte{65}}}}, // source, target, head
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{69}, Target: ðpb.Checkpoint{Root: []byte{65}}}}, // source, target
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{66}, Target: ðpb.Checkpoint{Root: []byte{68}}}}, // source, head
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Target: ðpb.Checkpoint{}}}, // source
|
||||
{Data: ðpb.AttestationData{Slot: 33, Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: ðpb.Checkpoint{Root: []byte{33}}}}, // source, target, head
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{69}, Target: ðpb.Checkpoint{Root: []byte{33}}}}, // source, target
|
||||
{Data: ðpb.AttestationData{Slot: 33, Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: ðpb.Checkpoint{Root: []byte{68}}}}, // source, head
|
||||
}
|
||||
|
||||
blockRoots := make([][]byte, 128)
|
||||
@@ -280,26 +268,26 @@ func TestMatchAttestations_CurrentEpoch(t *testing.T) {
|
||||
}
|
||||
|
||||
wantedSrcAtts := []*pb.PendingAttestation{
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, Target: ðpb.Checkpoint{}}},
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{66}, Target: ðpb.Checkpoint{Root: []byte{65}}}},
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{69}, Target: ðpb.Checkpoint{Root: []byte{65}}}},
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{66}, Target: ðpb.Checkpoint{Root: []byte{68}}}},
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Target: ðpb.Checkpoint{}}},
|
||||
{Data: ðpb.AttestationData{Slot: 33, Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: ðpb.Checkpoint{Root: []byte{33}}}},
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{69}, Target: ðpb.Checkpoint{Root: []byte{33}}}},
|
||||
{Data: ðpb.AttestationData{Slot: 33, Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: ðpb.Checkpoint{Root: []byte{68}}}},
|
||||
}
|
||||
if !reflect.DeepEqual(mAtts.source, wantedSrcAtts) {
|
||||
t.Error("source attestations don't match")
|
||||
}
|
||||
|
||||
wantedTgtAtts := []*pb.PendingAttestation{
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{66}, Target: ðpb.Checkpoint{Root: []byte{65}}}},
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{69}, Target: ðpb.Checkpoint{Root: []byte{65}}}},
|
||||
{Data: ðpb.AttestationData{Slot: 33, Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: ðpb.Checkpoint{Root: []byte{33}}}},
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{69}, Target: ðpb.Checkpoint{Root: []byte{33}}}},
|
||||
}
|
||||
if !reflect.DeepEqual(mAtts.Target, wantedTgtAtts) {
|
||||
t.Error("target attestations don't match")
|
||||
}
|
||||
|
||||
wantedHeadAtts := []*pb.PendingAttestation{
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{66}, Target: ðpb.Checkpoint{Root: []byte{65}}}},
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{Shard: s + 1}, BeaconBlockRoot: []byte{66}, Target: ðpb.Checkpoint{Root: []byte{68}}}},
|
||||
{Data: ðpb.AttestationData{Slot: 33, Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: ðpb.Checkpoint{Root: []byte{33}}}},
|
||||
{Data: ðpb.AttestationData{Slot: 33, Source: ðpb.Checkpoint{}, BeaconBlockRoot: []byte{34}, Target: ðpb.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 := ðpb.Crosslink{
|
||||
DataRoot: []byte{'B'},
|
||||
}
|
||||
atts := []*pb.PendingAttestation{
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{DataRoot: []byte{'A'}}, Target: ðpb.Checkpoint{}}},
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{DataRoot: []byte{'B'}}, Target: ðpb.Checkpoint{}}}, // Selected
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{DataRoot: []byte{'C'}}, Target: ðpb.Checkpoint{}}},
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{DataRoot: []byte{'B'}}, Target: ðpb.Checkpoint{}}}} // Selected
|
||||
|
||||
if !reflect.DeepEqual(attsForCrosslink(c, atts), []*pb.PendingAttestation{
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{DataRoot: []byte{'B'}}, Target: ðpb.Checkpoint{}}},
|
||||
{Data: ðpb.AttestationData{Source: ðpb.Checkpoint{}, Crosslink: ðpb.Crosslink{DataRoot: []byte{'B'}}, Target: ðpb.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 := ðpb.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: ðpb.AttestationData{
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: 1,
|
||||
DataRoot: []byte{'A'},
|
||||
},
|
||||
Target: ðpb.Checkpoint{},
|
||||
Source: ðpb.Checkpoint{},
|
||||
},
|
||||
},
|
||||
{
|
||||
Data: ðpb.AttestationData{
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: 1,
|
||||
DataRoot: []byte{'B'}, // Winner
|
||||
},
|
||||
Target: ðpb.Checkpoint{},
|
||||
Source: ðpb.Checkpoint{},
|
||||
},
|
||||
},
|
||||
{
|
||||
Data: ðpb.AttestationData{
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: 1,
|
||||
DataRoot: []byte{'C'},
|
||||
},
|
||||
Target: ðpb.Checkpoint{},
|
||||
Source: ðpb.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] = ðpb.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 := ðpb.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] = ðpb.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, ðpb.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 := ðpb.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] = ðpb.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] = ðpb.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: ðpb.AttestationData{Source: ðpb.Checkpoint{},
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: startShard + s,
|
||||
DataRoot: []byte{'B'},
|
||||
},
|
||||
Target: ðpb.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: ðpb.AttestationData{
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: startShard + uint64(i),
|
||||
DataRoot: []byte{'A'},
|
||||
},
|
||||
Target: ðpb.Checkpoint{},
|
||||
Source: ðpb.Checkpoint{},
|
||||
},
|
||||
InclusionDelay: uint64(i + 100),
|
||||
AggregationBits: bitfield.Bitlist{0xC0, 0xC0, 0xC0, 0xC0, 0x01},
|
||||
}
|
||||
}
|
||||
state.PreviousEpochAttestations = atts
|
||||
state.CurrentCrosslinks[startShard] = ðpb.Crosslink{
|
||||
DataRoot: []byte{'A'}, Shard: startShard,
|
||||
}
|
||||
state.CurrentCrosslinks[startShard+1] = ðpb.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: ðpb.AttestationData{
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: uint64(i),
|
||||
DataRoot: []byte{'A'},
|
||||
},
|
||||
Target: ðpb.Checkpoint{},
|
||||
Source: ðpb.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: ðpb.AttestationData{
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: startShard + uint64(i),
|
||||
DataRoot: []byte{'A'},
|
||||
},
|
||||
Target: ðpb.Checkpoint{},
|
||||
Source: ðpb.Checkpoint{},
|
||||
},
|
||||
@@ -1162,18 +789,11 @@ func TestAttestationDelta_SomeAttested(t *testing.T) {
|
||||
}
|
||||
}
|
||||
state.PreviousEpochAttestations = atts
|
||||
state.CurrentCrosslinks[startShard] = ðpb.Crosslink{
|
||||
DataRoot: []byte{'A'},
|
||||
}
|
||||
state.CurrentCrosslinks[startShard+1] = ðpb.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: ðpb.AttestationData{
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: startShard + uint64(i),
|
||||
DataRoot: []byte{'A'},
|
||||
},
|
||||
Target: ðpb.Checkpoint{},
|
||||
Source: ðpb.Checkpoint{},
|
||||
},
|
||||
@@ -1245,18 +862,11 @@ func TestAttestationDelta_SomeAttestedFinalityDelay(t *testing.T) {
|
||||
}
|
||||
state.PreviousEpochAttestations = atts
|
||||
state.FinalizedCheckpoint.Epoch = 0
|
||||
state.CurrentCrosslinks[startShard] = ðpb.Crosslink{
|
||||
DataRoot: []byte{'A'},
|
||||
}
|
||||
state.CurrentCrosslinks[startShard+1] = ðpb.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: ðpb.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: ðpb.AttestationData{
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: startShard + uint64(i),
|
||||
DataRoot: []byte{'A'},
|
||||
},
|
||||
Target: ðpb.Checkpoint{},
|
||||
Source: ðpb.Checkpoint{},
|
||||
},
|
||||
@@ -1456,26 +1061,17 @@ func TestProcessRewardsAndPenalties_SomeAttested(t *testing.T) {
|
||||
}
|
||||
}
|
||||
state.PreviousEpochAttestations = atts
|
||||
state.CurrentCrosslinks[startShard] = ðpb.Crosslink{
|
||||
DataRoot: []byte{'A'},
|
||||
}
|
||||
state.CurrentCrosslinks[startShard+1] = ðpb.Crosslink{
|
||||
DataRoot: []byte{'A'},
|
||||
}
|
||||
state.CurrentCrosslinks[startShard+2] = ðpb.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: ðpb.Checkpoint{},
|
||||
|
||||
@@ -27,14 +27,7 @@ func TestComputeValidatorParticipation(t *testing.T) {
|
||||
balances[i] = params.BeaconConfig().MaxEffectiveBalance
|
||||
}
|
||||
|
||||
atts := []*pb.PendingAttestation{{Data: ðpb.AttestationData{Crosslink: ðpb.Crosslink{Shard: 0}, Target: ðpb.Checkpoint{}}}}
|
||||
var crosslinks []*ethpb.Crosslink
|
||||
for i := uint64(0); i < params.BeaconConfig().ShardCount; i++ {
|
||||
crosslinks = append(crosslinks, ðpb.Crosslink{
|
||||
StartEpoch: 0,
|
||||
DataRoot: []byte{'A'},
|
||||
})
|
||||
}
|
||||
atts := []*pb.PendingAttestation{{Data: ðpb.AttestationData{Target: ðpb.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: ðpb.Checkpoint{},
|
||||
JustificationBits: bitfield.Bitvector4{0x00},
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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), ðpb.Eth1Data{})
|
||||
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), ðpb.Eth1Data{BlockHash: make([]byte, 32)})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
beaconState.Slot = 1
|
||||
att := ðpb.Attestation{Data: ðpb.AttestationData{
|
||||
Target: ðpb.Checkpoint{Epoch: 0},
|
||||
Crosslink: ðpb.Crosslink{Shard: 0}}}
|
||||
attSlot, err := helpers.AttestationDataSlot(beaconState, att.Data)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
Target: ðpb.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), ðpb.Eth1Data{})
|
||||
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), ðpb.Eth1Data{BlockHash: make([]byte, 32)})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
beaconState.Slot = 1
|
||||
att := ðpb.Attestation{Data: ðpb.AttestationData{
|
||||
Target: ðpb.Checkpoint{Epoch: 0},
|
||||
Crosslink: ðpb.Crosslink{Shard: 0}}}
|
||||
attSlot, err := helpers.AttestationDataSlot(beaconState, att.Data)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
Target: ðpb.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), ðpb.Eth1Data{})
|
||||
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), ðpb.Eth1Data{BlockHash: make([]byte, 32)})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
beaconState.Slot = params.BeaconConfig().SlotsPerEpoch
|
||||
att := ðpb.Attestation{Data: ðpb.AttestationData{
|
||||
Target: ðpb.Checkpoint{Epoch: 0},
|
||||
Crosslink: ðpb.Crosslink{Shard: 960}}}
|
||||
attSlot, err := helpers.AttestationDataSlot(beaconState, att.Data)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
Target: ðpb.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), ðpb.Eth1Data{})
|
||||
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), ðpb.Eth1Data{BlockHash: make([]byte, 32)})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
beaconState.Slot = params.BeaconConfig().SlotsPerEpoch + 1
|
||||
att := ðpb.Attestation{Data: ðpb.AttestationData{
|
||||
Target: ðpb.Checkpoint{Epoch: 1},
|
||||
Crosslink: ðpb.Crosslink{}}}
|
||||
attSlot, err := helpers.AttestationDataSlot(beaconState, att.Data)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
Target: ðpb.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), ðpb.Eth1Data{})
|
||||
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), ðpb.Eth1Data{BlockHash: make([]byte, 32)})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -220,11 +200,11 @@ func TestProcessAttestations(t *testing.T) {
|
||||
|
||||
bf := []byte{0xff}
|
||||
att1 := ðpb.Attestation{Data: ðpb.AttestationData{
|
||||
Target: ðpb.Checkpoint{Epoch: 0},
|
||||
Crosslink: ðpb.Crosslink{Shard: 960}}, AggregationBits: bf}
|
||||
Target: ðpb.Checkpoint{Epoch: 0}},
|
||||
AggregationBits: bf}
|
||||
att2 := ðpb.Attestation{Data: ðpb.AttestationData{
|
||||
Target: ðpb.Checkpoint{Epoch: 0},
|
||||
Crosslink: ðpb.Crosslink{Shard: 961}}, AggregationBits: bf}
|
||||
Target: ðpb.Checkpoint{Epoch: 0}},
|
||||
AggregationBits: bf}
|
||||
beaconState.BlockRoots[0] = []byte{'A'}
|
||||
att1.Data.Target.Root = []byte{'A'}
|
||||
att1.Data.BeaconBlockRoot = []byte{'A'}
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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: ðpb.AttestationData{
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: startShard + uint64(i),
|
||||
DataRoot: []byte{'A'},
|
||||
},
|
||||
Target: ðpb.Checkpoint{},
|
||||
Source: ðpb.Checkpoint{},
|
||||
},
|
||||
@@ -34,15 +29,6 @@ func TestProcessRewardsAndPenaltiesPrecompute(t *testing.T) {
|
||||
}
|
||||
}
|
||||
state.PreviousEpochAttestations = atts
|
||||
state.CurrentCrosslinks[startShard] = ðpb.Crosslink{
|
||||
DataRoot: []byte{'A'},
|
||||
}
|
||||
state.CurrentCrosslinks[startShard+1] = ðpb.Crosslink{
|
||||
DataRoot: []byte{'A'},
|
||||
}
|
||||
state.CurrentCrosslinks[startShard+2] = ðpb.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: ðpb.AttestationData{
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: startShard + uint64(i),
|
||||
DataRoot: []byte{'A'},
|
||||
},
|
||||
Target: ðpb.Checkpoint{},
|
||||
Source: ðpb.Checkpoint{},
|
||||
},
|
||||
@@ -92,12 +73,6 @@ func TestAttestationDeltaPrecompute(t *testing.T) {
|
||||
}
|
||||
}
|
||||
state.PreviousEpochAttestations = atts
|
||||
state.CurrentCrosslinks[startShard] = ðpb.Crosslink{
|
||||
DataRoot: []byte{'A'},
|
||||
}
|
||||
state.CurrentCrosslinks[startShard+1] = ðpb.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: ðpb.AttestationData{
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: startShard + uint64(i),
|
||||
DataRoot: []byte{'A'},
|
||||
},
|
||||
Target: ðpb.Checkpoint{},
|
||||
Source: ðpb.Checkpoint{},
|
||||
},
|
||||
InclusionDelay: uint64(i + 100),
|
||||
AggregationBits: bitfield.Bitlist{0xC0, 0xC0, 0xC0, 0xC0, 0x01},
|
||||
}
|
||||
}
|
||||
state.PreviousEpochAttestations = atts
|
||||
state.CurrentCrosslinks[startShard] = ðpb.Crosslink{
|
||||
DataRoot: []byte{'A'}, Shard: startShard,
|
||||
}
|
||||
state.CurrentCrosslinks[startShard+1] = ðpb.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: ðpb.Checkpoint{},
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
package spectest
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCrosslinksProcessingMainnet(t *testing.T) {
|
||||
runCrosslinkProcessingTests(t, "mainnet")
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package spectest
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCrosslinksProcessingMinimal(t *testing.T) {
|
||||
runCrosslinkProcessingTests(t, "minimal")
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -5,6 +5,5 @@ import (
|
||||
)
|
||||
|
||||
func TestJustificationAndFinalizationMinimal(t *testing.T) {
|
||||
t.Skip("Fails for could not get target atts current epoch")
|
||||
runJustificationAndFinalizationTests(t, "minimal")
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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), ðpb.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, ðpb.AttestationData{
|
||||
Target: ðpb.Checkpoint{Epoch: 0},
|
||||
Crosslink: ðpb.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*/, ðpb.AttestationData{
|
||||
Target: ðpb.Checkpoint{Epoch: 0},
|
||||
Crosslink: ðpb.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), ðpb.Eth1Data{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
s, err := helpers.AttestationDataSlot(beaconState, ðpb.AttestationData{
|
||||
Target: ðpb.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), ðpb.Eth1Data{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
s, err := helpers.AttestationDataSlot(beaconState, ðpb.AttestationData{
|
||||
Target: ðpb.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},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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
@@ -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.
|
||||
//
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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},
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 := ðpb.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 := ðpb.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 := ðpb.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 := ðpb.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 := ðpb.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 := ðpb.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 := ðpb.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 {
|
||||
|
||||
@@ -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",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -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 := ðpb.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)
|
||||
}
|
||||
}
|
||||
@@ -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] = ðpb.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
|
||||
}
|
||||
|
||||
|
||||
@@ -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, ðpb.Eth1Data{})
|
||||
state1, err := state.GenesisBeaconState(deposits, 0, ðpb.Eth1Data{BlockHash: make([]byte, 32)})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
state2, err := state.GenesisBeaconState(deposits, 0, ðpb.Eth1Data{})
|
||||
state2, err := state.GenesisBeaconState(deposits, 0, ðpb.Eth1Data{BlockHash: make([]byte, 32)})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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")
|
||||
|
||||
@@ -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), ðpb.Eth1Data{})
|
||||
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), ðpb.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), ðpb.Eth1Data{})
|
||||
deposits, _, privKeys := testutil.SetupInitialDeposits(t, 34)
|
||||
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), ðpb.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), ðpb.Eth1Data{})
|
||||
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), ðpb.Eth1Data{BlockHash: make([]byte, 32)})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -208,9 +203,6 @@ func TestProcessBlock_IncorrectProcessBlockAttestations(t *testing.T) {
|
||||
Data: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 0},
|
||||
Target: ðpb.Checkpoint{Epoch: 0},
|
||||
Crosslink: ðpb.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: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 1},
|
||||
Target: ðpb.Checkpoint{Epoch: 0},
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: 4,
|
||||
},
|
||||
},
|
||||
CustodyBit_0Indices: []uint64{0, 1},
|
||||
}
|
||||
@@ -260,8 +249,7 @@ func TestProcessBlock_IncorrectProcessBlockAttestations(t *testing.T) {
|
||||
|
||||
att := ðpb.Attestation{
|
||||
Data: ðpb.AttestationData{
|
||||
Target: ðpb.Checkpoint{Epoch: 0},
|
||||
Crosslink: ðpb.Crosslink{},
|
||||
Target: ðpb.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), ðpb.Eth1Data{})
|
||||
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), ðpb.Eth1Data{BlockHash: make([]byte, 32)})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -339,18 +327,14 @@ func TestProcessBlock_IncorrectProcessExits(t *testing.T) {
|
||||
Data: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 0},
|
||||
Target: ðpb.Checkpoint{Epoch: 0},
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: 4,
|
||||
}},
|
||||
},
|
||||
CustodyBit_0Indices: []uint64{0, 1},
|
||||
},
|
||||
Attestation_2: ðpb.IndexedAttestation{
|
||||
Data: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 1},
|
||||
Target: ðpb.Checkpoint{Epoch: 0},
|
||||
Crosslink: ðpb.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 := ðpb.Attestation{
|
||||
Data: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 0},
|
||||
Target: ðpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
|
||||
Crosslink: ðpb.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), ðpb.Eth1Data{})
|
||||
deposits, _, privKeys := testutil.SetupInitialDeposits(t, 32)
|
||||
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), ðpb.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 := ðpb.IndexedAttestation{
|
||||
Data: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 0, Root: []byte{'A'}},
|
||||
Target: ðpb.Checkpoint{Epoch: 0},
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: 4,
|
||||
},
|
||||
},
|
||||
Target: ðpb.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 := ðpb.IndexedAttestation{
|
||||
Data: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 0, Root: []byte{'B'}},
|
||||
Target: ðpb.Checkpoint{Epoch: 0},
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: 4,
|
||||
},
|
||||
},
|
||||
Target: ðpb.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 := ðpb.Attestation{
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: beaconState.Slot - 1,
|
||||
Target: ðpb.Checkpoint{Epoch: helpers.SlotToEpoch(beaconState.Slot)},
|
||||
Source: ðpb.Checkpoint{
|
||||
Epoch: 0,
|
||||
Root: []byte("hello-world"),
|
||||
},
|
||||
Crosslink: ðpb.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: ðpb.AttestationData{Crosslink: ðpb.Crosslink{Shard: 100}}}}
|
||||
atts := []*pb.PendingAttestation{{Data: ðpb.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: ðpb.AttestationData{Crosslink: ðpb.Crosslink{Shard: 0}, Target: ðpb.Checkpoint{}}}}
|
||||
var crosslinks []*ethpb.Crosslink
|
||||
for i := uint64(0); i < params.BeaconConfig().ShardCount; i++ {
|
||||
crosslinks = append(crosslinks, ðpb.Crosslink{
|
||||
StartEpoch: 0,
|
||||
DataRoot: []byte{'A'},
|
||||
})
|
||||
}
|
||||
atts := []*pb.PendingAttestation{{Data: ðpb.AttestationData{Target: ðpb.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: ðpb.Checkpoint{},
|
||||
JustificationBits: bitfield.Bitvector4{0x00},
|
||||
@@ -725,22 +651,13 @@ func TestProcessEpochPrecompute_CanProcess(t *testing.T) {
|
||||
helpers.ClearAllCaches()
|
||||
epoch := uint64(1)
|
||||
|
||||
atts := []*pb.PendingAttestation{{Data: ðpb.AttestationData{Crosslink: ðpb.Crosslink{Shard: 0}, Target: ðpb.Checkpoint{}}}}
|
||||
var crosslinks []*ethpb.Crosslink
|
||||
for i := uint64(0); i < params.BeaconConfig().ShardCount; i++ {
|
||||
crosslinks = append(crosslinks, ðpb.Crosslink{
|
||||
StartEpoch: 0,
|
||||
DataRoot: []byte{'A'},
|
||||
})
|
||||
}
|
||||
atts := []*pb.PendingAttestation{{Data: ðpb.AttestationData{Target: ðpb.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: ðpb.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: ðpb.AttestationData{
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: i,
|
||||
},
|
||||
},
|
||||
Data: ðpb.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, ðpb.Crosslink{
|
||||
StartEpoch: 0,
|
||||
DataRoot: []byte{'A'},
|
||||
})
|
||||
}
|
||||
|
||||
s := &pb.BeaconState{
|
||||
Slot: epoch*params.BeaconConfig().SlotsPerEpoch + 1,
|
||||
Validators: validators,
|
||||
Balances: balances,
|
||||
StartShard: 512,
|
||||
FinalizedCheckpoint: ðpb.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] = ðpb.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, ðpb.Crosslink{
|
||||
StartEpoch: 0,
|
||||
DataRoot: []byte{'A'},
|
||||
})
|
||||
}
|
||||
|
||||
s := &pb.BeaconState{
|
||||
Slot: 20,
|
||||
LatestBlockHeader: ðpb.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: ðpb.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: ðpb.IndexedAttestation{
|
||||
Data: ðpb.AttestationData{
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: 5,
|
||||
},
|
||||
},
|
||||
Data: ðpb.AttestationData{},
|
||||
CustodyBit_0Indices: []uint64{2, 3},
|
||||
},
|
||||
Attestation_2: ðpb.IndexedAttestation{
|
||||
Data: ðpb.AttestationData{
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: 5,
|
||||
},
|
||||
},
|
||||
Data: ðpb.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] = ðpb.Attestation{
|
||||
Data: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Root: []byte("hello-world")},
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: uint64(i),
|
||||
ParentRoot: encoded[:],
|
||||
DataRoot: params.BeaconConfig().ZeroHash[:],
|
||||
},
|
||||
},
|
||||
Source: ðpb.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), ðpb.Eth1Data{})
|
||||
s, _ := state.GenesisBeaconState(deposits, 0, ðpb.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 := ðpb.Attestation{
|
||||
Data: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 0, Root: params.BeaconConfig().ZeroHash[:]},
|
||||
Target: ðpb.Checkpoint{Epoch: 0},
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: uint64(i + 960),
|
||||
StartEpoch: 0,
|
||||
ParentRoot: crosslinkRoot[:],
|
||||
DataRoot: params.BeaconConfig().ZeroHash[:],
|
||||
},
|
||||
},
|
||||
Target: ðpb.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 := ðpb.BeaconBlock{
|
||||
Body: ðpb.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 := ðpb.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: ðpb.Eth1Data{DepositCount: 100},
|
||||
Eth1DepositIndex: 98,
|
||||
}
|
||||
block := ðpb.BeaconBlock{
|
||||
Body: ðpb.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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -67,13 +67,6 @@ func TestStore_ArchivedActiveValidatorChanges(t *testing.T) {
|
||||
Epoch: 5,
|
||||
Root: someRoot[:],
|
||||
},
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: 3,
|
||||
ParentRoot: someRoot[:],
|
||||
StartEpoch: 3,
|
||||
EndEpoch: 4,
|
||||
DataRoot: someRoot[:],
|
||||
},
|
||||
},
|
||||
},
|
||||
Attestation_2: ðpb.IndexedAttestation{
|
||||
@@ -87,13 +80,6 @@ func TestStore_ArchivedActiveValidatorChanges(t *testing.T) {
|
||||
Epoch: 5,
|
||||
Root: someRoot[:],
|
||||
},
|
||||
Crosslink: ðpb.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 := ðpb.ArchivedCommitteeInfo{
|
||||
Seed: someSeed[:],
|
||||
StartShard: 10,
|
||||
ProposerSeed: someSeed[:],
|
||||
AttesterSeed: someSeed[:],
|
||||
CommitteeCount: 4096,
|
||||
}
|
||||
epoch := uint64(10)
|
||||
|
||||
@@ -19,14 +19,7 @@ func TestStore_AttestationCRUD(t *testing.T) {
|
||||
db := setupDB(t)
|
||||
defer teardownDB(t, db)
|
||||
att := ðpb.Attestation{
|
||||
Data: ðpb.AttestationData{
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: 5,
|
||||
ParentRoot: []byte("parent"),
|
||||
StartEpoch: 1,
|
||||
EndEpoch: 2,
|
||||
},
|
||||
},
|
||||
Data: ðpb.AttestationData{Slot: 10},
|
||||
AggregationBits: bitfield.Bitlist{0b00000001, 0b1},
|
||||
CustodyBits: bitfield.NewBitlist(8),
|
||||
}
|
||||
@@ -76,12 +69,7 @@ func TestStore_AttestationsBatchDelete(t *testing.T) {
|
||||
totalAtts[i] = ðpb.Attestation{
|
||||
Data: ðpb.AttestationData{
|
||||
BeaconBlockRoot: []byte("head"),
|
||||
Crosslink: ðpb.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 := ðpb.Attestation{
|
||||
Data: ðpb.AttestationData{
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: 5,
|
||||
ParentRoot: []byte("parent"),
|
||||
StartEpoch: uint64(i + 1),
|
||||
EndEpoch: 2,
|
||||
},
|
||||
},
|
||||
Data: ðpb.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 := ðpb.Attestation{
|
||||
Data: ðpb.AttestationData{
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: 5,
|
||||
ParentRoot: []byte("parent"),
|
||||
StartEpoch: uint64(startEpoch),
|
||||
EndEpoch: 2,
|
||||
},
|
||||
},
|
||||
Data: ðpb.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 := ðpb.AttestationData{
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: 5,
|
||||
ParentRoot: []byte("parent"),
|
||||
StartEpoch: 1,
|
||||
EndEpoch: 2,
|
||||
},
|
||||
}
|
||||
commonData := ðpb.AttestationData{Slot: 10}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
|
||||
@@ -56,17 +56,13 @@ func TestStore_AttesterSlashing_CRUD(t *testing.T) {
|
||||
Attestation_1: ðpb.IndexedAttestation{
|
||||
Data: ðpb.AttestationData{
|
||||
BeaconBlockRoot: make([]byte, 32),
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: 5,
|
||||
},
|
||||
Slot: 5,
|
||||
},
|
||||
},
|
||||
Attestation_2: ðpb.IndexedAttestation{
|
||||
Data: ðpb.AttestationData{
|
||||
BeaconBlockRoot: make([]byte, 32),
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: 7,
|
||||
},
|
||||
Slot: 7,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -30,7 +30,7 @@ func TestHandleAttestation_Saves_NewAttestation(t *testing.T) {
|
||||
})
|
||||
|
||||
deposits, _, privKeys := testutil.SetupInitialDeposits(t, 100)
|
||||
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), ðpb.Eth1Data{})
|
||||
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), ðpb.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: ðpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
|
||||
Target: ðpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
|
||||
Crosslink: ðpb.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 := ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
|
||||
Target: ðpb.Checkpoint{Epoch: 0},
|
||||
Crosslink: ðpb.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), ðpb.Eth1Data{})
|
||||
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), ðpb.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), ðpb.Eth1Data{})
|
||||
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), ðpb.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 := ðpb.Attestation{
|
||||
Data: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
|
||||
Target: ðpb.Checkpoint{Epoch: 0},
|
||||
Crosslink: ðpb.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 := ðpb.Attestation{
|
||||
Data: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
|
||||
Target: ðpb.Checkpoint{Epoch: 0},
|
||||
Crosslink: ðpb.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 := ðpb.Attestation{
|
||||
Data: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
|
||||
Target: ðpb.Checkpoint{Epoch: 0},
|
||||
Crosslink: ðpb.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), ðpb.Eth1Data{})
|
||||
deposits, _, privKeys := testutil.SetupInitialDeposits(t, 32)
|
||||
beaconState, err := state.GenesisBeaconState(deposits, uint64(0), ðpb.Eth1Data{BlockHash: make([]byte, 32)})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -416,10 +366,6 @@ func TestRetrieveAttestations_OK(t *testing.T) {
|
||||
Data: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 0, Root: params.BeaconConfig().ZeroHash[:]},
|
||||
Target: ðpb.Checkpoint{Epoch: 0},
|
||||
Crosslink: ðpb.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] = ðpb.Attestation{
|
||||
Data: ðpb.AttestationData{
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: uint64(i),
|
||||
},
|
||||
Slot: uint64(i),
|
||||
Source: ðpb.Checkpoint{},
|
||||
Target: ðpb.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] = ðpb.Attestation{
|
||||
Data: ðpb.AttestationData{
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: uint64(i),
|
||||
},
|
||||
Slot: uint64(i),
|
||||
Source: ðpb.Checkpoint{},
|
||||
Target: ðpb.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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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] = ðpb.Attestation{
|
||||
Data: ðpb.AttestationData{
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: uint64(i),
|
||||
},
|
||||
Data: ðpb.AttestationData{Slot: uint64(i),
|
||||
Source: ðpb.Checkpoint{},
|
||||
Target: ðpb.Checkpoint{},
|
||||
},
|
||||
Target: ðpb.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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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",
|
||||
],
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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 = ðpb.AttestationData{
|
||||
Slot: req.Slot,
|
||||
Index: req.CommitteeIndex,
|
||||
BeaconBlockRoot: headRoot[:],
|
||||
Source: headState.CurrentJustifiedCheckpoint,
|
||||
Target: ðpb.Checkpoint{
|
||||
Epoch: targetEpoch,
|
||||
Root: targetRoot,
|
||||
},
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: req.Shard,
|
||||
StartEpoch: startEpoch,
|
||||
EndEpoch: endEpoch,
|
||||
ParentRoot: crosslinkRoot[:],
|
||||
DataRoot: params.BeaconConfig().ZeroHash[:],
|
||||
},
|
||||
}
|
||||
|
||||
if err := as.attestationCache.Put(ctx, req, res); err != nil {
|
||||
|
||||
@@ -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 := ðpb.Attestation{
|
||||
Data: ðpb.AttestationData{
|
||||
BeaconBlockRoot: root[:],
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: 935,
|
||||
DataRoot: []byte{'a'},
|
||||
},
|
||||
Source: ðpb.Checkpoint{},
|
||||
Target: ðpb.Checkpoint{},
|
||||
Source: ðpb.Checkpoint{},
|
||||
Target: ðpb.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: ðpb.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 := ðpb.AttestationData{
|
||||
Slot: 3*params.BeaconConfig().SlotsPerEpoch + 1,
|
||||
BeaconBlockRoot: blockRoot[:],
|
||||
Source: ðpb.Checkpoint{
|
||||
Epoch: 2,
|
||||
@@ -159,11 +140,6 @@ func TestRequestAttestation_OK(t *testing.T) {
|
||||
Target: ðpb.Checkpoint{
|
||||
Epoch: 3,
|
||||
},
|
||||
Crosslink: ðpb.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: ðpb.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 := ðpb.AttestationData{
|
||||
Slot: req.Slot,
|
||||
BeaconBlockRoot: blockRoot[:],
|
||||
Source: ðpb.Checkpoint{
|
||||
Epoch: helpers.SlotToEpoch(1500),
|
||||
Root: justifiedBlockRoot[:],
|
||||
},
|
||||
Target: ðpb.Checkpoint{
|
||||
Epoch: 156,
|
||||
},
|
||||
Crosslink: ðpb.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 := ðpb.AttestationData{
|
||||
|
||||
@@ -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 := ðpb.ValidatorAssignments_CommitteeAssignment{
|
||||
BeaconCommittees: committee,
|
||||
CommitteeIndex: committeeIndex,
|
||||
AttesterSlot: attesterSlot,
|
||||
ProposerSlot: proposerSlot,
|
||||
PublicKey: headState.Validators[index].PublicKey,
|
||||
}
|
||||
res = append(res, assign)
|
||||
continue
|
||||
}
|
||||
|
||||
res = append(res, ðpb.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 := ðpb.ValidatorAssignments_CommitteeAssignment{
|
||||
BeaconCommittees: committee,
|
||||
CommitteeIndex: committeeIndex,
|
||||
AttesterSlot: attesterSlot,
|
||||
ProposerSlot: proposerSlot,
|
||||
PublicKey: headState.Validators[index].PublicKey,
|
||||
}
|
||||
res = append(res, assign)
|
||||
}
|
||||
|
||||
return ðpb.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,
|
||||
|
||||
@@ -34,9 +34,7 @@ func TestBeaconChainServer_ListAttestationsNoPagination(t *testing.T) {
|
||||
attExample := ðpb.Attestation{
|
||||
Data: ðpb.AttestationData{
|
||||
BeaconBlockRoot: []byte("root"),
|
||||
Crosslink: ðpb.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: ðpb.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: ðpb.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: ðpb.Crosslink{
|
||||
Shard: 5,
|
||||
},
|
||||
Slot: 5,
|
||||
},
|
||||
AggregationBits: bitfield.Bitlist{0b11},
|
||||
},
|
||||
@@ -197,9 +189,7 @@ func TestBeaconChainServer_ListAttestationsPagination(t *testing.T) {
|
||||
attExample := ðpb.Attestation{
|
||||
Data: ðpb.AttestationData{
|
||||
BeaconBlockRoot: []byte("root"),
|
||||
Crosslink: ðpb.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: ðpb.AttestationData{
|
||||
BeaconBlockRoot: []byte("root"),
|
||||
Crosslink: ðpb.Crosslink{Shard: 3},
|
||||
Slot: 3,
|
||||
},
|
||||
AggregationBits: bitfield.Bitlist{0b11},
|
||||
CustodyBits: bitfield.NewBitlist(1)},
|
||||
{Data: ðpb.AttestationData{
|
||||
BeaconBlockRoot: []byte("root"),
|
||||
Crosslink: ðpb.Crosslink{Shard: 4},
|
||||
Slot: 4,
|
||||
},
|
||||
AggregationBits: bitfield.Bitlist{0b11},
|
||||
CustodyBits: bitfield.NewBitlist(1)},
|
||||
{Data: ðpb.AttestationData{
|
||||
BeaconBlockRoot: []byte("root"),
|
||||
Crosslink: ðpb.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: ðpb.AttestationData{
|
||||
BeaconBlockRoot: []byte("root"),
|
||||
Crosslink: ðpb.Crosslink{Shard: 50},
|
||||
Slot: 50,
|
||||
},
|
||||
AggregationBits: bitfield.Bitlist{0b11},
|
||||
CustodyBits: bitfield.NewBitlist(1)},
|
||||
{Data: ðpb.AttestationData{
|
||||
BeaconBlockRoot: []byte("root"),
|
||||
Crosslink: ðpb.Crosslink{Shard: 51},
|
||||
Slot: 51,
|
||||
},
|
||||
AggregationBits: bitfield.Bitlist{0b11},
|
||||
CustodyBits: bitfield.NewBitlist(1)},
|
||||
{Data: ðpb.AttestationData{
|
||||
BeaconBlockRoot: []byte("root"),
|
||||
Crosslink: ðpb.Crosslink{Shard: 52},
|
||||
Slot: 52,
|
||||
},
|
||||
AggregationBits: bitfield.Bitlist{0b11},
|
||||
CustodyBits: bitfield.NewBitlist(1)},
|
||||
{Data: ðpb.AttestationData{
|
||||
BeaconBlockRoot: []byte("root"),
|
||||
Crosslink: ðpb.Crosslink{Shard: 53},
|
||||
Slot: 53,
|
||||
},
|
||||
AggregationBits: bitfield.Bitlist{0b11},
|
||||
CustodyBits: bitfield.NewBitlist(1)},
|
||||
{Data: ðpb.AttestationData{
|
||||
BeaconBlockRoot: []byte("root"),
|
||||
Crosslink: ðpb.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: ðpb.AttestationData{
|
||||
BeaconBlockRoot: []byte("root"),
|
||||
Crosslink: ðpb.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: ðpb.AttestationData{
|
||||
BeaconBlockRoot: []byte("root"),
|
||||
Crosslink: ðpb.Crosslink{Shard: 0},
|
||||
},
|
||||
AggregationBits: bitfield.Bitlist{0b11},
|
||||
CustodyBits: bitfield.NewBitlist(1)},
|
||||
{Data: ðpb.AttestationData{
|
||||
BeaconBlockRoot: []byte("root"),
|
||||
Crosslink: ðpb.Crosslink{Shard: 1},
|
||||
Slot: 1,
|
||||
},
|
||||
AggregationBits: bitfield.Bitlist{0b11},
|
||||
CustodyBits: bitfield.NewBitlist(1),
|
||||
@@ -358,9 +347,7 @@ func TestBeaconChainServer_ListAttestationsPaginationOutOfRange(t *testing.T) {
|
||||
attExample := ðpb.Attestation{
|
||||
Data: ðpb.AttestationData{
|
||||
BeaconBlockRoot: []byte("root"),
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: i,
|
||||
},
|
||||
Slot: i,
|
||||
},
|
||||
AggregationBits: bitfield.Bitlist{0b11},
|
||||
}
|
||||
@@ -410,9 +397,7 @@ func TestBeaconChainServer_ListAttestationsDefaultPageSize(t *testing.T) {
|
||||
attExample := ðpb.Attestation{
|
||||
Data: ðpb.AttestationData{
|
||||
BeaconBlockRoot: []byte("root"),
|
||||
Crosslink: ðpb.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, ðpb.Validator{PublicKey: []byte{byte(i)}, ExitEpoch: 0})
|
||||
validators = append(validators, ðpb.Validator{
|
||||
PublicKey: pubKey[:],
|
||||
ExitEpoch: 0,
|
||||
})
|
||||
} else {
|
||||
validators = append(validators, ðpb.Validator{PublicKey: []byte{byte(i)}, ExitEpoch: params.BeaconConfig().FarFutureEpoch})
|
||||
validators = append(validators, ðpb.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(), ðpb.ListValidatorAssignmentsRequest{
|
||||
QueryFilter: ðpb.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, ðpb.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, ðpb.Validator{PublicKey: []byte{byte(i)}, ExitEpoch: 0})
|
||||
validators = append(validators, ðpb.Validator{
|
||||
PublicKey: pubKey[:],
|
||||
ExitEpoch: 0,
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
})
|
||||
} else {
|
||||
validators = append(validators, ðpb.Validator{PublicKey: []byte{byte(i)}, ExitEpoch: params.BeaconConfig().FarFutureEpoch})
|
||||
validators = append(validators, ðpb.Validator{
|
||||
PublicKey: pubKey[:],
|
||||
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
})
|
||||
}
|
||||
balances[i] = params.BeaconConfig().MaxEffectiveBalance
|
||||
}
|
||||
|
||||
blk := ðpb.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, ðpb.ArchivedCommitteeInfo{
|
||||
ProposerSeed: proposerSeed[:],
|
||||
AttesterSeed: attesterSeed[:],
|
||||
CommitteeCount: committeeCount * params.BeaconConfig().SlotsPerEpoch,
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := db.SaveArchivedCommitteeInfo(context.Background(), 0, ðpb.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 := ðpb.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(), ðpb.ListValidatorAssignmentsRequest{
|
||||
QueryFilter: ðpb.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, ðpb.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, ðpb.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, ðpb.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, ðpb.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: ðpb.AttestationData{Crosslink: ðpb.Crosslink{Shard: 0}, Target: ðpb.Checkpoint{}}}}
|
||||
var crosslinks []*ethpb.Crosslink
|
||||
for i := uint64(0); i < params.BeaconConfig().ShardCount; i++ {
|
||||
crosslinks = append(crosslinks, ðpb.Crosslink{
|
||||
StartEpoch: 0,
|
||||
DataRoot: []byte{'A'},
|
||||
})
|
||||
}
|
||||
atts := []*pbp2p.PendingAttestation{{Data: ðpb.AttestationData{Target: ðpb.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: ðpb.Checkpoint{},
|
||||
JustificationBits: bitfield.Bitvector4{0x00},
|
||||
|
||||
@@ -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{},
|
||||
|
||||
@@ -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, ðpb.Eth1Data{})
|
||||
beaconState, err := state.GenesisBeaconState(deposits, 0, ðpb.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, ðpb.Eth1Data{})
|
||||
beaconState, err := state.GenesisBeaconState(deposits, 0, ðpb.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"),
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ func TestNextEpochCommitteeAssignment_WrongPubkeyLength(t *testing.T) {
|
||||
helpers.ClearAllCaches()
|
||||
|
||||
deposits, _, _ := testutil.SetupInitialDeposits(t, 8)
|
||||
beaconState, err := state.GenesisBeaconState(deposits, 0, ðpb.Eth1Data{})
|
||||
beaconState, err := state.GenesisBeaconState(deposits, 0, ðpb.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, ðpb.Eth1Data{})
|
||||
beaconState, err := state.GenesisBeaconState(deposits, 0, ðpb.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, ðpb.Eth1Data{})
|
||||
state, err := state.GenesisBeaconState(deposits, 0, ðpb.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, ðpb.Eth1Data{})
|
||||
state, err := state.GenesisBeaconState(deposits, 0, ðpb.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, ðpb.Eth1Data{})
|
||||
state, err := state.GenesisBeaconState(deposits, 0, ðpb.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 {
|
||||
|
||||
@@ -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{
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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, ðpb.Eth1Data{})
|
||||
state, err := state.GenesisBeaconState(deposits, 0, ðpb.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: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 1},
|
||||
Target: ðpb.Checkpoint{Epoch: 0},
|
||||
Crosslink: ðpb.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: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{Epoch: 0},
|
||||
Target: ðpb.Checkpoint{Epoch: 0},
|
||||
Crosslink: ðpb.Crosslink{
|
||||
Shard: 4,
|
||||
},
|
||||
},
|
||||
CustodyBit_0Indices: []uint64{0, 1},
|
||||
}
|
||||
|
||||
@@ -101,7 +101,6 @@ func TestValidateBeaconBlockPubSub_BlockAlreadyPresentInCache(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
msg := ðpb.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 := ðpb.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 := ðpb.BeaconBlock{
|
||||
Slot: 1,
|
||||
ParentRoot: testutil.Random32Bytes(t),
|
||||
Signature: sk.Sign([]byte("data"), 0).Marshal(),
|
||||
}
|
||||
|
||||
@@ -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: ðpb.BeaconBlockHeader{},
|
||||
|
||||
@@ -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",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -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
|
||||
```
|
||||
|
||||
@@ -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
@@ -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",
|
||||
|
||||
@@ -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)
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user