@@ -3,6 +3,7 @@ package core
3
3
import (
4
4
"fmt"
5
5
"math/big"
6
+ "sync"
6
7
7
8
"github.com/ethereum/go-ethereum/core/types"
8
9
"github.com/ethereum/go-ethereum/ethutil"
@@ -50,14 +51,34 @@ type ChainManager struct {
50
51
eventMux * event.TypeMux
51
52
genesisBlock * types.Block
52
53
// Last known total difficulty
53
- TD * big.Int
54
+ mu sync.RWMutex
55
+ td * big.Int
56
+ lastBlockNumber uint64
57
+ currentBlock * types.Block
58
+ lastBlockHash []byte
54
59
55
- LastBlockNumber uint64
60
+ transState * state.StateDB
61
+ }
56
62
57
- CurrentBlock * types.Block
58
- LastBlockHash []byte
63
+ func (self * ChainManager ) Td () * big.Int {
64
+ self .mu .RLock ()
65
+ defer self .mu .RUnlock ()
59
66
60
- transState * state.StateDB
67
+ return self .td
68
+ }
69
+
70
+ func (self * ChainManager ) LastBlockNumber () uint64 {
71
+ self .mu .RLock ()
72
+ defer self .mu .RUnlock ()
73
+
74
+ return self .lastBlockNumber
75
+ }
76
+
77
+ func (self * ChainManager ) CurrentBlock () * types.Block {
78
+ self .mu .RLock ()
79
+ defer self .mu .RUnlock ()
80
+
81
+ return self .currentBlock
61
82
}
62
83
63
84
func NewChainManager (mux * event.TypeMux ) * ChainManager {
@@ -77,7 +98,7 @@ func (self *ChainManager) SetProcessor(proc types.BlockProcessor) {
77
98
}
78
99
79
100
func (self * ChainManager ) State () * state.StateDB {
80
- return self .CurrentBlock .State ()
101
+ return self .CurrentBlock () .State ()
81
102
}
82
103
83
104
func (self * ChainManager ) TransState () * state.StateDB {
@@ -91,27 +112,30 @@ func (bc *ChainManager) setLastBlock() {
91
112
AddTestNetFunds (bc .genesisBlock )
92
113
93
114
block := types .NewBlockFromBytes (data )
94
- bc .CurrentBlock = block
95
- bc .LastBlockHash = block .Hash ()
96
- bc .LastBlockNumber = block .Number .Uint64 ()
115
+ bc .currentBlock = block
116
+ bc .lastBlockHash = block .Hash ()
117
+ bc .lastBlockNumber = block .Number .Uint64 ()
97
118
98
119
// Set the last know difficulty (might be 0x0 as initial value, Genesis)
99
- bc .TD = ethutil .BigD (ethutil .Config .Db .LastKnownTD ())
120
+ bc .td = ethutil .BigD (ethutil .Config .Db .LastKnownTD ())
100
121
} else {
101
122
bc .Reset ()
102
123
}
103
124
104
- chainlogger .Infof ("Last block (#%d) %x\n " , bc .LastBlockNumber , bc .CurrentBlock .Hash ())
125
+ chainlogger .Infof ("Last block (#%d) %x\n " , bc .lastBlockNumber , bc .currentBlock .Hash ())
105
126
}
106
127
107
128
// Block creation & chain handling
108
129
func (bc * ChainManager ) NewBlock (coinbase []byte ) * types.Block {
130
+ bc .mu .RLock ()
131
+ defer bc .mu .RUnlock ()
132
+
109
133
var root interface {}
110
134
hash := ZeroHash256
111
135
112
136
if bc .CurrentBlock != nil {
113
- root = bc .CurrentBlock .Root ()
114
- hash = bc .LastBlockHash
137
+ root = bc .currentBlock .Root ()
138
+ hash = bc .lastBlockHash
115
139
}
116
140
117
141
block := types .CreateBlock (
@@ -122,47 +146,54 @@ func (bc *ChainManager) NewBlock(coinbase []byte) *types.Block {
122
146
nil ,
123
147
"" )
124
148
125
- parent := bc .CurrentBlock
149
+ parent := bc .currentBlock
126
150
if parent != nil {
127
151
block .Difficulty = CalcDifficulty (block , parent )
128
- block .Number = new (big.Int ).Add (bc .CurrentBlock .Number , ethutil .Big1 )
129
- block .GasLimit = block .CalcGasLimit (bc .CurrentBlock )
152
+ block .Number = new (big.Int ).Add (bc .currentBlock .Number , ethutil .Big1 )
153
+ block .GasLimit = block .CalcGasLimit (bc .currentBlock )
130
154
131
155
}
132
156
133
157
return block
134
158
}
135
159
136
160
func (bc * ChainManager ) Reset () {
161
+ bc .mu .Lock ()
162
+ defer bc .mu .Unlock ()
163
+
137
164
AddTestNetFunds (bc .genesisBlock )
138
165
139
166
bc .genesisBlock .Trie ().Sync ()
140
167
// Prepare the genesis block
141
168
bc .write (bc .genesisBlock )
142
169
bc .insert (bc .genesisBlock )
143
- bc .CurrentBlock = bc .genesisBlock
170
+ bc .currentBlock = bc .genesisBlock
144
171
145
- bc .SetTotalDifficulty (ethutil .Big ("0" ))
172
+ bc .setTotalDifficulty (ethutil .Big ("0" ))
146
173
147
174
// Set the last know difficulty (might be 0x0 as initial value, Genesis)
148
- bc .TD = ethutil .BigD (ethutil .Config .Db .LastKnownTD ())
175
+ bc .td = ethutil .BigD (ethutil .Config .Db .LastKnownTD ())
149
176
}
150
177
151
178
func (self * ChainManager ) Export () []byte {
152
- chainlogger .Infoln ("exporting" , self .CurrentBlock .Number , "blocks" )
179
+ self .mu .RLock ()
180
+ defer self .mu .RUnlock ()
181
+
182
+ chainlogger .Infof ("exporting %v blocks...\n " , self .currentBlock .Number )
153
183
154
- blocks := make (types.Blocks , int (self .CurrentBlock .Number .Int64 ())+ 1 )
155
- for block := self .CurrentBlock ; block != nil ; block = self .GetBlock (block .PrevHash ) {
184
+ blocks := make ([] * types.Block , int (self .currentBlock .Number .Int64 ())+ 1 )
185
+ for block := self .currentBlock ; block != nil ; block = self .GetBlock (block .PrevHash ) {
156
186
blocks [block .Number .Int64 ()] = block
157
187
}
188
+
158
189
return ethutil .Encode (blocks )
159
190
}
160
191
161
192
func (bc * ChainManager ) insert (block * types.Block ) {
162
193
encodedBlock := block .RlpEncode ()
163
194
ethutil .Config .Db .Put ([]byte ("LastBlock" ), encodedBlock )
164
- bc .CurrentBlock = block
165
- bc .LastBlockHash = block .Hash ()
195
+ bc .currentBlock = block
196
+ bc .lastBlockHash = block .Hash ()
166
197
}
167
198
168
199
func (bc * ChainManager ) write (block * types.Block ) {
@@ -213,7 +244,10 @@ func (self *ChainManager) GetBlock(hash []byte) *types.Block {
213
244
}
214
245
215
246
func (self * ChainManager ) GetBlockByNumber (num uint64 ) * types.Block {
216
- block := self .CurrentBlock
247
+ self .mu .RLock ()
248
+ defer self .mu .RUnlock ()
249
+
250
+ block := self .currentBlock
217
251
for ; block != nil ; block = self .GetBlock (block .PrevHash ) {
218
252
if block .Number .Uint64 () == num {
219
253
break
@@ -227,9 +261,9 @@ func (self *ChainManager) GetBlockByNumber(num uint64) *types.Block {
227
261
return block
228
262
}
229
263
230
- func (bc * ChainManager ) SetTotalDifficulty (td * big.Int ) {
264
+ func (bc * ChainManager ) setTotalDifficulty (td * big.Int ) {
231
265
ethutil .Config .Db .Put ([]byte ("LTD" ), td .Bytes ())
232
- bc .TD = td
266
+ bc .td = td
233
267
}
234
268
235
269
func (self * ChainManager ) CalcTotalDiff (block * types.Block ) (* big.Int , error ) {
@@ -262,8 +296,8 @@ func (bc *ChainManager) BlockInfo(block *types.Block) types.BlockInfo {
262
296
263
297
// Unexported method for writing extra non-essential block info to the db
264
298
func (bc * ChainManager ) writeBlockInfo (block * types.Block ) {
265
- bc .LastBlockNumber ++
266
- bi := types.BlockInfo {Number : bc .LastBlockNumber , Hash : block .Hash (), Parent : block .PrevHash , TD : bc .TD }
299
+ bc .lastBlockNumber ++
300
+ bi := types.BlockInfo {Number : bc .lastBlockNumber , Hash : block .Hash (), Parent : block .PrevHash , TD : bc .td }
267
301
268
302
// For now we use the block hash with the words "info" appended as key
269
303
ethutil .Config .Db .Put (append (block .Hash (), []byte ("Info" )... ), bi .RlpEncode ())
@@ -289,17 +323,22 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
289
323
return err
290
324
}
291
325
292
- self .write (block )
293
- if td .Cmp (self .TD ) > 0 {
294
- if block .Number .Cmp (new (big.Int ).Add (self .CurrentBlock .Number , ethutil .Big1 )) < 0 {
295
- chainlogger .Infof ("Split detected. New head #%v (%x), was #%v (%x)\n " , block .Number , block .Hash ()[:4 ], self .CurrentBlock .Number , self .CurrentBlock .Hash ()[:4 ])
326
+ self .mu .Lock ()
327
+ {
328
+
329
+ self .write (block )
330
+ if td .Cmp (self .td ) > 0 {
331
+ if block .Number .Cmp (new (big.Int ).Add (self .currentBlock .Number , ethutil .Big1 )) < 0 {
332
+ chainlogger .Infof ("Split detected. New head #%v (%x), was #%v (%x)\n " , block .Number , block .Hash ()[:4 ], self .currentBlock .Number , self .currentBlock .Hash ()[:4 ])
333
+ }
334
+
335
+ self .setTotalDifficulty (td )
336
+ self .insert (block )
337
+ self .transState = self .currentBlock .State ().Copy ()
296
338
}
297
339
298
- self .SetTotalDifficulty (td )
299
- self .insert (block )
300
- self .transState = self .State ().Copy ()
301
- //sm.eth.TxPool().RemoveSet(block.Transactions())
302
340
}
341
+ self .mu .Unlock ()
303
342
304
343
self .eventMux .Post (NewBlockEvent {block })
305
344
self .eventMux .Post (messages )
0 commit comments