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

     1  package v1
     2  
     3  import (
     4  	"github.com/pkg/errors"
     5  	types "github.com/prysmaticlabs/eth2-types"
     6  	"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
     7  	pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
     8  	"github.com/prysmaticlabs/prysm/shared/featureconfig"
     9  	"github.com/prysmaticlabs/prysm/shared/hashutil"
    10  	"github.com/prysmaticlabs/prysm/shared/htrutils"
    11  	"github.com/prysmaticlabs/prysm/shared/interfaces/version"
    12  	"github.com/prysmaticlabs/prysm/shared/params"
    13  )
    14  
    15  // GenesisTime of the beacon state as a uint64.
    16  func (b *BeaconState) GenesisTime() uint64 {
    17  	if !b.hasInnerState() {
    18  		return 0
    19  	}
    20  
    21  	b.lock.RLock()
    22  	defer b.lock.RUnlock()
    23  
    24  	return b.genesisTime()
    25  }
    26  
    27  // genesisTime of the beacon state as a uint64.
    28  // This assumes that a lock is already held on BeaconState.
    29  func (b *BeaconState) genesisTime() uint64 {
    30  	if !b.hasInnerState() {
    31  		return 0
    32  	}
    33  
    34  	return b.state.GenesisTime
    35  }
    36  
    37  // GenesisValidatorRoot of the beacon state.
    38  func (b *BeaconState) GenesisValidatorRoot() []byte {
    39  	if !b.hasInnerState() {
    40  		return nil
    41  	}
    42  	if b.state.GenesisValidatorsRoot == nil {
    43  		return params.BeaconConfig().ZeroHash[:]
    44  	}
    45  
    46  	b.lock.RLock()
    47  	defer b.lock.RUnlock()
    48  
    49  	return b.genesisValidatorRoot()
    50  }
    51  
    52  // genesisValidatorRoot of the beacon state.
    53  // This assumes that a lock is already held on BeaconState.
    54  func (b *BeaconState) genesisValidatorRoot() []byte {
    55  	if !b.hasInnerState() {
    56  		return nil
    57  	}
    58  	if b.state.GenesisValidatorsRoot == nil {
    59  		return params.BeaconConfig().ZeroHash[:]
    60  	}
    61  
    62  	root := make([]byte, 32)
    63  	copy(root, b.state.GenesisValidatorsRoot)
    64  	return root
    65  }
    66  
    67  // Version of the beacon state.
    68  func (b *BeaconState) Version() int {
    69  	return version.Phase0
    70  }
    71  
    72  // Slot of the current beacon chain state.
    73  func (b *BeaconState) Slot() types.Slot {
    74  	if !b.hasInnerState() {
    75  		return 0
    76  	}
    77  
    78  	b.lock.RLock()
    79  	defer b.lock.RUnlock()
    80  
    81  	return b.slot()
    82  }
    83  
    84  // slot of the current beacon chain state.
    85  // This assumes that a lock is already held on BeaconState.
    86  func (b *BeaconState) slot() types.Slot {
    87  	if !b.hasInnerState() {
    88  		return 0
    89  	}
    90  
    91  	return b.state.Slot
    92  }
    93  
    94  // Fork version of the beacon chain.
    95  func (b *BeaconState) Fork() *pbp2p.Fork {
    96  	if !b.hasInnerState() {
    97  		return nil
    98  	}
    99  	if b.state.Fork == nil {
   100  		return nil
   101  	}
   102  
   103  	b.lock.RLock()
   104  	defer b.lock.RUnlock()
   105  
   106  	return b.fork()
   107  }
   108  
   109  // fork version of the beacon chain.
   110  // This assumes that a lock is already held on BeaconState.
   111  func (b *BeaconState) fork() *pbp2p.Fork {
   112  	if !b.hasInnerState() {
   113  		return nil
   114  	}
   115  	if b.state.Fork == nil {
   116  		return nil
   117  	}
   118  
   119  	prevVersion := make([]byte, len(b.state.Fork.PreviousVersion))
   120  	copy(prevVersion, b.state.Fork.PreviousVersion)
   121  	currVersion := make([]byte, len(b.state.Fork.CurrentVersion))
   122  	copy(currVersion, b.state.Fork.CurrentVersion)
   123  	return &pbp2p.Fork{
   124  		PreviousVersion: prevVersion,
   125  		CurrentVersion:  currVersion,
   126  		Epoch:           b.state.Fork.Epoch,
   127  	}
   128  }
   129  
   130  // HistoricalRoots based on epochs stored in the beacon state.
   131  func (b *BeaconState) HistoricalRoots() [][]byte {
   132  	if !b.hasInnerState() {
   133  		return nil
   134  	}
   135  	if b.state.HistoricalRoots == nil {
   136  		return nil
   137  	}
   138  
   139  	b.lock.RLock()
   140  	defer b.lock.RUnlock()
   141  
   142  	return b.historicalRoots()
   143  }
   144  
   145  // historicalRoots based on epochs stored in the beacon state.
   146  // This assumes that a lock is already held on BeaconState.
   147  func (b *BeaconState) historicalRoots() [][]byte {
   148  	if !b.hasInnerState() {
   149  		return nil
   150  	}
   151  	return b.safeCopy2DByteSlice(b.state.HistoricalRoots)
   152  }
   153  
   154  // balancesLength returns the length of the balances slice.
   155  // This assumes that a lock is already held on BeaconState.
   156  func (b *BeaconState) balancesLength() int {
   157  	if !b.hasInnerState() {
   158  		return 0
   159  	}
   160  	if b.state.Balances == nil {
   161  		return 0
   162  	}
   163  
   164  	return len(b.state.Balances)
   165  }
   166  
   167  // RootsArrayHashTreeRoot computes the Merkle root of arrays of 32-byte hashes, such as [64][32]byte
   168  // according to the Simple Serialize specification of Ethereum.
   169  func RootsArrayHashTreeRoot(vals [][]byte, length uint64, fieldName string) ([32]byte, error) {
   170  	if featureconfig.Get().EnableSSZCache {
   171  		return cachedHasher.arraysRoot(vals, length, fieldName)
   172  	}
   173  	return nocachedHasher.arraysRoot(vals, length, fieldName)
   174  }
   175  
   176  func (h *stateRootHasher) arraysRoot(input [][]byte, length uint64, fieldName string) ([32]byte, error) {
   177  	lock.Lock()
   178  	defer lock.Unlock()
   179  	hashFunc := hashutil.CustomSHA256Hasher()
   180  	if _, ok := layersCache[fieldName]; !ok && h.rootsCache != nil {
   181  		depth := htrutils.Depth(length)
   182  		layersCache[fieldName] = make([][][32]byte, depth+1)
   183  	}
   184  
   185  	leaves := make([][32]byte, length)
   186  	for i, chunk := range input {
   187  		copy(leaves[i][:], chunk)
   188  	}
   189  	bytesProcessed := 0
   190  	changedIndices := make([]int, 0)
   191  	prevLeaves, ok := leavesCache[fieldName]
   192  	if len(prevLeaves) == 0 || h.rootsCache == nil {
   193  		prevLeaves = leaves
   194  	}
   195  
   196  	for i := 0; i < len(leaves); i++ {
   197  		// We check if any items changed since the roots were last recomputed.
   198  		notEqual := leaves[i] != prevLeaves[i]
   199  		if ok && h.rootsCache != nil && notEqual {
   200  			changedIndices = append(changedIndices, i)
   201  		}
   202  		bytesProcessed += 32
   203  	}
   204  	if len(changedIndices) > 0 && h.rootsCache != nil {
   205  		var rt [32]byte
   206  		var err error
   207  		// If indices did change since last computation, we only recompute
   208  		// the modified branches in the cached Merkle tree for this state field.
   209  		chunks := leaves
   210  
   211  		// We need to ensure we recompute indices of the Merkle tree which
   212  		// changed in-between calls to this function. This check adds an offset
   213  		// to the recomputed indices to ensure we do so evenly.
   214  		maxChangedIndex := changedIndices[len(changedIndices)-1]
   215  		if maxChangedIndex+2 == len(chunks) && maxChangedIndex%2 != 0 {
   216  			changedIndices = append(changedIndices, maxChangedIndex+1)
   217  		}
   218  		for i := 0; i < len(changedIndices); i++ {
   219  			rt, err = recomputeRoot(changedIndices[i], chunks, fieldName, hashFunc)
   220  			if err != nil {
   221  				return [32]byte{}, err
   222  			}
   223  		}
   224  		leavesCache[fieldName] = chunks
   225  		return rt, nil
   226  	}
   227  
   228  	res := h.merkleizeWithCache(leaves, length, fieldName, hashFunc)
   229  	if h.rootsCache != nil {
   230  		leavesCache[fieldName] = leaves
   231  	}
   232  	return res, nil
   233  }
   234  
   235  func recomputeRoot(idx int, chunks [][32]byte, fieldName string, hasher func([]byte) [32]byte) ([32]byte, error) {
   236  	items, ok := layersCache[fieldName]
   237  	if !ok {
   238  		return [32]byte{}, errors.New("could not recompute root as there was no cache found")
   239  	}
   240  	if items == nil {
   241  		return [32]byte{}, errors.New("could not recompute root as there were no items found in the layers cache")
   242  	}
   243  	layers := items
   244  	root := chunks[idx]
   245  	layers[0] = chunks
   246  	// The merkle tree structure looks as follows:
   247  	// [[r1, r2, r3, r4], [parent1, parent2], [root]]
   248  	// Using information about the index which changed, idx, we recompute
   249  	// only its branch up the tree.
   250  	currentIndex := idx
   251  	for i := 0; i < len(layers)-1; i++ {
   252  		isLeft := currentIndex%2 == 0
   253  		neighborIdx := currentIndex ^ 1
   254  
   255  		neighbor := [32]byte{}
   256  		if layers[i] != nil && len(layers[i]) != 0 && neighborIdx < len(layers[i]) {
   257  			neighbor = layers[i][neighborIdx]
   258  		}
   259  		if isLeft {
   260  			parentHash := hasher(append(root[:], neighbor[:]...))
   261  			root = parentHash
   262  		} else {
   263  			parentHash := hasher(append(neighbor[:], root[:]...))
   264  			root = parentHash
   265  		}
   266  		parentIdx := currentIndex / 2
   267  		// Update the cached layers at the parent index.
   268  		if len(layers[i+1]) == 0 {
   269  			layers[i+1] = append(layers[i+1], root)
   270  		} else {
   271  			layers[i+1][parentIdx] = root
   272  		}
   273  		currentIndex = parentIdx
   274  	}
   275  	layersCache[fieldName] = layers
   276  	// If there is only a single leaf, we return it (the identity element).
   277  	if len(layers[0]) == 1 {
   278  		return layers[0][0], nil
   279  	}
   280  	return root, nil
   281  }
   282  
   283  func (h *stateRootHasher) merkleizeWithCache(leaves [][32]byte, length uint64,
   284  	fieldName string, hasher func([]byte) [32]byte) [32]byte {
   285  	if len(leaves) == 1 {
   286  		return leaves[0]
   287  	}
   288  	hashLayer := leaves
   289  	layers := make([][][32]byte, htrutils.Depth(length)+1)
   290  	if items, ok := layersCache[fieldName]; ok && h.rootsCache != nil {
   291  		if len(items[0]) == len(leaves) {
   292  			layers = items
   293  		}
   294  	}
   295  	layers[0] = hashLayer
   296  	layers, hashLayer = stateutil.MerkleizeTrieLeaves(layers, hashLayer, hasher)
   297  	root := hashLayer[0]
   298  	if h.rootsCache != nil {
   299  		layersCache[fieldName] = layers
   300  	}
   301  	return root
   302  }