From 233690620ecaf4402d5c3172f579b0eb3d7fbb03 Mon Sep 17 00:00:00 2001
From: a
Date: Sun, 7 May 2023 01:24:09 -0500
Subject: [PATCH 01/34] new branch
---
cl/cltypes/solid/hashutil.go | 76 +++++++++
cl/cltypes/solid/interfaces.go | 14 ++
cl/cltypes/solid/uint64slice_byte.go | 152 ++++++++++++++++++
cl/cltypes/solid/uint64slice_byte_test.go | 34 ++++
cl/cltypes/solid/uint64slice_simple.go | 68 ++++++++
cl/cltypes/solid/validator.go | 124 ++++++++++++++
cl/cltypes/validator.go | 80 +++------
cl/merkle_tree/hasher.go | 29 +++-
cl/merkle_tree/merkle_root.go | 8 +
cl/merkle_tree/primitives.go | 9 ++
cmd/erigon-cl/core/state/accessors.go | 23 +--
cmd/erigon-cl/core/state/accessors_test.go | 37 +++--
cmd/erigon-cl/core/state/cache.go | 4 +-
cmd/erigon-cl/core/state/cache_accessors.go | 13 +-
cmd/erigon-cl/core/state/cache_mutators.go | 6 +-
cmd/erigon-cl/core/state/cache_setters.go | 2 +-
cmd/erigon-cl/core/state/copy.go | 16 +-
cmd/erigon-cl/core/state/mutators_test.go | 59 +++----
cmd/erigon-cl/core/state/raw/copy.go | 22 +--
cmd/erigon-cl/core/state/raw/getters.go | 31 ++--
cmd/erigon-cl/core/state/raw/hashing.go | 12 +-
cmd/erigon-cl/core/state/raw/setters.go | 58 ++++---
cmd/erigon-cl/core/state/raw/ssz.go | 34 ++--
cmd/erigon-cl/core/state/raw/state.go | 9 +-
cmd/erigon-cl/core/state/raw/test_util.go | 6 +-
.../core/state/shuffling/shuffling.go | 2 +-
cmd/erigon-cl/core/state/util.go | 27 ++--
.../finalization_and_justification.go | 26 +--
cmd/erigon-cl/core/transition/operations.go | 14 +-
.../core/transition/process_attestations.go | 8 +-
.../process_bls_to_execution_change.go | 7 +-
.../process_effective_balance_update.go | 17 +-
.../core/transition/process_epoch.go | 6 +-
.../transition/process_registry_updates.go | 21 ++-
.../process_rewards_and_penalties.go | 73 +++++----
.../core/transition/process_slashings.go | 18 ++-
.../core/transition/process_slots.go | 3 +-
cmd/erigon-cl/core/transition/processing.go | 9 +-
cmd/erigon-cl/forkchoice/checkpoint_state.go | 10 +-
cmd/erigon-cl/forkchoice/utils.go | 8 +-
40 files changed, 859 insertions(+), 316 deletions(-)
create mode 100644 cl/cltypes/solid/hashutil.go
create mode 100644 cl/cltypes/solid/interfaces.go
create mode 100644 cl/cltypes/solid/uint64slice_byte.go
create mode 100644 cl/cltypes/solid/uint64slice_byte_test.go
create mode 100644 cl/cltypes/solid/uint64slice_simple.go
create mode 100644 cl/cltypes/solid/validator.go
diff --git a/cl/cltypes/solid/hashutil.go b/cl/cltypes/solid/hashutil.go
new file mode 100644
index 00000000000..39a66233c31
--- /dev/null
+++ b/cl/cltypes/solid/hashutil.go
@@ -0,0 +1,76 @@
+package solid
+
+import (
+ "fmt"
+
+ "github.com/ledgerwatch/erigon/cl/merkle_tree"
+ "github.com/ledgerwatch/erigon/cl/utils"
+ "github.com/prysmaticlabs/gohashtree"
+)
+
+func TreeHashFlatSlice(input []byte, res []byte) (err error) {
+ err = merkle_tree.MerkleRootFromFlatLeaves(input, res)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+// MerkleizeVector uses our optimized routine to hash a list of 32-byte
+// elements.
+func MerkleizeVector(elements [][32]byte, length uint64) ([32]byte, error) {
+ depth := getDepth(length)
+ // Return zerohash at depth
+ if len(elements) == 0 {
+ return merkle_tree.ZeroHashes[depth], nil
+ }
+ for i := uint8(0); i < depth; i++ {
+ // Sequential
+ layerLen := len(elements)
+ if layerLen%2 == 1 {
+ elements = append(elements, merkle_tree.ZeroHashes[i])
+ }
+ outputLen := len(elements) / 2
+ if err := gohashtree.Hash(elements, elements); err != nil {
+ return [32]byte{}, err
+ }
+ elements = elements[:outputLen]
+ }
+ return elements[0], nil
+}
+
+// MerkleizeVector uses our optimized routine to hash a list of 32-byte
+// elements.
+func MerkleizeFlatLeaves(elements []byte) ([]byte, error) {
+ // merkleizeTrieLeaves returns intermediate roots of given leaves.
+ layer := make([]byte, len(elements)/2)
+ for len(elements) > 32 {
+ if !utils.IsPowerOf2(uint64(len(elements))) {
+ return nil, fmt.Errorf("hash layer is a non power of 2: %d", len(elements))
+ }
+ if err := gohashtree.HashByteSlice(layer, elements); err != nil {
+ return nil, err
+ }
+ elements = layer[:len(elements)/2]
+ }
+ return elements[:32], nil
+}
+
+func getDepth(v uint64) uint8 {
+ // If there are 0 or 1 nodes, the depth is 0.
+ if v <= 1 {
+ return 0
+ }
+
+ // Initialize the depth to 0.
+ depth := uint8(0)
+
+ // Divide the number of nodes by 2 until it is less than or equal to 1.
+ // The number of iterations is the depth of the tree.
+ for v > 1 {
+ v >>= 1
+ depth++
+ }
+
+ return depth
+}
diff --git a/cl/cltypes/solid/interfaces.go b/cl/cltypes/solid/interfaces.go
new file mode 100644
index 00000000000..b9cc9fddbd4
--- /dev/null
+++ b/cl/cltypes/solid/interfaces.go
@@ -0,0 +1,14 @@
+package solid
+
+type Uint64Slice interface {
+ Clear()
+ CopyTo(Uint64Slice)
+ Range(fn func(index int, value uint64, length int) bool)
+ Pop() uint64
+ Append(v uint64)
+ Get(index int) uint64
+ Set(index int, v uint64)
+ Length() int
+ Cap() int
+ HashSSZTo(xs []byte) error
+}
diff --git a/cl/cltypes/solid/uint64slice_byte.go b/cl/cltypes/solid/uint64slice_byte.go
new file mode 100644
index 00000000000..a1dbae3a945
--- /dev/null
+++ b/cl/cltypes/solid/uint64slice_byte.go
@@ -0,0 +1,152 @@
+package solid
+
+import (
+ "encoding/binary"
+
+ "github.com/ledgerwatch/erigon/cl/merkle_tree"
+ "github.com/ledgerwatch/erigon/cl/utils"
+ "github.com/prysmaticlabs/gohashtree"
+)
+
+type byteBasedUint64Slice struct {
+ u []byte
+ hashBuf []byte
+
+ l int // len
+ c int // cap
+}
+
+func NewUint64Slice(limit int) Uint64Slice {
+ o := &byteBasedUint64Slice{
+ c: limit,
+ }
+ o.u = make([]byte, 0)
+ return o
+}
+
+func (arr *byteBasedUint64Slice) Clear() {
+ arr.l = 0
+ for i := range arr.u {
+ arr.u[i] = 0
+ }
+}
+
+func (arr *byteBasedUint64Slice) CopyTo(target Uint64Slice) {
+ target.Clear()
+ switch c := target.(type) {
+ case *byteBasedUint64Slice:
+ c.c = arr.c
+ c.l = arr.l
+ if len(c.u) < len(arr.u) {
+ c.u = make([]byte, len(arr.u))
+ }
+ c.u = c.u[:len(arr.u)]
+ copy(c.u, arr.u)
+ return
+ default:
+ }
+ target.Range(func(index int, value uint64, length int) bool {
+ target.Append(value)
+ return true
+ })
+}
+
+func (arr *byteBasedUint64Slice) depth() int {
+ return int(getDepth(uint64(arr.c) / 4))
+}
+
+func (arr *byteBasedUint64Slice) Range(fn func(index int, value uint64, length int) bool) {
+ for i := 0; i < arr.l; i++ {
+ cont := fn(i, arr.Get(i), arr.l)
+ if !cont {
+ break
+ }
+ }
+}
+
+func (arr *byteBasedUint64Slice) Pop() uint64 {
+ offset := (arr.l - 1) * 8
+ val := binary.LittleEndian.Uint64(arr.u[offset : offset+8])
+ binary.LittleEndian.PutUint64(arr.u[offset:offset+8], 0)
+ arr.l = arr.l - 1
+ return val
+}
+
+func (arr *byteBasedUint64Slice) makeBuf(size int) {
+ diff := size - len(arr.hashBuf)
+ if diff > 0 {
+ arr.hashBuf = append(arr.hashBuf, make([]byte, diff)...)
+ }
+ arr.hashBuf = arr.hashBuf[:size]
+}
+
+func (arr *byteBasedUint64Slice) Append(v uint64) {
+ if len(arr.u) <= arr.l*8 {
+ arr.u = append(arr.u, make([]byte, 32)...)
+ }
+ offset := arr.l * 8
+ binary.LittleEndian.PutUint64(arr.u[offset:offset+8], v)
+ arr.l = arr.l + 1
+}
+
+func (arr *byteBasedUint64Slice) Get(index int) uint64 {
+ if index >= arr.l {
+ panic("index out of range")
+ }
+ offset := index * 8
+ return binary.LittleEndian.Uint64(arr.u[offset : offset+8])
+}
+
+func (arr *byteBasedUint64Slice) Set(index int, v uint64) {
+ if index >= arr.l {
+ panic("index out of range")
+ }
+ offset := index * 8
+ binary.LittleEndian.PutUint64(arr.u[offset:offset+8], v)
+}
+
+func (arr *byteBasedUint64Slice) Length() int {
+ return arr.l
+}
+
+func (arr *byteBasedUint64Slice) Cap() int {
+ return arr.c
+}
+
+func (arr *byteBasedUint64Slice) HashSSZTo(xs []byte) error {
+ depth := getDepth((uint64(arr.c)*8 + 31) / 32)
+ baseRoot := [32]byte{}
+ if arr.l == 0 {
+ copy(baseRoot[:], merkle_tree.ZeroHashes[depth][:])
+ } else {
+ err := arr.getBaseHash(baseRoot[:])
+ if err != nil {
+ return err
+ }
+ }
+ lengthRoot := merkle_tree.Uint64Root(uint64(arr.l))
+ ans := utils.Keccak256(baseRoot[:], lengthRoot[:])
+ copy(xs, ans[:])
+ return nil
+}
+
+func (arr *byteBasedUint64Slice) getBaseHash(xs []byte) error {
+ depth := getDepth((uint64(arr.c)*8 + 31) / 32)
+ offset := 32*((arr.l-1)/4) + 32
+ elements := arr.u[:offset]
+ for i := uint8(0); i < depth; i++ {
+ // Sequential
+ layerLen := len(elements)
+ if layerLen%64 == 32 {
+ elements = append(elements, merkle_tree.ZeroHashes[i][:]...)
+ }
+ outputLen := len(elements) / 2
+ arr.makeBuf(outputLen)
+ if err := gohashtree.HashByteSlice(arr.hashBuf, elements); err != nil {
+ return err
+ }
+ elements = arr.hashBuf
+ }
+ copy(xs, elements[:32])
+ return nil
+}
diff --git a/cl/cltypes/solid/uint64slice_byte_test.go b/cl/cltypes/solid/uint64slice_byte_test.go
new file mode 100644
index 00000000000..1fd7545225f
--- /dev/null
+++ b/cl/cltypes/solid/uint64slice_byte_test.go
@@ -0,0 +1,34 @@
+package solid_test
+
+import (
+ "log"
+ "testing"
+
+ "github.com/ledgerwatch/erigon/cl/cltypes/solid"
+ "github.com/ledgerwatch/erigon/cl/merkle_tree"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+func TestUint64SliceBasic(t *testing.T) {
+ slice := solid.NewUint64Slice(8)
+
+ slice.Append(3)
+ slice.Append(2)
+ slice.Append(1)
+
+ assert.EqualValues(t, 3, slice.Get(0))
+ assert.EqualValues(t, 2, slice.Get(1))
+ assert.EqualValues(t, 1, slice.Get(2))
+
+ out := [32]byte{}
+ err := slice.HashSSZTo(out[:])
+ require.NoError(t, err)
+
+ nums := []uint64{3, 2, 1}
+ root, err := merkle_tree.Uint64ListRootWithLimit(nums, 2)
+ require.NoError(t, err)
+ log.Printf("merkl tree: %x", root)
+ log.Printf("ours tree: %x", out)
+
+}
diff --git a/cl/cltypes/solid/uint64slice_simple.go b/cl/cltypes/solid/uint64slice_simple.go
new file mode 100644
index 00000000000..b74aab2e07d
--- /dev/null
+++ b/cl/cltypes/solid/uint64slice_simple.go
@@ -0,0 +1,68 @@
+package solid
+
+import (
+ "github.com/ledgerwatch/erigon/cl/merkle_tree"
+)
+
+type uint64SliceSimple struct {
+ u []uint64
+ c int
+}
+
+func NewSimpleUint64Slice(cap int) Uint64Slice {
+ return &uint64SliceSimple{
+ c: cap,
+ }
+}
+
+func (u *uint64SliceSimple) Clear() {
+ u.u = u.u[:0]
+}
+
+func (u *uint64SliceSimple) CopyTo(target Uint64Slice) {
+ target.Clear()
+ for _, v := range u.u {
+ target.Append(v)
+ }
+}
+
+func (u *uint64SliceSimple) Range(fn func(index int, value uint64, length int) bool) {
+ //TODO implement me
+ for i, v := range u.u {
+ fn(i, v, len(u.u))
+ }
+}
+
+func (u *uint64SliceSimple) Pop() (x uint64) {
+ x, u.u = u.u[0], u.u[1:]
+ return x
+}
+
+func (u *uint64SliceSimple) Append(v uint64) {
+ u.u = append(u.u, v)
+}
+
+func (u *uint64SliceSimple) Get(index int) uint64 {
+ return u.u[index]
+}
+
+func (u *uint64SliceSimple) Set(index int, v uint64) {
+ u.u[index] = v
+}
+
+func (u *uint64SliceSimple) Length() int {
+ return len(u.u)
+}
+
+func (u *uint64SliceSimple) Cap() int {
+ return u.c
+}
+
+func (u *uint64SliceSimple) HashSSZTo(xs []byte) error {
+ root, err := merkle_tree.Uint64ListRootWithLimit(u.u, (uint64(u.c)*8+31)/32)
+ if err != nil {
+ return err
+ }
+ copy(xs, root[:])
+ return nil
+}
diff --git a/cl/cltypes/solid/validator.go b/cl/cltypes/solid/validator.go
new file mode 100644
index 00000000000..29f5fd28540
--- /dev/null
+++ b/cl/cltypes/solid/validator.go
@@ -0,0 +1,124 @@
+package solid
+
+import (
+ "encoding/binary"
+
+ "github.com/ledgerwatch/erigon-lib/common"
+ "github.com/ledgerwatch/erigon/cl/cltypes/ssz"
+ "github.com/ledgerwatch/erigon/cl/merkle_tree"
+)
+
+// PublicKey 48
+// WithdrawalCredentials 32
+// EffectiveBalance 8
+// Slashed 1
+// ActivationEligibilityEpoch 8
+// ActivationEpoch 8
+// ExitEpoch 8
+// WithdrawableEpoch 8
+//
+// total: 121
+const validatorSize = 48 + 32 + 8 + 1 + 8 + 8 + 8 + 8
+
+type Validator [validatorSize]byte
+
+func (v *Validator) CopyTo(dst *Validator) {
+ copy(dst[:], v[:])
+}
+
+func (v *Validator) EncodeSSZ(dst []byte) []byte {
+ buf := dst
+ buf = append(buf, v[:]...)
+ return buf
+}
+
+func (v *Validator) DecodeSSZ(buf []byte, _ int) error {
+ if len(buf) < v.EncodingSizeSSZ() {
+ return ssz.ErrLowBufferSize
+ }
+ copy(v[:], buf)
+ return nil
+}
+
+func (v *Validator) EncodingSizeSSZ() int {
+ return 121
+}
+
+func (v *Validator) PublicKey() (o [48]byte) {
+ copy(o[:], v[:48])
+ return
+}
+func (v *Validator) WithdrawalCredentials() (o common.Hash) {
+ copy(o[:], v[48:80])
+ return
+}
+func (v *Validator) EffectiveBalance() uint64 {
+ return binary.LittleEndian.Uint64(v[80:88])
+}
+func (v *Validator) Slashed() bool {
+ return v[88] != 0
+}
+func (v *Validator) ActivationEligibilityEpoch() uint64 {
+ return binary.LittleEndian.Uint64(v[89:97])
+}
+func (v *Validator) ActivationEpoch() uint64 {
+ return binary.LittleEndian.Uint64(v[97:105])
+}
+func (v *Validator) ExitEpoch() uint64 {
+ return binary.LittleEndian.Uint64(v[105:113])
+}
+func (v *Validator) WithdrawableEpoch() uint64 {
+ return binary.LittleEndian.Uint64(v[113:121])
+}
+
+func (v *Validator) CopyHashBufferTo(o []byte) error {
+ for i := 0; i < 64; i++ {
+ o[i] = 0
+ }
+ copy(o[:64], v[:48])
+ err := merkle_tree.InPlacePublicKeyRoot(o[:64])
+ if err != nil {
+ return err
+ }
+ copy(o[32:64], v[48:80])
+ copy(o[64:96], v[80:88])
+ o[96] = v[88]
+ copy(o[128:160], v[89:97])
+ copy(o[160:192], v[97:105])
+ copy(o[192:224], v[105:113])
+ copy(o[224:256], v[113:121])
+
+ return nil
+
+}
+
+func (v *Validator) SetPublicKey(o [48]byte) {
+ copy(v[:48], o[:])
+ return
+}
+func (v *Validator) SetWithdrawalCredentials(o common.Hash) {
+ copy(v[48:80], o[:])
+ return
+}
+func (v *Validator) SetEffectiveBalance(i uint64) {
+ binary.LittleEndian.PutUint64(v[80:88], i)
+}
+func (v *Validator) SetSlashed(b bool) {
+ if b {
+ v[88] = 1
+ return
+ }
+ v[88] = 0
+}
+func (v *Validator) SetActivationEligibilityEpoch(i uint64) {
+ binary.LittleEndian.PutUint64(v[89:97], i)
+}
+func (v *Validator) SetActivationEpoch(i uint64) {
+ binary.LittleEndian.PutUint64(v[97:105], i)
+}
+func (v *Validator) SetExitEpoch(i uint64) {
+ binary.LittleEndian.PutUint64(v[105:113], i)
+}
+func (v *Validator) SetWithdrawableEpoch(i uint64) {
+ binary.LittleEndian.PutUint64(v[113:121], i)
+}
diff --git a/cl/cltypes/validator.go b/cl/cltypes/validator.go
index debeef7ff1b..0f8257814d0 100644
--- a/cl/cltypes/validator.go
+++ b/cl/cltypes/validator.go
@@ -7,6 +7,7 @@ import (
libcommon "github.com/ledgerwatch/erigon-lib/common"
+ "github.com/ledgerwatch/erigon/cl/cltypes/solid"
"github.com/ledgerwatch/erigon/cl/cltypes/ssz"
"github.com/ledgerwatch/erigon/cl/merkle_tree"
"github.com/ledgerwatch/erigon/cl/utils"
@@ -285,14 +286,8 @@ func (s *SyncCommittee) Equal(s2 *SyncCommittee) bool {
// Validator, contains if we were on bellatrix/alteir/phase0 and transition epoch.
type Validator struct {
- PublicKey [48]byte
- WithdrawalCredentials libcommon.Hash
- EffectiveBalance uint64
- Slashed bool
- ActivationEligibilityEpoch uint64
- ActivationEpoch uint64
- ExitEpoch uint64
- WithdrawableEpoch uint64
+ solid.Validator
+
// This is all stuff used by phase0 state transition. It makes many operations faster.
// Source attesters
IsCurrentMatchingSourceAttester bool
@@ -310,7 +305,7 @@ type Validator struct {
// DutiesAttested returns how many of its duties the validator attested and missed
func (v *Validator) DutiesAttested() (attested, missed uint64) {
- if v.Slashed {
+ if v.Slashed() {
return 0, 3
}
if v.IsPreviousMatchingSourceAttester {
@@ -326,80 +321,41 @@ func (v *Validator) DutiesAttested() (attested, missed uint64) {
return
}
func (v *Validator) IsSlashable(epoch uint64) bool {
- return !v.Slashed && (v.ActivationEpoch <= epoch) && (epoch < v.WithdrawableEpoch)
+ return !v.Slashed() && (v.ActivationEpoch() <= epoch) && (epoch < v.WithdrawableEpoch())
}
func (v *Validator) EncodeSSZ(dst []byte) ([]byte, error) {
- buf := dst
- buf = append(buf, v.PublicKey[:]...)
- buf = append(buf, v.WithdrawalCredentials[:]...)
- buf = append(buf, ssz.Uint64SSZ(v.EffectiveBalance)...)
- buf = append(buf, ssz.BoolSSZ(v.Slashed))
- buf = append(buf, ssz.Uint64SSZ(v.ActivationEligibilityEpoch)...)
- buf = append(buf, ssz.Uint64SSZ(v.ActivationEpoch)...)
- buf = append(buf, ssz.Uint64SSZ(v.ExitEpoch)...)
- buf = append(buf, ssz.Uint64SSZ(v.WithdrawableEpoch)...)
- return buf, nil
+ return v.Validator.EncodeSSZ(dst), nil
}
func (v *Validator) DecodeSSZ(buf []byte, _ int) error {
- if len(buf) < v.EncodingSizeSSZ() {
- return fmt.Errorf("[Validator] err: %s", ssz.ErrLowBufferSize)
- }
- copy(v.PublicKey[:], buf)
- copy(v.WithdrawalCredentials[:], buf[48:])
- v.EffectiveBalance = ssz.UnmarshalUint64SSZ(buf[80:])
- v.Slashed = buf[88] == 1
- v.ActivationEligibilityEpoch = ssz.UnmarshalUint64SSZ(buf[89:])
- v.ActivationEpoch = ssz.UnmarshalUint64SSZ(buf[97:])
- v.ExitEpoch = ssz.UnmarshalUint64SSZ(buf[105:])
- v.WithdrawableEpoch = ssz.UnmarshalUint64SSZ(buf[113:])
- return nil
-}
-
-func (v *Validator) EncodingSizeSSZ() int {
- return 121
+ return v.Validator.DecodeSSZ(buf, 0)
}
var validatorLeavesPool = sync.Pool{
New: func() any {
- o := make([][32]byte, 8)
- return &o
+ p := make([]byte, 8*32)
+ return &p
},
}
-func (v *Validator) HashSSZ() ([32]byte, error) {
- leavesp, _ := validatorLeavesPool.Get().(*[][32]byte)
+func (v *Validator) HashSSZ() (o [32]byte, err error) {
+ leavesp, _ := validatorLeavesPool.Get().(*[]byte)
leaves := *leavesp
defer func() {
- leaves = leaves[:8]
validatorLeavesPool.Put(leavesp)
}()
- var (
- err error
- )
- leaves[0], err = merkle_tree.PublicKeyRoot(v.PublicKey)
- if err != nil {
- return [32]byte{}, err
- }
- leaves[1] = v.WithdrawalCredentials
- leaves[2] = merkle_tree.Uint64Root(v.EffectiveBalance)
- leaves[3] = merkle_tree.BoolRoot(v.Slashed)
- leaves[4] = merkle_tree.Uint64Root(v.ActivationEligibilityEpoch)
- leaves[5] = merkle_tree.Uint64Root(v.ActivationEpoch)
- leaves[6] = merkle_tree.Uint64Root(v.ExitEpoch)
- leaves[7] = merkle_tree.Uint64Root(v.WithdrawableEpoch)
- leaves = leaves[:8]
- output, err := merkle_tree.ArraysRoot(leaves, 8)
- return output, err
+ v.CopyHashBufferTo(leaves)
+ leaves = leaves[:(8 * 32)]
+ err = solid.TreeHashFlatSlice(leaves, o[:])
+ return
}
// Active returns if validator is active for given epoch
func (v *Validator) Active(epoch uint64) bool {
- return v.ActivationEpoch <= epoch && epoch < v.ExitEpoch
+ return v.ActivationEpoch() <= epoch && epoch < v.ExitEpoch()
}
-func (v *Validator) Copy() *Validator {
- copied := *v
- return &copied
+func (v *Validator) CopyTo(target *Validator) {
+ v.Validator.CopyTo(&target.Validator)
}
diff --git a/cl/merkle_tree/hasher.go b/cl/merkle_tree/hasher.go
index 9180ead3e26..628b6c9db7e 100644
--- a/cl/merkle_tree/hasher.go
+++ b/cl/merkle_tree/hasher.go
@@ -15,14 +15,16 @@ const initialBufferSize = 0 // it is whatever
// merkleHasher is used internally to provide shared buffer internally to the merkle_tree package.
type merkleHasher struct {
// internalBuffer is the shared buffer we use for each operation
- internalBuffer [][32]byte
+ internalBuffer [][32]byte
+ internalFlatBuffer []byte
// mu is the lock to ensure thread safety
mu sync.Mutex
}
func newMerkleHasher() *merkleHasher {
return &merkleHasher{
- internalBuffer: make([][32]byte, initialBufferSize),
+ internalBuffer: make([][32]byte, initialBufferSize),
+ internalFlatBuffer: make([]byte, initialBufferSize*32),
}
}
@@ -43,6 +45,21 @@ func (m *merkleHasher) merkleizeTrieLeaves(leaves [][32]byte) ([32]byte, error)
return leaves[0], nil
}
+// merkleizeTrieLeaves returns intermediate roots of given leaves.
+func (m *merkleHasher) merkleizeTrieLeavesFlat(leaves []byte, out []byte) (err error) {
+ m.mu.Lock()
+ defer m.mu.Unlock()
+ layer := m.getFlatBuffer(len(leaves) / 2)
+ for len(leaves) > 32 {
+ if err := gohashtree.HashByteSlice(layer, leaves); err != nil {
+ return err
+ }
+ leaves = layer[:len(leaves)/2]
+ }
+ copy(out, leaves[:32])
+ return
+}
+
// getBuffer provides buffer of given size.
func (m *merkleHasher) getBuffer(size int) [][32]byte {
if size > len(m.internalBuffer) {
@@ -50,3 +67,11 @@ func (m *merkleHasher) getBuffer(size int) [][32]byte {
}
return m.internalBuffer[:size]
}
+
+// getBuffer provides buffer of given size.
+func (m *merkleHasher) getFlatBuffer(size int) []byte {
+ if size > len(m.internalFlatBuffer) {
+ m.internalFlatBuffer = make([]byte, size)
+ }
+ return m.internalFlatBuffer[:size]
+}
diff --git a/cl/merkle_tree/merkle_root.go b/cl/merkle_tree/merkle_root.go
index 0676f4cddd5..6ab2d05b15e 100644
--- a/cl/merkle_tree/merkle_root.go
+++ b/cl/merkle_tree/merkle_root.go
@@ -15,6 +15,14 @@ func MerkleRootFromLeaves(leaves [][32]byte) ([32]byte, error) {
return globalHasher.merkleizeTrieLeaves(hashLayer)
}
+func MerkleRootFromFlatLeaves(leaves []byte, out []byte) (err error) {
+ if len(leaves) <= 32 {
+ copy(out, leaves)
+ return
+ }
+ return globalHasher.merkleizeTrieLeavesFlat(leaves, out)
+}
+
// getDepth returns the depth of a merkle tree with a given number of nodes.
// The depth is defined as the number of levels in the tree, with the root
// node at level 0 and each child node at a level one greater than its parent.
diff --git a/cl/merkle_tree/primitives.go b/cl/merkle_tree/primitives.go
index 38157011d0f..b8d46cc5b1c 100644
--- a/cl/merkle_tree/primitives.go
+++ b/cl/merkle_tree/primitives.go
@@ -36,3 +36,12 @@ func PublicKeyRoot(key [48]byte) (libcommon.Hash, error) {
lastByte,
}, 2)
}
+
+func InPlacePublicKeyRoot(key []byte) error {
+ err := MerkleRootFromFlatLeaves(key, key)
+ if err != nil {
+ return err
+ }
+ key = key[:32]
+ return nil
+}
diff --git a/cmd/erigon-cl/core/state/accessors.go b/cmd/erigon-cl/core/state/accessors.go
index 680ecba4671..6745db671ea 100644
--- a/cmd/erigon-cl/core/state/accessors.go
+++ b/cmd/erigon-cl/core/state/accessors.go
@@ -86,7 +86,7 @@ func IsUnslashedParticipatingIndex(b *raw.BeaconState, epoch, index uint64, flag
if err != nil {
return false
}
- return validator.Active(epoch) && b.EpochParticipation(false)[index].HasFlag(flagIdx) && !validator.Slashed
+ return validator.Active(epoch) && b.EpochParticipation(false)[index].HasFlag(flagIdx) && !validator.Slashed()
}
// EligibleValidatorsIndicies Implementation of get_eligible_validator_indices as defined in the eth 2.0 specs.
@@ -95,7 +95,7 @@ func EligibleValidatorsIndicies(b *raw.BeaconState) (eligibleValidators []uint64
previousEpoch := PreviousEpoch(b)
b.ForEachValidator(func(validator *cltypes.Validator, i, total int) bool {
- if validator.Active(previousEpoch) || (validator.Slashed && previousEpoch+1 < validator.WithdrawableEpoch) {
+ if validator.Active(previousEpoch) || (validator.Slashed() && previousEpoch+1 < validator.WithdrawableEpoch()) {
eligibleValidators = append(eligibleValidators, uint64(i))
}
return true
@@ -115,7 +115,8 @@ func IsValidIndexedAttestation(b *raw.BeaconState, att *cltypes.IndexedAttestati
if err != nil {
return false, err
}
- pks = append(pks, val.PublicKey[:])
+ pk := val.PublicKey()
+ pks = append(pks, pk[:])
}
domain, err := b.GetDomain(b.BeaconConfig().DomainBeaconAttester, att.Data.Target.Epoch)
@@ -154,7 +155,7 @@ func GetUnslashedParticipatingIndices(b *raw.BeaconState, flagIndex int, epoch u
b.ForEachValidator(func(validator *cltypes.Validator, i, total int) bool {
if !validator.Active(epoch) ||
!participation[i].HasFlag(flagIndex) ||
- validator.Slashed {
+ validator.Slashed() {
return true
}
validatorSet = append(validatorSet, uint64(i))
@@ -165,14 +166,14 @@ func GetUnslashedParticipatingIndices(b *raw.BeaconState, flagIndex int, epoch u
// Implementation of is_eligible_for_activation_queue. Specs at: https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#is_eligible_for_activation_queue
func IsValidatorEligibleForActivationQueue(b *raw.BeaconState, validator *cltypes.Validator) bool {
- return validator.ActivationEligibilityEpoch == b.BeaconConfig().FarFutureEpoch &&
- validator.EffectiveBalance == b.BeaconConfig().MaxEffectiveBalance
+ return validator.ActivationEligibilityEpoch() == b.BeaconConfig().FarFutureEpoch &&
+ validator.EffectiveBalance() == b.BeaconConfig().MaxEffectiveBalance
}
// Implementation of is_eligible_for_activation. Specs at: https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#is_eligible_for_activation
func IsValidatorEligibleForActivation(b *raw.BeaconState, validator *cltypes.Validator) bool {
- return validator.ActivationEligibilityEpoch <= b.FinalizedCheckpoint().Epoch &&
- validator.ActivationEpoch == b.BeaconConfig().FarFutureEpoch
+ return validator.ActivationEligibilityEpoch() <= b.FinalizedCheckpoint().Epoch &&
+ validator.ActivationEpoch() == b.BeaconConfig().FarFutureEpoch
}
// Check whether a merge transition is complete by verifying the presence of a valid execution payload header.
@@ -204,14 +205,14 @@ func ExpectedWithdrawals(b *raw.BeaconState) []*types.Withdrawal {
// supposedly this operation is safe because we checked the validator length about
currentValidator, _ := b.ValidatorForValidatorIndex(int(nextWithdrawalValidatorIndex))
currentBalance, _ := b.ValidatorBalance(int(nextWithdrawalValidatorIndex))
-
+ wd := currentValidator.WithdrawalCredentials()
// Check if the validator is fully withdrawable
if isFullyWithdrawableValidator(b.BeaconConfig(), currentValidator, currentBalance, currentEpoch) {
// Add a new withdrawal with the validator's withdrawal credentials and balance
newWithdrawal := &types.Withdrawal{
Index: nextWithdrawalIndex,
Validator: nextWithdrawalValidatorIndex,
- Address: libcommon.BytesToAddress(currentValidator.WithdrawalCredentials[12:]),
+ Address: libcommon.BytesToAddress(wd[12:]),
Amount: currentBalance,
}
withdrawals = append(withdrawals, newWithdrawal)
@@ -221,7 +222,7 @@ func ExpectedWithdrawals(b *raw.BeaconState) []*types.Withdrawal {
newWithdrawal := &types.Withdrawal{
Index: nextWithdrawalIndex,
Validator: nextWithdrawalValidatorIndex,
- Address: libcommon.BytesToAddress(currentValidator.WithdrawalCredentials[12:]),
+ Address: libcommon.BytesToAddress(wd[12:]),
Amount: currentBalance - b.BeaconConfig().MaxEffectiveBalance,
}
withdrawals = append(withdrawals, newWithdrawal)
diff --git a/cmd/erigon-cl/core/state/accessors_test.go b/cmd/erigon-cl/core/state/accessors_test.go
index 3d1a2e3922e..2c3f7e88c2c 100644
--- a/cmd/erigon-cl/core/state/accessors_test.go
+++ b/cmd/erigon-cl/core/state/accessors_test.go
@@ -17,10 +17,10 @@ func getTestState(t *testing.T) *state.BeaconState {
numVals := 2048
validators := make([]*cltypes.Validator, numVals)
for i := 0; i < numVals; i++ {
- validators[i] = &cltypes.Validator{
- ActivationEpoch: 0,
- ExitEpoch: 10000,
- }
+ v := &cltypes.Validator{}
+ validators[i] = v
+ v.SetActivationEpoch(0)
+ v.SetExitEpoch(10000)
}
b := state.GetEmptyBeaconState()
b.SetValidators(validators)
@@ -50,10 +50,10 @@ func TestGetBeaconProposerIndex(t *testing.T) {
numVals := 2048
validators := make([]*cltypes.Validator, numVals)
for i := 0; i < numVals; i++ {
- validators[i] = &cltypes.Validator{
- ActivationEpoch: 0,
- ExitEpoch: 10000,
- }
+ v := &cltypes.Validator{}
+ validators[i] = v
+ v.SetActivationEpoch(0)
+ v.SetExitEpoch(10000)
}
testCases := []struct {
description string
@@ -137,7 +137,11 @@ func TestComputeShuffledIndex(t *testing.T) {
func generateBeaconStateWithValidators(n int) *state.BeaconState {
b := state.GetEmptyBeaconState()
for i := 0; i < n; i++ {
- b.AddValidator(&cltypes.Validator{EffectiveBalance: clparams.MainnetBeaconConfig.MaxEffectiveBalance}, clparams.MainnetBeaconConfig.MaxEffectiveBalance)
+ v := &cltypes.Validator{}
+ v.SetActivationEpoch(0)
+ v.SetExitEpoch(10000)
+ v.SetEffectiveBalance(clparams.MainnetBeaconConfig.MaxEffectiveBalance)
+ b.AddValidator(v, clparams.MainnetBeaconConfig.MaxEffectiveBalance)
}
return b
}
@@ -204,7 +208,12 @@ func TestComputeProposerIndex(t *testing.T) {
func TestSyncReward(t *testing.T) {
s := state.GetEmptyBeaconState()
- s.AddValidator(&cltypes.Validator{EffectiveBalance: 3099999999909, ExitEpoch: 2}, 3099999999909)
+
+ v := &cltypes.Validator{}
+ v.SetActivationEpoch(0)
+ v.SetExitEpoch(2)
+ v.SetEffectiveBalance(3099999999909)
+ s.AddValidator(v, 3099999999909)
propReward, partRew, err := s.SyncRewards()
require.NoError(t, err)
require.Equal(t, propReward, uint64(30))
@@ -220,10 +229,10 @@ func TestComputeCommittee(t *testing.T) {
for i := 0; i < len(validators); i++ {
var k [48]byte
copy(k[:], strconv.Itoa(i))
- validators[i] = &cltypes.Validator{
- PublicKey: k,
- ExitEpoch: clparams.MainnetBeaconConfig.FarFutureEpoch,
- }
+ v := &cltypes.Validator{}
+ v.SetExitEpoch(clparams.MainnetBeaconConfig.FarFutureEpoch)
+ v.SetPublicKey(k)
+ validators[i] = v
}
bState := state.GetEmptyBeaconState()
bState.SetValidators(validators)
diff --git a/cmd/erigon-cl/core/state/cache.go b/cmd/erigon-cl/core/state/cache.go
index daededed648..b7d8f0fe5e0 100644
--- a/cmd/erigon-cl/core/state/cache.go
+++ b/cmd/erigon-cl/core/state/cache.go
@@ -184,7 +184,7 @@ func (b *BeaconState) _refreshActiveBalances() {
*b.totalActiveBalanceCache = 0
b.ForEachValidator(func(validator *cltypes.Validator, idx, total int) bool {
if validator.Active(epoch) {
- *b.totalActiveBalanceCache += validator.EffectiveBalance
+ *b.totalActiveBalanceCache += validator.EffectiveBalance()
}
return true
})
@@ -212,7 +212,7 @@ func (b *BeaconState) initBeaconState() error {
b.publicKeyIndicies = make(map[[48]byte]uint64)
b.ForEachValidator(func(validator *cltypes.Validator, i, total int) bool {
- b.publicKeyIndicies[validator.PublicKey] = uint64(i)
+ b.publicKeyIndicies[validator.PublicKey()] = uint64(i)
return true
})
diff --git a/cmd/erigon-cl/core/state/cache_accessors.go b/cmd/erigon-cl/core/state/cache_accessors.go
index 9af55563e8b..caf0ea8e872 100644
--- a/cmd/erigon-cl/core/state/cache_accessors.go
+++ b/cmd/erigon-cl/core/state/cache_accessors.go
@@ -190,7 +190,14 @@ func (b *BeaconState) ComputeNextSyncCommittee() (*cltypes.SyncCommittee, error)
syncCommitteePubKeys := make([][48]byte, 0, cltypes.SyncCommitteeSize)
preInputs := shuffling.ComputeShuffledIndexPreInputs(b.BeaconConfig(), seed)
for len(syncCommitteePubKeys) < cltypes.SyncCommitteeSize {
- shuffledIndex, err := shuffling.ComputeShuffledIndex(b.BeaconConfig(), i%activeValidatorCount, activeValidatorCount, seed, preInputs, optimizedHashFunc)
+ shuffledIndex, err := shuffling.ComputeShuffledIndex(
+ b.BeaconConfig(),
+ i%activeValidatorCount,
+ activeValidatorCount,
+ seed,
+ preInputs,
+ optimizedHashFunc,
+ )
if err != nil {
return nil, err
}
@@ -205,8 +212,8 @@ func (b *BeaconState) ComputeNextSyncCommittee() (*cltypes.SyncCommittee, error)
if err != nil {
return nil, err
}
- if validator.EffectiveBalance*math.MaxUint8 >= beaconConfig.MaxEffectiveBalance*randomByte {
- syncCommitteePubKeys = append(syncCommitteePubKeys, validator.PublicKey)
+ if validator.EffectiveBalance()*math.MaxUint8 >= beaconConfig.MaxEffectiveBalance*randomByte {
+ syncCommitteePubKeys = append(syncCommitteePubKeys, validator.PublicKey())
}
i++
}
diff --git a/cmd/erigon-cl/core/state/cache_mutators.go b/cmd/erigon-cl/core/state/cache_mutators.go
index 4367fb65ede..f4cfd43e3d3 100644
--- a/cmd/erigon-cl/core/state/cache_mutators.go
+++ b/cmd/erigon-cl/core/state/cache_mutators.go
@@ -80,15 +80,15 @@ func (b *BeaconState) InitiateValidatorExit(index uint64) error {
currentEpoch := Epoch(b.BeaconState)
exitQueueEpoch := ComputeActivationExitEpoch(b.BeaconConfig(), currentEpoch)
b.ForEachValidator(func(v *cltypes.Validator, idx, total int) bool {
- if v.ExitEpoch != b.BeaconConfig().FarFutureEpoch && v.ExitEpoch > exitQueueEpoch {
- exitQueueEpoch = v.ExitEpoch
+ if v.ExitEpoch() != b.BeaconConfig().FarFutureEpoch && v.ExitEpoch() > exitQueueEpoch {
+ exitQueueEpoch = v.ExitEpoch()
}
return true
})
exitQueueChurn := 0
b.ForEachValidator(func(v *cltypes.Validator, idx, total int) bool {
- if v.ExitEpoch == exitQueueEpoch {
+ if v.ExitEpoch() == exitQueueEpoch {
exitQueueChurn += 1
}
return true
diff --git a/cmd/erigon-cl/core/state/cache_setters.go b/cmd/erigon-cl/core/state/cache_setters.go
index 69083752368..a1129d9594c 100644
--- a/cmd/erigon-cl/core/state/cache_setters.go
+++ b/cmd/erigon-cl/core/state/cache_setters.go
@@ -16,7 +16,7 @@ func (b *BeaconState) SetSlot(slot uint64) {
func (b *BeaconState) AddValidator(validator *cltypes.Validator, balance uint64) {
b.BeaconState.AddValidator(validator, balance)
- b.publicKeyIndicies[validator.PublicKey] = uint64(b.ValidatorLength()) - 1
+ b.publicKeyIndicies[validator.PublicKey()] = uint64(b.ValidatorLength()) - 1
// change in validator set means cache purging
b.totalActiveBalanceCache = nil
}
diff --git a/cmd/erigon-cl/core/state/copy.go b/cmd/erigon-cl/core/state/copy.go
index ea41bf23d78..0a7cf9d1c7d 100644
--- a/cmd/erigon-cl/core/state/copy.go
+++ b/cmd/erigon-cl/core/state/copy.go
@@ -24,17 +24,19 @@ func (b *BeaconState) copyCachesInto(bs *BeaconState) error {
if b.Version() == clparams.Phase0Version {
return bs.initBeaconState()
}
- bs.publicKeyIndicies = make(map[[48]byte]uint64)
+ if bs.publicKeyIndicies == nil {
+ bs.publicKeyIndicies = make(map[[48]byte]uint64)
+ }
+ for k := range bs.publicKeyIndicies {
+ delete(bs.publicKeyIndicies, k)
+ }
for pk, index := range b.publicKeyIndicies {
bs.publicKeyIndicies[pk] = index
}
// Sync caches
- if err := bs.initCaches(); err != nil {
- return err
- }
- copyLRU(bs.activeValidatorsCache, b.activeValidatorsCache)
- copyLRU(bs.shuffledSetsCache, b.shuffledSetsCache)
- copyLRU(bs.committeeCache, b.committeeCache)
+ bs.activeValidatorsCache = copyLRU(bs.activeValidatorsCache, b.activeValidatorsCache)
+ bs.shuffledSetsCache = copyLRU(bs.shuffledSetsCache, b.shuffledSetsCache)
+ bs.committeeCache = copyLRU(bs.committeeCache, b.committeeCache)
if b.totalActiveBalanceCache != nil {
bs.totalActiveBalanceCache = new(uint64)
diff --git a/cmd/erigon-cl/core/state/mutators_test.go b/cmd/erigon-cl/core/state/mutators_test.go
index 7c04ad35ea8..6b71dc822ab 100644
--- a/cmd/erigon-cl/core/state/mutators_test.go
+++ b/cmd/erigon-cl/core/state/mutators_test.go
@@ -17,7 +17,9 @@ func getTestStateBalances(t *testing.T) *state.BeaconState {
numVals := uint64(2048)
b := state.GetEmptyBeaconState()
for i := uint64(0); i < numVals; i++ {
- b.AddValidator(&cltypes.Validator{ExitEpoch: clparams.MainnetBeaconConfig.FarFutureEpoch}, i)
+ v := &cltypes.Validator{}
+ v.SetExitEpoch(clparams.MainnetBeaconConfig.FarFutureEpoch)
+ b.AddValidator(v, i)
}
return b
}
@@ -25,10 +27,10 @@ func getTestStateBalances(t *testing.T) *state.BeaconState {
func getTestStateValidators(t *testing.T, numVals int) *state.BeaconState {
validators := make([]*cltypes.Validator, numVals)
for i := 0; i < numVals; i++ {
- validators[i] = &cltypes.Validator{
- ActivationEpoch: 0,
- ExitEpoch: testExitEpoch,
- }
+ v := &cltypes.Validator{}
+ v.SetActivationEpoch(0)
+ v.SetExitEpoch(testExitEpoch)
+ validators[i] = v
}
b := state.GetEmptyBeaconState()
b.SetSlot(testExitEpoch * clparams.MainnetBeaconConfig.SlotsPerEpoch)
@@ -40,16 +42,16 @@ func TestIncreaseBalance(t *testing.T) {
s := getTestStateBalances(t)
testInd := uint64(42)
amount := uint64(100)
- beforeBalance := s.Balances()[testInd]
+ beforeBalance, _ := s.ValidatorBalance(int(testInd))
state.IncreaseBalance(s.BeaconState, testInd, amount)
- afterBalance := s.Balances()[testInd]
+ afterBalance, _ := s.ValidatorBalance(int(testInd))
require.Equal(t, afterBalance, beforeBalance+amount)
}
func TestDecreaseBalance(t *testing.T) {
sampleState := getTestStateBalances(t)
testInd := uint64(42)
- beforeBalance := sampleState.Balances()[testInd]
+ beforeBalance, _ := sampleState.ValidatorBalance(int(testInd))
testCases := []struct {
description string
@@ -77,13 +79,21 @@ func TestDecreaseBalance(t *testing.T) {
t.Run(tc.description, func(t *testing.T) {
s := getTestStateBalances(t)
require.NoError(t, state.DecreaseBalance(s.BeaconState, testInd, tc.delta))
- afterBalance := s.Balances()[testInd]
+ afterBalance, _ := s.ValidatorBalance(int(testInd))
require.Equal(t, afterBalance, tc.expectedBalance)
})
}
}
func TestInitiatieValidatorExit(t *testing.T) {
+
+ v1 := &cltypes.Validator{}
+ v1.SetExitEpoch(clparams.MainnetBeaconConfig.FarFutureEpoch)
+ v1.SetActivationEpoch(0)
+ v2 := &cltypes.Validator{}
+ v2.SetExitEpoch(testExitEpoch)
+ v2.SetWithdrawableEpoch(testExitEpoch + clparams.MainnetBeaconConfig.MinValidatorWithdrawabilityDelay)
+ v2.SetActivationEpoch(0)
testCases := []struct {
description string
numValidators uint64
@@ -96,36 +106,29 @@ func TestInitiatieValidatorExit(t *testing.T) {
numValidators: 3,
expectedExitEpoch: 58,
expectedWithdrawlableEpoch: 314,
- validator: &cltypes.Validator{
- ExitEpoch: clparams.MainnetBeaconConfig.FarFutureEpoch,
- ActivationEpoch: 0,
- },
+ validator: v1,
},
{
description: "exit_epoch_set",
numValidators: 3,
expectedExitEpoch: testExitEpoch,
expectedWithdrawlableEpoch: testExitEpoch + clparams.MainnetBeaconConfig.MinValidatorWithdrawabilityDelay,
- validator: &cltypes.Validator{
- ExitEpoch: testExitEpoch,
- WithdrawableEpoch: testExitEpoch + clparams.MainnetBeaconConfig.MinValidatorWithdrawabilityDelay,
- ActivationEpoch: 0,
- },
+ validator: v2,
},
}
for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) {
state := getTestStateValidators(t, int(tc.numValidators))
- state.SetValidators(append(state.Validators(), tc.validator))
- testInd := uint64(len(state.Validators()) - 1)
+ state.AppendValidator(tc.validator)
+ testInd := uint64(state.ValidatorLength() - 1)
state.InitiateValidatorExit(testInd)
val, err := state.ValidatorForValidatorIndex(int(testInd))
require.NoError(t, err)
- if val.ExitEpoch != tc.expectedExitEpoch {
- t.Errorf("unexpected exit epoch: got %d, want %d", val.ExitEpoch, tc.expectedExitEpoch)
+ if val.ExitEpoch() != tc.expectedExitEpoch {
+ t.Errorf("unexpected exit epoch: got %d, want %d", val.ExitEpoch(), tc.expectedExitEpoch)
}
- if val.WithdrawableEpoch != tc.expectedWithdrawlableEpoch {
- t.Errorf("unexpected withdrawable epoch: got %d, want %d", val.WithdrawableEpoch, tc.expectedWithdrawlableEpoch)
+ if val.WithdrawableEpoch() != tc.expectedWithdrawlableEpoch {
+ t.Errorf("unexpected withdrawable epoch: got %d, want %d", val.WithdrawableEpoch(), tc.expectedWithdrawlableEpoch)
}
})
}
@@ -138,18 +141,18 @@ func TestSlashValidator(t *testing.T) {
successState := getTestState(t)
successBalances := []uint64{}
- for i := 0; i < len(successState.Validators()); i++ {
+ for i := 0; i < successState.ValidatorLength(); i++ {
successBalances = append(successBalances, uint64(i+1))
}
successState.SetBalances(successBalances)
// Set up slashed balance.
preSlashBalance := uint64(1 << 20)
- successState.Balances()[slashedInd] = preSlashBalance
+ successState.SetValidatorBalance(slashedInd, preSlashBalance)
vali, err := successState.ValidatorForValidatorIndex(slashedInd)
require.NoError(t, err)
successState.SetValidatorAtIndex(slashedInd, vali)
- vali.EffectiveBalance = preSlashBalance
+ vali.SetEffectiveBalance(preSlashBalance)
testCases := []struct {
description string
@@ -180,7 +183,7 @@ func TestSlashValidator(t *testing.T) {
vali, err := tc.state.ValidatorForValidatorIndex(slashedInd)
require.NoError(t, err)
// Check that the validator is slashed.
- if !vali.Slashed {
+ if !vali.Slashed() {
t.Errorf("slashed index validator not set as slashed")
}
})
diff --git a/cmd/erigon-cl/core/state/raw/copy.go b/cmd/erigon-cl/core/state/raw/copy.go
index d556eb8c5de..36c2ea14863 100644
--- a/cmd/erigon-cl/core/state/raw/copy.go
+++ b/cmd/erigon-cl/core/state/raw/copy.go
@@ -24,21 +24,15 @@ func (b *BeaconState) CopyInto(dst *BeaconState) error {
dst.eth1DepositIndex = b.eth1DepositIndex
for i, validator := range b.validators {
if i >= len(dst.validators) {
- dst.validators = append(dst.validators, validator.Copy())
+ nv := &cltypes.Validator{}
+ validator.CopyTo(nv)
+ dst.validators = append(dst.validators, nv)
continue
}
- copy(dst.validators[i].WithdrawalCredentials[:], validator.WithdrawalCredentials[:])
- copy(dst.validators[i].PublicKey[:], validator.PublicKey[:])
- dst.validators[i].ActivationEligibilityEpoch = validator.ActivationEligibilityEpoch
- dst.validators[i].ActivationEpoch = validator.ActivationEpoch
- dst.validators[i].ExitEpoch = validator.ExitEpoch
- dst.validators[i].EffectiveBalance = validator.EffectiveBalance
- dst.validators[i].Slashed = validator.Slashed
- dst.validators[i].WithdrawableEpoch = validator.WithdrawableEpoch
+ validator.CopyTo(dst.validators[i])
}
dst.validators = dst.validators[:len(b.validators)]
- dst.balances = make([]uint64, len(b.balances))
- copy(dst.balances, b.balances)
+ b.balances.CopyTo(dst.balances)
copy(dst.randaoMixes[:], b.randaoMixes[:])
copy(dst.slashings[:], b.slashings[:])
dst.previousEpochParticipation = b.previousEpochParticipation.Copy()
@@ -47,12 +41,12 @@ func (b *BeaconState) CopyInto(dst *BeaconState) error {
dst.currentJustifiedCheckpoint = b.currentJustifiedCheckpoint.Copy()
dst.previousJustifiedCheckpoint = b.previousJustifiedCheckpoint.Copy()
if b.version == clparams.Phase0Version {
- return dst.init()
+ dst.init()
+ return nil
}
dst.currentSyncCommittee = b.currentSyncCommittee.Copy()
dst.nextSyncCommittee = b.nextSyncCommittee.Copy()
- dst.inactivityScores = make([]uint64, len(b.inactivityScores))
- copy(dst.inactivityScores, b.inactivityScores)
+ b.inactivityScores.CopyTo(dst.inactivityScores)
dst.justificationBits = b.justificationBits.Copy()
if b.version >= clparams.BellatrixVersion {
diff --git a/cmd/erigon-cl/core/state/raw/getters.go b/cmd/erigon-cl/core/state/raw/getters.go
index 9ac07c3a77a..c9eecf34a34 100644
--- a/cmd/erigon-cl/core/state/raw/getters.go
+++ b/cmd/erigon-cl/core/state/raw/getters.go
@@ -75,13 +75,12 @@ func (b *BeaconState) Eth1DepositIndex() uint64 {
return b.eth1DepositIndex
}
-func (b *BeaconState) Validators() []*cltypes.Validator {
- return b.validators
-}
-
func (b *BeaconState) ValidatorLength() int {
return len(b.validators)
}
+func (b *BeaconState) AppendValidator(in *cltypes.Validator) {
+ b.validators = append(b.validators, in)
+}
func (b *BeaconState) ForEachValidator(fn func(v *cltypes.Validator, idx int, total int) bool) {
for idx, v := range b.validators {
@@ -99,36 +98,32 @@ func (b *BeaconState) ValidatorForValidatorIndex(index int) (*cltypes.Validator,
return b.validators[index], nil
}
-func (b *BeaconState) Balances() []uint64 {
- return b.balances
-}
-
func (b *BeaconState) ValidatorBalance(index int) (uint64, error) {
- if index >= len(b.balances) {
+ if index >= b.balances.Length() {
return 0, ErrInvalidValidatorIndex
}
- return b.balances[index], nil
+ return b.balances.Get(index), nil
}
func (b *BeaconState) ValidatorExitEpoch(index int) (uint64, error) {
if index >= len(b.validators) {
return 0, ErrInvalidValidatorIndex
}
- return b.validators[index].ExitEpoch, nil
+ return b.validators[index].ExitEpoch(), nil
}
func (b *BeaconState) ValidatorWithdrawableEpoch(index int) (uint64, error) {
if index >= len(b.validators) {
return 0, ErrInvalidValidatorIndex
}
- return b.validators[index].WithdrawableEpoch, nil
+ return b.validators[index].WithdrawableEpoch(), nil
}
func (b *BeaconState) ValidatorEffectiveBalance(index int) (uint64, error) {
if index >= len(b.validators) {
return 0, ErrInvalidValidatorIndex
}
- return b.validators[index].EffectiveBalance, nil
+ return b.validators[index].EffectiveBalance(), nil
}
func (b *BeaconState) ValidatorMinCurrentInclusionDelayAttestation(index int) (*cltypes.PendingAttestation, error) {
@@ -196,15 +191,11 @@ func (b *BeaconState) CurrentJustifiedCheckpoint() *cltypes.Checkpoint {
return b.currentJustifiedCheckpoint
}
-func (b *BeaconState) InactivityScores() []uint64 {
- return b.inactivityScores
-}
-
func (b *BeaconState) ValidatorInactivityScore(index int) (uint64, error) {
- if len(b.inactivityScores) <= index {
+ if b.inactivityScores.Length() <= index {
return 0, ErrInvalidValidatorIndex
}
- return b.inactivityScores[index], nil
+ return b.inactivityScores.Get(index), nil
}
func (b *BeaconState) FinalizedCheckpoint() *cltypes.Checkpoint {
@@ -261,7 +252,7 @@ func (b *BeaconState) GetBlockRootAtSlot(slot uint64) (libcommon.Hash, error) {
return b.blockRoots[slot%b.BeaconConfig().SlotsPerHistoricalRoot], nil
}
-// GetBl
+// GetDomain
func (b *BeaconState) GetDomain(domainType [4]byte, epoch uint64) ([]byte, error) {
if epoch < b.fork.Epoch {
return fork.ComputeDomain(domainType[:], b.fork.PreviousVersion, b.genesisValidatorsRoot)
diff --git a/cmd/erigon-cl/core/state/raw/hashing.go b/cmd/erigon-cl/core/state/raw/hashing.go
index 60996358882..ecc44459e59 100644
--- a/cmd/erigon-cl/core/state/raw/hashing.go
+++ b/cmd/erigon-cl/core/state/raw/hashing.go
@@ -130,10 +130,8 @@ func (b *BeaconState) computeDirtyLeaves() error {
// Field(12): Balances
if b.isLeafDirty(BalancesLeafIndex) {
- root, err := merkle_tree.Uint64ListRootWithLimit(b.balances, state_encoding.ValidatorLimitForBalancesChunks())
- if err != nil {
- return err
- }
+ root := [32]byte{}
+ b.balances.HashSSZTo(root[:])
b.updateLeaf(BalancesLeafIndex, root)
}
@@ -226,10 +224,8 @@ func (b *BeaconState) computeDirtyLeaves() error {
}
// Field(21): Inactivity Scores
if b.isLeafDirty(InactivityScoresLeafIndex) {
- root, err := merkle_tree.Uint64ListRootWithLimit(b.inactivityScores, state_encoding.ValidatorLimitForBalancesChunks())
- if err != nil {
- return err
- }
+ root := [32]byte{}
+ b.inactivityScores.HashSSZTo(root[:])
b.updateLeaf(InactivityScoresLeafIndex, root)
}
diff --git a/cmd/erigon-cl/core/state/raw/setters.go b/cmd/erigon-cl/core/state/raw/setters.go
index 7afd32cced8..965e7a260e5 100644
--- a/cmd/erigon-cl/core/state/raw/setters.go
+++ b/cmd/erigon-cl/core/state/raw/setters.go
@@ -42,32 +42,32 @@ func (b *BeaconState) SetHistoricalRootAt(index int, root [32]byte) {
func (b *BeaconState) SetWithdrawalCredentialForValidatorAtIndex(index int, creds libcommon.Hash) {
b.markLeaf(ValidatorsLeafIndex)
- b.validators[index].WithdrawalCredentials = creds
+ b.validators[index].SetWithdrawalCredentials(creds)
}
func (b *BeaconState) SetExitEpochForValidatorAtIndex(index int, epoch uint64) {
b.markLeaf(ValidatorsLeafIndex)
- b.validators[index].ExitEpoch = epoch
+ b.validators[index].SetExitEpoch(epoch)
}
func (b *BeaconState) SetWithdrawableEpochForValidatorAtIndex(index int, epoch uint64) {
b.markLeaf(ValidatorsLeafIndex)
- b.validators[index].WithdrawableEpoch = epoch
+ b.validators[index].SetWithdrawableEpoch(epoch)
}
func (b *BeaconState) SetEffectiveBalanceForValidatorAtIndex(index int, balance uint64) {
b.markLeaf(ValidatorsLeafIndex)
- b.validators[index].EffectiveBalance = balance
+ b.validators[index].SetEffectiveBalance(balance)
}
func (b *BeaconState) SetActivationEpochForValidatorAtIndex(index int, epoch uint64) {
b.markLeaf(ValidatorsLeafIndex)
- b.validators[index].ActivationEpoch = epoch
+ b.validators[index].SetActivationEpoch(epoch)
}
func (b *BeaconState) SetActivationEligibilityEpochForValidatorAtIndex(index int, epoch uint64) {
b.markLeaf(ValidatorsLeafIndex)
- b.validators[index].ActivationEligibilityEpoch = epoch
+ b.validators[index].SetActivationEligibilityEpoch(epoch)
}
func (b *BeaconState) SetEth1Data(eth1Data *cltypes.Eth1Data) {
@@ -91,24 +91,24 @@ func (b *BeaconState) SetEth1DepositIndex(eth1DepositIndex uint64) {
}
func (b *BeaconState) SetValidatorSlashed(index int, slashed bool) error {
- if index >= len(b.balances) {
+ if index >= b.balances.Length() {
return ErrInvalidValidatorIndex
}
b.markLeaf(ValidatorsLeafIndex)
- b.validators[index].Slashed = slashed
+ b.validators[index].SetSlashed(slashed)
return nil
}
func (b *BeaconState) SetValidatorWithdrawableEpoch(index int, epoch uint64) error {
- if index >= len(b.balances) {
+ if index >= b.balances.Length() {
return ErrInvalidValidatorIndex
}
b.markLeaf(ValidatorsLeafIndex)
- b.validators[index].WithdrawableEpoch = epoch
+ b.validators[index].SetWithdrawableEpoch(epoch)
return nil
}
func (b *BeaconState) SetValidatorMinCurrentInclusionDelayAttestation(index int, value *cltypes.PendingAttestation) error {
- if index >= len(b.balances) {
+ if index >= b.balances.Length() {
return ErrInvalidValidatorIndex
}
b.markLeaf(ValidatorsLeafIndex)
@@ -116,7 +116,7 @@ func (b *BeaconState) SetValidatorMinCurrentInclusionDelayAttestation(index int,
return nil
}
func (b *BeaconState) SetValidatorIsCurrentMatchingSourceAttester(index int, value bool) error {
- if index >= len(b.balances) {
+ if index >= b.balances.Length() {
return ErrInvalidValidatorIndex
}
b.markLeaf(ValidatorsLeafIndex)
@@ -124,7 +124,7 @@ func (b *BeaconState) SetValidatorIsCurrentMatchingSourceAttester(index int, val
return nil
}
func (b *BeaconState) SetValidatorIsCurrentMatchingTargetAttester(index int, value bool) error {
- if index >= len(b.balances) {
+ if index >= b.balances.Length() {
return ErrInvalidValidatorIndex
}
b.markLeaf(ValidatorsLeafIndex)
@@ -132,7 +132,7 @@ func (b *BeaconState) SetValidatorIsCurrentMatchingTargetAttester(index int, val
return nil
}
func (b *BeaconState) SetValidatorIsCurrentMatchingHeadAttester(index int, value bool) error {
- if index >= len(b.balances) {
+ if index >= b.balances.Length() {
return ErrInvalidValidatorIndex
}
b.markLeaf(ValidatorsLeafIndex)
@@ -140,7 +140,7 @@ func (b *BeaconState) SetValidatorIsCurrentMatchingHeadAttester(index int, value
return nil
}
func (b *BeaconState) SetValidatorMinPreviousInclusionDelayAttestation(index int, value *cltypes.PendingAttestation) error {
- if index >= len(b.balances) {
+ if index >= b.balances.Length() {
return ErrInvalidValidatorIndex
}
b.markLeaf(ValidatorsLeafIndex)
@@ -148,7 +148,7 @@ func (b *BeaconState) SetValidatorMinPreviousInclusionDelayAttestation(index int
return nil
}
func (b *BeaconState) SetValidatorIsPreviousMatchingSourceAttester(index int, value bool) error {
- if index >= len(b.balances) {
+ if index >= b.balances.Length() {
return ErrInvalidValidatorIndex
}
b.markLeaf(ValidatorsLeafIndex)
@@ -156,7 +156,7 @@ func (b *BeaconState) SetValidatorIsPreviousMatchingSourceAttester(index int, va
return nil
}
func (b *BeaconState) SetValidatorIsPreviousMatchingTargetAttester(index int, value bool) error {
- if index >= len(b.balances) {
+ if index >= b.balances.Length() {
return ErrInvalidValidatorIndex
}
b.markLeaf(ValidatorsLeafIndex)
@@ -164,7 +164,7 @@ func (b *BeaconState) SetValidatorIsPreviousMatchingTargetAttester(index int, va
return nil
}
func (b *BeaconState) SetValidatorIsPreviousMatchingHeadAttester(index int, value bool) error {
- if index >= len(b.balances) {
+ if index >= b.balances.Length() {
return ErrInvalidValidatorIndex
}
b.markLeaf(ValidatorsLeafIndex)
@@ -173,11 +173,11 @@ func (b *BeaconState) SetValidatorIsPreviousMatchingHeadAttester(index int, valu
}
func (b *BeaconState) SetValidatorBalance(index int, balance uint64) error {
- if index >= len(b.balances) {
+ if index >= b.balances.Length() {
return ErrInvalidValidatorIndex
}
b.markLeaf(BalancesLeafIndex)
- b.balances[index] = balance
+ b.balances.Set(index, balance)
return nil
}
@@ -190,7 +190,7 @@ func (b *BeaconState) SetValidators(validators []*cltypes.Validator) error {
func (b *BeaconState) AddValidator(validator *cltypes.Validator, balance uint64) {
b.validators = append(b.validators, validator)
- b.balances = append(b.balances, balance)
+ b.balances.Append(balance)
b.markLeaf(ValidatorsLeafIndex)
b.markLeaf(BalancesLeafIndex)
@@ -198,7 +198,10 @@ func (b *BeaconState) AddValidator(validator *cltypes.Validator, balance uint64)
func (b *BeaconState) SetBalances(balances []uint64) {
b.markLeaf(BalancesLeafIndex)
- b.balances = balances
+ b.balances.Clear()
+ for _, v := range balances {
+ b.balances.Append(v)
+ }
}
func (b *BeaconState) SetRandaoMixAt(index int, mix libcommon.Hash) {
@@ -297,21 +300,24 @@ func (b *BeaconState) AddHistoricalRoot(root libcommon.Hash) {
}
func (b *BeaconState) SetInactivityScores(scores []uint64) {
- b.inactivityScores = scores
+ b.inactivityScores.Clear()
+ for _, v := range scores {
+ b.inactivityScores.Append(v)
+ }
b.markLeaf(InactivityScoresLeafIndex)
}
func (b *BeaconState) AddInactivityScore(score uint64) {
- b.inactivityScores = append(b.inactivityScores, score)
+ b.inactivityScores.Append(score)
b.markLeaf(InactivityScoresLeafIndex)
}
func (b *BeaconState) SetValidatorInactivityScore(index int, score uint64) error {
- if index >= len(b.inactivityScores) {
+ if index >= b.inactivityScores.Length() {
return ErrInvalidValidatorIndex
}
b.markLeaf(InactivityScoresLeafIndex)
- b.inactivityScores[index] = score
+ b.inactivityScores.Set(index, score)
return nil
}
diff --git a/cmd/erigon-cl/core/state/raw/ssz.go b/cmd/erigon-cl/core/state/raw/ssz.go
index 5a51a6a6cc7..fd923552a2e 100644
--- a/cmd/erigon-cl/core/state/raw/ssz.go
+++ b/cmd/erigon-cl/core/state/raw/ssz.go
@@ -66,7 +66,7 @@ func (b *BeaconState) EncodeSSZ(buf []byte) ([]byte, error) {
return nil, fmt.Errorf("too many validators")
}
- if len(b.balances) > state_encoding.ValidatorRegistryLimit {
+ if b.balances.Length() > state_encoding.ValidatorRegistryLimit {
return nil, fmt.Errorf("too many balances")
}
@@ -79,7 +79,7 @@ func (b *BeaconState) EncodeSSZ(buf []byte) ([]byte, error) {
return nil, fmt.Errorf("too many participations")
}
- if len(b.inactivityScores) > state_encoding.ValidatorRegistryLimit {
+ if b.inactivityScores.Length() > state_encoding.ValidatorRegistryLimit {
return nil, fmt.Errorf("too many inactivities scores")
}
// Start encoding
@@ -124,7 +124,7 @@ func (b *BeaconState) EncodeSSZ(buf []byte) ([]byte, error) {
// balances offset
dst = append(dst, ssz.OffsetSSZ(offset)...)
- offset += uint32(len(b.balances)) * 8
+ offset += uint32(b.balances.Length()) * 8
for _, mix := range &b.randaoMixes {
dst = append(dst, mix[:]...)
@@ -172,7 +172,7 @@ func (b *BeaconState) EncodeSSZ(buf []byte) ([]byte, error) {
// Inactivity scores offset
dst = append(dst, ssz.OffsetSSZ(offset)...)
- offset += uint32(len(b.inactivityScores)) * 8
+ offset += uint32(b.inactivityScores.Length()) * 8
// Sync commitees
if dst, err = b.currentSyncCommittee.EncodeSSZ(dst); err != nil {
@@ -211,9 +211,10 @@ func (b *BeaconState) EncodeSSZ(buf []byte) ([]byte, error) {
}
}
// Write balances (offset 4)
- for _, balance := range b.balances {
- dst = append(dst, ssz.Uint64SSZ(balance)...)
- }
+ b.balances.Range(func(index int, value uint64, length int) bool {
+ dst = append(dst, ssz.Uint64SSZ(value)...)
+ return true
+ })
// Write participations (offset 4 & 5)
if b.version == clparams.Phase0Version {
@@ -229,9 +230,10 @@ func (b *BeaconState) EncodeSSZ(buf []byte) ([]byte, error) {
}
if b.version >= clparams.AltairVersion {
// write inactivity scores (offset 6)
- for _, score := range b.inactivityScores {
- dst = append(dst, ssz.Uint64SSZ(score)...)
- }
+ b.inactivityScores.Range(func(index int, value uint64, length int) bool {
+ dst = append(dst, ssz.Uint64SSZ(value)...)
+ return true
+ })
}
// write execution header (offset 7)
@@ -384,9 +386,11 @@ func (b *BeaconState) DecodeSSZ(buf []byte, version int) error {
if b.validators, err = ssz.DecodeStaticList[*cltypes.Validator](buf, validatorsOffset, balancesOffset, 121, state_encoding.ValidatorRegistryLimit, version); err != nil {
return err
}
- if b.balances, err = ssz.DecodeNumbersList(buf, balancesOffset, previousEpochParticipationOffset, state_encoding.ValidatorRegistryLimit); err != nil {
+ rawBalances, err := ssz.DecodeNumbersList(buf, balancesOffset, previousEpochParticipationOffset, state_encoding.ValidatorRegistryLimit)
+ if err != nil {
return err
}
+ b.SetBalances(rawBalances)
if b.version == clparams.Phase0Version {
maxAttestations := b.beaconConfig.SlotsPerEpoch * b.beaconConfig.MaxAttestations
if b.previousEpochAttestations, err = ssz.DecodeDynamicList[*cltypes.PendingAttestation](buf, previousEpochParticipationOffset, currentEpochParticipationOffset, maxAttestations, version); err != nil {
@@ -412,9 +416,11 @@ func (b *BeaconState) DecodeSSZ(buf []byte, version int) error {
if executionPayloadOffset != 0 {
endOffset = executionPayloadOffset
}
- if b.inactivityScores, err = ssz.DecodeNumbersList(buf, inactivityScoresOffset, endOffset, state_encoding.ValidatorRegistryLimit); err != nil {
+ inactivityScores, err := ssz.DecodeNumbersList(buf, inactivityScoresOffset, endOffset, state_encoding.ValidatorRegistryLimit)
+ if err != nil {
return err
}
+ b.SetInactivityScores(inactivityScores)
if b.version == clparams.AltairVersion {
return b.init()
}
@@ -445,7 +451,7 @@ func (b *BeaconState) EncodingSizeSSZ() (size int) {
size = int(b.baseOffsetSSZ()) + (len(b.historicalRoots) * 32)
size += len(b.eth1DataVotes) * 72
size += len(b.validators) * 121
- size += len(b.balances) * 8
+ size += b.balances.Length() * 8
if b.version == clparams.Phase0Version {
for _, pendingAttestation := range b.previousEpochAttestations {
size += pendingAttestation.EncodingSizeSSZ()
@@ -458,7 +464,7 @@ func (b *BeaconState) EncodingSizeSSZ() (size int) {
size += len(b.currentEpochParticipation)
}
- size += len(b.inactivityScores) * 8
+ size += b.inactivityScores.Length() * 8
size += len(b.historicalSummaries) * 64
return
}
diff --git a/cmd/erigon-cl/core/state/raw/state.go b/cmd/erigon-cl/core/state/raw/state.go
index 7f7f257b359..1c0556cf2b3 100644
--- a/cmd/erigon-cl/core/state/raw/state.go
+++ b/cmd/erigon-cl/core/state/raw/state.go
@@ -4,6 +4,7 @@ import (
"github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon/cl/clparams"
"github.com/ledgerwatch/erigon/cl/cltypes"
+ "github.com/ledgerwatch/erigon/cl/cltypes/solid"
)
const (
@@ -27,7 +28,7 @@ type BeaconState struct {
eth1DataVotes []*cltypes.Eth1Data
eth1DepositIndex uint64
validators []*cltypes.Validator
- balances []uint64
+ balances solid.Uint64Slice
randaoMixes [randoMixesLength]common.Hash
slashings [slashingsLength]uint64
previousEpochParticipation cltypes.ParticipationFlagsList
@@ -37,7 +38,7 @@ type BeaconState struct {
previousJustifiedCheckpoint *cltypes.Checkpoint
currentJustifiedCheckpoint *cltypes.Checkpoint
finalizedCheckpoint *cltypes.Checkpoint
- inactivityScores []uint64
+ inactivityScores solid.Uint64Slice
currentSyncCommittee *cltypes.SyncCommittee
nextSyncCommittee *cltypes.SyncCommittee
// Bellatrix
@@ -62,6 +63,9 @@ type BeaconState struct {
func New(cfg *clparams.BeaconChainConfig) *BeaconState {
state := &BeaconState{
beaconConfig: cfg,
+ //inactivityScores: solid.NewSimpleUint64Slice(int(cfg.ValidatorRegistryLimit)),
+ inactivityScores: solid.NewUint64Slice(int(cfg.ValidatorRegistryLimit)),
+ balances: solid.NewUint64Slice(int(cfg.ValidatorRegistryLimit)),
}
state.init()
return state
@@ -72,5 +76,4 @@ func (b *BeaconState) init() error {
b.touchedLeaves = make(map[StateLeafIndex]bool)
}
return nil
-
}
diff --git a/cmd/erigon-cl/core/state/raw/test_util.go b/cmd/erigon-cl/core/state/raw/test_util.go
index bc0d3bb185c..78b251cace6 100644
--- a/cmd/erigon-cl/core/state/raw/test_util.go
+++ b/cmd/erigon-cl/core/state/raw/test_util.go
@@ -3,9 +3,11 @@ package raw
import (
"github.com/ledgerwatch/erigon/cl/clparams"
"github.com/ledgerwatch/erigon/cl/cltypes"
+ "github.com/ledgerwatch/erigon/cl/cltypes/solid"
)
func GetEmptyBeaconState() *BeaconState {
+ cfg := &clparams.MainnetBeaconConfig
b := &BeaconState{
fork: &cltypes.Fork{},
latestBlockHeader: &cltypes.BeaconBlockHeader{},
@@ -21,7 +23,9 @@ func GetEmptyBeaconState() *BeaconState {
finalizedCheckpoint: &cltypes.Checkpoint{},
latestExecutionPayloadHeader: cltypes.NewEth1Header(clparams.BellatrixVersion),
version: clparams.BellatrixVersion,
- beaconConfig: &clparams.MainnetBeaconConfig,
+ beaconConfig: cfg,
+ inactivityScores: solid.NewUint64Slice(int(cfg.ValidatorRegistryLimit)),
+ balances: solid.NewUint64Slice(int(cfg.ValidatorRegistryLimit)),
}
b.init()
return b
diff --git a/cmd/erigon-cl/core/state/shuffling/shuffling.go b/cmd/erigon-cl/core/state/shuffling/shuffling.go
index 5fc375bf6fb..9c39fda4c89 100644
--- a/cmd/erigon-cl/core/state/shuffling/shuffling.go
+++ b/cmd/erigon-cl/core/state/shuffling/shuffling.go
@@ -33,7 +33,7 @@ func ComputeProposerIndex(b *raw.BeaconState, indices []uint64, seed [32]byte) (
if err != nil {
return 0, err
}
- if validator.EffectiveBalance*maxRandomByte >= b.BeaconConfig().MaxEffectiveBalance*randomByte {
+ if validator.EffectiveBalance()*maxRandomByte >= b.BeaconConfig().MaxEffectiveBalance*randomByte {
return candidateIndex, nil
}
i += 1
diff --git a/cmd/erigon-cl/core/state/util.go b/cmd/erigon-cl/core/state/util.go
index 6e41a9a2069..f88a1df61c6 100644
--- a/cmd/erigon-cl/core/state/util.go
+++ b/cmd/erigon-cl/core/state/util.go
@@ -13,6 +13,7 @@ func copyLRU[K comparable, V any](dst *lru.Cache[K, V], src *lru.Cache[K, V]) *l
if dst == nil {
dst = new(lru.Cache[K, V])
}
+ dst.Purge()
for _, key := range src.Keys() {
val, has := src.Get(key)
if !has {
@@ -39,27 +40,27 @@ func ValidatorFromDeposit(conf *clparams.BeaconChainConfig, deposit *cltypes.Dep
amount := deposit.Data.Amount
effectiveBalance := utils.Min64(amount-amount%conf.EffectiveBalanceIncrement, conf.MaxEffectiveBalance)
- return &cltypes.Validator{
- PublicKey: deposit.Data.PubKey,
- WithdrawalCredentials: deposit.Data.WithdrawalCredentials,
- ActivationEligibilityEpoch: conf.FarFutureEpoch,
- ActivationEpoch: conf.FarFutureEpoch,
- ExitEpoch: conf.FarFutureEpoch,
- WithdrawableEpoch: conf.FarFutureEpoch,
- EffectiveBalance: effectiveBalance,
- }
+ validator := &cltypes.Validator{}
+ validator.SetPublicKey(deposit.Data.PubKey)
+ validator.SetWithdrawalCredentials(deposit.Data.WithdrawalCredentials)
+ validator.SetActivationEligibilityEpoch(conf.FarFutureEpoch)
+ validator.SetActivationEpoch(conf.FarFutureEpoch)
+ validator.SetExitEpoch(conf.FarFutureEpoch)
+ validator.SetWithdrawableEpoch(conf.FarFutureEpoch)
+ validator.SetEffectiveBalance(effectiveBalance)
+ return validator
}
// Check whether a validator is fully withdrawable at the given epoch.
func isFullyWithdrawableValidator(conf *clparams.BeaconChainConfig, validator *cltypes.Validator, balance uint64, epoch uint64) bool {
- return validator.WithdrawalCredentials[0] == conf.ETH1AddressWithdrawalPrefixByte &&
- validator.WithdrawableEpoch <= epoch && balance > 0
+ return validator.WithdrawalCredentials()[0] == conf.ETH1AddressWithdrawalPrefixByte &&
+ validator.WithdrawableEpoch() <= epoch && balance > 0
}
// Check whether a validator is partially withdrawable.
func isPartiallyWithdrawableValidator(conf *clparams.BeaconChainConfig, validator *cltypes.Validator, balance uint64) bool {
- return validator.WithdrawalCredentials[0] == conf.ETH1AddressWithdrawalPrefixByte &&
- validator.EffectiveBalance == conf.MaxEffectiveBalance && balance > conf.MaxEffectiveBalance
+ return validator.WithdrawalCredentials()[0] == conf.ETH1AddressWithdrawalPrefixByte &&
+ validator.EffectiveBalance() == conf.MaxEffectiveBalance && balance > conf.MaxEffectiveBalance
}
func ComputeActivationExitEpoch(config *clparams.BeaconChainConfig, epoch uint64) uint64 {
diff --git a/cmd/erigon-cl/core/transition/finalization_and_justification.go b/cmd/erigon-cl/core/transition/finalization_and_justification.go
index f6a4fcedcc9..7b7153c173e 100644
--- a/cmd/erigon-cl/core/transition/finalization_and_justification.go
+++ b/cmd/erigon-cl/core/transition/finalization_and_justification.go
@@ -71,33 +71,35 @@ func ProcessJustificationBitsAndFinality(s *state.BeaconState) error {
}
var previousTargetBalance, currentTargetBalance uint64
if s.Version() == clparams.Phase0Version {
- for _, validator := range s.Validators() {
- if validator.Slashed {
- continue
+ s.ForEachValidator(func(validator *cltypes.Validator, idx, total int) bool {
+ if validator.Slashed() {
+ return true
}
if validator.IsCurrentMatchingTargetAttester {
- currentTargetBalance += validator.EffectiveBalance
+ currentTargetBalance += validator.EffectiveBalance()
}
if validator.IsPreviousMatchingTargetAttester {
- previousTargetBalance += validator.EffectiveBalance
+ previousTargetBalance += validator.EffectiveBalance()
}
- }
+ return true
+ })
} else {
// Use bitlists to determine finality.
previousParticipation, currentParticipation := s.EpochParticipation(false), s.EpochParticipation(true)
- for i, validator := range s.Validators() {
- if validator.Slashed {
- continue
+ s.ForEachValidator(func(validator *cltypes.Validator, i, total int) bool {
+ if validator.Slashed() {
+ return true
}
if validator.Active(previousEpoch) &&
previousParticipation[i].HasFlag(int(beaconConfig.TimelyTargetFlagIndex)) {
- previousTargetBalance += validator.EffectiveBalance
+ previousTargetBalance += validator.EffectiveBalance()
}
if validator.Active(currentEpoch) &&
currentParticipation[i].HasFlag(int(beaconConfig.TimelyTargetFlagIndex)) {
- currentTargetBalance += validator.EffectiveBalance
+ currentTargetBalance += validator.EffectiveBalance()
}
- }
+ return true
+ })
}
return weighJustificationAndFinalization(s, previousTargetBalance, currentTargetBalance)
diff --git a/cmd/erigon-cl/core/transition/operations.go b/cmd/erigon-cl/core/transition/operations.go
index 71994641ed2..370e5e79415 100644
--- a/cmd/erigon-cl/core/transition/operations.go
+++ b/cmd/erigon-cl/core/transition/operations.go
@@ -56,12 +56,13 @@ func ProcessProposerSlashing(s *state.BeaconState, propSlashing *cltypes.Propose
if err != nil {
return fmt.Errorf("unable to compute signing root: %v", err)
}
- valid, err := bls.Verify(signedHeader.Signature[:], signingRoot[:], proposer.PublicKey[:])
+ pk := proposer.PublicKey()
+ valid, err := bls.Verify(signedHeader.Signature[:], signingRoot[:], pk[:])
if err != nil {
return fmt.Errorf("unable to verify signature: %v", err)
}
if !valid {
- return fmt.Errorf("invalid signature: signature %v, root %v, pubkey %v", signedHeader.Signature[:], signingRoot[:], proposer.PublicKey[:])
+ return fmt.Errorf("invalid signature: signature %v, root %v, pubkey %v", signedHeader.Signature[:], signingRoot[:], pk)
}
}
@@ -187,13 +188,13 @@ func ProcessVoluntaryExit(s *state.BeaconState, signedVoluntaryExit *cltypes.Sig
if !validator.Active(currentEpoch) {
return errors.New("ProcessVoluntaryExit: validator is not active")
}
- if validator.ExitEpoch != s.BeaconConfig().FarFutureEpoch {
+ if validator.ExitEpoch() != s.BeaconConfig().FarFutureEpoch {
return errors.New("ProcessVoluntaryExit: another exit for the same validator is already getting processed")
}
if currentEpoch < voluntaryExit.Epoch {
return errors.New("ProcessVoluntaryExit: exit is happening in the future")
}
- if currentEpoch < validator.ActivationEpoch+s.BeaconConfig().ShardCommitteePeriod {
+ if currentEpoch < validator.ActivationEpoch()+s.BeaconConfig().ShardCommitteePeriod {
return errors.New("ProcessVoluntaryExit: exit is happening too fast")
}
@@ -207,7 +208,8 @@ func ProcessVoluntaryExit(s *state.BeaconState, signedVoluntaryExit *cltypes.Sig
if err != nil {
return err
}
- valid, err := bls.Verify(signedVoluntaryExit.Signature[:], signingRoot[:], validator.PublicKey[:])
+ pk := validator.PublicKey()
+ valid, err := bls.Verify(signedVoluntaryExit.Signature[:], signingRoot[:], pk[:])
if err != nil {
return err
}
@@ -225,7 +227,7 @@ func ProcessWithdrawals(s *state.BeaconState, withdrawals types.Withdrawals, ful
// Get the list of withdrawals, the expected withdrawals (if performing full validation),
// and the beacon configuration.
beaconConfig := s.BeaconConfig()
- numValidators := uint64(len(s.Validators()))
+ numValidators := uint64(s.ValidatorLength())
// Check if full validation is required and verify expected withdrawals.
if fullValidation {
diff --git a/cmd/erigon-cl/core/transition/process_attestations.go b/cmd/erigon-cl/core/transition/process_attestations.go
index 1605e3146d5..aad7f144854 100644
--- a/cmd/erigon-cl/core/transition/process_attestations.go
+++ b/cmd/erigon-cl/core/transition/process_attestations.go
@@ -54,9 +54,13 @@ func processAttestationPostAltair(s *state.BeaconState, attestation *cltypes.Att
isCurrentEpoch := data.Target.Epoch == currentEpoch
- validators := s.Validators()
for _, attesterIndex := range attestingIndicies {
- baseReward := (validators[attesterIndex].EffectiveBalance / beaconConfig.EffectiveBalanceIncrement) * baseRewardPerIncrement
+ val, err := s.ValidatorEffectiveBalance(int(attesterIndex))
+ if err != nil {
+ return nil, err
+ }
+
+ baseReward := (val / beaconConfig.EffectiveBalanceIncrement) * baseRewardPerIncrement
for flagIndex, weight := range beaconConfig.ParticipationWeights() {
flagParticipation := s.EpochParticipationForValidatorIndex(isCurrentEpoch, int(attesterIndex))
if !slices.Contains(participationFlagsIndicies, uint8(flagIndex)) || flagParticipation.HasFlag(flagIndex) {
diff --git a/cmd/erigon-cl/core/transition/process_bls_to_execution_change.go b/cmd/erigon-cl/core/transition/process_bls_to_execution_change.go
index 9b0e0686f59..66e811e0b87 100644
--- a/cmd/erigon-cl/core/transition/process_bls_to_execution_change.go
+++ b/cmd/erigon-cl/core/transition/process_bls_to_execution_change.go
@@ -22,15 +22,16 @@ func ProcessBlsToExecutionChange(state *state.BeaconState, signedChange *cltypes
}
// Perform full validation if requested.
+ wc := validator.WithdrawalCredentials()
if fullValidation {
// Check the validator's withdrawal credentials prefix.
- if validator.WithdrawalCredentials[0] != beaconConfig.BLSWithdrawalPrefixByte {
+ if wc[0] != beaconConfig.BLSWithdrawalPrefixByte {
return fmt.Errorf("invalid withdrawal credentials prefix")
}
// Check the validator's withdrawal credentials against the provided message.
hashedFrom := utils.Keccak256(change.From[:])
- if !bytes.Equal(hashedFrom[1:], validator.WithdrawalCredentials[1:]) {
+ if !bytes.Equal(hashedFrom[1:], wc[1:]) {
return fmt.Errorf("invalid withdrawal credentials")
}
@@ -51,7 +52,7 @@ func ProcessBlsToExecutionChange(state *state.BeaconState, signedChange *cltypes
return fmt.Errorf("invalid signature")
}
}
- credentials := validator.WithdrawalCredentials
+ credentials := wc
// Reset the validator's withdrawal credentials.
credentials[0] = beaconConfig.ETH1AddressWithdrawalPrefixByte
copy(credentials[1:], make([]byte, 11))
diff --git a/cmd/erigon-cl/core/transition/process_effective_balance_update.go b/cmd/erigon-cl/core/transition/process_effective_balance_update.go
index a6c9d58508f..e98cc39c94d 100644
--- a/cmd/erigon-cl/core/transition/process_effective_balance_update.go
+++ b/cmd/erigon-cl/core/transition/process_effective_balance_update.go
@@ -1,6 +1,7 @@
package transition
import (
+ "github.com/ledgerwatch/erigon/cl/cltypes"
"github.com/ledgerwatch/erigon/cl/utils"
"github.com/ledgerwatch/erigon/cmd/erigon-cl/core/state"
)
@@ -13,17 +14,23 @@ func ProcessEffectiveBalanceUpdates(state *state.BeaconState) error {
downwardThreshold := histeresisIncrement * beaconConfig.HysteresisDownwardMultiplier
upwardThreshold := histeresisIncrement * beaconConfig.HysteresisUpwardMultiplier
// Iterate over validator set and compute the diff of each validator.
- for index, validator := range state.Validators() {
- balance, err := state.ValidatorBalance(index)
+ var err error
+ var balance uint64
+ state.ForEachValidator(func(validator *cltypes.Validator, index, total int) bool {
+ balance, err = state.ValidatorBalance(index)
if err != nil {
- return err
+ return false
}
- if balance+downwardThreshold < validator.EffectiveBalance ||
- validator.EffectiveBalance+upwardThreshold < balance {
+ eb := validator.EffectiveBalance()
+ if balance+downwardThreshold < eb || eb+upwardThreshold < balance {
// Set new effective balance
effectiveBalance := utils.Min64(balance-(balance%beaconConfig.EffectiveBalanceIncrement), beaconConfig.MaxEffectiveBalance)
state.SetEffectiveBalanceForValidatorAtIndex(index, effectiveBalance)
}
+ return true
+ })
+ if err != nil {
+ return err
}
return nil
}
diff --git a/cmd/erigon-cl/core/transition/process_epoch.go b/cmd/erigon-cl/core/transition/process_epoch.go
index 77fd00e4aa9..8d0e137681b 100644
--- a/cmd/erigon-cl/core/transition/process_epoch.go
+++ b/cmd/erigon-cl/core/transition/process_epoch.go
@@ -2,6 +2,7 @@ package transition
import (
"github.com/ledgerwatch/erigon/cl/clparams"
+ "github.com/ledgerwatch/erigon/cl/cltypes"
"github.com/ledgerwatch/erigon/cmd/erigon-cl/core/state"
)
@@ -52,7 +53,7 @@ func ProcessParticipationRecordUpdates(state *state.BeaconState) error {
state.SetPreviousEpochAttestations(state.CurrentEpochAttestations())
state.ResetCurrentEpochAttestations()
// Also mark all current attesters as previous
- for _, validator := range state.Validators() {
+ state.ForEachValidator(func(validator *cltypes.Validator, idx, total int) bool {
// Previous sources/target/head
validator.IsPreviousMatchingSourceAttester = validator.IsCurrentMatchingSourceAttester
validator.IsPreviousMatchingTargetAttester = validator.IsCurrentMatchingTargetAttester
@@ -63,6 +64,7 @@ func ProcessParticipationRecordUpdates(state *state.BeaconState) error {
validator.IsCurrentMatchingSourceAttester = false
validator.IsCurrentMatchingTargetAttester = false
validator.IsCurrentMatchingHeadAttester = false
- }
+ return true
+ })
return nil
}
diff --git a/cmd/erigon-cl/core/transition/process_registry_updates.go b/cmd/erigon-cl/core/transition/process_registry_updates.go
index 67524f437bd..c8138293eff 100644
--- a/cmd/erigon-cl/core/transition/process_registry_updates.go
+++ b/cmd/erigon-cl/core/transition/process_registry_updates.go
@@ -4,6 +4,7 @@ import (
"sort"
"github.com/ledgerwatch/erigon/cl/clparams"
+ "github.com/ledgerwatch/erigon/cl/cltypes"
"github.com/ledgerwatch/erigon/cmd/erigon-cl/core/state"
)
@@ -18,27 +19,33 @@ func ProcessRegistryUpdates(s *state.BeaconState) error {
currentEpoch := state.Epoch(s.BeaconState)
// start also initializing the activation queue.
activationQueue := make([]uint64, 0)
- validators := s.Validators()
// Process activation eligibility and ejections.
- for validatorIndex, validator := range validators {
+ var err error
+ s.ForEachValidator(func(validator *cltypes.Validator, validatorIndex, total int) bool {
if state.IsValidatorEligibleForActivationQueue(s.BeaconState, validator) {
s.SetActivationEligibilityEpochForValidatorAtIndex(validatorIndex, currentEpoch+1)
}
- if validator.Active(currentEpoch) && validator.EffectiveBalance <= beaconConfig.EjectionBalance {
- if err := s.InitiateValidatorExit(uint64(validatorIndex)); err != nil {
- return err
+ if validator.Active(currentEpoch) && validator.EffectiveBalance() <= beaconConfig.EjectionBalance {
+ if err = s.InitiateValidatorExit(uint64(validatorIndex)); err != nil {
+ return false
}
}
// Insert in the activation queue in case.
if state.IsValidatorEligibleForActivation(s.BeaconState, validator) {
activationQueue = append(activationQueue, uint64(validatorIndex))
}
+ return true
+ })
+ if err != nil {
+ return err
}
// order the queue accordingly.
sort.Slice(activationQueue, func(i, j int) bool {
// Order by the sequence of activation_eligibility_epoch setting and then index.
- if validators[activationQueue[i]].ActivationEligibilityEpoch != validators[activationQueue[j]].ActivationEligibilityEpoch {
- return validators[activationQueue[i]].ActivationEligibilityEpoch < validators[activationQueue[j]].ActivationEligibilityEpoch
+ validatori, _ := s.ValidatorForValidatorIndex(int(activationQueue[i]))
+ validatorj, _ := s.ValidatorForValidatorIndex(int(activationQueue[j]))
+ if validatori.ActivationEligibilityEpoch() != validatorj.ActivationEligibilityEpoch() {
+ return validatori.ActivationEligibilityEpoch() < validatorj.ActivationEligibilityEpoch()
}
return activationQueue[i] < activationQueue[j]
})
diff --git a/cmd/erigon-cl/core/transition/process_rewards_and_penalties.go b/cmd/erigon-cl/core/transition/process_rewards_and_penalties.go
index 412992bf579..17ee66463ba 100644
--- a/cmd/erigon-cl/core/transition/process_rewards_and_penalties.go
+++ b/cmd/erigon-cl/core/transition/process_rewards_and_penalties.go
@@ -2,6 +2,7 @@ package transition
import (
"github.com/ledgerwatch/erigon/cl/clparams"
+ "github.com/ledgerwatch/erigon/cl/cltypes"
"github.com/ledgerwatch/erigon/cmd/erigon-cl/core/state"
)
@@ -12,19 +13,19 @@ func processRewardsAndPenaltiesPostAltair(s *state.BeaconState) (err error) {
// Initialize variables
totalActiveBalance := s.GetTotalActiveBalance()
previousEpoch := state.PreviousEpoch(s.BeaconState)
- validators := s.Validators()
// Inactivity penalties denominator.
inactivityPenaltyDenominator := beaconConfig.InactivityScoreBias * beaconConfig.GetPenaltyQuotient(s.Version())
// Make buffer for flag indexes total balances.
flagsTotalBalances := make([]uint64, len(weights))
// Compute all total balances for each enable unslashed validator indicies with all flags on.
- for validatorIndex, validator := range s.Validators() {
+ s.ForEachValidator(func(validator *cltypes.Validator, validatorIndex, total int) bool {
for i := range weights {
if state.IsUnslashedParticipatingIndex(s.BeaconState, previousEpoch, uint64(validatorIndex), i) {
- flagsTotalBalances[i] += validator.EffectiveBalance
+ flagsTotalBalances[i] += validator.EffectiveBalance()
}
}
- }
+ return true
+ })
// precomputed multiplier for reward.
rewardMultipliers := make([]uint64, len(weights))
for i := range weights {
@@ -58,7 +59,11 @@ func processRewardsAndPenaltiesPostAltair(s *state.BeaconState) (err error) {
return err
}
// Process inactivity penalties.
- state.DecreaseBalance(s.BeaconState, index, (validators[index].EffectiveBalance*inactivityScore)/inactivityPenaltyDenominator)
+ effectiveBalance, err := s.ValidatorEffectiveBalance(int(index))
+ if err != nil {
+ return err
+ }
+ state.DecreaseBalance(s.BeaconState, index, (effectiveBalance*inactivityScore)/inactivityPenaltyDenominator)
}
}
return
@@ -73,24 +78,24 @@ func processRewardsAndPenaltiesPhase0(s *state.BeaconState) (err error) {
eligibleValidators := state.EligibleValidatorsIndicies(s.BeaconState)
// Initialize variables
rewardDenominator := s.GetTotalActiveBalance() / beaconConfig.EffectiveBalanceIncrement
- validators := s.Validators()
// Make buffer for flag indexes totTargetal balances.
var unslashedMatchingSourceBalanceIncrements, unslashedMatchingTargetBalanceIncrements, unslashedMatchingHeadBalanceIncrements uint64
// Compute all total balances for each enable unslashed validator indicies with all flags on.
- for _, validator := range s.Validators() {
- if validator.Slashed {
- continue
+ s.ForEachValidator(func(validator *cltypes.Validator, idx, total int) bool {
+ if validator.Slashed() {
+ return true
}
if validator.IsPreviousMatchingSourceAttester {
- unslashedMatchingSourceBalanceIncrements += validator.EffectiveBalance
+ unslashedMatchingSourceBalanceIncrements += validator.EffectiveBalance()
}
if validator.IsPreviousMatchingTargetAttester {
- unslashedMatchingTargetBalanceIncrements += validator.EffectiveBalance
+ unslashedMatchingTargetBalanceIncrements += validator.EffectiveBalance()
}
if validator.IsPreviousMatchingHeadAttester {
- unslashedMatchingHeadBalanceIncrements += validator.EffectiveBalance
+ unslashedMatchingHeadBalanceIncrements += validator.EffectiveBalance()
}
- }
+ return true
+ })
// Then compute their total increment.
unslashedMatchingSourceBalanceIncrements /= beaconConfig.EffectiveBalanceIncrement
unslashedMatchingTargetBalanceIncrements /= beaconConfig.EffectiveBalanceIncrement
@@ -101,27 +106,31 @@ func processRewardsAndPenaltiesPhase0(s *state.BeaconState) (err error) {
if err != nil {
return err
}
+ currentValidator, err := s.ValidatorForValidatorIndex(int(index))
+ if err != nil {
+ return err
+ }
// we can use a multiplier to account for all attesting
- attested, missed := validators[index].DutiesAttested()
+ attested, missed := currentValidator.DutiesAttested()
// If we attested then we reward the validator.
if state.InactivityLeaking(s.BeaconState) {
if err := state.IncreaseBalance(s.BeaconState, index, baseReward*attested); err != nil {
return err
}
} else {
- if !validators[index].Slashed && validators[index].IsPreviousMatchingSourceAttester {
+ if !currentValidator.Slashed() && currentValidator.IsPreviousMatchingSourceAttester {
rewardNumerator := baseReward * unslashedMatchingSourceBalanceIncrements
if err := state.IncreaseBalance(s.BeaconState, index, rewardNumerator/rewardDenominator); err != nil {
return err
}
}
- if !validators[index].Slashed && validators[index].IsPreviousMatchingTargetAttester {
+ if !currentValidator.Slashed() && currentValidator.IsPreviousMatchingTargetAttester {
rewardNumerator := baseReward * unslashedMatchingTargetBalanceIncrements
if err := state.IncreaseBalance(s.BeaconState, index, rewardNumerator/rewardDenominator); err != nil {
return err
}
}
- if !validators[index].Slashed && validators[index].IsPreviousMatchingHeadAttester {
+ if !currentValidator.Slashed() && currentValidator.IsPreviousMatchingHeadAttester {
rewardNumerator := baseReward * unslashedMatchingHeadBalanceIncrements
if err := state.IncreaseBalance(s.BeaconState, index, rewardNumerator/rewardDenominator); err != nil {
return err
@@ -135,9 +144,9 @@ func processRewardsAndPenaltiesPhase0(s *state.BeaconState) (err error) {
if state.DecreaseBalance(s.BeaconState, index, beaconConfig.BaseRewardsPerEpoch*baseReward-proposerReward); err != nil {
return err
}
- if validators[index].Slashed || !validators[index].IsPreviousMatchingTargetAttester {
+ if currentValidator.Slashed() || !currentValidator.IsPreviousMatchingTargetAttester {
// Increase penalities linearly if network is leaking.
- if state.DecreaseBalance(s.BeaconState, index, validators[index].EffectiveBalance*state.FinalityDelay(s.BeaconState)/beaconConfig.InactivityPenaltyQuotient); err != nil {
+ if state.DecreaseBalance(s.BeaconState, index, currentValidator.EffectiveBalance()*state.FinalityDelay(s.BeaconState)/beaconConfig.InactivityPenaltyQuotient); err != nil {
return err
}
}
@@ -150,24 +159,30 @@ func processRewardsAndPenaltiesPhase0(s *state.BeaconState) (err error) {
}
// Lastly process late attestations
- for index, validator := range validators {
- if validator.Slashed || !validator.IsPreviousMatchingSourceAttester {
- continue
+
+ s.ForEachValidator(func(validator *cltypes.Validator, index, total int) bool {
+ if validator.Slashed() || !validator.IsPreviousMatchingSourceAttester {
+ return true
}
- attestation := validators[index].MinPreviousInclusionDelayAttestation
- baseReward, err := s.BaseReward(uint64(index))
+ attestation := validator.MinPreviousInclusionDelayAttestation
+ var baseReward uint64
+ baseReward, err = s.BaseReward(uint64(index))
if err != nil {
- return err
+ return false
}
// Compute proposer reward.
proposerReward := (baseReward / beaconConfig.ProposerRewardQuotient)
- if err := state.IncreaseBalance(s.BeaconState, attestation.ProposerIndex, proposerReward); err != nil {
- return err
+ if err = state.IncreaseBalance(s.BeaconState, attestation.ProposerIndex, proposerReward); err != nil {
+ return false
}
maxAttesterReward := baseReward - proposerReward
- if err := state.IncreaseBalance(s.BeaconState, uint64(index), maxAttesterReward/attestation.InclusionDelay); err != nil {
- return err
+ if err = state.IncreaseBalance(s.BeaconState, uint64(index), maxAttesterReward/attestation.InclusionDelay); err != nil {
+ return false
}
+ return true
+ })
+ if err != nil {
+ return err
}
return
}
diff --git a/cmd/erigon-cl/core/transition/process_slashings.go b/cmd/erigon-cl/core/transition/process_slashings.go
index 27271e4a0ff..03d88eb5823 100644
--- a/cmd/erigon-cl/core/transition/process_slashings.go
+++ b/cmd/erigon-cl/core/transition/process_slashings.go
@@ -2,6 +2,7 @@ package transition
import (
"github.com/ledgerwatch/erigon/cl/clparams"
+ "github.com/ledgerwatch/erigon/cl/cltypes"
"github.com/ledgerwatch/erigon/cmd/erigon-cl/core/state"
)
@@ -19,20 +20,25 @@ func processSlashings(s *state.BeaconState, slashingMultiplier uint64) error {
}
beaconConfig := s.BeaconConfig()
// Apply penalties to validators who have been slashed and reached the withdrawable epoch
- for i, validator := range s.Validators() {
- if !validator.Slashed || epoch+beaconConfig.EpochsPerSlashingsVector/2 != validator.WithdrawableEpoch {
- continue
+ var err error
+ s.ForEachValidator(func(validator *cltypes.Validator, i, total int) bool {
+ if !validator.Slashed() || epoch+beaconConfig.EpochsPerSlashingsVector/2 != validator.WithdrawableEpoch() {
+ return true
}
// Get the effective balance increment
increment := beaconConfig.EffectiveBalanceIncrement
// Calculate the penalty numerator by multiplying the validator's effective balance by the total slashing amount
- penaltyNumerator := validator.EffectiveBalance / increment * slashing
+ penaltyNumerator := validator.EffectiveBalance() / increment * slashing
// Calculate the penalty by dividing the penalty numerator by the total balance and multiplying by the increment
penalty := penaltyNumerator / totalBalance * increment
// Decrease the validator's balance by the calculated penalty
- if err := state.DecreaseBalance(s.BeaconState, uint64(i), penalty); err != nil {
- return err
+ if err = state.DecreaseBalance(s.BeaconState, uint64(i), penalty); err != nil {
+ return false
}
+ return true
+ })
+ if err != nil {
+ return err
}
return nil
}
diff --git a/cmd/erigon-cl/core/transition/process_slots.go b/cmd/erigon-cl/core/transition/process_slots.go
index 20b90293989..e18c2d90d19 100644
--- a/cmd/erigon-cl/core/transition/process_slots.go
+++ b/cmd/erigon-cl/core/transition/process_slots.go
@@ -145,7 +145,8 @@ func verifyBlockSignature(s *state.BeaconState, block *cltypes.SignedBeaconBlock
if err != nil {
return false, err
}
- return bls.Verify(block.Signature[:], sigRoot[:], proposer.PublicKey[:])
+ pk := proposer.PublicKey()
+ return bls.Verify(block.Signature[:], sigRoot[:], pk[:])
}
// ProcessHistoricalRootsUpdate updates the historical root data structure by computing a new historical root batch when it is time to do so.
diff --git a/cmd/erigon-cl/core/transition/processing.go b/cmd/erigon-cl/core/transition/processing.go
index bbe72ab6b29..a5afa127a78 100644
--- a/cmd/erigon-cl/core/transition/processing.go
+++ b/cmd/erigon-cl/core/transition/processing.go
@@ -58,7 +58,7 @@ func ProcessBlockHeader(state *state.BeaconState, block *cltypes.BeaconBlock, fu
if err != nil {
return err
}
- if proposer.Slashed {
+ if proposer.Slashed() {
return fmt.Errorf("proposer: %d is slashed", block.ProposerIndex)
}
return nil
@@ -79,12 +79,13 @@ func ProcessRandao(s *state.BeaconState, randao [96]byte, proposerIndex uint64,
if err != nil {
return fmt.Errorf("ProcessRandao: unable to compute signing root: %v", err)
}
- valid, err := bls.Verify(randao[:], signingRoot[:], proposer.PublicKey[:])
+ pk := proposer.PublicKey()
+ valid, err := bls.Verify(randao[:], signingRoot[:], pk[:])
if err != nil {
- return fmt.Errorf("ProcessRandao: unable to verify public key: %x, with signing root: %x, and signature: %x, %v", proposer.PublicKey[:], signingRoot[:], randao[:], err)
+ return fmt.Errorf("ProcessRandao: unable to verify public key: %x, with signing root: %x, and signature: %x, %v", pk[:], signingRoot[:], randao[:], err)
}
if !valid {
- return fmt.Errorf("ProcessRandao: invalid signature: public key: %x, signing root: %x, signature: %x", proposer.PublicKey[:], signingRoot[:], randao[:])
+ return fmt.Errorf("ProcessRandao: invalid signature: public key: %x, signing root: %x, signature: %x", pk[:], signingRoot[:], randao[:])
}
}
diff --git a/cmd/erigon-cl/forkchoice/checkpoint_state.go b/cmd/erigon-cl/forkchoice/checkpoint_state.go
index 1c138c36856..8df981a2f27 100644
--- a/cmd/erigon-cl/forkchoice/checkpoint_state.go
+++ b/cmd/erigon-cl/forkchoice/checkpoint_state.go
@@ -57,11 +57,11 @@ func newCheckpointState(beaconConfig *clparams.BeaconChainConfig, validatorSet [
validators := make([]*checkpointValidator, len(validatorSet))
for i := range validatorSet {
validators[i] = &checkpointValidator{
- publicKey: validatorSet[i].PublicKey,
- activationEpoch: validatorSet[i].ActivationEpoch,
- exitEpoch: validatorSet[i].ExitEpoch,
- balance: validatorSet[i].EffectiveBalance,
- slashed: validatorSet[i].Slashed,
+ publicKey: validatorSet[i].PublicKey(),
+ activationEpoch: validatorSet[i].ActivationEpoch(),
+ exitEpoch: validatorSet[i].ExitEpoch(),
+ balance: validatorSet[i].EffectiveBalance(),
+ slashed: validatorSet[i].Slashed(),
}
}
return &checkpointState{
diff --git a/cmd/erigon-cl/forkchoice/utils.go b/cmd/erigon-cl/forkchoice/utils.go
index ddc9a60224d..682e2680863 100644
--- a/cmd/erigon-cl/forkchoice/utils.go
+++ b/cmd/erigon-cl/forkchoice/utils.go
@@ -89,7 +89,13 @@ func (f *ForkChoiceStore) getCheckpointState(checkpoint cltypes.Checkpoint) (*ch
}
}
mixes := baseState.RandaoMixes()
- checkpointState := newCheckpointState(f.forkGraph.Config(), baseState.Validators(),
+ // TODO: make this copy smarter when validators is a smarter struct
+ validators := make([]*cltypes.Validator, baseState.ValidatorLength())
+ baseState.ForEachValidator(func(v *cltypes.Validator, idx, total int) bool {
+ validators[idx] = v
+ return true
+ })
+ checkpointState := newCheckpointState(f.forkGraph.Config(), validators,
mixes[:], baseState.GenesisValidatorsRoot(), baseState.Fork(), baseState.GetTotalActiveBalance(), state.Epoch(baseState.BeaconState))
// Cache in memory what we are left with.
f.checkpointStates.Add(checkpoint, checkpointState)
From 76c7111094f30083037950bcacaf575445ab4985 Mon Sep 17 00:00:00 2001
From: a
Date: Sun, 7 May 2023 01:31:32 -0500
Subject: [PATCH 02/34] fix build
---
go.mod | 2 +-
go.sum | 2 ++
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/go.mod b/go.mod
index b5dc35cd42c..66024f30ab5 100644
--- a/go.mod
+++ b/go.mod
@@ -68,7 +68,7 @@ require (
github.com/protolambda/eth2-shuffle v1.1.0
github.com/protolambda/ztyp v0.2.2
github.com/prysmaticlabs/go-bitfield v0.0.0-20210809151128-385d8c5e3fb7
- github.com/prysmaticlabs/gohashtree v0.0.3-alpha
+ github.com/prysmaticlabs/gohashtree v0.0.3-alpha.0.20230502123415-aafd8b3ca202
github.com/quasilyte/go-ruleguard/dsl v0.3.22
github.com/rs/cors v1.9.0
github.com/shirou/gopsutil/v3 v3.23.4
diff --git a/go.sum b/go.sum
index 9d2d9ce802e..cd3ed6aeff8 100644
--- a/go.sum
+++ b/go.sum
@@ -681,6 +681,8 @@ github.com/prysmaticlabs/go-bitfield v0.0.0-20210809151128-385d8c5e3fb7 h1:0tVE4
github.com/prysmaticlabs/go-bitfield v0.0.0-20210809151128-385d8c5e3fb7/go.mod h1:wmuf/mdK4VMD+jA9ThwcUKjg3a2XWM9cVfFYjDyY4j4=
github.com/prysmaticlabs/gohashtree v0.0.3-alpha h1:1EVinCWdb3Lorq7xn8DYQHf48nCcdAM3Vb18KsFlRWY=
github.com/prysmaticlabs/gohashtree v0.0.3-alpha/go.mod h1:4pWaT30XoEx1j8KNJf3TV+E3mQkaufn7mf+jRNb/Fuk=
+github.com/prysmaticlabs/gohashtree v0.0.3-alpha.0.20230502123415-aafd8b3ca202 h1:ZsFouPKy81vvQo/Zup5gASVdOm6aiuwUhp7GxvQmjIA=
+github.com/prysmaticlabs/gohashtree v0.0.3-alpha.0.20230502123415-aafd8b3ca202/go.mod h1:4pWaT30XoEx1j8KNJf3TV+E3mQkaufn7mf+jRNb/Fuk=
github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe60+5DqOpCjPE=
github.com/quasilyte/go-ruleguard/dsl v0.3.22/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU=
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
From 833b14d6a37fa568addc51e73e7c395e60553aef Mon Sep 17 00:00:00 2001
From: a
Date: Sun, 7 May 2023 01:43:58 -0500
Subject: [PATCH 03/34] opatch
---
go.mod | 2 +-
go.sum | 2 ++
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/go.mod b/go.mod
index 66024f30ab5..ade1be8ec10 100644
--- a/go.mod
+++ b/go.mod
@@ -14,7 +14,7 @@ require (
require (
gfx.cafe/util/go/generic v0.0.0-20230502013805-237fcc25d586
github.com/99designs/gqlgen v0.17.30
- github.com/Giulio2002/bls v0.0.0-20230428210858-67fd06bbe237
+ github.com/Giulio2002/bls v0.0.0-20230506124236-f7b02834db57
github.com/RoaringBitmap/roaring v1.2.3
github.com/VictoriaMetrics/fastcache v1.12.1
github.com/VictoriaMetrics/metrics v1.23.1
diff --git a/go.sum b/go.sum
index cd3ed6aeff8..b304ba1e121 100644
--- a/go.sum
+++ b/go.sum
@@ -20,6 +20,8 @@ github.com/99designs/gqlgen v0.17.30/go.mod h1:i4rEatMrzzu6RXaHydq1nmEPZkb3bKQsn
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Giulio2002/bls v0.0.0-20230428210858-67fd06bbe237 h1:YSnR8buOFFDoIdGkkZ588jlaUXRHpBTrlauANv9wdD0=
github.com/Giulio2002/bls v0.0.0-20230428210858-67fd06bbe237/go.mod h1:o6qWofeW8A1XImbo3eHbC/wXnw/dasu0YuHEtdrjYzw=
+github.com/Giulio2002/bls v0.0.0-20230506124236-f7b02834db57 h1:DVxkPKa/TsvE/iouZmaEHQmo7qwbVIcAHhFn0tAPz3s=
+github.com/Giulio2002/bls v0.0.0-20230506124236-f7b02834db57/go.mod h1:o6qWofeW8A1XImbo3eHbC/wXnw/dasu0YuHEtdrjYzw=
github.com/RoaringBitmap/roaring v0.4.7/go.mod h1:8khRDP4HmeXns4xIj9oGrKSz7XTQiJx2zgh7AcNke4w=
github.com/RoaringBitmap/roaring v0.4.17/go.mod h1:D3qVegWTmfCaX4Bl5CrBE9hfrSrrXIr8KVNvRsDi1NI=
github.com/RoaringBitmap/roaring v0.4.23/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06Mq5mKs52e1TwOo=
From abbd5e069aa765fad2118b35819fa8f52d11ad07 Mon Sep 17 00:00:00 2001
From: a
Date: Sun, 7 May 2023 06:04:11 -0500
Subject: [PATCH 04/34] wip
fix test
broken
another patch
more fix
---
cl/cltypes/solid/bitlist.go | 80 +++++++++++++++++++
cl/cltypes/solid/interfaces.go | 14 ++++
cl/cltypes/solid/uint64slice_byte_test.go | 4 +-
cl/cltypes/solid/validator.go | 23 ++++++
cl/cltypes/validator_test.go | 47 +++++------
cmd/erigon-cl/core/state/accessors.go | 7 +-
cmd/erigon-cl/core/state/raw/copy.go | 4 +-
cmd/erigon-cl/core/state/raw/getters.go | 7 +-
cmd/erigon-cl/core/state/raw/hashing.go | 4 +-
cmd/erigon-cl/core/state/raw/setters.go | 24 ++++--
cmd/erigon-cl/core/state/raw/ssz.go | 19 ++---
cmd/erigon-cl/core/state/raw/state.go | 11 ++-
.../finalization_and_justification.go | 4 +-
13 files changed, 189 insertions(+), 59 deletions(-)
create mode 100644 cl/cltypes/solid/bitlist.go
diff --git a/cl/cltypes/solid/bitlist.go b/cl/cltypes/solid/bitlist.go
new file mode 100644
index 00000000000..6ad12899cb6
--- /dev/null
+++ b/cl/cltypes/solid/bitlist.go
@@ -0,0 +1,80 @@
+package solid
+
+import (
+ "github.com/ledgerwatch/erigon/cl/merkle_tree"
+)
+
+type bitlist struct {
+ u []byte
+ c int
+}
+
+func NewBitList(l int, c int) BitList {
+ return &bitlist{
+ u: make([]byte, l),
+ c: c,
+ }
+}
+func BitlistFromBytes(xs []byte, c int) BitList {
+ return &bitlist{
+ u: xs,
+ c: c,
+ }
+}
+
+func (u *bitlist) Clear() {
+ u.u = u.u[:0]
+}
+
+func (u *bitlist) CopyTo(target BitList) {
+ target.Clear()
+ for _, v := range u.u {
+ target.Append(v)
+ }
+}
+
+func (u *bitlist) Range(fn func(index int, value byte, length int) bool) {
+ for i, v := range u.u {
+ fn(i, v, len(u.u))
+ }
+}
+
+func (u *bitlist) Pop() (x byte) {
+ x, u.u = u.u[0], u.u[1:]
+ return x
+}
+
+func (u *bitlist) Append(v byte) {
+ u.u = append(u.u, v)
+}
+
+func (u *bitlist) Get(index int) byte {
+ return u.u[index]
+}
+
+func (u *bitlist) Set(index int, v byte) {
+ u.u[index] = v
+}
+
+func (u *bitlist) Length() int {
+ return len(u.u)
+}
+
+func (u *bitlist) Cap() int {
+ return u.c
+}
+
+func (u *bitlist) HashSSZTo(xs []byte) error {
+ root, err := merkle_tree.BitlistRootWithLimitForState(u.u, uint64(u.c))
+ if err != nil {
+ return err
+ }
+ copy(xs, root[:])
+ return nil
+}
+
+func (u *bitlist) EncodeSSZ(dst []byte) []byte {
+ buf := dst
+ buf = append(buf, u.u[:]...)
+ return buf
+}
diff --git a/cl/cltypes/solid/interfaces.go b/cl/cltypes/solid/interfaces.go
index b9cc9fddbd4..e78902924e6 100644
--- a/cl/cltypes/solid/interfaces.go
+++ b/cl/cltypes/solid/interfaces.go
@@ -12,3 +12,17 @@ type Uint64Slice interface {
Cap() int
HashSSZTo(xs []byte) error
}
+
+type BitList interface {
+ Clear()
+ CopyTo(BitList)
+ Range(fn func(index int, value byte, length int) bool)
+ Pop() byte
+ Append(v byte)
+ Get(index int) byte
+ Set(index int, v byte)
+ Length() int
+ Cap() int
+ EncodeSSZ(dst []byte) []byte
+ HashSSZTo(xs []byte) error
+}
diff --git a/cl/cltypes/solid/uint64slice_byte_test.go b/cl/cltypes/solid/uint64slice_byte_test.go
index 1fd7545225f..235994565a7 100644
--- a/cl/cltypes/solid/uint64slice_byte_test.go
+++ b/cl/cltypes/solid/uint64slice_byte_test.go
@@ -1,7 +1,6 @@
package solid_test
import (
- "log"
"testing"
"github.com/ledgerwatch/erigon/cl/cltypes/solid"
@@ -28,7 +27,6 @@ func TestUint64SliceBasic(t *testing.T) {
nums := []uint64{3, 2, 1}
root, err := merkle_tree.Uint64ListRootWithLimit(nums, 2)
require.NoError(t, err)
- log.Printf("merkl tree: %x", root)
- log.Printf("ours tree: %x", out)
+ require.EqualValues(t, root, out)
}
diff --git a/cl/cltypes/solid/validator.go b/cl/cltypes/solid/validator.go
index 29f5fd28540..c8fcfdb1dae 100644
--- a/cl/cltypes/solid/validator.go
+++ b/cl/cltypes/solid/validator.go
@@ -22,6 +22,29 @@ const validatorSize = 48 + 32 + 8 + 1 + 8 + 8 + 8 + 8
type Validator [validatorSize]byte
+func NewValidatorFromParameters(
+ PublicKey [48]byte,
+ WithdrawalCredentials [32]byte,
+ EffectiveBalance uint64,
+ Slashed bool,
+ ActivationEligibilityEpoch uint64,
+ ActivationEpoch uint64,
+ ExitEpoch uint64,
+ WithdrawableEpoch uint64,
+) *Validator {
+ v := &Validator{}
+ v.SetPublicKey(PublicKey)
+ v.SetWithdrawalCredentials(WithdrawalCredentials)
+ v.SetEffectiveBalance(EffectiveBalance)
+ v.SetSlashed(Slashed)
+ v.SetActivationEligibilityEpoch(ActivationEligibilityEpoch)
+ v.SetActivationEpoch(ActivationEpoch)
+ v.SetExitEpoch(ExitEpoch)
+ v.SetWithdrawableEpoch(WithdrawableEpoch)
+ return v
+
+}
+
func (v *Validator) CopyTo(dst *Validator) {
copy(dst[:], v[:])
}
diff --git a/cl/cltypes/validator_test.go b/cl/cltypes/validator_test.go
index 90c0a94d1e2..ef17f25a99e 100644
--- a/cl/cltypes/validator_test.go
+++ b/cl/cltypes/validator_test.go
@@ -6,6 +6,7 @@ import (
"github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon/cl/cltypes"
+ "github.com/ledgerwatch/erigon/cl/cltypes/solid"
"github.com/ledgerwatch/erigon/cl/utils"
"github.com/stretchr/testify/require"
)
@@ -26,27 +27,27 @@ func hex2BlsPublicKey(s string) (k [48]byte) {
return
}
-var testValidator1 = &cltypes.Validator{
- PublicKey: hex2BlsPublicKey("227a72a5b99042650eaa52ed66ebf50d31595dba2cbc3da3810378c6fa92c25b93fa0e652a1ac298549cceb6c40d6fc2"),
- WithdrawalCredentials: common.HexToHash("401ef8ad032de7a3b8a50ae67cd823b0944d2260cd0d018e710eebf8e832b021"),
- EffectiveBalance: 13619341603830475769,
- Slashed: true,
- ActivationEligibilityEpoch: 2719404809456332213,
- ActivationEpoch: 8707665390408467486,
- ExitEpoch: 6929014573432656651,
- WithdrawableEpoch: 3085466968797960434,
-}
+var testValidator1 = solid.NewValidatorFromParameters(
+ hex2BlsPublicKey("227a72a5b99042650eaa52ed66ebf50d31595dba2cbc3da3810378c6fa92c25b93fa0e652a1ac298549cceb6c40d6fc2"),
+ common.HexToHash("401ef8ad032de7a3b8a50ae67cd823b0944d2260cd0d018e710eebf8e832b021"),
+ 13619341603830475769,
+ true,
+ 2719404809456332213,
+ 8707665390408467486,
+ 6929014573432656651,
+ 3085466968797960434,
+)
-var testValidator2 = &cltypes.Validator{
- PublicKey: hex2BlsPublicKey("bff465728708cccd057fa4be1bf83eb42ec6a70e52cca2d24309de9e2b0cbc1a7110b92e8c7f475625d1e79f86f31a3e"),
- WithdrawalCredentials: common.HexToHash("3ba9e58ab7d3807a2733e3aa204fdacde3f0d16e7126492c72fa228eae20c5eb"),
- EffectiveBalance: 4748534886993468932,
- Slashed: false,
- ActivationEligibilityEpoch: 9720109592954569431,
- ActivationEpoch: 16116572433788512122,
- ExitEpoch: 12361131058646161796,
- WithdrawableEpoch: 8134858776785446209,
-}
+var testValidator2 = solid.NewValidatorFromParameters(
+ hex2BlsPublicKey("bff465728708cccd057fa4be1bf83eb42ec6a70e52cca2d24309de9e2b0cbc1a7110b92e8c7f475625d1e79f86f31a3e"),
+ common.HexToHash("3ba9e58ab7d3807a2733e3aa204fdacde3f0d16e7126492c72fa228eae20c5eb"),
+ 4748534886993468932,
+ false,
+ 9720109592954569431,
+ 16116572433788512122,
+ 12361131058646161796,
+ 8134858776785446209,
+)
var testValidator2Snappified, _ = hex.DecodeString("79f078bff465728708cccd057fa4be1bf83eb42ec6a70e52cca2d24309de9e2b0cbc1a7110b92e8c7f475625d1e79f86f31a3e3ba9e58ab7d3807a2733e3aa204fdacde3f0d16e7126492c72fa228eae20c5eb049ecb26522fe64100d782ece92cc4e4867a27d1403d91a9df8419a7ac348f8bab41e54308f5d2e470")
@@ -54,7 +55,7 @@ var testValidatorRoot1 = common.HexToHash("83e755dbe8b552c628677bcad4d5f28b29f9a
var testValidatorRoot2 = common.HexToHash("0bcf6f6b165f8ba4a0b59fad23195a83097cdfc62eca06d6219d5699f057aa14")
func TestValidatorSlashed(t *testing.T) {
- encoded, _ := testValidator1.EncodeSSZ([]byte{0x2})
+ encoded := testValidator1.EncodeSSZ([]byte{0x2})
decodedValidator := &cltypes.Validator{}
require.NoError(t, decodedValidator.DecodeSSZ(encoded[1:], 0))
root, err := decodedValidator.HashSSZ()
@@ -67,8 +68,8 @@ func TestValidatorNonSlashed(t *testing.T) {
decodedValidator := &cltypes.Validator{}
require.NoError(t, decodedValidator.DecodeSSZ(encoded, 0))
encoded2, _ := decodedValidator.EncodeSSZ(nil)
- require.Equal(t, encoded2, encoded)
- require.Equal(t, decodedValidator, testValidator2)
+ require.EqualValues(t, encoded2, encoded)
+ require.EqualValues(t, decodedValidator.Validator, *testValidator2)
root, err := decodedValidator.HashSSZ()
require.NoError(t, err)
require.Equal(t, common.Hash(root), testValidatorRoot2)
diff --git a/cmd/erigon-cl/core/state/accessors.go b/cmd/erigon-cl/core/state/accessors.go
index 6745db671ea..8af6b71bec9 100644
--- a/cmd/erigon-cl/core/state/accessors.go
+++ b/cmd/erigon-cl/core/state/accessors.go
@@ -7,6 +7,7 @@ import (
libcommon "github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon/cl/clparams"
"github.com/ledgerwatch/erigon/cl/cltypes"
+ "github.com/ledgerwatch/erigon/cl/cltypes/solid"
"github.com/ledgerwatch/erigon/cl/fork"
"github.com/ledgerwatch/erigon/cl/utils"
"github.com/ledgerwatch/erigon/cmd/erigon-cl/core/state/raw"
@@ -86,7 +87,7 @@ func IsUnslashedParticipatingIndex(b *raw.BeaconState, epoch, index uint64, flag
if err != nil {
return false
}
- return validator.Active(epoch) && b.EpochParticipation(false)[index].HasFlag(flagIdx) && !validator.Slashed()
+ return validator.Active(epoch) && cltypes.ParticipationFlags(b.EpochParticipation(false).Get(int(index))).HasFlag(flagIdx) && !validator.Slashed()
}
// EligibleValidatorsIndicies Implementation of get_eligible_validator_indices as defined in the eth 2.0 specs.
@@ -141,7 +142,7 @@ func IsValidIndexedAttestation(b *raw.BeaconState, att *cltypes.IndexedAttestati
// getUnslashedParticipatingIndices returns set of currently unslashed participating indexes
func GetUnslashedParticipatingIndices(b *raw.BeaconState, flagIndex int, epoch uint64) (validatorSet []uint64, err error) {
- var participation cltypes.ParticipationFlagsList
+ var participation solid.BitList
// Must be either previous or current epoch
switch epoch {
case Epoch(b):
@@ -154,7 +155,7 @@ func GetUnslashedParticipatingIndices(b *raw.BeaconState, flagIndex int, epoch u
// Iterate over all validators and include the active ones that have flag_index enabled and are not slashed.
b.ForEachValidator(func(validator *cltypes.Validator, i, total int) bool {
if !validator.Active(epoch) ||
- !participation[i].HasFlag(flagIndex) ||
+ !cltypes.ParticipationFlags(participation.Get(i)).HasFlag(flagIndex) ||
validator.Slashed() {
return true
}
diff --git a/cmd/erigon-cl/core/state/raw/copy.go b/cmd/erigon-cl/core/state/raw/copy.go
index 36c2ea14863..7dfb7d155cc 100644
--- a/cmd/erigon-cl/core/state/raw/copy.go
+++ b/cmd/erigon-cl/core/state/raw/copy.go
@@ -35,8 +35,8 @@ func (b *BeaconState) CopyInto(dst *BeaconState) error {
b.balances.CopyTo(dst.balances)
copy(dst.randaoMixes[:], b.randaoMixes[:])
copy(dst.slashings[:], b.slashings[:])
- dst.previousEpochParticipation = b.previousEpochParticipation.Copy()
- dst.currentEpochParticipation = b.currentEpochParticipation.Copy()
+ b.previousEpochParticipation.CopyTo(dst.previousEpochParticipation)
+ b.currentEpochParticipation.CopyTo(dst.currentEpochParticipation)
dst.finalizedCheckpoint = b.finalizedCheckpoint.Copy()
dst.currentJustifiedCheckpoint = b.currentJustifiedCheckpoint.Copy()
dst.previousJustifiedCheckpoint = b.previousJustifiedCheckpoint.Copy()
diff --git a/cmd/erigon-cl/core/state/raw/getters.go b/cmd/erigon-cl/core/state/raw/getters.go
index c9eecf34a34..3e73c7698ab 100644
--- a/cmd/erigon-cl/core/state/raw/getters.go
+++ b/cmd/erigon-cl/core/state/raw/getters.go
@@ -7,6 +7,7 @@ import (
libcommon "github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon/cl/clparams"
"github.com/ledgerwatch/erigon/cl/cltypes"
+ "github.com/ledgerwatch/erigon/cl/cltypes/solid"
"github.com/ledgerwatch/erigon/cl/fork"
)
@@ -165,7 +166,7 @@ func (b *BeaconState) SlashingSegmentAt(pos int) uint64 {
return b.slashings[pos]
}
-func (b *BeaconState) EpochParticipation(currentEpoch bool) cltypes.ParticipationFlagsList {
+func (b *BeaconState) EpochParticipation(currentEpoch bool) solid.BitList {
if currentEpoch {
return b.currentEpochParticipation
}
@@ -178,9 +179,9 @@ func (b *BeaconState) JustificationBits() cltypes.JustificationBits {
func (b *BeaconState) EpochParticipationForValidatorIndex(isCurrentEpoch bool, index int) cltypes.ParticipationFlags {
if isCurrentEpoch {
- return b.currentEpochParticipation[index]
+ return cltypes.ParticipationFlags(b.currentEpochParticipation.Get(index))
}
- return b.previousEpochParticipation[index]
+ return cltypes.ParticipationFlags(b.previousEpochParticipation.Get(index))
}
func (b *BeaconState) PreviousJustifiedCheckpoint() *cltypes.Checkpoint {
diff --git a/cmd/erigon-cl/core/state/raw/hashing.go b/cmd/erigon-cl/core/state/raw/hashing.go
index ecc44459e59..2ffe240c230 100644
--- a/cmd/erigon-cl/core/state/raw/hashing.go
+++ b/cmd/erigon-cl/core/state/raw/hashing.go
@@ -162,7 +162,7 @@ func (b *BeaconState) computeDirtyLeaves() error {
if b.version == clparams.Phase0Version {
root, err = merkle_tree.ListObjectSSZRoot(b.previousEpochAttestations, b.beaconConfig.SlotsPerEpoch*b.beaconConfig.MaxAttestations)
} else {
- root, err = merkle_tree.BitlistRootWithLimitForState(b.previousEpochParticipation.Bytes(), state_encoding.ValidatorRegistryLimit)
+ err = b.previousEpochParticipation.HashSSZTo(root[:])
}
if err != nil {
return err
@@ -178,7 +178,7 @@ func (b *BeaconState) computeDirtyLeaves() error {
if b.version == clparams.Phase0Version {
root, err = merkle_tree.ListObjectSSZRoot(b.currentEpochAttestations, b.beaconConfig.SlotsPerEpoch*b.beaconConfig.MaxAttestations)
} else {
- root, err = merkle_tree.BitlistRootWithLimitForState(b.currentEpochParticipation.Bytes(), state_encoding.ValidatorRegistryLimit)
+ err = b.currentEpochParticipation.HashSSZTo(root[:])
}
if err != nil {
return err
diff --git a/cmd/erigon-cl/core/state/raw/setters.go b/cmd/erigon-cl/core/state/raw/setters.go
index 965e7a260e5..8265a91573f 100644
--- a/cmd/erigon-cl/core/state/raw/setters.go
+++ b/cmd/erigon-cl/core/state/raw/setters.go
@@ -4,6 +4,8 @@ import (
libcommon "github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon/cl/clparams"
"github.com/ledgerwatch/erigon/cl/cltypes"
+ "github.com/ledgerwatch/erigon/cl/cltypes/solid"
+ "github.com/ledgerwatch/erigon/cmd/erigon-cl/core/state/state_encoding"
)
func (b *BeaconState) SetVersion(version clparams.StateVersion) {
@@ -221,11 +223,11 @@ func (b *BeaconState) IncrementSlashingSegmentAt(index int, delta uint64) {
func (b *BeaconState) SetEpochParticipationForValidatorIndex(isCurrentEpoch bool, index int, flags cltypes.ParticipationFlags) {
if isCurrentEpoch {
b.markLeaf(CurrentEpochParticipationLeafIndex)
- b.currentEpochParticipation[index] = flags
+ b.currentEpochParticipation.Set(index, byte(flags))
return
}
b.markLeaf(PreviousEpochParticipationLeafIndex)
- b.previousEpochParticipation[index] = flags
+ b.previousEpochParticipation.Set(index, byte(flags))
}
func (b *BeaconState) SetValidatorAtIndex(index int, validator *cltypes.Validator) {
@@ -235,7 +237,7 @@ func (b *BeaconState) SetValidatorAtIndex(index int, validator *cltypes.Validato
func (b *BeaconState) ResetEpochParticipation() {
b.previousEpochParticipation = b.currentEpochParticipation
- b.currentEpochParticipation = make(cltypes.ParticipationFlagsList, len(b.validators))
+ b.currentEpochParticipation = solid.NewBitList(len(b.validators), state_encoding.ValidatorRegistryLimit)
b.markLeaf(CurrentEpochParticipationLeafIndex)
b.markLeaf(PreviousEpochParticipationLeafIndex)
}
@@ -323,26 +325,32 @@ func (b *BeaconState) SetValidatorInactivityScore(index int, score uint64) error
func (b *BeaconState) SetCurrentEpochParticipationFlags(flags []cltypes.ParticipationFlags) {
b.markLeaf(CurrentEpochParticipationLeafIndex)
- b.currentEpochParticipation = flags
+ b.currentEpochParticipation.Clear()
+ for _, v := range flags {
+ b.currentEpochParticipation.Append(byte(v))
+ }
}
func (b *BeaconState) SetPreviousEpochParticipationFlags(flags []cltypes.ParticipationFlags) {
b.markLeaf(PreviousEpochParticipationLeafIndex)
- b.previousEpochParticipation = flags
+ for _, v := range flags {
+ b.previousEpochParticipation.Append(byte(v))
+ }
}
func (b *BeaconState) AddCurrentEpochParticipationFlags(flags cltypes.ParticipationFlags) {
b.markLeaf(CurrentEpochParticipationLeafIndex)
- b.currentEpochParticipation = append(b.currentEpochParticipation, flags)
+ b.currentEpochParticipation.Append(byte(flags))
}
func (b *BeaconState) AddPreviousEpochParticipationFlags(flags cltypes.ParticipationFlags) {
b.markLeaf(PreviousEpochParticipationLeafIndex)
- b.previousEpochParticipation = append(b.previousEpochParticipation, flags)
+ b.previousEpochParticipation.Append(byte(flags))
}
func (b *BeaconState) AddPreviousEpochParticipationAt(index int, delta byte) {
b.markLeaf(PreviousEpochParticipationLeafIndex)
- b.previousEpochParticipation[index] = b.previousEpochParticipation[index].Add(int(delta))
+ tmp := b.previousEpochParticipation.Get(index) + delta
+ b.previousEpochParticipation.Set(index, tmp)
}
// phase0 fields
diff --git a/cmd/erigon-cl/core/state/raw/ssz.go b/cmd/erigon-cl/core/state/raw/ssz.go
index fd923552a2e..c44f9595cc2 100644
--- a/cmd/erigon-cl/core/state/raw/ssz.go
+++ b/cmd/erigon-cl/core/state/raw/ssz.go
@@ -7,6 +7,7 @@ import (
"github.com/ledgerwatch/erigon/cl/clparams"
"github.com/ledgerwatch/erigon/cl/cltypes"
"github.com/ledgerwatch/erigon/cl/cltypes/clonable"
+ "github.com/ledgerwatch/erigon/cl/cltypes/solid"
"github.com/ledgerwatch/erigon/cl/cltypes/ssz"
"github.com/ledgerwatch/erigon/cmd/erigon-cl/core/state/state_encoding"
)
@@ -71,7 +72,7 @@ func (b *BeaconState) EncodeSSZ(buf []byte) ([]byte, error) {
}
maxEpochAttestations := int(b.beaconConfig.SlotsPerEpoch * b.beaconConfig.MaxAttestations)
- if b.version != clparams.Phase0Version && len(b.previousEpochParticipation) > state_encoding.ValidatorRegistryLimit || len(b.currentEpochParticipation) > state_encoding.ValidatorRegistryLimit {
+ if b.version != clparams.Phase0Version && b.previousEpochParticipation.Length() > state_encoding.ValidatorRegistryLimit || (b.currentEpochParticipation.Length()) > state_encoding.ValidatorRegistryLimit {
return nil, fmt.Errorf("too many participations")
}
@@ -142,7 +143,7 @@ func (b *BeaconState) EncodeSSZ(buf []byte) ([]byte, error) {
offset += uint32(attestation.EncodingSizeSSZ()) + 4
}
} else {
- offset += uint32(len(b.previousEpochParticipation))
+ offset += uint32(b.previousEpochParticipation.Length())
}
// current participation offset
dst = append(dst, ssz.OffsetSSZ(offset)...)
@@ -152,7 +153,7 @@ func (b *BeaconState) EncodeSSZ(buf []byte) ([]byte, error) {
offset += uint32(attestation.EncodingSizeSSZ()) + 4
}
} else {
- offset += uint32(len(b.currentEpochParticipation))
+ offset += uint32(b.currentEpochParticipation.Length())
}
dst = append(dst, b.justificationBits.Byte())
@@ -225,8 +226,8 @@ func (b *BeaconState) EncodeSSZ(buf []byte) ([]byte, error) {
return nil, err
}
} else {
- dst = append(dst, b.previousEpochParticipation.Bytes()...)
- dst = append(dst, b.currentEpochParticipation.Bytes()...)
+ dst = b.previousEpochParticipation.EncodeSSZ(dst)
+ dst = b.currentEpochParticipation.EncodeSSZ(dst)
}
if b.version >= clparams.AltairVersion {
// write inactivity scores (offset 6)
@@ -408,8 +409,8 @@ func (b *BeaconState) DecodeSSZ(buf []byte, version int) error {
if currentEpochParticipation, err = ssz.DecodeString(buf, uint64(currentEpochParticipationOffset), uint64(inactivityScoresOffset), state_encoding.ValidatorRegistryLimit); err != nil {
return err
}
- b.previousEpochParticipation, b.currentEpochParticipation = cltypes.ParticipationFlagsListFromBytes(previousEpochParticipation), cltypes.ParticipationFlagsListFromBytes(currentEpochParticipation)
-
+ b.previousEpochParticipation = solid.BitlistFromBytes(previousEpochParticipation, state_encoding.ValidatorRegistryLimit)
+ b.currentEpochParticipation = solid.BitlistFromBytes(currentEpochParticipation, state_encoding.ValidatorRegistryLimit)
}
endOffset := uint32(len(buf))
@@ -460,8 +461,8 @@ func (b *BeaconState) EncodingSizeSSZ() (size int) {
size += pendingAttestation.EncodingSizeSSZ()
}
} else {
- size += len(b.previousEpochParticipation)
- size += len(b.currentEpochParticipation)
+ size += b.previousEpochParticipation.Length()
+ size += b.currentEpochParticipation.Length()
}
size += b.inactivityScores.Length() * 8
diff --git a/cmd/erigon-cl/core/state/raw/state.go b/cmd/erigon-cl/core/state/raw/state.go
index 1c0556cf2b3..b21aeb568fe 100644
--- a/cmd/erigon-cl/core/state/raw/state.go
+++ b/cmd/erigon-cl/core/state/raw/state.go
@@ -5,6 +5,7 @@ import (
"github.com/ledgerwatch/erigon/cl/clparams"
"github.com/ledgerwatch/erigon/cl/cltypes"
"github.com/ledgerwatch/erigon/cl/cltypes/solid"
+ "github.com/ledgerwatch/erigon/cmd/erigon-cl/core/state/state_encoding"
)
const (
@@ -31,8 +32,8 @@ type BeaconState struct {
balances solid.Uint64Slice
randaoMixes [randoMixesLength]common.Hash
slashings [slashingsLength]uint64
- previousEpochParticipation cltypes.ParticipationFlagsList
- currentEpochParticipation cltypes.ParticipationFlagsList
+ previousEpochParticipation solid.BitList
+ currentEpochParticipation solid.BitList
justificationBits cltypes.JustificationBits
// Altair
previousJustifiedCheckpoint *cltypes.Checkpoint
@@ -64,8 +65,10 @@ func New(cfg *clparams.BeaconChainConfig) *BeaconState {
state := &BeaconState{
beaconConfig: cfg,
//inactivityScores: solid.NewSimpleUint64Slice(int(cfg.ValidatorRegistryLimit)),
- inactivityScores: solid.NewUint64Slice(int(cfg.ValidatorRegistryLimit)),
- balances: solid.NewUint64Slice(int(cfg.ValidatorRegistryLimit)),
+ inactivityScores: solid.NewUint64Slice(int(cfg.ValidatorRegistryLimit)),
+ balances: solid.NewUint64Slice(int(cfg.ValidatorRegistryLimit)),
+ previousEpochParticipation: solid.NewBitList(0, int(state_encoding.ValidatorRegistryLimit)),
+ currentEpochParticipation: solid.NewBitList(0, int(state_encoding.ValidatorRegistryLimit)),
}
state.init()
return state
diff --git a/cmd/erigon-cl/core/transition/finalization_and_justification.go b/cmd/erigon-cl/core/transition/finalization_and_justification.go
index 7b7153c173e..a92f4c526c7 100644
--- a/cmd/erigon-cl/core/transition/finalization_and_justification.go
+++ b/cmd/erigon-cl/core/transition/finalization_and_justification.go
@@ -91,11 +91,11 @@ func ProcessJustificationBitsAndFinality(s *state.BeaconState) error {
return true
}
if validator.Active(previousEpoch) &&
- previousParticipation[i].HasFlag(int(beaconConfig.TimelyTargetFlagIndex)) {
+ cltypes.ParticipationFlags(previousParticipation.Get(i)).HasFlag(int(beaconConfig.TimelyTargetFlagIndex)) {
previousTargetBalance += validator.EffectiveBalance()
}
if validator.Active(currentEpoch) &&
- currentParticipation[i].HasFlag(int(beaconConfig.TimelyTargetFlagIndex)) {
+ cltypes.ParticipationFlags(currentParticipation.Get(i)).HasFlag(int(beaconConfig.TimelyTargetFlagIndex)) {
currentTargetBalance += validator.EffectiveBalance()
}
return true
From 8cac97570a446dee115ee172b11d4163c01ca5ea Mon Sep 17 00:00:00 2001
From: a
Date: Sun, 7 May 2023 07:15:15 -0500
Subject: [PATCH 05/34] forgot to reset
---
cmd/erigon-cl/core/state/raw/setters.go | 1 +
1 file changed, 1 insertion(+)
diff --git a/cmd/erigon-cl/core/state/raw/setters.go b/cmd/erigon-cl/core/state/raw/setters.go
index 8265a91573f..4f48572a9d8 100644
--- a/cmd/erigon-cl/core/state/raw/setters.go
+++ b/cmd/erigon-cl/core/state/raw/setters.go
@@ -333,6 +333,7 @@ func (b *BeaconState) SetCurrentEpochParticipationFlags(flags []cltypes.Particip
func (b *BeaconState) SetPreviousEpochParticipationFlags(flags []cltypes.ParticipationFlags) {
b.markLeaf(PreviousEpochParticipationLeafIndex)
+ b.previousEpochParticipation.Clear()
for _, v := range flags {
b.previousEpochParticipation.Append(byte(v))
}
From 2dad1d6cd5ff343c4fd63b99dbc139a790ec6ac5 Mon Sep 17 00:00:00 2001
From: a
Date: Sun, 7 May 2023 07:54:26 -0500
Subject: [PATCH 06/34] fix addition
---
cmd/ef-tests-cl/consensus_tests/sanity.go | 2 ++
cmd/erigon-cl/core/state/raw/setters.go | 5 +++--
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/cmd/ef-tests-cl/consensus_tests/sanity.go b/cmd/ef-tests-cl/consensus_tests/sanity.go
index a48eeb9d0db..160c2871ba0 100644
--- a/cmd/ef-tests-cl/consensus_tests/sanity.go
+++ b/cmd/ef-tests-cl/consensus_tests/sanity.go
@@ -2,6 +2,7 @@ package consensus_tests
import (
"io/fs"
+ "log"
"os"
"testing"
@@ -62,6 +63,7 @@ var SanityBlocks = spectest.HandlerFunc(func(t *testing.T, root fs.FS, c spectes
var block *cltypes.SignedBeaconBlock
for _, block = range blocks {
+ log.Println(block)
err = transition.TransitionState(testState, block, true)
if err != nil {
break
diff --git a/cmd/erigon-cl/core/state/raw/setters.go b/cmd/erigon-cl/core/state/raw/setters.go
index 4f48572a9d8..3ad800bf038 100644
--- a/cmd/erigon-cl/core/state/raw/setters.go
+++ b/cmd/erigon-cl/core/state/raw/setters.go
@@ -348,10 +348,11 @@ func (b *BeaconState) AddPreviousEpochParticipationFlags(flags cltypes.Participa
b.markLeaf(PreviousEpochParticipationLeafIndex)
b.previousEpochParticipation.Append(byte(flags))
}
+
func (b *BeaconState) AddPreviousEpochParticipationAt(index int, delta byte) {
b.markLeaf(PreviousEpochParticipationLeafIndex)
- tmp := b.previousEpochParticipation.Get(index) + delta
- b.previousEpochParticipation.Set(index, tmp)
+ tmp := cltypes.ParticipationFlags(b.previousEpochParticipation.Get(index)).Add(int(delta))
+ b.previousEpochParticipation.Set(index, byte(tmp))
}
// phase0 fields
From 60ff904077fae64e0ce9708047b780b97a06fb54 Mon Sep 17 00:00:00 2001
From: a
Date: Sun, 7 May 2023 08:04:25 -0500
Subject: [PATCH 07/34] remove
---
cmd/ef-tests-cl/consensus_tests/sanity.go | 2 --
1 file changed, 2 deletions(-)
diff --git a/cmd/ef-tests-cl/consensus_tests/sanity.go b/cmd/ef-tests-cl/consensus_tests/sanity.go
index 160c2871ba0..a48eeb9d0db 100644
--- a/cmd/ef-tests-cl/consensus_tests/sanity.go
+++ b/cmd/ef-tests-cl/consensus_tests/sanity.go
@@ -2,7 +2,6 @@ package consensus_tests
import (
"io/fs"
- "log"
"os"
"testing"
@@ -63,7 +62,6 @@ var SanityBlocks = spectest.HandlerFunc(func(t *testing.T, root fs.FS, c spectes
var block *cltypes.SignedBeaconBlock
for _, block = range blocks {
- log.Println(block)
err = transition.TransitionState(testState, block, true)
if err != nil {
break
From 060107844629a2a834ed90316dc42d84d35d424d Mon Sep 17 00:00:00 2001
From: a
Date: Sun, 7 May 2023 08:52:14 -0500
Subject: [PATCH 08/34] a
---
cl/cltypes/solid/bitlist.go | 2 +-
cmd/ef-tests-cl/consensus_tests/sanity.go | 2 ++
cmd/erigon-cl/core/state/raw/getters.go | 4 ++++
cmd/erigon-cl/core/state/raw/ssz.go | 10 ++++++++--
4 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/cl/cltypes/solid/bitlist.go b/cl/cltypes/solid/bitlist.go
index 6ad12899cb6..b872c20ec69 100644
--- a/cl/cltypes/solid/bitlist.go
+++ b/cl/cltypes/solid/bitlist.go
@@ -75,6 +75,6 @@ func (u *bitlist) HashSSZTo(xs []byte) error {
func (u *bitlist) EncodeSSZ(dst []byte) []byte {
buf := dst
- buf = append(buf, u.u[:]...)
+ buf = append(buf, u.u...)
return buf
}
diff --git a/cmd/ef-tests-cl/consensus_tests/sanity.go b/cmd/ef-tests-cl/consensus_tests/sanity.go
index a48eeb9d0db..067a492485c 100644
--- a/cmd/ef-tests-cl/consensus_tests/sanity.go
+++ b/cmd/ef-tests-cl/consensus_tests/sanity.go
@@ -55,6 +55,8 @@ var SanityBlocks = spectest.HandlerFunc(func(t *testing.T, root fs.FS, c spectes
expectedState, err := spectest.ReadBeaconState(root, c.Version(), spectest.PostSsz)
if os.IsNotExist(err) {
expectedError = true
+ } else {
+ require.NoError(t, err)
}
blocks, err := spectest.ReadBlocks(root, c.Version())
diff --git a/cmd/erigon-cl/core/state/raw/getters.go b/cmd/erigon-cl/core/state/raw/getters.go
index 3e73c7698ab..17297390dfa 100644
--- a/cmd/erigon-cl/core/state/raw/getters.go
+++ b/cmd/erigon-cl/core/state/raw/getters.go
@@ -260,3 +260,7 @@ func (b *BeaconState) GetDomain(domainType [4]byte, epoch uint64) ([]byte, error
}
return fork.ComputeDomain(domainType[:], b.fork.CurrentVersion, b.genesisValidatorsRoot)
}
+
+func (b *BeaconState) DebugPrint(prefix string) {
+ fmt.Printf("%s: %x\n", prefix, b.currentEpochParticipation)
+}
diff --git a/cmd/erigon-cl/core/state/raw/ssz.go b/cmd/erigon-cl/core/state/raw/ssz.go
index c44f9595cc2..90a3ee99be0 100644
--- a/cmd/erigon-cl/core/state/raw/ssz.go
+++ b/cmd/erigon-cl/core/state/raw/ssz.go
@@ -409,8 +409,14 @@ func (b *BeaconState) DecodeSSZ(buf []byte, version int) error {
if currentEpochParticipation, err = ssz.DecodeString(buf, uint64(currentEpochParticipationOffset), uint64(inactivityScoresOffset), state_encoding.ValidatorRegistryLimit); err != nil {
return err
}
- b.previousEpochParticipation = solid.BitlistFromBytes(previousEpochParticipation, state_encoding.ValidatorRegistryLimit)
- b.currentEpochParticipation = solid.BitlistFromBytes(currentEpochParticipation, state_encoding.ValidatorRegistryLimit)
+ previousEpochParticipationCopy := make([]byte, len(previousEpochParticipation))
+ copy(previousEpochParticipationCopy, previousEpochParticipation)
+
+ currentEpochParticipationCopy := make([]byte, len(currentEpochParticipation))
+ copy(currentEpochParticipationCopy, currentEpochParticipation)
+
+ b.previousEpochParticipation = solid.BitlistFromBytes(previousEpochParticipationCopy, state_encoding.ValidatorRegistryLimit)
+ b.currentEpochParticipation = solid.BitlistFromBytes(currentEpochParticipationCopy, state_encoding.ValidatorRegistryLimit)
}
endOffset := uint32(len(buf))
From aedd1f8690730d152844e4df63d8308aaff6ea22 Mon Sep 17 00:00:00 2001
From: a
Date: Sun, 7 May 2023 09:11:26 -0500
Subject: [PATCH 09/34] pass the spec tests
---
cl/cltypes/solid/bitlist.go | 61 ++++++++++++++++++++++++----
cl/cltypes/solid/hashutil.go | 35 ++++++----------
cl/cltypes/solid/uint64slice_byte.go | 17 +++-----
3 files changed, 70 insertions(+), 43 deletions(-)
diff --git a/cl/cltypes/solid/bitlist.go b/cl/cltypes/solid/bitlist.go
index b872c20ec69..64b295a6fda 100644
--- a/cl/cltypes/solid/bitlist.go
+++ b/cl/cltypes/solid/bitlist.go
@@ -2,28 +2,36 @@ package solid
import (
"github.com/ledgerwatch/erigon/cl/merkle_tree"
+ "github.com/ledgerwatch/erigon/cl/utils"
+ "github.com/prysmaticlabs/gohashtree"
)
type bitlist struct {
u []byte
c int
+ l int
+
+ hashBuf
}
func NewBitList(l int, c int) BitList {
return &bitlist{
- u: make([]byte, l),
+ u: make([]byte, l+32),
+ l: l,
c: c,
}
}
func BitlistFromBytes(xs []byte, c int) BitList {
return &bitlist{
u: xs,
+ l: len(xs),
c: c,
}
}
func (u *bitlist) Clear() {
u.u = u.u[:0]
+ u.l = 0
}
func (u *bitlist) CopyTo(target BitList) {
@@ -41,11 +49,16 @@ func (u *bitlist) Range(fn func(index int, value byte, length int) bool) {
func (u *bitlist) Pop() (x byte) {
x, u.u = u.u[0], u.u[1:]
+ u.l = u.l - 1
return x
}
func (u *bitlist) Append(v byte) {
- u.u = append(u.u, v)
+ if len(u.u) <= u.l {
+ u.u = append(u.u, make([]byte, 32)...)
+ }
+ u.u[u.l] = v
+ u.l = u.l + 1
}
func (u *bitlist) Get(index int) byte {
@@ -57,7 +70,7 @@ func (u *bitlist) Set(index int, v byte) {
}
func (u *bitlist) Length() int {
- return len(u.u)
+ return u.l
}
func (u *bitlist) Cap() int {
@@ -65,16 +78,48 @@ func (u *bitlist) Cap() int {
}
func (u *bitlist) HashSSZTo(xs []byte) error {
- root, err := merkle_tree.BitlistRootWithLimitForState(u.u, uint64(u.c))
- if err != nil {
- return err
+ depth := getDepth((uint64(u.c) + 31) / 32)
+ baseRoot := [32]byte{}
+ if u.l == 0 {
+ copy(baseRoot[:], merkle_tree.ZeroHashes[depth][:])
+ } else {
+ err := u.getBaseHash(baseRoot[:])
+ if err != nil {
+ return err
+ }
+ }
+ lengthRoot := merkle_tree.Uint64Root(uint64(u.l))
+ ans := utils.Keccak256(baseRoot[:], lengthRoot[:])
+ copy(xs, ans[:])
+ return nil
+}
+
+func (arr *bitlist) getBaseHash(xs []byte) error {
+ depth := getDepth((uint64(arr.c) + 31) / 32)
+ offset := 32*(arr.l/32) + 32
+ if len(arr.u) <= offset {
+ arr.u = append(arr.u, make([]byte, offset-len(arr.u))...)
+ }
+ elements := arr.u[:offset]
+ for i := uint8(0); i < depth; i++ {
+ // Sequential
+ layerLen := len(elements)
+ if layerLen%64 == 32 {
+ elements = append(elements, merkle_tree.ZeroHashes[i][:]...)
+ }
+ outputLen := len(elements) / 2
+ arr.makeBuf(outputLen)
+ if err := gohashtree.HashByteSlice(arr.buf, elements); err != nil {
+ return err
+ }
+ elements = arr.buf
}
- copy(xs, root[:])
+ copy(xs, elements[:32])
return nil
}
func (u *bitlist) EncodeSSZ(dst []byte) []byte {
buf := dst
- buf = append(buf, u.u...)
+ buf = append(buf, u.u[:u.l]...)
return buf
}
diff --git a/cl/cltypes/solid/hashutil.go b/cl/cltypes/solid/hashutil.go
index 39a66233c31..f979013e7b7 100644
--- a/cl/cltypes/solid/hashutil.go
+++ b/cl/cltypes/solid/hashutil.go
@@ -8,6 +8,18 @@ import (
"github.com/prysmaticlabs/gohashtree"
)
+type hashBuf struct {
+ buf []byte
+}
+
+func (arr *hashBuf) makeBuf(size int) {
+ diff := size - len(arr.buf)
+ if diff > 0 {
+ arr.buf = append(arr.buf, make([]byte, diff)...)
+ }
+ arr.buf = arr.buf[:size]
+}
+
func TreeHashFlatSlice(input []byte, res []byte) (err error) {
err = merkle_tree.MerkleRootFromFlatLeaves(input, res)
if err != nil {
@@ -16,29 +28,6 @@ func TreeHashFlatSlice(input []byte, res []byte) (err error) {
return nil
}
-// MerkleizeVector uses our optimized routine to hash a list of 32-byte
-// elements.
-func MerkleizeVector(elements [][32]byte, length uint64) ([32]byte, error) {
- depth := getDepth(length)
- // Return zerohash at depth
- if len(elements) == 0 {
- return merkle_tree.ZeroHashes[depth], nil
- }
- for i := uint8(0); i < depth; i++ {
- // Sequential
- layerLen := len(elements)
- if layerLen%2 == 1 {
- elements = append(elements, merkle_tree.ZeroHashes[i])
- }
- outputLen := len(elements) / 2
- if err := gohashtree.Hash(elements, elements); err != nil {
- return [32]byte{}, err
- }
- elements = elements[:outputLen]
- }
- return elements[0], nil
-}
-
// MerkleizeVector uses our optimized routine to hash a list of 32-byte
// elements.
func MerkleizeFlatLeaves(elements []byte) ([]byte, error) {
diff --git a/cl/cltypes/solid/uint64slice_byte.go b/cl/cltypes/solid/uint64slice_byte.go
index a1dbae3a945..33f10eb3f0f 100644
--- a/cl/cltypes/solid/uint64slice_byte.go
+++ b/cl/cltypes/solid/uint64slice_byte.go
@@ -9,11 +9,12 @@ import (
)
type byteBasedUint64Slice struct {
- u []byte
- hashBuf []byte
+ u []byte
l int // len
c int // cap
+
+ hashBuf
}
func NewUint64Slice(limit int) Uint64Slice {
@@ -72,14 +73,6 @@ func (arr *byteBasedUint64Slice) Pop() uint64 {
return val
}
-func (arr *byteBasedUint64Slice) makeBuf(size int) {
- diff := size - len(arr.hashBuf)
- if diff > 0 {
- arr.hashBuf = append(arr.hashBuf, make([]byte, diff)...)
- }
- arr.hashBuf = arr.hashBuf[:size]
-}
-
func (arr *byteBasedUint64Slice) Append(v uint64) {
if len(arr.u) <= arr.l*8 {
arr.u = append(arr.u, make([]byte, 32)...)
@@ -142,10 +135,10 @@ func (arr *byteBasedUint64Slice) getBaseHash(xs []byte) error {
}
outputLen := len(elements) / 2
arr.makeBuf(outputLen)
- if err := gohashtree.HashByteSlice(arr.hashBuf, elements); err != nil {
+ if err := gohashtree.HashByteSlice(arr.buf, elements); err != nil {
return err
}
- elements = arr.hashBuf
+ elements = arr.buf
}
copy(xs, elements[:32])
return nil
From f50a99fd08fbd4cd30095ad0efe176369df5d2f9 Mon Sep 17 00:00:00 2001
From: a
Date: Sun, 7 May 2023 09:12:27 -0500
Subject: [PATCH 10/34] simplify
---
cl/cltypes/solid/bitlist.go | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/cl/cltypes/solid/bitlist.go b/cl/cltypes/solid/bitlist.go
index 64b295a6fda..131fdb13f20 100644
--- a/cl/cltypes/solid/bitlist.go
+++ b/cl/cltypes/solid/bitlist.go
@@ -83,7 +83,7 @@ func (u *bitlist) HashSSZTo(xs []byte) error {
if u.l == 0 {
copy(baseRoot[:], merkle_tree.ZeroHashes[depth][:])
} else {
- err := u.getBaseHash(baseRoot[:])
+ err := u.getBaseHash(baseRoot[:], depth)
if err != nil {
return err
}
@@ -94,8 +94,7 @@ func (u *bitlist) HashSSZTo(xs []byte) error {
return nil
}
-func (arr *bitlist) getBaseHash(xs []byte) error {
- depth := getDepth((uint64(arr.c) + 31) / 32)
+func (arr *bitlist) getBaseHash(xs []byte, depth uint8) error {
offset := 32*(arr.l/32) + 32
if len(arr.u) <= offset {
arr.u = append(arr.u, make([]byte, offset-len(arr.u))...)
From 8897a9e258698ebc6d87f8c22386ec21c09b03dc Mon Sep 17 00:00:00 2001
From: a
Date: Sun, 7 May 2023 09:16:10 -0500
Subject: [PATCH 11/34] merge
---
cmd/caplin-phase1/caplin1/run.go | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/cmd/caplin-phase1/caplin1/run.go b/cmd/caplin-phase1/caplin1/run.go
index 9d4738faf4d..f85cf38e826 100644
--- a/cmd/caplin-phase1/caplin1/run.go
+++ b/cmd/caplin-phase1/caplin1/run.go
@@ -29,7 +29,8 @@ func RunCaplinPhase1(ctx context.Context, sentinel sentinel.SentinelClient, beac
}
bls.SetEnabledCaching(true)
state.ForEachValidator(func(v *cltypes.Validator, idx, total int) bool {
- if err := bls.LoadPublicKeyIntoCache(v.PublicKey[:], false); err != nil {
+ pk := v.PublicKey()
+ if err := bls.LoadPublicKeyIntoCache(pk[:], false); err != nil {
panic(err)
}
return true
From ce99bc4b3296f840fcac08b84617ca3143385b93 Mon Sep 17 00:00:00 2001
From: a
Date: Sun, 7 May 2023 09:22:58 -0500
Subject: [PATCH 12/34] caplin
---
cmd/caplin-phase1/main.go | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/cmd/caplin-phase1/main.go b/cmd/caplin-phase1/main.go
index 656a05ba265..bff11cbfd1e 100644
--- a/cmd/caplin-phase1/main.go
+++ b/cmd/caplin-phase1/main.go
@@ -33,6 +33,7 @@ import (
"github.com/ledgerwatch/erigon/cmd/sentinel/sentinel"
"github.com/ledgerwatch/erigon/cmd/sentinel/sentinel/service"
lightclientapp "github.com/ledgerwatch/erigon/turbo/app"
+ "github.com/ledgerwatch/erigon/turbo/debug"
)
func main() {
@@ -52,6 +53,9 @@ func runCaplinNode(cliCtx *cli.Context) error {
if err != nil {
log.Error("[Phase1] Could not initialize caplin", "err", err)
}
+ if _, err := debug.Setup(cliCtx, true /* root logger */); err != nil {
+ return err
+ }
log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(cfg.LogLvl), log.StderrHandler))
log.Info("[Phase1]", "chain", cliCtx.String(flags.Chain.Name))
log.Info("[Phase1] Running Caplin", "cfg", cfg)
From ee33d8e4035372226a2971fe339dd0d22bbbd26f Mon Sep 17 00:00:00 2001
From: a
Date: Tue, 9 May 2023 10:02:41 -0500
Subject: [PATCH 13/34] fix some tests
---
cmd/erigon-cl/core/state/raw/state.go | 5 +-
cmd/erigon-cl/core/state/raw/test_util.go | 2 +
.../core/transition/operations_test.go | 51 +++++++++----------
.../core/transition/process_slots_test.go | 10 +++-
.../process_sync_committee_update_test.go | 6 ++-
.../core/transition/processing_test.go | 12 ++---
6 files changed, 47 insertions(+), 39 deletions(-)
diff --git a/cmd/erigon-cl/core/state/raw/state.go b/cmd/erigon-cl/core/state/raw/state.go
index b21aeb568fe..daa2f677dad 100644
--- a/cmd/erigon-cl/core/state/raw/state.go
+++ b/cmd/erigon-cl/core/state/raw/state.go
@@ -5,7 +5,6 @@ import (
"github.com/ledgerwatch/erigon/cl/clparams"
"github.com/ledgerwatch/erigon/cl/cltypes"
"github.com/ledgerwatch/erigon/cl/cltypes/solid"
- "github.com/ledgerwatch/erigon/cmd/erigon-cl/core/state/state_encoding"
)
const (
@@ -67,8 +66,8 @@ func New(cfg *clparams.BeaconChainConfig) *BeaconState {
//inactivityScores: solid.NewSimpleUint64Slice(int(cfg.ValidatorRegistryLimit)),
inactivityScores: solid.NewUint64Slice(int(cfg.ValidatorRegistryLimit)),
balances: solid.NewUint64Slice(int(cfg.ValidatorRegistryLimit)),
- previousEpochParticipation: solid.NewBitList(0, int(state_encoding.ValidatorRegistryLimit)),
- currentEpochParticipation: solid.NewBitList(0, int(state_encoding.ValidatorRegistryLimit)),
+ previousEpochParticipation: solid.NewBitList(0, int(cfg.ValidatorRegistryLimit)),
+ currentEpochParticipation: solid.NewBitList(0, int(cfg.ValidatorRegistryLimit)),
}
state.init()
return state
diff --git a/cmd/erigon-cl/core/state/raw/test_util.go b/cmd/erigon-cl/core/state/raw/test_util.go
index 78b251cace6..f0a2aa44cc8 100644
--- a/cmd/erigon-cl/core/state/raw/test_util.go
+++ b/cmd/erigon-cl/core/state/raw/test_util.go
@@ -26,6 +26,8 @@ func GetEmptyBeaconState() *BeaconState {
beaconConfig: cfg,
inactivityScores: solid.NewUint64Slice(int(cfg.ValidatorRegistryLimit)),
balances: solid.NewUint64Slice(int(cfg.ValidatorRegistryLimit)),
+ previousEpochParticipation: solid.NewBitList(0, int(cfg.ValidatorRegistryLimit)),
+ currentEpochParticipation: solid.NewBitList(0, int(cfg.ValidatorRegistryLimit)),
}
b.init()
return b
diff --git a/cmd/erigon-cl/core/transition/operations_test.go b/cmd/erigon-cl/core/transition/operations_test.go
index 2eedea892e6..38111efa7f2 100644
--- a/cmd/erigon-cl/core/transition/operations_test.go
+++ b/cmd/erigon-cl/core/transition/operations_test.go
@@ -188,36 +188,33 @@ func TestProcessProposerSlashing(t *testing.T) {
func TestProcessAttesterSlashing(t *testing.T) {
unchangingState := getTestState(t)
- unchangingState.SetValidatorAtIndex(0, &cltypes.Validator{
- Slashed: false,
- ActivationEpoch: 0,
- WithdrawableEpoch: 10000,
- PublicKey: testPublicKeySlashing,
- })
- unchangingState.SetValidatorAtIndex(1, &cltypes.Validator{
- Slashed: false,
- ActivationEpoch: 0,
- WithdrawableEpoch: 10000,
- PublicKey: testPublicKey2Slashing,
- })
+ v1 := &cltypes.Validator{}
+ v1.SetSlashed(false)
+ v1.SetActivationEpoch(0)
+ v1.SetWithdrawableEpoch(10000)
+ v1.SetPublicKey(testPublicKeySlashing)
+ v1c := &cltypes.Validator{}
+ v1.CopyTo(v1c)
+
+ v2 := &cltypes.Validator{}
+ v2.SetSlashed(false)
+ v2.SetActivationEpoch(0)
+ v2.SetWithdrawableEpoch(10000)
+ v2.SetPublicKey(testPublicKey2Slashing)
+ v2c := &cltypes.Validator{}
+ v2.CopyTo(v2c)
+
+ unchangingState.SetValidatorAtIndex(0, v1)
+ unchangingState.SetValidatorAtIndex(1, v2)
successState := getTestState(t)
- successState.SetValidatorAtIndex(0, &cltypes.Validator{
- Slashed: false,
- ActivationEpoch: 0,
- WithdrawableEpoch: 10000,
- PublicKey: testPublicKeySlashing,
- })
- successState.SetValidatorAtIndex(1, &cltypes.Validator{
- Slashed: false,
- ActivationEpoch: 0,
- WithdrawableEpoch: 10000,
- PublicKey: testPublicKey2Slashing,
- })
+ successState.SetValidatorAtIndex(0, v1c)
+ successState.SetValidatorAtIndex(1, v2c)
successBalances := []uint64{}
- for i := 0; i < len(successState.Validators()); i++ {
+ successState.ForEachValidator(func(v *cltypes.Validator, i, total int) bool {
successBalances = append(successBalances, uint64(i+1))
- }
+ return true
+ })
successState.SetBalances(successBalances)
successSlashing := getSuccessfulAttesterSlashing()
@@ -352,5 +349,5 @@ func TestProcessVoluntaryExits(t *testing.T) {
require.NoError(t, ProcessVoluntaryExit(state, exit, false), "Could not process exits")
newRegistry, err := state.ValidatorForValidatorIndex(0)
require.NoError(t, err)
- require.Equal(t, newRegistry.ExitEpoch, uint64(266))
+ require.Equal(t, newRegistry.ExitEpoch(), uint64(266))
}
diff --git a/cmd/erigon-cl/core/transition/process_slots_test.go b/cmd/erigon-cl/core/transition/process_slots_test.go
index dc7b91549af..97eb3a9439d 100644
--- a/cmd/erigon-cl/core/transition/process_slots_test.go
+++ b/cmd/erigon-cl/core/transition/process_slots_test.go
@@ -130,7 +130,10 @@ func TestTransitionSlot(t *testing.T) {
func TestProcessSlots(t *testing.T) {
slot42 := getTestBeaconState()
- slot42.AddValidator(&cltypes.Validator{ExitEpoch: clparams.MainnetBeaconConfig.FarFutureEpoch, WithdrawableEpoch: clparams.MainnetBeaconConfig.FarFutureEpoch}, 1)
+ v := &cltypes.Validator{}
+ v.SetExitEpoch(clparams.MainnetBeaconConfig.FarFutureEpoch)
+ v.SetWithdrawableEpoch(clparams.MainnetBeaconConfig.FarFutureEpoch)
+ slot42.AddValidator(v, 1)
slot42.SetSlot(42)
testCases := []struct {
description string
@@ -188,7 +191,10 @@ func TestProcessSlots(t *testing.T) {
for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) {
- tc.prevState.AddValidator(&cltypes.Validator{ExitEpoch: clparams.MainnetBeaconConfig.FarFutureEpoch, WithdrawableEpoch: clparams.MainnetBeaconConfig.FarFutureEpoch}, 1)
+ v := &cltypes.Validator{}
+ v.SetExitEpoch(clparams.MainnetBeaconConfig.FarFutureEpoch)
+ v.SetWithdrawableEpoch(clparams.MainnetBeaconConfig.FarFutureEpoch)
+ tc.prevState.AddValidator(v, 1)
err := ProcessSlots(tc.prevState, tc.startSlot+tc.numSlots)
if tc.wantErr {
if err == nil {
diff --git a/cmd/erigon-cl/core/transition/process_sync_committee_update_test.go b/cmd/erigon-cl/core/transition/process_sync_committee_update_test.go
index 96e4ddc2b78..b16260a0ccb 100644
--- a/cmd/erigon-cl/core/transition/process_sync_committee_update_test.go
+++ b/cmd/erigon-cl/core/transition/process_sync_committee_update_test.go
@@ -23,7 +23,11 @@ func TestProcessSyncCommittee(t *testing.T) {
for i := 0; i < validatorNum; i++ {
var pubKey [48]byte
binary.BigEndian.PutUint64(pubKey[:], uint64(i))
- state.AddValidator(&cltypes.Validator{ExitEpoch: clparams.MainnetBeaconConfig.FarFutureEpoch, PublicKey: pk, EffectiveBalance: 2000000000}, 2000000000)
+ v := &cltypes.Validator{}
+ v.SetExitEpoch(clparams.MainnetBeaconConfig.FarFutureEpoch)
+ v.SetPublicKey(pk)
+ v.SetEffectiveBalance(2000000000)
+ state.AddValidator(v, 2000000000)
if len(currentCommittee.PubKeys) != cltypes.SyncCommitteeSize {
currentCommittee.PubKeys = append(currentCommittee.PubKeys, [48]byte{})
} else if len(nextCommittee.PubKeys) != cltypes.SyncCommitteeSize {
diff --git a/cmd/erigon-cl/core/transition/processing_test.go b/cmd/erigon-cl/core/transition/processing_test.go
index 6ea60b5492e..baa8266e187 100644
--- a/cmd/erigon-cl/core/transition/processing_test.go
+++ b/cmd/erigon-cl/core/transition/processing_test.go
@@ -24,10 +24,10 @@ func getTestState(t *testing.T) *state.BeaconState {
numVals := 2048
validators := make([]*cltypes.Validator, numVals)
for i := 0; i < numVals; i++ {
- validators[i] = &cltypes.Validator{
- ActivationEpoch: 0,
- ExitEpoch: 10000,
- }
+ v := &cltypes.Validator{}
+ v.SetActivationEpoch(0)
+ v.SetExitEpoch(10000)
+ validators[i] = v
}
b := state.GetEmptyBeaconState()
b.SetValidators(validators)
@@ -85,7 +85,7 @@ func TestProcessBlockHeader(t *testing.T) {
badStateSlashed := getTestState(t)
validator, err := badStateSlashed.ValidatorForValidatorIndex(int(testBlock.ProposerIndex))
require.NoError(t, err)
- validator.Slashed = true
+ validator.SetSlashed(true)
badStateSlashed.SetValidatorAtIndex(int(testBlock.ProposerIndex), validator)
testCases := []struct {
@@ -162,7 +162,7 @@ func TestProcessRandao(t *testing.T) {
}
validator, err := testStateSuccess.ValidatorForValidatorIndex(int(propInd))
require.NoError(t, err)
- validator.PublicKey = testPublicKeyRandao
+ validator.SetPublicKey(testPublicKeyRandao)
testStateSuccess.SetValidatorAtIndex(int(propInd), validator)
testBlock := getTestBlock(t)
testBlock.Body.RandaoReveal = testSignatureRandao
From 451f0e4639ab95df0afd8539a1d9904dc4f7a7a9 Mon Sep 17 00:00:00 2001
From: a
Date: Tue, 9 May 2023 10:33:15 -0500
Subject: [PATCH 14/34] lint
---
cl/merkle_tree/primitives.go | 1 -
1 file changed, 1 deletion(-)
diff --git a/cl/merkle_tree/primitives.go b/cl/merkle_tree/primitives.go
index b8d46cc5b1c..f58ac6edce2 100644
--- a/cl/merkle_tree/primitives.go
+++ b/cl/merkle_tree/primitives.go
@@ -42,6 +42,5 @@ func InPlacePublicKeyRoot(key []byte) error {
if err != nil {
return err
}
- key = key[:32]
return nil
}
From a302512db3e7a76fad3c7d96f4848db37da166a1 Mon Sep 17 00:00:00 2001
From: a
Date: Tue, 9 May 2023 10:57:40 -0500
Subject: [PATCH 15/34] remove pool for now
---
cl/cltypes/validator.go | 25 +++++++++++++------------
1 file changed, 13 insertions(+), 12 deletions(-)
diff --git a/cl/cltypes/validator.go b/cl/cltypes/validator.go
index 0f8257814d0..171b30bfdb1 100644
--- a/cl/cltypes/validator.go
+++ b/cl/cltypes/validator.go
@@ -3,7 +3,6 @@ package cltypes
import (
"bytes"
"fmt"
- "sync"
libcommon "github.com/ledgerwatch/erigon-lib/common"
@@ -332,19 +331,21 @@ func (v *Validator) DecodeSSZ(buf []byte, _ int) error {
return v.Validator.DecodeSSZ(buf, 0)
}
-var validatorLeavesPool = sync.Pool{
- New: func() any {
- p := make([]byte, 8*32)
- return &p
- },
-}
+//var validatorLeavesPool = sync.Pool{
+// New: func() any {
+// p := make([]byte, 8*32)
+// return &p
+// },
+//}
func (v *Validator) HashSSZ() (o [32]byte, err error) {
- leavesp, _ := validatorLeavesPool.Get().(*[]byte)
- leaves := *leavesp
- defer func() {
- validatorLeavesPool.Put(leavesp)
- }()
+ // leavesp, _ := validatorLeavesPool.Get().(*[]byte)
+ // leaves := *leavesp
+ //
+ // defer func() {
+ // validatorLeavesPool.Put(leavesp)
+ // }()
+ leaves := make([]byte, 8*32)
v.CopyHashBufferTo(leaves)
leaves = leaves[:(8 * 32)]
err = solid.TreeHashFlatSlice(leaves, o[:])
From 14658e92dcdcdd3ef865e3a719ea1e2e0a2a02da Mon Sep 17 00:00:00 2001
From: a
Date: Tue, 9 May 2023 11:57:57 -0500
Subject: [PATCH 16/34] fix test
---
cmd/erigon-cl/core/transition/operations_test.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cmd/erigon-cl/core/transition/operations_test.go b/cmd/erigon-cl/core/transition/operations_test.go
index 38111efa7f2..e3b73ac5b40 100644
--- a/cmd/erigon-cl/core/transition/operations_test.go
+++ b/cmd/erigon-cl/core/transition/operations_test.go
@@ -349,5 +349,5 @@ func TestProcessVoluntaryExits(t *testing.T) {
require.NoError(t, ProcessVoluntaryExit(state, exit, false), "Could not process exits")
newRegistry, err := state.ValidatorForValidatorIndex(0)
require.NoError(t, err)
- require.Equal(t, newRegistry.ExitEpoch(), uint64(266))
+ require.Equal(t, newRegistry.ExitEpoch, uint64(266))
}
From e1742020dcdad9b917a1f32eb65c1f1feb70f7b3 Mon Sep 17 00:00:00 2001
From: a
Date: Tue, 9 May 2023 12:00:42 -0500
Subject: [PATCH 17/34] another patch
---
cmd/erigon-cl/core/transition/operations_test.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cmd/erigon-cl/core/transition/operations_test.go b/cmd/erigon-cl/core/transition/operations_test.go
index e3b73ac5b40..38111efa7f2 100644
--- a/cmd/erigon-cl/core/transition/operations_test.go
+++ b/cmd/erigon-cl/core/transition/operations_test.go
@@ -349,5 +349,5 @@ func TestProcessVoluntaryExits(t *testing.T) {
require.NoError(t, ProcessVoluntaryExit(state, exit, false), "Could not process exits")
newRegistry, err := state.ValidatorForValidatorIndex(0)
require.NoError(t, err)
- require.Equal(t, newRegistry.ExitEpoch, uint64(266))
+ require.Equal(t, newRegistry.ExitEpoch(), uint64(266))
}
From 33006a22c92f81edd883409d5f3365f00438f271 Mon Sep 17 00:00:00 2001
From: a
Date: Tue, 9 May 2023 12:52:34 -0500
Subject: [PATCH 18/34] rever prysm, bad test to see what happens on mac os
---
cl/cltypes/solid/bitlist.go | 3 +--
cl/cltypes/solid/hashutil.go | 3 +--
cl/cltypes/solid/uint64slice_byte.go | 3 +--
cl/merkle_tree/hasher.go | 33 +++++++++++++++++++++++-----
cl/merkle_tree/merkle_root.go | 7 ++++++
go.mod | 2 +-
go.sum | 2 ++
7 files changed, 41 insertions(+), 12 deletions(-)
diff --git a/cl/cltypes/solid/bitlist.go b/cl/cltypes/solid/bitlist.go
index 131fdb13f20..b0cdcdbb025 100644
--- a/cl/cltypes/solid/bitlist.go
+++ b/cl/cltypes/solid/bitlist.go
@@ -3,7 +3,6 @@ package solid
import (
"github.com/ledgerwatch/erigon/cl/merkle_tree"
"github.com/ledgerwatch/erigon/cl/utils"
- "github.com/prysmaticlabs/gohashtree"
)
type bitlist struct {
@@ -108,7 +107,7 @@ func (arr *bitlist) getBaseHash(xs []byte, depth uint8) error {
}
outputLen := len(elements) / 2
arr.makeBuf(outputLen)
- if err := gohashtree.HashByteSlice(arr.buf, elements); err != nil {
+ if err := merkle_tree.HashByteSlice(arr.buf, elements); err != nil {
return err
}
elements = arr.buf
diff --git a/cl/cltypes/solid/hashutil.go b/cl/cltypes/solid/hashutil.go
index f979013e7b7..006ff8350b6 100644
--- a/cl/cltypes/solid/hashutil.go
+++ b/cl/cltypes/solid/hashutil.go
@@ -5,7 +5,6 @@ import (
"github.com/ledgerwatch/erigon/cl/merkle_tree"
"github.com/ledgerwatch/erigon/cl/utils"
- "github.com/prysmaticlabs/gohashtree"
)
type hashBuf struct {
@@ -37,7 +36,7 @@ func MerkleizeFlatLeaves(elements []byte) ([]byte, error) {
if !utils.IsPowerOf2(uint64(len(elements))) {
return nil, fmt.Errorf("hash layer is a non power of 2: %d", len(elements))
}
- if err := gohashtree.HashByteSlice(layer, elements); err != nil {
+ if err := merkle_tree.HashByteSlice(layer, elements); err != nil {
return nil, err
}
elements = layer[:len(elements)/2]
diff --git a/cl/cltypes/solid/uint64slice_byte.go b/cl/cltypes/solid/uint64slice_byte.go
index 33f10eb3f0f..37cf7cea6a6 100644
--- a/cl/cltypes/solid/uint64slice_byte.go
+++ b/cl/cltypes/solid/uint64slice_byte.go
@@ -5,7 +5,6 @@ import (
"github.com/ledgerwatch/erigon/cl/merkle_tree"
"github.com/ledgerwatch/erigon/cl/utils"
- "github.com/prysmaticlabs/gohashtree"
)
type byteBasedUint64Slice struct {
@@ -135,7 +134,7 @@ func (arr *byteBasedUint64Slice) getBaseHash(xs []byte) error {
}
outputLen := len(elements) / 2
arr.makeBuf(outputLen)
- if err := gohashtree.HashByteSlice(arr.buf, elements); err != nil {
+ if err := merkle_tree.HashByteSlice(arr.buf, elements); err != nil {
return err
}
elements = arr.buf
diff --git a/cl/merkle_tree/hasher.go b/cl/merkle_tree/hasher.go
index 628b6c9db7e..8c2f0bc3f41 100644
--- a/cl/merkle_tree/hasher.go
+++ b/cl/merkle_tree/hasher.go
@@ -49,17 +49,32 @@ func (m *merkleHasher) merkleizeTrieLeaves(leaves [][32]byte) ([32]byte, error)
func (m *merkleHasher) merkleizeTrieLeavesFlat(leaves []byte, out []byte) (err error) {
m.mu.Lock()
defer m.mu.Unlock()
- layer := m.getFlatBuffer(len(leaves) / 2)
- for len(leaves) > 32 {
- if err := gohashtree.HashByteSlice(layer, leaves); err != nil {
+ layer := m.getBufferFromFlat(leaves)
+ for len(layer) > 1 {
+ if err := gohashtree.Hash(layer, layer); err != nil {
return err
}
- leaves = layer[:len(leaves)/2]
+ layer = layer[:len(layer)/2]
}
- copy(out, leaves[:32])
+ copy(out, layer[0][:])
return
}
+func (m *merkleHasher) hashByteSlice(out []byte, in []byte) error {
+ m.mu.Lock()
+ defer m.mu.Unlock()
+ l := m.getBufferFromFlat(in)
+ o := make([][32]byte, len(l)/2)
+ err := gohashtree.Hash(o, l)
+ if err != nil {
+ return err
+ }
+ for i := range o {
+ copy(out[i*32:(i+1)*32], o[i][:])
+ }
+ return nil
+}
+
// getBuffer provides buffer of given size.
func (m *merkleHasher) getBuffer(size int) [][32]byte {
if size > len(m.internalBuffer) {
@@ -68,6 +83,14 @@ func (m *merkleHasher) getBuffer(size int) [][32]byte {
return m.internalBuffer[:size]
}
+func (m *merkleHasher) getBufferFromFlat(xs []byte) [][32]byte {
+ buf := m.getBuffer(len(xs) / 32)
+ for i := 0; i < len(xs)/32; i = i + 1 {
+ copy(buf[i][:], xs[i*32:(i+1)*32])
+ }
+ return buf
+}
+
// getBuffer provides buffer of given size.
func (m *merkleHasher) getFlatBuffer(size int) []byte {
if size > len(m.internalFlatBuffer) {
diff --git a/cl/merkle_tree/merkle_root.go b/cl/merkle_tree/merkle_root.go
index 6ab2d05b15e..e29ebf29c51 100644
--- a/cl/merkle_tree/merkle_root.go
+++ b/cl/merkle_tree/merkle_root.go
@@ -4,6 +4,13 @@ import (
"errors"
)
+func HashByteSlice(out, in []byte) error {
+ if len(in) == 0 {
+ return errors.New("zero leaves provided")
+ }
+ return globalHasher.hashByteSlice(out, in)
+}
+
func MerkleRootFromLeaves(leaves [][32]byte) ([32]byte, error) {
if len(leaves) == 0 {
return [32]byte{}, errors.New("zero leaves provided")
diff --git a/go.mod b/go.mod
index 09009f89c81..96853e29efa 100644
--- a/go.mod
+++ b/go.mod
@@ -68,7 +68,7 @@ require (
github.com/protolambda/eth2-shuffle v1.1.0
github.com/protolambda/ztyp v0.2.2
github.com/prysmaticlabs/go-bitfield v0.0.0-20210809151128-385d8c5e3fb7
- github.com/prysmaticlabs/gohashtree v0.0.3-alpha.0.20230502123415-aafd8b3ca202
+ github.com/prysmaticlabs/gohashtree v0.0.3-alpha
github.com/quasilyte/go-ruleguard/dsl v0.3.22
github.com/rs/cors v1.9.0
github.com/shirou/gopsutil/v3 v3.23.4
diff --git a/go.sum b/go.sum
index 187ade2f70c..354282685d9 100644
--- a/go.sum
+++ b/go.sum
@@ -679,6 +679,8 @@ github.com/protolambda/ztyp v0.2.2 h1:rVcL3vBu9W/aV646zF6caLS/dyn9BN8NYiuJzicLNy
github.com/protolambda/ztyp v0.2.2/go.mod h1:9bYgKGqg3wJqT9ac1gI2hnVb0STQq7p/1lapqrqY1dU=
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/gohashtree v0.0.3-alpha h1:1EVinCWdb3Lorq7xn8DYQHf48nCcdAM3Vb18KsFlRWY=
+github.com/prysmaticlabs/gohashtree v0.0.3-alpha/go.mod h1:4pWaT30XoEx1j8KNJf3TV+E3mQkaufn7mf+jRNb/Fuk=
github.com/prysmaticlabs/gohashtree v0.0.3-alpha.0.20230502123415-aafd8b3ca202 h1:ZsFouPKy81vvQo/Zup5gASVdOm6aiuwUhp7GxvQmjIA=
github.com/prysmaticlabs/gohashtree v0.0.3-alpha.0.20230502123415-aafd8b3ca202/go.mod h1:4pWaT30XoEx1j8KNJf3TV+E3mQkaufn7mf+jRNb/Fuk=
github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe60+5DqOpCjPE=
From 09ca38a139ef5628034259b3bbcd7d75109a4d24 Mon Sep 17 00:00:00 2001
From: a
Date: Tue, 9 May 2023 13:19:25 -0500
Subject: [PATCH 19/34] start
---
cl/merkle_tree/merkle_root.go | 34 +++++++++++++++++++++++++++++++++-
1 file changed, 33 insertions(+), 1 deletion(-)
diff --git a/cl/merkle_tree/merkle_root.go b/cl/merkle_tree/merkle_root.go
index e29ebf29c51..aba4f6e18ae 100644
--- a/cl/merkle_tree/merkle_root.go
+++ b/cl/merkle_tree/merkle_root.go
@@ -2,13 +2,45 @@ package merkle_tree
import (
"errors"
+ "reflect"
+ "unsafe"
+
+ "github.com/prysmaticlabs/gohashtree"
)
func HashByteSlice(out, in []byte) error {
if len(in) == 0 {
return errors.New("zero leaves provided")
}
- return globalHasher.hashByteSlice(out, in)
+
+ if len(out)%32 != 0 {
+ return errors.New("output must be multple of 32")
+ }
+ if len(in)%64 != 0 {
+ return errors.New("input must be multple of 64")
+ }
+ c_in := convertHeader(in)
+ c_out := convertHeader(out)
+ err := gohashtree.Hash(c_out, c_in)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func convertHeader(xs []byte) [][32]byte {
+ header := *(*reflect.SliceHeader)(unsafe.Pointer(&xs))
+ header.Len /= 32
+ header.Cap /= 32
+ chunkedChunks := *(*[][32]byte)(unsafe.Pointer(&header))
+ return chunkedChunks
+}
+func convertHeaderBack(xs [][32]byte) []byte {
+ header := *(*reflect.SliceHeader)(unsafe.Pointer(&xs))
+ header.Len *= 32
+ header.Cap *= 32
+ unchunkedChunks := *(*[]byte)(unsafe.Pointer(&header))
+ return unchunkedChunks
}
func MerkleRootFromLeaves(leaves [][32]byte) ([32]byte, error) {
From cbb3c51f722b989fe8094c2599ec55228d115002 Mon Sep 17 00:00:00 2001
From: a
Date: Tue, 9 May 2023 13:45:12 -0500
Subject: [PATCH 20/34] note
---
cl/merkle_tree/merkle_root.go | 32 ++++++++++++++++++++------------
1 file changed, 20 insertions(+), 12 deletions(-)
diff --git a/cl/merkle_tree/merkle_root.go b/cl/merkle_tree/merkle_root.go
index aba4f6e18ae..0a844ac3e88 100644
--- a/cl/merkle_tree/merkle_root.go
+++ b/cl/merkle_tree/merkle_root.go
@@ -29,18 +29,26 @@ func HashByteSlice(out, in []byte) error {
}
func convertHeader(xs []byte) [][32]byte {
- header := *(*reflect.SliceHeader)(unsafe.Pointer(&xs))
- header.Len /= 32
- header.Cap /= 32
- chunkedChunks := *(*[][32]byte)(unsafe.Pointer(&header))
- return chunkedChunks
-}
-func convertHeaderBack(xs [][32]byte) []byte {
- header := *(*reflect.SliceHeader)(unsafe.Pointer(&xs))
- header.Len *= 32
- header.Cap *= 32
- unchunkedChunks := *(*[]byte)(unsafe.Pointer(&header))
- return unchunkedChunks
+ // this commented naive method of conversion supposedly leads to corruption https://github.com/golang/go/issues/40701
+ //header := *(*reflect.SliceHeader)(unsafe.Pointer(&xs))
+ //header.Len /= 32
+ //header.Cap /= 32
+ //chunkedChunks := *(*[][32]byte)(unsafe.Pointer(&header))
+ //supposedly, this is because escape analysis does not correctly analyze this, and so you have this ghost header?
+
+ // i wont pretend to understand, but my solution for the problem is as so
+
+ // first i grab the slice header of the input
+ header := (*reflect.SliceHeader)(unsafe.Pointer(&xs))
+ // then i allocate a new result slice of no size - this should make the escape analyzer happy i think?
+ dat := make([][32]byte, 0)
+ // we then get the header of our output to modify
+ chunkedHeader := (*reflect.SliceHeader)(unsafe.Pointer(&dat))
+ // then we move over the values
+ chunkedHeader.Len = header.Len / 32
+ chunkedHeader.Cap = header.Cap / 32
+ chunkedHeader.Data = header.Data
+ return dat
}
func MerkleRootFromLeaves(leaves [][32]byte) ([32]byte, error) {
From 13562c5366a1f29682c13c867b5f711e26f0433b Mon Sep 17 00:00:00 2001
From: a
Date: Wed, 10 May 2023 07:07:26 -0500
Subject: [PATCH 21/34] add comment
---
cl/merkle_tree/merkle_root.go | 1 +
1 file changed, 1 insertion(+)
diff --git a/cl/merkle_tree/merkle_root.go b/cl/merkle_tree/merkle_root.go
index 0a844ac3e88..d115829e949 100644
--- a/cl/merkle_tree/merkle_root.go
+++ b/cl/merkle_tree/merkle_root.go
@@ -8,6 +8,7 @@ import (
"github.com/prysmaticlabs/gohashtree"
)
+// HashByteSlice is gohashtree HashBytSlice but using our hopefully safer header converstion
func HashByteSlice(out, in []byte) error {
if len(in) == 0 {
return errors.New("zero leaves provided")
From 0b088233746ea70835ced3661ac3c1246c7cfb19 Mon Sep 17 00:00:00 2001
From: a
Date: Wed, 10 May 2023 07:40:48 -0500
Subject: [PATCH 22/34] instrumentation basic
---
cmd/erigon-cl/core/state/ssz.go | 19 +++++++++--
.../core/transition/block_transition.go | 18 ++++++++++
metrics/methelp/timer.go | 33 +++++++++++++++++++
3 files changed, 68 insertions(+), 2 deletions(-)
create mode 100644 metrics/methelp/timer.go
diff --git a/cmd/erigon-cl/core/state/ssz.go b/cmd/erigon-cl/core/state/ssz.go
index ca26fb33c68..335d4e9200f 100644
--- a/cmd/erigon-cl/core/state/ssz.go
+++ b/cmd/erigon-cl/core/state/ssz.go
@@ -1,23 +1,38 @@
package state
import (
+ "github.com/VictoriaMetrics/metrics"
"github.com/ledgerwatch/erigon/cl/cltypes/clonable"
+ "github.com/ledgerwatch/erigon/metrics/methelp"
)
func (b *BeaconState) EncodeSSZ(buf []byte) ([]byte, error) {
- return b.BeaconState.EncodeSSZ(buf)
+ h := methelp.NewHistTimer("encode_ssz_beacon_state_dur")
+ bts, err := b.BeaconState.EncodeSSZ(buf)
+ if err != nil {
+ return nil, err
+ }
+ h.PutSince()
+ sz := metrics.NewHistogram("encode_ssz_beacon_state_size")
+ sz.Update(float64(len(bts)))
+ return bts, err
}
func (b *BeaconState) DecodeSSZ(buf []byte, version int) error {
+ h := methelp.NewHistTimer("decode_ssz_beacon_state_dur")
if err := b.BeaconState.DecodeSSZ(buf, version); err != nil {
return err
}
+ sz := metrics.NewHistogram("decode_ssz_beacon_state_size")
+ sz.Update(float64(len(buf)))
+ h.PutSince()
return b.initBeaconState()
}
// SSZ size of the Beacon State
func (b *BeaconState) EncodingSizeSSZ() (size int) {
- return b.BeaconState.EncodingSizeSSZ()
+ sz := b.BeaconState.EncodingSizeSSZ()
+ return sz
}
func (b *BeaconState) Clone() clonable.Clonable {
diff --git a/cmd/erigon-cl/core/transition/block_transition.go b/cmd/erigon-cl/core/transition/block_transition.go
index a3ba1c0fa73..a8b49a936db 100644
--- a/cmd/erigon-cl/core/transition/block_transition.go
+++ b/cmd/erigon-cl/core/transition/block_transition.go
@@ -8,6 +8,7 @@ import (
"github.com/ledgerwatch/erigon/cl/clparams"
"github.com/ledgerwatch/erigon/cl/cltypes"
"github.com/ledgerwatch/erigon/cmd/erigon-cl/core/state"
+ "github.com/ledgerwatch/erigon/metrics/methelp"
)
// processBlock takes a block and transitions the state to the next slot, using the provided execution payload if enabled.
@@ -19,48 +20,65 @@ func processBlock(state *state.BeaconState, signedBlock *cltypes.SignedBeaconBlo
return fmt.Errorf("processBlock: wrong state version for block at slot %d", block.Slot)
}
+ h := methelp.NewHistTimer("beacon_process_block")
+
+ c := h.Child("block_header_dur")
// Process the block header.
if err := ProcessBlockHeader(state, block, fullValidation); err != nil {
return fmt.Errorf("processBlock: failed to process block header: %v", err)
}
+ c.PutSince()
// Process execution payload if enabled.
if version >= clparams.BellatrixVersion && executionEnabled(state, block.Body.ExecutionPayload) {
if state.Version() >= clparams.CapellaVersion {
// Process withdrawals in the execution payload.
+ c = h.Child("withdrawals")
if err := ProcessWithdrawals(state, block.Body.ExecutionPayload.Withdrawals, fullValidation); err != nil {
return fmt.Errorf("processBlock: failed to process withdrawals: %v", err)
}
+ c.PutSince()
}
// Process the execution payload.
+ c = h.Child("execution_payload")
if err := ProcessExecutionPayload(state, block.Body.ExecutionPayload); err != nil {
return fmt.Errorf("processBlock: failed to process execution payload: %v", err)
}
+ c.PutSince()
}
// Process RANDAO reveal.
+ c = h.Child("randao_reveal")
if err := ProcessRandao(state, block.Body.RandaoReveal, block.ProposerIndex, fullValidation); err != nil {
return fmt.Errorf("processBlock: failed to process RANDAO reveal: %v", err)
}
+ c.PutSince()
// Process Eth1 data.
+ c = h.Child("eth1_data")
if err := ProcessEth1Data(state, block.Body.Eth1Data); err != nil {
return fmt.Errorf("processBlock: failed to process Eth1 data: %v", err)
}
+ c.PutSince()
// Process block body operations.
+ c = h.Child("operations")
if err := processOperations(state, block.Body, fullValidation); err != nil {
return fmt.Errorf("processBlock: failed to process block body operations: %v", err)
}
+ c.PutSince()
// Process sync aggregate in case of Altair version.
if version >= clparams.AltairVersion {
+ c = h.Child("sync_aggregate")
if err := ProcessSyncAggregate(state, block.Body.SyncAggregate, fullValidation); err != nil {
return fmt.Errorf("processBlock: failed to process sync aggregate: %v", err)
}
+ c.PutSince()
}
+ h.PutSince()
return nil
}
diff --git a/metrics/methelp/timer.go b/metrics/methelp/timer.go
new file mode 100644
index 00000000000..1726c1881c6
--- /dev/null
+++ b/metrics/methelp/timer.go
@@ -0,0 +1,33 @@
+package methelp
+
+import (
+ "strings"
+ "time"
+
+ "github.com/VictoriaMetrics/metrics"
+)
+
+type HistTimer struct {
+ *metrics.Histogram
+
+ start time.Time
+
+ name string
+}
+
+func NewHistTimer(name string) *HistTimer {
+ return &HistTimer{
+ Histogram: metrics.NewHistogram(name),
+ start: time.Now(),
+ name: name,
+ }
+}
+
+func (h *HistTimer) PutSince() {
+ h.Histogram.UpdateDuration(h.start)
+}
+
+func (h *HistTimer) Child(suffix string) *HistTimer {
+ suffix = strings.TrimPrefix(suffix, "_")
+ return NewHistTimer(h.name + "_" + suffix)
+}
From 6bb3303cc106dacea081f769af23868bcb47be66 Mon Sep 17 00:00:00 2001
From: a
Date: Wed, 10 May 2023 09:01:22 -0500
Subject: [PATCH 23/34] basic instrumentation
---
cmd/erigon-cl/core/state/ssz.go | 2 +-
.../core/transition/block_transition.go | 31 ++++++++++++++-----
go.mod | 2 ++
go.sum | 6 ++--
metrics/methelp/timer.go | 11 ++++++-
5 files changed, 39 insertions(+), 13 deletions(-)
diff --git a/cmd/erigon-cl/core/state/ssz.go b/cmd/erigon-cl/core/state/ssz.go
index 335d4e9200f..5774986e278 100644
--- a/cmd/erigon-cl/core/state/ssz.go
+++ b/cmd/erigon-cl/core/state/ssz.go
@@ -23,7 +23,7 @@ func (b *BeaconState) DecodeSSZ(buf []byte, version int) error {
if err := b.BeaconState.DecodeSSZ(buf, version); err != nil {
return err
}
- sz := metrics.NewHistogram("decode_ssz_beacon_state_size")
+ sz := methelp.NewHistTimer("decode_ssz_beacon_state_size")
sz.Update(float64(len(buf)))
h.PutSince()
return b.initBeaconState()
diff --git a/cmd/erigon-cl/core/transition/block_transition.go b/cmd/erigon-cl/core/transition/block_transition.go
index a8b49a936db..69b9317aa11 100644
--- a/cmd/erigon-cl/core/transition/block_transition.go
+++ b/cmd/erigon-cl/core/transition/block_transition.go
@@ -22,7 +22,7 @@ func processBlock(state *state.BeaconState, signedBlock *cltypes.SignedBeaconBlo
h := methelp.NewHistTimer("beacon_process_block")
- c := h.Child("block_header_dur")
+ c := h.Tag("process_step", "block_header")
// Process the block header.
if err := ProcessBlockHeader(state, block, fullValidation); err != nil {
return fmt.Errorf("processBlock: failed to process block header: %v", err)
@@ -33,7 +33,7 @@ func processBlock(state *state.BeaconState, signedBlock *cltypes.SignedBeaconBlo
if version >= clparams.BellatrixVersion && executionEnabled(state, block.Body.ExecutionPayload) {
if state.Version() >= clparams.CapellaVersion {
// Process withdrawals in the execution payload.
- c = h.Child("withdrawals")
+ c = h.Tag("process_step", "withdrawals")
if err := ProcessWithdrawals(state, block.Body.ExecutionPayload.Withdrawals, fullValidation); err != nil {
return fmt.Errorf("processBlock: failed to process withdrawals: %v", err)
}
@@ -41,7 +41,7 @@ func processBlock(state *state.BeaconState, signedBlock *cltypes.SignedBeaconBlo
}
// Process the execution payload.
- c = h.Child("execution_payload")
+ c = h.Tag("process_step", "execution_payload")
if err := ProcessExecutionPayload(state, block.Body.ExecutionPayload); err != nil {
return fmt.Errorf("processBlock: failed to process execution payload: %v", err)
}
@@ -49,21 +49,21 @@ func processBlock(state *state.BeaconState, signedBlock *cltypes.SignedBeaconBlo
}
// Process RANDAO reveal.
- c = h.Child("randao_reveal")
+ c = h.Tag("process_step", "randao_reveal")
if err := ProcessRandao(state, block.Body.RandaoReveal, block.ProposerIndex, fullValidation); err != nil {
return fmt.Errorf("processBlock: failed to process RANDAO reveal: %v", err)
}
c.PutSince()
// Process Eth1 data.
- c = h.Child("eth1_data")
+ c = h.Tag("process_step", "eth1_data")
if err := ProcessEth1Data(state, block.Body.Eth1Data); err != nil {
return fmt.Errorf("processBlock: failed to process Eth1 data: %v", err)
}
c.PutSince()
// Process block body operations.
- c = h.Child("operations")
+ c = h.Tag("process_step", "operations")
if err := processOperations(state, block.Body, fullValidation); err != nil {
return fmt.Errorf("processBlock: failed to process block body operations: %v", err)
}
@@ -71,7 +71,7 @@ func processBlock(state *state.BeaconState, signedBlock *cltypes.SignedBeaconBlo
// Process sync aggregate in case of Altair version.
if version >= clparams.AltairVersion {
- c = h.Child("sync_aggregate")
+ c = h.Tag("process_step", "sync_aggregate")
if err := ProcessSyncAggregate(state, block.Body.SyncAggregate, fullValidation); err != nil {
return fmt.Errorf("processBlock: failed to process sync aggregate: %v", err)
}
@@ -86,41 +86,58 @@ func processOperations(state *state.BeaconState, blockBody *cltypes.BeaconBody,
if len(blockBody.Deposits) != int(maximumDeposits(state)) {
return errors.New("outstanding deposits do not match maximum deposits")
}
+ h := methelp.NewHistTimer("beacon_process_block_operations")
+
// Process each proposer slashing
+ c := h.Tag("operation", "proposer_slashings")
for _, slashing := range blockBody.ProposerSlashings {
if err := ProcessProposerSlashing(state, slashing); err != nil {
return fmt.Errorf("ProcessProposerSlashing: %s", err)
}
}
+ c.PutSince()
// Process each attester slashing
+ c = h.Tag("operation", "attester_slashings")
for _, slashing := range blockBody.AttesterSlashings {
if err := ProcessAttesterSlashing(state, slashing); err != nil {
return fmt.Errorf("ProcessAttesterSlashing: %s", err)
}
}
+ c.PutSince()
+
// Process each attestations
+ c = h.Tag("operation", "attestations")
if err := ProcessAttestations(state, blockBody.Attestations, fullValidation); err != nil {
return fmt.Errorf("ProcessAttestation: %s", err)
}
+ c.PutSince()
+
// Process each deposit
+ c = h.Tag("operation", "deposit")
for _, dep := range blockBody.Deposits {
if err := ProcessDeposit(state, dep, fullValidation); err != nil {
return fmt.Errorf("ProcessDeposit: %s", err)
}
}
+ c.PutSince()
+
// Process each voluntary exit.
+ c = h.Tag("operation", "voluntary_exit")
for _, exit := range blockBody.VoluntaryExits {
if err := ProcessVoluntaryExit(state, exit, fullValidation); err != nil {
return fmt.Errorf("ProcessVoluntaryExit: %s", err)
}
}
+ c.PutSince()
// Process each execution change. this will only have entries after the capella fork.
+ c = h.Tag("operation", "execution_change")
for _, addressChange := range blockBody.ExecutionChanges {
if err := ProcessBlsToExecutionChange(state, addressChange, fullValidation); err != nil {
return err
}
}
+ c.PutSince()
return nil
}
diff --git a/go.mod b/go.mod
index 96853e29efa..08300b12a13 100644
--- a/go.mod
+++ b/go.mod
@@ -271,3 +271,5 @@ require (
)
replace github.com/tendermint/tendermint => github.com/bnb-chain/tendermint v0.31.12
+
+replace github.com/VictoriaMetrics/metrics => github.com/greyireland/metrics v0.0.5
diff --git a/go.sum b/go.sum
index 354282685d9..4e3f970e62c 100644
--- a/go.sum
+++ b/go.sum
@@ -29,8 +29,6 @@ github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWX
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40=
github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o=
-github.com/VictoriaMetrics/metrics v1.23.1 h1:/j8DzeJBxSpL2qSIdqnRFLvQQhbJyJbbEi22yMm7oL0=
-github.com/VictoriaMetrics/metrics v1.23.1/go.mod h1:rAr/llLpEnAdTehiNlUxKgnjcOuROSzpw0GvjpEbvFc=
github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8=
github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo=
@@ -358,6 +356,8 @@ github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
+github.com/greyireland/metrics v0.0.5 h1:FgHLl8lF4D0i77NlgJM7txwdwGStSH5x/thxv2o0IPA=
+github.com/greyireland/metrics v0.0.5/go.mod h1:rAr/llLpEnAdTehiNlUxKgnjcOuROSzpw0GvjpEbvFc=
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI=
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8=
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
@@ -681,8 +681,6 @@ github.com/prysmaticlabs/go-bitfield v0.0.0-20210809151128-385d8c5e3fb7 h1:0tVE4
github.com/prysmaticlabs/go-bitfield v0.0.0-20210809151128-385d8c5e3fb7/go.mod h1:wmuf/mdK4VMD+jA9ThwcUKjg3a2XWM9cVfFYjDyY4j4=
github.com/prysmaticlabs/gohashtree v0.0.3-alpha h1:1EVinCWdb3Lorq7xn8DYQHf48nCcdAM3Vb18KsFlRWY=
github.com/prysmaticlabs/gohashtree v0.0.3-alpha/go.mod h1:4pWaT30XoEx1j8KNJf3TV+E3mQkaufn7mf+jRNb/Fuk=
-github.com/prysmaticlabs/gohashtree v0.0.3-alpha.0.20230502123415-aafd8b3ca202 h1:ZsFouPKy81vvQo/Zup5gASVdOm6aiuwUhp7GxvQmjIA=
-github.com/prysmaticlabs/gohashtree v0.0.3-alpha.0.20230502123415-aafd8b3ca202/go.mod h1:4pWaT30XoEx1j8KNJf3TV+E3mQkaufn7mf+jRNb/Fuk=
github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe60+5DqOpCjPE=
github.com/quasilyte/go-ruleguard/dsl v0.3.22/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU=
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
diff --git a/metrics/methelp/timer.go b/metrics/methelp/timer.go
index 1726c1881c6..9450a696ac2 100644
--- a/metrics/methelp/timer.go
+++ b/metrics/methelp/timer.go
@@ -1,6 +1,7 @@
package methelp
import (
+ "fmt"
"strings"
"time"
@@ -17,7 +18,7 @@ type HistTimer struct {
func NewHistTimer(name string) *HistTimer {
return &HistTimer{
- Histogram: metrics.NewHistogram(name),
+ Histogram: metrics.GetOrCreateCompatibleHistogram(name),
start: time.Now(),
name: name,
}
@@ -27,6 +28,14 @@ func (h *HistTimer) PutSince() {
h.Histogram.UpdateDuration(h.start)
}
+func (h *HistTimer) Tag(tag string, value string) *HistTimer {
+ return &HistTimer{
+ Histogram: metrics.GetOrCreateCompatibleHistogram(fmt.Sprintf(`%s{%s="%s"}`, h.name, tag, value)),
+ start: time.Now(),
+ name: h.name,
+ }
+}
+
func (h *HistTimer) Child(suffix string) *HistTimer {
suffix = strings.TrimPrefix(suffix, "_")
return NewHistTimer(h.name + "_" + suffix)
From 811a7f189b1e474db64d83952cea8ea00fc6c14d Mon Sep 17 00:00:00 2001
From: a
Date: Wed, 10 May 2023 09:14:41 -0500
Subject: [PATCH 24/34] multiple tags
---
metrics/methelp/timer.go | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/metrics/methelp/timer.go b/metrics/methelp/timer.go
index 9450a696ac2..0ccd6a69f5f 100644
--- a/metrics/methelp/timer.go
+++ b/metrics/methelp/timer.go
@@ -28,9 +28,20 @@ func (h *HistTimer) PutSince() {
h.Histogram.UpdateDuration(h.start)
}
-func (h *HistTimer) Tag(tag string, value string) *HistTimer {
+func (h *HistTimer) Tag(pairs ...string) *HistTimer {
+ if len(pairs)%2 != 0 {
+ pairs = append(pairs, "UNEQUAL_KEY_VALUE_TAGS")
+ }
+ toJoin := []string{}
+ for i := 0; i < len(pairs); i = i + 2 {
+ toJoin = append(toJoin, fmt.Sprintf(`%s="%s"`, pairs[i], pairs[i+1]))
+ }
+ tags := ""
+ if len(toJoin) > 0 {
+ tags = "{" + strings.Join(toJoin, ",") + "}"
+ }
return &HistTimer{
- Histogram: metrics.GetOrCreateCompatibleHistogram(fmt.Sprintf(`%s{%s="%s"}`, h.name, tag, value)),
+ Histogram: metrics.GetOrCreateCompatibleHistogram(h.name + tags),
start: time.Now(),
name: h.name,
}
From aff2bac2f086af95139b58b94bdd0bc7e88d5a5d Mon Sep 17 00:00:00 2001
From: a
Date: Wed, 10 May 2023 09:15:46 -0500
Subject: [PATCH 25/34] rawName in timer allows using tag on tag and child on
tag
---
metrics/methelp/timer.go | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/metrics/methelp/timer.go b/metrics/methelp/timer.go
index 0ccd6a69f5f..3aefda89d1b 100644
--- a/metrics/methelp/timer.go
+++ b/metrics/methelp/timer.go
@@ -17,10 +17,11 @@ type HistTimer struct {
}
func NewHistTimer(name string) *HistTimer {
+ rawName := strings.Split(name, "{")
return &HistTimer{
Histogram: metrics.GetOrCreateCompatibleHistogram(name),
start: time.Now(),
- name: name,
+ name: rawName[0],
}
}
From 23a727bae365d7230aea886395716a181ec1723a Mon Sep 17 00:00:00 2001
From: a
Date: Wed, 10 May 2023 09:23:53 -0500
Subject: [PATCH 26/34] refmt
---
cmd/sentinel/sentinel/service/start.go | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/cmd/sentinel/sentinel/service/start.go b/cmd/sentinel/sentinel/service/start.go
index 23d3628c601..f306fb73c7c 100644
--- a/cmd/sentinel/sentinel/service/start.go
+++ b/cmd/sentinel/sentinel/service/start.go
@@ -89,7 +89,11 @@ WaitingLoop:
}
}
- conn, err := grpc.DialContext(ctx, srvCfg.Addr, grpc.WithTransportCredentials(creds), grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(maxMessageSize)))
+ conn, err := grpc.DialContext(ctx,
+ srvCfg.Addr,
+ grpc.WithTransportCredentials(creds),
+ grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(maxMessageSize)),
+ )
if err != nil {
return nil, err
}
From 5cdf994dfda44d4713154d87d0e1aef49fcaafb1 Mon Sep 17 00:00:00 2001
From: a
Date: Wed, 10 May 2023 09:34:47 -0500
Subject: [PATCH 27/34] new
---
cmd/sentinel/sentinel/sentinel.go | 21 ++++-----------------
metrics/exp/exp.go | 11 +++++++----
2 files changed, 11 insertions(+), 21 deletions(-)
diff --git a/cmd/sentinel/sentinel/sentinel.go b/cmd/sentinel/sentinel/sentinel.go
index 4b042a7cfb2..e79f29a6cd3 100644
--- a/cmd/sentinel/sentinel/sentinel.go
+++ b/cmd/sentinel/sentinel/sentinel.go
@@ -20,7 +20,6 @@ import (
"math"
"net"
- "net/http"
"time"
"github.com/ledgerwatch/erigon-lib/kv"
@@ -41,7 +40,6 @@ import (
rcmgr "github.com/libp2p/go-libp2p/p2p/host/resource-manager"
rcmgrObs "github.com/libp2p/go-libp2p/p2p/host/resource-manager/obs"
"github.com/prometheus/client_golang/prometheus"
- "github.com/prometheus/client_golang/prometheus/promhttp"
)
const (
@@ -236,10 +234,10 @@ func New(
db kv.RoDB,
) (*Sentinel, error) {
s := &Sentinel{
- ctx: ctx,
- cfg: cfg,
- db: db,
- // metrics: true,
+ ctx: ctx,
+ cfg: cfg,
+ db: db,
+ metrics: true,
}
// Setup discovery
@@ -265,17 +263,6 @@ func New(
return nil, err
}
if s.metrics {
- http.Handle("/metrics", promhttp.Handler())
- go func() {
- server := &http.Server{
- Addr: ":2112",
- ReadHeaderTimeout: time.Hour,
- }
- if err := server.ListenAndServe(); err != nil {
- panic(err)
- }
- }()
-
rcmgrObs.MustRegisterWith(prometheus.DefaultRegisterer)
str, err := rcmgrObs.NewStatsTraceReporter()
diff --git a/metrics/exp/exp.go b/metrics/exp/exp.go
index 763dc41efe5..76e6ddc76c5 100644
--- a/metrics/exp/exp.go
+++ b/metrics/exp/exp.go
@@ -8,6 +8,8 @@ import (
metrics2 "github.com/VictoriaMetrics/metrics"
"github.com/ledgerwatch/log/v3"
+ "github.com/prometheus/client_golang/prometheus"
+ "github.com/prometheus/client_golang/prometheus/promhttp"
)
// Setup starts a dedicated metrics server at the given address.
@@ -18,10 +20,11 @@ func Setup(address string) {
metrics2.WritePrometheus(w, true)
})
//m.Handle("/debug/metrics", ExpHandler(metrics.DefaultRegistry))
- //m.Handle("/debug/metrics/prometheus2", promhttp.HandlerFor(prometheus2.DefaultGatherer, promhttp.HandlerOpts{
- // EnableOpenMetrics: true,
- //}))
- log.Info("Starting metrics server", "addr", fmt.Sprintf("http://%s/debug/metrics/prometheus", address))
+ http.Handle("/debug/metrics/prometheus2", promhttp.HandlerFor(prometheus.DefaultGatherer, promhttp.HandlerOpts{}))
+ log.Info("Starting metrics server", "addr",
+ fmt.Sprintf("http://%s/debug/metrics/prometheus", address),
+ fmt.Sprintf("http://%s/debug/metrics/prometheus2", address),
+ )
go func() {
if err := http.ListenAndServe(address, nil); err != nil { // nolint:gosec
log.Error("Failure in running metrics server", "err", err)
From 249a5d46a904e1bb8f8f26831210f059efc774ee Mon Sep 17 00:00:00 2001
From: a
Date: Wed, 10 May 2023 10:05:42 -0500
Subject: [PATCH 28/34] combine metric handlers
---
cmd/erigon-cl/core/state/cache.go | 8 ++---
cmd/erigon-cl/core/state/cache_accessors.go | 1 +
cmd/erigon-cl/core/state/lru/lru.go | 33 +++++++++++++++++++
cmd/erigon-cl/core/state/util.go | 5 +--
.../core/transition/process_attestations.go | 7 +++-
metrics/exp/exp.go | 16 ++++++---
6 files changed, 57 insertions(+), 13 deletions(-)
create mode 100644 cmd/erigon-cl/core/state/lru/lru.go
diff --git a/cmd/erigon-cl/core/state/cache.go b/cmd/erigon-cl/core/state/cache.go
index b7d8f0fe5e0..583b410206f 100644
--- a/cmd/erigon-cl/core/state/cache.go
+++ b/cmd/erigon-cl/core/state/cache.go
@@ -4,12 +4,12 @@ import (
"crypto/sha256"
"encoding/binary"
- lru "github.com/hashicorp/golang-lru/v2"
"github.com/ledgerwatch/erigon-lib/common"
libcommon "github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon/cl/clparams"
"github.com/ledgerwatch/erigon/cl/cltypes"
"github.com/ledgerwatch/erigon/cl/utils"
+ "github.com/ledgerwatch/erigon/cmd/erigon-cl/core/state/lru"
"github.com/ledgerwatch/erigon/cmd/erigon-cl/core/state/raw"
"github.com/ledgerwatch/erigon/cmd/erigon-cl/core/state/shuffling"
)
@@ -194,13 +194,13 @@ func (b *BeaconState) _refreshActiveBalances() {
func (b *BeaconState) initCaches() error {
var err error
- if b.activeValidatorsCache, err = lru.New[uint64, []uint64](5); err != nil {
+ if b.activeValidatorsCache, err = lru.New[uint64, []uint64]("beacon_active_validators_cache", 5); err != nil {
return err
}
- if b.shuffledSetsCache, err = lru.New[common.Hash, []uint64](5); err != nil {
+ if b.shuffledSetsCache, err = lru.New[common.Hash, []uint64]("beacon_shuffled_sets_cache", 5); err != nil {
return err
}
- if b.committeeCache, err = lru.New[[16]byte, []uint64](256); err != nil {
+ if b.committeeCache, err = lru.New[[16]byte, []uint64]("beacon_committee_cache", 256); err != nil {
return err
}
return nil
diff --git a/cmd/erigon-cl/core/state/cache_accessors.go b/cmd/erigon-cl/core/state/cache_accessors.go
index caf0ea8e872..de4e3c2dc18 100644
--- a/cmd/erigon-cl/core/state/cache_accessors.go
+++ b/cmd/erigon-cl/core/state/cache_accessors.go
@@ -159,6 +159,7 @@ func (b *BeaconState) GetBeaconCommitee(slot, committeeIndex uint64) ([]uint64,
var cacheKey [16]byte
binary.BigEndian.PutUint64(cacheKey[:], slot)
binary.BigEndian.PutUint64(cacheKey[8:], committeeIndex)
+
if cachedCommittee, ok := b.committeeCache.Get(cacheKey); ok {
return cachedCommittee, nil
}
diff --git a/cmd/erigon-cl/core/state/lru/lru.go b/cmd/erigon-cl/core/state/lru/lru.go
new file mode 100644
index 00000000000..ed7a1f8d2ed
--- /dev/null
+++ b/cmd/erigon-cl/core/state/lru/lru.go
@@ -0,0 +1,33 @@
+package lru
+
+import (
+ "fmt"
+
+ "github.com/VictoriaMetrics/metrics"
+ lru "github.com/hashicorp/golang-lru/v2"
+)
+
+// Cache is a wrapper around hashicorp lru but with metric for Get
+type Cache[K comparable, V any] struct {
+ *lru.Cache[K, V]
+
+ metricName string
+}
+
+func New[K comparable, V any](metricName string, size int) (*Cache[K, V], error) {
+ v, err := lru.NewWithEvict[K, V](size, nil)
+ if err != nil {
+ return nil, err
+ }
+ return &Cache[K, V]{Cache: v, metricName: metricName}, nil
+}
+
+func (c *Cache[K, V]) Get(k K) (V, bool) {
+ v, ok := c.Cache.Get(k)
+ if ok {
+ metrics.GetOrCreateCounter(fmt.Sprintf(`golang_lru_cache_hit{%s="%s"}`, "cache", c.metricName)).Inc()
+ } else {
+ metrics.GetOrCreateCounter(fmt.Sprintf(`golang_lru_cache_miss{%s="%s"}`, "cache", c.metricName)).Inc()
+ }
+ return v, ok
+}
diff --git a/cmd/erigon-cl/core/state/util.go b/cmd/erigon-cl/core/state/util.go
index f88a1df61c6..e37b456100d 100644
--- a/cmd/erigon-cl/core/state/util.go
+++ b/cmd/erigon-cl/core/state/util.go
@@ -3,16 +3,13 @@ package state
import (
"sort"
- lru "github.com/hashicorp/golang-lru/v2"
"github.com/ledgerwatch/erigon/cl/clparams"
"github.com/ledgerwatch/erigon/cl/cltypes"
"github.com/ledgerwatch/erigon/cl/utils"
+ "github.com/ledgerwatch/erigon/cmd/erigon-cl/core/state/lru"
)
func copyLRU[K comparable, V any](dst *lru.Cache[K, V], src *lru.Cache[K, V]) *lru.Cache[K, V] {
- if dst == nil {
- dst = new(lru.Cache[K, V])
- }
dst.Purge()
for _, key := range src.Keys() {
val, has := src.Get(key)
diff --git a/cmd/erigon-cl/core/transition/process_attestations.go b/cmd/erigon-cl/core/transition/process_attestations.go
index 8cd27e13c11..97f0cbc76bf 100644
--- a/cmd/erigon-cl/core/transition/process_attestations.go
+++ b/cmd/erigon-cl/core/transition/process_attestations.go
@@ -8,21 +8,25 @@ import (
"github.com/ledgerwatch/erigon/cl/cltypes"
"github.com/ledgerwatch/erigon/cl/utils"
"github.com/ledgerwatch/erigon/cmd/erigon-cl/core/state"
+ "github.com/ledgerwatch/erigon/metrics/methelp"
"golang.org/x/exp/slices"
)
func ProcessAttestations(s *state.BeaconState, attestations []*cltypes.Attestation, fullValidation bool) error {
var err error
attestingIndiciesSet := make([][]uint64, len(attestations))
-
+ h := methelp.NewHistTimer("beacon_process_attestations")
baseRewardPerIncrement := s.BaseRewardPerIncrement()
+ c := h.Tag("attestation_step", "process")
for i, attestation := range attestations {
if attestingIndiciesSet[i], err = processAttestation(s, attestation, baseRewardPerIncrement); err != nil {
return err
}
}
+ c.PutSince()
if fullValidation {
+ c = h.Tag("attestation_step", "validate")
valid, err := verifyAttestations(s, attestations, attestingIndiciesSet)
if err != nil {
return err
@@ -30,6 +34,7 @@ func ProcessAttestations(s *state.BeaconState, attestations []*cltypes.Attestati
if !valid {
return errors.New("ProcessAttestation: wrong bls data")
}
+ c.PutSince()
}
return nil
diff --git a/metrics/exp/exp.go b/metrics/exp/exp.go
index 76e6ddc76c5..e4e5dbc0c3f 100644
--- a/metrics/exp/exp.go
+++ b/metrics/exp/exp.go
@@ -9,7 +9,7 @@ import (
metrics2 "github.com/VictoriaMetrics/metrics"
"github.com/ledgerwatch/log/v3"
"github.com/prometheus/client_golang/prometheus"
- "github.com/prometheus/client_golang/prometheus/promhttp"
+ "github.com/prometheus/common/expfmt"
)
// Setup starts a dedicated metrics server at the given address.
@@ -17,13 +17,21 @@ import (
func Setup(address string) {
http.HandleFunc("/debug/metrics/prometheus", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
- metrics2.WritePrometheus(w, true)
+ metrics2.WritePrometheus(w, false)
+ contentType := expfmt.Negotiate(r.Header)
+ enc := expfmt.NewEncoder(w, contentType)
+ mf, err := prometheus.DefaultGatherer.Gather()
+ if err != nil {
+ return
+ }
+ for _, m := range mf {
+ enc.Encode(m)
+ }
})
//m.Handle("/debug/metrics", ExpHandler(metrics.DefaultRegistry))
- http.Handle("/debug/metrics/prometheus2", promhttp.HandlerFor(prometheus.DefaultGatherer, promhttp.HandlerOpts{}))
+ //http.Handle("/debug/metrics/prometheus2", promhttp.HandlerFor(prometheus.DefaultGatherer, promhttp.HandlerOpts{}))
log.Info("Starting metrics server", "addr",
fmt.Sprintf("http://%s/debug/metrics/prometheus", address),
- fmt.Sprintf("http://%s/debug/metrics/prometheus2", address),
)
go func() {
if err := http.ListenAndServe(address, nil); err != nil { // nolint:gosec
From d5a42a7cec5dec12b8d04deaeb1b7f5777a51f40 Mon Sep 17 00:00:00 2001
From: a
Date: Wed, 10 May 2023 11:35:45 -0500
Subject: [PATCH 29/34] metric
---
cmd/erigon-cl/core/transition/block_transition.go | 5 ++++-
cmd/erigon-cl/core/transition/process_attestations.go | 11 +++++++++++
2 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/cmd/erigon-cl/core/transition/block_transition.go b/cmd/erigon-cl/core/transition/block_transition.go
index 69b9317aa11..4616c2fa81a 100644
--- a/cmd/erigon-cl/core/transition/block_transition.go
+++ b/cmd/erigon-cl/core/transition/block_transition.go
@@ -106,7 +106,10 @@ func processOperations(state *state.BeaconState, blockBody *cltypes.BeaconBody,
c.PutSince()
// Process each attestations
- c = h.Tag("operation", "attestations")
+ c = h.Tag("operation", "attestations", "validation", "false")
+ if fullValidation {
+ c = h.Tag("operation", "attestations", "validation", "true")
+ }
if err := ProcessAttestations(state, blockBody.Attestations, fullValidation); err != nil {
return fmt.Errorf("ProcessAttestation: %s", err)
}
diff --git a/cmd/erigon-cl/core/transition/process_attestations.go b/cmd/erigon-cl/core/transition/process_attestations.go
index 97f0cbc76bf..294c9802750 100644
--- a/cmd/erigon-cl/core/transition/process_attestations.go
+++ b/cmd/erigon-cl/core/transition/process_attestations.go
@@ -46,19 +46,27 @@ func processAttestationPostAltair(s *state.BeaconState, attestation *cltypes.Att
stateSlot := s.Slot()
beaconConfig := s.BeaconConfig()
+ h := methelp.NewHistTimer("beacon_process_attestation_post_altair")
+
+ c := h.Tag("step", "get_participation_flag")
participationFlagsIndicies, err := s.GetAttestationParticipationFlagIndicies(attestation.Data, stateSlot-data.Slot)
if err != nil {
return nil, err
}
+ c.PutSince()
+ c = h.Tag("step", "get_attesting_indices")
attestingIndicies, err := s.GetAttestingIndicies(attestation.Data, attestation.AggregationBits, true)
if err != nil {
return nil, err
}
+ c.PutSince()
+
var proposerRewardNumerator uint64
isCurrentEpoch := data.Target.Epoch == currentEpoch
+ c = h.Tag("step", "update_attestation")
for _, attesterIndex := range attestingIndicies {
val, err := s.ValidatorEffectiveBalance(int(attesterIndex))
if err != nil {
@@ -75,11 +83,14 @@ func processAttestationPostAltair(s *state.BeaconState, attestation *cltypes.Att
proposerRewardNumerator += baseReward * weight
}
}
+ c.PutSince()
// Reward proposer
+ c = h.Tag("step", "get_proposer_index")
proposer, err := s.GetBeaconProposerIndex()
if err != nil {
return nil, err
}
+ c.PutSince()
proposerRewardDenominator := (beaconConfig.WeightDenominator - beaconConfig.ProposerWeight) * beaconConfig.WeightDenominator / beaconConfig.ProposerWeight
reward := proposerRewardNumerator / proposerRewardDenominator
return attestingIndicies, state.IncreaseBalance(s.BeaconState, proposer, reward)
From 511ea2310cc40bc24a59250e9055c1df5f42da1e Mon Sep 17 00:00:00 2001
From: a
Date: Wed, 10 May 2023 14:11:08 -0500
Subject: [PATCH 30/34] better comment
---
cl/cltypes/solid/uint64slice_byte.go | 3 +++
1 file changed, 3 insertions(+)
diff --git a/cl/cltypes/solid/uint64slice_byte.go b/cl/cltypes/solid/uint64slice_byte.go
index 37cf7cea6a6..4a066a784e7 100644
--- a/cl/cltypes/solid/uint64slice_byte.go
+++ b/cl/cltypes/solid/uint64slice_byte.go
@@ -8,9 +8,12 @@ import (
)
type byteBasedUint64Slice struct {
+ // the bytes that back the slice
u []byte
+ // length of slice
l int // len
+ // cap of slize
c int // cap
hashBuf
From 5d656696189e78ae3522e567766321a9ff3dddec Mon Sep 17 00:00:00 2001
From: a
Date: Wed, 10 May 2023 14:16:30 -0500
Subject: [PATCH 31/34] bitlist
---
cl/cltypes/solid/bitlist.go | 3 +++
1 file changed, 3 insertions(+)
diff --git a/cl/cltypes/solid/bitlist.go b/cl/cltypes/solid/bitlist.go
index b0cdcdbb025..6c1c588c783 100644
--- a/cl/cltypes/solid/bitlist.go
+++ b/cl/cltypes/solid/bitlist.go
@@ -6,8 +6,11 @@ import (
)
type bitlist struct {
+ // the underlying bytes that store the data
u []byte
+ // cap, or max size of the bitlist
c int
+ // current length of the bitlist
l int
hashBuf
From 1144731078b394e930b9e8c2c78f870e31796748 Mon Sep 17 00:00:00 2001
From: a
Date: Thu, 11 May 2023 07:20:18 -0500
Subject: [PATCH 32/34] instrumentation
---
cmd/sentinel/sentinel/sentinel.go | 2 --
cmd/sentinel/sentinel/service/start.go | 4 +++-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/cmd/sentinel/sentinel/sentinel.go b/cmd/sentinel/sentinel/sentinel.go
index e79f29a6cd3..d121c0c7b00 100644
--- a/cmd/sentinel/sentinel/sentinel.go
+++ b/cmd/sentinel/sentinel/sentinel.go
@@ -39,7 +39,6 @@ import (
"github.com/libp2p/go-libp2p/core/peer"
rcmgr "github.com/libp2p/go-libp2p/p2p/host/resource-manager"
rcmgrObs "github.com/libp2p/go-libp2p/p2p/host/resource-manager/obs"
- "github.com/prometheus/client_golang/prometheus"
)
const (
@@ -263,7 +262,6 @@ func New(
return nil, err
}
if s.metrics {
- rcmgrObs.MustRegisterWith(prometheus.DefaultRegisterer)
str, err := rcmgrObs.NewStatsTraceReporter()
if err != nil {
diff --git a/cmd/sentinel/sentinel/service/start.go b/cmd/sentinel/sentinel/service/start.go
index f306fb73c7c..9bd02608462 100644
--- a/cmd/sentinel/sentinel/service/start.go
+++ b/cmd/sentinel/sentinel/service/start.go
@@ -11,6 +11,8 @@ import (
"github.com/ledgerwatch/erigon/cl/cltypes"
"github.com/ledgerwatch/erigon/cmd/sentinel/sentinel"
"github.com/ledgerwatch/log/v3"
+ rcmgrObs "github.com/libp2p/go-libp2p/p2p/host/resource-manager/obs"
+ "github.com/prometheus/client_golang/prometheus"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/insecure"
@@ -61,11 +63,11 @@ func createSentinel(cfg *sentinel.SentinelConfig, db kv.RoDB) (*sentinel.Sentine
func StartSentinelService(cfg *sentinel.SentinelConfig, db kv.RoDB, srvCfg *ServerConfig, creds credentials.TransportCredentials, initialStatus *cltypes.Status) (sentinelrpc.SentinelClient, error) {
ctx := context.Background()
-
sent, err := createSentinel(cfg, db)
if err != nil {
return nil, err
}
+ rcmgrObs.MustRegisterWith(prometheus.DefaultRegisterer)
log.Info("[Sentinel] Sentinel started", "enr", sent.String())
if initialStatus != nil {
sent.SetStatus(initialStatus)
From a94aa1a5f75456cda89a300467e501dd57401de4 Mon Sep 17 00:00:00 2001
From: a
Date: Thu, 11 May 2023 07:29:31 -0500
Subject: [PATCH 33/34] merge
---
cmd/erigon-cl/core/state/ssz.go | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/cmd/erigon-cl/core/state/ssz.go b/cmd/erigon-cl/core/state/ssz.go
index f7843eb690d..694547eb270 100644
--- a/cmd/erigon-cl/core/state/ssz.go
+++ b/cmd/erigon-cl/core/state/ssz.go
@@ -1,13 +1,10 @@
package state
import (
-<<<<<<< HEAD
"github.com/VictoriaMetrics/metrics"
- "github.com/ledgerwatch/erigon/cl/cltypes/clonable"
"github.com/ledgerwatch/erigon/metrics/methelp"
-=======
+
"github.com/ledgerwatch/erigon-lib/types/clonable"
->>>>>>> devel
)
func (b *BeaconState) EncodeSSZ(buf []byte) ([]byte, error) {
From c3b2241b43bb5fb8216b723df62bb358108535df Mon Sep 17 00:00:00 2001
From: a
Date: Thu, 11 May 2023 07:43:40 -0500
Subject: [PATCH 34/34] use timer
---
cmd/erigon-cl/core/state/ssz.go | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/cmd/erigon-cl/core/state/ssz.go b/cmd/erigon-cl/core/state/ssz.go
index 694547eb270..521046c48f1 100644
--- a/cmd/erigon-cl/core/state/ssz.go
+++ b/cmd/erigon-cl/core/state/ssz.go
@@ -1,7 +1,6 @@
package state
import (
- "github.com/VictoriaMetrics/metrics"
"github.com/ledgerwatch/erigon/metrics/methelp"
"github.com/ledgerwatch/erigon-lib/types/clonable"
@@ -14,7 +13,7 @@ func (b *BeaconState) EncodeSSZ(buf []byte) ([]byte, error) {
return nil, err
}
h.PutSince()
- sz := metrics.NewHistogram("encode_ssz_beacon_state_size")
+ sz := methelp.NewHistTimer("encode_ssz_beacon_state_size")
sz.Update(float64(len(bts)))
return bts, err
}