mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2025-01-06 01:32:18 +00:00
abe679e90e
* begin state service * begin on the state trie idea * created beacon state structure * add in the full clone getter * return by value instead * add all setters * new state setters are being completed * arrays roots exposed * close to finishing all these headerssss * functionality complete * added in proto benchmark test * test for compatibility * add test for compat * comments fixed * add clone * add clone * remove underlying copies * make it immutable * integrate it into chainservice * revert * wrap up comments for package * address all comments and godocs * address all comments * clone the pending attestation properly * properly clone remaining items * tests pass fixed bug * prevent nil pointer exceptions * fixed up some bugs in the clone comparisons Co-authored-by: Nishant Das <nish1993@hotmail.com> Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
354 lines
9.8 KiB
Go
354 lines
9.8 KiB
Go
package state
|
|
|
|
import (
|
|
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
|
"github.com/prysmaticlabs/go-bitfield"
|
|
pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
|
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
|
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
|
"github.com/prysmaticlabs/prysm/shared/params"
|
|
"github.com/prysmaticlabs/prysm/shared/stateutil"
|
|
)
|
|
|
|
type fieldIndex int
|
|
|
|
// Below we define a set of useful enum values for the field
|
|
// indices of the beacon state. For example, genesisTime is the
|
|
// 0th field of the beacon state. This is helpful when we are
|
|
// updating the Merkle branches up the trie representation
|
|
// of the beacon state.
|
|
const (
|
|
genesisTime fieldIndex = iota
|
|
slot
|
|
fork
|
|
latestBlockHeader
|
|
blockRoots
|
|
stateRoots
|
|
historicalRoots
|
|
eth1Data
|
|
eth1DataVotes
|
|
eth1DepositIndex
|
|
validators
|
|
balances
|
|
randaoMixes
|
|
slashings
|
|
previousEpochAttestations
|
|
currentEpochAttestations
|
|
justificationBits
|
|
previousJustifiedCheckpoint
|
|
currentJustifiedCheckpoint
|
|
finalizedCheckpoint
|
|
)
|
|
|
|
// SetGenesisTime for the beacon state.
|
|
func (b *BeaconState) SetGenesisTime(val uint64) error {
|
|
b.state.GenesisTime = val
|
|
root := stateutil.Uint64Root(val)
|
|
b.lock.Lock()
|
|
b.merkleLayers[0][genesisTime] = root[:]
|
|
b.recomputeRoot(int(genesisTime))
|
|
b.lock.Unlock()
|
|
return nil
|
|
}
|
|
|
|
// SetSlot for the beacon state.
|
|
func (b *BeaconState) SetSlot(val uint64) error {
|
|
b.state.Slot = val
|
|
root := stateutil.Uint64Root(val)
|
|
b.lock.Lock()
|
|
b.merkleLayers[0][slot] = root[:]
|
|
b.recomputeRoot(int(slot))
|
|
b.lock.Unlock()
|
|
return nil
|
|
}
|
|
|
|
// SetFork version for the beacon chain.
|
|
func (b *BeaconState) SetFork(val *pbp2p.Fork) error {
|
|
root, err := stateutil.ForkRoot(val)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
b.state.Fork = val
|
|
b.lock.Lock()
|
|
b.merkleLayers[0][fork] = root[:]
|
|
b.recomputeRoot(int(fork))
|
|
b.lock.Unlock()
|
|
return nil
|
|
}
|
|
|
|
// SetLatestBlockHeader in the beacon state.
|
|
func (b *BeaconState) SetLatestBlockHeader(val *ethpb.BeaconBlockHeader) error {
|
|
root, err := stateutil.BlockHeaderRoot(val)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
b.state.LatestBlockHeader = val
|
|
b.lock.Lock()
|
|
b.merkleLayers[0][latestBlockHeader] = root[:]
|
|
b.recomputeRoot(int(latestBlockHeader))
|
|
b.lock.Unlock()
|
|
return nil
|
|
}
|
|
|
|
// SetBlockRoots for the beacon state. This PR updates the entire
|
|
// list to a new value by overwriting the previous one.
|
|
func (b *BeaconState) SetBlockRoots(val [][]byte) error {
|
|
root, err := stateutil.RootsArrayHashTreeRoot(val, params.BeaconConfig().SlotsPerHistoricalRoot, "BlockRoots")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
b.state.BlockRoots = val
|
|
b.lock.Lock()
|
|
b.merkleLayers[0][blockRoots] = root[:]
|
|
b.recomputeRoot(int(blockRoots))
|
|
b.lock.Unlock()
|
|
return nil
|
|
}
|
|
|
|
// SetStateRoots for the beacon state. This PR updates the entire
|
|
// to a new value by overwriting the previous one.
|
|
func (b *BeaconState) SetStateRoots(val [][]byte) error {
|
|
root, err := stateutil.RootsArrayHashTreeRoot(val, params.BeaconConfig().SlotsPerHistoricalRoot, "StateRoots")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
b.state.StateRoots = val
|
|
b.lock.Lock()
|
|
b.merkleLayers[0][stateRoots] = root[:]
|
|
b.recomputeRoot(int(stateRoots))
|
|
b.lock.Unlock()
|
|
return nil
|
|
}
|
|
|
|
// SetHistoricalRoots for the beacon state. This PR updates the entire
|
|
// list to a new value by overwriting the previous one.
|
|
func (b *BeaconState) SetHistoricalRoots(val [][]byte) error {
|
|
root, err := stateutil.HistoricalRootsRoot(val)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
b.state.HistoricalRoots = val
|
|
b.lock.Lock()
|
|
b.merkleLayers[0][historicalRoots] = root[:]
|
|
b.recomputeRoot(int(historicalRoots))
|
|
b.lock.Unlock()
|
|
return nil
|
|
}
|
|
|
|
// SetEth1Data for the beacon state.
|
|
func (b *BeaconState) SetEth1Data(val *ethpb.Eth1Data) error {
|
|
root, err := stateutil.Eth1Root(val)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
b.state.Eth1Data = val
|
|
b.lock.Lock()
|
|
b.merkleLayers[0][eth1Data] = root[:]
|
|
b.recomputeRoot(int(eth1Data))
|
|
b.lock.Unlock()
|
|
return nil
|
|
}
|
|
|
|
// SetEth1DataVotes for the beacon state. This PR updates the entire
|
|
// list to a new value by overwriting the previous one.
|
|
func (b *BeaconState) SetEth1DataVotes(val []*ethpb.Eth1Data) error {
|
|
root, err := stateutil.Eth1DataVotesRoot(val)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
b.state.Eth1DataVotes = val
|
|
b.lock.Lock()
|
|
b.merkleLayers[0][eth1DataVotes] = root[:]
|
|
b.recomputeRoot(int(eth1DataVotes))
|
|
b.lock.Unlock()
|
|
return nil
|
|
}
|
|
|
|
// SetEth1DepositIndex for the beacon state.
|
|
func (b *BeaconState) SetEth1DepositIndex(val uint64) error {
|
|
b.state.Eth1DepositIndex = val
|
|
root := stateutil.Uint64Root(val)
|
|
b.lock.Lock()
|
|
b.merkleLayers[0][eth1DepositIndex] = root[:]
|
|
b.recomputeRoot(int(eth1DepositIndex))
|
|
b.lock.Unlock()
|
|
return nil
|
|
}
|
|
|
|
// SetValidators for the beacon state. This PR updates the entire
|
|
// to a new value by overwriting the previous one.
|
|
func (b *BeaconState) SetValidators(val []*ethpb.Validator) error {
|
|
root, err := stateutil.ValidatorRegistryRoot(val)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
b.state.Validators = val
|
|
b.lock.Lock()
|
|
b.merkleLayers[0][validators] = root[:]
|
|
b.recomputeRoot(int(validators))
|
|
b.lock.Unlock()
|
|
return nil
|
|
}
|
|
|
|
// SetBalances for the beacon state. This PR updates the entire
|
|
// list to a new value by overwriting the previous one.
|
|
func (b *BeaconState) SetBalances(val []uint64) error {
|
|
root, err := stateutil.ValidatorBalancesRoot(val)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
b.state.Balances = val
|
|
b.lock.Lock()
|
|
b.merkleLayers[0][balances] = root[:]
|
|
b.recomputeRoot(int(balances))
|
|
b.lock.Unlock()
|
|
return nil
|
|
}
|
|
|
|
// SetRandaoMixes for the beacon state. This PR updates the entire
|
|
// list to a new value by overwriting the previous one.
|
|
func (b *BeaconState) SetRandaoMixes(val [][]byte) error {
|
|
root, err := stateutil.RootsArrayHashTreeRoot(val, params.BeaconConfig().EpochsPerHistoricalVector, "RandaoMixes")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
b.state.RandaoMixes = val
|
|
b.lock.Lock()
|
|
b.merkleLayers[0][randaoMixes] = root[:]
|
|
b.recomputeRoot(int(randaoMixes))
|
|
b.lock.Unlock()
|
|
return nil
|
|
}
|
|
|
|
// SetSlashings for the beacon state. This PR updates the entire
|
|
// list to a new value by overwriting the previous one.
|
|
func (b *BeaconState) SetSlashings(val []uint64) error {
|
|
root, err := stateutil.SlashingsRoot(val)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
b.state.Slashings = val
|
|
b.lock.Lock()
|
|
b.merkleLayers[0][slashings] = root[:]
|
|
b.recomputeRoot(int(slashings))
|
|
b.lock.Unlock()
|
|
return nil
|
|
}
|
|
|
|
// SetPreviousEpochAttestations for the beacon state. This PR updates the entire
|
|
// list to a new value by overwriting the previous one.
|
|
func (b *BeaconState) SetPreviousEpochAttestations(val []*pbp2p.PendingAttestation) error {
|
|
root, err := stateutil.EpochAttestationsRoot(val)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
b.state.PreviousEpochAttestations = val
|
|
b.lock.Lock()
|
|
b.merkleLayers[0][previousEpochAttestations] = root[:]
|
|
b.recomputeRoot(int(previousEpochAttestations))
|
|
b.lock.Unlock()
|
|
return nil
|
|
}
|
|
|
|
// SetCurrentEpochAttestations for the beacon state. This PR updates the entire
|
|
// list to a new value by overwriting the previous one.
|
|
func (b *BeaconState) SetCurrentEpochAttestations(val []*pbp2p.PendingAttestation) error {
|
|
root, err := stateutil.EpochAttestationsRoot(val)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
b.state.CurrentEpochAttestations = val
|
|
b.lock.Lock()
|
|
b.merkleLayers[0][currentEpochAttestations] = root[:]
|
|
b.recomputeRoot(int(currentEpochAttestations))
|
|
b.lock.Unlock()
|
|
return nil
|
|
}
|
|
|
|
// SetJustificationBits for the beacon state.
|
|
func (b *BeaconState) SetJustificationBits(val bitfield.Bitvector4) error {
|
|
root := bytesutil.ToBytes32(b.state.JustificationBits)
|
|
b.state.JustificationBits = val
|
|
b.lock.Lock()
|
|
b.merkleLayers[0][justificationBits] = root[:]
|
|
b.recomputeRoot(int(justificationBits))
|
|
b.lock.Unlock()
|
|
return nil
|
|
}
|
|
|
|
// SetPreviousJustifiedCheckpoint for the beacon state.
|
|
func (b *BeaconState) SetPreviousJustifiedCheckpoint(val *ethpb.Checkpoint) error {
|
|
root, err := stateutil.CheckpointRoot(val)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
b.state.PreviousJustifiedCheckpoint = val
|
|
b.lock.Lock()
|
|
b.merkleLayers[0][previousJustifiedCheckpoint] = root[:]
|
|
b.recomputeRoot(int(previousJustifiedCheckpoint))
|
|
b.lock.Unlock()
|
|
return nil
|
|
}
|
|
|
|
// SetCurrentJustifiedCheckpoint for the beacon state.
|
|
func (b *BeaconState) SetCurrentJustifiedCheckpoint(val *ethpb.Checkpoint) error {
|
|
root, err := stateutil.CheckpointRoot(val)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
b.state.CurrentJustifiedCheckpoint = val
|
|
b.lock.Lock()
|
|
b.merkleLayers[0][currentJustifiedCheckpoint] = root[:]
|
|
b.recomputeRoot(int(currentJustifiedCheckpoint))
|
|
b.lock.Unlock()
|
|
return nil
|
|
}
|
|
|
|
// SetFinalizedCheckpoint for the beacon state.
|
|
func (b *BeaconState) SetFinalizedCheckpoint(val *ethpb.Checkpoint) error {
|
|
root, err := stateutil.CheckpointRoot(val)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
b.state.FinalizedCheckpoint = val
|
|
b.lock.Lock()
|
|
b.merkleLayers[0][finalizedCheckpoint] = root[:]
|
|
b.recomputeRoot(int(finalizedCheckpoint))
|
|
b.lock.Unlock()
|
|
return nil
|
|
}
|
|
|
|
// Recomputes the branch up the index in the Merkle trie representation
|
|
// of the beacon state. This method performs map reads and the caller MUST
|
|
// hold the lock before calling this method.
|
|
func (b *BeaconState) recomputeRoot(idx int) {
|
|
layers := b.merkleLayers
|
|
// The merkle tree structure looks as follows:
|
|
// [[r1, r2, r3, r4], [parent1, parent2], [root]]
|
|
// Using information about the index which changed, idx, we recompute
|
|
// only its branch up the tree.
|
|
currentIndex := idx
|
|
root := b.merkleLayers[0][idx]
|
|
for i := 0; i < len(layers)-1; i++ {
|
|
isLeft := currentIndex%2 == 0
|
|
neighborIdx := currentIndex ^ 1
|
|
|
|
neighbor := make([]byte, 32)
|
|
if layers[i] != nil && len(layers[i]) != 0 && neighborIdx < len(layers[i]) {
|
|
neighbor = layers[i][neighborIdx]
|
|
}
|
|
if isLeft {
|
|
parentHash := hashutil.Hash(append(root, neighbor...))
|
|
root = parentHash[:]
|
|
} else {
|
|
parentHash := hashutil.Hash(append(neighbor, root...))
|
|
root = parentHash[:]
|
|
}
|
|
parentIdx := currentIndex / 2
|
|
// Update the cached layers at the parent index.
|
|
layers[i+1][parentIdx] = root
|
|
currentIndex = parentIdx
|
|
}
|
|
b.merkleLayers = layers
|
|
}
|