Skip to content

Commit

Permalink
Update to slash by slot instead of epoch (#5297)
Browse files Browse the repository at this point in the history
* change to slash by slot instead of epoch

* gaz

* fix test

* fix test

* fix infinite loop on error parse
  • Loading branch information
shayzluf authored Apr 3, 2020
1 parent bbcd895 commit 8d6aed9
Show file tree
Hide file tree
Showing 9 changed files with 64 additions and 50 deletions.
1 change: 1 addition & 0 deletions slasher/beaconclient/receivers.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ func (bs *Service) receiveBlocks(ctx context.Context) {
}
if err != nil {
log.WithError(err).Error("Could not receive block from beacon node")
break
}
if res == nil {
continue
Expand Down
22 changes: 11 additions & 11 deletions slasher/db/kv/block_header.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ func unmarshalBlockHeader(ctx context.Context, enc []byte) (*ethpb.SignedBeaconB
return protoBlockHeader, nil
}

// BlockHeaders accepts an epoch and validator id and returns the corresponding block header array.
// BlockHeaders accepts an slot and validator id and returns the corresponding block header array.
// Returns nil if the block header for those values does not exist.
func (db *Store) BlockHeaders(ctx context.Context, epoch uint64, validatorID uint64) ([]*ethpb.SignedBeaconBlockHeader, error) {
func (db *Store) BlockHeaders(ctx context.Context, slot uint64, validatorID uint64) ([]*ethpb.SignedBeaconBlockHeader, error) {
ctx, span := trace.StartSpan(ctx, "slasherDB.BlockHeaders")
defer span.End()
var blockHeaders []*ethpb.SignedBeaconBlockHeader
err := db.view(func(tx *bolt.Tx) error {
c := tx.Bucket(historicBlockHeadersBucket).Cursor()
prefix := encodeEpochValidatorID(epoch, validatorID)
prefix := encodeSlotValidatorID(slot, validatorID)
for k, v := c.Seek(prefix); k != nil && bytes.HasPrefix(k, prefix); k, v = c.Next() {
bh, err := unmarshalBlockHeader(ctx, v)
if err != nil {
Expand All @@ -46,11 +46,11 @@ func (db *Store) BlockHeaders(ctx context.Context, epoch uint64, validatorID uin
return blockHeaders, err
}

// HasBlockHeader accepts an epoch and validator id and returns true if the block header exists.
func (db *Store) HasBlockHeader(ctx context.Context, epoch uint64, validatorID uint64) bool {
// HasBlockHeader accepts a slot and validator id and returns true if the block header exists.
func (db *Store) HasBlockHeader(ctx context.Context, slot uint64, validatorID uint64) bool {
ctx, span := trace.StartSpan(ctx, "slasherDB.HasBlockHeader")
defer span.End()
prefix := encodeEpochValidatorID(epoch, validatorID)
prefix := encodeSlotValidatorID(slot, validatorID)
var hasBlockHeader bool
// #nosec G104
_ = db.view(func(tx *bolt.Tx) error {
Expand All @@ -71,7 +71,7 @@ func (db *Store) SaveBlockHeader(ctx context.Context, blockHeader *ethpb.SignedB
ctx, span := trace.StartSpan(ctx, "slasherDB.SaveBlockHeader")
defer span.End()
epoch := helpers.SlotToEpoch(blockHeader.Header.Slot)
key := encodeEpochValidatorIDSig(epoch, blockHeader.Header.ProposerIndex, blockHeader.Signature)
key := encodeSlotValidatorIDSig(blockHeader.Header.Slot, blockHeader.Header.ProposerIndex, blockHeader.Signature)
enc, err := proto.Marshal(blockHeader)
if err != nil {
return errors.Wrap(err, "failed to encode block")
Expand All @@ -96,12 +96,11 @@ func (db *Store) SaveBlockHeader(ctx context.Context, blockHeader *ethpb.SignedB
return nil
}

// DeleteBlockHeader deletes a block header using the epoch and validator id.
// DeleteBlockHeader deletes a block header using the slot and validator id.
func (db *Store) DeleteBlockHeader(ctx context.Context, blockHeader *ethpb.SignedBeaconBlockHeader) error {
ctx, span := trace.StartSpan(ctx, "slasherDB.DeleteBlockHeader")
defer span.End()
epoch := helpers.SlotToEpoch(blockHeader.Header.Slot)
key := encodeEpochValidatorIDSig(epoch, blockHeader.Header.ProposerIndex, blockHeader.Signature)
key := encodeSlotValidatorIDSig(blockHeader.Header.Slot, blockHeader.Header.ProposerIndex, blockHeader.Signature)
return db.update(func(tx *bolt.Tx) error {
bucket := tx.Bucket(historicBlockHeadersBucket)
if err := bucket.Delete(key); err != nil {
Expand All @@ -119,10 +118,11 @@ func (db *Store) PruneBlockHistory(ctx context.Context, currentEpoch uint64, pru
if pruneTill <= 0 {
return nil
}
pruneTillSlot := uint64(pruneTill) * params.BeaconConfig().SlotsPerEpoch
return db.update(func(tx *bolt.Tx) error {
bucket := tx.Bucket(historicBlockHeadersBucket)
c := tx.Bucket(historicBlockHeadersBucket).Cursor()
for k, _ := c.First(); k != nil && bytesutil.FromBytes8(k[:8]) <= uint64(pruneTill); k, _ = c.Next() {
for k, _ := c.First(); k != nil && bytesutil.FromBytes8(k[:8]) <= pruneTillSlot; k, _ = c.Next() {
if err := bucket.Delete(k); err != nil {
return errors.Wrap(err, "failed to delete the block header from historical bucket")
}
Expand Down
29 changes: 17 additions & 12 deletions slasher/db/kv/block_header_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ func TestNilDBHistoryBlkHdr(t *testing.T) {
defer teardownDB(t, db)
ctx := context.Background()

epoch := uint64(1)
slot := uint64(1)
validatorID := uint64(1)

hasBlockHeader := db.HasBlockHeader(ctx, epoch, validatorID)
hasBlockHeader := db.HasBlockHeader(ctx, slot, validatorID)
if hasBlockHeader {
t.Fatal("HasBlockHeader should return false")
}

bPrime, err := db.BlockHeaders(ctx, epoch, validatorID)
bPrime, err := db.BlockHeaders(ctx, slot, validatorID)
if err != nil {
t.Fatalf("failed to get block: %v", err)
}
Expand All @@ -52,9 +52,11 @@ func TestSaveHistoryBlkHdr(t *testing.T) {
bh: &ethpb.SignedBeaconBlockHeader{Signature: []byte("let me in 2nd"), Header: &ethpb.BeaconBlockHeader{Slot: 0, ProposerIndex: 1}},
},
{

bh: &ethpb.SignedBeaconBlockHeader{Signature: []byte("let me in 3rd"), Header: &ethpb.BeaconBlockHeader{Slot: params.BeaconConfig().SlotsPerEpoch + 1, ProposerIndex: 0}},
},
{
bh: &ethpb.SignedBeaconBlockHeader{Signature: []byte("let me in 3rd"), Header: &ethpb.BeaconBlockHeader{Slot: 1, ProposerIndex: 0}},
},
}

for _, tt := range tests {
Expand All @@ -63,7 +65,7 @@ func TestSaveHistoryBlkHdr(t *testing.T) {
t.Fatalf("save block failed: %v", err)
}

bha, err := db.BlockHeaders(ctx, helpers.SlotToEpoch(tt.bh.Header.Slot), tt.bh.Header.ProposerIndex)
bha, err := db.BlockHeaders(ctx, tt.bh.Header.Slot, tt.bh.Header.ProposerIndex)
if err != nil {
t.Fatalf("failed to get block: %v", err)
}
Expand Down Expand Up @@ -104,7 +106,7 @@ func TestDeleteHistoryBlkHdr(t *testing.T) {
}

for _, tt := range tests {
bha, err := db.BlockHeaders(ctx, helpers.SlotToEpoch(tt.bh.Header.Slot), tt.bh.Header.ProposerIndex)
bha, err := db.BlockHeaders(ctx, tt.bh.Header.Slot, tt.bh.Header.ProposerIndex)
if err != nil {
t.Fatalf("failed to get block: %v", err)
}
Expand All @@ -116,7 +118,7 @@ func TestDeleteHistoryBlkHdr(t *testing.T) {
if err != nil {
t.Fatalf("save block failed: %v", err)
}
bh, err := db.BlockHeaders(ctx, helpers.SlotToEpoch(tt.bh.Header.Slot), tt.bh.Header.ProposerIndex)
bh, err := db.BlockHeaders(ctx, tt.bh.Header.Slot, tt.bh.Header.ProposerIndex)

if err != nil {
t.Fatal(err)
Expand Down Expand Up @@ -148,10 +150,13 @@ func TestHasHistoryBlkHdr(t *testing.T) {
{
bh: &ethpb.SignedBeaconBlockHeader{Signature: []byte("let me in 3rd"), Header: &ethpb.BeaconBlockHeader{Slot: params.BeaconConfig().SlotsPerEpoch + 1, ProposerIndex: 0}},
},
{
bh: &ethpb.SignedBeaconBlockHeader{Signature: []byte("let me in 4th"), Header: &ethpb.BeaconBlockHeader{Slot: 1, ProposerIndex: 0}},
},
}
for _, tt := range tests {

found := db.HasBlockHeader(ctx, helpers.SlotToEpoch(tt.bh.Header.Slot), tt.bh.Header.ProposerIndex)
found := db.HasBlockHeader(ctx, tt.bh.Header.Slot, tt.bh.Header.ProposerIndex)
if found {
t.Fatal("has block header should return false for block headers that are not in db")
}
Expand All @@ -166,7 +171,7 @@ func TestHasHistoryBlkHdr(t *testing.T) {
t.Fatalf("save block failed: %v", err)
}

found := db.HasBlockHeader(ctx, helpers.SlotToEpoch(tt.bh.Header.Slot), tt.bh.Header.ProposerIndex)
found := db.HasBlockHeader(ctx, tt.bh.Header.Slot, tt.bh.Header.ProposerIndex)

if !found {
t.Fatal("has block header should return true")
Expand Down Expand Up @@ -207,7 +212,7 @@ func TestPruneHistoryBlkHdr(t *testing.T) {
t.Fatalf("save block header failed: %v", err)
}

bha, err := db.BlockHeaders(ctx, helpers.SlotToEpoch(tt.bh.Header.Slot), tt.bh.Header.ProposerIndex)
bha, err := db.BlockHeaders(ctx, tt.bh.Header.Slot, tt.bh.Header.ProposerIndex)
if err != nil {
t.Fatalf("failed to get block header: %v", err)
}
Expand All @@ -224,11 +229,11 @@ func TestPruneHistoryBlkHdr(t *testing.T) {
}

for _, tt := range tests {
bha, err := db.BlockHeaders(ctx, helpers.SlotToEpoch(tt.bh.Header.Slot), tt.bh.Header.ProposerIndex)
bha, err := db.BlockHeaders(ctx, tt.bh.Header.Slot, tt.bh.Header.ProposerIndex)
if err != nil {
t.Fatalf("failed to get block header: %v", err)
}
if helpers.SlotToEpoch(tt.bh.Header.Slot) > currentEpoch-historyToKeep {
if helpers.SlotToEpoch(tt.bh.Header.Slot) >= currentEpoch-historyToKeep {
if bha == nil || !reflect.DeepEqual(bha[0], tt.bh) {
t.Fatalf("get should return bh: %v", bha)
}
Expand Down
8 changes: 4 additions & 4 deletions slasher/db/kv/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ var (
validatorsMinMaxSpanBucket = []byte("validators-min-max-span-bucket")
)

func encodeEpochValidatorID(epoch uint64, validatorID uint64) []byte {
return append(bytesutil.Bytes8(epoch), bytesutil.Bytes8(validatorID)...)
func encodeSlotValidatorID(slot uint64, validatorID uint64) []byte {
return append(bytesutil.Bytes8(slot), bytesutil.Bytes8(validatorID)...)
}

func encodeEpochValidatorIDSig(epoch uint64, validatorID uint64, sig []byte) []byte {
return append(append(bytesutil.Bytes8(epoch), bytesutil.Bytes8(validatorID)...), sig...)
func encodeSlotValidatorIDSig(slot uint64, validatorID uint64, sig []byte) []byte {
return append(append(bytesutil.Bytes8(slot), bytesutil.Bytes8(validatorID)...), sig...)
}

func encodeEpochSig(targetEpoch uint64, sig []byte) []byte {
Expand Down
3 changes: 2 additions & 1 deletion slasher/detection/detect.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,8 @@ func isDoublePropose(
prevBlockHeader *ethpb.SignedBeaconBlockHeader,
) bool {
return incomingBlockHeader.Header.ProposerIndex == prevBlockHeader.Header.ProposerIndex &&
!bytes.Equal(incomingBlockHeader.Signature, prevBlockHeader.Signature)
!bytes.Equal(incomingBlockHeader.Signature, prevBlockHeader.Signature) &&
incomingBlockHeader.Header.Slot == prevBlockHeader.Header.Slot
}

func isDoubleVote(incomingAtt *ethpb.IndexedAttestation, prevAtt *ethpb.IndexedAttestation) bool {
Expand Down
18 changes: 9 additions & 9 deletions slasher/detection/detect_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -352,11 +352,11 @@ func TestDetect_detectProposerSlashing(t *testing.T) {
incomingBlk *ethpb.SignedBeaconBlockHeader
slashing *ethpb.ProposerSlashing
}
blk1epoch0, err := testDetect.SignedBlockHeader(testDetect.StartSlot(0), 0)
blk1slot0, err := testDetect.SignedBlockHeader(testDetect.StartSlot(0), 0)
if err != nil {
t.Fatal(err)
}
blk2epoch0, err := testDetect.SignedBlockHeader(testDetect.StartSlot(0)+1, 0)
blk2slot0, err := testDetect.SignedBlockHeader(testDetect.StartSlot(0), 0)
if err != nil {
t.Fatal(err)
}
Expand All @@ -367,21 +367,21 @@ func TestDetect_detectProposerSlashing(t *testing.T) {
tests := []testStruct{
{
name: "same block sig dont slash",
blk: blk1epoch0,
incomingBlk: blk1epoch0,
blk: blk1slot0,
incomingBlk: blk1slot0,
slashing: nil,
},
{
name: "block from different epoch dont slash",
blk: blk1epoch0,
blk: blk1slot0,
incomingBlk: blk1epoch1,
slashing: nil,
},
{
name: "different sig from same epoch slash",
blk: blk1epoch0,
incomingBlk: blk2epoch0,
slashing: &ethpb.ProposerSlashing{Header_1: blk2epoch0, Header_2: blk1epoch0},
name: "different sig from same slot slash",
blk: blk1slot0,
incomingBlk: blk2slot0,
slashing: &ethpb.ProposerSlashing{Header_1: blk2slot0, Header_2: blk1slot0},
},
}
for _, tt := range tests {
Expand Down
1 change: 0 additions & 1 deletion slasher/detection/proposals/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ go_library(
importpath = "github.com/prysmaticlabs/prysm/slasher/detection/proposals",
visibility = ["//visibility:public"],
deps = [
"//beacon-chain/core/helpers:go_default_library",
"//slasher/db:go_default_library",
"//slasher/db/types:go_default_library",
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
Expand Down
4 changes: 1 addition & 3 deletions slasher/detection/proposals/detector.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"context"

ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/slasher/db"
status "github.com/prysmaticlabs/prysm/slasher/db/types"
"go.opencensus.io/trace"
Expand All @@ -31,8 +30,7 @@ func (dd *ProposeDetector) DetectDoublePropose(
) (*ethpb.ProposerSlashing, error) {
ctx, span := trace.StartSpan(ctx, "detector.DetectDoublePropose")
defer span.End()
epoch := helpers.SlotToEpoch(incomingBlk.Header.Slot)
bha, err := dd.slasherDB.BlockHeaders(ctx, epoch, incomingBlk.Header.ProposerIndex)
bha, err := dd.slasherDB.BlockHeaders(ctx, incomingBlk.Header.Slot, incomingBlk.Header.ProposerIndex)
if err != nil {
return nil, err
}
Expand Down
28 changes: 19 additions & 9 deletions slasher/detection/proposals/detector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,15 @@ func TestProposalsDetector_DetectSlashingsForBlockHeaders(t *testing.T) {
incomingBlk *ethpb.SignedBeaconBlockHeader
slashing *ethpb.ProposerSlashing
}
blk1epoch0, err := testDetect.SignedBlockHeader(testDetect.StartSlot(0), 0)
blk1slot0, err := testDetect.SignedBlockHeader(testDetect.StartSlot(0), 0)
if err != nil {
t.Fatal(err)
}
blk2epoch0, err := testDetect.SignedBlockHeader(testDetect.StartSlot(0)+1, 0)
blk2slot0, err := testDetect.SignedBlockHeader(testDetect.StartSlot(0), 0)
if err != nil {
t.Fatal(err)
}
blk1slot1, err := testDetect.SignedBlockHeader(testDetect.StartSlot(0)+1, 0)
if err != nil {
t.Fatal(err)
}
Expand All @@ -35,21 +39,27 @@ func TestProposalsDetector_DetectSlashingsForBlockHeaders(t *testing.T) {
tests := []testStruct{
{
name: "same block sig dont slash",
blk: blk1epoch0,
incomingBlk: blk1epoch0,
blk: blk1slot0,
incomingBlk: blk1slot0,
slashing: nil,
},
{
name: "block from different epoch dont slash",
blk: blk1epoch0,
blk: blk1slot0,
incomingBlk: blk1epoch1,
slashing: nil,
},
{
name: "different sig from same epoch slash",
blk: blk1epoch0,
incomingBlk: blk2epoch0,
slashing: &ethpb.ProposerSlashing{Header_1: blk2epoch0, Header_2: blk1epoch0},
name: "different sig from different slot dont slash",
blk: blk1slot0,
incomingBlk: blk1slot1,
slashing: nil,
},
{
name: "different sig from same slot slash",
blk: blk1slot0,
incomingBlk: blk2slot0,
slashing: &ethpb.ProposerSlashing{Header_1: blk2slot0, Header_2: blk1slot0},
},
}

Expand Down

0 comments on commit 8d6aed9

Please sign in to comment.