From 1a0a399bedadcaa88d05428225947daa2cdfb85d Mon Sep 17 00:00:00 2001 From: terence tsao Date: Thu, 26 Mar 2020 17:09:14 -0700 Subject: [PATCH] Handle genesis case for blocks/states at slot index (#5224) * Handle highest slot = 0 * TestStore_GenesisState_CanGetHighestBelow * TestStore_GenesisBlock_CanGetHighestAt * Merge refs/heads/master into handle-genesis --- beacon-chain/blockchain/process_block.go | 2 +- beacon-chain/blockchain/receive_block.go | 2 +- beacon-chain/db/kv/blocks.go | 9 +++++ beacon-chain/db/kv/blocks_test.go | 35 ++++++++++++++++ beacon-chain/db/kv/state.go | 9 +++++ beacon-chain/db/kv/state_test.go | 51 ++++++++++++++++++++++++ beacon-chain/rpc/beacon/blocks.go | 2 +- slasher/rpc/server.go | 4 +- slasher/rpc/service.go | 2 +- 9 files changed, 110 insertions(+), 6 deletions(-) diff --git a/beacon-chain/blockchain/process_block.go b/beacon-chain/blockchain/process_block.go index 564ff1630c32..60a1fa2e468b 100644 --- a/beacon-chain/blockchain/process_block.go +++ b/beacon-chain/blockchain/process_block.go @@ -5,13 +5,13 @@ import ( "encoding/hex" "fmt" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" "github.com/pkg/errors" ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/state" "github.com/prysmaticlabs/prysm/beacon-chain/flags" stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" "github.com/prysmaticlabs/prysm/shared/attestationutil" "github.com/prysmaticlabs/prysm/shared/bytesutil" "github.com/prysmaticlabs/prysm/shared/featureconfig" diff --git a/beacon-chain/blockchain/receive_block.go b/beacon-chain/blockchain/receive_block.go index 63511811c4fd..9919a805c3e7 100644 --- a/beacon-chain/blockchain/receive_block.go +++ b/beacon-chain/blockchain/receive_block.go @@ -5,7 +5,6 @@ import ( "context" "encoding/hex" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" "github.com/pkg/errors" ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1" "github.com/prysmaticlabs/go-ssz" @@ -14,6 +13,7 @@ import ( statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state" + "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" "github.com/prysmaticlabs/prysm/shared/featureconfig" "github.com/prysmaticlabs/prysm/shared/traceutil" "github.com/sirupsen/logrus" diff --git a/beacon-chain/db/kv/blocks.go b/beacon-chain/db/kv/blocks.go index 93aec0eb2ab3..260e149f2170 100644 --- a/beacon-chain/db/kv/blocks.go +++ b/beacon-chain/db/kv/blocks.go @@ -360,6 +360,15 @@ func (k *Store) blocksAtSlotBitfieldIndex(ctx context.Context, tx *bolt.Tx, inde highestSlot := index - 1 highestSlot = int(math.Max(0, float64(highestSlot))) + + if highestSlot == 0 { + gBlock, err := k.GenesisBlock(ctx) + if err != nil { + return nil, err + } + return []*ethpb.SignedBeaconBlock{gBlock}, nil + } + f := filters.NewFilter().SetStartSlot(uint64(highestSlot)).SetEndSlot(uint64(highestSlot)) keys, err := getBlockRootsByFilter(ctx, tx, f) diff --git a/beacon-chain/db/kv/blocks_test.go b/beacon-chain/db/kv/blocks_test.go index d29a8335e52f..7ce3b682d43e 100644 --- a/beacon-chain/db/kv/blocks_test.go +++ b/beacon-chain/db/kv/blocks_test.go @@ -508,6 +508,41 @@ func TestStore_SaveBlock_CanGetHighestAt(t *testing.T) { } } +func TestStore_GenesisBlock_CanGetHighestAt(t *testing.T) { + db := setupDB(t) + defer teardownDB(t, db) + ctx := context.Background() + + genesisBlock := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{}} + genesisRoot, _ := ssz.HashTreeRoot(genesisBlock.Block) + db.SaveGenesisBlockRoot(ctx, genesisRoot) + db.SaveBlock(ctx, genesisBlock) + block1 := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 1}} + db.SaveBlock(ctx, block1) + + highestAt, err := db.HighestSlotBlocksBelow(ctx, 2) + if err != nil { + t.Fatal(err) + } + if !proto.Equal(block1, highestAt[0]) { + t.Errorf("Wanted %v, received %v", block1, highestAt) + } + highestAt, err = db.HighestSlotBlocksBelow(ctx, 1) + if err != nil { + t.Fatal(err) + } + if !proto.Equal(genesisBlock, highestAt[0]) { + t.Errorf("Wanted %v, received %v", genesisBlock, highestAt) + } + highestAt, err = db.HighestSlotBlocksBelow(ctx, 0) + if err != nil { + t.Fatal(err) + } + if !proto.Equal(genesisBlock, highestAt[0]) { + t.Errorf("Wanted %v, received %v", genesisBlock, highestAt) + } +} + func TestStore_SaveBlocks_CanGetHighest(t *testing.T) { db := setupDB(t) defer teardownDB(t, db) diff --git a/beacon-chain/db/kv/state.go b/beacon-chain/db/kv/state.go index 5b9f3c619c91..814a7de1bd39 100644 --- a/beacon-chain/db/kv/state.go +++ b/beacon-chain/db/kv/state.go @@ -392,6 +392,15 @@ func (k *Store) statesAtSlotBitfieldIndex(ctx context.Context, tx *bolt.Tx, inde highestSlot := index - 1 highestSlot = int(math.Max(0, float64(highestSlot))) + + if highestSlot == 0 { + gState, err := k.GenesisState(ctx) + if err != nil { + return nil, err + } + return []*state.BeaconState{gState}, nil + } + f := filters.NewFilter().SetStartSlot(uint64(highestSlot)).SetEndSlot(uint64(highestSlot)) keys, err := getBlockRootsByFilter(ctx, tx, f) diff --git a/beacon-chain/db/kv/state_test.go b/beacon-chain/db/kv/state_test.go index d43489561e78..a9d981bfeaff 100644 --- a/beacon-chain/db/kv/state_test.go +++ b/beacon-chain/db/kv/state_test.go @@ -447,3 +447,54 @@ func TestStore_SaveDeleteState_CanGetHighestBelow(t *testing.T) { t.Errorf("Did not retrieve saved state: %v != %v", highest, s2) } } + +func TestStore_GenesisState_CanGetHighestBelow(t *testing.T) { + db := setupDB(t) + defer teardownDB(t, db) + + s := &pb.BeaconState{} + genesisState, err := state.InitializeFromProto(s) + if err != nil { + t.Fatal(err) + } + genesisRoot := [32]byte{'a'} + db.SaveGenesisBlockRoot(context.Background(), genesisRoot) + db.SaveState(context.Background(), genesisState, genesisRoot) + + s0 := &pb.BeaconState{Slot: 1} + b := ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Slot: 1}} + r, _ := ssz.HashTreeRoot(b.Block) + if err := db.SaveBlock(context.Background(), b); err != nil { + t.Fatal(err) + } + st, err := state.InitializeFromProto(s0) + if err != nil { + t.Fatal(err) + } + if err := db.SaveState(context.Background(), st, r); err != nil { + t.Fatal(err) + } + + highest, err := db.HighestSlotStatesBelow(context.Background(), 2) + if err != nil { + t.Fatal(err) + } + if !proto.Equal(highest[0].InnerStateUnsafe(), s0) { + t.Errorf("Did not retrieve saved state: %v != %v", highest, s0) + } + + highest, err = db.HighestSlotStatesBelow(context.Background(), 1) + if err != nil { + t.Fatal(err) + } + if !proto.Equal(highest[0].InnerStateUnsafe(), genesisState.InnerStateUnsafe()) { + t.Errorf("Did not retrieve saved state: %v != %v", highest, s0) + } + highest, err = db.HighestSlotStatesBelow(context.Background(), 0) + if err != nil { + t.Fatal(err) + } + if !proto.Equal(highest[0].InnerStateUnsafe(), genesisState.InnerStateUnsafe()) { + t.Errorf("Did not retrieve saved state: %v != %v", highest, s0) + } +} diff --git a/beacon-chain/rpc/beacon/blocks.go b/beacon-chain/rpc/beacon/blocks.go index 81746a0edc63..d753981d2c6b 100644 --- a/beacon-chain/rpc/beacon/blocks.go +++ b/beacon-chain/rpc/beacon/blocks.go @@ -4,7 +4,6 @@ import ( "context" "strconv" - "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" ptypes "github.com/gogo/protobuf/types" ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1" "github.com/prysmaticlabs/go-ssz" @@ -14,6 +13,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/db/filters" "github.com/prysmaticlabs/prysm/beacon-chain/flags" + "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" "github.com/prysmaticlabs/prysm/shared/bytesutil" "github.com/prysmaticlabs/prysm/shared/pagination" "google.golang.org/grpc/codes" diff --git a/slasher/rpc/server.go b/slasher/rpc/server.go index e6ba9b80de6c..51a1a5a7a25d 100644 --- a/slasher/rpc/server.go +++ b/slasher/rpc/server.go @@ -3,12 +3,12 @@ package rpc import ( "context" - "github.com/prysmaticlabs/prysm/slasher/db" - log "github.com/sirupsen/logrus" "github.com/pkg/errors" ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1" slashpb "github.com/prysmaticlabs/prysm/proto/slashing" + "github.com/prysmaticlabs/prysm/slasher/db" "github.com/prysmaticlabs/prysm/slasher/detection" + log "github.com/sirupsen/logrus" "go.opencensus.io/trace" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" diff --git a/slasher/rpc/service.go b/slasher/rpc/service.go index e27ab0112c1e..2d4e3edb2c79 100644 --- a/slasher/rpc/service.go +++ b/slasher/rpc/service.go @@ -5,13 +5,13 @@ import ( "fmt" "net" - "github.com/prysmaticlabs/prysm/slasher/db" middleware "github.com/grpc-ecosystem/go-grpc-middleware" recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery" grpc_opentracing "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing" grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus" slashpb "github.com/prysmaticlabs/prysm/proto/slashing" "github.com/prysmaticlabs/prysm/shared/traceutil" + "github.com/prysmaticlabs/prysm/slasher/db" "github.com/prysmaticlabs/prysm/slasher/detection" log "github.com/sirupsen/logrus" "go.opencensus.io/plugin/ocgrpc"