Native beacon state: v1 (#10086)

This commit is contained in:
Radosław Kapka
2022-01-24 11:24:38 +01:00
committed by GitHub
parent b4fa626aff
commit 5cc201288d
47 changed files with 1662 additions and 1049 deletions

View File

@@ -5,6 +5,7 @@ go_library(
srcs = [ srcs = [
"block_roots.go", "block_roots.go",
"byte32.go", "byte32.go",
"historical_roots.go",
"randao_mixes.go", "randao_mixes.go",
"state_roots.go", "state_roots.go",
], ],
@@ -21,9 +22,13 @@ go_test(
srcs = [ srcs = [
"block_roots_test.go", "block_roots_test.go",
"byte32_test.go", "byte32_test.go",
"historical_roots_test.go",
"randao_mixes_test.go", "randao_mixes_test.go",
"state_roots_test.go", "state_roots_test.go",
], ],
embed = [":go_default_library"], embed = [":go_default_library"],
deps = ["//config/fieldparams:go_default_library"], deps = [
"//config/fieldparams:go_default_library",
"//testing/assert:go_default_library",
],
) )

View File

@@ -67,3 +67,16 @@ func (r *BlockRoots) MarshalSSZ() ([]byte, error) {
func (_ *BlockRoots) SizeSSZ() int { func (_ *BlockRoots) SizeSSZ() int {
return fieldparams.BlockRootsLength * 32 return fieldparams.BlockRootsLength * 32
} }
// Slice converts a customtypes.BlockRoots object into a 2D byte slice.
func (r *BlockRoots) Slice() [][]byte {
if r == nil {
return nil
}
bRoots := make([][]byte, len(r))
for i, root := range r {
tmp := root
bRoots[i] = tmp[:]
}
return bRoots
}

View File

@@ -5,6 +5,7 @@ import (
"testing" "testing"
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
"github.com/prysmaticlabs/prysm/testing/assert"
) )
func TestBlockRoots_Casting(t *testing.T) { func TestBlockRoots_Casting(t *testing.T) {
@@ -90,3 +91,15 @@ func TestBlockRoots_SizeSSZ(t *testing.T) {
t.Errorf("Wrong SSZ size. Expected %v vs actual %v", fieldparams.BlockRootsLength*32, d.SizeSSZ()) t.Errorf("Wrong SSZ size. Expected %v vs actual %v", fieldparams.BlockRootsLength*32, d.SizeSSZ())
} }
} }
func TestBlockRoots_Slice(t *testing.T) {
a, b, c := [32]byte{'a'}, [32]byte{'b'}, [32]byte{'c'}
roots := BlockRoots{}
roots[1] = a
roots[10] = b
roots[100] = c
slice := roots.Slice()
assert.DeepEqual(t, a[:], slice[1])
assert.DeepEqual(t, b[:], slice[10])
assert.DeepEqual(t, c[:], slice[100])
}

View File

@@ -0,0 +1,81 @@
package customtypes
import (
"fmt"
fssz "github.com/ferranbt/fastssz"
)
var _ fssz.HashRoot = (HistoricalRoots)([][32]byte{})
var _ fssz.Marshaler = (*HistoricalRoots)(nil)
var _ fssz.Unmarshaler = (*HistoricalRoots)(nil)
// Byte32 represents a 32 bytes HistoricalRoots object in Ethereum beacon chain consensus.
type HistoricalRoots [][32]byte
// HashTreeRoot returns calculated hash root.
func (r HistoricalRoots) HashTreeRoot() ([32]byte, error) {
return fssz.HashWithDefaultHasher(r)
}
// HashTreeRootWith hashes a HistoricalRoots object with a Hasher from the default HasherPool.
func (r HistoricalRoots) HashTreeRootWith(hh *fssz.Hasher) error {
index := hh.Index()
for _, sRoot := range r {
hh.Append(sRoot[:])
}
hh.Merkleize(index)
return nil
}
// UnmarshalSSZ deserializes the provided bytes buffer into the HistoricalRoots object.
func (r *HistoricalRoots) UnmarshalSSZ(buf []byte) error {
if len(buf) != r.SizeSSZ() {
return fmt.Errorf("expected buffer of length %d received %d", r.SizeSSZ(), len(buf))
}
mixes := make([][32]byte, len(buf)/32)
for i := range mixes {
copy(mixes[i][:], buf[i*32:(i+1)*32])
}
*r = mixes
return nil
}
// MarshalSSZTo marshals HistoricalRoots with the provided byte slice.
func (r *HistoricalRoots) MarshalSSZTo(dst []byte) ([]byte, error) {
marshalled, err := r.MarshalSSZ()
if err != nil {
return nil, err
}
return append(dst, marshalled...), nil
}
// MarshalSSZ marshals HistoricalRoots into a serialized object.
func (r *HistoricalRoots) MarshalSSZ() ([]byte, error) {
marshalled := make([]byte, len(*r)*32)
for i, r32 := range *r {
for j, rr := range r32 {
marshalled[i*32+j] = rr
}
}
return marshalled, nil
}
// SizeSSZ returns the size of the serialized object.
func (r *HistoricalRoots) SizeSSZ() int {
return len(*r) * 32
}
// Slice converts a customtypes.HistoricalRoots object into a 2D byte slice.
func (r *HistoricalRoots) Slice() [][]byte {
if r == nil {
return nil
}
hRoots := make([][]byte, len(*r))
for i, root := range *r {
tmp := root
hRoots[i] = tmp[:]
}
return hRoots
}

View File

@@ -0,0 +1,102 @@
package customtypes
import (
"reflect"
"testing"
"github.com/prysmaticlabs/prysm/testing/assert"
)
func TestHistoricalRoots_Casting(t *testing.T) {
b := make([][32]byte, 4)
d := HistoricalRoots(b)
if !reflect.DeepEqual([][32]byte(d), b) {
t.Errorf("Unequal: %v = %v", d, b)
}
}
func TestHistoricalRoots_UnmarshalSSZ(t *testing.T) {
t.Run("Ok", func(t *testing.T) {
d := HistoricalRoots(make([][32]byte, 2))
b := make([][32]byte, 2)
b[0] = [32]byte{'f', 'o', 'o'}
b[1] = [32]byte{'b', 'a', 'r'}
bb := make([]byte, 2*32)
for i, elem32 := range b {
for j, elem := range elem32 {
bb[i*32+j] = elem
}
}
err := d.UnmarshalSSZ(bb)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
if !reflect.DeepEqual(b, [][32]byte(d)) {
t.Errorf("Unequal: %v = %v", b, [][32]byte(d))
}
})
t.Run("Wrong slice length", func(t *testing.T) {
d := HistoricalRoots(make([][32]byte, 2))
b := make([][16]byte, 2)
b[0] = [16]byte{'f', 'o', 'o'}
b[1] = [16]byte{'b', 'a', 'r'}
bb := make([]byte, 2*16)
for i, elem16 := range b {
for j, elem := range elem16 {
bb[i*16+j] = elem
}
}
err := d.UnmarshalSSZ(bb)
if err == nil {
t.Error("Expected error")
}
})
}
func TestHistoricalRoots_MarshalSSZTo(t *testing.T) {
d := HistoricalRoots(make([][32]byte, 1))
d[0] = [32]byte{'f', 'o', 'o'}
dst := []byte("bar")
b, err := d.MarshalSSZTo(dst)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
expected := []byte{'b', 'a', 'r', 'f', 'o', 'o'}
actual := []byte{b[0], b[1], b[2], b[3], b[4], b[5]}
if !reflect.DeepEqual(expected, actual) {
t.Errorf("Unequal: %v = %v", expected, actual)
}
}
func TestHistoricalRoots_MarshalSSZ(t *testing.T) {
d := HistoricalRoots(make([][32]byte, 2))
d[0] = [32]byte{'f', 'o', 'o'}
d[1] = [32]byte{'b', 'a', 'r'}
b, err := d.MarshalSSZ()
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
if !reflect.DeepEqual(d[0][:], b[0:32]) {
t.Errorf("Unequal: %v = %v", d[0], b[0:32])
}
if !reflect.DeepEqual(d[1][:], b[32:64]) {
t.Errorf("Unequal: %v = %v", d[0], b[32:64])
}
}
func TestHistoricalRoots_SizeSSZ(t *testing.T) {
d := HistoricalRoots(make([][32]byte, 2))
if d.SizeSSZ() != 2*32 {
t.Errorf("Wrong SSZ size. Expected %v vs actual %v", 2*32, d.SizeSSZ())
}
}
func TestHistoricalRoots_Slice(t *testing.T) {
a, b, c := [32]byte{'a'}, [32]byte{'b'}, [32]byte{'c'}
roots := HistoricalRoots{a, b, c}
slice := roots.Slice()
assert.DeepEqual(t, a[:], slice[0])
assert.DeepEqual(t, b[:], slice[1])
assert.DeepEqual(t, c[:], slice[2])
}

View File

@@ -11,7 +11,7 @@ var _ fssz.HashRoot = (RandaoMixes)([fieldparams.RandaoMixesLength][32]byte{})
var _ fssz.Marshaler = (*RandaoMixes)(nil) var _ fssz.Marshaler = (*RandaoMixes)(nil)
var _ fssz.Unmarshaler = (*RandaoMixes)(nil) var _ fssz.Unmarshaler = (*RandaoMixes)(nil)
// Byte32 represents a 32 bytes RandaoMixes object in Ethereum beacon chain consensus. // RandaoMixes represents RANDAO mixes of the beacon state.
type RandaoMixes [fieldparams.RandaoMixesLength][32]byte type RandaoMixes [fieldparams.RandaoMixesLength][32]byte
// HashTreeRoot returns calculated hash root. // HashTreeRoot returns calculated hash root.
@@ -68,63 +68,15 @@ func (_ *RandaoMixes) SizeSSZ() int {
return fieldparams.RandaoMixesLength * 32 return fieldparams.RandaoMixesLength * 32
} }
var _ fssz.HashRoot = (HistoricalRoots)([][32]byte{}) // Slice converts a customtypes.RandaoMixes object into a 2D byte slice.
var _ fssz.Marshaler = (*HistoricalRoots)(nil) func (r *RandaoMixes) Slice() [][]byte {
var _ fssz.Unmarshaler = (*HistoricalRoots)(nil) if r == nil {
return nil
// Byte32 represents a 32 bytes HistoricalRoots object in Ethereum beacon chain consensus.
type HistoricalRoots [][32]byte
// HashTreeRoot returns calculated hash root.
func (r HistoricalRoots) HashTreeRoot() ([32]byte, error) {
return fssz.HashWithDefaultHasher(r)
}
// HashTreeRootWith hashes a HistoricalRoots object with a Hasher from the default HasherPool.
func (r HistoricalRoots) HashTreeRootWith(hh *fssz.Hasher) error {
index := hh.Index()
for _, sRoot := range r {
hh.Append(sRoot[:])
} }
hh.Merkleize(index) mixes := make([][]byte, len(r))
return nil for i, root := range r {
} tmp := root
mixes[i] = tmp[:]
// UnmarshalSSZ deserializes the provided bytes buffer into the HistoricalRoots object.
func (r *HistoricalRoots) UnmarshalSSZ(buf []byte) error {
if len(buf) != r.SizeSSZ() {
return fmt.Errorf("expected buffer of length %d received %d", r.SizeSSZ(), len(buf))
} }
return mixes
mixes := make([][32]byte, len(buf)/32)
for i := range mixes {
copy(mixes[i][:], buf[i*32:(i+1)*32])
}
*r = mixes
return nil
}
// MarshalSSZTo marshals HistoricalRoots with the provided byte slice.
func (r *HistoricalRoots) MarshalSSZTo(dst []byte) ([]byte, error) {
marshalled, err := r.MarshalSSZ()
if err != nil {
return nil, err
}
return append(dst, marshalled...), nil
}
// MarshalSSZ marshals HistoricalRoots into a serialized object.
func (r *HistoricalRoots) MarshalSSZ() ([]byte, error) {
marshalled := make([]byte, len(*r)*32)
for i, r32 := range *r {
for j, rr := range r32 {
marshalled[i*32+j] = rr
}
}
return marshalled, nil
}
// SizeSSZ returns the size of the serialized object.
func (r *HistoricalRoots) SizeSSZ() int {
return len(*r) * 32
} }

View File

@@ -5,6 +5,7 @@ import (
"testing" "testing"
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
"github.com/prysmaticlabs/prysm/testing/assert"
) )
func TestRandaoMixes_Casting(t *testing.T) { func TestRandaoMixes_Casting(t *testing.T) {
@@ -91,87 +92,14 @@ func TestRandaoMixes_SizeSSZ(t *testing.T) {
} }
} }
func TestHistoricalRoots_Casting(t *testing.T) { func TestRandaoMixes_Slice(t *testing.T) {
b := make([][32]byte, 4) a, b, c := [32]byte{'a'}, [32]byte{'b'}, [32]byte{'c'}
d := HistoricalRoots(b) roots := RandaoMixes{}
if !reflect.DeepEqual([][32]byte(d), b) { roots[1] = a
t.Errorf("Unequal: %v = %v", d, b) roots[10] = b
} roots[100] = c
} slice := roots.Slice()
assert.DeepEqual(t, a[:], slice[1])
func TestHistoricalRoots_UnmarshalSSZ(t *testing.T) { assert.DeepEqual(t, b[:], slice[10])
t.Run("Ok", func(t *testing.T) { assert.DeepEqual(t, c[:], slice[100])
d := HistoricalRoots(make([][32]byte, 2))
b := make([][32]byte, 2)
b[0] = [32]byte{'f', 'o', 'o'}
b[1] = [32]byte{'b', 'a', 'r'}
bb := make([]byte, 2*32)
for i, elem32 := range b {
for j, elem := range elem32 {
bb[i*32+j] = elem
}
}
err := d.UnmarshalSSZ(bb)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
if !reflect.DeepEqual(b, [][32]byte(d)) {
t.Errorf("Unequal: %v = %v", b, [][32]byte(d))
}
})
t.Run("Wrong slice length", func(t *testing.T) {
d := HistoricalRoots(make([][32]byte, 2))
b := make([][16]byte, 2)
b[0] = [16]byte{'f', 'o', 'o'}
b[1] = [16]byte{'b', 'a', 'r'}
bb := make([]byte, 2*16)
for i, elem16 := range b {
for j, elem := range elem16 {
bb[i*16+j] = elem
}
}
err := d.UnmarshalSSZ(bb)
if err == nil {
t.Error("Expected error")
}
})
}
func TestHistoricalRoots_MarshalSSZTo(t *testing.T) {
d := HistoricalRoots(make([][32]byte, 1))
d[0] = [32]byte{'f', 'o', 'o'}
dst := []byte("bar")
b, err := d.MarshalSSZTo(dst)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
expected := []byte{'b', 'a', 'r', 'f', 'o', 'o'}
actual := []byte{b[0], b[1], b[2], b[3], b[4], b[5]}
if !reflect.DeepEqual(expected, actual) {
t.Errorf("Unequal: %v = %v", expected, actual)
}
}
func TestHistoricalRoots_MarshalSSZ(t *testing.T) {
d := HistoricalRoots(make([][32]byte, 2))
d[0] = [32]byte{'f', 'o', 'o'}
d[1] = [32]byte{'b', 'a', 'r'}
b, err := d.MarshalSSZ()
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
if !reflect.DeepEqual(d[0][:], b[0:32]) {
t.Errorf("Unequal: %v = %v", d[0], b[0:32])
}
if !reflect.DeepEqual(d[1][:], b[32:64]) {
t.Errorf("Unequal: %v = %v", d[0], b[32:64])
}
}
func TestHistoricalRoots_SizeSSZ(t *testing.T) {
d := HistoricalRoots(make([][32]byte, 2))
if d.SizeSSZ() != 2*32 {
t.Errorf("Wrong SSZ size. Expected %v vs actual %v", 2*32, d.SizeSSZ())
}
} }

View File

@@ -67,3 +67,16 @@ func (r *StateRoots) MarshalSSZ() ([]byte, error) {
func (_ *StateRoots) SizeSSZ() int { func (_ *StateRoots) SizeSSZ() int {
return fieldparams.StateRootsLength * 32 return fieldparams.StateRootsLength * 32
} }
// Slice converts a customtypes.StateRoots object into a 2D byte slice.
func (r *StateRoots) Slice() [][]byte {
if r == nil {
return nil
}
sRoots := make([][]byte, len(r))
for i, root := range r {
tmp := root
sRoots[i] = tmp[:]
}
return sRoots
}

View File

@@ -5,6 +5,7 @@ import (
"testing" "testing"
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams" fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
"github.com/prysmaticlabs/prysm/testing/assert"
) )
func TestStateRoots_Casting(t *testing.T) { func TestStateRoots_Casting(t *testing.T) {
@@ -90,3 +91,15 @@ func TestStateRoots_SizeSSZ(t *testing.T) {
t.Errorf("Wrong SSZ size. Expected %v vs actual %v", fieldparams.StateRootsLength*32, d.SizeSSZ()) t.Errorf("Wrong SSZ size. Expected %v vs actual %v", fieldparams.StateRootsLength*32, d.SizeSSZ())
} }
} }
func TestStateRoots_Slice(t *testing.T) {
a, b, c := [32]byte{'a'}, [32]byte{'b'}, [32]byte{'c'}
roots := StateRoots{}
roots[1] = a
roots[10] = b
roots[100] = c
slice := roots.Slice()
assert.DeepEqual(t, a[:], slice[1])
assert.DeepEqual(t, b[:], slice[10])
assert.DeepEqual(t, c[:], slice[100])
}

View File

@@ -1,4 +1,6 @@
load("@prysm//tools/go:def.bzl", "go_library", "go_test") load("@prysm//tools/go:def.bzl", "go_library", "go_test")
load("//proto:ssz_proto_library.bzl", "ssz_proto_files")
load("//tools:ssz.bzl", "SSZ_DEPS", "ssz_gen_marshal")
go_library( go_library(
name = "go_default_library", name = "go_default_library",
@@ -27,7 +29,11 @@ go_library(
"types.go", "types.go",
"unsupported_getters.go", "unsupported_getters.go",
"unsupported_setters.go", "unsupported_setters.go",
], ":ssz_generated_files", # keep
] + select({
"//config:mainnet": ["beacon_state_mainnet.go"],
"//config:minimal": ["beacon_state_minimal.go"],
}),
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/v1", importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/v1",
visibility = [ visibility = [
"//beacon-chain:__subpackages__", "//beacon-chain:__subpackages__",
@@ -46,6 +52,7 @@ go_library(
], ],
deps = [ deps = [
"//beacon-chain/state:go_default_library", "//beacon-chain/state:go_default_library",
"//beacon-chain/state/state-native/custom-types:go_default_library",
"//beacon-chain/state/state-native/fieldtrie:go_default_library", "//beacon-chain/state/state-native/fieldtrie:go_default_library",
"//beacon-chain/state/stateutil:go_default_library", "//beacon-chain/state/stateutil:go_default_library",
"//beacon-chain/state/types:go_default_library", "//beacon-chain/state/types:go_default_library",
@@ -58,6 +65,7 @@ go_library(
"//encoding/ssz:go_default_library", "//encoding/ssz:go_default_library",
"//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1:go_default_library",
"//runtime/version:go_default_library", "//runtime/version:go_default_library",
"@com_github_ferranbt_fastssz//:go_default_library",
"@com_github_pkg_errors//:go_default_library", "@com_github_pkg_errors//:go_default_library",
"@com_github_prysmaticlabs_eth2_types//:go_default_library", "@com_github_prysmaticlabs_eth2_types//:go_default_library",
"@com_github_prysmaticlabs_go_bitfield//:go_default_library", "@com_github_prysmaticlabs_go_bitfield//:go_default_library",
@@ -81,7 +89,10 @@ go_test(
"state_test.go", "state_test.go",
"state_trie_test.go", "state_trie_test.go",
"types_test.go", "types_test.go",
], ] + select({
"//config:mainnet": ["beacon_state_mainnet_test.go"],
"//config:minimal": ["beacon_state_minimal_test.go"],
}),
embed = [":go_default_library"], embed = [":go_default_library"],
deps = [ deps = [
"//beacon-chain/state:go_default_library", "//beacon-chain/state:go_default_library",
@@ -103,3 +114,20 @@ go_test(
"@org_golang_google_protobuf//proto:go_default_library", "@org_golang_google_protobuf//proto:go_default_library",
], ],
) )
ssz_gen_marshal(
name = "ssz_generated_files",
srcs = select({
"//config:mainnet": ["beacon_state_mainnet.go"],
"//config:minimal": ["beacon_state_minimal.go"],
}),
includes = [
"//beacon-chain/state/state-native/custom-types:go_default_library",
"//config/fieldparams:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
],
objs = [
"BeaconState[no-htr]",
],
)

View File

@@ -0,0 +1,50 @@
// +build !minimal
package v1
import (
"sync"
eth2types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/go-bitfield"
customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types"
"github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/fieldtrie"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
"github.com/prysmaticlabs/prysm/beacon-chain/state/types"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
)
// BeaconState defines a struct containing utilities for the Ethereum Beacon Chain state, defining
// getters and setters for its respective values and helpful functions such as HashTreeRoot().
type BeaconState struct {
genesisTime uint64 `ssz-gen:"true"`
genesisValidatorsRoot customtypes.Byte32 `ssz-gen:"true" ssz-size:"32"`
slot eth2types.Slot `ssz-gen:"true"`
fork *ethpb.Fork `ssz-gen:"true"`
latestBlockHeader *ethpb.BeaconBlockHeader `ssz-gen:"true"`
blockRoots *customtypes.BlockRoots `ssz-gen:"true" ssz-size:"8192,32"`
stateRoots *customtypes.StateRoots `ssz-gen:"true" ssz-size:"8192,32"`
historicalRoots customtypes.HistoricalRoots `ssz-gen:"true" ssz-size:"?,32" ssz-max:"16777216"`
eth1Data *ethpb.Eth1Data `ssz-gen:"true"`
eth1DataVotes []*ethpb.Eth1Data `ssz-gen:"true" ssz-max:"2048"`
eth1DepositIndex uint64 `ssz-gen:"true"`
validators []*ethpb.Validator `ssz-gen:"true" ssz-max:"1099511627776"`
balances []uint64 `ssz-gen:"true" ssz-max:"1099511627776"`
randaoMixes *customtypes.RandaoMixes `ssz-gen:"true" ssz-size:"65536,32"`
slashings []uint64 `ssz-gen:"true" ssz-size:"8192"`
previousEpochAttestations []*ethpb.PendingAttestation `ssz-gen:"true" ssz-max:"4096"`
currentEpochAttestations []*ethpb.PendingAttestation `ssz-gen:"true" ssz-max:"4096"`
justificationBits bitfield.Bitvector4 `ssz-gen:"true" ssz-size:"1"`
previousJustifiedCheckpoint *ethpb.Checkpoint `ssz-gen:"true"`
currentJustifiedCheckpoint *ethpb.Checkpoint `ssz-gen:"true"`
finalizedCheckpoint *ethpb.Checkpoint `ssz-gen:"true"`
lock sync.RWMutex
dirtyFields map[types.FieldIndex]bool
dirtyIndices map[types.FieldIndex][]uint64
stateFieldLeaves map[types.FieldIndex]*fieldtrie.FieldTrie
rebuildTrie map[types.FieldIndex]bool
valMapHandler *stateutil.ValidatorMapHandler
merkleLayers [][][]byte
sharedFieldReferences map[types.FieldIndex]*stateutil.Reference
}

View File

@@ -0,0 +1,81 @@
// +build !minimal
package v1
import (
"reflect"
"strconv"
"testing"
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
"github.com/prysmaticlabs/prysm/testing/assert"
"github.com/prysmaticlabs/prysm/testing/require"
)
func TestMainnetSszValuesAgainstFieldParams(t *testing.T) {
// Casting needed to avoid lock copy analyzer issue.
bs := (interface{})(BeaconState{})
bsType := reflect.TypeOf(bs)
f, ok := bsType.FieldByName("genesisValidatorsRoot")
require.Equal(t, true, ok, "Required field not found")
v := f.Tag.Get("ssz-size")
assert.Equal(t, strconv.Itoa(fieldparams.RootLength), v)
f, ok = bsType.FieldByName("blockRoots")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-size")
assert.Equal(t, strconv.Itoa(fieldparams.BlockRootsLength)+","+strconv.Itoa(fieldparams.RootLength), v)
f, ok = bsType.FieldByName("stateRoots")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-size")
assert.Equal(t, strconv.Itoa(fieldparams.StateRootsLength)+","+strconv.Itoa(fieldparams.RootLength), v)
f, ok = bsType.FieldByName("historicalRoots")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-size")
assert.Equal(t, "?,"+strconv.Itoa(fieldparams.RootLength), v)
v = f.Tag.Get("ssz-max")
assert.Equal(t, strconv.Itoa(fieldparams.HistoricalRootsLength), v)
f, ok = bsType.FieldByName("eth1DataVotes")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-max")
assert.Equal(t, strconv.Itoa(fieldparams.Eth1DataVotesLength), v)
f, ok = bsType.FieldByName("validators")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-max")
assert.Equal(t, strconv.Itoa(fieldparams.ValidatorRegistryLimit), v)
f, ok = bsType.FieldByName("balances")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-max")
assert.Equal(t, strconv.Itoa(fieldparams.ValidatorRegistryLimit), v)
f, ok = bsType.FieldByName("randaoMixes")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-size")
assert.Equal(t, strconv.Itoa(fieldparams.RandaoMixesLength)+","+strconv.Itoa(fieldparams.RootLength), v)
f, ok = bsType.FieldByName("slashings")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-size")
assert.Equal(t, strconv.Itoa(fieldparams.SlashingsLength), v)
f, ok = bsType.FieldByName("previousEpochAttestations")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-max")
assert.Equal(t, strconv.Itoa(fieldparams.PreviousEpochAttestationsLength), v)
f, ok = bsType.FieldByName("currentEpochAttestations")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-max")
assert.Equal(t, strconv.Itoa(fieldparams.CurrentEpochAttestationsLength), v)
f, ok = bsType.FieldByName("justificationBits")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-size")
assert.Equal(t, "1", v)
}

View File

@@ -0,0 +1,50 @@
// +build minimal
package v1
import (
"sync"
eth2types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/go-bitfield"
customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types"
"github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/fieldtrie"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
"github.com/prysmaticlabs/prysm/beacon-chain/state/types"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
)
// BeaconState defines a struct containing utilities for the Ethereum Beacon Chain state, defining
// getters and setters for its respective values and helpful functions such as HashTreeRoot().
type BeaconState struct {
genesisTime uint64 `ssz-gen:"true"`
genesisValidatorsRoot customtypes.Byte32 `ssz-gen:"true" ssz-size:"32"`
slot eth2types.Slot `ssz-gen:"true"`
fork *ethpb.Fork `ssz-gen:"true"`
latestBlockHeader *ethpb.BeaconBlockHeader `ssz-gen:"true"`
blockRoots *customtypes.BlockRoots `ssz-gen:"true" ssz-size:"64,32"`
stateRoots *customtypes.StateRoots `ssz-gen:"true" ssz-size:"64,32"`
historicalRoots customtypes.HistoricalRoots `ssz-gen:"true" ssz-size:"?,32" ssz-max:"16777216"`
eth1Data *ethpb.Eth1Data `ssz-gen:"true"`
eth1DataVotes []*ethpb.Eth1Data `ssz-gen:"true" ssz-max:"32"`
eth1DepositIndex uint64 `ssz-gen:"true"`
validators []*ethpb.Validator `ssz-gen:"true" ssz-max:"1099511627776"`
balances []uint64 `ssz-gen:"true" ssz-max:"1099511627776"`
randaoMixes *customtypes.RandaoMixes `ssz-gen:"true" ssz-size:"64,32"`
slashings []uint64 `ssz-gen:"true" ssz-size:"64"`
previousEpochAttestations []*ethpb.PendingAttestation `ssz-gen:"true" ssz-max:"1024"`
currentEpochAttestations []*ethpb.PendingAttestation `ssz-gen:"true" ssz-max:"1024"`
justificationBits bitfield.Bitvector4 `ssz-gen:"true" ssz-size:"1"`
previousJustifiedCheckpoint *ethpb.Checkpoint `ssz-gen:"true"`
currentJustifiedCheckpoint *ethpb.Checkpoint `ssz-gen:"true"`
finalizedCheckpoint *ethpb.Checkpoint `ssz-gen:"true"`
lock sync.RWMutex
dirtyFields map[types.FieldIndex]bool
dirtyIndices map[types.FieldIndex][]uint64
stateFieldLeaves map[types.FieldIndex]*fieldtrie.FieldTrie
rebuildTrie map[types.FieldIndex]bool
valMapHandler *stateutil.ValidatorMapHandler
merkleLayers [][][]byte
sharedFieldReferences map[types.FieldIndex]*stateutil.Reference
}

View File

@@ -0,0 +1,81 @@
// +build minimal
package v1
import (
"reflect"
"strconv"
"testing"
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
"github.com/prysmaticlabs/prysm/testing/assert"
"github.com/prysmaticlabs/prysm/testing/require"
)
func TestMinimalSszValuesAgainstFieldParams(t *testing.T) {
// Casting needed to avoid lock copy analyzer issue.
bs := (interface{})(BeaconState{})
bsType := reflect.TypeOf(bs)
f, ok := bsType.FieldByName("genesisValidatorsRoot")
require.Equal(t, true, ok, "Required field not found")
v := f.Tag.Get("ssz-size")
assert.Equal(t, strconv.Itoa(fieldparams.RootLength), v)
f, ok = bsType.FieldByName("blockRoots")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-size")
assert.Equal(t, strconv.Itoa(fieldparams.BlockRootsLength)+","+strconv.Itoa(fieldparams.RootLength), v)
f, ok = bsType.FieldByName("stateRoots")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-size")
assert.Equal(t, strconv.Itoa(fieldparams.StateRootsLength)+","+strconv.Itoa(fieldparams.RootLength), v)
f, ok = bsType.FieldByName("historicalRoots")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-size")
assert.Equal(t, "?,"+strconv.Itoa(fieldparams.RootLength), v)
v = f.Tag.Get("ssz-max")
assert.Equal(t, strconv.Itoa(fieldparams.HistoricalRootsLength), v)
f, ok = bsType.FieldByName("eth1DataVotes")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-max")
assert.Equal(t, strconv.Itoa(fieldparams.Eth1DataVotesLength), v)
f, ok = bsType.FieldByName("validators")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-max")
assert.Equal(t, strconv.Itoa(fieldparams.ValidatorRegistryLimit), v)
f, ok = bsType.FieldByName("balances")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-max")
assert.Equal(t, strconv.Itoa(fieldparams.ValidatorRegistryLimit), v)
f, ok = bsType.FieldByName("randaoMixes")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-size")
assert.Equal(t, strconv.Itoa(fieldparams.RandaoMixesLength)+","+strconv.Itoa(fieldparams.RootLength), v)
f, ok = bsType.FieldByName("slashings")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-size")
assert.Equal(t, strconv.Itoa(fieldparams.SlashingsLength), v)
f, ok = bsType.FieldByName("previousEpochAttestations")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-max")
assert.Equal(t, strconv.Itoa(fieldparams.PreviousEpochAttestationsLength), v)
f, ok = bsType.FieldByName("currentEpochAttestations")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-max")
assert.Equal(t, strconv.Itoa(fieldparams.CurrentEpochAttestationsLength), v)
f, ok = bsType.FieldByName("justificationBits")
require.Equal(t, true, ok, "Required field not found")
v = f.Tag.Get("ssz-size")
assert.Equal(t, "1", v)
}

View File

@@ -0,0 +1,493 @@
// Code generated by fastssz. DO NOT EDIT.
// Hash: 6de36f732d72b5c4c0c967bc0edcc752b7afdd337e829486954eb6affda84da8
package v1
import (
ssz "github.com/ferranbt/fastssz"
eth2types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
)
// MarshalSSZ ssz marshals the BeaconState object
func (b *BeaconState) MarshalSSZ() ([]byte, error) {
return ssz.MarshalSSZ(b)
}
// MarshalSSZTo ssz marshals the BeaconState object to a target array
func (b *BeaconState) MarshalSSZTo(buf []byte) (dst []byte, err error) {
dst = buf
offset := int(2687377)
// Field (0) 'genesisTime'
dst = ssz.MarshalUint64(dst, b.genesisTime)
// Field (1) 'genesisValidatorsRoot'
dst = append(dst, b.genesisValidatorsRoot[:]...)
// Field (2) 'slot'
dst = ssz.MarshalUint64(dst, uint64(b.slot))
// Field (3) 'fork'
if b.fork == nil {
b.fork = new(ethpb.Fork)
}
if dst, err = b.fork.MarshalSSZTo(dst); err != nil {
return
}
// Field (4) 'latestBlockHeader'
if b.latestBlockHeader == nil {
b.latestBlockHeader = new(ethpb.BeaconBlockHeader)
}
if dst, err = b.latestBlockHeader.MarshalSSZTo(dst); err != nil {
return
}
// Field (5) 'blockRoots'
for ii := 0; ii < 8192; ii++ {
dst = append(dst, b.blockRoots[ii][:]...)
}
// Field (6) 'stateRoots'
for ii := 0; ii < 8192; ii++ {
dst = append(dst, b.stateRoots[ii][:]...)
}
// Offset (7) 'historicalRoots'
dst = ssz.WriteOffset(dst, offset)
offset += len(b.historicalRoots) * 32
// Field (8) 'eth1Data'
if b.eth1Data == nil {
b.eth1Data = new(ethpb.Eth1Data)
}
if dst, err = b.eth1Data.MarshalSSZTo(dst); err != nil {
return
}
// Offset (9) 'eth1DataVotes'
dst = ssz.WriteOffset(dst, offset)
offset += len(b.eth1DataVotes) * 72
// Field (10) 'eth1DepositIndex'
dst = ssz.MarshalUint64(dst, b.eth1DepositIndex)
// Offset (11) 'validators'
dst = ssz.WriteOffset(dst, offset)
offset += len(b.validators) * 121
// Offset (12) 'balances'
dst = ssz.WriteOffset(dst, offset)
offset += len(b.balances) * 8
// Field (13) 'randaoMixes'
for ii := 0; ii < 65536; ii++ {
dst = append(dst, b.randaoMixes[ii][:]...)
}
// Field (14) 'slashings'
if len(b.slashings) != 8192 {
err = ssz.ErrVectorLength
return
}
for ii := 0; ii < 8192; ii++ {
dst = ssz.MarshalUint64(dst, b.slashings[ii])
}
// Offset (15) 'previousEpochAttestations'
dst = ssz.WriteOffset(dst, offset)
for ii := 0; ii < len(b.previousEpochAttestations); ii++ {
offset += 4
offset += b.previousEpochAttestations[ii].SizeSSZ()
}
// Offset (16) 'currentEpochAttestations'
dst = ssz.WriteOffset(dst, offset)
for ii := 0; ii < len(b.currentEpochAttestations); ii++ {
offset += 4
offset += b.currentEpochAttestations[ii].SizeSSZ()
}
// Field (17) 'justificationBits'
if len(b.justificationBits) != 1 {
err = ssz.ErrBytesLength
return
}
dst = append(dst, b.justificationBits...)
// Field (18) 'previousJustifiedCheckpoint'
if b.previousJustifiedCheckpoint == nil {
b.previousJustifiedCheckpoint = new(ethpb.Checkpoint)
}
if dst, err = b.previousJustifiedCheckpoint.MarshalSSZTo(dst); err != nil {
return
}
// Field (19) 'currentJustifiedCheckpoint'
if b.currentJustifiedCheckpoint == nil {
b.currentJustifiedCheckpoint = new(ethpb.Checkpoint)
}
if dst, err = b.currentJustifiedCheckpoint.MarshalSSZTo(dst); err != nil {
return
}
// Field (20) 'finalizedCheckpoint'
if b.finalizedCheckpoint == nil {
b.finalizedCheckpoint = new(ethpb.Checkpoint)
}
if dst, err = b.finalizedCheckpoint.MarshalSSZTo(dst); err != nil {
return
}
// Field (7) 'historicalRoots'
if len(b.historicalRoots) > 16777216 {
err = ssz.ErrListTooBig
return
}
for ii := 0; ii < len(b.historicalRoots); ii++ {
dst = append(dst, b.historicalRoots[ii][:]...)
}
// Field (9) 'eth1DataVotes'
if len(b.eth1DataVotes) > 2048 {
err = ssz.ErrListTooBig
return
}
for ii := 0; ii < len(b.eth1DataVotes); ii++ {
if dst, err = b.eth1DataVotes[ii].MarshalSSZTo(dst); err != nil {
return
}
}
// Field (11) 'validators'
if len(b.validators) > 1099511627776 {
err = ssz.ErrListTooBig
return
}
for ii := 0; ii < len(b.validators); ii++ {
if dst, err = b.validators[ii].MarshalSSZTo(dst); err != nil {
return
}
}
// Field (12) 'balances'
if len(b.balances) > 1099511627776 {
err = ssz.ErrListTooBig
return
}
for ii := 0; ii < len(b.balances); ii++ {
dst = ssz.MarshalUint64(dst, b.balances[ii])
}
// Field (15) 'previousEpochAttestations'
if len(b.previousEpochAttestations) > 4096 {
err = ssz.ErrListTooBig
return
}
{
offset = 4 * len(b.previousEpochAttestations)
for ii := 0; ii < len(b.previousEpochAttestations); ii++ {
dst = ssz.WriteOffset(dst, offset)
offset += b.previousEpochAttestations[ii].SizeSSZ()
}
}
for ii := 0; ii < len(b.previousEpochAttestations); ii++ {
if dst, err = b.previousEpochAttestations[ii].MarshalSSZTo(dst); err != nil {
return
}
}
// Field (16) 'currentEpochAttestations'
if len(b.currentEpochAttestations) > 4096 {
err = ssz.ErrListTooBig
return
}
{
offset = 4 * len(b.currentEpochAttestations)
for ii := 0; ii < len(b.currentEpochAttestations); ii++ {
dst = ssz.WriteOffset(dst, offset)
offset += b.currentEpochAttestations[ii].SizeSSZ()
}
}
for ii := 0; ii < len(b.currentEpochAttestations); ii++ {
if dst, err = b.currentEpochAttestations[ii].MarshalSSZTo(dst); err != nil {
return
}
}
return
}
// UnmarshalSSZ ssz unmarshals the BeaconState object
func (b *BeaconState) UnmarshalSSZ(buf []byte) error {
var err error
size := uint64(len(buf))
if size < 2687377 {
return ssz.ErrSize
}
tail := buf
var o7, o9, o11, o12, o15, o16 uint64
// Field (0) 'genesisTime'
b.genesisTime = ssz.UnmarshallUint64(buf[0:8])
// Field (1) 'genesisValidatorsRoot'
copy(b.genesisValidatorsRoot[:], buf[8:40])
// Field (2) 'slot'
b.slot = eth2types.Slot(ssz.UnmarshallUint64(buf[40:48]))
// Field (3) 'fork'
if b.fork == nil {
b.fork = new(ethpb.Fork)
}
if err = b.fork.UnmarshalSSZ(buf[48:64]); err != nil {
return err
}
// Field (4) 'latestBlockHeader'
if b.latestBlockHeader == nil {
b.latestBlockHeader = new(ethpb.BeaconBlockHeader)
}
if err = b.latestBlockHeader.UnmarshalSSZ(buf[64:176]); err != nil {
return err
}
// Field (5) 'blockRoots'
for ii := 0; ii < 8192; ii++ {
copy(b.blockRoots[ii][:], buf[176:262320][ii*32:(ii+1)*32])
}
// Field (6) 'stateRoots'
for ii := 0; ii < 8192; ii++ {
copy(b.stateRoots[ii][:], buf[262320:524464][ii*32:(ii+1)*32])
}
// Offset (7) 'historicalRoots'
if o7 = ssz.ReadOffset(buf[524464:524468]); o7 > size {
return ssz.ErrOffset
}
if o7 < 2687377 {
return ssz.ErrInvalidVariableOffset
}
// Field (8) 'eth1Data'
if b.eth1Data == nil {
b.eth1Data = new(ethpb.Eth1Data)
}
if err = b.eth1Data.UnmarshalSSZ(buf[524468:524540]); err != nil {
return err
}
// Offset (9) 'eth1DataVotes'
if o9 = ssz.ReadOffset(buf[524540:524544]); o9 > size || o7 > o9 {
return ssz.ErrOffset
}
// Field (10) 'eth1DepositIndex'
b.eth1DepositIndex = ssz.UnmarshallUint64(buf[524544:524552])
// Offset (11) 'validators'
if o11 = ssz.ReadOffset(buf[524552:524556]); o11 > size || o9 > o11 {
return ssz.ErrOffset
}
// Offset (12) 'balances'
if o12 = ssz.ReadOffset(buf[524556:524560]); o12 > size || o11 > o12 {
return ssz.ErrOffset
}
// Field (13) 'randaoMixes'
for ii := 0; ii < 65536; ii++ {
copy(b.randaoMixes[ii][:], buf[524560:2621712][ii*32:(ii+1)*32])
}
// Field (14) 'slashings'
b.slashings = ssz.ExtendUint64(b.slashings, 8192)
for ii := 0; ii < 8192; ii++ {
b.slashings[ii] = ssz.UnmarshallUint64(buf[2621712:2687248][ii*8 : (ii+1)*8])
}
// Offset (15) 'previousEpochAttestations'
if o15 = ssz.ReadOffset(buf[2687248:2687252]); o15 > size || o12 > o15 {
return ssz.ErrOffset
}
// Offset (16) 'currentEpochAttestations'
if o16 = ssz.ReadOffset(buf[2687252:2687256]); o16 > size || o15 > o16 {
return ssz.ErrOffset
}
// Field (17) 'justificationBits'
if cap(b.justificationBits) == 0 {
b.justificationBits = make([]byte, 0, len(buf[2687256:2687257]))
}
b.justificationBits = append(b.justificationBits, buf[2687256:2687257]...)
// Field (18) 'previousJustifiedCheckpoint'
if b.previousJustifiedCheckpoint == nil {
b.previousJustifiedCheckpoint = new(ethpb.Checkpoint)
}
if err = b.previousJustifiedCheckpoint.UnmarshalSSZ(buf[2687257:2687297]); err != nil {
return err
}
// Field (19) 'currentJustifiedCheckpoint'
if b.currentJustifiedCheckpoint == nil {
b.currentJustifiedCheckpoint = new(ethpb.Checkpoint)
}
if err = b.currentJustifiedCheckpoint.UnmarshalSSZ(buf[2687297:2687337]); err != nil {
return err
}
// Field (20) 'finalizedCheckpoint'
if b.finalizedCheckpoint == nil {
b.finalizedCheckpoint = new(ethpb.Checkpoint)
}
if err = b.finalizedCheckpoint.UnmarshalSSZ(buf[2687337:2687377]); err != nil {
return err
}
// Field (7) 'historicalRoots'
{
buf = tail[o7:o9]
num, err := ssz.DivideInt2(len(buf), 32, 16777216)
if err != nil {
return err
}
b.historicalRoots = make([][32]byte, num)
for ii := 0; ii < num; ii++ {
copy(b.historicalRoots[ii][:], buf[ii*32:(ii+1)*32])
}
}
// Field (9) 'eth1DataVotes'
{
buf = tail[o9:o11]
num, err := ssz.DivideInt2(len(buf), 72, 2048)
if err != nil {
return err
}
b.eth1DataVotes = make([]*ethpb.Eth1Data, num)
for ii := 0; ii < num; ii++ {
if b.eth1DataVotes[ii] == nil {
b.eth1DataVotes[ii] = new(ethpb.Eth1Data)
}
if err = b.eth1DataVotes[ii].UnmarshalSSZ(buf[ii*72 : (ii+1)*72]); err != nil {
return err
}
}
}
// Field (11) 'validators'
{
buf = tail[o11:o12]
num, err := ssz.DivideInt2(len(buf), 121, 1099511627776)
if err != nil {
return err
}
b.validators = make([]*ethpb.Validator, num)
for ii := 0; ii < num; ii++ {
if b.validators[ii] == nil {
b.validators[ii] = new(ethpb.Validator)
}
if err = b.validators[ii].UnmarshalSSZ(buf[ii*121 : (ii+1)*121]); err != nil {
return err
}
}
}
// Field (12) 'balances'
{
buf = tail[o12:o15]
num, err := ssz.DivideInt2(len(buf), 8, 1099511627776)
if err != nil {
return err
}
b.balances = ssz.ExtendUint64(b.balances, num)
for ii := 0; ii < num; ii++ {
b.balances[ii] = ssz.UnmarshallUint64(buf[ii*8 : (ii+1)*8])
}
}
// Field (15) 'previousEpochAttestations'
{
buf = tail[o15:o16]
num, err := ssz.DecodeDynamicLength(buf, 4096)
if err != nil {
return err
}
b.previousEpochAttestations = make([]*ethpb.PendingAttestation, num)
err = ssz.UnmarshalDynamic(buf, num, func(indx int, buf []byte) (err error) {
if b.previousEpochAttestations[indx] == nil {
b.previousEpochAttestations[indx] = new(ethpb.PendingAttestation)
}
if err = b.previousEpochAttestations[indx].UnmarshalSSZ(buf); err != nil {
return err
}
return nil
})
if err != nil {
return err
}
}
// Field (16) 'currentEpochAttestations'
{
buf = tail[o16:]
num, err := ssz.DecodeDynamicLength(buf, 4096)
if err != nil {
return err
}
b.currentEpochAttestations = make([]*ethpb.PendingAttestation, num)
err = ssz.UnmarshalDynamic(buf, num, func(indx int, buf []byte) (err error) {
if b.currentEpochAttestations[indx] == nil {
b.currentEpochAttestations[indx] = new(ethpb.PendingAttestation)
}
if err = b.currentEpochAttestations[indx].UnmarshalSSZ(buf); err != nil {
return err
}
return nil
})
if err != nil {
return err
}
}
return err
}
// SizeSSZ returns the ssz encoded size in bytes for the BeaconState object
func (b *BeaconState) SizeSSZ() (size int) {
size = 2687377
// Field (7) 'historicalRoots'
size += len(b.historicalRoots) * 32
// Field (9) 'eth1DataVotes'
size += len(b.eth1DataVotes) * 72
// Field (11) 'validators'
size += len(b.validators) * 121
// Field (12) 'balances'
size += len(b.balances) * 8
// Field (15) 'previousEpochAttestations'
for ii := 0; ii < len(b.previousEpochAttestations); ii++ {
size += 4
size += b.previousEpochAttestations[ii].SizeSSZ()
}
// Field (16) 'currentEpochAttestations'
for ii := 0; ii < len(b.currentEpochAttestations); ii++ {
size += 4
size += b.currentEpochAttestations[ii].SizeSSZ()
}
return
}

View File

@@ -6,50 +6,36 @@ import (
// PreviousEpochAttestations corresponding to blocks on the beacon chain. // PreviousEpochAttestations corresponding to blocks on the beacon chain.
func (b *BeaconState) PreviousEpochAttestations() ([]*ethpb.PendingAttestation, error) { func (b *BeaconState) PreviousEpochAttestations() ([]*ethpb.PendingAttestation, error) {
if !b.hasInnerState() { if b.previousEpochAttestations == nil {
return nil, nil
}
if b.state.PreviousEpochAttestations == nil {
return nil, nil return nil, nil
} }
b.lock.RLock() b.lock.RLock()
defer b.lock.RUnlock() defer b.lock.RUnlock()
return b.previousEpochAttestations(), nil return b.previousEpochAttestationsVal(), nil
} }
// previousEpochAttestations corresponding to blocks on the beacon chain. // previousEpochAttestationsVal corresponding to blocks on the beacon chain.
// This assumes that a lock is already held on BeaconState. // This assumes that a lock is already held on BeaconState.
func (b *BeaconState) previousEpochAttestations() []*ethpb.PendingAttestation { func (b *BeaconState) previousEpochAttestationsVal() []*ethpb.PendingAttestation {
if !b.hasInnerState() { return ethpb.CopyPendingAttestationSlice(b.previousEpochAttestations)
return nil
}
return ethpb.CopyPendingAttestationSlice(b.state.PreviousEpochAttestations)
} }
// CurrentEpochAttestations corresponding to blocks on the beacon chain. // CurrentEpochAttestations corresponding to blocks on the beacon chain.
func (b *BeaconState) CurrentEpochAttestations() ([]*ethpb.PendingAttestation, error) { func (b *BeaconState) CurrentEpochAttestations() ([]*ethpb.PendingAttestation, error) {
if !b.hasInnerState() { if b.currentEpochAttestations == nil {
return nil, nil
}
if b.state.CurrentEpochAttestations == nil {
return nil, nil return nil, nil
} }
b.lock.RLock() b.lock.RLock()
defer b.lock.RUnlock() defer b.lock.RUnlock()
return b.currentEpochAttestations(), nil return b.currentEpochAttestationsVal(), nil
} }
// currentEpochAttestations corresponding to blocks on the beacon chain. // currentEpochAttestations corresponding to blocks on the beacon chain.
// This assumes that a lock is already held on BeaconState. // This assumes that a lock is already held on BeaconState.
func (b *BeaconState) currentEpochAttestations() []*ethpb.PendingAttestation { func (b *BeaconState) currentEpochAttestationsVal() []*ethpb.PendingAttestation {
if !b.hasInnerState() { return ethpb.CopyPendingAttestationSlice(b.currentEpochAttestations)
return nil
}
return ethpb.CopyPendingAttestationSlice(b.state.CurrentEpochAttestations)
} }

View File

@@ -1,47 +1,42 @@
package v1 package v1
import ( import (
"github.com/prysmaticlabs/prysm/encoding/bytesutil" "fmt"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
) )
// LatestBlockHeader stored within the beacon state. // LatestBlockHeader stored within the beacon state.
func (b *BeaconState) LatestBlockHeader() *ethpb.BeaconBlockHeader { func (b *BeaconState) LatestBlockHeader() *ethpb.BeaconBlockHeader {
if !b.hasInnerState() { if b.latestBlockHeader == nil {
return nil
}
if b.state.LatestBlockHeader == nil {
return nil return nil
} }
b.lock.RLock() b.lock.RLock()
defer b.lock.RUnlock() defer b.lock.RUnlock()
return b.latestBlockHeader() return b.latestBlockHeaderVal()
} }
// latestBlockHeader stored within the beacon state. // latestBlockHeaderVal stored within the beacon state.
// This assumes that a lock is already held on BeaconState. // This assumes that a lock is already held on BeaconState.
func (b *BeaconState) latestBlockHeader() *ethpb.BeaconBlockHeader { func (b *BeaconState) latestBlockHeaderVal() *ethpb.BeaconBlockHeader {
if !b.hasInnerState() { if b.latestBlockHeader == nil {
return nil
}
if b.state.LatestBlockHeader == nil {
return nil return nil
} }
hdr := &ethpb.BeaconBlockHeader{ hdr := &ethpb.BeaconBlockHeader{
Slot: b.state.LatestBlockHeader.Slot, Slot: b.latestBlockHeader.Slot,
ProposerIndex: b.state.LatestBlockHeader.ProposerIndex, ProposerIndex: b.latestBlockHeader.ProposerIndex,
} }
parentRoot := make([]byte, len(b.state.LatestBlockHeader.ParentRoot)) parentRoot := make([]byte, len(b.latestBlockHeader.ParentRoot))
bodyRoot := make([]byte, len(b.state.LatestBlockHeader.BodyRoot)) bodyRoot := make([]byte, len(b.latestBlockHeader.BodyRoot))
stateRoot := make([]byte, len(b.state.LatestBlockHeader.StateRoot)) stateRoot := make([]byte, len(b.latestBlockHeader.StateRoot))
copy(parentRoot, b.state.LatestBlockHeader.ParentRoot) copy(parentRoot, b.latestBlockHeader.ParentRoot)
copy(bodyRoot, b.state.LatestBlockHeader.BodyRoot) copy(bodyRoot, b.latestBlockHeader.BodyRoot)
copy(stateRoot, b.state.LatestBlockHeader.StateRoot) copy(stateRoot, b.latestBlockHeader.StateRoot)
hdr.ParentRoot = parentRoot hdr.ParentRoot = parentRoot
hdr.BodyRoot = bodyRoot hdr.BodyRoot = bodyRoot
hdr.StateRoot = stateRoot hdr.StateRoot = stateRoot
@@ -50,50 +45,39 @@ func (b *BeaconState) latestBlockHeader() *ethpb.BeaconBlockHeader {
// BlockRoots kept track of in the beacon state. // BlockRoots kept track of in the beacon state.
func (b *BeaconState) BlockRoots() [][]byte { func (b *BeaconState) BlockRoots() [][]byte {
if !b.hasInnerState() { if b.blockRoots == nil {
return nil
}
if b.state.BlockRoots == nil {
return nil return nil
} }
b.lock.RLock() b.lock.RLock()
defer b.lock.RUnlock() defer b.lock.RUnlock()
return b.blockRoots() return b.blockRoots.Slice()
}
// blockRoots kept track of in the beacon state.
// This assumes that a lock is already held on BeaconState.
func (b *BeaconState) blockRoots() [][]byte {
if !b.hasInnerState() {
return nil
}
return bytesutil.SafeCopy2dBytes(b.state.BlockRoots)
} }
// BlockRootAtIndex retrieves a specific block root based on an // BlockRootAtIndex retrieves a specific block root based on an
// input index value. // input index value.
func (b *BeaconState) BlockRootAtIndex(idx uint64) ([]byte, error) { func (b *BeaconState) BlockRootAtIndex(idx uint64) ([]byte, error) {
if !b.hasInnerState() { if b.blockRoots == nil {
return nil, ErrNilInnerState return []byte{}, nil
}
if b.state.BlockRoots == nil {
return nil, nil
} }
b.lock.RLock() b.lock.RLock()
defer b.lock.RUnlock() defer b.lock.RUnlock()
return b.blockRootAtIndex(idx) r, err := b.blockRootAtIndex(idx)
if err != nil {
return nil, err
}
return r[:], nil
} }
// blockRootAtIndex retrieves a specific block root based on an // blockRootAtIndex retrieves a specific block root based on an
// input index value. // input index value.
// This assumes that a lock is already held on BeaconState. // This assumes that a lock is already held on BeaconState.
func (b *BeaconState) blockRootAtIndex(idx uint64) ([]byte, error) { func (b *BeaconState) blockRootAtIndex(idx uint64) ([32]byte, error) {
if !b.hasInnerState() { if uint64(len(b.blockRoots)) <= idx {
return nil, ErrNilInnerState return [32]byte{}, fmt.Errorf("index %d out of range", idx)
} }
return bytesutil.SafeCopyRootAtIndex(b.state.BlockRoots, idx) return b.blockRoots[idx], nil
} }

View File

@@ -3,6 +3,7 @@ package v1
import ( import (
"testing" "testing"
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
"github.com/prysmaticlabs/prysm/encoding/bytesutil" "github.com/prysmaticlabs/prysm/encoding/bytesutil"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/require"
@@ -29,9 +30,21 @@ func TestBeaconState_BlockRoots(t *testing.T) {
s, err := InitializeFromProto(&ethpb.BeaconState{}) s, err := InitializeFromProto(&ethpb.BeaconState{})
require.NoError(t, err) require.NoError(t, err)
got := s.BlockRoots() got := s.BlockRoots()
require.DeepEqual(t, ([][]byte)(nil), got) want := make([][]byte, fieldparams.BlockRootsLength)
for i := range want {
want[i] = make([]byte, 32)
}
require.DeepEqual(t, want, got)
want := [][]byte{{'a'}} want = make([][]byte, fieldparams.BlockRootsLength)
for i := range want {
if i == 0 {
want[i] = bytesutil.PadTo([]byte{'a'}, 32)
} else {
want[i] = make([]byte, 32)
}
}
s, err = InitializeFromProto(&ethpb.BeaconState{BlockRoots: want}) s, err = InitializeFromProto(&ethpb.BeaconState{BlockRoots: want})
require.NoError(t, err) require.NoError(t, err)
got = s.BlockRoots() got = s.BlockRoots()
@@ -47,10 +60,15 @@ func TestBeaconState_BlockRootAtIndex(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
got, err := s.BlockRootAtIndex(0) got, err := s.BlockRootAtIndex(0)
require.NoError(t, err) require.NoError(t, err)
require.DeepEqual(t, ([]byte)(nil), got) require.DeepEqual(t, bytesutil.PadTo([]byte{}, 32), got)
r := [][]byte{{'a'}} r := [fieldparams.BlockRootsLength][32]byte{{'a'}}
s, err = InitializeFromProto(&ethpb.BeaconState{BlockRoots: r}) bRoots := make([][]byte, len(r))
for i, root := range r {
tmp := root
bRoots[i] = tmp[:]
}
s, err = InitializeFromProto(&ethpb.BeaconState{BlockRoots: bRoots})
require.NoError(t, err) require.NoError(t, err)
got, err = s.BlockRootAtIndex(0) got, err = s.BlockRootAtIndex(0)
require.NoError(t, err) require.NoError(t, err)

View File

@@ -10,151 +10,115 @@ import (
// JustificationBits marking which epochs have been justified in the beacon chain. // JustificationBits marking which epochs have been justified in the beacon chain.
func (b *BeaconState) JustificationBits() bitfield.Bitvector4 { func (b *BeaconState) JustificationBits() bitfield.Bitvector4 {
if !b.hasInnerState() { if b.justificationBits == nil {
return nil
}
if b.state.JustificationBits == nil {
return nil return nil
} }
b.lock.RLock() b.lock.RLock()
defer b.lock.RUnlock() defer b.lock.RUnlock()
return b.justificationBits() return b.justificationBitsVal()
} }
// justificationBits marking which epochs have been justified in the beacon chain. // justificationBitsVal marking which epochs have been justified in the beacon chain.
// This assumes that a lock is already held on BeaconState. // This assumes that a lock is already held on BeaconState.
func (b *BeaconState) justificationBits() bitfield.Bitvector4 { func (b *BeaconState) justificationBitsVal() bitfield.Bitvector4 {
if !b.hasInnerState() { if b.justificationBits == nil {
return nil
}
if b.state.JustificationBits == nil {
return nil return nil
} }
res := make([]byte, len(b.state.JustificationBits.Bytes())) res := make([]byte, len(b.justificationBits.Bytes()))
copy(res, b.state.JustificationBits.Bytes()) copy(res, b.justificationBits.Bytes())
return res return res
} }
// PreviousJustifiedCheckpoint denoting an epoch and block root. // PreviousJustifiedCheckpoint denoting an epoch and block root.
func (b *BeaconState) PreviousJustifiedCheckpoint() *ethpb.Checkpoint { func (b *BeaconState) PreviousJustifiedCheckpoint() *ethpb.Checkpoint {
if !b.hasInnerState() { if b.previousJustifiedCheckpoint == nil {
return nil
}
if b.state.PreviousJustifiedCheckpoint == nil {
return nil return nil
} }
b.lock.RLock() b.lock.RLock()
defer b.lock.RUnlock() defer b.lock.RUnlock()
return b.previousJustifiedCheckpoint() return b.previousJustifiedCheckpointVal()
} }
// previousJustifiedCheckpoint denoting an epoch and block root. // previousJustifiedCheckpointVal denoting an epoch and block root.
// This assumes that a lock is already held on BeaconState. // This assumes that a lock is already held on BeaconState.
func (b *BeaconState) previousJustifiedCheckpoint() *ethpb.Checkpoint { func (b *BeaconState) previousJustifiedCheckpointVal() *ethpb.Checkpoint {
if !b.hasInnerState() { return ethpb.CopyCheckpoint(b.previousJustifiedCheckpoint)
return nil
}
return ethpb.CopyCheckpoint(b.state.PreviousJustifiedCheckpoint)
} }
// CurrentJustifiedCheckpoint denoting an epoch and block root. // CurrentJustifiedCheckpoint denoting an epoch and block root.
func (b *BeaconState) CurrentJustifiedCheckpoint() *ethpb.Checkpoint { func (b *BeaconState) CurrentJustifiedCheckpoint() *ethpb.Checkpoint {
if !b.hasInnerState() { if b.currentJustifiedCheckpoint == nil {
return nil
}
if b.state.CurrentJustifiedCheckpoint == nil {
return nil return nil
} }
b.lock.RLock() b.lock.RLock()
defer b.lock.RUnlock() defer b.lock.RUnlock()
return b.currentJustifiedCheckpoint() return b.currentJustifiedCheckpointVal()
} }
// currentJustifiedCheckpoint denoting an epoch and block root. // currentJustifiedCheckpointVal denoting an epoch and block root.
// This assumes that a lock is already held on BeaconState. // This assumes that a lock is already held on BeaconState.
func (b *BeaconState) currentJustifiedCheckpoint() *ethpb.Checkpoint { func (b *BeaconState) currentJustifiedCheckpointVal() *ethpb.Checkpoint {
if !b.hasInnerState() { return ethpb.CopyCheckpoint(b.currentJustifiedCheckpoint)
return nil
}
return ethpb.CopyCheckpoint(b.state.CurrentJustifiedCheckpoint)
} }
// MatchCurrentJustifiedCheckpoint returns true if input justified checkpoint matches // MatchCurrentJustifiedCheckpoint returns true if input justified checkpoint matches
// the current justified checkpoint in state. // the current justified checkpoint in state.
func (b *BeaconState) MatchCurrentJustifiedCheckpoint(c *ethpb.Checkpoint) bool { func (b *BeaconState) MatchCurrentJustifiedCheckpoint(c *ethpb.Checkpoint) bool {
if !b.hasInnerState() { if b.currentJustifiedCheckpoint == nil {
return false
}
if b.state.CurrentJustifiedCheckpoint == nil {
return false return false
} }
if c.Epoch != b.state.CurrentJustifiedCheckpoint.Epoch { if c.Epoch != b.currentJustifiedCheckpoint.Epoch {
return false return false
} }
return bytes.Equal(c.Root, b.state.CurrentJustifiedCheckpoint.Root) return bytes.Equal(c.Root, b.currentJustifiedCheckpoint.Root)
} }
// MatchPreviousJustifiedCheckpoint returns true if the input justified checkpoint matches // MatchPreviousJustifiedCheckpoint returns true if the input justified checkpoint matches
// the previous justified checkpoint in state. // the previous justified checkpoint in state.
func (b *BeaconState) MatchPreviousJustifiedCheckpoint(c *ethpb.Checkpoint) bool { func (b *BeaconState) MatchPreviousJustifiedCheckpoint(c *ethpb.Checkpoint) bool {
if !b.hasInnerState() { if b.previousJustifiedCheckpoint == nil {
return false
}
if b.state.PreviousJustifiedCheckpoint == nil {
return false return false
} }
if c.Epoch != b.state.PreviousJustifiedCheckpoint.Epoch { if c.Epoch != b.previousJustifiedCheckpoint.Epoch {
return false return false
} }
return bytes.Equal(c.Root, b.state.PreviousJustifiedCheckpoint.Root) return bytes.Equal(c.Root, b.previousJustifiedCheckpoint.Root)
} }
// FinalizedCheckpoint denoting an epoch and block root. // FinalizedCheckpoint denoting an epoch and block root.
func (b *BeaconState) FinalizedCheckpoint() *ethpb.Checkpoint { func (b *BeaconState) FinalizedCheckpoint() *ethpb.Checkpoint {
if !b.hasInnerState() { if b.finalizedCheckpoint == nil {
return nil
}
if b.state.FinalizedCheckpoint == nil {
return nil return nil
} }
b.lock.RLock() b.lock.RLock()
defer b.lock.RUnlock() defer b.lock.RUnlock()
return b.finalizedCheckpoint() return b.finalizedCheckpointVal()
} }
// finalizedCheckpoint denoting an epoch and block root. // finalizedCheckpointVal denoting an epoch and block root.
// This assumes that a lock is already held on BeaconState. // This assumes that a lock is already held on BeaconState.
func (b *BeaconState) finalizedCheckpoint() *ethpb.Checkpoint { func (b *BeaconState) finalizedCheckpointVal() *ethpb.Checkpoint {
if !b.hasInnerState() { return ethpb.CopyCheckpoint(b.finalizedCheckpoint)
return nil
}
return ethpb.CopyCheckpoint(b.state.FinalizedCheckpoint)
} }
// FinalizedCheckpointEpoch returns the epoch value of the finalized checkpoint. // FinalizedCheckpointEpoch returns the epoch value of the finalized checkpoint.
func (b *BeaconState) FinalizedCheckpointEpoch() types.Epoch { func (b *BeaconState) FinalizedCheckpointEpoch() types.Epoch {
if !b.hasInnerState() { if b.finalizedCheckpoint == nil {
return 0
}
if b.state.FinalizedCheckpoint == nil {
return 0 return 0
} }
b.lock.RLock() b.lock.RLock()
defer b.lock.RUnlock() defer b.lock.RUnlock()
return b.state.FinalizedCheckpoint.Epoch return b.finalizedCheckpoint.Epoch
} }

View File

@@ -6,62 +6,50 @@ import (
// Eth1Data corresponding to the proof-of-work chain information stored in the beacon state. // Eth1Data corresponding to the proof-of-work chain information stored in the beacon state.
func (b *BeaconState) Eth1Data() *ethpb.Eth1Data { func (b *BeaconState) Eth1Data() *ethpb.Eth1Data {
if !b.hasInnerState() { if b.eth1Data == nil {
return nil
}
if b.state.Eth1Data == nil {
return nil return nil
} }
b.lock.RLock() b.lock.RLock()
defer b.lock.RUnlock() defer b.lock.RUnlock()
return b.eth1Data() return b.eth1DataVal()
} }
// eth1Data corresponding to the proof-of-work chain information stored in the beacon state. // eth1DataVal corresponding to the proof-of-work chain information stored in the beacon state.
// This assumes that a lock is already held on BeaconState. // This assumes that a lock is already held on BeaconState.
func (b *BeaconState) eth1Data() *ethpb.Eth1Data { func (b *BeaconState) eth1DataVal() *ethpb.Eth1Data {
if !b.hasInnerState() { if b.eth1Data == nil {
return nil
}
if b.state.Eth1Data == nil {
return nil return nil
} }
return ethpb.CopyETH1Data(b.state.Eth1Data) return ethpb.CopyETH1Data(b.eth1Data)
} }
// Eth1DataVotes corresponds to votes from Ethereum on the canonical proof-of-work chain // Eth1DataVotes corresponds to votes from Ethereum on the canonical proof-of-work chain
// data retrieved from eth1. // data retrieved from eth1.
func (b *BeaconState) Eth1DataVotes() []*ethpb.Eth1Data { func (b *BeaconState) Eth1DataVotes() []*ethpb.Eth1Data {
if !b.hasInnerState() { if b.eth1DataVotes == nil {
return nil
}
if b.state.Eth1DataVotes == nil {
return nil return nil
} }
b.lock.RLock() b.lock.RLock()
defer b.lock.RUnlock() defer b.lock.RUnlock()
return b.eth1DataVotes() return b.eth1DataVotesVal()
} }
// eth1DataVotes corresponds to votes from Ethereum on the canonical proof-of-work chain // eth1DataVotesVal corresponds to votes from Ethereum on the canonical proof-of-work chain
// data retrieved from eth1. // data retrieved from eth1.
// This assumes that a lock is already held on BeaconState. // This assumes that a lock is already held on BeaconState.
func (b *BeaconState) eth1DataVotes() []*ethpb.Eth1Data { func (b *BeaconState) eth1DataVotesVal() []*ethpb.Eth1Data {
if !b.hasInnerState() { if b.eth1DataVotes == nil {
return nil
}
if b.state.Eth1DataVotes == nil {
return nil return nil
} }
res := make([]*ethpb.Eth1Data, len(b.state.Eth1DataVotes)) res := make([]*ethpb.Eth1Data, len(b.eth1DataVotes))
for i := 0; i < len(res); i++ { for i := 0; i < len(res); i++ {
res[i] = ethpb.CopyETH1Data(b.state.Eth1DataVotes[i]) res[i] = ethpb.CopyETH1Data(b.eth1DataVotes[i])
} }
return res return res
} }
@@ -69,23 +57,8 @@ func (b *BeaconState) eth1DataVotes() []*ethpb.Eth1Data {
// Eth1DepositIndex corresponds to the index of the deposit made to the // Eth1DepositIndex corresponds to the index of the deposit made to the
// validator deposit contract at the time of this state's eth1 data. // validator deposit contract at the time of this state's eth1 data.
func (b *BeaconState) Eth1DepositIndex() uint64 { func (b *BeaconState) Eth1DepositIndex() uint64 {
if !b.hasInnerState() {
return 0
}
b.lock.RLock() b.lock.RLock()
defer b.lock.RUnlock() defer b.lock.RUnlock()
return b.eth1DepositIndex() return b.eth1DepositIndex
}
// eth1DepositIndex corresponds to the index of the deposit made to the
// validator deposit contract at the time of this state's eth1 data.
// This assumes that a lock is already held on BeaconState.
func (b *BeaconState) eth1DepositIndex() uint64 {
if !b.hasInnerState() {
return 0
}
return b.state.Eth1DepositIndex
} }

View File

@@ -2,62 +2,24 @@ package v1
import ( import (
types "github.com/prysmaticlabs/eth2-types" types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/config/params"
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/runtime/version" "github.com/prysmaticlabs/prysm/runtime/version"
) )
// GenesisTime of the beacon state as a uint64. // GenesisTime of the beacon state as a uint64.
func (b *BeaconState) GenesisTime() uint64 { func (b *BeaconState) GenesisTime() uint64 {
if !b.hasInnerState() {
return 0
}
b.lock.RLock() b.lock.RLock()
defer b.lock.RUnlock() defer b.lock.RUnlock()
return b.genesisTime() return b.genesisTime
}
// genesisTime of the beacon state as a uint64.
// This assumes that a lock is already held on BeaconState.
func (b *BeaconState) genesisTime() uint64 {
if !b.hasInnerState() {
return 0
}
return b.state.GenesisTime
} }
// GenesisValidatorRoot of the beacon state. // GenesisValidatorRoot of the beacon state.
func (b *BeaconState) GenesisValidatorRoot() []byte { func (b *BeaconState) GenesisValidatorRoot() []byte {
if !b.hasInnerState() {
return nil
}
if b.state.GenesisValidatorsRoot == nil {
return params.BeaconConfig().ZeroHash[:]
}
b.lock.RLock() b.lock.RLock()
defer b.lock.RUnlock() defer b.lock.RUnlock()
return b.genesisValidatorRoot() return b.genesisValidatorsRoot[:]
}
// genesisValidatorRoot of the beacon state.
// This assumes that a lock is already held on BeaconState.
func (b *BeaconState) genesisValidatorRoot() []byte {
if !b.hasInnerState() {
return nil
}
if b.state.GenesisValidatorsRoot == nil {
return params.BeaconConfig().ZeroHash[:]
}
root := make([]byte, 32)
copy(root, b.state.GenesisValidatorsRoot)
return root
} }
// Version of the beacon state. This method // Version of the beacon state. This method
@@ -69,95 +31,60 @@ func (_ *BeaconState) Version() int {
// Slot of the current beacon chain state. // Slot of the current beacon chain state.
func (b *BeaconState) Slot() types.Slot { func (b *BeaconState) Slot() types.Slot {
if !b.hasInnerState() {
return 0
}
b.lock.RLock() b.lock.RLock()
defer b.lock.RUnlock() defer b.lock.RUnlock()
return b.slot() return b.slot
}
// slot of the current beacon chain state.
// This assumes that a lock is already held on BeaconState.
func (b *BeaconState) slot() types.Slot {
if !b.hasInnerState() {
return 0
}
return b.state.Slot
} }
// Fork version of the beacon chain. // Fork version of the beacon chain.
func (b *BeaconState) Fork() *ethpb.Fork { func (b *BeaconState) Fork() *ethpb.Fork {
if !b.hasInnerState() { if b.fork == nil {
return nil
}
if b.state.Fork == nil {
return nil return nil
} }
b.lock.RLock() b.lock.RLock()
defer b.lock.RUnlock() defer b.lock.RUnlock()
return b.fork() return b.forkVal()
} }
// fork version of the beacon chain. // forkVal version of the beacon chain.
// This assumes that a lock is already held on BeaconState. // This assumes that a lock is already held on BeaconState.
func (b *BeaconState) fork() *ethpb.Fork { func (b *BeaconState) forkVal() *ethpb.Fork {
if !b.hasInnerState() { if b.fork == nil {
return nil
}
if b.state.Fork == nil {
return nil return nil
} }
prevVersion := make([]byte, len(b.state.Fork.PreviousVersion)) prevVersion := make([]byte, len(b.fork.PreviousVersion))
copy(prevVersion, b.state.Fork.PreviousVersion) copy(prevVersion, b.fork.PreviousVersion)
currVersion := make([]byte, len(b.state.Fork.CurrentVersion)) currVersion := make([]byte, len(b.fork.CurrentVersion))
copy(currVersion, b.state.Fork.CurrentVersion) copy(currVersion, b.fork.CurrentVersion)
return &ethpb.Fork{ return &ethpb.Fork{
PreviousVersion: prevVersion, PreviousVersion: prevVersion,
CurrentVersion: currVersion, CurrentVersion: currVersion,
Epoch: b.state.Fork.Epoch, Epoch: b.fork.Epoch,
} }
} }
// HistoricalRoots based on epochs stored in the beacon state. // HistoricalRoots based on epochs stored in the beacon state.
func (b *BeaconState) HistoricalRoots() [][]byte { func (b *BeaconState) HistoricalRoots() [][]byte {
if !b.hasInnerState() { if b.historicalRoots == nil {
return nil
}
if b.state.HistoricalRoots == nil {
return nil return nil
} }
b.lock.RLock() b.lock.RLock()
defer b.lock.RUnlock() defer b.lock.RUnlock()
return b.historicalRoots() return b.historicalRoots.Slice()
}
// historicalRoots based on epochs stored in the beacon state.
// This assumes that a lock is already held on BeaconState.
func (b *BeaconState) historicalRoots() [][]byte {
if !b.hasInnerState() {
return nil
}
return bytesutil.SafeCopy2dBytes(b.state.HistoricalRoots)
} }
// balancesLength returns the length of the balances slice. // balancesLength returns the length of the balances slice.
// This assumes that a lock is already held on BeaconState. // This assumes that a lock is already held on BeaconState.
func (b *BeaconState) balancesLength() int { func (b *BeaconState) balancesLength() int {
if !b.hasInnerState() { if b.balances == nil {
return 0
}
if b.state.Balances == nil {
return 0 return 0
} }
return len(b.state.Balances) return len(b.balances)
} }

View File

@@ -1,67 +1,51 @@
package v1 package v1
import ( import (
"github.com/prysmaticlabs/prysm/encoding/bytesutil" "fmt"
) )
// RandaoMixes of block proposers on the beacon chain. // RandaoMixes of block proposers on the beacon chain.
func (b *BeaconState) RandaoMixes() [][]byte { func (b *BeaconState) RandaoMixes() [][]byte {
if !b.hasInnerState() { if b.randaoMixes == nil {
return nil
}
if b.state.RandaoMixes == nil {
return nil return nil
} }
b.lock.RLock() b.lock.RLock()
defer b.lock.RUnlock() defer b.lock.RUnlock()
return b.randaoMixes() return b.randaoMixes.Slice()
}
// randaoMixes of block proposers on the beacon chain.
// This assumes that a lock is already held on BeaconState.
func (b *BeaconState) randaoMixes() [][]byte {
if !b.hasInnerState() {
return nil
}
return bytesutil.SafeCopy2dBytes(b.state.RandaoMixes)
} }
// RandaoMixAtIndex retrieves a specific block root based on an // RandaoMixAtIndex retrieves a specific block root based on an
// input index value. // input index value.
func (b *BeaconState) RandaoMixAtIndex(idx uint64) ([]byte, error) { func (b *BeaconState) RandaoMixAtIndex(idx uint64) ([]byte, error) {
if !b.hasInnerState() { if b.randaoMixes == nil {
return nil, ErrNilInnerState
}
if b.state.RandaoMixes == nil {
return nil, nil return nil, nil
} }
b.lock.RLock() b.lock.RLock()
defer b.lock.RUnlock() defer b.lock.RUnlock()
return b.randaoMixAtIndex(idx) m, err := b.randaoMixAtIndex(idx)
if err != nil {
return nil, err
}
return m[:], nil
} }
// randaoMixAtIndex retrieves a specific block root based on an // randaoMixAtIndex retrieves a specific block root based on an
// input index value. // input index value.
// This assumes that a lock is already held on BeaconState. // This assumes that a lock is already held on BeaconState.
func (b *BeaconState) randaoMixAtIndex(idx uint64) ([]byte, error) { func (b *BeaconState) randaoMixAtIndex(idx uint64) ([32]byte, error) {
if !b.hasInnerState() { if uint64(len(b.randaoMixes)) <= idx {
return nil, ErrNilInnerState return [32]byte{}, fmt.Errorf("index %d out of range", idx)
} }
return b.randaoMixes[idx], nil
return bytesutil.SafeCopyRootAtIndex(b.state.RandaoMixes, idx)
} }
// RandaoMixesLength returns the length of the randao mixes slice. // RandaoMixesLength returns the length of the randao mixes slice.
func (b *BeaconState) RandaoMixesLength() int { func (b *BeaconState) RandaoMixesLength() int {
if !b.hasInnerState() { if b.randaoMixes == nil {
return 0
}
if b.state.RandaoMixes == nil {
return 0 return 0
} }
@@ -74,12 +58,9 @@ func (b *BeaconState) RandaoMixesLength() int {
// randaoMixesLength returns the length of the randao mixes slice. // randaoMixesLength returns the length of the randao mixes slice.
// This assumes that a lock is already held on BeaconState. // This assumes that a lock is already held on BeaconState.
func (b *BeaconState) randaoMixesLength() int { func (b *BeaconState) randaoMixesLength() int {
if !b.hasInnerState() { if b.randaoMixes == nil {
return 0
}
if b.state.RandaoMixes == nil {
return 0 return 0
} }
return len(b.state.RandaoMixes) return len(b.randaoMixes)
} }

View File

@@ -1,115 +1,119 @@
package v1 package v1
import ( import (
"fmt"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
) )
// InnerStateUnsafe returns the pointer value of the underlying // ToProtoUnsafe returns the pointer value of the underlying
// beacon state proto object, bypassing immutability. Use with care. // beacon state proto object, bypassing immutability. Use with care.
func (b *BeaconState) InnerStateUnsafe() interface{} { func (b *BeaconState) ToProtoUnsafe() interface{} {
if b == nil { if b == nil {
return nil return nil
} }
return b.state
gvrCopy := b.genesisValidatorsRoot
return &ethpb.BeaconState{
GenesisTime: b.genesisTime,
GenesisValidatorsRoot: gvrCopy[:],
Slot: b.slot,
Fork: b.fork,
LatestBlockHeader: b.latestBlockHeader,
BlockRoots: b.blockRoots.Slice(),
StateRoots: b.stateRoots.Slice(),
HistoricalRoots: b.historicalRoots.Slice(),
Eth1Data: b.eth1Data,
Eth1DataVotes: b.eth1DataVotes,
Eth1DepositIndex: b.eth1DepositIndex,
Validators: b.validators,
Balances: b.balances,
RandaoMixes: b.randaoMixes.Slice(),
Slashings: b.slashings,
PreviousEpochAttestations: b.previousEpochAttestations,
CurrentEpochAttestations: b.currentEpochAttestations,
JustificationBits: b.justificationBits,
PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint,
CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint,
FinalizedCheckpoint: b.finalizedCheckpoint,
}
} }
// CloneInnerState the beacon state into a protobuf for usage. // ToProto the beacon state into a protobuf for usage.
func (b *BeaconState) CloneInnerState() interface{} { func (b *BeaconState) ToProto() interface{} {
if b == nil || b.state == nil { if b == nil {
return nil return nil
} }
b.lock.RLock() b.lock.RLock()
defer b.lock.RUnlock() defer b.lock.RUnlock()
return &ethpb.BeaconState{
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 gvrCopy := b.genesisValidatorsRoot
// is populated correctly. Returns false if nil.
func (b *BeaconState) hasInnerState() bool { return &ethpb.BeaconState{
return b != nil && b.state != nil GenesisTime: b.genesisTime,
GenesisValidatorsRoot: gvrCopy[:],
Slot: b.slot,
Fork: b.forkVal(),
LatestBlockHeader: b.latestBlockHeaderVal(),
BlockRoots: b.blockRoots.Slice(),
StateRoots: b.stateRoots.Slice(),
HistoricalRoots: b.historicalRoots.Slice(),
Eth1Data: b.eth1DataVal(),
Eth1DataVotes: b.eth1DataVotesVal(),
Eth1DepositIndex: b.eth1DepositIndex,
Validators: b.validatorsVal(),
Balances: b.balancesVal(),
RandaoMixes: b.randaoMixes.Slice(),
Slashings: b.slashingsVal(),
PreviousEpochAttestations: b.previousEpochAttestationsVal(),
CurrentEpochAttestations: b.currentEpochAttestationsVal(),
JustificationBits: b.justificationBitsVal(),
PreviousJustifiedCheckpoint: b.previousJustifiedCheckpointVal(),
CurrentJustifiedCheckpoint: b.currentJustifiedCheckpointVal(),
FinalizedCheckpoint: b.finalizedCheckpointVal(),
}
} }
// StateRoots kept track of in the beacon state. // StateRoots kept track of in the beacon state.
func (b *BeaconState) StateRoots() [][]byte { func (b *BeaconState) StateRoots() [][]byte {
if !b.hasInnerState() { if b.stateRoots == nil {
return nil
}
if b.state.StateRoots == nil {
return nil return nil
} }
b.lock.RLock() b.lock.RLock()
defer b.lock.RUnlock() defer b.lock.RUnlock()
return b.stateRoots() return b.stateRoots.Slice()
}
// 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 bytesutil.SafeCopy2dBytes(b.state.StateRoots)
} }
// StateRootAtIndex retrieves a specific state root based on an // StateRootAtIndex retrieves a specific state root based on an
// input index value. // input index value.
func (b *BeaconState) StateRootAtIndex(idx uint64) ([]byte, error) { func (b *BeaconState) StateRootAtIndex(idx uint64) ([]byte, error) {
if !b.hasInnerState() { if b.stateRoots == nil {
return nil, ErrNilInnerState
}
if b.state.StateRoots == nil {
return nil, nil return nil, nil
} }
b.lock.RLock() b.lock.RLock()
defer b.lock.RUnlock() defer b.lock.RUnlock()
return b.stateRootAtIndex(idx) r, err := b.stateRootAtIndex(idx)
if err != nil {
return nil, err
}
return r[:], nil
} }
// stateRootAtIndex retrieves a specific state root based on an // stateRootAtIndex retrieves a specific state root based on an
// input index value. // input index value.
// This assumes that a lock is already held on BeaconState. // This assumes that a lock is already held on BeaconState.
func (b *BeaconState) stateRootAtIndex(idx uint64) ([]byte, error) { func (b *BeaconState) stateRootAtIndex(idx uint64) ([32]byte, error) {
if !b.hasInnerState() { if uint64(len(b.stateRoots)) <= idx {
return nil, ErrNilInnerState return [32]byte{}, fmt.Errorf("index %d out of range", idx)
} }
return bytesutil.SafeCopyRootAtIndex(b.state.StateRoots, idx) return b.stateRoots[idx], nil
}
// 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. // ProtobufBeaconState transforms an input into beacon state in the form of protobuf.
@@ -121,3 +125,14 @@ func ProtobufBeaconState(s interface{}) (*ethpb.BeaconState, error) {
} }
return pbState, nil return pbState, nil
} }
// InnerStateUnsafe returns the pointer value of the underlying
// beacon state proto object, bypassing immutability. Use with care.
func (b *BeaconState) InnerStateUnsafe() interface{} {
return b.ToProtoUnsafe()
}
// CloneInnerState the beacon state into a protobuf for usage.
func (b *BeaconState) CloneInnerState() interface{} {
return b.ToProto()
}

View File

@@ -1,7 +1,6 @@
package v1 package v1
import ( import (
"runtime/debug"
"sync" "sync"
"testing" "testing"
@@ -30,54 +29,6 @@ func TestBeaconState_SlotDataRace(t *testing.T) {
wg.Wait() wg.Wait()
} }
func TestNilState_NoPanic(t *testing.T) {
var st *BeaconState
defer func() {
if r := recover(); r != nil {
t.Errorf("Method panicked when it was not supposed to: %v\n%v\n", r, string(debug.Stack()))
}
}()
// retrieve elements from nil state
_ = st.GenesisTime()
_ = st.GenesisValidatorRoot()
_ = st.GenesisValidatorRoot()
_ = st.Slot()
_ = st.Fork()
_ = st.LatestBlockHeader()
_ = st.BlockRoots()
_, err := st.BlockRootAtIndex(0)
_ = err
_ = st.StateRoots()
_ = st.HistoricalRoots()
_ = st.Eth1Data()
_ = st.Eth1DataVotes()
_ = st.Eth1DepositIndex()
_, err = st.ValidatorAtIndex(0)
_ = err
_, err = st.ValidatorAtIndexReadOnly(0)
_ = err
_, _ = st.ValidatorIndexByPubkey([fieldparams.BLSPubkeyLength]byte{})
_ = st.PubkeyAtIndex(0)
_ = st.NumValidators()
_ = st.Balances()
_, err = st.BalanceAtIndex(0)
_ = err
_ = st.BalancesLength()
_ = st.RandaoMixes()
_, err = st.RandaoMixAtIndex(0)
_ = err
_ = st.RandaoMixesLength()
_ = st.Slashings()
_, err = st.PreviousEpochAttestations()
require.NoError(t, err)
_, err = st.CurrentEpochAttestations()
require.NoError(t, err)
_ = st.JustificationBits()
_ = st.PreviousJustifiedCheckpoint()
_ = st.CurrentJustifiedCheckpoint()
_ = st.FinalizedCheckpoint()
}
func TestBeaconState_MatchCurrentJustifiedCheckpt(t *testing.T) { func TestBeaconState_MatchCurrentJustifiedCheckpt(t *testing.T) {
c1 := &ethpb.Checkpoint{Epoch: 1} c1 := &ethpb.Checkpoint{Epoch: 1}
c2 := &ethpb.Checkpoint{Epoch: 2} c2 := &ethpb.Checkpoint{Epoch: 2}
@@ -87,8 +38,6 @@ func TestBeaconState_MatchCurrentJustifiedCheckpt(t *testing.T) {
require.Equal(t, false, beaconState.MatchCurrentJustifiedCheckpoint(c2)) require.Equal(t, false, beaconState.MatchCurrentJustifiedCheckpoint(c2))
require.Equal(t, false, beaconState.MatchPreviousJustifiedCheckpoint(c1)) require.Equal(t, false, beaconState.MatchPreviousJustifiedCheckpoint(c1))
require.Equal(t, false, beaconState.MatchPreviousJustifiedCheckpoint(c2)) require.Equal(t, false, beaconState.MatchPreviousJustifiedCheckpoint(c2))
beaconState.state = nil
require.Equal(t, false, beaconState.MatchCurrentJustifiedCheckpoint(c1))
} }
func TestBeaconState_MatchPreviousJustifiedCheckpt(t *testing.T) { func TestBeaconState_MatchPreviousJustifiedCheckpt(t *testing.T) {
@@ -101,16 +50,6 @@ func TestBeaconState_MatchPreviousJustifiedCheckpt(t *testing.T) {
require.Equal(t, false, beaconState.MatchCurrentJustifiedCheckpoint(c2)) require.Equal(t, false, beaconState.MatchCurrentJustifiedCheckpoint(c2))
require.Equal(t, true, beaconState.MatchPreviousJustifiedCheckpoint(c1)) require.Equal(t, true, beaconState.MatchPreviousJustifiedCheckpoint(c1))
require.Equal(t, false, beaconState.MatchPreviousJustifiedCheckpoint(c2)) require.Equal(t, false, beaconState.MatchPreviousJustifiedCheckpoint(c2))
beaconState.state = nil
require.Equal(t, false, beaconState.MatchPreviousJustifiedCheckpoint(c1))
}
func TestBeaconState_MarshalSSZ_NilState(t *testing.T) {
s, err := InitializeFromProto(&ethpb.BeaconState{})
require.NoError(t, err)
s.state = nil
_, err = s.MarshalSSZ()
require.ErrorContains(t, "nil beacon state", err)
} }
func TestBeaconState_ValidatorByPubkey(t *testing.T) { func TestBeaconState_ValidatorByPubkey(t *testing.T) {

View File

@@ -31,32 +31,26 @@ func (e *ValidatorIndexOutOfRangeError) Error() string {
// Validators participating in consensus on the beacon chain. // Validators participating in consensus on the beacon chain.
func (b *BeaconState) Validators() []*ethpb.Validator { func (b *BeaconState) Validators() []*ethpb.Validator {
if !b.hasInnerState() { if b.validators == nil {
return nil
}
if b.state.Validators == nil {
return nil return nil
} }
b.lock.RLock() b.lock.RLock()
defer b.lock.RUnlock() defer b.lock.RUnlock()
return b.validators() return b.validatorsVal()
} }
// validators participating in consensus on the beacon chain. // validatorsVal participating in consensus on the beacon chain.
// This assumes that a lock is already held on BeaconState. // This assumes that a lock is already held on BeaconState.
func (b *BeaconState) validators() []*ethpb.Validator { func (b *BeaconState) validatorsVal() []*ethpb.Validator {
if !b.hasInnerState() { if b.validators == nil {
return nil
}
if b.state.Validators == nil {
return nil return nil
} }
res := make([]*ethpb.Validator, len(b.state.Validators)) res := make([]*ethpb.Validator, len(b.validators))
for i := 0; i < len(res); i++ { for i := 0; i < len(res); i++ {
val := b.state.Validators[i] val := b.validators[i]
if val == nil { if val == nil {
continue continue
} }
@@ -69,16 +63,13 @@ func (b *BeaconState) validators() []*ethpb.Validator {
// This assumes that a lock is already held on BeaconState. This does not // This assumes that a lock is already held on BeaconState. This does not
// copy fully and instead just copies the reference. // copy fully and instead just copies the reference.
func (b *BeaconState) validatorsReferences() []*ethpb.Validator { func (b *BeaconState) validatorsReferences() []*ethpb.Validator {
if !b.hasInnerState() { if b.validators == nil {
return nil
}
if b.state.Validators == nil {
return nil return nil
} }
res := make([]*ethpb.Validator, len(b.state.Validators)) res := make([]*ethpb.Validator, len(b.validators))
for i := 0; i < len(res); i++ { for i := 0; i < len(res); i++ {
validator := b.state.Validators[i] validator := b.validators[i]
if validator == nil { if validator == nil {
continue continue
} }
@@ -90,13 +81,10 @@ func (b *BeaconState) validatorsReferences() []*ethpb.Validator {
// ValidatorAtIndex is the validator at the provided index. // ValidatorAtIndex is the validator at the provided index.
func (b *BeaconState) ValidatorAtIndex(idx types.ValidatorIndex) (*ethpb.Validator, error) { func (b *BeaconState) ValidatorAtIndex(idx types.ValidatorIndex) (*ethpb.Validator, error) {
if !b.hasInnerState() { if b.validators == nil {
return nil, ErrNilInnerState
}
if b.state.Validators == nil {
return &ethpb.Validator{}, nil return &ethpb.Validator{}, nil
} }
if uint64(len(b.state.Validators)) <= uint64(idx) { if uint64(len(b.validators)) <= uint64(idx) {
e := NewValidatorIndexOutOfRangeError(idx) e := NewValidatorIndexOutOfRangeError(idx)
return nil, &e return nil, &e
} }
@@ -104,20 +92,17 @@ func (b *BeaconState) ValidatorAtIndex(idx types.ValidatorIndex) (*ethpb.Validat
b.lock.RLock() b.lock.RLock()
defer b.lock.RUnlock() defer b.lock.RUnlock()
val := b.state.Validators[idx] val := b.validators[idx]
return ethpb.CopyValidator(val), nil return ethpb.CopyValidator(val), nil
} }
// ValidatorAtIndexReadOnly is the validator at the provided index. This method // ValidatorAtIndexReadOnly is the validator at the provided index. This method
// doesn't clone the validator. // doesn't clone the validator.
func (b *BeaconState) ValidatorAtIndexReadOnly(idx types.ValidatorIndex) (state.ReadOnlyValidator, error) { func (b *BeaconState) ValidatorAtIndexReadOnly(idx types.ValidatorIndex) (state.ReadOnlyValidator, error) {
if !b.hasInnerState() { if b.validators == nil {
return nil, ErrNilInnerState
}
if b.state.Validators == nil {
return nil, state.ErrNilValidatorsInState return nil, state.ErrNilValidatorsInState
} }
if uint64(len(b.state.Validators)) <= uint64(idx) { if uint64(len(b.validators)) <= uint64(idx) {
e := NewValidatorIndexOutOfRangeError(idx) e := NewValidatorIndexOutOfRangeError(idx)
return nil, &e return nil, &e
} }
@@ -125,7 +110,7 @@ func (b *BeaconState) ValidatorAtIndexReadOnly(idx types.ValidatorIndex) (state.
b.lock.RLock() b.lock.RLock()
defer b.lock.RUnlock() defer b.lock.RUnlock()
return NewValidator(b.state.Validators[idx]) return NewValidator(b.validators[idx])
} }
// ValidatorIndexByPubkey returns a given validator by its 48-byte public key. // ValidatorIndexByPubkey returns a given validator by its 48-byte public key.
@@ -135,7 +120,7 @@ func (b *BeaconState) ValidatorIndexByPubkey(key [fieldparams.BLSPubkeyLength]by
} }
b.lock.RLock() b.lock.RLock()
defer b.lock.RUnlock() defer b.lock.RUnlock()
numOfVals := len(b.state.Validators) numOfVals := len(b.validators)
idx, ok := b.valMapHandler.Get(key) idx, ok := b.valMapHandler.Get(key)
if ok && numOfVals <= int(idx) { if ok && numOfVals <= int(idx) {
@@ -147,43 +132,34 @@ func (b *BeaconState) ValidatorIndexByPubkey(key [fieldparams.BLSPubkeyLength]by
// PubkeyAtIndex returns the pubkey at the given // PubkeyAtIndex returns the pubkey at the given
// validator index. // validator index.
func (b *BeaconState) PubkeyAtIndex(idx types.ValidatorIndex) [fieldparams.BLSPubkeyLength]byte { func (b *BeaconState) PubkeyAtIndex(idx types.ValidatorIndex) [fieldparams.BLSPubkeyLength]byte {
if !b.hasInnerState() { if uint64(idx) >= uint64(len(b.validators)) {
return [fieldparams.BLSPubkeyLength]byte{}
}
if uint64(idx) >= uint64(len(b.state.Validators)) {
return [fieldparams.BLSPubkeyLength]byte{} return [fieldparams.BLSPubkeyLength]byte{}
} }
b.lock.RLock() b.lock.RLock()
defer b.lock.RUnlock() defer b.lock.RUnlock()
if b.state.Validators[idx] == nil { if b.validators[idx] == nil {
return [fieldparams.BLSPubkeyLength]byte{} return [fieldparams.BLSPubkeyLength]byte{}
} }
return bytesutil.ToBytes48(b.state.Validators[idx].PublicKey) return bytesutil.ToBytes48(b.validators[idx].PublicKey)
} }
// NumValidators returns the size of the validator registry. // NumValidators returns the size of the validator registry.
func (b *BeaconState) NumValidators() int { func (b *BeaconState) NumValidators() int {
if !b.hasInnerState() {
return 0
}
b.lock.RLock() b.lock.RLock()
defer b.lock.RUnlock() defer b.lock.RUnlock()
return len(b.state.Validators) return len(b.validators)
} }
// ReadFromEveryValidator reads values from every validator and applies it to the provided function. // ReadFromEveryValidator reads values from every validator and applies it to the provided function.
// Warning: This method is potentially unsafe, as it exposes the actual validator registry. // Warning: This method is potentially unsafe, as it exposes the actual validator registry.
func (b *BeaconState) ReadFromEveryValidator(f func(idx int, val state.ReadOnlyValidator) error) error { func (b *BeaconState) ReadFromEveryValidator(f func(idx int, val state.ReadOnlyValidator) error) error {
if !b.hasInnerState() { if b.validators == nil {
return ErrNilInnerState
}
if b.state.Validators == nil {
return errors.New("nil validators in state") return errors.New("nil validators in state")
} }
b.lock.RLock() b.lock.RLock()
validators := b.state.Validators validators := b.validators
b.lock.RUnlock() b.lock.RUnlock()
for i, v := range validators { for i, v := range validators {
@@ -200,58 +176,46 @@ func (b *BeaconState) ReadFromEveryValidator(f func(idx int, val state.ReadOnlyV
// Balances of validators participating in consensus on the beacon chain. // Balances of validators participating in consensus on the beacon chain.
func (b *BeaconState) Balances() []uint64 { func (b *BeaconState) Balances() []uint64 {
if !b.hasInnerState() { if b.balances == nil {
return nil
}
if b.state.Balances == nil {
return nil return nil
} }
b.lock.RLock() b.lock.RLock()
defer b.lock.RUnlock() defer b.lock.RUnlock()
return b.balances() return b.balancesVal()
} }
// balances of validators participating in consensus on the beacon chain. // balances of validators participating in consensus on the beacon chain.
// This assumes that a lock is already held on BeaconState. // This assumes that a lock is already held on BeaconState.
func (b *BeaconState) balances() []uint64 { func (b *BeaconState) balancesVal() []uint64 {
if !b.hasInnerState() { if b.balances == nil {
return nil
}
if b.state.Balances == nil {
return nil return nil
} }
res := make([]uint64, len(b.state.Balances)) res := make([]uint64, len(b.balances))
copy(res, b.state.Balances) copy(res, b.balances)
return res return res
} }
// BalanceAtIndex of validator with the provided index. // BalanceAtIndex of validator with the provided index.
func (b *BeaconState) BalanceAtIndex(idx types.ValidatorIndex) (uint64, error) { func (b *BeaconState) BalanceAtIndex(idx types.ValidatorIndex) (uint64, error) {
if !b.hasInnerState() { if b.balances == nil {
return 0, ErrNilInnerState
}
if b.state.Balances == nil {
return 0, nil return 0, nil
} }
b.lock.RLock() b.lock.RLock()
defer b.lock.RUnlock() defer b.lock.RUnlock()
if uint64(len(b.state.Balances)) <= uint64(idx) { if uint64(len(b.balances)) <= uint64(idx) {
return 0, fmt.Errorf("index of %d does not exist", idx) return 0, fmt.Errorf("index of %d does not exist", idx)
} }
return b.state.Balances[idx], nil return b.balances[idx], nil
} }
// BalancesLength returns the length of the balances slice. // BalancesLength returns the length of the balances slice.
func (b *BeaconState) BalancesLength() int { func (b *BeaconState) BalancesLength() int {
if !b.hasInnerState() { if b.balances == nil {
return 0
}
if b.state.Balances == nil {
return 0 return 0
} }
@@ -263,30 +227,24 @@ func (b *BeaconState) BalancesLength() int {
// Slashings of validators on the beacon chain. // Slashings of validators on the beacon chain.
func (b *BeaconState) Slashings() []uint64 { func (b *BeaconState) Slashings() []uint64 {
if !b.hasInnerState() { if b.slashings == nil {
return nil
}
if b.state.Slashings == nil {
return nil return nil
} }
b.lock.RLock() b.lock.RLock()
defer b.lock.RUnlock() defer b.lock.RUnlock()
return b.slashings() return b.slashingsVal()
} }
// slashings of validators on the beacon chain. // slashings of validators on the beacon chain.
// This assumes that a lock is already held on BeaconState. // This assumes that a lock is already held on BeaconState.
func (b *BeaconState) slashings() []uint64 { func (b *BeaconState) slashingsVal() []uint64 {
if !b.hasInnerState() { if b.slashings == nil {
return nil
}
if b.state.Slashings == nil {
return nil return nil
} }
res := make([]uint64, len(b.state.Slashings)) res := make([]uint64, len(b.slashings))
copy(res, b.state.Slashings) copy(res, b.slashings)
return res return res
} }

View File

@@ -39,7 +39,7 @@ func (b *BeaconState) FinalizedRootProof(ctx context.Context) ([][]byte, error)
if err := b.recomputeDirtyFields(ctx); err != nil { if err := b.recomputeDirtyFields(ctx); err != nil {
return nil, err return nil, err
} }
cpt := b.state.FinalizedCheckpoint cpt := b.finalizedCheckpoint
// The epoch field of a finalized checkpoint is the neighbor // The epoch field of a finalized checkpoint is the neighbor
// index of the finalized root field in its Merkle tree representation // index of the finalized root field in its Merkle tree representation
// of the checkpoint. This neighbor is the first element added to the proof. // of the checkpoint. This neighbor is the first element added to the proof.

View File

@@ -64,14 +64,14 @@ func TestStateReferenceCopy_NoUnexpectedRootsMutation(t *testing.T) {
assertRefCount(t, a, stateRoots, 2) assertRefCount(t, a, stateRoots, 2)
assertRefCount(t, b, blockRoots, 2) assertRefCount(t, b, blockRoots, 2)
assertRefCount(t, b, stateRoots, 2) assertRefCount(t, b, stateRoots, 2)
assert.Equal(t, 1, len(b.state.GetBlockRoots()), "No block roots found") assert.Equal(t, 8192, len(b.BlockRoots()), "Wrong number of block roots found")
assert.Equal(t, 1, len(b.state.GetStateRoots()), "No state roots found") assert.Equal(t, 8192, len(b.StateRoots()), "Wrong number of state roots found")
// Assert shared state. // Assert shared state.
blockRootsA := a.state.GetBlockRoots() blockRootsA := a.BlockRoots()
stateRootsA := a.state.GetStateRoots() stateRootsA := a.StateRoots()
blockRootsB := b.state.GetBlockRoots() blockRootsB := b.BlockRoots()
stateRootsB := b.state.GetStateRoots() stateRootsB := b.StateRoots()
if len(blockRootsA) != len(blockRootsB) || len(blockRootsA) < 1 { if len(blockRootsA) != len(blockRootsB) || len(blockRootsA) < 1 {
t.Errorf("Unexpected number of block roots, want: %v", 1) t.Errorf("Unexpected number of block roots, want: %v", 1)
} }
@@ -88,20 +88,20 @@ func TestStateReferenceCopy_NoUnexpectedRootsMutation(t *testing.T) {
require.NoError(t, a.UpdateStateRootAtIndex(0, root2)) require.NoError(t, a.UpdateStateRootAtIndex(0, root2))
// Assert no shared state mutation occurred only on state a (copy on write). // Assert no shared state mutation occurred only on state a (copy on write).
assertValNotFound(t, a.state.GetBlockRoots(), root1[:]) assertValNotFound(t, a.BlockRoots(), root1[:])
assertValNotFound(t, a.state.GetStateRoots(), root1[:]) assertValNotFound(t, a.StateRoots(), root1[:])
assertValFound(t, a.state.GetBlockRoots(), root2[:]) assertValFound(t, a.BlockRoots(), root2[:])
assertValFound(t, a.state.GetStateRoots(), root2[:]) assertValFound(t, a.StateRoots(), root2[:])
assertValFound(t, b.state.GetBlockRoots(), root1[:]) assertValFound(t, b.BlockRoots(), root1[:])
assertValFound(t, b.state.GetStateRoots(), root1[:]) assertValFound(t, b.StateRoots(), root1[:])
if len(blockRootsA) != len(blockRootsB) || len(blockRootsA) < 1 { if len(blockRootsA) != len(blockRootsB) || len(blockRootsA) < 1 {
t.Errorf("Unexpected number of block roots, want: %v", 1) t.Errorf("Unexpected number of block roots, want: %v", 1)
} }
if len(stateRootsA) != len(stateRootsB) || len(stateRootsA) < 1 { if len(stateRootsA) != len(stateRootsB) || len(stateRootsA) < 1 {
t.Errorf("Unexpected number of state roots, want: %v", 1) t.Errorf("Unexpected number of state roots, want: %v", 1)
} }
assert.DeepEqual(t, root2[:], a.state.GetBlockRoots()[0], "Expected mutation not found") assert.DeepEqual(t, root2[:], a.BlockRoots()[0], "Expected mutation not found")
assert.DeepEqual(t, root2[:], a.state.GetStateRoots()[0], "Expected mutation not found") assert.DeepEqual(t, root2[:], a.StateRoots()[0], "Expected mutation not found")
assert.DeepEqual(t, root1[:], blockRootsB[0], "Unexpected mutation found") assert.DeepEqual(t, root1[:], blockRootsB[0], "Unexpected mutation found")
assert.DeepEqual(t, root1[:], stateRootsB[0], "Unexpected mutation found") assert.DeepEqual(t, root1[:], stateRootsB[0], "Unexpected mutation found")
@@ -114,7 +114,7 @@ func TestStateReferenceCopy_NoUnexpectedRootsMutation(t *testing.T) {
func TestStateReferenceCopy_NoUnexpectedRandaoMutation(t *testing.T) { func TestStateReferenceCopy_NoUnexpectedRandaoMutation(t *testing.T) {
val1, val2 := []byte("foo"), []byte("bar") val1, val2 := bytesutil.PadTo([]byte("foo"), 32), bytesutil.PadTo([]byte("bar"), 32)
a, err := InitializeFromProtoUnsafe(&ethpb.BeaconState{ a, err := InitializeFromProtoUnsafe(&ethpb.BeaconState{
RandaoMixes: [][]byte{ RandaoMixes: [][]byte{
val1, val1,
@@ -129,11 +129,10 @@ func TestStateReferenceCopy_NoUnexpectedRandaoMutation(t *testing.T) {
require.Equal(t, true, ok) require.Equal(t, true, ok)
assertRefCount(t, a, randaoMixes, 2) assertRefCount(t, a, randaoMixes, 2)
assertRefCount(t, b, randaoMixes, 2) assertRefCount(t, b, randaoMixes, 2)
assert.Equal(t, 1, len(b.state.GetRandaoMixes()), "No randao mixes found")
// Assert shared state. // Assert shared state.
mixesA := a.state.GetRandaoMixes() mixesA := a.RandaoMixes()
mixesB := b.state.GetRandaoMixes() mixesB := b.RandaoMixes()
if len(mixesA) != len(mixesB) || len(mixesA) < 1 { if len(mixesA) != len(mixesB) || len(mixesA) < 1 {
t.Errorf("Unexpected number of mix values, want: %v", 1) t.Errorf("Unexpected number of mix values, want: %v", 1)
} }
@@ -147,13 +146,13 @@ func TestStateReferenceCopy_NoUnexpectedRandaoMutation(t *testing.T) {
if len(mixesA) != len(mixesB) || len(mixesA) < 1 { if len(mixesA) != len(mixesB) || len(mixesA) < 1 {
t.Errorf("Unexpected number of mix values, want: %v", 1) t.Errorf("Unexpected number of mix values, want: %v", 1)
} }
assertValFound(t, a.state.GetRandaoMixes(), val2) assertValFound(t, a.RandaoMixes(), val2)
assertValNotFound(t, a.state.GetRandaoMixes(), val1) assertValNotFound(t, a.RandaoMixes(), val1)
assertValFound(t, b.state.GetRandaoMixes(), val1) assertValFound(t, b.RandaoMixes(), val1)
assertValNotFound(t, b.state.GetRandaoMixes(), val2) assertValNotFound(t, b.RandaoMixes(), val2)
assertValFound(t, mixesB, val1) assertValFound(t, mixesB, val1)
assertValNotFound(t, mixesB, val2) assertValNotFound(t, mixesB, val2)
assert.DeepEqual(t, val2, a.state.GetRandaoMixes()[0], "Expected mutation not found") assert.DeepEqual(t, val2, a.RandaoMixes()[0], "Expected mutation not found")
assert.DeepEqual(t, val1, mixesB[0], "Unexpected mutation found") assert.DeepEqual(t, val1, mixesB[0], "Unexpected mutation found")
// Copy on write happened, reference counters are reset. // Copy on write happened, reference counters are reset.
@@ -208,14 +207,26 @@ func TestStateReferenceCopy_NoUnexpectedAttestationsMutation(t *testing.T) {
assertRefCount(t, a, currentEpochAttestations, 2) assertRefCount(t, a, currentEpochAttestations, 2)
assertRefCount(t, b, previousEpochAttestations, 2) assertRefCount(t, b, previousEpochAttestations, 2)
assertRefCount(t, b, currentEpochAttestations, 2) assertRefCount(t, b, currentEpochAttestations, 2)
assert.Equal(t, 1, len(b.state.GetPreviousEpochAttestations()), "Unexpected number of attestations") bPrevEpochAtts, err := b.PreviousEpochAttestations()
assert.Equal(t, 1, len(b.state.GetCurrentEpochAttestations()), "Unexpected number of attestations") require.NoError(t, err)
bCurrEpochAtts, err := b.CurrentEpochAttestations()
require.NoError(t, err)
assert.Equal(t, 1, len(bPrevEpochAtts), "Unexpected number of attestations")
assert.Equal(t, 1, len(bCurrEpochAtts), "Unexpected number of attestations")
// Assert shared state. // Assert shared state.
curAttsA := a.state.GetCurrentEpochAttestations() aCurrEpochAtts, err := a.CurrentEpochAttestations()
prevAttsA := a.state.GetPreviousEpochAttestations() require.NoError(t, err)
curAttsB := b.state.GetCurrentEpochAttestations() curAttsA := aCurrEpochAtts
prevAttsB := b.state.GetPreviousEpochAttestations() aPrevEpochAtts, err := a.PreviousEpochAttestations()
require.NoError(t, err)
prevAttsA := aPrevEpochAtts
bCurrEpochAtts, err = b.CurrentEpochAttestations()
require.NoError(t, err)
curAttsB := bCurrEpochAtts
bPrevEpochAtts, err = b.PreviousEpochAttestations()
require.NoError(t, err)
prevAttsB := bPrevEpochAtts
if len(curAttsA) != len(curAttsB) || len(curAttsA) < 1 { if len(curAttsA) != len(curAttsB) || len(curAttsA) < 1 {
t.Errorf("Unexpected number of attestations, want: %v", 1) t.Errorf("Unexpected number of attestations, want: %v", 1)
} }
@@ -236,52 +247,72 @@ func TestStateReferenceCopy_NoUnexpectedAttestationsMutation(t *testing.T) {
preAtt, err = a.PreviousEpochAttestations() preAtt, err = a.PreviousEpochAttestations()
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, 2, len(preAtt), "Unexpected number of attestations") assert.Equal(t, 2, len(preAtt), "Unexpected number of attestations")
assertAttFound(a.state.GetCurrentEpochAttestations(), 1) aCurrEpochAtts, err = a.CurrentEpochAttestations()
assertAttFound(a.state.GetPreviousEpochAttestations(), 1) require.NoError(t, err)
assertAttFound(a.state.GetCurrentEpochAttestations(), 2) aPrevEpochAtts, err = a.PreviousEpochAttestations()
assertAttFound(a.state.GetPreviousEpochAttestations(), 2) require.NoError(t, err)
assertAttFound(b.state.GetCurrentEpochAttestations(), 1) bCurrEpochAtts, err = b.CurrentEpochAttestations()
assertAttFound(b.state.GetPreviousEpochAttestations(), 1) require.NoError(t, err)
assertAttNotFound(b.state.GetCurrentEpochAttestations(), 2) bPrevEpochAtts, err = b.PreviousEpochAttestations()
assertAttNotFound(b.state.GetPreviousEpochAttestations(), 2) require.NoError(t, err)
assertAttFound(aCurrEpochAtts, 1)
assertAttFound(aPrevEpochAtts, 1)
assertAttFound(aCurrEpochAtts, 2)
assertAttFound(aPrevEpochAtts, 2)
assertAttFound(bCurrEpochAtts, 1)
assertAttFound(bPrevEpochAtts, 1)
assertAttNotFound(bCurrEpochAtts, 2)
assertAttNotFound(bPrevEpochAtts, 2)
// Mutator should only affect calling state: a. // Mutator should only affect calling state: a.
applyToEveryAttestation := func(state *ethpb.BeaconState) { applyToEveryAttestation := func(state *BeaconState) {
// One MUST copy on write. // One MUST copy on write.
atts = make([]*ethpb.PendingAttestation, len(state.CurrentEpochAttestations)) atts = make([]*ethpb.PendingAttestation, len(state.currentEpochAttestations))
copy(atts, state.CurrentEpochAttestations) copy(atts, state.currentEpochAttestations)
state.CurrentEpochAttestations = atts state.currentEpochAttestations = atts
for i := range state.GetCurrentEpochAttestations() { currEpochAtts, err := state.CurrentEpochAttestations()
att := ethpb.CopyPendingAttestation(state.CurrentEpochAttestations[i]) require.NoError(t, err)
for i := range currEpochAtts {
att := ethpb.CopyPendingAttestation(state.currentEpochAttestations[i])
att.AggregationBits = bitfield.NewBitlist(3) att.AggregationBits = bitfield.NewBitlist(3)
state.CurrentEpochAttestations[i] = att state.currentEpochAttestations[i] = att
} }
atts = make([]*ethpb.PendingAttestation, len(state.PreviousEpochAttestations)) atts = make([]*ethpb.PendingAttestation, len(state.previousEpochAttestations))
copy(atts, state.PreviousEpochAttestations) copy(atts, state.previousEpochAttestations)
state.PreviousEpochAttestations = atts state.previousEpochAttestations = atts
for i := range state.GetPreviousEpochAttestations() { prevEpochAtts, err := state.PreviousEpochAttestations()
att := ethpb.CopyPendingAttestation(state.PreviousEpochAttestations[i]) require.NoError(t, err)
for i := range prevEpochAtts {
att := ethpb.CopyPendingAttestation(state.previousEpochAttestations[i])
att.AggregationBits = bitfield.NewBitlist(3) att.AggregationBits = bitfield.NewBitlist(3)
state.PreviousEpochAttestations[i] = att state.previousEpochAttestations[i] = att
} }
} }
applyToEveryAttestation(a.state) applyToEveryAttestation(a)
aCurrEpochAtts, err = a.CurrentEpochAttestations()
require.NoError(t, err)
aPrevEpochAtts, err = a.PreviousEpochAttestations()
require.NoError(t, err)
bCurrEpochAtts, err = b.CurrentEpochAttestations()
require.NoError(t, err)
bPrevEpochAtts, err = b.PreviousEpochAttestations()
require.NoError(t, err)
// Assert no shared state mutation occurred only on state a (copy on write). // Assert no shared state mutation occurred only on state a (copy on write).
assertAttFound(a.state.GetCurrentEpochAttestations(), 3) assertAttFound(aCurrEpochAtts, 3)
assertAttFound(a.state.GetPreviousEpochAttestations(), 3) assertAttFound(aPrevEpochAtts, 3)
assertAttNotFound(a.state.GetCurrentEpochAttestations(), 1) assertAttNotFound(aCurrEpochAtts, 1)
assertAttNotFound(a.state.GetPreviousEpochAttestations(), 1) assertAttNotFound(aPrevEpochAtts, 1)
assertAttNotFound(a.state.GetCurrentEpochAttestations(), 2) assertAttNotFound(aCurrEpochAtts, 2)
assertAttNotFound(a.state.GetPreviousEpochAttestations(), 2) assertAttNotFound(aPrevEpochAtts, 2)
// State b must be unaffected. // State b must be unaffected.
assertAttNotFound(b.state.GetCurrentEpochAttestations(), 3) assertAttNotFound(bCurrEpochAtts, 3)
assertAttNotFound(b.state.GetPreviousEpochAttestations(), 3) assertAttNotFound(bPrevEpochAtts, 3)
assertAttFound(b.state.GetCurrentEpochAttestations(), 1) assertAttFound(bCurrEpochAtts, 1)
assertAttFound(b.state.GetPreviousEpochAttestations(), 1) assertAttFound(bPrevEpochAtts, 1)
assertAttNotFound(b.state.GetCurrentEpochAttestations(), 2) assertAttNotFound(bCurrEpochAtts, 2)
assertAttNotFound(b.state.GetPreviousEpochAttestations(), 2) assertAttNotFound(bPrevEpochAtts, 2)
// Copy on write happened, reference counters are reset. // Copy on write happened, reference counters are reset.
assertRefCount(t, a, currentEpochAttestations, 1) assertRefCount(t, a, currentEpochAttestations, 1)
@@ -310,7 +341,7 @@ func TestValidatorReferences_RemainsConsistent(t *testing.T) {
// Update First Validator. // Update First Validator.
assert.NoError(t, a.UpdateValidatorAtIndex(0, &ethpb.Validator{PublicKey: []byte{'Z'}})) assert.NoError(t, a.UpdateValidatorAtIndex(0, &ethpb.Validator{PublicKey: []byte{'Z'}}))
assert.DeepNotEqual(t, a.state.Validators[0], b.state.Validators[0], "validators are equal when they are supposed to be different") assert.DeepNotEqual(t, a.Validators()[0], b.Validators()[0], "validators are equal when they are supposed to be different")
// Modify all validators from copied state. // Modify all validators from copied state.
assert.NoError(t, b.ApplyToEveryValidator(func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error) { assert.NoError(t, b.ApplyToEveryValidator(func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error) {
return true, &ethpb.Validator{PublicKey: []byte{'V'}}, nil return true, &ethpb.Validator{PublicKey: []byte{'V'}}, nil

View File

@@ -11,13 +11,10 @@ import (
// RotateAttestations sets the previous epoch attestations to the current epoch attestations and // RotateAttestations sets the previous epoch attestations to the current epoch attestations and
// then clears the current epoch attestations. // then clears the current epoch attestations.
func (b *BeaconState) RotateAttestations() error { func (b *BeaconState) RotateAttestations() error {
if !b.hasInnerState() {
return ErrNilInnerState
}
b.lock.Lock() b.lock.Lock()
defer b.lock.Unlock() defer b.lock.Unlock()
b.setPreviousEpochAttestations(b.currentEpochAttestations()) b.setPreviousEpochAttestations(b.currentEpochAttestationsVal())
b.setCurrentEpochAttestations([]*ethpb.PendingAttestation{}) b.setCurrentEpochAttestations([]*ethpb.PendingAttestation{})
return nil return nil
} }
@@ -26,7 +23,7 @@ func (b *BeaconState) setPreviousEpochAttestations(val []*ethpb.PendingAttestati
b.sharedFieldReferences[previousEpochAttestations].MinusRef() b.sharedFieldReferences[previousEpochAttestations].MinusRef()
b.sharedFieldReferences[previousEpochAttestations] = stateutil.NewRef(1) b.sharedFieldReferences[previousEpochAttestations] = stateutil.NewRef(1)
b.state.PreviousEpochAttestations = val b.previousEpochAttestations = val
b.markFieldAsDirty(previousEpochAttestations) b.markFieldAsDirty(previousEpochAttestations)
b.rebuildTrie[previousEpochAttestations] = true b.rebuildTrie[previousEpochAttestations] = true
} }
@@ -35,7 +32,7 @@ func (b *BeaconState) setCurrentEpochAttestations(val []*ethpb.PendingAttestatio
b.sharedFieldReferences[currentEpochAttestations].MinusRef() b.sharedFieldReferences[currentEpochAttestations].MinusRef()
b.sharedFieldReferences[currentEpochAttestations] = stateutil.NewRef(1) b.sharedFieldReferences[currentEpochAttestations] = stateutil.NewRef(1)
b.state.CurrentEpochAttestations = val b.currentEpochAttestations = val
b.markFieldAsDirty(currentEpochAttestations) b.markFieldAsDirty(currentEpochAttestations)
b.rebuildTrie[currentEpochAttestations] = true b.rebuildTrie[currentEpochAttestations] = true
} }
@@ -43,13 +40,10 @@ func (b *BeaconState) setCurrentEpochAttestations(val []*ethpb.PendingAttestatio
// AppendCurrentEpochAttestations for the beacon state. Appends the new value // AppendCurrentEpochAttestations for the beacon state. Appends the new value
// to the the end of list. // to the the end of list.
func (b *BeaconState) AppendCurrentEpochAttestations(val *ethpb.PendingAttestation) error { func (b *BeaconState) AppendCurrentEpochAttestations(val *ethpb.PendingAttestation) error {
if !b.hasInnerState() {
return ErrNilInnerState
}
b.lock.Lock() b.lock.Lock()
defer b.lock.Unlock() defer b.lock.Unlock()
atts := b.state.CurrentEpochAttestations atts := b.currentEpochAttestations
max := uint64(fieldparams.CurrentEpochAttestationsLength) max := uint64(fieldparams.CurrentEpochAttestationsLength)
if uint64(len(atts)) >= max { if uint64(len(atts)) >= max {
return fmt.Errorf("current pending attestation exceeds max length %d", max) return fmt.Errorf("current pending attestation exceeds max length %d", max)
@@ -57,42 +51,39 @@ func (b *BeaconState) AppendCurrentEpochAttestations(val *ethpb.PendingAttestati
if b.sharedFieldReferences[currentEpochAttestations].Refs() > 1 { if b.sharedFieldReferences[currentEpochAttestations].Refs() > 1 {
// Copy elements in underlying array by reference. // Copy elements in underlying array by reference.
atts = make([]*ethpb.PendingAttestation, len(b.state.CurrentEpochAttestations)) atts = make([]*ethpb.PendingAttestation, len(b.currentEpochAttestations))
copy(atts, b.state.CurrentEpochAttestations) copy(atts, b.currentEpochAttestations)
b.sharedFieldReferences[currentEpochAttestations].MinusRef() b.sharedFieldReferences[currentEpochAttestations].MinusRef()
b.sharedFieldReferences[currentEpochAttestations] = stateutil.NewRef(1) b.sharedFieldReferences[currentEpochAttestations] = stateutil.NewRef(1)
} }
b.state.CurrentEpochAttestations = append(atts, val) b.currentEpochAttestations = append(atts, val)
b.markFieldAsDirty(currentEpochAttestations) b.markFieldAsDirty(currentEpochAttestations)
b.addDirtyIndices(currentEpochAttestations, []uint64{uint64(len(b.state.CurrentEpochAttestations) - 1)}) b.addDirtyIndices(currentEpochAttestations, []uint64{uint64(len(b.currentEpochAttestations) - 1)})
return nil return nil
} }
// AppendPreviousEpochAttestations for the beacon state. Appends the new value // AppendPreviousEpochAttestations for the beacon state. Appends the new value
// to the the end of list. // to the the end of list.
func (b *BeaconState) AppendPreviousEpochAttestations(val *ethpb.PendingAttestation) error { func (b *BeaconState) AppendPreviousEpochAttestations(val *ethpb.PendingAttestation) error {
if !b.hasInnerState() {
return ErrNilInnerState
}
b.lock.Lock() b.lock.Lock()
defer b.lock.Unlock() defer b.lock.Unlock()
atts := b.state.PreviousEpochAttestations atts := b.previousEpochAttestations
max := uint64(fieldparams.PreviousEpochAttestationsLength) max := uint64(fieldparams.PreviousEpochAttestationsLength)
if uint64(len(atts)) >= max { if uint64(len(atts)) >= max {
return fmt.Errorf("previous pending attestation exceeds max length %d", max) return fmt.Errorf("previous pending attestation exceeds max length %d", max)
} }
if b.sharedFieldReferences[previousEpochAttestations].Refs() > 1 { if b.sharedFieldReferences[previousEpochAttestations].Refs() > 1 {
atts = make([]*ethpb.PendingAttestation, len(b.state.PreviousEpochAttestations)) atts = make([]*ethpb.PendingAttestation, len(b.previousEpochAttestations))
copy(atts, b.state.PreviousEpochAttestations) copy(atts, b.previousEpochAttestations)
b.sharedFieldReferences[previousEpochAttestations].MinusRef() b.sharedFieldReferences[previousEpochAttestations].MinusRef()
b.sharedFieldReferences[previousEpochAttestations] = stateutil.NewRef(1) b.sharedFieldReferences[previousEpochAttestations] = stateutil.NewRef(1)
} }
b.state.PreviousEpochAttestations = append(atts, val) b.previousEpochAttestations = append(atts, val)
b.markFieldAsDirty(previousEpochAttestations) b.markFieldAsDirty(previousEpochAttestations)
b.addDirtyIndices(previousEpochAttestations, []uint64{uint64(len(b.state.PreviousEpochAttestations) - 1)}) b.addDirtyIndices(previousEpochAttestations, []uint64{uint64(len(b.previousEpochAttestations) - 1)})
return nil return nil
} }

View File

@@ -1,14 +1,10 @@
package v1 package v1
import ( import (
"context"
"testing" "testing"
types "github.com/prysmaticlabs/eth2-types" types "github.com/prysmaticlabs/eth2-types"
stateTypes "github.com/prysmaticlabs/prysm/beacon-chain/state/types"
"github.com/prysmaticlabs/prysm/config/params"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/testing/assert"
"github.com/prysmaticlabs/prysm/testing/require" "github.com/prysmaticlabs/prysm/testing/require"
) )
@@ -21,52 +17,6 @@ func TestBeaconState_RotateAttestations(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, st.RotateAttestations()) require.NoError(t, st.RotateAttestations())
require.Equal(t, 0, len(st.currentEpochAttestations())) require.Equal(t, 0, len(st.currentEpochAttestationsVal()))
require.Equal(t, types.Slot(456), st.previousEpochAttestations()[0].Data.Slot) require.Equal(t, types.Slot(456), st.previousEpochAttestationsVal()[0].Data.Slot)
}
func TestAppendBeyondIndicesLimit(t *testing.T) {
zeroHash := params.BeaconConfig().ZeroHash
mockblockRoots := make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot)
for i := 0; i < len(mockblockRoots); i++ {
mockblockRoots[i] = zeroHash[:]
}
mockstateRoots := make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot)
for i := 0; i < len(mockstateRoots); i++ {
mockstateRoots[i] = zeroHash[:]
}
mockrandaoMixes := make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector)
for i := 0; i < len(mockrandaoMixes); i++ {
mockrandaoMixes[i] = zeroHash[:]
}
st, err := InitializeFromProto(&ethpb.BeaconState{
Slot: 1,
CurrentEpochAttestations: []*ethpb.PendingAttestation{{Data: &ethpb.AttestationData{Slot: 456}}},
PreviousEpochAttestations: []*ethpb.PendingAttestation{{Data: &ethpb.AttestationData{Slot: 123}}},
Validators: []*ethpb.Validator{},
Eth1Data: &ethpb.Eth1Data{},
BlockRoots: mockblockRoots,
StateRoots: mockstateRoots,
RandaoMixes: mockrandaoMixes,
})
require.NoError(t, err)
_, err = st.HashTreeRoot(context.Background())
require.NoError(t, err)
for i := stateTypes.FieldIndex(0); i < stateTypes.FieldIndex(params.BeaconConfig().BeaconStateFieldCount); i++ {
st.dirtyFields[i] = true
}
_, err = st.HashTreeRoot(context.Background())
require.NoError(t, err)
for i := 0; i < 10; i++ {
assert.NoError(t, st.AppendValidator(&ethpb.Validator{}))
}
assert.Equal(t, false, st.rebuildTrie[validators])
assert.NotEqual(t, len(st.dirtyIndices[validators]), 0)
for i := 0; i < indicesLimit; i++ {
assert.NoError(t, st.AppendValidator(&ethpb.Validator{}))
}
assert.Equal(t, true, st.rebuildTrie[validators])
assert.Equal(t, len(st.dirtyIndices[validators]), 0)
} }

View File

@@ -3,19 +3,18 @@ package v1
import ( import (
"fmt" "fmt"
customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
) )
// SetLatestBlockHeader in the beacon state. // SetLatestBlockHeader in the beacon state.
func (b *BeaconState) SetLatestBlockHeader(val *ethpb.BeaconBlockHeader) error { func (b *BeaconState) SetLatestBlockHeader(val *ethpb.BeaconBlockHeader) error {
if !b.hasInnerState() {
return ErrNilInnerState
}
b.lock.Lock() b.lock.Lock()
defer b.lock.Unlock() defer b.lock.Unlock()
b.state.LatestBlockHeader = ethpb.CopyBeaconBlockHeader(val) b.latestBlockHeader = ethpb.CopyBeaconBlockHeader(val)
b.markFieldAsDirty(latestBlockHeader) b.markFieldAsDirty(latestBlockHeader)
return nil return nil
} }
@@ -23,16 +22,18 @@ func (b *BeaconState) SetLatestBlockHeader(val *ethpb.BeaconBlockHeader) error {
// SetBlockRoots for the beacon state. Updates the entire // SetBlockRoots for the beacon state. Updates the entire
// list to a new value by overwriting the previous one. // list to a new value by overwriting the previous one.
func (b *BeaconState) SetBlockRoots(val [][]byte) error { func (b *BeaconState) SetBlockRoots(val [][]byte) error {
if !b.hasInnerState() {
return ErrNilInnerState
}
b.lock.Lock() b.lock.Lock()
defer b.lock.Unlock() defer b.lock.Unlock()
b.sharedFieldReferences[blockRoots].MinusRef() b.sharedFieldReferences[blockRoots].MinusRef()
b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1) b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1)
b.state.BlockRoots = val var rootsArr [fieldparams.BlockRootsLength][32]byte
for i := 0; i < len(rootsArr); i++ {
copy(rootsArr[i][:], val[i])
}
roots := customtypes.BlockRoots(rootsArr)
b.blockRoots = &roots
b.markFieldAsDirty(blockRoots) b.markFieldAsDirty(blockRoots)
b.rebuildTrie[blockRoots] = true b.rebuildTrie[blockRoots] = true
return nil return nil
@@ -41,26 +42,24 @@ func (b *BeaconState) SetBlockRoots(val [][]byte) error {
// UpdateBlockRootAtIndex for the beacon state. Updates the block root // UpdateBlockRootAtIndex for the beacon state. Updates the block root
// at a specific index to a new value. // at a specific index to a new value.
func (b *BeaconState) UpdateBlockRootAtIndex(idx uint64, blockRoot [32]byte) error { func (b *BeaconState) UpdateBlockRootAtIndex(idx uint64, blockRoot [32]byte) error {
if !b.hasInnerState() { if uint64(len(b.blockRoots)) <= idx {
return ErrNilInnerState
}
if uint64(len(b.state.BlockRoots)) <= idx {
return fmt.Errorf("invalid index provided %d", idx) return fmt.Errorf("invalid index provided %d", idx)
} }
b.lock.Lock() b.lock.Lock()
defer b.lock.Unlock() defer b.lock.Unlock()
r := b.state.BlockRoots r := b.blockRoots
if ref := b.sharedFieldReferences[blockRoots]; ref.Refs() > 1 { if ref := b.sharedFieldReferences[blockRoots]; ref.Refs() > 1 {
// Copy elements in underlying array by reference. // Copy elements in underlying array by reference.
r = make([][]byte, len(b.state.BlockRoots)) roots := *b.blockRoots
copy(r, b.state.BlockRoots) rootsCopy := roots
r = &rootsCopy
ref.MinusRef() ref.MinusRef()
b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1) b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1)
} }
r[idx] = blockRoot[:] r[idx] = blockRoot
b.state.BlockRoots = r b.blockRoots = r
b.markFieldAsDirty(blockRoots) b.markFieldAsDirty(blockRoots)
b.addDirtyIndices(blockRoots, []uint64{idx}) b.addDirtyIndices(blockRoots, []uint64{idx})

View File

@@ -7,52 +7,40 @@ import (
// SetJustificationBits for the beacon state. // SetJustificationBits for the beacon state.
func (b *BeaconState) SetJustificationBits(val bitfield.Bitvector4) error { func (b *BeaconState) SetJustificationBits(val bitfield.Bitvector4) error {
if !b.hasInnerState() {
return ErrNilInnerState
}
b.lock.Lock() b.lock.Lock()
defer b.lock.Unlock() defer b.lock.Unlock()
b.state.JustificationBits = val b.justificationBits = val
b.markFieldAsDirty(justificationBits) b.markFieldAsDirty(justificationBits)
return nil return nil
} }
// SetPreviousJustifiedCheckpoint for the beacon state. // SetPreviousJustifiedCheckpoint for the beacon state.
func (b *BeaconState) SetPreviousJustifiedCheckpoint(val *ethpb.Checkpoint) error { func (b *BeaconState) SetPreviousJustifiedCheckpoint(val *ethpb.Checkpoint) error {
if !b.hasInnerState() {
return ErrNilInnerState
}
b.lock.Lock() b.lock.Lock()
defer b.lock.Unlock() defer b.lock.Unlock()
b.state.PreviousJustifiedCheckpoint = val b.previousJustifiedCheckpoint = val
b.markFieldAsDirty(previousJustifiedCheckpoint) b.markFieldAsDirty(previousJustifiedCheckpoint)
return nil return nil
} }
// SetCurrentJustifiedCheckpoint for the beacon state. // SetCurrentJustifiedCheckpoint for the beacon state.
func (b *BeaconState) SetCurrentJustifiedCheckpoint(val *ethpb.Checkpoint) error { func (b *BeaconState) SetCurrentJustifiedCheckpoint(val *ethpb.Checkpoint) error {
if !b.hasInnerState() {
return ErrNilInnerState
}
b.lock.Lock() b.lock.Lock()
defer b.lock.Unlock() defer b.lock.Unlock()
b.state.CurrentJustifiedCheckpoint = val b.currentJustifiedCheckpoint = val
b.markFieldAsDirty(currentJustifiedCheckpoint) b.markFieldAsDirty(currentJustifiedCheckpoint)
return nil return nil
} }
// SetFinalizedCheckpoint for the beacon state. // SetFinalizedCheckpoint for the beacon state.
func (b *BeaconState) SetFinalizedCheckpoint(val *ethpb.Checkpoint) error { func (b *BeaconState) SetFinalizedCheckpoint(val *ethpb.Checkpoint) error {
if !b.hasInnerState() {
return ErrNilInnerState
}
b.lock.Lock() b.lock.Lock()
defer b.lock.Unlock() defer b.lock.Unlock()
b.state.FinalizedCheckpoint = val b.finalizedCheckpoint = val
b.markFieldAsDirty(finalizedCheckpoint) b.markFieldAsDirty(finalizedCheckpoint)
return nil return nil
} }

View File

@@ -7,13 +7,10 @@ import (
// SetEth1Data for the beacon state. // SetEth1Data for the beacon state.
func (b *BeaconState) SetEth1Data(val *ethpb.Eth1Data) error { func (b *BeaconState) SetEth1Data(val *ethpb.Eth1Data) error {
if !b.hasInnerState() {
return ErrNilInnerState
}
b.lock.Lock() b.lock.Lock()
defer b.lock.Unlock() defer b.lock.Unlock()
b.state.Eth1Data = val b.eth1Data = val
b.markFieldAsDirty(eth1Data) b.markFieldAsDirty(eth1Data)
return nil return nil
} }
@@ -21,16 +18,13 @@ func (b *BeaconState) SetEth1Data(val *ethpb.Eth1Data) error {
// SetEth1DataVotes for the beacon state. Updates the entire // SetEth1DataVotes for the beacon state. Updates the entire
// list to a new value by overwriting the previous one. // list to a new value by overwriting the previous one.
func (b *BeaconState) SetEth1DataVotes(val []*ethpb.Eth1Data) error { func (b *BeaconState) SetEth1DataVotes(val []*ethpb.Eth1Data) error {
if !b.hasInnerState() {
return ErrNilInnerState
}
b.lock.Lock() b.lock.Lock()
defer b.lock.Unlock() defer b.lock.Unlock()
b.sharedFieldReferences[eth1DataVotes].MinusRef() b.sharedFieldReferences[eth1DataVotes].MinusRef()
b.sharedFieldReferences[eth1DataVotes] = stateutil.NewRef(1) b.sharedFieldReferences[eth1DataVotes] = stateutil.NewRef(1)
b.state.Eth1DataVotes = val b.eth1DataVotes = val
b.markFieldAsDirty(eth1DataVotes) b.markFieldAsDirty(eth1DataVotes)
b.rebuildTrie[eth1DataVotes] = true b.rebuildTrie[eth1DataVotes] = true
return nil return nil
@@ -38,13 +32,10 @@ func (b *BeaconState) SetEth1DataVotes(val []*ethpb.Eth1Data) error {
// SetEth1DepositIndex for the beacon state. // SetEth1DepositIndex for the beacon state.
func (b *BeaconState) SetEth1DepositIndex(val uint64) error { func (b *BeaconState) SetEth1DepositIndex(val uint64) error {
if !b.hasInnerState() {
return ErrNilInnerState
}
b.lock.Lock() b.lock.Lock()
defer b.lock.Unlock() defer b.lock.Unlock()
b.state.Eth1DepositIndex = val b.eth1DepositIndex = val
b.markFieldAsDirty(eth1DepositIndex) b.markFieldAsDirty(eth1DepositIndex)
return nil return nil
} }
@@ -52,23 +43,20 @@ func (b *BeaconState) SetEth1DepositIndex(val uint64) error {
// AppendEth1DataVotes for the beacon state. Appends the new value // AppendEth1DataVotes for the beacon state. Appends the new value
// to the the end of list. // to the the end of list.
func (b *BeaconState) AppendEth1DataVotes(val *ethpb.Eth1Data) error { func (b *BeaconState) AppendEth1DataVotes(val *ethpb.Eth1Data) error {
if !b.hasInnerState() {
return ErrNilInnerState
}
b.lock.Lock() b.lock.Lock()
defer b.lock.Unlock() defer b.lock.Unlock()
votes := b.state.Eth1DataVotes votes := b.eth1DataVotes
if b.sharedFieldReferences[eth1DataVotes].Refs() > 1 { if b.sharedFieldReferences[eth1DataVotes].Refs() > 1 {
// Copy elements in underlying array by reference. // Copy elements in underlying array by reference.
votes = make([]*ethpb.Eth1Data, len(b.state.Eth1DataVotes)) votes = make([]*ethpb.Eth1Data, len(b.eth1DataVotes))
copy(votes, b.state.Eth1DataVotes) copy(votes, b.eth1DataVotes)
b.sharedFieldReferences[eth1DataVotes].MinusRef() b.sharedFieldReferences[eth1DataVotes].MinusRef()
b.sharedFieldReferences[eth1DataVotes] = stateutil.NewRef(1) b.sharedFieldReferences[eth1DataVotes] = stateutil.NewRef(1)
} }
b.state.Eth1DataVotes = append(votes, val) b.eth1DataVotes = append(votes, val)
b.markFieldAsDirty(eth1DataVotes) b.markFieldAsDirty(eth1DataVotes)
b.addDirtyIndices(eth1DataVotes, []uint64{uint64(len(b.state.Eth1DataVotes) - 1)}) b.addDirtyIndices(eth1DataVotes, []uint64{uint64(len(b.eth1DataVotes) - 1)})
return nil return nil
} }

View File

@@ -6,7 +6,9 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
stateTypes "github.com/prysmaticlabs/prysm/beacon-chain/state/types" stateTypes "github.com/prysmaticlabs/prysm/beacon-chain/state/types"
"github.com/prysmaticlabs/prysm/config/features" "github.com/prysmaticlabs/prysm/config/features"
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
"github.com/prysmaticlabs/prysm/crypto/hash" "github.com/prysmaticlabs/prysm/crypto/hash"
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
) )
@@ -44,7 +46,7 @@ func (b *BeaconState) SetGenesisTime(val uint64) error {
b.lock.Lock() b.lock.Lock()
defer b.lock.Unlock() defer b.lock.Unlock()
b.state.GenesisTime = val b.genesisTime = val
b.markFieldAsDirty(genesisTime) b.markFieldAsDirty(genesisTime)
return nil return nil
} }
@@ -54,29 +56,26 @@ func (b *BeaconState) SetGenesisValidatorRoot(val []byte) error {
b.lock.Lock() b.lock.Lock()
defer b.lock.Unlock() defer b.lock.Unlock()
b.state.GenesisValidatorsRoot = val if len(val) != fieldparams.RootLength {
return errors.New("incorrect validator root length")
}
b.genesisValidatorsRoot = bytesutil.ToBytes32(val)
b.markFieldAsDirty(genesisValidatorRoot) b.markFieldAsDirty(genesisValidatorRoot)
return nil return nil
} }
// SetSlot for the beacon state. // SetSlot for the beacon state.
func (b *BeaconState) SetSlot(val types.Slot) error { func (b *BeaconState) SetSlot(val types.Slot) error {
if !b.hasInnerState() {
return ErrNilInnerState
}
b.lock.Lock() b.lock.Lock()
defer b.lock.Unlock() defer b.lock.Unlock()
b.state.Slot = val b.slot = val
b.markFieldAsDirty(slot) b.markFieldAsDirty(slot)
return nil return nil
} }
// SetFork version for the beacon chain. // SetFork version for the beacon chain.
func (b *BeaconState) SetFork(val *ethpb.Fork) error { func (b *BeaconState) SetFork(val *ethpb.Fork) error {
if !b.hasInnerState() {
return ErrNilInnerState
}
b.lock.Lock() b.lock.Lock()
defer b.lock.Unlock() defer b.lock.Unlock()
@@ -84,7 +83,7 @@ func (b *BeaconState) SetFork(val *ethpb.Fork) error {
if !ok { if !ok {
return errors.New("proto.Clone did not return a fork proto") return errors.New("proto.Clone did not return a fork proto")
} }
b.state.Fork = fk b.fork = fk
b.markFieldAsDirty(fork) b.markFieldAsDirty(fork)
return nil return nil
} }
@@ -92,16 +91,17 @@ func (b *BeaconState) SetFork(val *ethpb.Fork) error {
// SetHistoricalRoots for the beacon state. Updates the entire // SetHistoricalRoots for the beacon state. Updates the entire
// list to a new value by overwriting the previous one. // list to a new value by overwriting the previous one.
func (b *BeaconState) SetHistoricalRoots(val [][]byte) error { func (b *BeaconState) SetHistoricalRoots(val [][]byte) error {
if !b.hasInnerState() {
return ErrNilInnerState
}
b.lock.Lock() b.lock.Lock()
defer b.lock.Unlock() defer b.lock.Unlock()
b.sharedFieldReferences[historicalRoots].MinusRef() b.sharedFieldReferences[historicalRoots].MinusRef()
b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1) b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1)
b.state.HistoricalRoots = val roots := make([][32]byte, len(val))
for i, r := range val {
copy(roots[i][:], r)
}
b.historicalRoots = roots
b.markFieldAsDirty(historicalRoots) b.markFieldAsDirty(historicalRoots)
return nil return nil
} }
@@ -109,21 +109,18 @@ func (b *BeaconState) SetHistoricalRoots(val [][]byte) error {
// AppendHistoricalRoots for the beacon state. Appends the new value // AppendHistoricalRoots for the beacon state. Appends the new value
// to the the end of list. // to the the end of list.
func (b *BeaconState) AppendHistoricalRoots(root [32]byte) error { func (b *BeaconState) AppendHistoricalRoots(root [32]byte) error {
if !b.hasInnerState() {
return ErrNilInnerState
}
b.lock.Lock() b.lock.Lock()
defer b.lock.Unlock() defer b.lock.Unlock()
roots := b.state.HistoricalRoots roots := b.historicalRoots
if b.sharedFieldReferences[historicalRoots].Refs() > 1 { if b.sharedFieldReferences[historicalRoots].Refs() > 1 {
roots = make([][]byte, len(b.state.HistoricalRoots)) roots = make([][32]byte, len(b.historicalRoots))
copy(roots, b.state.HistoricalRoots) copy(roots, b.historicalRoots)
b.sharedFieldReferences[historicalRoots].MinusRef() b.sharedFieldReferences[historicalRoots].MinusRef()
b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1) b.sharedFieldReferences[historicalRoots] = stateutil.NewRef(1)
} }
b.state.HistoricalRoots = append(roots, root[:]) b.historicalRoots = append(roots, root)
b.markFieldAsDirty(historicalRoots) b.markFieldAsDirty(historicalRoots)
return nil return nil
} }

View File

@@ -2,22 +2,27 @@ package v1
import ( import (
"github.com/pkg/errors" "github.com/pkg/errors"
customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
) )
// SetRandaoMixes for the beacon state. Updates the entire // SetRandaoMixes for the beacon state. Updates the entire
// randao mixes to a new value by overwriting the previous one. // randao mixes to a new value by overwriting the previous one.
func (b *BeaconState) SetRandaoMixes(val [][]byte) error { func (b *BeaconState) SetRandaoMixes(val [][]byte) error {
if !b.hasInnerState() {
return ErrNilInnerState
}
b.lock.Lock() b.lock.Lock()
defer b.lock.Unlock() defer b.lock.Unlock()
b.sharedFieldReferences[randaoMixes].MinusRef() b.sharedFieldReferences[randaoMixes].MinusRef()
b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1) b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1)
b.state.RandaoMixes = val var mixesArr [fieldparams.RandaoMixesLength][32]byte
for i := 0; i < len(mixesArr); i++ {
copy(mixesArr[i][:], val[i])
}
mixes := customtypes.RandaoMixes(mixesArr)
b.randaoMixes = &mixes
b.markFieldAsDirty(randaoMixes) b.markFieldAsDirty(randaoMixes)
b.rebuildTrie[randaoMixes] = true b.rebuildTrie[randaoMixes] = true
return nil return nil
@@ -26,26 +31,24 @@ func (b *BeaconState) SetRandaoMixes(val [][]byte) error {
// UpdateRandaoMixesAtIndex for the beacon state. Updates the randao mixes // UpdateRandaoMixesAtIndex for the beacon state. Updates the randao mixes
// at a specific index to a new value. // at a specific index to a new value.
func (b *BeaconState) UpdateRandaoMixesAtIndex(idx uint64, val []byte) error { func (b *BeaconState) UpdateRandaoMixesAtIndex(idx uint64, val []byte) error {
if !b.hasInnerState() { if uint64(len(b.randaoMixes)) <= idx {
return ErrNilInnerState
}
if uint64(len(b.state.RandaoMixes)) <= idx {
return errors.Errorf("invalid index provided %d", idx) return errors.Errorf("invalid index provided %d", idx)
} }
b.lock.Lock() b.lock.Lock()
defer b.lock.Unlock() defer b.lock.Unlock()
mixes := b.state.RandaoMixes mixes := b.randaoMixes
if refs := b.sharedFieldReferences[randaoMixes].Refs(); refs > 1 { if refs := b.sharedFieldReferences[randaoMixes].Refs(); refs > 1 {
// Copy elements in underlying array by reference. // Copy elements in underlying array by reference.
mixes = make([][]byte, len(b.state.RandaoMixes)) m := *b.randaoMixes
copy(mixes, b.state.RandaoMixes) mCopy := m
mixes = &mCopy
b.sharedFieldReferences[randaoMixes].MinusRef() b.sharedFieldReferences[randaoMixes].MinusRef()
b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1) b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1)
} }
mixes[idx] = val mixes[idx] = bytesutil.ToBytes32(val)
b.state.RandaoMixes = mixes b.randaoMixes = mixes
b.markFieldAsDirty(randaoMixes) b.markFieldAsDirty(randaoMixes)
b.addDirtyIndices(randaoMixes, []uint64{idx}) b.addDirtyIndices(randaoMixes, []uint64{idx})

View File

@@ -2,22 +2,26 @@ package v1
import ( import (
"github.com/pkg/errors" "github.com/pkg/errors"
customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
) )
// SetStateRoots for the beacon state. Updates the state roots // SetStateRoots for the beacon state. Updates the state roots
// to a new value by overwriting the previous value. // to a new value by overwriting the previous value.
func (b *BeaconState) SetStateRoots(val [][]byte) error { func (b *BeaconState) SetStateRoots(val [][]byte) error {
if !b.hasInnerState() {
return ErrNilInnerState
}
b.lock.Lock() b.lock.Lock()
defer b.lock.Unlock() defer b.lock.Unlock()
b.sharedFieldReferences[stateRoots].MinusRef() b.sharedFieldReferences[stateRoots].MinusRef()
b.sharedFieldReferences[stateRoots] = stateutil.NewRef(1) b.sharedFieldReferences[stateRoots] = stateutil.NewRef(1)
b.state.StateRoots = val var rootsArr [fieldparams.StateRootsLength][32]byte
for i := 0; i < len(rootsArr); i++ {
copy(rootsArr[i][:], val[i])
}
roots := customtypes.StateRoots(rootsArr)
b.stateRoots = &roots
b.markFieldAsDirty(stateRoots) b.markFieldAsDirty(stateRoots)
b.rebuildTrie[stateRoots] = true b.rebuildTrie[stateRoots] = true
return nil return nil
@@ -26,12 +30,8 @@ func (b *BeaconState) SetStateRoots(val [][]byte) error {
// UpdateStateRootAtIndex for the beacon state. Updates the state root // UpdateStateRootAtIndex for the beacon state. Updates the state root
// at a specific index to a new value. // at a specific index to a new value.
func (b *BeaconState) UpdateStateRootAtIndex(idx uint64, stateRoot [32]byte) error { func (b *BeaconState) UpdateStateRootAtIndex(idx uint64, stateRoot [32]byte) error {
if !b.hasInnerState() {
return ErrNilInnerState
}
b.lock.RLock() b.lock.RLock()
if uint64(len(b.state.StateRoots)) <= idx { if uint64(len(b.stateRoots)) <= idx {
b.lock.RUnlock() b.lock.RUnlock()
return errors.Errorf("invalid index provided %d", idx) return errors.Errorf("invalid index provided %d", idx)
} }
@@ -41,17 +41,18 @@ func (b *BeaconState) UpdateStateRootAtIndex(idx uint64, stateRoot [32]byte) err
defer b.lock.Unlock() defer b.lock.Unlock()
// Check if we hold the only reference to the shared state roots slice. // Check if we hold the only reference to the shared state roots slice.
r := b.state.StateRoots r := b.stateRoots
if ref := b.sharedFieldReferences[stateRoots]; ref.Refs() > 1 { if ref := b.sharedFieldReferences[stateRoots]; ref.Refs() > 1 {
// Copy elements in underlying array by reference. // Copy elements in underlying array by reference.
r = make([][]byte, len(b.state.StateRoots)) roots := *b.stateRoots
copy(r, b.state.StateRoots) rootsCopy := roots
r = &rootsCopy
ref.MinusRef() ref.MinusRef()
b.sharedFieldReferences[stateRoots] = stateutil.NewRef(1) b.sharedFieldReferences[stateRoots] = stateutil.NewRef(1)
} }
r[idx] = stateRoot[:] r[idx] = stateRoot
b.state.StateRoots = r b.stateRoots = r
b.markFieldAsDirty(stateRoots) b.markFieldAsDirty(stateRoots)
b.addDirtyIndices(stateRoots, []uint64{idx}) b.addDirtyIndices(stateRoots, []uint64{idx})

View File

@@ -11,29 +11,23 @@ import (
// SetValidators for the beacon state. Updates the entire // SetValidators for the beacon state. Updates the entire
// to a new value by overwriting the previous one. // to a new value by overwriting the previous one.
func (b *BeaconState) SetValidators(val []*ethpb.Validator) error { func (b *BeaconState) SetValidators(val []*ethpb.Validator) error {
if !b.hasInnerState() {
return ErrNilInnerState
}
b.lock.Lock() b.lock.Lock()
defer b.lock.Unlock() defer b.lock.Unlock()
b.state.Validators = val b.validators = val
b.sharedFieldReferences[validators].MinusRef() b.sharedFieldReferences[validators].MinusRef()
b.sharedFieldReferences[validators] = stateutil.NewRef(1) b.sharedFieldReferences[validators] = stateutil.NewRef(1)
b.markFieldAsDirty(validators) b.markFieldAsDirty(validators)
b.rebuildTrie[validators] = true b.rebuildTrie[validators] = true
b.valMapHandler = stateutil.NewValMapHandler(b.state.Validators) b.valMapHandler = stateutil.NewValMapHandler(b.validators)
return nil return nil
} }
// ApplyToEveryValidator applies the provided callback function to each validator in the // ApplyToEveryValidator applies the provided callback function to each validator in the
// validator registry. // validator registry.
func (b *BeaconState) ApplyToEveryValidator(f func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error)) error { func (b *BeaconState) ApplyToEveryValidator(f func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error)) error {
if !b.hasInnerState() {
return ErrNilInnerState
}
b.lock.Lock() b.lock.Lock()
v := b.state.Validators v := b.validators
if ref := b.sharedFieldReferences[validators]; ref.Refs() > 1 { if ref := b.sharedFieldReferences[validators]; ref.Refs() > 1 {
v = b.validatorsReferences() v = b.validatorsReferences()
ref.MinusRef() ref.MinusRef()
@@ -55,7 +49,7 @@ func (b *BeaconState) ApplyToEveryValidator(f func(idx int, val *ethpb.Validator
b.lock.Lock() b.lock.Lock()
defer b.lock.Unlock() defer b.lock.Unlock()
b.state.Validators = v b.validators = v
b.markFieldAsDirty(validators) b.markFieldAsDirty(validators)
b.addDirtyIndices(validators, changedVals) b.addDirtyIndices(validators, changedVals)
@@ -65,16 +59,13 @@ func (b *BeaconState) ApplyToEveryValidator(f func(idx int, val *ethpb.Validator
// UpdateValidatorAtIndex for the beacon state. Updates the validator // UpdateValidatorAtIndex for the beacon state. Updates the validator
// at a specific index to a new value. // at a specific index to a new value.
func (b *BeaconState) UpdateValidatorAtIndex(idx types.ValidatorIndex, val *ethpb.Validator) error { func (b *BeaconState) UpdateValidatorAtIndex(idx types.ValidatorIndex, val *ethpb.Validator) error {
if !b.hasInnerState() { if uint64(len(b.validators)) <= uint64(idx) {
return ErrNilInnerState
}
if uint64(len(b.state.Validators)) <= uint64(idx) {
return errors.Errorf("invalid index provided %d", idx) return errors.Errorf("invalid index provided %d", idx)
} }
b.lock.Lock() b.lock.Lock()
defer b.lock.Unlock() defer b.lock.Unlock()
v := b.state.Validators v := b.validators
if ref := b.sharedFieldReferences[validators]; ref.Refs() > 1 { if ref := b.sharedFieldReferences[validators]; ref.Refs() > 1 {
v = b.validatorsReferences() v = b.validatorsReferences()
ref.MinusRef() ref.MinusRef()
@@ -82,7 +73,7 @@ func (b *BeaconState) UpdateValidatorAtIndex(idx types.ValidatorIndex, val *ethp
} }
v[idx] = val v[idx] = val
b.state.Validators = v b.validators = v
b.markFieldAsDirty(validators) b.markFieldAsDirty(validators)
b.addDirtyIndices(validators, []uint64{uint64(idx)}) b.addDirtyIndices(validators, []uint64{uint64(idx)})
@@ -92,16 +83,13 @@ func (b *BeaconState) UpdateValidatorAtIndex(idx types.ValidatorIndex, val *ethp
// SetBalances for the beacon state. Updates the entire // SetBalances for the beacon state. Updates the entire
// list to a new value by overwriting the previous one. // list to a new value by overwriting the previous one.
func (b *BeaconState) SetBalances(val []uint64) error { func (b *BeaconState) SetBalances(val []uint64) error {
if !b.hasInnerState() {
return ErrNilInnerState
}
b.lock.Lock() b.lock.Lock()
defer b.lock.Unlock() defer b.lock.Unlock()
b.sharedFieldReferences[balances].MinusRef() b.sharedFieldReferences[balances].MinusRef()
b.sharedFieldReferences[balances] = stateutil.NewRef(1) b.sharedFieldReferences[balances] = stateutil.NewRef(1)
b.state.Balances = val b.balances = val
b.markFieldAsDirty(balances) b.markFieldAsDirty(balances)
b.rebuildTrie[balances] = true b.rebuildTrie[balances] = true
return nil return nil
@@ -110,24 +98,21 @@ func (b *BeaconState) SetBalances(val []uint64) error {
// UpdateBalancesAtIndex for the beacon state. This method updates the balance // UpdateBalancesAtIndex for the beacon state. This method updates the balance
// at a specific index to a new value. // at a specific index to a new value.
func (b *BeaconState) UpdateBalancesAtIndex(idx types.ValidatorIndex, val uint64) error { func (b *BeaconState) UpdateBalancesAtIndex(idx types.ValidatorIndex, val uint64) error {
if !b.hasInnerState() { if uint64(len(b.balances)) <= uint64(idx) {
return ErrNilInnerState
}
if uint64(len(b.state.Balances)) <= uint64(idx) {
return errors.Errorf("invalid index provided %d", idx) return errors.Errorf("invalid index provided %d", idx)
} }
b.lock.Lock() b.lock.Lock()
defer b.lock.Unlock() defer b.lock.Unlock()
bals := b.state.Balances bals := b.balances
if b.sharedFieldReferences[balances].Refs() > 1 { if b.sharedFieldReferences[balances].Refs() > 1 {
bals = b.balances() bals = b.balancesVal()
b.sharedFieldReferences[balances].MinusRef() b.sharedFieldReferences[balances].MinusRef()
b.sharedFieldReferences[balances] = stateutil.NewRef(1) b.sharedFieldReferences[balances] = stateutil.NewRef(1)
} }
bals[idx] = val bals[idx] = val
b.state.Balances = bals b.balances = bals
b.markFieldAsDirty(balances) b.markFieldAsDirty(balances)
b.addDirtyIndices(balances, []uint64{uint64(idx)}) b.addDirtyIndices(balances, []uint64{uint64(idx)})
return nil return nil
@@ -136,16 +121,13 @@ func (b *BeaconState) UpdateBalancesAtIndex(idx types.ValidatorIndex, val uint64
// SetSlashings for the beacon state. Updates the entire // SetSlashings for the beacon state. Updates the entire
// list to a new value by overwriting the previous one. // list to a new value by overwriting the previous one.
func (b *BeaconState) SetSlashings(val []uint64) error { func (b *BeaconState) SetSlashings(val []uint64) error {
if !b.hasInnerState() {
return ErrNilInnerState
}
b.lock.Lock() b.lock.Lock()
defer b.lock.Unlock() defer b.lock.Unlock()
b.sharedFieldReferences[slashings].MinusRef() b.sharedFieldReferences[slashings].MinusRef()
b.sharedFieldReferences[slashings] = stateutil.NewRef(1) b.sharedFieldReferences[slashings] = stateutil.NewRef(1)
b.state.Slashings = val b.slashings = val
b.markFieldAsDirty(slashings) b.markFieldAsDirty(slashings)
return nil return nil
} }
@@ -153,25 +135,22 @@ func (b *BeaconState) SetSlashings(val []uint64) error {
// UpdateSlashingsAtIndex for the beacon state. Updates the slashings // UpdateSlashingsAtIndex for the beacon state. Updates the slashings
// at a specific index to a new value. // at a specific index to a new value.
func (b *BeaconState) UpdateSlashingsAtIndex(idx, val uint64) error { func (b *BeaconState) UpdateSlashingsAtIndex(idx, val uint64) error {
if !b.hasInnerState() { if uint64(len(b.slashings)) <= idx {
return ErrNilInnerState
}
if uint64(len(b.state.Slashings)) <= idx {
return errors.Errorf("invalid index provided %d", idx) return errors.Errorf("invalid index provided %d", idx)
} }
b.lock.Lock() b.lock.Lock()
defer b.lock.Unlock() defer b.lock.Unlock()
s := b.state.Slashings s := b.slashings
if b.sharedFieldReferences[slashings].Refs() > 1 { if b.sharedFieldReferences[slashings].Refs() > 1 {
s = b.slashings() s = b.slashingsVal()
b.sharedFieldReferences[slashings].MinusRef() b.sharedFieldReferences[slashings].MinusRef()
b.sharedFieldReferences[slashings] = stateutil.NewRef(1) b.sharedFieldReferences[slashings] = stateutil.NewRef(1)
} }
s[idx] = val s[idx] = val
b.state.Slashings = s b.slashings = s
b.markFieldAsDirty(slashings) b.markFieldAsDirty(slashings)
return nil return nil
@@ -180,13 +159,10 @@ func (b *BeaconState) UpdateSlashingsAtIndex(idx, val uint64) error {
// AppendValidator for the beacon state. Appends the new value // AppendValidator for the beacon state. Appends the new value
// to the the end of list. // to the the end of list.
func (b *BeaconState) AppendValidator(val *ethpb.Validator) error { func (b *BeaconState) AppendValidator(val *ethpb.Validator) error {
if !b.hasInnerState() {
return ErrNilInnerState
}
b.lock.Lock() b.lock.Lock()
defer b.lock.Unlock() defer b.lock.Unlock()
vals := b.state.Validators vals := b.validators
if b.sharedFieldReferences[validators].Refs() > 1 { if b.sharedFieldReferences[validators].Refs() > 1 {
vals = b.validatorsReferences() vals = b.validatorsReferences()
b.sharedFieldReferences[validators].MinusRef() b.sharedFieldReferences[validators].MinusRef()
@@ -194,8 +170,8 @@ func (b *BeaconState) AppendValidator(val *ethpb.Validator) error {
} }
// append validator to slice // append validator to slice
b.state.Validators = append(vals, val) b.validators = append(vals, val)
valIdx := types.ValidatorIndex(len(b.state.Validators) - 1) valIdx := types.ValidatorIndex(len(b.validators) - 1)
b.valMapHandler.Set(bytesutil.ToBytes48(val.PublicKey), valIdx) b.valMapHandler.Set(bytesutil.ToBytes48(val.PublicKey), valIdx)
@@ -207,21 +183,18 @@ func (b *BeaconState) AppendValidator(val *ethpb.Validator) error {
// AppendBalance for the beacon state. Appends the new value // AppendBalance for the beacon state. Appends the new value
// to the the end of list. // to the the end of list.
func (b *BeaconState) AppendBalance(bal uint64) error { func (b *BeaconState) AppendBalance(bal uint64) error {
if !b.hasInnerState() {
return ErrNilInnerState
}
b.lock.Lock() b.lock.Lock()
defer b.lock.Unlock() defer b.lock.Unlock()
bals := b.state.Balances bals := b.balances
if b.sharedFieldReferences[balances].Refs() > 1 { if b.sharedFieldReferences[balances].Refs() > 1 {
bals = b.balances() bals = b.balancesVal()
b.sharedFieldReferences[balances].MinusRef() b.sharedFieldReferences[balances].MinusRef()
b.sharedFieldReferences[balances] = stateutil.NewRef(1) b.sharedFieldReferences[balances] = stateutil.NewRef(1)
} }
b.state.Balances = append(bals, bal) b.balances = append(bals, bal)
balIdx := len(b.state.Balances) - 1 balIdx := len(b.balances) - 1
b.markFieldAsDirty(balances) b.markFieldAsDirty(balances)
b.addDirtyIndices(balances, []uint64{uint64(balIdx)}) b.addDirtyIndices(balances, []uint64{uint64(balIdx)})
return nil return nil

View File

@@ -101,12 +101,6 @@ func TestBeaconState_NoDeadlock(t *testing.T) {
func TestStateTrie_IsNil(t *testing.T) { func TestStateTrie_IsNil(t *testing.T) {
var emptyState *BeaconState var emptyState *BeaconState
assert.Equal(t, true, emptyState.IsNil()) assert.Equal(t, true, emptyState.IsNil())
emptyProto := &BeaconState{state: nil}
assert.Equal(t, true, emptyProto.IsNil())
nonNilState := &BeaconState{state: &ethpb.BeaconState{}}
assert.Equal(t, false, nonNilState.IsNil())
} }
func TestBeaconState_AppendBalanceWithTrie(t *testing.T) { func TestBeaconState_AppendBalanceWithTrie(t *testing.T) {
@@ -187,7 +181,7 @@ func TestBeaconState_AppendBalanceWithTrie(t *testing.T) {
_, err = st.HashTreeRoot(context.Background()) _, err = st.HashTreeRoot(context.Background())
assert.NoError(t, err) assert.NoError(t, err)
newRt := bytesutil.ToBytes32(st.merkleLayers[0][balances]) newRt := bytesutil.ToBytes32(st.merkleLayers[0][balances])
wantedRt, err := stateutil.Uint64ListRootWithRegistryLimit(st.state.Balances) wantedRt, err := stateutil.Uint64ListRootWithRegistryLimit(st.balances)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, wantedRt, newRt, "state roots are unequal") assert.Equal(t, wantedRt, newRt, "state roots are unequal")
} }

View File

@@ -6,7 +6,9 @@ import (
"sort" "sort"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/beacon-chain/state" "github.com/prysmaticlabs/prysm/beacon-chain/state"
customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types"
"github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/fieldtrie" "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/fieldtrie"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
"github.com/prysmaticlabs/prysm/beacon-chain/state/types" "github.com/prysmaticlabs/prysm/beacon-chain/state/types"
@@ -27,16 +29,54 @@ func InitializeFromProto(st *ethpb.BeaconState) (*BeaconState, error) {
return InitializeFromProtoUnsafe(proto.Clone(st).(*ethpb.BeaconState)) return InitializeFromProtoUnsafe(proto.Clone(st).(*ethpb.BeaconState))
} }
// InitializeFromProtoUnsafe directly uses the beacon state protobuf pointer // InitializeFromProtoUnsafe directly uses the beacon state protobuf fields
// and sets it as the inner state of the BeaconState type. // and sets them as fields of the BeaconState type.
func InitializeFromProtoUnsafe(st *ethpb.BeaconState) (*BeaconState, error) { func InitializeFromProtoUnsafe(st *ethpb.BeaconState) (*BeaconState, error) {
if st == nil { if st == nil {
return nil, errors.New("received nil state") return nil, errors.New("received nil state")
} }
var bRoots customtypes.BlockRoots
for i, r := range st.BlockRoots {
copy(bRoots[i][:], r)
}
var sRoots customtypes.StateRoots
for i, r := range st.StateRoots {
copy(sRoots[i][:], r)
}
hRoots := customtypes.HistoricalRoots(make([][32]byte, len(st.HistoricalRoots)))
for i, r := range st.HistoricalRoots {
copy(hRoots[i][:], r)
}
var mixes customtypes.RandaoMixes
for i, m := range st.RandaoMixes {
copy(mixes[i][:], m)
}
fieldCount := params.BeaconConfig().BeaconStateFieldCount fieldCount := params.BeaconConfig().BeaconStateFieldCount
b := &BeaconState{ b := &BeaconState{
state: st, genesisTime: st.GenesisTime,
genesisValidatorsRoot: bytesutil.ToBytes32(st.GenesisValidatorsRoot),
slot: st.Slot,
fork: st.Fork,
latestBlockHeader: st.LatestBlockHeader,
blockRoots: &bRoots,
stateRoots: &sRoots,
historicalRoots: hRoots,
eth1Data: st.Eth1Data,
eth1DataVotes: st.Eth1DataVotes,
eth1DepositIndex: st.Eth1DepositIndex,
validators: st.Validators,
balances: st.Balances,
randaoMixes: &mixes,
slashings: st.Slashings,
previousEpochAttestations: st.PreviousEpochAttestations,
currentEpochAttestations: st.CurrentEpochAttestations,
justificationBits: st.JustificationBits,
previousJustifiedCheckpoint: st.PreviousJustifiedCheckpoint,
currentJustifiedCheckpoint: st.CurrentJustifiedCheckpoint,
finalizedCheckpoint: st.FinalizedCheckpoint,
dirtyFields: make(map[types.FieldIndex]bool, fieldCount), dirtyFields: make(map[types.FieldIndex]bool, fieldCount),
dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount), dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount),
stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount), stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount),
@@ -74,44 +114,41 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconState) (*BeaconState, error) {
// Copy returns a deep copy of the beacon state. // Copy returns a deep copy of the beacon state.
func (b *BeaconState) Copy() state.BeaconState { func (b *BeaconState) Copy() state.BeaconState {
if !b.hasInnerState() {
return nil
}
b.lock.RLock() b.lock.RLock()
defer b.lock.RUnlock() defer b.lock.RUnlock()
fieldCount := params.BeaconConfig().BeaconStateFieldCount fieldCount := params.BeaconConfig().BeaconStateFieldCount
dst := &BeaconState{ dst := &BeaconState{
state: &ethpb.BeaconState{ // Primitive types, safe to copy.
// Primitive types, safe to copy. genesisTime: b.genesisTime,
GenesisTime: b.state.GenesisTime, slot: b.slot,
Slot: b.state.Slot, eth1DepositIndex: b.eth1DepositIndex,
Eth1DepositIndex: b.state.Eth1DepositIndex,
// Large arrays, infrequently changed, constant size. // Large arrays, infrequently changed, constant size.
RandaoMixes: b.state.RandaoMixes, slashings: b.slashings,
StateRoots: b.state.StateRoots,
BlockRoots: b.state.BlockRoots,
PreviousEpochAttestations: b.state.PreviousEpochAttestations,
CurrentEpochAttestations: b.state.CurrentEpochAttestations,
Slashings: b.state.Slashings,
Eth1DataVotes: b.state.Eth1DataVotes,
// Large arrays, increases over time. // Large arrays, infrequently changed, constant size.
Validators: b.state.Validators, blockRoots: b.blockRoots,
Balances: b.state.Balances, stateRoots: b.stateRoots,
HistoricalRoots: b.state.HistoricalRoots, randaoMixes: b.randaoMixes,
previousEpochAttestations: b.previousEpochAttestations,
currentEpochAttestations: b.currentEpochAttestations,
eth1DataVotes: b.eth1DataVotes,
// Large arrays, increases over time.
balances: b.balances,
historicalRoots: b.historicalRoots,
validators: b.validators,
// Everything else, too small to be concerned about, constant size.
genesisValidatorsRoot: b.genesisValidatorsRoot,
justificationBits: b.justificationBitsVal(),
fork: b.forkVal(),
latestBlockHeader: b.latestBlockHeaderVal(),
eth1Data: b.eth1DataVal(),
previousJustifiedCheckpoint: b.previousJustifiedCheckpointVal(),
currentJustifiedCheckpoint: b.currentJustifiedCheckpointVal(),
finalizedCheckpoint: b.finalizedCheckpointVal(),
// Everything else, too small to be concerned about, constant size.
Fork: b.fork(),
LatestBlockHeader: b.latestBlockHeader(),
Eth1Data: b.eth1Data(),
JustificationBits: b.justificationBits(),
PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint(),
CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint(),
FinalizedCheckpoint: b.finalizedCheckpoint(),
GenesisValidatorsRoot: b.genesisValidatorRoot(),
},
dirtyFields: make(map[types.FieldIndex]bool, fieldCount), dirtyFields: make(map[types.FieldIndex]bool, fieldCount),
dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount), dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount),
rebuildTrie: make(map[types.FieldIndex]bool, fieldCount), rebuildTrie: make(map[types.FieldIndex]bool, fieldCount),
@@ -210,7 +247,11 @@ func (b *BeaconState) initializeMerkleLayers(ctx context.Context) error {
if len(b.merkleLayers) > 0 { if len(b.merkleLayers) > 0 {
return nil return nil
} }
fieldRoots, err := computeFieldRoots(ctx, b.state) protoState, ok := b.ToProtoUnsafe().(*ethpb.BeaconState)
if !ok {
return errors.New("state is of the wrong type")
}
fieldRoots, err := computeFieldRoots(ctx, protoState)
if err != nil { if err != nil {
return err return err
} }
@@ -258,7 +299,7 @@ func (b *BeaconState) FieldReferencesCount() map[string]uint64 {
// IsNil checks if the state and the underlying proto // IsNil checks if the state and the underlying proto
// object are nil. // object are nil.
func (b *BeaconState) IsNil() bool { func (b *BeaconState) IsNil() bool {
return b == nil || b.state == nil return b == nil
} }
func (b *BeaconState) rootSelector(ctx context.Context, field types.FieldIndex) ([32]byte, error) { func (b *BeaconState) rootSelector(ctx context.Context, field types.FieldIndex) ([32]byte, error) {
@@ -269,46 +310,50 @@ func (b *BeaconState) rootSelector(ctx context.Context, field types.FieldIndex)
hasher := hash.CustomSHA256Hasher() hasher := hash.CustomSHA256Hasher()
switch field { switch field {
case genesisTime: case genesisTime:
return ssz.Uint64Root(b.state.GenesisTime), nil return ssz.Uint64Root(b.genesisTime), nil
case genesisValidatorRoot: case genesisValidatorRoot:
return bytesutil.ToBytes32(b.state.GenesisValidatorsRoot), nil return b.genesisValidatorsRoot, nil
case slot: case slot:
return ssz.Uint64Root(uint64(b.state.Slot)), nil return ssz.Uint64Root(uint64(b.slot)), nil
case eth1DepositIndex: case eth1DepositIndex:
return ssz.Uint64Root(b.state.Eth1DepositIndex), nil return ssz.Uint64Root(b.eth1DepositIndex), nil
case fork: case fork:
return ssz.ForkRoot(b.state.Fork) return ssz.ForkRoot(b.fork)
case latestBlockHeader: case latestBlockHeader:
return stateutil.BlockHeaderRoot(b.state.LatestBlockHeader) return stateutil.BlockHeaderRoot(b.latestBlockHeader)
case blockRoots: case blockRoots:
if b.rebuildTrie[field] { if b.rebuildTrie[field] {
err := b.resetFieldTrie(field, b.state.BlockRoots, fieldparams.BlockRootsLength) err := b.resetFieldTrie(field, b.blockRoots, fieldparams.BlockRootsLength)
if err != nil { if err != nil {
return [32]byte{}, err return [32]byte{}, err
} }
delete(b.rebuildTrie, field) delete(b.rebuildTrie, field)
return b.stateFieldLeaves[field].TrieRoot() return b.stateFieldLeaves[field].TrieRoot()
} }
return b.recomputeFieldTrie(blockRoots, b.state.BlockRoots) return b.recomputeFieldTrie(blockRoots, b.blockRoots)
case stateRoots: case stateRoots:
if b.rebuildTrie[field] { if b.rebuildTrie[field] {
err := b.resetFieldTrie(field, b.state.StateRoots, fieldparams.StateRootsLength) err := b.resetFieldTrie(field, b.stateRoots, fieldparams.StateRootsLength)
if err != nil { if err != nil {
return [32]byte{}, err return [32]byte{}, err
} }
delete(b.rebuildTrie, field) delete(b.rebuildTrie, field)
return b.stateFieldLeaves[field].TrieRoot() return b.stateFieldLeaves[field].TrieRoot()
} }
return b.recomputeFieldTrie(stateRoots, b.state.StateRoots) return b.recomputeFieldTrie(stateRoots, b.stateRoots)
case historicalRoots: case historicalRoots:
return ssz.ByteArrayRootWithLimit(b.state.HistoricalRoots, fieldparams.HistoricalRootsLength) hRoots := make([][]byte, len(b.historicalRoots))
for i := range hRoots {
hRoots[i] = b.historicalRoots[i][:]
}
return ssz.ByteArrayRootWithLimit(hRoots, fieldparams.HistoricalRootsLength)
case eth1Data: case eth1Data:
return stateutil.Eth1Root(hasher, b.state.Eth1Data) return stateutil.Eth1Root(hasher, b.eth1Data)
case eth1DataVotes: case eth1DataVotes:
if b.rebuildTrie[field] { if b.rebuildTrie[field] {
err := b.resetFieldTrie( err := b.resetFieldTrie(
field, field,
b.state.Eth1DataVotes, b.eth1DataVotes,
fieldparams.Eth1DataVotesLength, fieldparams.Eth1DataVotesLength,
) )
if err != nil { if err != nil {
@@ -317,50 +362,50 @@ func (b *BeaconState) rootSelector(ctx context.Context, field types.FieldIndex)
delete(b.rebuildTrie, field) delete(b.rebuildTrie, field)
return b.stateFieldLeaves[field].TrieRoot() return b.stateFieldLeaves[field].TrieRoot()
} }
return b.recomputeFieldTrie(field, b.state.Eth1DataVotes) return b.recomputeFieldTrie(field, b.eth1DataVotes)
case validators: case validators:
if b.rebuildTrie[field] { if b.rebuildTrie[field] {
err := b.resetFieldTrie(field, b.state.Validators, fieldparams.ValidatorRegistryLimit) err := b.resetFieldTrie(field, b.validators, fieldparams.ValidatorRegistryLimit)
if err != nil { if err != nil {
return [32]byte{}, err return [32]byte{}, err
} }
delete(b.rebuildTrie, validators) delete(b.rebuildTrie, validators)
return b.stateFieldLeaves[field].TrieRoot() return b.stateFieldLeaves[field].TrieRoot()
} }
return b.recomputeFieldTrie(validators, b.state.Validators) return b.recomputeFieldTrie(validators, b.validators)
case balances: case balances:
if features.Get().EnableBalanceTrieComputation { if features.Get().EnableBalanceTrieComputation {
if b.rebuildTrie[field] { if b.rebuildTrie[field] {
maxBalCap := uint64(fieldparams.ValidatorRegistryLimit) maxBalCap := uint64(fieldparams.ValidatorRegistryLimit)
elemSize := uint64(8) elemSize := uint64(8)
balLimit := (maxBalCap*elemSize + 31) / 32 balLimit := (maxBalCap*elemSize + 31) / 32
err := b.resetFieldTrie(field, b.state.Balances, balLimit) err := b.resetFieldTrie(field, b.balances, balLimit)
if err != nil { if err != nil {
return [32]byte{}, err return [32]byte{}, err
} }
delete(b.rebuildTrie, field) delete(b.rebuildTrie, field)
return b.stateFieldLeaves[field].TrieRoot() return b.stateFieldLeaves[field].TrieRoot()
} }
return b.recomputeFieldTrie(balances, b.state.Balances) return b.recomputeFieldTrie(balances, b.balances)
} }
return stateutil.Uint64ListRootWithRegistryLimit(b.state.Balances) return stateutil.Uint64ListRootWithRegistryLimit(b.balances)
case randaoMixes: case randaoMixes:
if b.rebuildTrie[field] { if b.rebuildTrie[field] {
err := b.resetFieldTrie(field, b.state.RandaoMixes, fieldparams.RandaoMixesLength) err := b.resetFieldTrie(field, b.randaoMixes, fieldparams.RandaoMixesLength)
if err != nil { if err != nil {
return [32]byte{}, err return [32]byte{}, err
} }
delete(b.rebuildTrie, field) delete(b.rebuildTrie, field)
return b.stateFieldLeaves[field].TrieRoot() return b.stateFieldLeaves[field].TrieRoot()
} }
return b.recomputeFieldTrie(randaoMixes, b.state.RandaoMixes) return b.recomputeFieldTrie(randaoMixes, b.randaoMixes)
case slashings: case slashings:
return ssz.SlashingsRoot(b.state.Slashings) return ssz.SlashingsRoot(b.slashings)
case previousEpochAttestations: case previousEpochAttestations:
if b.rebuildTrie[field] { if b.rebuildTrie[field] {
err := b.resetFieldTrie( err := b.resetFieldTrie(
field, field,
b.state.PreviousEpochAttestations, b.previousEpochAttestations,
fieldparams.PreviousEpochAttestationsLength, fieldparams.PreviousEpochAttestationsLength,
) )
if err != nil { if err != nil {
@@ -369,12 +414,12 @@ func (b *BeaconState) rootSelector(ctx context.Context, field types.FieldIndex)
delete(b.rebuildTrie, field) delete(b.rebuildTrie, field)
return b.stateFieldLeaves[field].TrieRoot() return b.stateFieldLeaves[field].TrieRoot()
} }
return b.recomputeFieldTrie(field, b.state.PreviousEpochAttestations) return b.recomputeFieldTrie(field, b.previousEpochAttestations)
case currentEpochAttestations: case currentEpochAttestations:
if b.rebuildTrie[field] { if b.rebuildTrie[field] {
err := b.resetFieldTrie( err := b.resetFieldTrie(
field, field,
b.state.CurrentEpochAttestations, b.currentEpochAttestations,
fieldparams.CurrentEpochAttestationsLength, fieldparams.CurrentEpochAttestationsLength,
) )
if err != nil { if err != nil {
@@ -383,15 +428,15 @@ func (b *BeaconState) rootSelector(ctx context.Context, field types.FieldIndex)
delete(b.rebuildTrie, field) delete(b.rebuildTrie, field)
return b.stateFieldLeaves[field].TrieRoot() return b.stateFieldLeaves[field].TrieRoot()
} }
return b.recomputeFieldTrie(field, b.state.CurrentEpochAttestations) return b.recomputeFieldTrie(field, b.currentEpochAttestations)
case justificationBits: case justificationBits:
return bytesutil.ToBytes32(b.state.JustificationBits), nil return bytesutil.ToBytes32(b.justificationBits), nil
case previousJustifiedCheckpoint: case previousJustifiedCheckpoint:
return ssz.CheckpointRoot(hasher, b.state.PreviousJustifiedCheckpoint) return ssz.CheckpointRoot(hasher, b.previousJustifiedCheckpoint)
case currentJustifiedCheckpoint: case currentJustifiedCheckpoint:
return ssz.CheckpointRoot(hasher, b.state.CurrentJustifiedCheckpoint) return ssz.CheckpointRoot(hasher, b.currentJustifiedCheckpoint)
case finalizedCheckpoint: case finalizedCheckpoint:
return ssz.CheckpointRoot(hasher, b.state.FinalizedCheckpoint) return ssz.CheckpointRoot(hasher, b.finalizedCheckpoint)
} }
return [32]byte{}, errors.New("invalid field index provided") return [32]byte{}, errors.New("invalid field index provided")
} }

View File

@@ -1,15 +1,10 @@
package v1 package v1
import ( import (
"sync"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/beacon-chain/state" "github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/fieldtrie"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
"github.com/prysmaticlabs/prysm/beacon-chain/state/types" "github.com/prysmaticlabs/prysm/beacon-chain/state/types"
"github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/config/params"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
) )
// Ensure type BeaconState below implements BeaconState interface. // Ensure type BeaconState below implements BeaconState interface.
@@ -38,20 +33,6 @@ var fieldMap map[types.FieldIndex]types.DataType
// operations can be performed on state. // operations can be performed on state.
var ErrNilInnerState = errors.New("nil inner state") var ErrNilInnerState = errors.New("nil inner state")
// BeaconState defines a struct containing utilities for the Ethereum Beacon Chain state, defining
// getters and setters for its respective values and helpful functions such as HashTreeRoot().
type BeaconState struct {
state *ethpb.BeaconState
lock sync.RWMutex
dirtyFields map[types.FieldIndex]bool
dirtyIndices map[types.FieldIndex][]uint64
stateFieldLeaves map[types.FieldIndex]*fieldtrie.FieldTrie
rebuildTrie map[types.FieldIndex]bool
valMapHandler *stateutil.ValidatorMapHandler
merkleLayers [][][]byte
sharedFieldReferences map[types.FieldIndex]*stateutil.Reference
}
// Field Aliases for values from the types package. // Field Aliases for values from the types package.
const ( const (
genesisTime = types.GenesisTime genesisTime = types.GenesisTime

View File

@@ -20,14 +20,18 @@ import (
func TestBeaconState_ProtoBeaconStateCompatibility(t *testing.T) { func TestBeaconState_ProtoBeaconStateCompatibility(t *testing.T) {
params.SetupTestConfigCleanup(t) params.SetupTestConfigCleanup(t)
params.OverrideBeaconConfig(params.MinimalSpecConfig()) cfg := params.MinimalSpecConfig()
cfg.SlotsPerHistoricalRoot = fieldparams.BlockRootsLength
cfg.EpochsPerHistoricalVector = fieldparams.RandaoMixesLength
params.OverrideBeaconConfig(cfg)
ctx := context.Background() ctx := context.Background()
genesis := setupGenesisState(t, 64) genesis := setupGenesisState(t, 64)
customState, err := v1.InitializeFromProto(genesis) customState, err := v1.InitializeFromProto(genesis)
require.NoError(t, err) require.NoError(t, err)
cloned, ok := proto.Clone(genesis).(*ethpb.BeaconState) cloned, ok := proto.Clone(genesis).(*ethpb.BeaconState)
assert.Equal(t, true, ok, "Object is not of type *ethpb.BeaconState") assert.Equal(t, true, ok, "Object is not of type *ethpb.BeaconState")
custom := customState.CloneInnerState() custom := customState.ToProto()
assert.DeepSSZEqual(t, cloned, custom) assert.DeepSSZEqual(t, cloned, custom)
r1, err := customState.HashTreeRoot(ctx) r1, err := customState.HashTreeRoot(ctx)
@@ -142,7 +146,7 @@ func BenchmarkStateClone_Manual(b *testing.B) {
require.NoError(b, err) require.NoError(b, err)
b.StartTimer() b.StartTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
_ = st.CloneInnerState() _ = st.ToProto()
} }
} }
@@ -226,7 +230,7 @@ func TestForkManualCopy_OK(t *testing.T) {
} }
require.NoError(t, a.SetFork(wantedFork)) require.NoError(t, a.SetFork(wantedFork))
pbState, err := v1.ProtobufBeaconState(a.InnerStateUnsafe()) pbState, err := v1.ProtobufBeaconState(a.ToProtoUnsafe())
require.NoError(t, err) require.NoError(t, err)
require.DeepEqual(t, pbState.Fork, wantedFork) require.DeepEqual(t, pbState.Fork, wantedFork)
} }

View File

@@ -846,8 +846,8 @@ def prysm_deps():
name = "com_github_ferranbt_fastssz", name = "com_github_ferranbt_fastssz",
importpath = "github.com/ferranbt/fastssz", importpath = "github.com/ferranbt/fastssz",
replace = "github.com/prysmaticlabs/fastssz", replace = "github.com/prysmaticlabs/fastssz",
sum = "h1:BC9nIbhpQMyFlmLUJsVv8/+UewAVIjJegtvgaP9bV/M=", sum = "h1:MRQwO/qZtHJFQA7M3uQBadrscFC5org7fWm8CCBRzMM=",
version = "v0.0.0-20211123050228-97d96f38caae", version = "v0.0.0-20220110145812-fafb696cae88",
) )
go_repository( go_repository(

View File

@@ -228,6 +228,16 @@ func SafeCopy2dBytes(ary [][]byte) [][]byte {
return nil return nil
} }
// SafeCopy2d32Bytes will copy and return a non-nil 2d byte array, otherwise it returns nil.
func SafeCopy2d32Bytes(ary [][32]byte) [][32]byte {
if ary != nil {
copied := make([][32]byte, len(ary))
copy(copied, ary)
return copied
}
return nil
}
// ReverseBytes32Slice will reverse the provided slice's order. // ReverseBytes32Slice will reverse the provided slice's order.
func ReverseBytes32Slice(arr [][32]byte) [][32]byte { func ReverseBytes32Slice(arr [][32]byte) [][32]byte {
for i, j := 0, len(arr)-1; i < j; i, j = i+1, j-1 { for i, j := 0, len(arr)-1; i < j; i, j = i+1, j-1 {

View File

@@ -507,3 +507,12 @@ func TestReverseByteOrder(t *testing.T) {
assert.Equal(t, bytes.Equal(input, []byte{0, 1, 2, 3, 4, 5}), true) assert.Equal(t, bytes.Equal(input, []byte{0, 1, 2, 3, 4, 5}), true)
assert.Equal(t, bytes.Equal(expectedResult, output), true) assert.Equal(t, bytes.Equal(expectedResult, output), true)
} }
func TestSafeCopy2d32Bytes(t *testing.T) {
input := make([][32]byte, 2)
input[0] = bytesutil.ToBytes32([]byte{'a'})
input[1] = bytesutil.ToBytes32([]byte{'b'})
output := bytesutil.SafeCopy2d32Bytes(input)
assert.Equal(t, false, &input == &output, "No copy was made")
assert.DeepEqual(t, input, output)
}

2
go.mod
View File

@@ -117,4 +117,4 @@ replace github.com/json-iterator/go => github.com/prestonvanloon/go v1.1.7-0.201
// See https://github.com/prysmaticlabs/grpc-gateway/issues/2 // See https://github.com/prysmaticlabs/grpc-gateway/issues/2
replace github.com/grpc-ecosystem/grpc-gateway/v2 => github.com/prysmaticlabs/grpc-gateway/v2 v2.3.1-0.20210702154020-550e1cd83ec1 replace github.com/grpc-ecosystem/grpc-gateway/v2 => github.com/prysmaticlabs/grpc-gateway/v2 v2.3.1-0.20210702154020-550e1cd83ec1
replace github.com/ferranbt/fastssz => github.com/prysmaticlabs/fastssz v0.0.0-20211123050228-97d96f38caae replace github.com/ferranbt/fastssz => github.com/prysmaticlabs/fastssz v0.0.0-20220110145812-fafb696cae88

4
go.sum
View File

@@ -1106,8 +1106,8 @@ github.com/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38i
github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4= github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4=
github.com/prysmaticlabs/eth2-types v0.0.0-20210303084904-c9735a06829d h1:1dN7YAqMN3oAJ0LceWcyv/U4jHLh+5urnSnr4br6zg4= github.com/prysmaticlabs/eth2-types v0.0.0-20210303084904-c9735a06829d h1:1dN7YAqMN3oAJ0LceWcyv/U4jHLh+5urnSnr4br6zg4=
github.com/prysmaticlabs/eth2-types v0.0.0-20210303084904-c9735a06829d/go.mod h1:kOmQ/zdobQf7HUohDTifDNFEZfNaSCIY5fkONPL+dWU= github.com/prysmaticlabs/eth2-types v0.0.0-20210303084904-c9735a06829d/go.mod h1:kOmQ/zdobQf7HUohDTifDNFEZfNaSCIY5fkONPL+dWU=
github.com/prysmaticlabs/fastssz v0.0.0-20211123050228-97d96f38caae h1:BC9nIbhpQMyFlmLUJsVv8/+UewAVIjJegtvgaP9bV/M= github.com/prysmaticlabs/fastssz v0.0.0-20220110145812-fafb696cae88 h1:MRQwO/qZtHJFQA7M3uQBadrscFC5org7fWm8CCBRzMM=
github.com/prysmaticlabs/fastssz v0.0.0-20211123050228-97d96f38caae/go.mod h1:S8yiDeAXy8f88W4Ul+0dBMPx49S05byYbmZD6Uv94K4= github.com/prysmaticlabs/fastssz v0.0.0-20220110145812-fafb696cae88/go.mod h1:ASoCYXOqVPSr7KRfiBbbAOxyOwRBfl9gpwTvEKqbnkc=
github.com/prysmaticlabs/go-bitfield v0.0.0-20210108222456-8e92c3709aa0/go.mod h1:hCwmef+4qXWjv0jLDbQdWnL0Ol7cS7/lCSS26WR+u6s= github.com/prysmaticlabs/go-bitfield v0.0.0-20210108222456-8e92c3709aa0/go.mod h1:hCwmef+4qXWjv0jLDbQdWnL0Ol7cS7/lCSS26WR+u6s=
github.com/prysmaticlabs/go-bitfield v0.0.0-20210809151128-385d8c5e3fb7 h1:0tVE4tdWQK9ZpYygoV7+vS6QkDvQVySboMVEIxBJmXw= github.com/prysmaticlabs/go-bitfield v0.0.0-20210809151128-385d8c5e3fb7 h1:0tVE4tdWQK9ZpYygoV7+vS6QkDvQVySboMVEIxBJmXw=
github.com/prysmaticlabs/go-bitfield v0.0.0-20210809151128-385d8c5e3fb7/go.mod h1:wmuf/mdK4VMD+jA9ThwcUKjg3a2XWM9cVfFYjDyY4j4= github.com/prysmaticlabs/go-bitfield v0.0.0-20210809151128-385d8c5e3fb7/go.mod h1:wmuf/mdK4VMD+jA9ThwcUKjg3a2XWM9cVfFYjDyY4j4=

View File

@@ -4,7 +4,7 @@
# Script to copy ssz.go files from bazel build folder to appropriate location. # Script to copy ssz.go files from bazel build folder to appropriate location.
# Bazel builds to bazel-bin/... folder, script copies them back to original folder where target is. # Bazel builds to bazel-bin/... folder, script copies them back to original folder where target is.
bazel query 'kind(ssz_gen_marshal, //proto/...)' | xargs bazel build bazel query 'kind(ssz_gen_marshal, //proto/...) union kind(ssz_gen_marshal, //beacon-chain/state/...)' | xargs bazel build
# Get locations of proto ssz.go files. # Get locations of proto ssz.go files.
file_list=() file_list=()

View File

@@ -147,6 +147,7 @@
"validator/.*": "" "validator/.*": ""
}, },
"exclude_files": { "exclude_files": {
"beacon-chain/state/state-native/v1/generated.ssz.go": "Exclude generated SSZ file"
} }
}, },
"properpermissions": { "properpermissions": {