6
6
"errors"
7
7
"fmt"
8
8
"sync"
9
+ "sync/atomic"
9
10
"time"
10
11
11
12
"github.com/ipfs/go-datastore"
@@ -50,8 +51,7 @@ type Executor struct {
50
51
options common.BlockOptions
51
52
52
53
// State management
53
- lastState types.State
54
- lastStateMtx * sync.RWMutex
54
+ lastState * atomic.Pointer [types.State ]
55
55
56
56
// Channels for coordination
57
57
txNotifyCh chan struct {}
@@ -112,7 +112,7 @@ func NewExecutor(
112
112
headerBroadcaster : headerBroadcaster ,
113
113
dataBroadcaster : dataBroadcaster ,
114
114
options : options ,
115
- lastStateMtx : & sync. RWMutex {},
115
+ lastState : & atomic. Pointer [types. State ] {},
116
116
txNotifyCh : make (chan struct {}, 1 ),
117
117
errorCh : errorCh ,
118
118
logger : logger .With ().Str ("component" , "executor" ).Logger (),
@@ -150,18 +150,29 @@ func (e *Executor) Stop() error {
150
150
return nil
151
151
}
152
152
153
- // GetLastState returns the current state
153
+ // GetLastState returns the current state.
154
154
func (e * Executor ) GetLastState () types.State {
155
- e .lastStateMtx .RLock ()
156
- defer e .lastStateMtx .RUnlock ()
157
- return e .lastState
155
+ state := e .getLastState ()
156
+ state .AppHash = bytes .Clone (state .AppHash )
157
+ state .LastResultsHash = bytes .Clone (state .LastResultsHash )
158
+
159
+ return state
160
+ }
161
+
162
+ // getLastState returns the current state.
163
+ // getLastState should never directly mutate.
164
+ func (e * Executor ) getLastState () types.State {
165
+ state := e .lastState .Load ()
166
+ if state == nil {
167
+ return types.State {}
168
+ }
169
+
170
+ return * state
158
171
}
159
172
160
- // SetLastState updates the current state
161
- func (e * Executor ) SetLastState (state types.State ) {
162
- e .lastStateMtx .Lock ()
163
- defer e .lastStateMtx .Unlock ()
164
- e .lastState = state
173
+ // setLastState updates the current state
174
+ func (e * Executor ) setLastState (state types.State ) {
175
+ e .lastState .Store (& state )
165
176
}
166
177
167
178
// NotifyNewTransactions signals that new transactions are available
@@ -198,7 +209,7 @@ func (e *Executor) initializeState() error {
198
209
}
199
210
}
200
211
201
- e .SetLastState (state )
212
+ e .setLastState (state )
202
213
203
214
// Set store height
204
215
if err := e .store .SetHeight (e .ctx , state .LastBlockHeight ); err != nil {
@@ -218,7 +229,7 @@ func (e *Executor) executionLoop() {
218
229
219
230
var delay time.Duration
220
231
initialHeight := e .genesis .InitialHeight
221
- currentState := e .GetLastState ()
232
+ currentState := e .getLastState ()
222
233
223
234
if currentState .LastBlockHeight < initialHeight {
224
235
delay = time .Until (e .genesis .StartTime .Add (e .config .Node .BlockTime .Duration ))
@@ -291,7 +302,7 @@ func (e *Executor) produceBlock() error {
291
302
}
292
303
}()
293
304
294
- currentState := e .GetLastState ()
305
+ currentState := e .getLastState ()
295
306
newHeight := currentState .LastBlockHeight + 1
296
307
297
308
e .logger .Debug ().Uint64 ("height" , newHeight ).Msg ("producing block" )
@@ -429,7 +440,7 @@ func (e *Executor) retrieveBatch(ctx context.Context) (*BatchData, error) {
429
440
430
441
// createBlock creates a new block from the given batch
431
442
func (e * Executor ) createBlock (ctx context.Context , height uint64 , batchData * BatchData ) (* types.SignedHeader , * types.Data , error ) {
432
- currentState := e .GetLastState ()
443
+ currentState := e .getLastState ()
433
444
headerTime := uint64 (e .genesis .StartTime .UnixNano ())
434
445
435
446
// Get last block info
@@ -518,7 +529,7 @@ func (e *Executor) createBlock(ctx context.Context, height uint64, batchData *Ba
518
529
519
530
// applyBlock applies the block to get the new state
520
531
func (e * Executor ) applyBlock (ctx context.Context , header types.Header , data * types.Data ) (types.State , error ) {
521
- currentState := e .GetLastState ()
532
+ currentState := e .getLastState ()
522
533
523
534
// Prepare transactions
524
535
rawTxs := make ([][]byte , len (data .Txs ))
@@ -601,7 +612,7 @@ func (e *Executor) updateState(ctx context.Context, newState types.State) error
601
612
return err
602
613
}
603
614
604
- e .SetLastState (newState )
615
+ e .setLastState (newState )
605
616
e .metrics .Height .Set (float64 (newState .LastBlockHeight ))
606
617
607
618
return nil
0 commit comments