@@ -107,8 +107,8 @@ type BlockChain struct {
107
107
procmu sync.RWMutex // block processor lock
108
108
109
109
checkpoint int // checkpoint counts towards the new checkpoint
110
- currentBlock * types. Block // Current head of the block chain
111
- currentFastBlock * types. Block // Current head of the fast-sync chain (may be above the block chain!)
110
+ currentBlock atomic. Value // Current head of the block chain
111
+ currentFastBlock atomic. Value // Current head of the fast-sync chain (may be above the block chain!)
112
112
113
113
stateCache state.Database // State database to reuse between imports (contains state cache)
114
114
bodyCache * lru.Cache // Cache for the most recent block bodies
@@ -224,10 +224,10 @@ func (bc *BlockChain) loadLastState() error {
224
224
}
225
225
}
226
226
// Everything seems to be fine, set as the head block
227
- bc .currentBlock = currentBlock
227
+ bc .currentBlock . Store ( currentBlock )
228
228
229
229
// Restore the last known head header
230
- currentHeader := bc . currentBlock .Header ()
230
+ currentHeader := currentBlock .Header ()
231
231
if head := GetHeadHeaderHash (bc .db ); head != (common.Hash {}) {
232
232
if header := bc .GetHeaderByHash (head ); header != nil {
233
233
currentHeader = header
@@ -236,21 +236,23 @@ func (bc *BlockChain) loadLastState() error {
236
236
bc .hc .SetCurrentHeader (currentHeader )
237
237
238
238
// Restore the last known head fast block
239
- bc .currentFastBlock = bc . currentBlock
239
+ bc .currentFastBlock . Store ( currentBlock )
240
240
if head := GetHeadFastBlockHash (bc .db ); head != (common.Hash {}) {
241
241
if block := bc .GetBlockByHash (head ); block != nil {
242
- bc .currentFastBlock = block
242
+ bc .currentFastBlock . Store ( block )
243
243
}
244
244
}
245
245
246
246
// Issue a status log for the user
247
+ currentFastBlock := bc .CurrentFastBlock ()
248
+
247
249
headerTd := bc .GetTd (currentHeader .Hash (), currentHeader .Number .Uint64 ())
248
- blockTd := bc .GetTd (bc . currentBlock .Hash (), bc . currentBlock .NumberU64 ())
249
- fastTd := bc .GetTd (bc . currentFastBlock .Hash (), bc . currentFastBlock .NumberU64 ())
250
+ blockTd := bc .GetTd (currentBlock .Hash (), currentBlock .NumberU64 ())
251
+ fastTd := bc .GetTd (currentFastBlock .Hash (), currentFastBlock .NumberU64 ())
250
252
251
253
log .Info ("Loaded most recent local header" , "number" , currentHeader .Number , "hash" , currentHeader .Hash (), "td" , headerTd )
252
- log .Info ("Loaded most recent local full block" , "number" , bc . currentBlock .Number (), "hash" , bc . currentBlock .Hash (), "td" , blockTd )
253
- log .Info ("Loaded most recent local fast block" , "number" , bc . currentFastBlock .Number (), "hash" , bc . currentFastBlock .Hash (), "td" , fastTd )
254
+ log .Info ("Loaded most recent local full block" , "number" , currentBlock .Number (), "hash" , currentBlock .Hash (), "td" , blockTd )
255
+ log .Info ("Loaded most recent local fast block" , "number" , currentFastBlock .Number (), "hash" , currentFastBlock .Hash (), "td" , fastTd )
254
256
255
257
return nil
256
258
}
@@ -279,30 +281,32 @@ func (bc *BlockChain) SetHead(head uint64) error {
279
281
bc .futureBlocks .Purge ()
280
282
281
283
// Rewind the block chain, ensuring we don't end up with a stateless head block
282
- if bc .currentBlock != nil && currentHeader .Number .Uint64 () < bc . currentBlock .NumberU64 () {
283
- bc .currentBlock = bc .GetBlock (currentHeader .Hash (), currentHeader .Number .Uint64 ())
284
+ if currentBlock := bc .CurrentBlock (); currentBlock != nil && currentHeader .Number .Uint64 () < currentBlock .NumberU64 () {
285
+ bc .currentBlock . Store ( bc .GetBlock (currentHeader .Hash (), currentHeader .Number .Uint64 () ))
284
286
}
285
- if bc .currentBlock != nil {
286
- if _ , err := state .New (bc . currentBlock .Root (), bc .stateCache ); err != nil {
287
+ if currentBlock := bc .CurrentBlock (); currentBlock != nil {
288
+ if _ , err := state .New (currentBlock .Root (), bc .stateCache ); err != nil {
287
289
// Rewound state missing, rolled back to before pivot, reset to genesis
288
- bc .currentBlock = nil
290
+ bc .currentBlock . Store ( bc . genesisBlock )
289
291
}
290
292
}
291
293
// Rewind the fast block in a simpleton way to the target head
292
- if bc .currentFastBlock != nil && currentHeader .Number .Uint64 () < bc . currentFastBlock .NumberU64 () {
293
- bc .currentFastBlock = bc .GetBlock (currentHeader .Hash (), currentHeader .Number .Uint64 ())
294
+ if currentFastBlock := bc .CurrentFastBlock (); currentFastBlock != nil && currentHeader .Number .Uint64 () < currentFastBlock .NumberU64 () {
295
+ bc .currentFastBlock . Store ( bc .GetBlock (currentHeader .Hash (), currentHeader .Number .Uint64 () ))
294
296
}
295
297
// If either blocks reached nil, reset to the genesis state
296
- if bc .currentBlock == nil {
297
- bc .currentBlock = bc .genesisBlock
298
+ if currentBlock := bc .CurrentBlock (); currentBlock == nil {
299
+ bc .currentBlock . Store ( bc .genesisBlock )
298
300
}
299
- if bc .currentFastBlock == nil {
300
- bc .currentFastBlock = bc .genesisBlock
301
+ if currentFastBlock := bc .CurrentFastBlock (); currentFastBlock == nil {
302
+ bc .currentFastBlock . Store ( bc .genesisBlock )
301
303
}
302
- if err := WriteHeadBlockHash (bc .db , bc .currentBlock .Hash ()); err != nil {
304
+ currentBlock := bc .CurrentBlock ()
305
+ currentFastBlock := bc .CurrentFastBlock ()
306
+ if err := WriteHeadBlockHash (bc .db , currentBlock .Hash ()); err != nil {
303
307
log .Crit ("Failed to reset head full block" , "err" , err )
304
308
}
305
- if err := WriteHeadFastBlockHash (bc .db , bc . currentFastBlock .Hash ()); err != nil {
309
+ if err := WriteHeadFastBlockHash (bc .db , currentFastBlock .Hash ()); err != nil {
306
310
log .Crit ("Failed to reset head fast block" , "err" , err )
307
311
}
308
312
return bc .loadLastState ()
@@ -321,7 +325,7 @@ func (bc *BlockChain) FastSyncCommitHead(hash common.Hash) error {
321
325
}
322
326
// If all checks out, manually set the head block
323
327
bc .mu .Lock ()
324
- bc .currentBlock = block
328
+ bc .currentBlock . Store ( block )
325
329
bc .mu .Unlock ()
326
330
327
331
log .Info ("Committed new head block" , "number" , block .Number (), "hash" , hash )
@@ -330,28 +334,19 @@ func (bc *BlockChain) FastSyncCommitHead(hash common.Hash) error {
330
334
331
335
// GasLimit returns the gas limit of the current HEAD block.
332
336
func (bc * BlockChain ) GasLimit () uint64 {
333
- bc .mu .RLock ()
334
- defer bc .mu .RUnlock ()
335
-
336
- return bc .currentBlock .GasLimit ()
337
+ return bc .CurrentBlock ().GasLimit ()
337
338
}
338
339
339
340
// CurrentBlock retrieves the current head block of the canonical chain. The
340
341
// block is retrieved from the blockchain's internal cache.
341
342
func (bc * BlockChain ) CurrentBlock () * types.Block {
342
- bc .mu .RLock ()
343
- defer bc .mu .RUnlock ()
344
-
345
- return bc .currentBlock
343
+ return bc .currentBlock .Load ().(* types.Block )
346
344
}
347
345
348
346
// CurrentFastBlock retrieves the current fast-sync head block of the canonical
349
347
// chain. The block is retrieved from the blockchain's internal cache.
350
348
func (bc * BlockChain ) CurrentFastBlock () * types.Block {
351
- bc .mu .RLock ()
352
- defer bc .mu .RUnlock ()
353
-
354
- return bc .currentFastBlock
349
+ return bc .currentFastBlock .Load ().(* types.Block )
355
350
}
356
351
357
352
// SetProcessor sets the processor required for making state modifications.
@@ -416,10 +411,10 @@ func (bc *BlockChain) ResetWithGenesisBlock(genesis *types.Block) error {
416
411
}
417
412
bc .genesisBlock = genesis
418
413
bc .insert (bc .genesisBlock )
419
- bc .currentBlock = bc .genesisBlock
414
+ bc .currentBlock . Store ( bc .genesisBlock )
420
415
bc .hc .SetGenesis (bc .genesisBlock .Header ())
421
416
bc .hc .SetCurrentHeader (bc .genesisBlock .Header ())
422
- bc .currentFastBlock = bc .genesisBlock
417
+ bc .currentFastBlock . Store ( bc .genesisBlock )
423
418
424
419
return nil
425
420
}
@@ -444,7 +439,7 @@ func (bc *BlockChain) repair(head **types.Block) error {
444
439
445
440
// Export writes the active chain to the given writer.
446
441
func (bc * BlockChain ) Export (w io.Writer ) error {
447
- return bc .ExportN (w , uint64 (0 ), bc .currentBlock .NumberU64 ())
442
+ return bc .ExportN (w , uint64 (0 ), bc .CurrentBlock () .NumberU64 ())
448
443
}
449
444
450
445
// ExportN writes a subset of the active chain to the given writer.
@@ -488,7 +483,7 @@ func (bc *BlockChain) insert(block *types.Block) {
488
483
if err := WriteHeadBlockHash (bc .db , block .Hash ()); err != nil {
489
484
log .Crit ("Failed to insert head block hash" , "err" , err )
490
485
}
491
- bc .currentBlock = block
486
+ bc .currentBlock . Store ( block )
492
487
493
488
// If the block is better than our head or is on a different chain, force update heads
494
489
if updateHeads {
@@ -497,7 +492,7 @@ func (bc *BlockChain) insert(block *types.Block) {
497
492
if err := WriteHeadFastBlockHash (bc .db , block .Hash ()); err != nil {
498
493
log .Crit ("Failed to insert head fast block hash" , "err" , err )
499
494
}
500
- bc .currentFastBlock = block
495
+ bc .currentFastBlock . Store ( block )
501
496
}
502
497
}
503
498
@@ -714,13 +709,15 @@ func (bc *BlockChain) Rollback(chain []common.Hash) {
714
709
if currentHeader .Hash () == hash {
715
710
bc .hc .SetCurrentHeader (bc .GetHeader (currentHeader .ParentHash , currentHeader .Number .Uint64 ()- 1 ))
716
711
}
717
- if bc .currentFastBlock .Hash () == hash {
718
- bc .currentFastBlock = bc .GetBlock (bc .currentFastBlock .ParentHash (), bc .currentFastBlock .NumberU64 ()- 1 )
719
- WriteHeadFastBlockHash (bc .db , bc .currentFastBlock .Hash ())
712
+ if currentFastBlock := bc .CurrentFastBlock (); currentFastBlock .Hash () == hash {
713
+ newFastBlock := bc .GetBlock (currentFastBlock .ParentHash (), currentFastBlock .NumberU64 ()- 1 )
714
+ bc .currentFastBlock .Store (newFastBlock )
715
+ WriteHeadFastBlockHash (bc .db , newFastBlock .Hash ())
720
716
}
721
- if bc .currentBlock .Hash () == hash {
722
- bc .currentBlock = bc .GetBlock (bc .currentBlock .ParentHash (), bc .currentBlock .NumberU64 ()- 1 )
723
- WriteHeadBlockHash (bc .db , bc .currentBlock .Hash ())
717
+ if currentBlock := bc .CurrentBlock (); currentBlock .Hash () == hash {
718
+ newBlock := bc .GetBlock (currentBlock .ParentHash (), currentBlock .NumberU64 ()- 1 )
719
+ bc .currentBlock .Store (newBlock )
720
+ WriteHeadBlockHash (bc .db , newBlock .Hash ())
724
721
}
725
722
}
726
723
}
@@ -829,11 +826,12 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
829
826
bc .mu .Lock ()
830
827
head := blockChain [len (blockChain )- 1 ]
831
828
if td := bc .GetTd (head .Hash (), head .NumberU64 ()); td != nil { // Rewind may have occurred, skip in that case
832
- if bc .GetTd (bc .currentFastBlock .Hash (), bc .currentFastBlock .NumberU64 ()).Cmp (td ) < 0 {
829
+ currentFastBlock := bc .CurrentFastBlock ()
830
+ if bc .GetTd (currentFastBlock .Hash (), currentFastBlock .NumberU64 ()).Cmp (td ) < 0 {
833
831
if err := WriteHeadFastBlockHash (bc .db , head .Hash ()); err != nil {
834
832
log .Crit ("Failed to update head fast block hash" , "err" , err )
835
833
}
836
- bc .currentFastBlock = head
834
+ bc .currentFastBlock . Store ( head )
837
835
}
838
836
}
839
837
bc .mu .Unlock ()
@@ -880,7 +878,8 @@ func (bc *BlockChain) WriteBlockWithState(block *types.Block, receipts []*types.
880
878
bc .mu .Lock ()
881
879
defer bc .mu .Unlock ()
882
880
883
- localTd := bc .GetTd (bc .currentBlock .Hash (), bc .currentBlock .NumberU64 ())
881
+ currentBlock := bc .CurrentBlock ()
882
+ localTd := bc .GetTd (currentBlock .Hash (), currentBlock .NumberU64 ())
884
883
externTd := new (big.Int ).Add (block .Difficulty (), ptd )
885
884
886
885
// Irrelevant of the canonical status, write the block itself to the database
@@ -955,14 +954,15 @@ func (bc *BlockChain) WriteBlockWithState(block *types.Block, receipts []*types.
955
954
// Second clause in the if statement reduces the vulnerability to selfish mining.
956
955
// Please refer to http://www.cs.cornell.edu/~ie53/publications/btcProcFC.pdf
957
956
reorg := externTd .Cmp (localTd ) > 0
957
+ currentBlock = bc .CurrentBlock ()
958
958
if ! reorg && externTd .Cmp (localTd ) == 0 {
959
959
// Split same-difficulty blocks by number, then at random
960
- reorg = block .NumberU64 () < bc . currentBlock .NumberU64 () || (block .NumberU64 () == bc . currentBlock .NumberU64 () && mrand .Float64 () < 0.5 )
960
+ reorg = block .NumberU64 () < currentBlock .NumberU64 () || (block .NumberU64 () == currentBlock .NumberU64 () && mrand .Float64 () < 0.5 )
961
961
}
962
962
if reorg {
963
963
// Reorganise the chain if the parent is not the head block
964
- if block .ParentHash () != bc . currentBlock .Hash () {
965
- if err := bc .reorg (bc . currentBlock , block ); err != nil {
964
+ if block .ParentHash () != currentBlock .Hash () {
965
+ if err := bc .reorg (currentBlock , block ); err != nil {
966
966
return NonStatTy , err
967
967
}
968
968
}
@@ -1091,7 +1091,8 @@ func (bc *BlockChain) insertChain(chain types.Blocks) (int, []interface{}, []*ty
1091
1091
case err == consensus .ErrPrunedAncestor :
1092
1092
// Block competing with the canonical chain, store in the db, but don't process
1093
1093
// until the competitor TD goes above the canonical TD
1094
- localTd := bc .GetTd (bc .currentBlock .Hash (), bc .currentBlock .NumberU64 ())
1094
+ currentBlock := bc .CurrentBlock ()
1095
+ localTd := bc .GetTd (currentBlock .Hash (), currentBlock .NumberU64 ())
1095
1096
externTd := new (big.Int ).Add (bc .GetTd (block .ParentHash (), block .NumberU64 ()- 1 ), block .Difficulty ())
1096
1097
if localTd .Cmp (externTd ) > 0 {
1097
1098
if err = bc .WriteBlockWithoutState (block , externTd ); err != nil {
@@ -1480,9 +1481,6 @@ func (bc *BlockChain) writeHeader(header *types.Header) error {
1480
1481
// CurrentHeader retrieves the current head header of the canonical chain. The
1481
1482
// header is retrieved from the HeaderChain's internal cache.
1482
1483
func (bc * BlockChain ) CurrentHeader () * types.Header {
1483
- bc .mu .RLock ()
1484
- defer bc .mu .RUnlock ()
1485
-
1486
1484
return bc .hc .CurrentHeader ()
1487
1485
}
1488
1486
0 commit comments