mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-22 03:30:35 +00:00
Import proposal protection (#7430)
* Import proposals protection db * Import old proposal protection data structure to new one * test empty slots * Update validator/db/kv/new_proposal_history.go Co-authored-by: Victor Farazdagi <simple.square@gmail.com> * Update validator/db/kv/new_proposal_history_test.go Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> Co-authored-by: Victor Farazdagi <simple.square@gmail.com>
This commit is contained in:
parent
25ebed9a70
commit
1315a15d9d
@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
@ -43,9 +44,9 @@ func (store *Store) SaveProposalHistoryForSlot(ctx context.Context, pubKey []byt
|
||||
|
||||
err := store.update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(newhistoricProposalsBucket)
|
||||
valBucket := bucket.Bucket(pubKey)
|
||||
if valBucket == nil {
|
||||
return fmt.Errorf("validator history is empty for validator %#x", pubKey)
|
||||
valBucket, err := bucket.CreateBucketIfNotExists(pubKey)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not create bucket for public key %#x", pubKey)
|
||||
}
|
||||
if err := valBucket.Put(bytesutil.Uint64ToBytesBigEndian(slot), signingRoot); err != nil {
|
||||
return err
|
||||
@ -58,6 +59,78 @@ func (store *Store) SaveProposalHistoryForSlot(ctx context.Context, pubKey []byt
|
||||
return err
|
||||
}
|
||||
|
||||
// ImportProposalHistory accepts a validator public key and returns the corresponding signing root.
|
||||
// Returns nil if there is no proposal history for the validator at this slot.
|
||||
func (store *Store) ImportProposalHistory(ctx context.Context) error {
|
||||
ctx, span := trace.StartSpan(ctx, "Validator.ImportProposalHistory")
|
||||
defer span.End()
|
||||
|
||||
var allKeys [][]byte
|
||||
err := store.db.View(func(tx *bolt.Tx) error {
|
||||
proposalsBucket := tx.Bucket(historicProposalsBucket)
|
||||
if err := proposalsBucket.ForEach(func(pubKey, _ []byte) error {
|
||||
pubKeyCopy := make([]byte, len(pubKey))
|
||||
copy(pubKeyCopy, pubKey)
|
||||
allKeys = append(allKeys, pubKeyCopy)
|
||||
return nil
|
||||
}); err != nil {
|
||||
return errors.Wrapf(err, "could not retrieve proposals for source in %s", store.databasePath)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
allKeys = removeDuplicateKeys(allKeys)
|
||||
var prs []*pubKeyProposals
|
||||
err = store.db.View(func(tx *bolt.Tx) error {
|
||||
proposalsBucket := tx.Bucket(historicProposalsBucket)
|
||||
for _, pk := range allKeys {
|
||||
pr, err := getPubKeyProposals(pk, proposalsBucket)
|
||||
prs = append(prs, pr)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not retrieve public key old proposals format")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = store.db.Update(func(tx *bolt.Tx) error {
|
||||
newProposalsBucket := tx.Bucket(newhistoricProposalsBucket)
|
||||
for _, pr := range prs {
|
||||
valBucket, err := newProposalsBucket.CreateBucketIfNotExists(pr.PubKey)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not could not create bucket for public key")
|
||||
}
|
||||
for _, epochProposals := range pr.Proposals {
|
||||
// Adding an extra byte for the bitlist length.
|
||||
slotBitlist := make(bitfield.Bitlist, params.BeaconConfig().SlotsPerEpoch/8+1)
|
||||
slotBits := epochProposals.Proposals
|
||||
if len(slotBits) == 0 {
|
||||
continue
|
||||
}
|
||||
copy(slotBitlist, slotBits)
|
||||
for i := uint64(0); i < params.BeaconConfig().SlotsPerEpoch; i++ {
|
||||
if slotBitlist.BitAt(i) {
|
||||
ss, err := helpers.StartSlot(bytesutil.FromBytes8(epochProposals.Epoch))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := valBucket.Put(bytesutil.Uint64ToBytesBigEndian(ss+i), []byte{1}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// UpdatePublicKeysNewBuckets for a specified list of keys.
|
||||
func (store *Store) UpdatePublicKeysNewBuckets(pubKeys [][48]byte) error {
|
||||
return store.update(func(tx *bolt.Tx) error {
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
@ -137,3 +138,42 @@ func TestPruneProposalHistoryBySlot_OK(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestStore_ImportProposalHistory(t *testing.T) {
|
||||
pubkey := [48]byte{3}
|
||||
ctx := context.Background()
|
||||
db := setupDB(t, [][48]byte{pubkey})
|
||||
proposedSlots := make(map[uint64]bool)
|
||||
proposedSlots[0] = true
|
||||
proposedSlots[1] = true
|
||||
proposedSlots[20] = true
|
||||
proposedSlots[31] = true
|
||||
proposedSlots[32] = true
|
||||
proposedSlots[33] = true
|
||||
proposedSlots[1023] = true
|
||||
proposedSlots[1024] = true
|
||||
proposedSlots[1025] = true
|
||||
lastIndex := 1025 + params.BeaconConfig().SlotsPerEpoch
|
||||
|
||||
for slot := range proposedSlots {
|
||||
slotBitlist, err := db.ProposalHistoryForEpoch(context.Background(), pubkey[:], helpers.SlotToEpoch(slot))
|
||||
require.NoError(t, err)
|
||||
slotBitlist.SetBitAt(slot%params.BeaconConfig().SlotsPerEpoch, true)
|
||||
err = db.SaveProposalHistoryForEpoch(context.Background(), pubkey[:], helpers.SlotToEpoch(slot), slotBitlist)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
err := db.ImportProposalHistory(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
for slot := uint64(0); slot <= lastIndex; slot++ {
|
||||
if _, ok := proposedSlots[slot]; ok {
|
||||
root, err := db.ProposalHistoryForSlot(ctx, pubkey[:], slot)
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, bytesutil.PadTo([]byte{1}, 32), root, "slot: %d", slot)
|
||||
continue
|
||||
}
|
||||
root, err := db.ProposalHistoryForSlot(ctx, pubkey[:], slot)
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, bytesutil.PadTo([]byte{}, 32), root)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user