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

     1  package v1
     2  
     3  import (
     4  	"context"
     5  	"encoding/binary"
     6  	"sync"
     7  
     8  	"github.com/dgraph-io/ristretto"
     9  	"github.com/pkg/errors"
    10  	"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
    11  	pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
    12  	"github.com/prysmaticlabs/prysm/shared/bytesutil"
    13  	"github.com/prysmaticlabs/prysm/shared/featureconfig"
    14  	"github.com/prysmaticlabs/prysm/shared/hashutil"
    15  	"github.com/prysmaticlabs/prysm/shared/htrutils"
    16  	"github.com/prysmaticlabs/prysm/shared/params"
    17  	"go.opencensus.io/trace"
    18  )
    19  
    20  var (
    21  	leavesCache = make(map[string][][32]byte, params.BeaconConfig().BeaconStateFieldCount)
    22  	layersCache = make(map[string][][][32]byte, params.BeaconConfig().BeaconStateFieldCount)
    23  	lock        sync.RWMutex
    24  )
    25  
    26  const cacheSize = 100000
    27  
    28  var nocachedHasher *stateRootHasher
    29  var cachedHasher *stateRootHasher
    30  
    31  func init() {
    32  	rootsCache, err := ristretto.NewCache(&ristretto.Config{
    33  		NumCounters: cacheSize, // number of keys to track frequency of (1M).
    34  		MaxCost:     1 << 22,   // maximum cost of cache (3MB).
    35  		// 100,000 roots will take up approximately 3 MB in memory.
    36  		BufferItems: 64, // number of keys per Get buffer.
    37  	})
    38  	if err != nil {
    39  		panic(err)
    40  	}
    41  	// Temporarily disable roots cache until cache issues can be resolved.
    42  	cachedHasher = &stateRootHasher{rootsCache: rootsCache}
    43  	nocachedHasher = &stateRootHasher{}
    44  }
    45  
    46  type stateRootHasher struct {
    47  	rootsCache *ristretto.Cache
    48  }
    49  
    50  // computeFieldRoots returns the hash tree root computations of every field in
    51  // the beacon state as a list of 32 byte roots.
    52  func computeFieldRoots(ctx context.Context, state *pb.BeaconState) ([][]byte, error) {
    53  	if featureconfig.Get().EnableSSZCache {
    54  		return cachedHasher.computeFieldRootsWithHasher(ctx, state)
    55  	}
    56  	return nocachedHasher.computeFieldRootsWithHasher(ctx, state)
    57  }
    58  
    59  func (h *stateRootHasher) computeFieldRootsWithHasher(ctx context.Context, state *pb.BeaconState) ([][]byte, error) {
    60  	ctx, span := trace.StartSpan(ctx, "beaconState.computeFieldRootsWithHasher")
    61  	defer span.End()
    62  
    63  	if state == nil {
    64  		return nil, errors.New("nil state")
    65  	}
    66  	hasher := hashutil.CustomSHA256Hasher()
    67  	fieldRoots := make([][]byte, params.BeaconConfig().BeaconStateFieldCount)
    68  
    69  	// Genesis time root.
    70  	genesisRoot := htrutils.Uint64Root(state.GenesisTime)
    71  	fieldRoots[0] = genesisRoot[:]
    72  
    73  	// Genesis validator root.
    74  	r := [32]byte{}
    75  	copy(r[:], state.GenesisValidatorsRoot)
    76  	fieldRoots[1] = r[:]
    77  
    78  	// Slot root.
    79  	slotRoot := htrutils.Uint64Root(uint64(state.Slot))
    80  	fieldRoots[2] = slotRoot[:]
    81  
    82  	// Fork data structure root.
    83  	forkHashTreeRoot, err := htrutils.ForkRoot(state.Fork)
    84  	if err != nil {
    85  		return nil, errors.Wrap(err, "could not compute fork merkleization")
    86  	}
    87  	fieldRoots[3] = forkHashTreeRoot[:]
    88  
    89  	// BeaconBlockHeader data structure root.
    90  	headerHashTreeRoot, err := stateutil.BlockHeaderRoot(state.LatestBlockHeader)
    91  	if err != nil {
    92  		return nil, errors.Wrap(err, "could not compute block header merkleization")
    93  	}
    94  	fieldRoots[4] = headerHashTreeRoot[:]
    95  
    96  	// BlockRoots array root.
    97  	blockRootsRoot, err := h.arraysRoot(state.BlockRoots, uint64(params.BeaconConfig().SlotsPerHistoricalRoot), "BlockRoots")
    98  	if err != nil {
    99  		return nil, errors.Wrap(err, "could not compute block roots merkleization")
   100  	}
   101  	fieldRoots[5] = blockRootsRoot[:]
   102  
   103  	// StateRoots array root.
   104  	stateRootsRoot, err := h.arraysRoot(state.StateRoots, uint64(params.BeaconConfig().SlotsPerHistoricalRoot), "StateRoots")
   105  	if err != nil {
   106  		return nil, errors.Wrap(err, "could not compute state roots merkleization")
   107  	}
   108  	fieldRoots[6] = stateRootsRoot[:]
   109  
   110  	// HistoricalRoots slice root.
   111  	historicalRootsRt, err := htrutils.HistoricalRootsRoot(state.HistoricalRoots)
   112  	if err != nil {
   113  		return nil, errors.Wrap(err, "could not compute historical roots merkleization")
   114  	}
   115  	fieldRoots[7] = historicalRootsRt[:]
   116  
   117  	// Eth1Data data structure root.
   118  	eth1HashTreeRoot, err := eth1Root(hasher, state.Eth1Data)
   119  	if err != nil {
   120  		return nil, errors.Wrap(err, "could not compute eth1data merkleization")
   121  	}
   122  	fieldRoots[8] = eth1HashTreeRoot[:]
   123  
   124  	// Eth1DataVotes slice root.
   125  	eth1VotesRoot, err := eth1DataVotesRoot(state.Eth1DataVotes)
   126  	if err != nil {
   127  		return nil, errors.Wrap(err, "could not compute eth1data votes merkleization")
   128  	}
   129  	fieldRoots[9] = eth1VotesRoot[:]
   130  
   131  	// Eth1DepositIndex root.
   132  	eth1DepositIndexBuf := make([]byte, 8)
   133  	binary.LittleEndian.PutUint64(eth1DepositIndexBuf, state.Eth1DepositIndex)
   134  	eth1DepositBuf := bytesutil.ToBytes32(eth1DepositIndexBuf)
   135  	fieldRoots[10] = eth1DepositBuf[:]
   136  
   137  	// Validators slice root.
   138  	validatorsRoot, err := h.validatorRegistryRoot(state.Validators)
   139  	if err != nil {
   140  		return nil, errors.Wrap(err, "could not compute validator registry merkleization")
   141  	}
   142  	fieldRoots[11] = validatorsRoot[:]
   143  
   144  	// Balances slice root.
   145  	balancesRoot, err := stateutil.Uint64ListRootWithRegistryLimit(state.Balances)
   146  	if err != nil {
   147  		return nil, errors.Wrap(err, "could not compute validator balances merkleization")
   148  	}
   149  	fieldRoots[12] = balancesRoot[:]
   150  
   151  	// RandaoMixes array root.
   152  	randaoRootsRoot, err := h.arraysRoot(state.RandaoMixes, uint64(params.BeaconConfig().EpochsPerHistoricalVector), "RandaoMixes")
   153  	if err != nil {
   154  		return nil, errors.Wrap(err, "could not compute randao roots merkleization")
   155  	}
   156  	fieldRoots[13] = randaoRootsRoot[:]
   157  
   158  	// Slashings array root.
   159  	slashingsRootsRoot, err := htrutils.SlashingsRoot(state.Slashings)
   160  	if err != nil {
   161  		return nil, errors.Wrap(err, "could not compute slashings merkleization")
   162  	}
   163  	fieldRoots[14] = slashingsRootsRoot[:]
   164  
   165  	// PreviousEpochAttestations slice root.
   166  	prevAttsRoot, err := h.epochAttestationsRoot(state.PreviousEpochAttestations)
   167  	if err != nil {
   168  		return nil, errors.Wrap(err, "could not compute previous epoch attestations merkleization")
   169  	}
   170  	fieldRoots[15] = prevAttsRoot[:]
   171  
   172  	// CurrentEpochAttestations slice root.
   173  	currAttsRoot, err := h.epochAttestationsRoot(state.CurrentEpochAttestations)
   174  	if err != nil {
   175  		return nil, errors.Wrap(err, "could not compute current epoch attestations merkleization")
   176  	}
   177  	fieldRoots[16] = currAttsRoot[:]
   178  
   179  	// JustificationBits root.
   180  	justifiedBitsRoot := bytesutil.ToBytes32(state.JustificationBits)
   181  	fieldRoots[17] = justifiedBitsRoot[:]
   182  
   183  	// PreviousJustifiedCheckpoint data structure root.
   184  	prevCheckRoot, err := htrutils.CheckpointRoot(hasher, state.PreviousJustifiedCheckpoint)
   185  	if err != nil {
   186  		return nil, errors.Wrap(err, "could not compute previous justified checkpoint merkleization")
   187  	}
   188  	fieldRoots[18] = prevCheckRoot[:]
   189  
   190  	// CurrentJustifiedCheckpoint data structure root.
   191  	currJustRoot, err := htrutils.CheckpointRoot(hasher, state.CurrentJustifiedCheckpoint)
   192  	if err != nil {
   193  		return nil, errors.Wrap(err, "could not compute current justified checkpoint merkleization")
   194  	}
   195  	fieldRoots[19] = currJustRoot[:]
   196  
   197  	// FinalizedCheckpoint data structure root.
   198  	finalRoot, err := htrutils.CheckpointRoot(hasher, state.FinalizedCheckpoint)
   199  	if err != nil {
   200  		return nil, errors.Wrap(err, "could not compute finalized checkpoint merkleization")
   201  	}
   202  	fieldRoots[20] = finalRoot[:]
   203  	return fieldRoots, nil
   204  }