core: fix the nonce check one more time
The block nonce verification was effectively disabled by a typo. This time, there is an actual test for it.
This commit is contained in:
		| @@ -551,12 +551,12 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) { | |||||||
| 		bstart := time.Now() | 		bstart := time.Now() | ||||||
| 		// Wait for block i's nonce to be verified before processing | 		// Wait for block i's nonce to be verified before processing | ||||||
| 		// its state transition. | 		// its state transition. | ||||||
| 		for nonceChecked[i] { | 		for !nonceChecked[i] { | ||||||
| 			r := <-nonceDone | 			r := <-nonceDone | ||||||
| 			nonceChecked[r.i] = true | 			nonceChecked[r.i] = true | ||||||
| 			if !r.valid { | 			if !r.valid { | ||||||
| 				block := chain[i] | 				block := chain[r.i] | ||||||
| 				return i, ValidationError("Block (#%v / %x) nonce is invalid (= %x)", block.Number(), block.Hash(), block.Nonce) | 				return r.i, &BlockNonceErr{Hash: block.Hash(), Number: block.Number(), Nonce: block.Nonce()} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -3,6 +3,7 @@ package core | |||||||
| import ( | import ( | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"math/big" | 	"math/big" | ||||||
|  | 	"math/rand" | ||||||
| 	"os" | 	"os" | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
| 	"runtime" | 	"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 | 	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 { | type InvalidTxErr struct { | ||||||
| 	Message string | 	Message string | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user