github.com/prysmaticlabs/prysm@v1.4.4/validator/db/kv/deprecated_attester_protection.go (about)

     1  package kv
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	types "github.com/prysmaticlabs/eth2-types"
     8  	"github.com/prysmaticlabs/prysm/shared/bytesutil"
     9  	"github.com/prysmaticlabs/prysm/shared/params"
    10  )
    11  
    12  const (
    13  	// The size of each data entry in bytes for the source epoch (8 bytes) and signing root (32 bytes).
    14  	uint64Size             = 8
    15  	latestEpochWrittenSize = uint64Size
    16  	targetSize             = uint64Size
    17  	sourceSize             = uint64Size
    18  	signingRootSize        = 32
    19  	historySize            = targetSize + sourceSize + signingRootSize
    20  	minimalSize            = latestEpochWrittenSize
    21  )
    22  
    23  // deprecatedHistoryData stores the needed data to confirm if an attestation is slashable
    24  // or repeated.
    25  type deprecatedHistoryData struct {
    26  	Source      types.Epoch
    27  	SigningRoot []byte
    28  }
    29  
    30  // deprecatedEncodedAttestingHistory encapsulated history data.
    31  type deprecatedEncodedAttestingHistory []byte
    32  
    33  func (dh deprecatedEncodedAttestingHistory) assertSize() error {
    34  	if dh == nil || len(dh) < minimalSize {
    35  		return fmt.Errorf("encapsulated data size: %d is smaller then minimal size: %d", len(dh), minimalSize)
    36  	}
    37  	if (len(dh)-minimalSize)%historySize != 0 {
    38  		return fmt.Errorf("encapsulated data size: %d is not a multiple of entry size: %d", len(dh), historySize)
    39  	}
    40  	return nil
    41  }
    42  
    43  func (dhd *deprecatedHistoryData) isEmpty() bool {
    44  	if dhd == (*deprecatedHistoryData)(nil) {
    45  		return true
    46  	}
    47  	if dhd.Source == params.BeaconConfig().FarFutureEpoch {
    48  		return true
    49  	}
    50  	return false
    51  }
    52  
    53  func emptyHistoryData() *deprecatedHistoryData {
    54  	h := &deprecatedHistoryData{Source: params.BeaconConfig().FarFutureEpoch, SigningRoot: bytesutil.PadTo([]byte{}, 32)}
    55  	return h
    56  }
    57  
    58  // newDeprecatedAttestingHistory creates a new encapsulated attestation history byte array
    59  // sized by the latest epoch written.
    60  func newDeprecatedAttestingHistory(target types.Epoch) deprecatedEncodedAttestingHistory {
    61  	relativeTarget := target % params.BeaconConfig().WeakSubjectivityPeriod
    62  	historyDataSize := (relativeTarget + 1) * historySize
    63  	arraySize := latestEpochWrittenSize + historyDataSize
    64  	en := make(deprecatedEncodedAttestingHistory, arraySize)
    65  	enc := en
    66  	ctx := context.Background()
    67  	var err error
    68  	for i := types.Epoch(0); i <= target%params.BeaconConfig().WeakSubjectivityPeriod; i++ {
    69  		enc, err = enc.setTargetData(ctx, i, emptyHistoryData())
    70  		if err != nil {
    71  			log.WithError(err).Error("Failed to set empty target data")
    72  		}
    73  	}
    74  	return enc
    75  }
    76  
    77  func (dh deprecatedEncodedAttestingHistory) getLatestEpochWritten(ctx context.Context) (types.Epoch, error) {
    78  	if err := dh.assertSize(); err != nil {
    79  		return 0, err
    80  	}
    81  	return types.Epoch(bytesutil.FromBytes8(dh[:latestEpochWrittenSize])), nil
    82  }
    83  
    84  func (dh deprecatedEncodedAttestingHistory) setLatestEpochWritten(
    85  	ctx context.Context,
    86  	latestEpochWritten types.Epoch,
    87  ) (deprecatedEncodedAttestingHistory, error) {
    88  	if err := dh.assertSize(); err != nil {
    89  		return nil, err
    90  	}
    91  	copy(dh[:latestEpochWrittenSize], bytesutil.EpochToBytesLittleEndian(latestEpochWritten))
    92  	return dh, nil
    93  }
    94  
    95  func (dh deprecatedEncodedAttestingHistory) getTargetData(ctx context.Context, target types.Epoch) (*deprecatedHistoryData, error) {
    96  	if err := dh.assertSize(); err != nil {
    97  		return nil, err
    98  	}
    99  	// Cursor for the location to read target epoch from.
   100  	// Modulus of target epoch X weak subjectivity period in order to have maximum size to the encapsulated data array.
   101  	cursor := (target%params.BeaconConfig().WeakSubjectivityPeriod)*historySize + latestEpochWrittenSize
   102  	if uint64(len(dh)) < uint64(cursor+historySize) {
   103  		return nil, nil
   104  	}
   105  	history := &deprecatedHistoryData{}
   106  	history.Source = types.Epoch(bytesutil.FromBytes8(dh[cursor : cursor+sourceSize]))
   107  	sr := make([]byte, 32)
   108  	copy(sr, dh[cursor+sourceSize:cursor+historySize])
   109  	history.SigningRoot = sr
   110  	return history, nil
   111  }
   112  
   113  func (dh deprecatedEncodedAttestingHistory) setTargetData(
   114  	ctx context.Context,
   115  	target types.Epoch,
   116  	historyData *deprecatedHistoryData,
   117  ) (deprecatedEncodedAttestingHistory, error) {
   118  	if err := dh.assertSize(); err != nil {
   119  		return nil, err
   120  	}
   121  	// Cursor for the location to write target epoch to.
   122  	// Modulus of target epoch  X weak subjectivity period in order to have maximum size to the encapsulated data array.
   123  	cursor := latestEpochWrittenSize + (target%params.BeaconConfig().WeakSubjectivityPeriod)*historySize
   124  
   125  	if uint64(len(dh)) < uint64(cursor+historySize) {
   126  		ext := make([]byte, uint64(cursor+historySize)-uint64(len(dh)))
   127  		dh = append(dh, ext...)
   128  	}
   129  	copy(dh[cursor:cursor+sourceSize], bytesutil.EpochToBytesLittleEndian(historyData.Source))
   130  	copy(dh[cursor+sourceSize:cursor+sourceSize+signingRootSize], historyData.SigningRoot)
   131  
   132  	return dh, nil
   133  }