diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go index 64faf6ad1..cbb2d42aa 100644 --- a/cmd/utils/cmd.go +++ b/cmd/utils/cmd.go @@ -172,7 +172,7 @@ func ImportChain(chainmgr *core.ChainManager, fn string) error { n++ if n == batchSize { - if err := chainmgr.InsertChain(blocks); err != nil { + if _, err := chainmgr.InsertChain(blocks); err != nil { return fmt.Errorf("invalid block %v", err) } n = 0 @@ -181,7 +181,7 @@ func ImportChain(chainmgr *core.ChainManager, fn string) error { } if n > 0 { - if err := chainmgr.InsertChain(blocks[:n]); err != nil { + if _, err := chainmgr.InsertChain(blocks[:n]); err != nil { return fmt.Errorf("invalid block %v", err) } } 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..253228bfd 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()))) @@ -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/eth/downloader/downloader.go b/eth/downloader/downloader.go index a3917854f..a7e83a532 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -37,7 +37,7 @@ var ( ) type hashCheckFn func(common.Hash) bool -type chainInsertFn func(types.Blocks) error +type chainInsertFn func(types.Blocks) (int, error) type hashIterFn func() (common.Hash, error) type blockPack struct { @@ -432,12 +432,11 @@ func (d *Downloader) process(peer *peer) error { // TODO check for parent error. When there's a parent error we should stop // processing and start requesting the `block.hash` so that it's parent and // grandparents can be requested and queued. - err = d.insertChain(blocks[:max]) + var i int + i, err = d.insertChain(blocks[:max]) if err != nil && core.IsParentErr(err) { - glog.V(logger.Debug).Infoln("Aborting process due to missing parent.") + glog.V(logger.Debug).Infof("Aborting process due to missing parent (%d)\n", i) - // XXX this needs a lot of attention - blocks = nil break } else if err != nil { // immediatly unregister the false peer but do not disconnect diff --git a/eth/handler.go b/eth/handler.go index 61149049e..2dd4c74db 100644 --- a/eth/handler.go +++ b/eth/handler.go @@ -376,7 +376,7 @@ func (self *ProtocolManager) handleMsg(p *peer) error { // if the parent exists we process the block and propagate to our peers // if the parent does not exists we delegate to the downloader. if self.chainman.HasBlock(request.Block.ParentHash()) { - if err := self.chainman.InsertChain(types.Blocks{request.Block}); err != nil { + if _, err := self.chainman.InsertChain(types.Blocks{request.Block}); err != nil { // handle error return nil } diff --git a/miner/worker.go b/miner/worker.go index a38b8a5d4..87d17dfd6 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -184,7 +184,7 @@ func (self *worker) wait() { continue } - if err := self.chain.InsertChain(types.Blocks{block}); err == nil { + if _, err := self.chain.InsertChain(types.Blocks{block}); err == nil { for _, uncle := range block.Uncles() { delete(self.possibleUncles, uncle.Hash()) } diff --git a/tests/block_test_util.go b/tests/block_test_util.go index 06f082ca3..093c9be0c 100644 --- a/tests/block_test_util.go +++ b/tests/block_test_util.go @@ -162,7 +162,7 @@ func (t *BlockTest) TryBlocksInsert(chainManager *core.ChainManager) error { } } // RLP decoding worked, try to insert into chain: - err = chainManager.InsertChain(types.Blocks{cb}) + _, err = chainManager.InsertChain(types.Blocks{cb}) if err != nil { if b.BlockHeader == nil { continue // OK - block is supposed to be invalid, continue with next block