@@ -2,13 +2,17 @@ package stategen
2
2
3
3
import (
4
4
"context"
5
- "errors "
5
+ "fmt "
6
6
7
+ "github.com/pkg/errors"
7
8
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
8
9
transition "github.com/prysmaticlabs/prysm/beacon-chain/core/state"
9
10
"github.com/prysmaticlabs/prysm/beacon-chain/db/filters"
10
11
"github.com/prysmaticlabs/prysm/beacon-chain/state"
12
+ stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
11
13
"github.com/prysmaticlabs/prysm/shared/bytesutil"
14
+ "github.com/prysmaticlabs/prysm/shared/featureconfig"
15
+ "go.opencensus.io/trace"
12
16
)
13
17
14
18
// ReplayBlocks replays the input blocks on the input state until the target slot is reached.
@@ -17,17 +21,31 @@ func (s *State) ReplayBlocks(ctx context.Context, state *state.BeaconState, sign
17
21
// The input block list is sorted in decreasing slots order.
18
22
if len (signed ) > 0 {
19
23
for i := len (signed ) - 1 ; i >= 0 ; i -- {
20
- state , err = transition .ExecuteStateTransitionNoVerifyAttSigs (ctx , state , signed [i ])
21
- if err != nil {
22
- return nil , err
24
+ if featureconfig .Get ().EnableStateGenSigVerify {
25
+ state , err = transition .ExecuteStateTransition (ctx , state , signed [i ])
26
+ if err != nil {
27
+ return nil , err
28
+ }
29
+ } else {
30
+ state , err = executeStateTransitionStateGen (ctx , state , signed [i ])
31
+ if err != nil {
32
+ return nil , err
33
+ }
23
34
}
24
35
}
25
36
}
26
37
27
38
// If there is skip slots at the end.
28
- state , err = transition .ProcessSlots (ctx , state , targetSlot )
29
- if err != nil {
30
- return nil , err
39
+ if featureconfig .Get ().EnableStateGenSigVerify {
40
+ state , err = transition .ProcessSlots (ctx , state , targetSlot )
41
+ if err != nil {
42
+ return nil , err
43
+ }
44
+ } else {
45
+ state , err = processSlotsStateGen (ctx , state , targetSlot )
46
+ if err != nil {
47
+ return nil , err
48
+ }
31
49
}
32
50
33
51
return state , nil
@@ -78,3 +96,77 @@ func (s *State) LoadBlocks(ctx context.Context, startSlot uint64, endSlot uint64
78
96
79
97
return filteredBlocks , nil
80
98
}
99
+
100
+ // executeStateTransitionStateGen applies state transition on input historical state and block for state gen usages.
101
+ // There's no signature verification involved given state gen only works with stored block and state in DB.
102
+ // If the objects are already in stored in DB, one can omit redundant signature checks and ssz hashing calculations.
103
+ // WARNING: This method should not be used on an unverified new block.
104
+ func executeStateTransitionStateGen (
105
+ ctx context.Context ,
106
+ state * stateTrie.BeaconState ,
107
+ signed * ethpb.SignedBeaconBlock ,
108
+ ) (* stateTrie.BeaconState , error ) {
109
+ if ctx .Err () != nil {
110
+ return nil , ctx .Err ()
111
+ }
112
+ if signed == nil || signed .Block == nil {
113
+ return nil , errors .New ("nil block" )
114
+ }
115
+
116
+ ctx , span := trace .StartSpan (ctx , "beacon-chain.ChainService.ExecuteStateTransitionStateGen" )
117
+ defer span .End ()
118
+ var err error
119
+
120
+ // Execute per slots transition.
121
+ // Given this is for state gen, a node uses the version process slots without skip slots cache.
122
+ state , err = processSlotsStateGen (ctx , state , signed .Block .Slot )
123
+ if err != nil {
124
+ return nil , errors .Wrap (err , "could not process slot" )
125
+ }
126
+
127
+ // Execute per block transition.
128
+ // Given this is for state gen, a node only cares about the post state without proposer
129
+ // and randao signature verifications.
130
+ state , err = transition .ProcessBlockForStateRoot (ctx , state , signed )
131
+ if err != nil {
132
+ return nil , errors .Wrap (err , "could not process block" )
133
+ }
134
+
135
+ return state , nil
136
+ }
137
+
138
+ // processSlotsStateGen to process old slots for state gen usages.
139
+ // There's no skip slot cache involved given state gen only works with already stored block and state in DB.
140
+ // WARNING: This method should not be used for future slot.
141
+ func processSlotsStateGen (ctx context.Context , state * stateTrie.BeaconState , slot uint64 ) (* stateTrie.BeaconState , error ) {
142
+ ctx , span := trace .StartSpan (ctx , "beacon-chain.ChainService.ProcessSlotsStateGen" )
143
+ defer span .End ()
144
+ if state == nil {
145
+ return nil , errors .New ("nil state" )
146
+ }
147
+
148
+ if state .Slot () > slot {
149
+ err := fmt .Errorf ("expected state.slot %d < slot %d" , state .Slot (), slot )
150
+ return nil , err
151
+ }
152
+
153
+ if state .Slot () == slot {
154
+ return state , nil
155
+ }
156
+
157
+ for state .Slot () < slot {
158
+ state , err := transition .ProcessSlot (ctx , state )
159
+ if err != nil {
160
+ return nil , errors .Wrap (err , "could not process slot" )
161
+ }
162
+ if transition .CanProcessEpoch (state ) {
163
+ state , err = transition .ProcessEpochPrecompute (ctx , state )
164
+ if err != nil {
165
+ return nil , errors .Wrap (err , "could not process epoch with optimizations" )
166
+ }
167
+ }
168
+ state .SetSlot (state .Slot () + 1 )
169
+ }
170
+
171
+ return state , nil
172
+ }
0 commit comments