MESS — Modified Exponential Subjective Scoring¶
MESS (ECBP-1100) is an artificial finality mechanism for Ethereum Classic. It penalizes deep reorganizations by applying an exponential scoring penalty to alternative chains that diverge far from the canonical head.
Network activation¶
MESS shipped as a temporary safety measure, not a permanent consensus rule, so it is
not part of the fork ID — core-geth classifies ECBP-1100 as a
cross-compatible transition rather than a hard fork, so it never enters the forkid
block list. In go-ethereum-classic it is configured only for Classic mainnet
(params/config_etc.go):
| Network | MESS activated | MESS deactivated |
|---|---|---|
| Classic (mainnet) | 11,380,000 (09 Oct 2020) | 19,250,000 (31 Jan 2024, with the Spiral hard fork) |
| Mordor (testnet) | not configured | not configured |
ECIP-1110 ties MESS deactivation to the Spiral activation block (19,250,000), which Ethereum Classic announced for 31 Jan 2024.
Mordor divergence (intentional): getc's
MordorChainConfigleavesECBP1100Transition/ECBP1100DeactivateTransitionunset, soIsECBP1100is always false on Mordor — a deliberate divergence from core-geth. This does not affect syncing or block validity: MESS is a fork-choice / reorg policy (it only vetoes deep reorgs against a competing chain viareorgFilter), never a block-validity rule, and it is only active once a node is already synced — not during catch-up. Mordor replays to the same canonical chain with or without it. The only thing getc forgoes is MESS's deep-reorg protection during the elapsed 2,380,000 → 10,400,000 window.Note: MESS activated at 11,380,000 — distinct from Etchash (ECIP-1099) at 11,700,000. Etchash is a consensus fork (it changes the PoW DAG) and counts toward the fork ID, which is why it appears in the fork list and MESS does not.
| Metric | Value |
|---|---|
| Dedicated files | 3 |
| Extension points | 6 |
| Upstream files touched | 5 |
Architecture¶
Fork-choice flow¶
block arrives → blockchain.go writeKnownBlock / writeBlockAndSetHead
→ forker.ReorgNeeded(current, extern) [core/forkchoice_pow.go]
→ TD comparison
→ reorgFilter(current, extern)
→ IsMESSEnabled() && IsECBP1100(num)
→ findCommonAncestor()
→ if unresolved (no ancestor / missing header) → REJECT + log (fail-closed)
→ ecbp1100(): antigravity polynomial check
→ REJECT (errReorgFinality) + log, or ALLOW
Note the fail-closed stance: if the common ancestor cannot be resolved, MESS rejects the
reorg rather than allowing it — a reorg it cannot verify is exactly the case MESS exists to
guard. (core-geth propagates the same error in its equivalent ForkChoice.ReorgNeeded.)
Activation lifecycle¶
chainSyncer loop [eth/sync_pow.go] — on sync done / when already synced
→ checkMESSActivation() [eth/sync_mess.go]
enable: !enabled && shouldEnableMESS() && peers ≥ 5 → EnableMESS(true, "synced")
disable: enabled && peers < 5 → EnableMESS(false, "low peers")
shouldEnableMESS() = !messForceDisable && (messForceEnable || IsECBP1100(head))
messSafetyLoop [eth/sync_mess.go] — separate ticker, 30 × blocktime ≈ 6.5 min (ECIP-1100)
→ if enabled && head stale → EnableMESS(false, "stale head")
Dedicated Files¶
These files are entirely new and exist only for MESS. Files that MESS merely hooks
into — like the revived core/forkchoice_pow.go — are shown under Fork Choice below,
not here.
| File | Description | Changed |
|---|---|---|
core/blockchain_mess.go · diff |
MESS algorithm — ecbp1100 polynomial, findCommonAncestor, NewForkChoiceWithMESS | +270 -0 |
core/blockchain_mess_test.go · diff |
MESS unit tests | +700 -0 |
eth/sync_mess.go · diff |
MESS activation control — messSafetyLoop, checkMESSActivation, shouldEnableMESS | +107 -0 |
Fork Choice — revived, with the MESS hook¶
core/forkchoice_pow.go is not a MESS-only file: it transplants back the pre-purge
total-difficulty fork choice that upstream removed with TD. MESS only
adds a hook here — the reorgFilter / reorgAllowed callback that lets the MESS
algorithm veto a reorg. The symbols below are that revived fork choice (full picture in the
Total Difficulty subsystem); the MESS algorithm itself
lives in core/blockchain_mess.go.
| Symbol | Original | Current | Status | Diff |
|---|---|---|---|---|
ChainReader |
forkchoice | forkchoice_pow | ✅ | view |
ForkChoice 📋 |
forkchoice | forkchoice_pow | +10 -0 | view |
NewForkChoice |
forkchoice | forkchoice_pow | ✅ | view |
ForkChoice.ReorgNeeded 📋 |
forkchoice | forkchoice_pow | +13 -10 | view |
ForkChoice.reorgAllowed |
— | forkchoice_pow | 🆕 | view |
Extension Points¶
Modifications to upstream files that wire in MESS behavior.
Struct Fields¶
| # | File | Name | Lines | Description | Wires To |
|---|---|---|---|---|---|
| 1 | params/config.go |
ChainConfig ETC fields | 497-507 | ECIP fork blocks (1017/1041/1099/Spiral), era rounds, DieHard bomb pause, MESS (ECBP-1100) activation/deactivation | params/config_etc.go |
| 2 | eth/handler.go |
handler.messForceEnable/Disable | 126-127 | MESS emergency override flags propagated from ethconfig | eth/sync_mess.go |
| 3 | eth/ethconfig/config.go |
Config.MESSForceEnable/Disable | 214-215 | Emergency MESS overrides — force enable or force disable regardless of chain config | eth/ethconfig/config.go |
Conditional Blocks¶
| # | File | Name | Lines | Description | Wires To |
|---|---|---|---|---|---|
| 4 | eth/handler.go |
isPow in Start (PoW syncer) | 467-477 | Starts chainSyncer, block fetcher, and MESS safety loop for PoW chains | eth/handler_pow.go, eth/sync_pow.go |
| 5 | core/blockchain.go |
IsPow in NewBlockChain | 428-429 | Initializes ForkChoice with MESS for PoW chains | core/forkchoice_pow.go |
Config Plumbing¶
| # | File | Name | Lines | Description | Wires To |
|---|---|---|---|---|---|
| 6 | eth/backend.go |
MESS flags passthrough | 343-344 | Passes MESSForceEnable/Disable from ethconfig to handler config | eth/handler.go |