diff --git a/core/blockchain.go b/core/blockchain.go index acc6a4dea0..b13cac0b84 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -1317,7 +1317,7 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types. // If we exceeded out time allowance, flush an entire trie to disk flushToDisk := bc.gcproc > bc.cacheConfig.TrieTimeLimit || - bc.chainConfig.isForkBlock(current+1) + bc.chainConfig.IsForkBlock(current+1) if flushToDisk { // If the header is missing (canonical chain behind), we're reorging a low // diff sidechain. Suspend committing until this operation is completed. @@ -1824,6 +1824,21 @@ func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator) (i if parent == nil { return it.index, nil, nil, errors.New("missing parent") } + if parent.Number.Cmp(common.Big1) <= 0 { + // What most likely happened, is that the even though the common ancestor + // is not that far back, it is still earlier than the fast-sync pivot point. + // In that scenario, the only place from where we can start restoring + // the state is the genesis, which is probably not what the user + // wants, or expects: a fast-sync that switches over to a full-sync. + // + // There is a high likelihood that this sidechain is actually an invalid + // chain, but for some reason longer. If the user actually wants to land + // on the other chain, it would be better to do a fast-sync to that one, + // instead of progressing further via sidechain import + log.Warn("Sidechain import aborted, due to extreme size. Please re-sync if you believe this is in error", + "start", numbers[len(numbers)-1], "count", len(numbers)) + return it.index, nil, nil, errors.New("state regeneration task too large") + } // Import all the pruned blocks to make the state available var ( blocks []*types.Block diff --git a/params/config.go b/params/config.go index 37becf74e7..be8bb03bf6 100644 --- a/params/config.go +++ b/params/config.go @@ -470,8 +470,8 @@ func isForked(s, head *big.Int) bool { } // isForkBlock returns whether the given block number designates a fork block -func (c *ChainConfig) isForkBlock(n uint64) bool { - number := big.NewInt(n) +func (c *ChainConfig) IsForkBlock(n uint64) bool { + number := new(big.Int).SetUint64(n) for _, forkNum := range []*big.Int{ c.HomesteadBlock, c.DAOForkBlock, @@ -483,7 +483,7 @@ func (c *ChainConfig) isForkBlock(n uint64) bool { c.PetersburgBlock, c.IstanbulBlock, } { - h := forkNum.Cmp(number) + h := number.Cmp(forkNum) if h < 0 { return false } @@ -491,6 +491,7 @@ func (c *ChainConfig) isForkBlock(n uint64) bool { return true } } + return false } func configNumEqual(x, y *big.Int) bool {