18
18
package core
19
19
20
20
import (
21
+ crand "crypto/rand"
21
22
"errors"
22
23
"fmt"
23
24
"io"
25
+ "math"
24
26
"math/big"
25
- "math/rand"
27
+ mrand "math/rand"
26
28
"runtime"
27
29
"sync"
28
30
"sync/atomic"
@@ -89,7 +91,8 @@ type BlockChain struct {
89
91
procInterrupt int32 // interrupt signaler for block processing
90
92
wg sync.WaitGroup
91
93
92
- pow pow.PoW
94
+ pow pow.PoW
95
+ rand * mrand.Rand
93
96
}
94
97
95
98
func NewBlockChain (chainDb ethdb.Database , pow pow.PoW , mux * event.TypeMux ) (* BlockChain , error ) {
@@ -112,6 +115,12 @@ func NewBlockChain(chainDb ethdb.Database, pow pow.PoW, mux *event.TypeMux) (*Bl
112
115
futureBlocks : futureBlocks ,
113
116
pow : pow ,
114
117
}
118
+ // Seed a fast but crypto originating random generator
119
+ seed , err := crand .Int (crand .Reader , big .NewInt (math .MaxInt64 ))
120
+ if err != nil {
121
+ return nil , err
122
+ }
123
+ bc .rand = mrand .New (mrand .NewSource (seed .Int64 ()))
115
124
116
125
bc .genesisBlock = bc .GetBlockByNumber (0 )
117
126
if bc .genesisBlock == nil {
@@ -178,21 +187,21 @@ func (self *BlockChain) loadLastState() error {
178
187
fastTd := self .GetTd (self .currentFastBlock .Hash ())
179
188
180
189
glog .V (logger .Info ).Infof ("Last header: #%d [%x…] TD=%v" , self .currentHeader .Number , self .currentHeader .Hash ().Bytes ()[:4 ], headerTd )
181
- glog .V (logger .Info ).Infof ("Fast block: #%d [%x…] TD=%v" , self .currentFastBlock .Number (), self .currentFastBlock .Hash ().Bytes ()[:4 ], fastTd )
182
190
glog .V (logger .Info ).Infof ("Last block: #%d [%x…] TD=%v" , self .currentBlock .Number (), self .currentBlock .Hash ().Bytes ()[:4 ], blockTd )
191
+ glog .V (logger .Info ).Infof ("Fast block: #%d [%x…] TD=%v" , self .currentFastBlock .Number (), self .currentFastBlock .Hash ().Bytes ()[:4 ], fastTd )
183
192
184
193
return nil
185
194
}
186
195
187
- // SetHead rewind the local chain to a new head entity . In the case of headers,
188
- // everything above the new head will be deleted and the new one set. In the case
189
- // of blocks though, the head may be further rewound if block bodies are missing
190
- // (non-archive nodes after a fast sync).
196
+ // SetHead rewinds the local chain to a new head. In the case of headers, everything
197
+ // above the new head will be deleted and the new one set. In the case of blocks
198
+ // though, the head may be further rewound if block bodies are missing (non-archive
199
+ // nodes after a fast sync).
191
200
func (bc * BlockChain ) SetHead (head uint64 ) {
192
201
bc .mu .Lock ()
193
202
defer bc .mu .Unlock ()
194
203
195
- // Figure out the highest known canonical assignment
204
+ // Figure out the highest known canonical headers and/or blocks
196
205
height := uint64 (0 )
197
206
if bc .currentHeader != nil {
198
207
if hh := bc .currentHeader .Number .Uint64 (); hh > height {
@@ -266,7 +275,7 @@ func (bc *BlockChain) SetHead(head uint64) {
266
275
// FastSyncCommitHead sets the current head block to the one defined by the hash
267
276
// irrelevant what the chain contents were prior.
268
277
func (self * BlockChain ) FastSyncCommitHead (hash common.Hash ) error {
269
- // Make sure that both the block as well at it's state trie exists
278
+ // Make sure that both the block as well at its state trie exists
270
279
block := self .GetBlock (hash )
271
280
if block == nil {
272
281
return fmt .Errorf ("non existent block [%x…]" , hash [:4 ])
@@ -298,7 +307,7 @@ func (self *BlockChain) LastBlockHash() common.Hash {
298
307
}
299
308
300
309
// CurrentHeader retrieves the current head header of the canonical chain. The
301
- // header is retrieved from the chain manager 's internal cache.
310
+ // header is retrieved from the blockchain 's internal cache.
302
311
func (self * BlockChain ) CurrentHeader () * types.Header {
303
312
self .mu .RLock ()
304
313
defer self .mu .RUnlock ()
@@ -307,7 +316,7 @@ func (self *BlockChain) CurrentHeader() *types.Header {
307
316
}
308
317
309
318
// CurrentBlock retrieves the current head block of the canonical chain. The
310
- // block is retrieved from the chain manager 's internal cache.
319
+ // block is retrieved from the blockchain 's internal cache.
311
320
func (self * BlockChain ) CurrentBlock () * types.Block {
312
321
self .mu .RLock ()
313
322
defer self .mu .RUnlock ()
@@ -316,7 +325,7 @@ func (self *BlockChain) CurrentBlock() *types.Block {
316
325
}
317
326
318
327
// CurrentFastBlock retrieves the current fast-sync head block of the canonical
319
- // chain. The block is retrieved from the chain manager 's internal cache.
328
+ // chain. The block is retrieved from the blockchain 's internal cache.
320
329
func (self * BlockChain ) CurrentFastBlock () * types.Block {
321
330
self .mu .RLock ()
322
331
defer self .mu .RUnlock ()
@@ -353,7 +362,7 @@ func (bc *BlockChain) ResetWithGenesisBlock(genesis *types.Block) {
353
362
bc .mu .Lock ()
354
363
defer bc .mu .Unlock ()
355
364
356
- // Prepare the genesis block and reinitialize the chain
365
+ // Prepare the genesis block and reinitialise the chain
357
366
if err := WriteTd (bc .chainDb , genesis .Hash (), genesis .Difficulty ()); err != nil {
358
367
glog .Fatalf ("failed to write genesis block TD: %v" , err )
359
368
}
@@ -403,7 +412,7 @@ func (self *BlockChain) ExportN(w io.Writer, first uint64, last uint64) error {
403
412
// insert injects a new head block into the current block chain. This method
404
413
// assumes that the block is indeed a true head. It will also reset the head
405
414
// header and the head fast sync block to this very same block to prevent them
406
- // from diverging on a different header chain.
415
+ // from pointing to a possibly old canonical chain (i.e. side chain by now) .
407
416
//
408
417
// Note, this function assumes that the `mu` mutex is held!
409
418
func (bc * BlockChain ) insert (block * types.Block ) {
@@ -625,10 +634,10 @@ const (
625
634
626
635
// writeHeader writes a header into the local chain, given that its parent is
627
636
// already known. If the total difficulty of the newly inserted header becomes
628
- // greater than the old known TD, the canonical chain is re-routed.
637
+ // greater than the current known TD, the canonical chain is re-routed.
629
638
//
630
639
// Note: This method is not concurrent-safe with inserting blocks simultaneously
631
- // into the chain, as side effects caused by reorganizations cannot be emulated
640
+ // into the chain, as side effects caused by reorganisations cannot be emulated
632
641
// without the real blocks. Hence, writing headers directly should only be done
633
642
// in two scenarios: pure-header mode of operation (light clients), or properly
634
643
// separated header/block phases (non-archive clients).
@@ -678,10 +687,9 @@ func (self *BlockChain) writeHeader(header *types.Header) error {
678
687
return nil
679
688
}
680
689
681
- // InsertHeaderChain will attempt to insert the given header chain in to the
682
- // local chain, possibly creating a fork. If an error is returned, it will
683
- // return the index number of the failing header as well an error describing
684
- // what went wrong.
690
+ // InsertHeaderChain attempts to insert the given header chain in to the local
691
+ // chain, possibly creating a reorg. If an error is returned, it will return the
692
+ // index number of the failing header as well an error describing what went wrong.
685
693
//
686
694
// The verify parameter can be used to fine tune whether nonce verification
687
695
// should be done or not. The reason behind the optional check is because some
@@ -702,7 +710,7 @@ func (self *BlockChain) InsertHeaderChain(chain []*types.Header, checkFreq int)
702
710
// Generate the list of headers that should be POW verified
703
711
verify := make ([]bool , len (chain ))
704
712
for i := 0 ; i < len (verify )/ checkFreq ; i ++ {
705
- index := i * checkFreq + rand .Intn (checkFreq )
713
+ index := i * checkFreq + self . rand .Intn (checkFreq )
706
714
if index >= len (verify ) {
707
715
index = len (verify ) - 1
708
716
}
@@ -766,10 +774,6 @@ func (self *BlockChain) InsertHeaderChain(chain []*types.Header, checkFreq int)
766
774
pending .Wait ()
767
775
768
776
// If anything failed, report
769
- if atomic .LoadInt32 (& self .procInterrupt ) == 1 {
770
- glog .V (logger .Debug ).Infoln ("premature abort during receipt chain processing" )
771
- return 0 , nil
772
- }
773
777
if failed > 0 {
774
778
for i , err := range errs {
775
779
if err != nil {
@@ -807,6 +811,9 @@ func (self *BlockChain) InsertHeaderChain(chain []*types.Header, checkFreq int)
807
811
// Rollback is designed to remove a chain of links from the database that aren't
808
812
// certain enough to be valid.
809
813
func (self * BlockChain ) Rollback (chain []common.Hash ) {
814
+ self .mu .Lock ()
815
+ defer self .mu .Unlock ()
816
+
810
817
for i := len (chain ) - 1 ; i >= 0 ; i -- {
811
818
hash := chain [i ]
812
819
@@ -905,6 +912,12 @@ func (self *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain
905
912
glog .Fatal (errs [index ])
906
913
return
907
914
}
915
+ if err := WriteMipmapBloom (self .chainDb , block .NumberU64 (), receipts ); err != nil {
916
+ errs [index ] = fmt .Errorf ("failed to write log blooms: %v" , err )
917
+ atomic .AddInt32 (& failed , 1 )
918
+ glog .Fatal (errs [index ])
919
+ return
920
+ }
908
921
atomic .AddInt32 (& stats .processed , 1 )
909
922
}
910
923
}
@@ -920,17 +933,17 @@ func (self *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain
920
933
pending .Wait ()
921
934
922
935
// If anything failed, report
923
- if atomic .LoadInt32 (& self .procInterrupt ) == 1 {
924
- glog .V (logger .Debug ).Infoln ("premature abort during receipt chain processing" )
925
- return 0 , nil
926
- }
927
936
if failed > 0 {
928
937
for i , err := range errs {
929
938
if err != nil {
930
939
return i , err
931
940
}
932
941
}
933
942
}
943
+ if atomic .LoadInt32 (& self .procInterrupt ) == 1 {
944
+ glog .V (logger .Debug ).Infoln ("premature abort during receipt chain processing" )
945
+ return 0 , nil
946
+ }
934
947
// Update the head fast sync block if better
935
948
self .mu .Lock ()
936
949
head := blockChain [len (errs )- 1 ]
0 commit comments