Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Caplin: remove merkle tree disk-based caching #13671

Merged
merged 33 commits into from
Feb 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cl/beacon/synced_data/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ type SyncedData interface {
OnHeadState(newState *state.CachingBeaconState) error
UnsetHeadState()
ViewHeadState(fn ViewHeadStateFn) error
ViewPreviousHeadState(fn ViewHeadStateFn) error
Syncing() bool
HeadSlot() uint64
HeadRoot() common.Hash
Expand Down
38 changes: 38 additions & 0 deletions cl/beacon/synced_data/mock_services/synced_data_mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

39 changes: 34 additions & 5 deletions cl/beacon/synced_data/synced_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ import (
"github.com/erigontech/erigon/cl/phase1/core/state"
)

var ErrNotSynced = errors.New("not synced")
var (
ErrNotSynced = errors.New("not synced")
ErrPreviousStateNotAvailable = errors.New("previous state not available")
)

var _ SyncedData = (*SyncedDataManager)(nil)

Expand All @@ -43,11 +46,11 @@ type SyncedDataManager struct {
headRoot atomic.Value
headSlot atomic.Uint64

headState *state.CachingBeaconState
headState *state.CachingBeaconState
previousHeadState *state.CachingBeaconState

accessLock sync.RWMutex // lock used for accessing atomic methods

mu sync.RWMutex
mu sync.RWMutex
}

func NewSyncedDataManager(cfg *clparams.BeaconChainConfig, enabled bool) *SyncedDataManager {
Expand All @@ -57,6 +60,7 @@ func NewSyncedDataManager(cfg *clparams.BeaconChainConfig, enabled bool) *Synced
}
}

// OnHeadState updates the current head state and tracks the previous state.
func (s *SyncedDataManager) OnHeadState(newState *state.CachingBeaconState) (err error) {
if !s.enabled {
return
Expand All @@ -67,8 +71,21 @@ func (s *SyncedDataManager) OnHeadState(newState *state.CachingBeaconState) (err
s.accessLock.Lock()
defer s.accessLock.Unlock()

// Save current state as previous state, if available.
if s.headState != nil {
if s.previousHeadState != nil {
err = s.headState.CopyInto(s.previousHeadState)
} else {
s.previousHeadState, err = s.headState.Copy()
}
if err != nil {
return err
}
}

var blkRoot common.Hash

// Update headState with the new state.
if s.headState == nil {
s.headState, err = newState.Copy()
} else {
Expand All @@ -83,9 +100,10 @@ func (s *SyncedDataManager) OnHeadState(newState *state.CachingBeaconState) (err
}
s.headSlot.Store(newState.Slot())
s.headRoot.Store(blkRoot)
return err
return nil
}

// ViewHeadState allows safe, read-only access to the current head state.
func (s *SyncedDataManager) ViewHeadState(fn ViewHeadStateFn) error {
_, synced := s.headRoot.Load().(common.Hash)
if !s.enabled || !synced {
Expand All @@ -112,6 +130,16 @@ func (s *SyncedDataManager) ViewHeadState(fn ViewHeadStateFn) error {
return nil
}

// ViewPreviousHeadState allows safe, read-only access to the previous head state.
func (s *SyncedDataManager) ViewPreviousHeadState(fn ViewHeadStateFn) error {
s.mu.RLock()
defer s.mu.RUnlock()
if s.previousHeadState == nil {
return ErrPreviousStateNotAvailable
}
return fn(s.previousHeadState)
}

func (s *SyncedDataManager) Syncing() bool {
_, synced := s.headRoot.Load().(common.Hash)
return !synced
Expand Down Expand Up @@ -147,6 +175,7 @@ func (s *SyncedDataManager) UnsetHeadState() {
s.headRoot = atomic.Value{}
s.headSlot.Store(uint64(0))
s.headState = nil
s.previousHeadState = nil
}

func (s *SyncedDataManager) ValidatorPublicKeyByIndex(index int) (common.Bytes48, error) {
Expand Down
5 changes: 2 additions & 3 deletions cl/clparams/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,8 @@ const (

var (
MainnetBootstrapNodes = []string{
// Teku team's bootnode
"enr:-KG4QOtcP9X1FbIMOe17QNMKqDxCpm14jcX5tiOE4_TyMrFqbmhPZHK_ZPG2Gxb1GE2xdtodOfx9-cgvNtxnRyHEmC0ghGV0aDKQ9aX9QgAAAAD__________4JpZIJ2NIJpcIQDE8KdiXNlY3AyNTZrMaEDhpehBDbZjM_L9ek699Y7vhUJ-eAdMyQW_Fil522Y0fODdGNwgiMog3VkcIIjKA",
"enr:-KG4QL-eqFoHy0cI31THvtZjpYUu_Jdw_MO7skQRJxY1g5HTN1A0epPCU6vi0gLGUgrzpU-ygeMSS8ewVxDpKfYmxMMGhGV0aDKQtTA_KgAAAAD__________4JpZIJ2NIJpcIQ2_DUbiXNlY3AyNTZrMaED8GJ2vzUqgL6-KD1xalo1CsmY4X1HaDnyl6Y_WayCo9GDdGNwgiMog3VkcIIjKA",
"enr:-KG4QNTx85fjxABbSq_Rta9wy56nQ1fHK0PewJbGjLm1M4bMGx5-3Qq4ZX2-iFJ0pys_O90sVXNNOxp2E7afBsGsBrgDhGV0aDKQu6TalgMAAAD__________4JpZIJ2NIJpcIQEnfA2iXNlY3AyNTZrMaECGXWQ-rQ2KZKRH1aOW4IlPDBkY4XDphxg9pxKytFCkayDdGNwgiMog3VkcIIjKA",
"enr:-KG4QF4B5WrlFcRhUU6dZETwY5ZzAXnA0vGC__L1Kdw602nDZwXSTs5RFXFIFUnbQJmhNGVU6OIX7KVrCSTODsz1tK4DhGV0aDKQu6TalgMAAAD__________4JpZIJ2NIJpcIQExNYEiXNlY3AyNTZrMaECQmM9vp7KhaXhI-nqL_R0ovULLCFSFTa9CPPSdb1zPX6DdGNwgiMog3VkcIIjKA",
// Prylab team's bootnodes
"enr:-Ku4QImhMc1z8yCiNJ1TyUxdcfNucje3BGwEHzodEZUan8PherEo4sF7pPHPSIB1NNuSg5fZy7qFsjmUKs2ea1Whi0EBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpD1pf1CAAAAAP__________gmlkgnY0gmlwhBLf22SJc2VjcDI1NmsxoQOVphkDqal4QzPMksc5wnpuC3gvSC8AfbFOnZY_On34wIN1ZHCCIyg",
"enr:-Ku4QP2xDnEtUXIjzJ_DhlCRN9SN99RYQPJL92TMlSv7U5C1YnYLjwOQHgZIUXw6c-BvRg2Yc2QsZxxoS_pPRVe0yK8Bh2F0dG5ldHOIAAAAAAAAAACEZXRoMpD1pf1CAAAAAP__________gmlkgnY0gmlwhBLf22SJc2VjcDI1NmsxoQMeFF5GrS7UZpAH2Ly84aLK-TyvH-dRo0JM1i8yygH50YN1ZHCCJxA",
Expand Down
22 changes: 0 additions & 22 deletions cl/cltypes/solid/hash_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package solid

import (
"encoding/json"
"io"

libcommon "github.com/erigontech/erigon-lib/common"
"github.com/erigontech/erigon-lib/common/length"
Expand Down Expand Up @@ -190,24 +189,3 @@ func (h *hashList) Range(fn func(int, libcommon.Hash, int) bool) {
func (h *hashList) Pop() libcommon.Hash {
panic("didnt ask, dont need it, go fuck yourself")
}

func (h *hashList) ReadMerkleTree(r io.Reader) error {
if h.MerkleTree == nil {
h.MerkleTree = &merkle_tree.MerkleTree{}
h.MerkleTree.Initialize(h.l, merkle_tree.OptimalMaxTreeCacheDepth, func(idx int, out []byte) {
copy(out, h.u[idx*length.Hash:(idx+1)*length.Hash])
}, /*limit=*/ nil)
}
return h.MerkleTree.ReadMerkleTree(r)
}

func (h *hashList) WriteMerkleTree(w io.Writer) error {
if h.MerkleTree == nil {
cap := uint64(h.c)
h.MerkleTree = &merkle_tree.MerkleTree{}
h.MerkleTree.Initialize(h.l, merkle_tree.OptimalMaxTreeCacheDepth, func(idx int, out []byte) {
copy(out, h.u[idx*length.Hash:(idx+1)*length.Hash])
}, /*limit=*/ &cap)
}
return h.MerkleTree.WriteMerkleTree(w)
}
9 changes: 0 additions & 9 deletions cl/cltypes/solid/hash_vector.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package solid

import (
"encoding/json"
"io"

libcommon "github.com/erigontech/erigon-lib/common"
"github.com/erigontech/erigon-lib/common/length"
Expand Down Expand Up @@ -118,11 +117,3 @@ func (h *hashVector) Range(fn func(int, libcommon.Hash, int) bool) {
func (h *hashVector) Pop() libcommon.Hash {
panic("didnt ask, dont need it, go fuck yourself")
}

func (h *hashVector) ReadMerkleTree(r io.Reader) error {
return h.u.ReadMerkleTree(r)
}

func (h *hashVector) WriteMerkleTree(w io.Writer) error {
return h.u.WriteMerkleTree(w)
}
9 changes: 0 additions & 9 deletions cl/cltypes/solid/uint64_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package solid

import (
"encoding/json"
"io"

"github.com/erigontech/erigon-lib/types/clonable"
)
Expand Down Expand Up @@ -119,14 +118,6 @@ func (arr *uint64ListSSZ) Append(v uint64) {
arr.u.Append(v)
}

func (arr *uint64ListSSZ) ReadMerkleTree(r io.Reader) error {
return arr.u.ReadMerkleTree(r)
}

func (arr *uint64ListSSZ) WriteMerkleTree(w io.Writer) error {
return arr.u.WriteMerkleTree(w)
}

// Check if it is sorted and check if there are duplicates. O(N) complexity.
func IsUint64SortedSet(set IterableSSZ[uint64]) bool {
for i := 0; i < set.Length()-1; i++ {
Expand Down
9 changes: 0 additions & 9 deletions cl/cltypes/solid/uint64_vector.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package solid

import (
"encoding/json"
"io"

"github.com/erigontech/erigon-lib/types/clonable"
)
Expand Down Expand Up @@ -110,11 +109,3 @@ func (arr *uint64VectorSSZ) Pop() uint64 {
func (arr *uint64VectorSSZ) Append(uint64) {
panic("not implemented")
}

func (arr *uint64VectorSSZ) ReadMerkleTree(r io.Reader) error {
return arr.u.ReadMerkleTree(r)
}

func (arr *uint64VectorSSZ) WriteMerkleTree(w io.Writer) error {
return arr.u.WriteMerkleTree(w)
}
22 changes: 0 additions & 22 deletions cl/cltypes/solid/uint64slice_byte.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ package solid
import (
"encoding/binary"
"encoding/json"
"io"
"strconv"

"github.com/erigontech/erigon-lib/common/length"
Expand Down Expand Up @@ -229,24 +228,3 @@ func (arr *byteBasedUint64Slice) DecodeSSZ(buf []byte, _ int) error {
func (arr *byteBasedUint64Slice) EncodingSizeSSZ() int {
return arr.l * 8
}

func (arr *byteBasedUint64Slice) ReadMerkleTree(r io.Reader) error {
if arr.MerkleTree == nil {
arr.MerkleTree = &merkle_tree.MerkleTree{}
arr.MerkleTree.Initialize((arr.l+3)/4, merkle_tree.OptimalMaxTreeCacheDepth, func(idx int, out []byte) {
copy(out, arr.u[idx*length.Hash:])
}, nil)
}
return arr.MerkleTree.ReadMerkleTree(r)
}

func (arr *byteBasedUint64Slice) WriteMerkleTree(w io.Writer) error {
if arr.MerkleTree == nil {
arr.MerkleTree = &merkle_tree.MerkleTree{}
cap := uint64((arr.c*8 + length.Hash - 1) / length.Hash)
arr.MerkleTree.Initialize((arr.l+3)/4, merkle_tree.OptimalMaxTreeCacheDepth, func(idx int, out []byte) {
copy(out, arr.u[idx*length.Hash:])
}, &cap)
}
return arr.MerkleTree.WriteMerkleTree(w)
}
46 changes: 11 additions & 35 deletions cl/cltypes/solid/validator_set.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package solid

import (
"encoding/json"
"io"

libcommon "github.com/erigontech/erigon-lib/common"
"github.com/erigontech/erigon-lib/types/clonable"
Expand Down Expand Up @@ -141,14 +140,23 @@ func (v *ValidatorSet) CopyTo(t *ValidatorSet) {
t.MerkleTree = &merkle_tree.MerkleTree{}
}
v.MerkleTree.CopyInto(t.MerkleTree)

hashBuffer := make([]byte, 8*32)
t.MerkleTree.SetComputeLeafFn(func(idx int, out []byte) {
copy(out, t.buffer[idx*validatorSize:])
validator := t.Get(idx)
if err := validator.CopyHashBufferTo(hashBuffer); err != nil {
panic(err)
}
hashBuffer = hashBuffer[:(8 * 32)]
if err := merkle_tree.MerkleRootFromFlatLeaves(hashBuffer, out); err != nil {
panic(err)
}
})
} else {
t.MerkleTree = nil
}
// skip copying (unsupported for phase0)
t.phase0Data = make([]Phase0Data, t.l)
t.phase0Data = make([]Phase0Data, v.l)
copy(t.buffer, v.buffer)
copy(t.attesterBits, v.attesterBits)
t.attesterBits = t.attesterBits[:v.l]
Expand Down Expand Up @@ -377,35 +385,3 @@ func (v *ValidatorSet) UnmarshalJSON(data []byte) error {
}
return nil
}

func (v *ValidatorSet) ReadMerkleTree(r io.Reader) error {
if v.MerkleTree == nil {
v.MerkleTree = &merkle_tree.MerkleTree{}
hashBuffer := make([]byte, 8*32)
v.MerkleTree.Initialize(v.l, merkle_tree.OptimalMaxTreeCacheDepth, func(idx int, out []byte) {
validator := v.Get(idx)
if err := validator.CopyHashBufferTo(hashBuffer); err != nil {
panic(err)
}
hashBuffer = hashBuffer[:(8 * 32)]
if err := merkle_tree.MerkleRootFromFlatLeaves(hashBuffer, out); err != nil {
panic(err)
}
}, nil)
}
return v.MerkleTree.ReadMerkleTree(r)
}

func (arr *ValidatorSet) WriteMerkleTree(w io.Writer) error {
if arr.MerkleTree == nil {
arr.MerkleTree = &merkle_tree.MerkleTree{}
cap := uint64(arr.c)
arr.MerkleTree.Initialize(arr.l, merkle_tree.OptimalMaxTreeCacheDepth, func(idx int, out []byte) {
validator := arr.Get(idx)
if err := validator.CopyHashBufferTo(out); err != nil {
panic(err)
}
}, &cap)
}
return arr.MerkleTree.WriteMerkleTree(w)
}
Loading
Loading