Skip to content

ForkChoice.ReorgNeeded

Source (upstream pre-purge) Current
File core/forkchoice.go forkchoice_pow.go
Symbol ForkChoice.ReorgNeeded ForkChoice.ReorgNeeded
Ref f4d53133f~1 etc/v1.17.3-full-node

TTD merge logic removed (ETC is perpetual PoW). All reorg paths now go through reorgAllowed() — extension point for MESS artificial finality.

3-way merge — purge → getc ← upstream

pre-purgecore-geth≈ adapted (origin inferred by similarity)fork-only
// ReorgNeeded returns whether the reorg should be applied
// based on the given external header and local canonical chain.
// 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, extern *types.Header) (needed bool, err error) {
// When the external header is not adopted as the new canonical head it is a
// side block — an uncle candidate for the PoW miner. Notify subscribers.
defer func() {
if err == nil && !needed {
f.sideBlockFeed.Send(ChainSideEvent{Header: extern})
}
}()
var (
localTD = f.chain.GetTd(current.Hash(), current.Number.Uint64())
externTd = f.chain.GetTd(extern.Hash(), extern.Number.Uint64())
)
if localTD == nil || externTd == nil {
return false, errors.New("missing td")
}
// If the total difficulty is higher than our known, add it to the canonical chain
if diff := externTd.Cmp(localTD); diff > 0 {
return f.reorgAllowed(current, extern)
} 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 := 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)
}
if !reorg {
return false, nil
}
return f.reorgAllowed(current, extern)
core-geth validation — +17 -66 | | | |---|---| | File | [`forkchoice.go`](https://github.com/etclabscore/core-geth/blob/v1.12.20/core/forkchoice.go) | | Symbol | `ForkChoice.ReorgNeeded` | | Ref | `v1.12.20` |
--- a/core-geth/core/forkchoice.go
+++ b/etc/core/forkchoice_pow.go
@@ -3,7 +3,14 @@
 // 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, extern *types.Header) (bool, error) {
+func (f *ForkChoice) ReorgNeeded(current *types.Header, extern *types.Header) (needed bool, err error) {
+   // When the external header is not adopted as the new canonical head it is a
+   // side block — an uncle candidate for the PoW miner. Notify subscribers.
+   defer func() {
+       if err == nil && !needed {
+           f.sideBlockFeed.Send(ChainSideEvent{Header: extern})
+       }
+   }()
    var (
        localTD  = f.chain.GetTd(current.Hash(), current.Number.Uint64())
        externTd = f.chain.GetTd(extern.Hash(), extern.Number.Uint64())
@@ -11,35 +18,16 @@
    if localTD == nil || externTd == nil {
        return false, errors.New("missing td")
    }
-   // Accept the new header as the chain head if the transition
-   // is already triggered. We assume all the headers after the
-   // transition come from the trusted consensus layer.
-   if ttd := f.chain.Config().GetEthashTerminalTotalDifficulty(); 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
-   // }
-   /*
-       This is chunk was added with the following commit, citing it to be logically inoperative.
-       etclabscore/core-geth omits it because of subsequent Artificial Finality checks on the reorg var.
-
-           core: clarify code in forkchoice (#26257)
-
-           refactoring without logic change
-           0dc9b01c github.com/setunapo 20221128
-   */
-
+   // If the total difficulty is higher than our known, add it to the canonical chain
+   if diff := externTd.Cmp(localTD); diff > 0 {
+       return f.reorgAllowed(current, extern)
+   } 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
-   tie := externTd.Cmp(localTD) == 0
-   if tie {
+   reorg := false
        externNum, localNum := extern.Number.Uint64(), current.Number.Uint64()
        if externNum < localNum {
            reorg = true
@@ -50,45 +38,8 @@
            }
            reorg = !currentPreserve && (externPreserve || f.rand.Float64() < 0.5)
        }
-   }
-
-   // If reorg is not needed (false), then we can just return.
-   // The following logic adds a condition only in the case where a reorg would
-   // otherwise be indicated.
    if !reorg {
-       return reorg, nil
-   }
-
-   if bc, ok := f.chain.(*BlockChain); ok {
-       // Short circuit if not configured for Artificial Finality.
-       if !bc.IsArtificialFinalityEnabled() {
-           return reorg, nil
-       }
-   }
-   if !f.chain.Config().IsEnabled(f.chain.Config().GetECBP1100Transition, current.Number) {
-       return reorg, nil
-   }
-
-   commonHeader, err := f.CommonAncestor(current, extern)
-   if err != nil {
-       return reorg, err
-   }
-
-   if err := ecbp1100(commonHeader, current, extern, f.chain.GetTd); err != nil {
-       reorg = false
-       log.Warn("Reorg disallowed", "error", err)
-   } else if current.Number.Uint64()-commonHeader.Number.Uint64() > 2 {
-       // Reorg is allowed, only log the MESS line if old chain is longer than normal.
-       log.Info("ECBP1100-MESS 🔓",
-           "status", "accepted",
-           "age", common.PrettyAge(time.Unix(int64(commonHeader.Time), 0)),
-           "current.span", common.PrettyDuration(time.Duration(current.Time-commonHeader.Time)*time.Second),
-           "proposed.span", common.PrettyDuration(time.Duration(extern.Time-commonHeader.Time)*time.Second),
-           "common.bno", commonHeader.Number.Uint64(), "common.hash", commonHeader.Hash(),
-           "current.bno", current.Number.Uint64(), "current.hash", current.Hash(),
-           "proposed.bno", extern.Number.Uint64(), "proposed.hash", extern.Hash(),
-       )
+       return false, nil
    }
-
-   return reorg, nil
+   return f.reorgAllowed(current, extern)
 }

← MESS