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 }