diff --git a/core/forkchoice.go b/core/forkchoice.go index b0dbb200e..b293c851b 100644 --- a/core/forkchoice.go +++ b/core/forkchoice.go @@ -74,10 +74,10 @@ func NewForkChoice(chainReader ChainReader, preserve func(header *types.Header) // In the td mode, the new head is chosen if the corresponding // total difficulty is higher. In the extern mode, the trusted // header is always selected as the head. -func (f *ForkChoice) ReorgNeeded(current *types.Header, header *types.Header) (bool, error) { +func (f *ForkChoice) ReorgNeeded(current *types.Header, extern *types.Header) (bool, error) { var ( localTD = f.chain.GetTd(current.Hash(), current.Number.Uint64()) - externTd = f.chain.GetTd(header.Hash(), header.Number.Uint64()) + externTd = f.chain.GetTd(extern.Hash(), extern.Number.Uint64()) ) if localTD == nil || externTd == nil { return false, errors.New("missing td") @@ -88,21 +88,26 @@ func (f *ForkChoice) ReorgNeeded(current *types.Header, header *types.Header) (b if ttd := f.chain.Config().TerminalTotalDifficulty; ttd != nil && ttd.Cmp(externTd) <= 0 { return true, nil } + // If the total difficulty is higher than our known, add it to the canonical chain + if diff := externTd.Cmp(localTD); diff > 0 { + return true, nil + } else if diff < 0 { + return false, nil + } + // Local and external difficulty is identical. // Second clause in the if statement reduces the vulnerability to selfish mining. // Please refer to http://www.cs.cornell.edu/~ie53/publications/btcProcFC.pdf - reorg := externTd.Cmp(localTD) > 0 - if !reorg && externTd.Cmp(localTD) == 0 { - number, headNumber := header.Number.Uint64(), current.Number.Uint64() - if number < headNumber { - reorg = true - } else if number == headNumber { - var currentPreserve, externPreserve bool - if f.preserve != nil { - currentPreserve, externPreserve = f.preserve(current), f.preserve(header) - } - reorg = !currentPreserve && (externPreserve || f.rand.Float64() < 0.5) + reorg := false + externNum, localNum := extern.Number.Uint64(), current.Number.Uint64() + if externNum < localNum { + reorg = true + } else if externNum == localNum { + var currentPreserve, externPreserve bool + if f.preserve != nil { + currentPreserve, externPreserve = f.preserve(current), f.preserve(extern) } + reorg = !currentPreserve && (externPreserve || f.rand.Float64() < 0.5) } return reorg, nil }