Skip to content

Commit b024191

Browse files
authored
Get cold intermediate state with slot (#5097)
* loadColdIntermediateStateWithSlot * Starting test * Tests
1 parent 1f87cb1 commit b024191

File tree

2 files changed

+121
-0
lines changed

2 files changed

+121
-0
lines changed

beacon-chain/state/stategen/cold.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,52 @@ func (s *State) loadColdIntermediateStateByRoot(ctx context.Context, slot uint64
9797
return s.ReplayBlocks(ctx, lowArchivedPointState, replayBlks, slot)
9898
}
9999

100+
// This loads a cold state by slot where the slot lies between the archived point.
101+
// This is a slower implementation given there's no root and slot is the only argument. It requires fetching
102+
// all the blocks between the archival points.
103+
func (s *State) loadColdIntermediateStateBySlot(ctx context.Context, slot uint64) (*state.BeaconState, error) {
104+
ctx, span := trace.StartSpan(ctx, "stateGen.loadColdIntermediateStateBySlot")
105+
defer span.End()
106+
107+
// Load the archive point for lower and high side of the intermediate state.
108+
lowArchivedPointIdx := slot / s.slotsPerArchivedPoint
109+
highArchivedPointIdx := lowArchivedPointIdx + 1
110+
111+
lowArchivedPointState, err := s.archivedPointByIndex(ctx, lowArchivedPointIdx)
112+
if err != nil {
113+
return nil, errors.Wrap(err, "could not get lower bound archived state using index")
114+
}
115+
if lowArchivedPointState == nil {
116+
return nil, errUnknownArchivedState
117+
}
118+
119+
// If the slot of the high archived point lies outside of the split slot, use the split slot and root
120+
// for the upper archived point.
121+
var highArchivedPointRoot [32]byte
122+
highArchivedPointSlot := highArchivedPointIdx * s.slotsPerArchivedPoint
123+
if highArchivedPointSlot >= s.splitInfo.slot {
124+
highArchivedPointRoot = s.splitInfo.root
125+
highArchivedPointSlot = s.splitInfo.slot
126+
} else {
127+
if _, err := s.archivedPointByIndex(ctx, highArchivedPointSlot); err != nil {
128+
return nil, errors.Wrap(err, "could not get upper bound archived state using index")
129+
}
130+
highArchivedPointRoot = s.beaconDB.ArchivedPointRoot(ctx, highArchivedPointIdx)
131+
slot, err := s.blockRootSlot(ctx, highArchivedPointRoot)
132+
if err != nil {
133+
return nil, errors.Wrap(err, "could not get high archived point slot")
134+
}
135+
highArchivedPointSlot = slot
136+
}
137+
138+
replayBlks, err := s.LoadBlocks(ctx, lowArchivedPointState.Slot()+1, highArchivedPointSlot, highArchivedPointRoot)
139+
if err != nil {
140+
return nil, errors.Wrap(err, "could not load block for cold state using slot")
141+
}
142+
143+
return s.ReplayBlocks(ctx, lowArchivedPointState, replayBlks, slot)
144+
}
145+
100146
// Given the archive index, this returns the archived cold state in the DB.
101147
// If the archived state does not exist in the state, it'll compute it and save it.
102148
func (s *State) archivedPointByIndex(ctx context.Context, archiveIndex uint64) (*state.BeaconState, error) {

beacon-chain/state/stategen/cold_test.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ package stategen
22

33
import (
44
"context"
5+
"strings"
56
"testing"
67

78
"github.com/gogo/protobuf/proto"
89
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
910
"github.com/prysmaticlabs/go-ssz"
1011
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
1112
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
13+
"github.com/prysmaticlabs/prysm/shared/params"
1214
"github.com/prysmaticlabs/prysm/shared/testutil"
1315
)
1416

@@ -132,6 +134,79 @@ func TestLoadColdStateByRoot_IntermediatePlayback(t *testing.T) {
132134
}
133135
}
134136

137+
func TestLoadColdStateBySlotIntermediatePlayback_BeforeCutoff(t *testing.T) {
138+
ctx := context.Background()
139+
db := testDB.SetupDB(t)
140+
defer testDB.TeardownDB(t, db)
141+
142+
service := New(db)
143+
service.slotsPerArchivedPoint = params.BeaconConfig().SlotsPerEpoch * 2
144+
145+
beaconState, _ := testutil.DeterministicGenesisState(t, 32)
146+
if err := service.beaconDB.SaveArchivedPointState(ctx, beaconState, 0); err != nil {
147+
t.Fatal(err)
148+
}
149+
if err := service.beaconDB.SaveArchivedPointRoot(ctx, [32]byte{}, 0); err != nil {
150+
t.Fatal(err)
151+
}
152+
if err := service.beaconDB.SaveArchivedPointState(ctx, beaconState, 1); err != nil {
153+
t.Fatal(err)
154+
}
155+
if err := service.beaconDB.SaveArchivedPointRoot(ctx, [32]byte{}, 1); err != nil {
156+
t.Fatal(err)
157+
}
158+
159+
slot := uint64(20)
160+
loadedState, err := service.loadColdIntermediateStateBySlot(ctx, slot)
161+
if err != nil {
162+
t.Fatal(err)
163+
}
164+
if loadedState.Slot() != slot {
165+
t.Error("Did not correctly save state")
166+
}
167+
}
168+
169+
func TestLoadColdStateBySlotIntermediatePlayback_AfterCutoff(t *testing.T) {
170+
ctx := context.Background()
171+
db := testDB.SetupDB(t)
172+
defer testDB.TeardownDB(t, db)
173+
174+
service := New(db)
175+
service.slotsPerArchivedPoint = params.BeaconConfig().SlotsPerEpoch
176+
177+
beaconState, _ := testutil.DeterministicGenesisState(t, 32)
178+
if err := service.beaconDB.SaveArchivedPointState(ctx, beaconState, 0); err != nil {
179+
t.Fatal(err)
180+
}
181+
if err := service.beaconDB.SaveArchivedPointRoot(ctx, [32]byte{}, 0); err != nil {
182+
t.Fatal(err)
183+
}
184+
185+
slot := uint64(10)
186+
loadedState, err := service.loadColdIntermediateStateBySlot(ctx, slot)
187+
if err != nil {
188+
t.Fatal(err)
189+
}
190+
if loadedState.Slot() != slot {
191+
t.Error("Did not correctly save state")
192+
}
193+
}
194+
195+
196+
func TestLoadColdStateByRoot_UnknownArchivedState(t *testing.T) {
197+
ctx := context.Background()
198+
db := testDB.SetupDB(t)
199+
defer testDB.TeardownDB(t, db)
200+
201+
service := New(db)
202+
service.slotsPerArchivedPoint = 1
203+
if _, err := service.loadColdIntermediateStateBySlot(ctx, 0);
204+
!strings.Contains(err.Error(), errUnknownArchivedState.Error()) {
205+
t.Log(err)
206+
t.Error("Did not get wanted error")
207+
}
208+
}
209+
135210
func TestArchivedPointByIndex_HasPoint(t *testing.T) {
136211
ctx := context.Background()
137212
db := testDB.SetupDB(t)

0 commit comments

Comments
 (0)