Compare commits

...

17 Commits

Author SHA1 Message Date
satushh
4ae247e0b9 Merge branch 'develop' into eas-metric-2 2025-12-09 16:49:44 +00:00
Snezhkko
5a2e51b894 fix(rpc): incorrect constructor return type (#16084)
The constructor `NewStateRootNotFoundError` incorrectly returned
`StateNotFoundError`. This prevented handlers that rely on
errors.As(err, *lookup.StateRootNotFoundError) from matching and mapping
the error to HTTP 404. The function now returns
StateRootNotFoundError and constructs that type, restoring the intended
behavior for “state root not found” cases.

---------

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
2025-12-09 13:56:00 +00:00
Potuz
d20ec4c7a1 Track the dependent root of the latest finalized checkpoint (#16103)
This PR adds the dependent root of the latest finalized checkpoint to
forkchoice since this node will be typically pruned upon finalization.
2025-12-08 16:16:32 +00:00
satushh
ce55a55f30 remove some unwanted logs 2025-12-01 12:07:06 +00:00
satushh
bb8374ae31 Merge branch 'develop' into eas-metric-2 2025-12-01 12:04:35 +00:00
satushh
391c20f2ba fmt 2025-12-01 12:04:02 +00:00
satushh
c0c825d69e remove unwanted GetCustodyInfo 2025-12-01 11:49:33 +00:00
satushh
af736f6260 Merge branch 'develop' into eas-metric-2 2025-11-28 18:42:38 +00:00
satushh
b4dadc35bf naming and description changes 2025-11-28 18:42:02 +00:00
satushh
e5ab8495b0 remove common package and keep metrics in respective packages 2025-11-28 18:39:54 +00:00
satushh
2cfce7265e remove unwanted refreshCustodyMetrics and update db metric during startup 2025-11-28 13:50:31 +00:00
satushh
d4f5dc9823 tidy up 2025-11-27 18:42:23 +00:00
satushh
72c75bce83 changelog 2025-11-27 18:10:39 +00:00
satushh
37764704fe format 2025-11-27 18:09:06 +00:00
satushh
730f31d346 bazel run //:gazelle -- fix 2025-11-27 18:07:17 +00:00
satushh
170bbc166f Merge branch 'develop' into eas-metric-2 2025-11-27 18:02:35 +00:00
satushh
8167e2a22c eas metric + GetCustodyInfo for restarts 2025-11-27 17:59:19 +00:00
17 changed files with 86 additions and 7 deletions

View File

@@ -58,6 +58,7 @@ go_library(
"//beacon-chain/db:go_default_library",
"//beacon-chain/db/filesystem:go_default_library",
"//beacon-chain/db/filters:go_default_library",
"//beacon-chain/db/kv:go_default_library",
"//beacon-chain/execution:go_default_library",
"//beacon-chain/forkchoice:go_default_library",
"//beacon-chain/forkchoice/doubly-linked-tree:go_default_library",

View File

@@ -19,6 +19,7 @@ import (
"github.com/OffchainLabs/prysm/v7/beacon-chain/core/transition"
"github.com/OffchainLabs/prysm/v7/beacon-chain/db"
"github.com/OffchainLabs/prysm/v7/beacon-chain/db/filesystem"
"github.com/OffchainLabs/prysm/v7/beacon-chain/db/kv"
"github.com/OffchainLabs/prysm/v7/beacon-chain/execution"
f "github.com/OffchainLabs/prysm/v7/beacon-chain/forkchoice"
lightClient "github.com/OffchainLabs/prysm/v7/beacon-chain/light-client"
@@ -300,6 +301,8 @@ func (s *Service) StartFromSavedState(saved state.BeaconState) error {
return errors.Wrap(err, "could not get and save custody group count")
}
kv.EarliestAvailableSlotMetric.Set(float64(earliestAvailableSlot))
if _, _, err := s.cfg.P2P.UpdateCustodyInfo(earliestAvailableSlot, custodySubnetCount); err != nil {
return errors.Wrap(err, "update custody info")
}

View File

View File

@@ -19,6 +19,7 @@ go_library(
"kv.go",
"lightclient.go",
"log.go",
"metrics.go",
"migration.go",
"migration_archived_index.go",
"migration_block_slot_index.go",

View File

@@ -70,6 +70,8 @@ func (s *Store) UpdateCustodyInfo(ctx context.Context, earliestAvailableSlot pri
"groupCount": storedGroupCount,
}).Debug("Custody info")
EarliestAvailableSlotMetric.Set(float64(storedEarliestAvailableSlot))
return storedEarliestAvailableSlot, storedGroupCount, nil
}
@@ -143,6 +145,8 @@ func (s *Store) UpdateEarliestAvailableSlot(ctx context.Context, earliestAvailab
log.WithField("earliestAvailableSlot", storedEarliestAvailableSlot).Debug("Updated earliest available slot")
EarliestAvailableSlotMetric.Set(float64(storedEarliestAvailableSlot))
return nil
}

View File

@@ -0,0 +1,14 @@
package kv
import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
)
var (
// EarliestAvailableSlotMetric tracks the earliest available slot in the database
EarliestAvailableSlotMetric = promauto.NewGauge(prometheus.GaugeOpts{
Name: "earliest_available_slot_db",
Help: "The earliest available slot tracked by the database",
})
)

View File

@@ -642,8 +642,12 @@ func (f *ForkChoice) DependentRootForEpoch(root [32]byte, epoch primitives.Epoch
if !ok || node == nil {
return [32]byte{}, ErrNilNode
}
if slots.ToEpoch(node.slot) >= epoch && node.parent != nil {
node = node.parent
if slots.ToEpoch(node.slot) >= epoch {
if node.parent != nil {
node = node.parent
} else {
return f.store.finalizedDependentRoot, nil
}
}
return node.root, nil
}

View File

@@ -212,6 +212,9 @@ func (s *Store) prune(ctx context.Context) error {
return nil
}
// Save the new finalized dependent root because it will be pruned
s.finalizedDependentRoot = finalizedNode.parent.root
// Prune nodeByRoot starting from root
if err := s.pruneFinalizedNodeByRootMap(ctx, s.treeRootNode, finalizedNode); err != nil {
return err

View File

@@ -465,6 +465,7 @@ func TestStore_TargetRootForEpoch(t *testing.T) {
ctx := t.Context()
f := setup(1, 1)
// Insert a block in slot 32
state, blk, err := prepareForkchoiceState(ctx, params.BeaconConfig().SlotsPerEpoch, [32]byte{'a'}, params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1)
require.NoError(t, err)
require.NoError(t, f.InsertNode(ctx, state, blk))
@@ -475,6 +476,7 @@ func TestStore_TargetRootForEpoch(t *testing.T) {
require.NoError(t, err)
require.Equal(t, dependent, [32]byte{})
// Insert a block in slot 33
state, blk1, err := prepareForkchoiceState(ctx, params.BeaconConfig().SlotsPerEpoch+1, [32]byte{'b'}, blk.Root(), params.BeaconConfig().ZeroHash, 1, 1)
require.NoError(t, err)
require.NoError(t, f.InsertNode(ctx, state, blk1))
@@ -488,7 +490,7 @@ func TestStore_TargetRootForEpoch(t *testing.T) {
require.NoError(t, err)
require.Equal(t, dependent, [32]byte{})
// Insert a block for the next epoch (missed slot 0)
// Insert a block for the next epoch (missed slot 0), slot 65
state, blk2, err := prepareForkchoiceState(ctx, 2*params.BeaconConfig().SlotsPerEpoch+1, [32]byte{'c'}, blk1.Root(), params.BeaconConfig().ZeroHash, 1, 1)
require.NoError(t, err)
@@ -509,6 +511,7 @@ func TestStore_TargetRootForEpoch(t *testing.T) {
require.NoError(t, err)
require.Equal(t, dependent, blk1.Root())
// Insert a block at slot 66
state, blk3, err := prepareForkchoiceState(ctx, 2*params.BeaconConfig().SlotsPerEpoch+2, [32]byte{'d'}, blk2.Root(), params.BeaconConfig().ZeroHash, 1, 1)
require.NoError(t, err)
require.NoError(t, f.InsertNode(ctx, state, blk3))
@@ -533,8 +536,11 @@ func TestStore_TargetRootForEpoch(t *testing.T) {
dependent, err = f.DependentRoot(1)
require.NoError(t, err)
require.Equal(t, [32]byte{}, dependent)
dependent, err = f.DependentRoot(2)
require.NoError(t, err)
require.Equal(t, blk1.Root(), dependent)
// Insert a block for next epoch (slot 0 present)
// Insert a block for the next epoch, slot 96 (descends from finalized at slot 33)
state, blk4, err := prepareForkchoiceState(ctx, 3*params.BeaconConfig().SlotsPerEpoch, [32]byte{'e'}, blk1.Root(), params.BeaconConfig().ZeroHash, 1, 1)
require.NoError(t, err)
require.NoError(t, f.InsertNode(ctx, state, blk4))
@@ -551,6 +557,7 @@ func TestStore_TargetRootForEpoch(t *testing.T) {
require.NoError(t, err)
require.Equal(t, dependent, blk1.Root())
// Insert a block at slot 97
state, blk5, err := prepareForkchoiceState(ctx, 3*params.BeaconConfig().SlotsPerEpoch+1, [32]byte{'f'}, blk4.Root(), params.BeaconConfig().ZeroHash, 1, 1)
require.NoError(t, err)
require.NoError(t, f.InsertNode(ctx, state, blk5))
@@ -600,12 +607,16 @@ func TestStore_TargetRootForEpoch(t *testing.T) {
require.NoError(t, err)
require.Equal(t, target, blk1.Root())
// Prune finalization
// Prune finalization, finalize the block at slot 96
s.finalizedCheckpoint.Root = blk4.Root()
require.NoError(t, s.prune(ctx))
target, err = f.TargetRootForEpoch(blk4.Root(), 3)
require.NoError(t, err)
require.Equal(t, blk4.Root(), target)
// Dependent root for the finalized block should be the root of the pruned block at slot 33
dependent, err = f.DependentRootForEpoch(blk4.Root(), 3)
require.NoError(t, err)
require.Equal(t, blk1.Root(), dependent)
}
func TestStore_DependentRootForEpoch(t *testing.T) {

View File

@@ -31,6 +31,7 @@ type Store struct {
proposerBoostRoot [fieldparams.RootLength]byte // latest block root that was boosted after being received in a timely manner.
previousProposerBoostRoot [fieldparams.RootLength]byte // previous block root that was boosted after being received in a timely manner.
previousProposerBoostScore uint64 // previous proposer boosted root score.
finalizedDependentRoot [fieldparams.RootLength]byte // dependent root at finalized checkpoint.
committeeWeight uint64 // tracks the total active validator balance divided by the number of slots per Epoch.
treeRootNode *Node // the root node of the store tree.
headNode *Node // last head Node

View File

@@ -20,6 +20,7 @@ go_library(
"interfaces.go",
"log.go",
"message_id.go",
"metrics.go",
"monitoring.go",
"options.go",
"pubsub.go",

View File

@@ -22,6 +22,8 @@ func (s *Service) EarliestAvailableSlot(ctx context.Context) (primitives.Slot, e
return 0, errors.Wrap(err, "wait for custody info")
}
EarliestAvailableSlotMetric.Set(float64(custodyInfo.earliestAvailableSlot))
return custodyInfo.earliestAvailableSlot, nil
}
@@ -80,11 +82,15 @@ func (s *Service) UpdateCustodyInfo(earliestAvailableSlot primitives.Slot, custo
close(s.custodyInfoSet)
// Update P2P metric when initializing custody info
EarliestAvailableSlotMetric.Set(float64(earliestAvailableSlot))
return earliestAvailableSlot, custodyGroupCount, nil
}
inMemory := s.custodyInfo
if custodyGroupCount <= inMemory.groupCount {
EarliestAvailableSlotMetric.Set(float64(inMemory.earliestAvailableSlot))
return inMemory.earliestAvailableSlot, inMemory.groupCount, nil
}
@@ -97,6 +103,7 @@ func (s *Service) UpdateCustodyInfo(earliestAvailableSlot primitives.Slot, custo
if custodyGroupCount <= samplesPerSlot {
inMemory.groupCount = custodyGroupCount
EarliestAvailableSlotMetric.Set(float64(inMemory.earliestAvailableSlot))
return inMemory.earliestAvailableSlot, custodyGroupCount, nil
}
@@ -107,11 +114,15 @@ func (s *Service) UpdateCustodyInfo(earliestAvailableSlot primitives.Slot, custo
if earliestAvailableSlot < fuluForkSlot {
inMemory.groupCount = custodyGroupCount
EarliestAvailableSlotMetric.Set(float64(inMemory.earliestAvailableSlot))
return inMemory.earliestAvailableSlot, custodyGroupCount, nil
}
inMemory.earliestAvailableSlot = earliestAvailableSlot
inMemory.groupCount = custodyGroupCount
EarliestAvailableSlotMetric.Set(float64(earliestAvailableSlot))
return earliestAvailableSlot, custodyGroupCount, nil
}
@@ -133,6 +144,7 @@ func (s *Service) UpdateEarliestAvailableSlot(earliestAvailableSlot primitives.S
// Allow decrease (for backfill scenarios)
if earliestAvailableSlot < s.custodyInfo.earliestAvailableSlot {
s.custodyInfo.earliestAvailableSlot = earliestAvailableSlot
EarliestAvailableSlotMetric.Set(float64(earliestAvailableSlot))
return nil
}
@@ -163,6 +175,7 @@ func (s *Service) UpdateEarliestAvailableSlot(earliestAvailableSlot primitives.S
}
s.custodyInfo.earliestAvailableSlot = earliestAvailableSlot
EarliestAvailableSlotMetric.Set(float64(earliestAvailableSlot))
return nil
}

View File

@@ -0,0 +1,14 @@
package p2p
import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
)
var (
// EarliestAvailableSlotMetric tracks the earliest available slot in the p2p service
EarliestAvailableSlotMetric = promauto.NewGauge(prometheus.GaugeOpts{
Name: "earliest_available_slot_p2p",
Help: "The earliest available slot tracked by the p2p service",
})
)

View File

@@ -82,8 +82,8 @@ type StateRootNotFoundError struct {
}
// NewStateRootNotFoundError creates a new error instance.
func NewStateRootNotFoundError(stateRootsSize int) StateNotFoundError {
return StateNotFoundError{
func NewStateRootNotFoundError(stateRootsSize int) StateRootNotFoundError {
return StateRootNotFoundError{
message: fmt.Sprintf("state root not found in the last %d state roots", stateRootsSize),
}
}

View File

@@ -0,0 +1,3 @@
## Fixed
- incorrect constructor return type [#16084](https://github.com/OffchainLabs/prysm/pull/16084)

View File

@@ -0,0 +1,3 @@
### Added
- Track the dependent root of the latest finalized checkpoint in forkchoice.

View File

@@ -0,0 +1,3 @@
### Added
- Metric for earliest available slot.