aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeffrey Wilcke <jeffrey@ethereum.org>2015-06-08 16:31:34 +0800
committerJeffrey Wilcke <jeffrey@ethereum.org>2015-06-08 16:31:34 +0800
commitc6faa18ec9630066683548ed410e364555fd838d (patch)
tree9441cf372102130b1a6e963ae9b6c4370cad8776
parente822f440b044bbe378cea65d2061eddfae0d0806 (diff)
parent6c27e2aaf6de99518feea48981882a8a39fa0727 (diff)
downloadgo-tangerine-c6faa18ec9630066683548ed410e364555fd838d.tar.gz
go-tangerine-c6faa18ec9630066683548ed410e364555fd838d.tar.zst
go-tangerine-c6faa18ec9630066683548ed410e364555fd838d.zip
Merge pull request #1198 from fjl/core-fix-nonce-check
core: fix nonce verification one more time
-rw-r--r--core/blocks.go1
-rw-r--r--core/chain_manager.go6
-rw-r--r--core/chain_manager_test.go53
-rw-r--r--core/error.go17
4 files changed, 74 insertions, 3 deletions
diff --git a/core/blocks.go b/core/blocks.go
index 83727ff62..f0d39e1e1 100644
--- a/core/blocks.go
+++ b/core/blocks.go
@@ -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,
}
diff --git a/core/chain_manager.go b/core/chain_manager.go
index 86d1c1454..291e411ae 100644
--- a/core/chain_manager.go
+++ b/core/chain_manager.go
@@ -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()}
}
}
diff --git a/core/chain_manager_test.go b/core/chain_manager_test.go
index 560e85f77..45bec7140 100644
--- a/core/chain_manager_test.go
+++ b/core/chain_manager_test.go
@@ -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) {
+}
diff --git a/core/error.go b/core/error.go
index 2bdad364f..3f3c350df 100644
--- a/core/error.go
+++ b/core/error.go
@@ -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
}