@@ -44,16 +44,18 @@ import (
44
44
type BlockTest struct {
45
45
Genesis * types.Block
46
46
47
- Json * btJSON
48
- preAccounts map [string ]btAccount
49
- postAccounts map [string ]btAccount
47
+ Json * btJSON
48
+ preAccounts map [string ]btAccount
49
+ postAccounts map [string ]btAccount
50
+ lastblockhash string
50
51
}
51
52
52
53
type btJSON struct {
53
54
Blocks []btBlock
54
55
GenesisBlockHeader btHeader
55
56
Pre map [string ]btAccount
56
57
PostState map [string ]btAccount
58
+ Lastblockhash string
57
59
}
58
60
59
61
type btBlock struct {
@@ -77,6 +79,7 @@ type btHeader struct {
77
79
MixHash string
78
80
Nonce string
79
81
Number string
82
+ Hash string
80
83
ParentHash string
81
84
ReceiptTrie string
82
85
SeedHash string
@@ -178,16 +181,24 @@ func runBlockTest(test *BlockTest) error {
178
181
return fmt .Errorf ("InsertPreState: %v" , err )
179
182
}
180
183
181
- err = test .TryBlocksInsert (ethereum .ChainManager ())
184
+ cm := ethereum .ChainManager ()
185
+ validBlocks , err := test .TryBlocksInsert (cm )
182
186
if err != nil {
183
187
return err
184
188
}
185
189
186
- newDB := ethereum .ChainManager ().State ()
190
+ lastblockhash := common .HexToHash (test .lastblockhash )
191
+ cmlast := cm .LastBlockHash ()
192
+ if lastblockhash != cmlast {
193
+ return fmt .Errorf ("lastblockhash validation mismatch: want: %x, have: %x" , lastblockhash , cmlast )
194
+ }
195
+
196
+ newDB := cm .State ()
187
197
if err = test .ValidatePostState (newDB ); err != nil {
188
198
return fmt .Errorf ("post state validation failed: %v" , err )
189
199
}
190
- return nil
200
+
201
+ return test .ValidateImportedHeaders (cm , validBlocks )
191
202
}
192
203
193
204
func (test * BlockTest ) makeEthConfig () * eth.Config {
@@ -265,16 +276,16 @@ func (t *BlockTest) InsertPreState(ethereum *eth.Ethereum) (*state.StateDB, erro
265
276
expected we are expected to ignore it and continue processing and then validate the
266
277
post state.
267
278
*/
268
- func (t * BlockTest ) TryBlocksInsert (chainManager * core.ChainManager ) error {
269
- blockNums := make (map [ string ] bool )
279
+ func (t * BlockTest ) TryBlocksInsert (chainManager * core.ChainManager ) ([] btBlock , error ) {
280
+ validBlocks := make ([] btBlock , 0 )
270
281
// insert the test blocks, which will execute all transactions
271
282
for _ , b := range t .Json .Blocks {
272
283
cb , err := mustConvertBlock (b )
273
284
if err != nil {
274
285
if b .BlockHeader == nil {
275
286
continue // OK - block is supposed to be invalid, continue with next block
276
287
} else {
277
- return fmt .Errorf ("Block RLP decoding failed when expected to succeed: %v" , err )
288
+ return nil , fmt .Errorf ("Block RLP decoding failed when expected to succeed: %v" , err )
278
289
}
279
290
}
280
291
// RLP decoding worked, try to insert into chain:
@@ -283,47 +294,23 @@ func (t *BlockTest) TryBlocksInsert(chainManager *core.ChainManager) error {
283
294
if b .BlockHeader == nil {
284
295
continue // OK - block is supposed to be invalid, continue with next block
285
296
} else {
286
- return fmt .Errorf ("Block insertion into chain failed: %v" , err )
297
+ return nil , fmt .Errorf ("Block insertion into chain failed: %v" , err )
287
298
}
288
299
}
289
300
if b .BlockHeader == nil {
290
- return fmt .Errorf ("Block insertion should have failed" )
301
+ return nil , fmt .Errorf ("Block insertion should have failed" )
291
302
}
292
303
293
304
// validate RLP decoding by checking all values against test file JSON
294
- if err = t .validateBlockHeader (b .BlockHeader , cb .Header ()); err != nil {
295
- return fmt .Errorf ("Deserialised block header validation failed: %v" , err )
296
- }
297
-
298
- // validate the imported header against test file JSON
299
-
300
- /*
301
- TODO: currently test files do not contain information on what
302
- reorg is expected other than possibly the post state (which may
303
- or may not depend on a specific chain).
304
-
305
- discussed with winswega and it was agreed to add this information
306
- to the test files explicitly.
307
-
308
- meanwhile we skip header validation on blocks with the same block
309
- number as a prior block, since this test code cannot know what
310
- blocks are in the longest chain without making use of the very
311
- protocol rules the tests verify or rely on the correctness of the
312
- code that is being tested.
313
-
314
- */
315
- if ! blockNums [b .BlockHeader .Number ] {
316
- importedBlock := chainManager .CurrentBlock ()
317
- if err = t .validateBlockHeader (b .BlockHeader , importedBlock .Header ()); err != nil {
318
- return fmt .Errorf ("Imported block header validation failed: %v" , err )
319
- }
320
- blockNums [b .BlockHeader .Number ] = true
305
+ if err = validateHeader (b .BlockHeader , cb .Header ()); err != nil {
306
+ return nil , fmt .Errorf ("Deserialised block header validation failed: %v" , err )
321
307
}
308
+ validBlocks = append (validBlocks , b )
322
309
}
323
- return nil
310
+ return validBlocks , nil
324
311
}
325
312
326
- func ( s * BlockTest ) validateBlockHeader (h * btHeader , h2 * types.Header ) error {
313
+ func validateHeader (h * btHeader , h2 * types.Header ) error {
327
314
expectedBloom := mustConvertBytes (h .Bloom )
328
315
if ! bytes .Equal (expectedBloom , h2 .Bloom .Bytes ()) {
329
316
return fmt .Errorf ("Bloom: want: %x have: %x" , expectedBloom , h2 .Bloom .Bytes ())
@@ -439,6 +426,27 @@ func (t *BlockTest) ValidatePostState(statedb *state.StateDB) error {
439
426
return nil
440
427
}
441
428
429
+ func (test * BlockTest ) ValidateImportedHeaders (cm * core.ChainManager , validBlocks []btBlock ) error {
430
+ // to get constant lookup when verifying block headers by hash (some tests have many blocks)
431
+ bmap := make (map [string ]btBlock , len (test .Json .Blocks ))
432
+ for _ , b := range validBlocks {
433
+ bmap [b .BlockHeader .Hash ] = b
434
+ }
435
+
436
+ // iterate over blocks backwards from HEAD and validate imported
437
+ // headers vs test file. some tests have reorgs, and we import
438
+ // block-by-block, so we can only validate imported headers after
439
+ // all blocks have been processed by ChainManager, as they may not
440
+ // be part of the longest chain until last block is imported.
441
+ for b := cm .CurrentBlock (); b != nil && b .NumberU64 () != 0 ; b = cm .GetBlock (b .Header ().ParentHash ) {
442
+ bHash := common .Bytes2Hex (b .Hash ().Bytes ()) // hex without 0x prefix
443
+ if err := validateHeader (bmap [bHash ].BlockHeader , b .Header ()); err != nil {
444
+ return fmt .Errorf ("Imported block header validation failed: %v" , err )
445
+ }
446
+ }
447
+ return nil
448
+ }
449
+
442
450
func convertBlockTests (in map [string ]* btJSON ) (map [string ]* BlockTest , error ) {
443
451
out := make (map [string ]* BlockTest )
444
452
for name , test := range in {
@@ -461,7 +469,7 @@ func convertBlockTest(in *btJSON) (out *BlockTest, err error) {
461
469
err = fmt .Errorf ("%v\n %s" , recovered , buf )
462
470
}
463
471
}()
464
- out = & BlockTest {preAccounts : in .Pre , postAccounts : in .PostState , Json : in }
472
+ out = & BlockTest {preAccounts : in .Pre , postAccounts : in .PostState , Json : in , lastblockhash : in . Lastblockhash }
465
473
out .Genesis = mustConvertGenesis (in .GenesisBlockHeader )
466
474
return out , err
467
475
}
0 commit comments