Merge pull request #1198 from fjl/core-fix-nonce-check
core: fix nonce verification one more time
This commit is contained in:
		@@ -7,4 +7,5 @@ var BadHashes = map[common.Hash]bool{
 | 
			
		||||
	common.HexToHash("f269c503aed286caaa0d114d6a5320e70abbc2febe37953207e76a2873f2ba79"): true,
 | 
			
		||||
	common.HexToHash("38f5bbbffd74804820ffa4bab0cd540e9de229725afb98c1a7e57936f4a714bc"): true,
 | 
			
		||||
	common.HexToHash("7064455b364775a16afbdecd75370e912c6e2879f202eda85b9beae547fff3ac"): true,
 | 
			
		||||
	common.HexToHash("5b7c80070a6eff35f3eb3181edb023465c776d40af2885571e1bc4689f3a44d8"): true,
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -551,12 +551,12 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
 | 
			
		||||
		bstart := time.Now()
 | 
			
		||||
		// Wait for block i's nonce to be verified before processing
 | 
			
		||||
		// its state transition.
 | 
			
		||||
		for nonceChecked[i] {
 | 
			
		||||
		for !nonceChecked[i] {
 | 
			
		||||
			r := <-nonceDone
 | 
			
		||||
			nonceChecked[r.i] = true
 | 
			
		||||
			if !r.valid {
 | 
			
		||||
				block := chain[i]
 | 
			
		||||
				return i, ValidationError("Block (#%v / %x) nonce is invalid (= %x)", block.Number(), block.Hash(), block.Nonce)
 | 
			
		||||
				block := chain[r.i]
 | 
			
		||||
				return r.i, &BlockNonceErr{Hash: block.Hash(), Number: block.Number(), Nonce: block.Nonce()}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@ package core
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"math/big"
 | 
			
		||||
	"math/rand"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"runtime"
 | 
			
		||||
@@ -426,3 +427,55 @@ func TestReorgShortest(t *testing.T) {
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestInsertNonceError(t *testing.T) {
 | 
			
		||||
	for i := 1; i < 25 && !t.Failed(); i++ {
 | 
			
		||||
		db, _ := ethdb.NewMemDatabase()
 | 
			
		||||
		genesis := GenesisBlock(db)
 | 
			
		||||
		bc := chm(genesis, db)
 | 
			
		||||
		bc.processor = NewBlockProcessor(db, db, bc.pow, bc, bc.eventMux)
 | 
			
		||||
		blocks := makeChain(bc.processor.(*BlockProcessor), bc.currentBlock, i, db, 0)
 | 
			
		||||
 | 
			
		||||
		fail := rand.Int() % len(blocks)
 | 
			
		||||
		failblock := blocks[fail]
 | 
			
		||||
		bc.pow = failpow{failblock.NumberU64()}
 | 
			
		||||
		n, err := bc.InsertChain(blocks)
 | 
			
		||||
 | 
			
		||||
		// Check that the returned error indicates the nonce failure.
 | 
			
		||||
		if n != fail {
 | 
			
		||||
			t.Errorf("(i=%d) wrong failed block index: got %d, want %d", i, n, fail)
 | 
			
		||||
		}
 | 
			
		||||
		if !IsBlockNonceErr(err) {
 | 
			
		||||
			t.Fatalf("(i=%d) got %q, want a nonce error", i, err)
 | 
			
		||||
		}
 | 
			
		||||
		nerr := err.(*BlockNonceErr)
 | 
			
		||||
		if nerr.Number.Cmp(failblock.Number()) != 0 {
 | 
			
		||||
			t.Errorf("(i=%d) wrong block number in error, got %v, want %v", i, nerr.Number, failblock.Number())
 | 
			
		||||
		}
 | 
			
		||||
		if nerr.Hash != failblock.Hash() {
 | 
			
		||||
			t.Errorf("(i=%d) wrong block hash in error, got %v, want %v", i, nerr.Hash, failblock.Hash())
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Check that all no blocks after the failing block have been inserted.
 | 
			
		||||
		for _, block := range blocks[fail:] {
 | 
			
		||||
			if bc.HasBlock(block.Hash()) {
 | 
			
		||||
				t.Errorf("(i=%d) invalid block %d present in chain", i, block.NumberU64())
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// failpow returns false from Verify for a certain block number.
 | 
			
		||||
type failpow struct{ num uint64 }
 | 
			
		||||
 | 
			
		||||
func (pow failpow) Search(pow.Block, <-chan struct{}) (nonce uint64, mixHash []byte) {
 | 
			
		||||
	return 0, nil
 | 
			
		||||
}
 | 
			
		||||
func (pow failpow) Verify(b pow.Block) bool {
 | 
			
		||||
	return b.NumberU64() != pow.num
 | 
			
		||||
}
 | 
			
		||||
func (pow failpow) GetHashrate() int64 {
 | 
			
		||||
	return 0
 | 
			
		||||
}
 | 
			
		||||
func (pow failpow) Turbo(bool) {
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -90,6 +90,23 @@ func IsNonceErr(err error) bool {
 | 
			
		||||
	return ok
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BlockNonceErr indicates that a block's nonce is invalid.
 | 
			
		||||
type BlockNonceErr struct {
 | 
			
		||||
	Number *big.Int
 | 
			
		||||
	Hash   common.Hash
 | 
			
		||||
	Nonce  uint64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (err *BlockNonceErr) Error() string {
 | 
			
		||||
	return fmt.Sprintf("block %d (%v) nonce is invalid (got %d)", err.Number, err.Hash, err.Nonce)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsBlockNonceErr returns true for invalid block nonce errors.
 | 
			
		||||
func IsBlockNonceErr(err error) bool {
 | 
			
		||||
	_, ok := err.(*BlockNonceErr)
 | 
			
		||||
	return ok
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type InvalidTxErr struct {
 | 
			
		||||
	Message string
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user