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 }