Skip to content

Commit 95beb49

Browse files
state-diff configs
1 parent a3baf98 commit 95beb49

File tree

12 files changed

+204
-4
lines changed

12 files changed

+204
-4
lines changed

beacon-chain/db/kv/BUILD.bazel

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ go_library(
2727
"p2p.go",
2828
"schema.go",
2929
"state.go",
30+
"state_diff_cache.go",
3031
"state_summary.go",
3132
"state_summary_cache.go",
3233
"utils.go",
@@ -41,6 +42,7 @@ go_library(
4142
"//beacon-chain/db/iface:go_default_library",
4243
"//beacon-chain/state:go_default_library",
4344
"//beacon-chain/state/state-native:go_default_library",
45+
"//cmd/beacon-chain/flags:go_default_library",
4446
"//config/features:go_default_library",
4547
"//config/fieldparams:go_default_library",
4648
"//config/params:go_default_library",

beacon-chain/db/kv/kv.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ type Store struct {
9191
blockCache *ristretto.Cache[string, interfaces.ReadOnlySignedBeaconBlock]
9292
validatorEntryCache *ristretto.Cache[[]byte, *ethpb.Validator]
9393
stateSummaryCache *stateSummaryCache
94+
stateDiffCache *stateDiffCache
9495
ctx context.Context
9596
}
9697

@@ -112,6 +113,7 @@ var Buckets = [][]byte{
112113
lightClientUpdatesBucket,
113114
lightClientBootstrapBucket,
114115
lightClientSyncCommitteeBucket,
116+
stateDiffBucket,
115117
// Indices buckets.
116118
blockSlotIndicesBucket,
117119
stateSlotIndicesBucket,
@@ -201,6 +203,14 @@ func NewKVStore(ctx context.Context, dirPath string, opts ...KVStoreOption) (*St
201203
return nil, err
202204
}
203205

206+
if features.Get().EnableStateDiff {
207+
sdCache, err := newStateDiffCache(kv)
208+
if err != nil {
209+
return nil, err
210+
}
211+
kv.stateDiffCache = sdCache
212+
}
213+
204214
return kv, nil
205215
}
206216

beacon-chain/db/kv/schema.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ var (
1616
stateValidatorsBucket = []byte("state-validators")
1717
feeRecipientBucket = []byte("fee-recipient")
1818
registrationBucket = []byte("registration")
19+
stateDiffBucket = []byte("state-diff")
1920

2021
// Light Client Updates Bucket
2122
lightClientUpdatesBucket = []byte("light-client-updates")
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package kv
2+
3+
import (
4+
"encoding/binary"
5+
"errors"
6+
"sync"
7+
8+
"github.com/OffchainLabs/prysm/v6/beacon-chain/state"
9+
"github.com/OffchainLabs/prysm/v6/cmd/beacon-chain/flags"
10+
"go.etcd.io/bbolt"
11+
)
12+
13+
type stateDiffCache struct {
14+
sync.RWMutex
15+
anchors []state.ReadOnlyBeaconState
16+
offset uint64
17+
}
18+
19+
func newStateDiffCache(s *Store) (*stateDiffCache, error) {
20+
var offset uint64
21+
22+
err := s.db.View(func(tx *bbolt.Tx) error {
23+
bucket := tx.Bucket(stateDiffBucket)
24+
if bucket == nil {
25+
return bbolt.ErrBucketNotFound
26+
}
27+
28+
offsetBytes := bucket.Get([]byte("offset"))
29+
if offsetBytes == nil {
30+
return errors.New("state diff cache: offset not found")
31+
}
32+
offset = binary.LittleEndian.Uint64(offsetBytes)
33+
return nil
34+
})
35+
if err != nil {
36+
return nil, err
37+
}
38+
39+
return &stateDiffCache{
40+
anchors: make([]state.ReadOnlyBeaconState, len(flags.Get().StateDiffExponents)),
41+
offset: offset,
42+
}, nil
43+
}
44+
45+
func (c *stateDiffCache) getAnchor(level int) state.ReadOnlyBeaconState {
46+
c.RLock()
47+
defer c.RUnlock()
48+
return c.anchors[level]
49+
}
50+
51+
func (c *stateDiffCache) setAnchor(level int, anchor state.ReadOnlyBeaconState) error {
52+
c.Lock()
53+
defer c.Unlock()
54+
if level >= len(c.anchors) || level < 0 {
55+
return errors.New("state diff cache: anchor level out of range")
56+
}
57+
c.anchors[level] = anchor
58+
return nil
59+
}
60+
61+
func (c *stateDiffCache) getOffset() uint64 {
62+
c.RLock()
63+
defer c.RUnlock()
64+
return c.offset
65+
}
66+
67+
func (c *stateDiffCache) setOffset(offset uint64) {
68+
c.Lock()
69+
defer c.Unlock()
70+
c.offset = offset
71+
}
72+
73+
func (c *stateDiffCache) clearAnchors() {
74+
c.Lock()
75+
defer c.Unlock()
76+
c.anchors = make([]state.ReadOnlyBeaconState, len(flags.Get().StateDiffExponents))
77+
}

beacon-chain/node/node.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,10 @@ func configureBeacon(cliCtx *cli.Context) error {
277277
return errors.Wrap(err, "could not configure beacon chain")
278278
}
279279

280-
flags.ConfigureGlobalFlags(cliCtx)
280+
err := flags.ConfigureGlobalFlags(cliCtx)
281+
if err != nil {
282+
return errors.Wrap(err, "could not configure global flags")
283+
}
281284

282285
if err := configureChainConfig(cliCtx); err != nil {
283286
return errors.Wrap(err, "could not configure chain config")
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
### Added
2+
3+
- Add initial configs for the state-diff feature.

cmd/beacon-chain/flags/BUILD.bazel

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,23 @@ go_library(
1818
],
1919
deps = [
2020
"//cmd:go_default_library",
21+
"//config/features:go_default_library",
2122
"//config/params:go_default_library",
23+
"@com_github_pkg_errors//:go_default_library",
2224
"@com_github_sirupsen_logrus//:go_default_library",
2325
"@com_github_urfave_cli_v2//:go_default_library",
2426
],
2527
)
2628

2729
go_test(
2830
name = "go_default_test",
29-
srcs = ["api_module_test.go"],
31+
srcs = [
32+
"api_module_test.go",
33+
"config_test.go",
34+
],
3035
embed = [":go_default_library"],
31-
deps = ["//testing/assert:go_default_library"],
36+
deps = [
37+
"//testing/assert:go_default_library",
38+
"//testing/require:go_default_library",
39+
],
3240
)

cmd/beacon-chain/flags/base.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,4 +344,10 @@ var (
344344
Usage: "Maximum number of signatures to batch verify at once for beacon attestation p2p gossip.",
345345
Value: 1000,
346346
}
347+
// StateDiffExponents defines the state diff tree hierarchy levels.
348+
StateDiffExponents = &cli.IntSliceFlag{
349+
Name: "state-diff-exponents",
350+
Usage: "A comma-separated list of exponents (of 2) in decreasing order, defining the state diff hierarchy levels. The last exponent must be greater than or equal to 5.",
351+
Value: cli.NewIntSlice(21, 18, 16, 13, 11, 9, 5),
352+
}
347353
)

cmd/beacon-chain/flags/config.go

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
package flags
22

33
import (
4+
"math"
5+
46
"github.com/OffchainLabs/prysm/v6/cmd"
7+
"github.com/OffchainLabs/prysm/v6/config/features"
8+
"github.com/pkg/errors"
59
"github.com/urfave/cli/v2"
610
)
711

@@ -19,6 +23,7 @@ type GlobalFlags struct {
1923
BlobBatchLimitBurstFactor int
2024
DataColumnBatchLimit int
2125
DataColumnBatchLimitBurstFactor int
26+
StateDiffExponents []int
2227
}
2328

2429
var globalConfig *GlobalFlags
@@ -38,7 +43,7 @@ func Init(c *GlobalFlags) {
3843

3944
// ConfigureGlobalFlags initializes the global config.
4045
// based on the provided cli context.
41-
func ConfigureGlobalFlags(ctx *cli.Context) {
46+
func ConfigureGlobalFlags(ctx *cli.Context) error {
4247
cfg := &GlobalFlags{}
4348

4449
if ctx.Bool(SubscribeToAllSubnets.Name) {
@@ -51,6 +56,18 @@ func ConfigureGlobalFlags(ctx *cli.Context) {
5156
cfg.SubscribeAllDataSubnets = true
5257
}
5358

59+
// State-diff-exponents
60+
cfg.StateDiffExponents = ctx.IntSlice(StateDiffExponents.Name)
61+
if features.Get().EnableStateDiff {
62+
if err := validateStateDiffExponents(cfg.StateDiffExponents); err != nil {
63+
return err
64+
}
65+
} else {
66+
if ctx.IsSet(StateDiffExponents.Name) {
67+
log.Warn("--state-diff-exponents is set but --enable-state-diff is not; the value will be ignored.")
68+
}
69+
}
70+
5471
cfg.BlockBatchLimit = ctx.Int(BlockBatchLimit.Name)
5572
cfg.BlockBatchLimitBurstFactor = ctx.Int(BlockBatchLimitBurstFactor.Name)
5673
cfg.BlobBatchLimit = ctx.Int(BlobBatchLimit.Name)
@@ -63,6 +80,7 @@ func ConfigureGlobalFlags(ctx *cli.Context) {
6380
configureMinimumPeers(ctx, cfg)
6481

6582
Init(cfg)
83+
return nil
6684
}
6785

6886
// MaxDialIsActive checks if the user has enabled the max dial flag.
@@ -78,3 +96,21 @@ func configureMinimumPeers(ctx *cli.Context, cfg *GlobalFlags) {
7896
cfg.MinimumSyncPeers = maxPeers
7997
}
8098
}
99+
100+
func validateStateDiffExponents(exponents []int) error {
101+
length := len(exponents)
102+
if length == 0 || length > 15 {
103+
return errors.New("state diff exponents must contain between 1 and 15 values")
104+
}
105+
if exponents[length-1] < 5 {
106+
return errors.New("the last state diff exponent must be at least 5")
107+
}
108+
prev := math.MaxInt
109+
for _, exp := range exponents {
110+
if exp >= prev {
111+
return errors.New("state diff exponents must be in strictly decreasing order")
112+
}
113+
prev = exp
114+
}
115+
return nil
116+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package flags
2+
3+
import (
4+
"strconv"
5+
"testing"
6+
7+
"github.com/OffchainLabs/prysm/v6/testing/require"
8+
)
9+
10+
func TestValidateStateDiffExponents(t *testing.T) {
11+
tests := []struct {
12+
idx int
13+
exponents []int
14+
wantErr bool
15+
errMsg string
16+
}{
17+
{idx: 1, exponents: []int{0, 1, 2}, wantErr: true, errMsg: "at least 5"},
18+
{idx: 2, exponents: []int{1, 2, 3}, wantErr: true, errMsg: "at least 5"},
19+
{idx: 3, exponents: []int{9, 8, 4}, wantErr: true, errMsg: "at least 5"},
20+
{idx: 4, exponents: []int{3, 4, 5}, wantErr: true, errMsg: "decreasing"},
21+
{idx: 5, exponents: []int{15, 14, 14, 12, 11}, wantErr: true, errMsg: "decreasing"},
22+
{idx: 6, exponents: []int{15, 14, 13, 12, 11}, wantErr: false},
23+
{idx: 7, exponents: []int{21, 18, 16, 13, 11, 9, 5}, wantErr: false},
24+
{idx: 8, exponents: []int{30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 18, 16, 13, 11, 9, 5}, wantErr: true, errMsg: "between 1 and 15 values"},
25+
{idx: 9, exponents: []int{}, wantErr: true, errMsg: "between 1 and 15 values"},
26+
}
27+
28+
for _, tt := range tests {
29+
t.Run(strconv.Itoa(tt.idx), func(t *testing.T) {
30+
err := validateStateDiffExponents(tt.exponents)
31+
if tt.wantErr {
32+
require.ErrorContains(t, tt.errMsg, err)
33+
} else {
34+
require.NoError(t, err)
35+
}
36+
})
37+
}
38+
}

0 commit comments

Comments
 (0)