aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorJeffrey Wilcke <jeffrey@ethereum.org>2015-04-30 06:52:25 +0800
committerJeffrey Wilcke <jeffrey@ethereum.org>2015-04-30 06:52:25 +0800
commit3fef60190384106af390dd23a65384b9cc6e4a28 (patch)
tree49f52b8bba6af0228bb20758dd1465f8dce6842d /core
parent764e81bf12bc45b00cec7db216e72d6396cf0c13 (diff)
parent30b921ef463247da63dece1cb81887f7e66668ff (diff)
downloaddexon-3fef60190384106af390dd23a65384b9cc6e4a28.tar
dexon-3fef60190384106af390dd23a65384b9cc6e4a28.tar.gz
dexon-3fef60190384106af390dd23a65384b9cc6e4a28.tar.bz2
dexon-3fef60190384106af390dd23a65384b9cc6e4a28.tar.lz
dexon-3fef60190384106af390dd23a65384b9cc6e4a28.tar.xz
dexon-3fef60190384106af390dd23a65384b9cc6e4a28.tar.zst
dexon-3fef60190384106af390dd23a65384b9cc6e4a28.zip
Merge pull request #830 from obscuren/downloader-missing-parent
eth/downloader: missing parent improvement
Diffstat (limited to 'core')
-rw-r--r--core/chain_makers.go2
-rw-r--r--core/chain_manager.go10
-rw-r--r--core/chain_manager_test.go37
-rw-r--r--core/transaction_pool.go23
-rw-r--r--core/transaction_pool_test.go27
-rw-r--r--core/types/block.go2
6 files changed, 89 insertions, 12 deletions
diff --git a/core/chain_makers.go b/core/chain_makers.go
index 4512a5493..73c2205f4 100644
--- a/core/chain_makers.go
+++ b/core/chain_makers.go
@@ -141,6 +141,6 @@ func newCanonical(n int, db common.Database) (*BlockProcessor, error) {
return bman, nil
}
lchain := makeChain(bman, parent, n, db, CanonicalSeed)
- err := bman.bc.InsertChain(lchain)
+ _, err := bman.bc.InsertChain(lchain)
return bman, err
}
diff --git a/core/chain_manager.go b/core/chain_manager.go
index 32ad4a2ba..4fdb2edce 100644
--- a/core/chain_manager.go
+++ b/core/chain_manager.go
@@ -497,7 +497,9 @@ func (self *ChainManager) procFutureBlocks() {
self.InsertChain(blocks)
}
-func (self *ChainManager) InsertChain(chain types.Blocks) error {
+// InsertChain will attempt to insert the given chain in to the canonical chain or, otherwise, create a fork. It an error is returned
+// it will return the index number of the failing block as well an error describing what went wrong (for possible errors see core/errors.go).
+func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
// A queued approach to delivering events. This is generally faster than direct delivery and requires much less mutex acquiring.
var (
queue = make([]interface{}, len(chain))
@@ -540,7 +542,7 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
glog.V(logger.Error).Infoln(err)
glog.V(logger.Debug).Infoln(block)
- return err
+ return i, err
}
block.Td = new(big.Int).Set(CalculateTD(block, self.GetBlock(block.ParentHash())))
@@ -591,7 +593,7 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
}
} else {
if glog.V(logger.Detail) {
- glog.Infof("inserted forked block #%d (%d TXs %d UNCs) (%x...)\n", block.Number(), len(block.Transactions()), len(block.Uncles()), block.Hash().Bytes()[0:4])
+ glog.Infof("inserted forked block #%d (TD=%v) (%d TXs %d UNCs) (%x...)\n", block.Number(), block.Difficulty(), len(block.Transactions()), len(block.Uncles()), block.Hash().Bytes()[0:4])
}
queue[i] = ChainSideEvent{block, logs}
@@ -613,7 +615,7 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
go self.eventMux.Post(queueEvent)
- return nil
+ return 0, nil
}
// diff takes two blocks, an old chain and a new chain and will reconstruct the blocks and inserts them
diff --git a/core/chain_manager_test.go b/core/chain_manager_test.go
index a88afd7c8..50915459b 100644
--- a/core/chain_manager_test.go
+++ b/core/chain_manager_test.go
@@ -9,6 +9,7 @@ import (
"strconv"
"testing"
+ "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
@@ -44,7 +45,7 @@ func testFork(t *testing.T, bman *BlockProcessor, i, N int, f func(td1, td2 *big
// extend the fork
parent := bman2.bc.CurrentBlock()
chainB := makeChain(bman2, parent, N, db, ForkSeed)
- err = bman2.bc.InsertChain(chainB)
+ _, err = bman2.bc.InsertChain(chainB)
if err != nil {
t.Fatal("Insert chain error for fork:", err)
}
@@ -108,7 +109,7 @@ func loadChain(fn string, t *testing.T) (types.Blocks, error) {
}
func insertChain(done chan bool, chainMan *ChainManager, chain types.Blocks, t *testing.T) {
- err := chainMan.InsertChain(chain)
+ _, err := chainMan.InsertChain(chain)
if err != nil {
fmt.Println(err)
t.FailNow()
@@ -369,11 +370,8 @@ func makeChainWithDiff(genesis *types.Block, d []int, seed byte) []*types.Block
return chain
}
-func TestReorg(t *testing.T) {
- db, _ := ethdb.NewMemDatabase()
+func chm(genesis *types.Block, db common.Database) *ChainManager {
var eventMux event.TypeMux
-
- genesis := GenesisBlock(db)
bc := &ChainManager{blockDb: db, stateDb: db, genesisBlock: genesis, eventMux: &eventMux}
bc.cache = NewBlockCache(100)
bc.futureBlocks = NewBlockCache(100)
@@ -381,6 +379,14 @@ func TestReorg(t *testing.T) {
bc.ResetWithGenesisBlock(genesis)
bc.txState = state.ManageState(bc.State())
+ return bc
+}
+
+func TestReorgLongest(t *testing.T) {
+ db, _ := ethdb.NewMemDatabase()
+ genesis := GenesisBlock(db)
+ bc := chm(genesis, db)
+
chain1 := makeChainWithDiff(genesis, []int{1, 2, 4}, 10)
chain2 := makeChainWithDiff(genesis, []int{1, 2, 3, 4}, 11)
@@ -394,3 +400,22 @@ func TestReorg(t *testing.T) {
}
}
}
+
+func TestReorgShortest(t *testing.T) {
+ db, _ := ethdb.NewMemDatabase()
+ genesis := GenesisBlock(db)
+ bc := chm(genesis, db)
+
+ chain1 := makeChainWithDiff(genesis, []int{1, 2, 3, 4}, 10)
+ chain2 := makeChainWithDiff(genesis, []int{1, 10}, 11)
+
+ bc.InsertChain(chain1)
+ bc.InsertChain(chain2)
+
+ prev := bc.CurrentBlock()
+ for block := bc.GetBlockByNumber(bc.CurrentBlock().NumberU64() - 1); block.NumberU64() != 0; prev, block = block, bc.GetBlockByNumber(block.NumberU64()-1) {
+ if prev.ParentHash() != block.Hash() {
+ t.Errorf("parent hash mismatch %x - %x", prev.ParentHash(), block.Hash())
+ }
+ }
+}
diff --git a/core/transaction_pool.go b/core/transaction_pool.go
index 8543aa017..22a804e1d 100644
--- a/core/transaction_pool.go
+++ b/core/transaction_pool.go
@@ -306,6 +306,27 @@ func (pool *TxPool) checkQueue() {
}
}
+func (pool *TxPool) removeTx(hash common.Hash) {
+ // delete from pending pool
+ delete(pool.txs, hash)
+
+ // delete from queue
+out:
+ for address, txs := range pool.queue {
+ for i, tx := range txs {
+ if tx.Hash() == hash {
+ if len(txs) == 1 {
+ // if only one tx, remove entire address entry
+ delete(pool.queue, address)
+ } else {
+ pool.queue[address][len(txs)-1], pool.queue[address] = nil, append(txs[:i], txs[i+1:]...)
+ }
+ break out
+ }
+ }
+ }
+}
+
func (pool *TxPool) validatePool() {
pool.mu.Lock()
defer pool.mu.Unlock()
@@ -316,7 +337,7 @@ func (pool *TxPool) validatePool() {
glog.Infof("removed tx (%x) from pool: %v\n", hash[:4], err)
}
- delete(pool.txs, hash)
+ pool.removeTx(hash)
}
}
}
diff --git a/core/transaction_pool_test.go b/core/transaction_pool_test.go
index 4d66776f0..49224be5b 100644
--- a/core/transaction_pool_test.go
+++ b/core/transaction_pool_test.go
@@ -111,3 +111,30 @@ func TestTransactionQueue(t *testing.T) {
t.Error("expected transaction queue to be empty. is", len(pool.queue[from]))
}
}
+
+func TestRemoveTx(t *testing.T) {
+ pool, key := setupTxPool()
+ tx := transaction()
+ tx.SignECDSA(key)
+ from, _ := tx.From()
+ pool.currentState().AddBalance(from, big.NewInt(1))
+ pool.queueTx(tx)
+ pool.addTx(tx)
+ if len(pool.queue) != 1 {
+ t.Error("expected queue to be 1, got", len(pool.queue))
+ }
+
+ if len(pool.txs) != 1 {
+ t.Error("expected txs to be 1, got", len(pool.txs))
+ }
+
+ pool.removeTx(tx.Hash())
+
+ if len(pool.queue) > 0 {
+ t.Error("expected queue to be 0, got", len(pool.queue))
+ }
+
+ if len(pool.txs) > 0 {
+ t.Error("expected txs to be 0, got", len(pool.txs))
+ }
+}
diff --git a/core/types/block.go b/core/types/block.go
index 19cf49c12..c93452fa7 100644
--- a/core/types/block.go
+++ b/core/types/block.go
@@ -99,6 +99,8 @@ type Block struct {
Td *big.Int
queued bool // flag for blockpool to skip TD check
+ ReceivedAt time.Time
+
receipts Receipts
}