Skip to content

Commit 49e0267

Browse files
committed
Locks, refactor, tests
* Added additional chain tests * Added proper mutex' on chain * Removed ethereum dependencies
1 parent 590aace commit 49e0267

File tree

12 files changed

+168
-66
lines changed

12 files changed

+168
-66
lines changed

_data/chain1

171 KB
Binary file not shown.

_data/chain2

27.5 KB
Binary file not shown.

core/block_manager.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -256,12 +256,12 @@ func (sm *BlockManager) CalculateTD(block *types.Block) (*big.Int, bool) {
256256

257257
// TD(genesis_block) = 0 and TD(B) = TD(B.parent) + sum(u.difficulty for u in B.uncles) + B.difficulty
258258
td := new(big.Int)
259-
td = td.Add(sm.bc.TD, uncleDiff)
259+
td = td.Add(sm.bc.Td(), uncleDiff)
260260
td = td.Add(td, block.Difficulty)
261261

262262
// The new TD will only be accepted if the new difficulty is
263263
// is greater than the previous.
264-
if td.Cmp(sm.bc.TD) > 0 {
264+
if td.Cmp(sm.bc.Td()) > 0 {
265265
return td, true
266266
}
267267

@@ -279,7 +279,7 @@ func (sm *BlockManager) ValidateBlock(block, parent *types.Block) error {
279279

280280
diff := block.Time - parent.Time
281281
if diff < 0 {
282-
return ValidationError("Block timestamp less then prev block %v (%v - %v)", diff, block.Time, sm.bc.CurrentBlock.Time)
282+
return ValidationError("Block timestamp less then prev block %v (%v - %v)", diff, block.Time, sm.bc.CurrentBlock().Time)
283283
}
284284

285285
/* XXX

core/chain_manager.go

Lines changed: 76 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package core
33
import (
44
"fmt"
55
"math/big"
6+
"sync"
67

78
"github.com/ethereum/go-ethereum/core/types"
89
"github.com/ethereum/go-ethereum/ethutil"
@@ -50,14 +51,34 @@ type ChainManager struct {
5051
eventMux *event.TypeMux
5152
genesisBlock *types.Block
5253
// 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
5459

55-
LastBlockNumber uint64
60+
transState *state.StateDB
61+
}
5662

57-
CurrentBlock *types.Block
58-
LastBlockHash []byte
63+
func (self *ChainManager) Td() *big.Int {
64+
self.mu.RLock()
65+
defer self.mu.RUnlock()
5966

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
6182
}
6283

6384
func NewChainManager(mux *event.TypeMux) *ChainManager {
@@ -77,7 +98,7 @@ func (self *ChainManager) SetProcessor(proc types.BlockProcessor) {
7798
}
7899

79100
func (self *ChainManager) State() *state.StateDB {
80-
return self.CurrentBlock.State()
101+
return self.CurrentBlock().State()
81102
}
82103

83104
func (self *ChainManager) TransState() *state.StateDB {
@@ -91,27 +112,30 @@ func (bc *ChainManager) setLastBlock() {
91112
AddTestNetFunds(bc.genesisBlock)
92113

93114
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()
97118

98119
// 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())
100121
} else {
101122
bc.Reset()
102123
}
103124

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())
105126
}
106127

107128
// Block creation & chain handling
108129
func (bc *ChainManager) NewBlock(coinbase []byte) *types.Block {
130+
bc.mu.RLock()
131+
defer bc.mu.RUnlock()
132+
109133
var root interface{}
110134
hash := ZeroHash256
111135

112136
if bc.CurrentBlock != nil {
113-
root = bc.CurrentBlock.Root()
114-
hash = bc.LastBlockHash
137+
root = bc.currentBlock.Root()
138+
hash = bc.lastBlockHash
115139
}
116140

117141
block := types.CreateBlock(
@@ -122,47 +146,54 @@ func (bc *ChainManager) NewBlock(coinbase []byte) *types.Block {
122146
nil,
123147
"")
124148

125-
parent := bc.CurrentBlock
149+
parent := bc.currentBlock
126150
if parent != nil {
127151
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)
130154

131155
}
132156

133157
return block
134158
}
135159

136160
func (bc *ChainManager) Reset() {
161+
bc.mu.Lock()
162+
defer bc.mu.Unlock()
163+
137164
AddTestNetFunds(bc.genesisBlock)
138165

139166
bc.genesisBlock.Trie().Sync()
140167
// Prepare the genesis block
141168
bc.write(bc.genesisBlock)
142169
bc.insert(bc.genesisBlock)
143-
bc.CurrentBlock = bc.genesisBlock
170+
bc.currentBlock = bc.genesisBlock
144171

145-
bc.SetTotalDifficulty(ethutil.Big("0"))
172+
bc.setTotalDifficulty(ethutil.Big("0"))
146173

147174
// 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())
149176
}
150177

151178
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)
153183

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) {
156186
blocks[block.Number.Int64()] = block
157187
}
188+
158189
return ethutil.Encode(blocks)
159190
}
160191

161192
func (bc *ChainManager) insert(block *types.Block) {
162193
encodedBlock := block.RlpEncode()
163194
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()
166197
}
167198

168199
func (bc *ChainManager) write(block *types.Block) {
@@ -213,7 +244,10 @@ func (self *ChainManager) GetBlock(hash []byte) *types.Block {
213244
}
214245

215246
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
217251
for ; block != nil; block = self.GetBlock(block.PrevHash) {
218252
if block.Number.Uint64() == num {
219253
break
@@ -227,9 +261,9 @@ func (self *ChainManager) GetBlockByNumber(num uint64) *types.Block {
227261
return block
228262
}
229263

230-
func (bc *ChainManager) SetTotalDifficulty(td *big.Int) {
264+
func (bc *ChainManager) setTotalDifficulty(td *big.Int) {
231265
ethutil.Config.Db.Put([]byte("LTD"), td.Bytes())
232-
bc.TD = td
266+
bc.td = td
233267
}
234268

235269
func (self *ChainManager) CalcTotalDiff(block *types.Block) (*big.Int, error) {
@@ -262,8 +296,8 @@ func (bc *ChainManager) BlockInfo(block *types.Block) types.BlockInfo {
262296

263297
// Unexported method for writing extra non-essential block info to the db
264298
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}
267301

268302
// For now we use the block hash with the words "info" appended as key
269303
ethutil.Config.Db.Put(append(block.Hash(), []byte("Info")...), bi.RlpEncode())
@@ -289,17 +323,22 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
289323
return err
290324
}
291325

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()
296338
}
297339

298-
self.SetTotalDifficulty(td)
299-
self.insert(block)
300-
self.transState = self.State().Copy()
301-
//sm.eth.TxPool().RemoveSet(block.Transactions())
302340
}
341+
self.mu.Unlock()
303342

304343
self.eventMux.Post(NewBlockEvent{block})
305344
self.eventMux.Post(messages)

core/chain_manager_test.go

Lines changed: 62 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,75 @@ package core
33
import (
44
"fmt"
55
"path"
6+
"runtime"
67
"testing"
78

9+
"github.com/ethereum/go-ethereum/core/types"
10+
"github.com/ethereum/go-ethereum/ethdb"
811
"github.com/ethereum/go-ethereum/ethutil"
12+
"github.com/ethereum/go-ethereum/event"
13+
//logpkg "github.com/ethereum/go-ethereum/logger"
914
)
1015

11-
func TestChainInsertions(t *testing.T) {
12-
c1, err := ethutil.ReadAllFile(path.Join("..", "_data", "chain1"))
16+
//var Logger logpkg.LogSystem
17+
//var Log = logpkg.NewLogger("TEST")
18+
19+
func init() {
20+
runtime.GOMAXPROCS(runtime.NumCPU())
21+
//Logger = logpkg.NewStdLogSystem(os.Stdout, log.LstdFlags, logpkg.InfoLevel)
22+
//logpkg.AddLogSystem(Logger)
23+
24+
ethutil.ReadConfig("/tmp/ethtest", "/tmp/ethtest", "ETH")
25+
26+
db, err := ethdb.NewMemDatabase()
27+
if err != nil {
28+
panic("Could not create mem-db, failing")
29+
}
30+
ethutil.Config.Db = db
31+
}
32+
33+
func loadChain(fn string, t *testing.T) types.Blocks {
34+
c1, err := ethutil.ReadAllFile(path.Join("..", "_data", fn))
1335
if err != nil {
1436
fmt.Println(err)
1537
t.FailNow()
1638
}
17-
data1, _ := ethutil.Decode([]byte(c1), 0)
18-
fmt.Println(data1)
39+
value := ethutil.NewValueFromBytes([]byte(c1))
40+
blocks := make(types.Blocks, value.Len())
41+
it := value.NewIterator()
42+
for it.Next() {
43+
blocks[it.Idx()] = types.NewBlockFromRlpValue(it.Value())
44+
}
45+
46+
return blocks
47+
}
48+
49+
func insertChain(done chan bool, chainMan *ChainManager, chain types.Blocks, t *testing.T) {
50+
err := chainMan.InsertChain(chain)
51+
if err != nil {
52+
fmt.Println(err)
53+
t.FailNow()
54+
}
55+
done <- true
56+
}
57+
58+
func TestChainInsertions(t *testing.T) {
59+
chain1 := loadChain("chain1", t)
60+
chain2 := loadChain("chain2", t)
61+
var eventMux event.TypeMux
62+
chainMan := NewChainManager(&eventMux)
63+
txPool := NewTxPool(chainMan, nil, &eventMux)
64+
blockMan := NewBlockManager(txPool, chainMan, &eventMux)
65+
chainMan.SetProcessor(blockMan)
66+
67+
const max = 2
68+
done := make(chan bool, max)
69+
70+
go insertChain(done, chainMan, chain1, t)
71+
go insertChain(done, chainMan, chain2, t)
72+
73+
for i := 0; i < max; i++ {
74+
<-done
75+
}
76+
fmt.Println(chainMan.CurrentBlock())
1977
}

core/filter.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,11 @@ func (self *Filter) SetSkip(skip int) {
7878
func (self *Filter) Find() []*state.Message {
7979
var earliestBlockNo uint64 = uint64(self.earliest)
8080
if self.earliest == -1 {
81-
earliestBlockNo = self.eth.ChainManager().CurrentBlock.Number.Uint64()
81+
earliestBlockNo = self.eth.ChainManager().CurrentBlock().Number.Uint64()
8282
}
8383
var latestBlockNo uint64 = uint64(self.latest)
8484
if self.latest == -1 {
85-
latestBlockNo = self.eth.ChainManager().CurrentBlock.Number.Uint64()
85+
latestBlockNo = self.eth.ChainManager().CurrentBlock().Number.Uint64()
8686
}
8787

8888
var (

core/filter_test.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1 @@
11
package core
2-
3-
// import "testing"
4-
5-
// func TestFilter(t *testing.T) {
6-
// NewFilter(NewTestManager())
7-
// }

0 commit comments

Comments
 (0)