aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorJeffrey Wilcke <jeffrey@ethereum.org>2016-08-18 23:04:31 +0800
committerGitHub <noreply@github.com>2016-08-18 23:04:31 +0800
commit99a0c7643542aecf4fae43acabfb0a8efbd4b560 (patch)
treecf1c2f8448b010ad36aa553b5be0f2697a2abb59 /core
parentc2eea6306e55321164e721e69a384765d8417655 (diff)
parent5ca5ccf90cc5af0789268f10bc3189f4539ea15c (diff)
downloadgo-tangerine-99a0c7643542aecf4fae43acabfb0a8efbd4b560.tar
go-tangerine-99a0c7643542aecf4fae43acabfb0a8efbd4b560.tar.gz
go-tangerine-99a0c7643542aecf4fae43acabfb0a8efbd4b560.tar.bz2
go-tangerine-99a0c7643542aecf4fae43acabfb0a8efbd4b560.tar.lz
go-tangerine-99a0c7643542aecf4fae43acabfb0a8efbd4b560.tar.xz
go-tangerine-99a0c7643542aecf4fae43acabfb0a8efbd4b560.tar.zst
go-tangerine-99a0c7643542aecf4fae43acabfb0a8efbd4b560.zip
Merge pull request #2915 from obscuren/release/1.4
Geth 1.4.11
Diffstat (limited to 'core')
-rw-r--r--core/blockchain.go19
-rw-r--r--core/blockchain_test.go38
-rw-r--r--core/database_util.go6
-rw-r--r--core/headerchain.go17
-rw-r--r--core/vm/contracts.go4
5 files changed, 64 insertions, 20 deletions
diff --git a/core/blockchain.go b/core/blockchain.go
index 3fbb117d3..8f00f2cc4 100644
--- a/core/blockchain.go
+++ b/core/blockchain.go
@@ -770,6 +770,14 @@ func (self *BlockChain) WriteBlock(block *types.Block) (status WriteStatus, err
localTd := self.GetTd(self.currentBlock.Hash())
externTd := new(big.Int).Add(block.Difficulty(), ptd)
+ // Irrelevant of the canonical status, write the block itself to the database
+ if err := self.hc.WriteTd(block.Hash(), externTd); err != nil {
+ glog.Fatalf("failed to write block total difficulty: %v", err)
+ }
+ if err := WriteBlock(self.chainDb, block); err != nil {
+ glog.Fatalf("failed to write block contents: %v", err)
+ }
+
// If the total difficulty is higher than our known, add it to the canonical chain
// Second clause in the if statement reduces the vulnerability to selfish mining.
// Please refer to http://www.cs.cornell.edu/~ie53/publications/btcProcFC.pdf
@@ -780,20 +788,11 @@ func (self *BlockChain) WriteBlock(block *types.Block) (status WriteStatus, err
return NonStatTy, err
}
}
- // Insert the block as the new head of the chain
- self.insert(block)
+ self.insert(block) // Insert the block as the new head of the chain
status = CanonStatTy
} else {
status = SideStatTy
}
- // Irrelevant of the canonical status, write the block itself to the database
- if err := self.hc.WriteTd(block.Hash(), externTd); err != nil {
- glog.Fatalf("failed to write block total difficulty: %v", err)
- }
- if err := WriteBlock(self.chainDb, block); err != nil {
- glog.Fatalf("failed to write block contents: %v", err)
- }
-
self.futureBlocks.Remove(block.Hash())
return
diff --git a/core/blockchain_test.go b/core/blockchain_test.go
index 2f6ddf9c9..18fe30f18 100644
--- a/core/blockchain_test.go
+++ b/core/blockchain_test.go
@@ -1090,3 +1090,41 @@ done:
}
}
+
+// Tests if the canonical block can be fetched from the database during chain insertion.
+func TestCanonicalBlockRetrieval(t *testing.T) {
+ var (
+ db, _ = ethdb.NewMemDatabase()
+ genesis = WriteGenesisBlockForTesting(db)
+ )
+
+ evmux := &event.TypeMux{}
+ blockchain, _ := NewBlockChain(db, testChainConfig(), FakePow{}, evmux)
+
+ chain, _ := GenerateChain(nil, genesis, db, 10, func(i int, gen *BlockGen) {})
+
+ for i, _ := range chain {
+ go func(block *types.Block) {
+ // try to retrieve a block by its canonical hash and see if the block data can be retrieved.
+ for {
+ ch := GetCanonicalHash(db, block.NumberU64())
+ if ch == (common.Hash{}) {
+ continue // busy wait for canonical hash to be written
+ }
+ if ch != block.Hash() {
+ t.Fatalf("unknown canonical hash, want %s, got %s", block.Hash().Hex(), ch.Hex())
+ }
+ fb := GetBlock(db, ch)
+ if fb == nil {
+ t.Fatalf("unable to retrieve block %d for canonical hash: %s", block.NumberU64(), ch.Hex())
+ }
+ if fb.Hash() != block.Hash() {
+ t.Fatalf("invalid block hash for block %d, want %s, got %s", block.NumberU64(), block.Hash().Hex(), fb.Hash().Hex())
+ }
+ return
+ }
+ }(chain[i])
+
+ blockchain.InsertChain(types.Blocks{chain[i]})
+ }
+}
diff --git a/core/database_util.go b/core/database_util.go
index 3ba80062c..3a110f7d0 100644
--- a/core/database_util.go
+++ b/core/database_util.go
@@ -157,7 +157,11 @@ func GetTd(db ethdb.Database, hash common.Hash) *big.Int {
}
// GetBlock retrieves an entire block corresponding to the hash, assembling it
-// back from the stored header and body.
+// back from the stored header and body. If either the header or body could not
+// be retrieved nil is returned.
+//
+// Note, due to concurrent download of header and block body the header and thus
+// canonical hash can be stored in the database but the body data not (yet).
func GetBlock(db ethdb.Database, hash common.Hash) *types.Block {
// Retrieve the block header and body contents
header := GetHeader(db, hash)
diff --git a/core/headerchain.go b/core/headerchain.go
index 5e0fbfb08..3503a1c33 100644
--- a/core/headerchain.go
+++ b/core/headerchain.go
@@ -129,6 +129,14 @@ func (hc *HeaderChain) WriteHeader(header *types.Header) (status WriteStatus, er
localTd := hc.GetTd(hc.currentHeaderHash)
externTd := new(big.Int).Add(header.Difficulty, ptd)
+ // Irrelevant of the canonical status, write the td and header to the database
+ if err := hc.WriteTd(hash, externTd); err != nil {
+ glog.Fatalf("failed to write header total difficulty: %v", err)
+ }
+ if err := WriteHeader(hc.chainDb, header); err != nil {
+ glog.Fatalf("failed to write header contents: %v", err)
+ }
+
// If the total difficulty is higher than our known, add it to the canonical chain
// Second clause in the if statement reduces the vulnerability to selfish mining.
// Please refer to http://www.cs.cornell.edu/~ie53/publications/btcProcFC.pdf
@@ -150,6 +158,7 @@ func (hc *HeaderChain) WriteHeader(header *types.Header) (status WriteStatus, er
headHeader = hc.GetHeader(headHash)
headNumber = headHeader.Number.Uint64()
}
+
// Extend the canonical chain with the new header
if err := WriteCanonicalHash(hc.chainDb, hash, number); err != nil {
glog.Fatalf("failed to insert header number: %v", err)
@@ -157,19 +166,13 @@ func (hc *HeaderChain) WriteHeader(header *types.Header) (status WriteStatus, er
if err := WriteHeadHeaderHash(hc.chainDb, hash); err != nil {
glog.Fatalf("failed to insert head header hash: %v", err)
}
+
hc.currentHeaderHash, hc.currentHeader = hash, types.CopyHeader(header)
status = CanonStatTy
} else {
status = SideStatTy
}
- // Irrelevant of the canonical status, write the header itself to the database
- if err := hc.WriteTd(hash, externTd); err != nil {
- glog.Fatalf("failed to write header total difficulty: %v", err)
- }
- if err := WriteHeader(hc.chainDb, header); err != nil {
- glog.Fatalf("failed to write header contents: %v", err)
- }
hc.headerCache.Add(hash, header)
return
diff --git a/core/vm/contracts.go b/core/vm/contracts.go
index 5cc9f903b..b45f14724 100644
--- a/core/vm/contracts.go
+++ b/core/vm/contracts.go
@@ -95,7 +95,7 @@ func ecrecoverFunc(in []byte) []byte {
// tighter sig s values in homestead only apply to tx sigs
if !crypto.ValidateSignatureValues(v, r, s, false) {
- glog.V(logger.Debug).Infof("EC RECOVER FAIL: v, r or s value invalid")
+ glog.V(logger.Detail).Infof("ECRECOVER error: v, r or s value invalid")
return nil
}
@@ -106,7 +106,7 @@ func ecrecoverFunc(in []byte) []byte {
pubKey, err := crypto.Ecrecover(in[:32], rsv)
// make sure the public key is a valid one
if err != nil {
- glog.V(logger.Error).Infof("EC RECOVER FAIL: ", err)
+ glog.V(logger.Detail).Infoln("ECRECOVER error: ", err)
return nil
}