2021-06-30 15:06:19 +00:00
|
|
|
package v1
|
2021-04-12 14:23:55 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
|
2021-05-26 18:33:46 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/shared/copyutil"
|
2021-05-26 16:19:54 +00:00
|
|
|
|
2021-04-12 14:23:55 +00:00
|
|
|
"github.com/pkg/errors"
|
2021-07-21 21:34:07 +00:00
|
|
|
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
2021-04-12 14:23:55 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// InnerStateUnsafe returns the pointer value of the underlying
|
|
|
|
// beacon state proto object, bypassing immutability. Use with care.
|
|
|
|
func (b *BeaconState) InnerStateUnsafe() interface{} {
|
|
|
|
if b == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return b.state
|
|
|
|
}
|
|
|
|
|
|
|
|
// CloneInnerState the beacon state into a protobuf for usage.
|
|
|
|
func (b *BeaconState) CloneInnerState() interface{} {
|
|
|
|
if b == nil || b.state == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
b.lock.RLock()
|
|
|
|
defer b.lock.RUnlock()
|
2021-07-29 21:45:17 +00:00
|
|
|
return ðpb.BeaconState{
|
2021-04-12 14:23:55 +00:00
|
|
|
GenesisTime: b.genesisTime(),
|
|
|
|
GenesisValidatorsRoot: b.genesisValidatorRoot(),
|
|
|
|
Slot: b.slot(),
|
|
|
|
Fork: b.fork(),
|
|
|
|
LatestBlockHeader: b.latestBlockHeader(),
|
|
|
|
BlockRoots: b.blockRoots(),
|
|
|
|
StateRoots: b.stateRoots(),
|
|
|
|
HistoricalRoots: b.historicalRoots(),
|
|
|
|
Eth1Data: b.eth1Data(),
|
|
|
|
Eth1DataVotes: b.eth1DataVotes(),
|
|
|
|
Eth1DepositIndex: b.eth1DepositIndex(),
|
|
|
|
Validators: b.validators(),
|
|
|
|
Balances: b.balances(),
|
|
|
|
RandaoMixes: b.randaoMixes(),
|
|
|
|
Slashings: b.slashings(),
|
|
|
|
PreviousEpochAttestations: b.previousEpochAttestations(),
|
|
|
|
CurrentEpochAttestations: b.currentEpochAttestations(),
|
|
|
|
JustificationBits: b.justificationBits(),
|
|
|
|
PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint(),
|
|
|
|
CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint(),
|
|
|
|
FinalizedCheckpoint: b.finalizedCheckpoint(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// hasInnerState detects if the internal reference to the state data structure
|
|
|
|
// is populated correctly. Returns false if nil.
|
|
|
|
func (b *BeaconState) hasInnerState() bool {
|
|
|
|
return b != nil && b.state != nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// StateRoots kept track of in the beacon state.
|
|
|
|
func (b *BeaconState) StateRoots() [][]byte {
|
|
|
|
if !b.hasInnerState() {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
if b.state.StateRoots == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
b.lock.RLock()
|
|
|
|
defer b.lock.RUnlock()
|
|
|
|
|
|
|
|
return b.stateRoots()
|
|
|
|
}
|
|
|
|
|
|
|
|
// StateRoots kept track of in the beacon state.
|
|
|
|
// This assumes that a lock is already held on BeaconState.
|
|
|
|
func (b *BeaconState) stateRoots() [][]byte {
|
|
|
|
if !b.hasInnerState() {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return b.safeCopy2DByteSlice(b.state.StateRoots)
|
|
|
|
}
|
|
|
|
|
|
|
|
// StateRootAtIndex retrieves a specific state root based on an
|
|
|
|
// input index value.
|
|
|
|
func (b *BeaconState) StateRootAtIndex(idx uint64) ([]byte, error) {
|
|
|
|
if !b.hasInnerState() {
|
|
|
|
return nil, ErrNilInnerState
|
|
|
|
}
|
|
|
|
if b.state.StateRoots == nil {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
b.lock.RLock()
|
|
|
|
defer b.lock.RUnlock()
|
|
|
|
|
|
|
|
return b.stateRootAtIndex(idx)
|
|
|
|
}
|
|
|
|
|
|
|
|
// stateRootAtIndex retrieves a specific state root based on an
|
|
|
|
// input index value.
|
|
|
|
// This assumes that a lock is already held on BeaconState.
|
|
|
|
func (b *BeaconState) stateRootAtIndex(idx uint64) ([]byte, error) {
|
|
|
|
if !b.hasInnerState() {
|
|
|
|
return nil, ErrNilInnerState
|
|
|
|
}
|
|
|
|
return b.safeCopyBytesAtIndex(b.state.StateRoots, idx)
|
|
|
|
}
|
|
|
|
|
|
|
|
// MarshalSSZ marshals the underlying beacon state to bytes.
|
|
|
|
func (b *BeaconState) MarshalSSZ() ([]byte, error) {
|
|
|
|
if !b.hasInnerState() {
|
|
|
|
return nil, errors.New("nil beacon state")
|
|
|
|
}
|
|
|
|
return b.state.MarshalSSZ()
|
|
|
|
}
|
|
|
|
|
|
|
|
// ProtobufBeaconState transforms an input into beacon state in the form of protobuf.
|
|
|
|
// Error is returned if the input is not type protobuf beacon state.
|
2021-07-29 21:45:17 +00:00
|
|
|
func ProtobufBeaconState(s interface{}) (*ethpb.BeaconState, error) {
|
|
|
|
pbState, ok := s.(*ethpb.BeaconState)
|
2021-04-12 14:23:55 +00:00
|
|
|
if !ok {
|
2021-07-29 21:45:17 +00:00
|
|
|
return nil, errors.New("input is not type ethpb.BeaconState")
|
2021-04-12 14:23:55 +00:00
|
|
|
}
|
|
|
|
return pbState, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *BeaconState) safeCopy2DByteSlice(input [][]byte) [][]byte {
|
|
|
|
if input == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
dst := make([][]byte, len(input))
|
|
|
|
for i, r := range input {
|
|
|
|
tmp := make([]byte, len(r))
|
|
|
|
copy(tmp, r)
|
|
|
|
dst[i] = tmp
|
|
|
|
}
|
|
|
|
return dst
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *BeaconState) safeCopyBytesAtIndex(input [][]byte, idx uint64) ([]byte, error) {
|
|
|
|
if input == nil {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if uint64(len(input)) <= idx {
|
|
|
|
return nil, fmt.Errorf("index %d out of range", idx)
|
|
|
|
}
|
|
|
|
root := make([]byte, 32)
|
|
|
|
copy(root, input[idx])
|
|
|
|
return root, nil
|
|
|
|
}
|
|
|
|
|
2021-07-29 21:45:17 +00:00
|
|
|
func (b *BeaconState) safeCopyPendingAttestationSlice(input []*ethpb.PendingAttestation) []*ethpb.PendingAttestation {
|
2021-04-12 14:23:55 +00:00
|
|
|
if input == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-07-29 21:45:17 +00:00
|
|
|
res := make([]*ethpb.PendingAttestation, len(input))
|
2021-04-12 14:23:55 +00:00
|
|
|
for i := 0; i < len(res); i++ {
|
2021-05-26 18:33:46 +00:00
|
|
|
res[i] = copyutil.CopyPendingAttestation(input[i])
|
2021-04-12 14:23:55 +00:00
|
|
|
}
|
|
|
|
return res
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *BeaconState) safeCopyCheckpoint(input *ethpb.Checkpoint) *ethpb.Checkpoint {
|
|
|
|
if input == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-05-26 18:33:46 +00:00
|
|
|
return copyutil.CopyCheckpoint(input)
|
2021-04-12 14:23:55 +00:00
|
|
|
}
|