github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/state/v1/getters_attestation.go (about)

     1  package v1
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"fmt"
     7  
     8  	"github.com/pkg/errors"
     9  	"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
    10  	pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
    11  	"github.com/prysmaticlabs/prysm/shared/hashutil"
    12  	"github.com/prysmaticlabs/prysm/shared/htrutils"
    13  	"github.com/prysmaticlabs/prysm/shared/params"
    14  )
    15  
    16  // PreviousEpochAttestations corresponding to blocks on the beacon chain.
    17  func (b *BeaconState) PreviousEpochAttestations() ([]*pbp2p.PendingAttestation, error) {
    18  	if !b.hasInnerState() {
    19  		return nil, nil
    20  	}
    21  	if b.state.PreviousEpochAttestations == nil {
    22  		return nil, nil
    23  	}
    24  
    25  	b.lock.RLock()
    26  	defer b.lock.RUnlock()
    27  
    28  	return b.previousEpochAttestations(), nil
    29  }
    30  
    31  // previousEpochAttestations corresponding to blocks on the beacon chain.
    32  // This assumes that a lock is already held on BeaconState.
    33  func (b *BeaconState) previousEpochAttestations() []*pbp2p.PendingAttestation {
    34  	if !b.hasInnerState() {
    35  		return nil
    36  	}
    37  
    38  	return b.safeCopyPendingAttestationSlice(b.state.PreviousEpochAttestations)
    39  }
    40  
    41  // CurrentEpochAttestations corresponding to blocks on the beacon chain.
    42  func (b *BeaconState) CurrentEpochAttestations() ([]*pbp2p.PendingAttestation, error) {
    43  	if !b.hasInnerState() {
    44  		return nil, nil
    45  	}
    46  	if b.state.CurrentEpochAttestations == nil {
    47  		return nil, nil
    48  	}
    49  
    50  	b.lock.RLock()
    51  	defer b.lock.RUnlock()
    52  
    53  	return b.currentEpochAttestations(), nil
    54  }
    55  
    56  // currentEpochAttestations corresponding to blocks on the beacon chain.
    57  // This assumes that a lock is already held on BeaconState.
    58  func (b *BeaconState) currentEpochAttestations() []*pbp2p.PendingAttestation {
    59  	if !b.hasInnerState() {
    60  		return nil
    61  	}
    62  
    63  	return b.safeCopyPendingAttestationSlice(b.state.CurrentEpochAttestations)
    64  }
    65  
    66  func (h *stateRootHasher) epochAttestationsRoot(atts []*pbp2p.PendingAttestation) ([32]byte, error) {
    67  	max := uint64(params.BeaconConfig().SlotsPerEpoch) * params.BeaconConfig().MaxAttestations
    68  	if uint64(len(atts)) > max {
    69  		return [32]byte{}, fmt.Errorf("epoch attestation exceeds max length %d", max)
    70  	}
    71  
    72  	hasher := hashutil.CustomSHA256Hasher()
    73  	roots := make([][]byte, len(atts))
    74  	for i := 0; i < len(atts); i++ {
    75  		pendingRoot, err := h.pendingAttestationRoot(hasher, atts[i])
    76  		if err != nil {
    77  			return [32]byte{}, errors.Wrap(err, "could not attestation merkleization")
    78  		}
    79  		roots[i] = pendingRoot[:]
    80  	}
    81  
    82  	attsRootsRoot, err := htrutils.BitwiseMerkleize(
    83  		hasher,
    84  		roots,
    85  		uint64(len(roots)),
    86  		uint64(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().MaxAttestations)),
    87  	)
    88  	if err != nil {
    89  		return [32]byte{}, errors.Wrap(err, "could not compute epoch attestations merkleization")
    90  	}
    91  	attsLenBuf := new(bytes.Buffer)
    92  	if err := binary.Write(attsLenBuf, binary.LittleEndian, uint64(len(atts))); err != nil {
    93  		return [32]byte{}, errors.Wrap(err, "could not marshal epoch attestations length")
    94  	}
    95  	// We need to mix in the length of the slice.
    96  	attsLenRoot := make([]byte, 32)
    97  	copy(attsLenRoot, attsLenBuf.Bytes())
    98  	res := htrutils.MixInLength(attsRootsRoot, attsLenRoot)
    99  	return res, nil
   100  }
   101  
   102  func (h *stateRootHasher) pendingAttestationRoot(hasher htrutils.HashFn, att *pbp2p.PendingAttestation) ([32]byte, error) {
   103  	if att == nil {
   104  		return [32]byte{}, errors.New("nil pending attestation")
   105  	}
   106  	// Marshal attestation to determine if it exists in the cache.
   107  	enc := stateutil.PendingAttEncKey(att)
   108  
   109  	// Check if it exists in cache:
   110  	if h.rootsCache != nil {
   111  		if found, ok := h.rootsCache.Get(string(enc)); found != nil && ok {
   112  			return found.([32]byte), nil
   113  		}
   114  	}
   115  
   116  	res, err := stateutil.PendingAttRootWithHasher(hasher, att)
   117  	if err != nil {
   118  		return [32]byte{}, err
   119  	}
   120  	if h.rootsCache != nil {
   121  		h.rootsCache.Set(string(enc), res, 32)
   122  	}
   123  	return res, nil
   124  }