@@ -368,36 +368,63 @@ func generateWitness(blockchain *core.BlockChain, block *types.Block) (*stateles
368
368
if err := blockchain .Validator ().ValidateState (block , statedb , receipts , usedGas ); err != nil {
369
369
return nil , fmt .Errorf ("failed to validate block %d: %w" , block .Number (), err )
370
370
}
371
- return witness , testWitness (blockchain , block , witness )
371
+
372
+ // FIXME: testWitness will fail from time to time, the problem is caused by occasional state root mismatch
373
+ // after processing the block based on witness. We need to investigate the root cause and fix it.
374
+ for retries := 0 ; retries < 5 ; retries ++ {
375
+ if err = testWitness (blockchain , block , witness ); err == nil {
376
+ return witness , nil
377
+ } else {
378
+ log .Warn ("Failed to validate witness" , "block" , block .Number (), "error" , err )
379
+ }
380
+ }
381
+ return witness , err
372
382
}
373
383
374
384
func testWitness (blockchain * core.BlockChain , block * types.Block , witness * stateless.Witness ) error {
375
385
stateRoot := witness .Root ()
376
- if diskRoot , _ := rawdb .ReadDiskStateRoot (blockchain .Database (), stateRoot ); diskRoot != (common.Hash {}) {
386
+ diskRoot , err := rawdb .ReadDiskStateRoot (blockchain .Database (), stateRoot )
387
+ if err != nil {
388
+ return fmt .Errorf ("failed to read disk state root for stateRoot %s: %w" , stateRoot .Hex (), err )
389
+ }
390
+ if diskRoot != (common.Hash {}) {
391
+ log .Debug ("Using disk root for state root" , "stateRoot" , stateRoot .Hex (), "diskRoot" , diskRoot .Hex ())
377
392
stateRoot = diskRoot
378
393
}
379
394
380
395
// Create and populate the state database to serve as the stateless backend
381
396
statedb , err := state .New (stateRoot , state .NewDatabase (witness .MakeHashDB ()), nil )
382
397
if err != nil {
383
- return fmt .Errorf ("failed to create state database: %w" , err )
398
+ return fmt .Errorf ("failed to create state database with stateRoot %s : %w" , stateRoot . Hex () , err )
384
399
}
385
400
386
401
receipts , _ , usedGas , err := blockchain .Processor ().Process (block , statedb , * blockchain .GetVMConfig ())
387
402
if err != nil {
388
- return fmt .Errorf ("failed to process block %d: %w" , block .Number (), err )
403
+ return fmt .Errorf ("failed to process block %d (hash : %s): % w" , block .Number (), block . Hash (). Hex (), err )
389
404
}
390
405
391
406
if err := blockchain .Validator ().ValidateState (block , statedb , receipts , usedGas ); err != nil {
392
- return fmt .Errorf ("failed to validate block %d: %w" , block .Number (), err )
407
+ return fmt .Errorf ("failed to validate block %d (hash : %s): % w" , block .Number (), block . Hash (). Hex (), err )
393
408
}
394
409
395
410
postStateRoot := block .Root ()
396
- if diskRoot , _ := rawdb .ReadDiskStateRoot (blockchain .Database (), postStateRoot ); diskRoot != (common.Hash {}) {
411
+ diskRoot , err = rawdb .ReadDiskStateRoot (blockchain .Database (), postStateRoot )
412
+ if err != nil {
413
+ return fmt .Errorf ("failed to read disk state root for postStateRoot %s: %w" , postStateRoot .Hex (), err )
414
+ }
415
+ if diskRoot != (common.Hash {}) {
416
+ log .Debug ("Using disk root for post state root" , "postStateRoot" , postStateRoot .Hex (), "diskRoot" , diskRoot .Hex ())
397
417
postStateRoot = diskRoot
398
418
}
399
- if statedb .GetRootHash () != postStateRoot {
400
- return fmt .Errorf ("failed to commit statelessly %d: %w" , block .Number (), err )
419
+ computedRoot := statedb .GetRootHash ()
420
+ if computedRoot != postStateRoot {
421
+ log .Debug ("State root mismatch" , "block" , block .Number (), "expected" , postStateRoot .Hex (), "got" , computedRoot )
422
+ executionWitness := ToExecutionWitness (witness )
423
+ jsonStr , err := json .Marshal (executionWitness )
424
+ if err != nil {
425
+ return fmt .Errorf ("state root mismatch after processing block %d (hash: %s): expected %s, got %s, but failed to marshal witness: %w" , block .Number (), block .Hash ().Hex (), postStateRoot .Hex (), computedRoot , err )
426
+ }
427
+ return fmt .Errorf ("state root mismatch after processing block %d (hash: %s): expected %s, got %s, witness: %s" , block .Number (), block .Hash ().Hex (), postStateRoot .Hex (), computedRoot , string (jsonStr ))
401
428
}
402
429
return nil
403
430
}
0 commit comments