@@ -18,9 +18,11 @@ package miner
1818
1919import (
2020 "math/big"
21+ "math/rand"
2122 "testing"
2223 "time"
2324
25+ "github.com/ethereum/go-ethereum/accounts"
2426 "github.com/ethereum/go-ethereum/common"
2527 "github.com/ethereum/go-ethereum/consensus"
2628 "github.com/ethereum/go-ethereum/consensus/clique"
@@ -35,6 +37,15 @@ import (
3537 "github.com/ethereum/go-ethereum/params"
3638)
3739
40+ const (
41+ // testCode is the testing contract binary code which will initialises some
42+ // variables in constructor
43+ testCode = "0x60806040527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0060005534801561003457600080fd5b5060fc806100436000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c80630c4dae8814603757806398a213cf146053575b600080fd5b603d607e565b6040518082815260200191505060405180910390f35b607c60048036036020811015606757600080fd5b81019080803590602001909291905050506084565b005b60005481565b806000819055507fe9e44f9f7da8c559de847a3232b57364adc0354f15a2cd8dc636d54396f9587a6000546040518082815260200191505060405180910390a15056fea265627a7a723058208ae31d9424f2d0bc2a3da1a5dd659db2d71ec322a17db8f87e19e209e3a1ff4a64736f6c634300050a0032"
44+
45+ // testGas is the gas required for contract deployment.
46+ testGas = 144109
47+ )
48+
3849var (
3950 // Test chain configurations
4051 testTxPoolConfig core.TxPoolConfig
@@ -81,29 +92,30 @@ type testWorkerBackend struct {
8192 txPool * core.TxPool
8293 chain * core.BlockChain
8394 testTxFeed event.Feed
95+ genesis * core.Genesis
8496 uncleBlock * types.Block
8597}
8698
87- func newTestWorkerBackend (t * testing.T , chainConfig * params.ChainConfig , engine consensus.Engine , n int ) * testWorkerBackend {
88- var (
89- db = rawdb .NewMemoryDatabase ()
90- gspec = core.Genesis {
91- Config : chainConfig ,
92- Alloc : core.GenesisAlloc {testBankAddress : {Balance : testBankFunds }},
93- }
94- )
99+ func newTestWorkerBackend (t * testing.T , chainConfig * params.ChainConfig , engine consensus.Engine , db ethdb.Database , n int ) * testWorkerBackend {
100+ var gspec = core.Genesis {
101+ Config : chainConfig ,
102+ Alloc : core.GenesisAlloc {testBankAddress : {Balance : testBankFunds }},
103+ }
95104
96- switch engine .(type ) {
105+ switch e := engine .(type ) {
97106 case * clique.Clique :
98107 gspec .ExtraData = make ([]byte , 32 + common .AddressLength + crypto .SignatureLength )
99- copy (gspec .ExtraData [32 :], testBankAddress [:])
108+ copy (gspec .ExtraData [32 :32 + common .AddressLength ], testBankAddress .Bytes ())
109+ e .Authorize (testBankAddress , func (account accounts.Account , s string , data []byte ) ([]byte , error ) {
110+ return crypto .Sign (crypto .Keccak256 (data ), testBankKey )
111+ })
100112 case * ethash.Ethash :
101113 default :
102114 t .Fatalf ("unexpected consensus engine type: %T" , engine )
103115 }
104116 genesis := gspec .MustCommit (db )
105117
106- chain , _ := core .NewBlockChain (db , nil , gspec .Config , engine , vm.Config {}, nil )
118+ chain , _ := core .NewBlockChain (db , & core. CacheConfig { TrieDirtyDisabled : true } , gspec .Config , engine , vm.Config {}, nil )
107119 txpool := core .NewTxPool (testTxPoolConfig , chainConfig , chain )
108120
109121 // Generate a small n-block chain and an uncle block for it
@@ -127,6 +139,7 @@ func newTestWorkerBackend(t *testing.T, chainConfig *params.ChainConfig, engine
127139 db : db ,
128140 chain : chain ,
129141 txPool : txpool ,
142+ genesis : & gspec ,
130143 uncleBlock : blocks [0 ],
131144 }
132145}
@@ -137,14 +150,123 @@ func (b *testWorkerBackend) PostChainEvents(events []interface{}) {
137150 b .chain .PostChainEvents (events , nil )
138151}
139152
140- func newTestWorker (t * testing.T , chainConfig * params.ChainConfig , engine consensus.Engine , blocks int ) (* worker , * testWorkerBackend ) {
141- backend := newTestWorkerBackend (t , chainConfig , engine , blocks )
153+ func (b * testWorkerBackend ) newRandomUncle () * types.Block {
154+ var parent * types.Block
155+ cur := b .chain .CurrentBlock ()
156+ if cur .NumberU64 () == 0 {
157+ parent = b .chain .Genesis ()
158+ } else {
159+ parent = b .chain .GetBlockByHash (b .chain .CurrentBlock ().ParentHash ())
160+ }
161+ blocks , _ := core .GenerateChain (b .chain .Config (), parent , b .chain .Engine (), b .db , 1 , func (i int , gen * core.BlockGen ) {
162+ var addr common.Address
163+ rand .Read (addr .Bytes ())
164+ gen .SetCoinbase (addr )
165+ })
166+ return blocks [0 ]
167+ }
168+
169+ func (b * testWorkerBackend ) newRandomTx (creation bool ) * types.Transaction {
170+ var tx * types.Transaction
171+ if creation {
172+ tx , _ = types .SignTx (types .NewContractCreation (b .txPool .Nonce (testBankAddress ), big .NewInt (0 ), testGas , nil , common .FromHex (testCode )), types.HomesteadSigner {}, testBankKey )
173+ } else {
174+ tx , _ = types .SignTx (types .NewTransaction (b .txPool .Nonce (testBankAddress ), testUserAddress , big .NewInt (1000 ), params .TxGas , nil , nil ), types.HomesteadSigner {}, testBankKey )
175+ }
176+ return tx
177+ }
178+
179+ func newTestWorker (t * testing.T , chainConfig * params.ChainConfig , engine consensus.Engine , db ethdb.Database , blocks int ) (* worker , * testWorkerBackend ) {
180+ backend := newTestWorkerBackend (t , chainConfig , engine , db , blocks )
142181 backend .txPool .AddLocals (pendingTxs )
143182 w := newWorker (testConfig , chainConfig , engine , backend , new (event.TypeMux ), nil )
144183 w .setEtherbase (testBankAddress )
145184 return w , backend
146185}
147186
187+ func TestGenerateBlockAndImportEthash (t * testing.T ) {
188+ testGenerateBlockAndImport (t , false )
189+ }
190+
191+ func TestGenerateBlockAndImportClique (t * testing.T ) {
192+ testGenerateBlockAndImport (t , true )
193+ }
194+
195+ func testGenerateBlockAndImport (t * testing.T , isClique bool ) {
196+ var (
197+ engine consensus.Engine
198+ chainConfig * params.ChainConfig
199+ db = rawdb .NewMemoryDatabase ()
200+ )
201+ if isClique {
202+ chainConfig = params .AllCliqueProtocolChanges
203+ engine = clique .New (chainConfig .Clique , db )
204+ } else {
205+ chainConfig = params .AllEthashProtocolChanges
206+ engine = ethash .NewFaker ()
207+ }
208+
209+ w , b := newTestWorker (t , chainConfig , engine , db , 0 )
210+ defer w .close ()
211+
212+ db2 := rawdb .NewMemoryDatabase ()
213+ b .genesis .MustCommit (db2 )
214+ chain , _ := core .NewBlockChain (db2 , nil , b .chain .Config (), engine , vm.Config {}, nil )
215+ defer chain .Stop ()
216+
217+ newBlock := make (chan struct {})
218+ listenNewBlock := func () {
219+ sub := w .mux .Subscribe (core.NewMinedBlockEvent {})
220+ defer sub .Unsubscribe ()
221+
222+ for item := range sub .Chan () {
223+ block := item .Data .(core.NewMinedBlockEvent ).Block
224+ _ , err := chain .InsertChain ([]* types.Block {block })
225+ if err != nil {
226+ t .Fatalf ("Failed to insert new mined block:%d, error:%v" , block .NumberU64 (), err )
227+ }
228+ newBlock <- struct {}{}
229+ }
230+ }
231+
232+ // Ensure worker has finished initialization
233+ for {
234+ b := w .pendingBlock ()
235+ if b != nil && b .NumberU64 () == 1 {
236+ break
237+ }
238+ }
239+ w .start () // Start mining!
240+
241+ // Ignore first 2 commits caused by start operation
242+ ignored := make (chan struct {}, 2 )
243+ w .skipSealHook = func (task * task ) bool {
244+ ignored <- struct {}{}
245+ return true
246+ }
247+ for i := 0 ; i < 2 ; i ++ {
248+ <- ignored
249+ }
250+
251+ go listenNewBlock ()
252+
253+ // Ignore empty commit here for less noise
254+ w .skipSealHook = func (task * task ) bool {
255+ return len (task .receipts ) == 0
256+ }
257+ for i := 0 ; i < 50 ; i ++ {
258+ b .txPool .AddLocal (b .newRandomTx (true ))
259+ b .txPool .AddLocal (b .newRandomTx (false ))
260+ b .PostChainEvents ([]interface {}{core.ChainSideEvent {Block : b .newRandomUncle ()}})
261+ b .PostChainEvents ([]interface {}{core.ChainSideEvent {Block : b .newRandomUncle ()}})
262+ select {
263+ case <- newBlock :
264+ case <- time .NewTimer (time .Millisecond * 1500 ).C : // Worker needs 1s to include new changes.
265+ t .Fatalf ("timeout" )
266+ }
267+ }
268+ }
269+
148270func TestPendingStateAndBlockEthash (t * testing.T ) {
149271 testPendingStateAndBlock (t , ethashChainConfig , ethash .NewFaker ())
150272}
@@ -155,7 +277,7 @@ func TestPendingStateAndBlockClique(t *testing.T) {
155277func testPendingStateAndBlock (t * testing.T , chainConfig * params.ChainConfig , engine consensus.Engine ) {
156278 defer engine .Close ()
157279
158- w , b := newTestWorker (t , chainConfig , engine , 0 )
280+ w , b := newTestWorker (t , chainConfig , engine , rawdb . NewMemoryDatabase (), 0 )
159281 defer w .close ()
160282
161283 // Ensure snapshot has been updated.
@@ -187,7 +309,7 @@ func TestEmptyWorkClique(t *testing.T) {
187309func testEmptyWork (t * testing.T , chainConfig * params.ChainConfig , engine consensus.Engine ) {
188310 defer engine .Close ()
189311
190- w , _ := newTestWorker (t , chainConfig , engine , 0 )
312+ w , _ := newTestWorker (t , chainConfig , engine , rawdb . NewMemoryDatabase (), 0 )
191313 defer w .close ()
192314
193315 var (
@@ -241,7 +363,7 @@ func TestStreamUncleBlock(t *testing.T) {
241363 ethash := ethash .NewFaker ()
242364 defer ethash .Close ()
243365
244- w , b := newTestWorker (t , ethashChainConfig , ethash , 1 )
366+ w , b := newTestWorker (t , ethashChainConfig , ethash , rawdb . NewMemoryDatabase (), 1 )
245367 defer w .close ()
246368
247369 var taskCh = make (chan struct {})
@@ -304,7 +426,7 @@ func TestRegenerateMiningBlockClique(t *testing.T) {
304426func testRegenerateMiningBlock (t * testing.T , chainConfig * params.ChainConfig , engine consensus.Engine ) {
305427 defer engine .Close ()
306428
307- w , b := newTestWorker (t , chainConfig , engine , 0 )
429+ w , b := newTestWorker (t , chainConfig , engine , rawdb . NewMemoryDatabase (), 0 )
308430 defer w .close ()
309431
310432 var taskCh = make (chan struct {})
@@ -369,7 +491,7 @@ func TestAdjustIntervalClique(t *testing.T) {
369491func testAdjustInterval (t * testing.T , chainConfig * params.ChainConfig , engine consensus.Engine ) {
370492 defer engine .Close ()
371493
372- w , _ := newTestWorker (t , chainConfig , engine , 0 )
494+ w , _ := newTestWorker (t , chainConfig , engine , rawdb . NewMemoryDatabase (), 0 )
373495 defer w .close ()
374496
375497 w .skipSealHook = func (task * task ) bool {
0 commit comments