Summary
eth/69 (EIP-7642) is a post-Merge optimization. Its central change, removing total difficulty (td) from the wire Status message, is sound for proof-of-stake Ethereum, where td froze at the terminal total difficulty and stopped carrying information. For a proof-of-work network like Ethereum Classic, the same change is net-negative for a reason that is easy to miss. td on the wire is not a sync optimization. It is the wire-level expression of proof-of-work's fork-choice rule: in proof-of-work the canonical chain is the heaviest (most cumulative work), not the longest. eth/69 deletes that signal and replaces it with a block number (latest), i.e. chain length, the exact metric the protocol deliberately moved away from in 2015. Length cannot distinguish a heavy chain from a long, low-difficulty one, so ranking and chain discovery by length re-opens an attack class proof-of-work closed a decade ago. The exposure is bounded for an already-synced node (local fork choice still protects it) but real for syncing nodes, worst under snap sync, and cheap to amplify with sybils. The good ideas eth/69 also carries are separable from this premise, and an ETC-native protocol can take them without it.
What eth/69 was actually for
EIP-7642 is motivated by three post-Merge realities:
Total difficulty became meaningless. Post-Merge blocks have difficulty 0;
tdis constant. Fork choice moved to the consensus layer. Thetdfield inStatuswas dead weight on Ethereum mainnet.History expiry. Ethereum mainnet clients began dropping pre-Merge history.
BlockRangeUpdate(msg 0x11) lets peers advertise the block range they actually serve.Bloom-filter removal from receipts. Clients regenerate the bloom anyway, so carrying it on the wire is redundant.
These are Ethereum-mainnet, post-Merge concerns, and they do not all transfer the same way. The first is false for proof-of-work. The second is not pressing today, since the network is not expiring history, though the mechanism behind it could be useful later. The third is real, minor, and severable, and it is the one with value right now.
Message-flow comparison: eth/68 vs. eth/69 on a PoW client
It helps to pin down what each version does on the wire, from the moment a client opens a connection to the point it can decide which chain to follow.
eth/68

The td in Status is itself an unverified claim: a peer can put any number there. What makes it the right primitive is that td is the same quantity fork choice uses, and the client recomputes it on every header it imports. A false claim self-corrects. A peer claiming a huge td it cannot back with valid headers is exposed as soon as those headers are requested.
eth/69

Status no longer carries any weight signal, only latest, a block number. A client can fetch and PoW-check the claimed head, which proves the head exists, but length is not the fork-choice metric: knowing a peer is at a high block number does not tell you its chain is the heaviest. That gap is the whole problem, and it is sharpest exactly where proof-of-work and proof-of-stake differ.
Why proof-of-work puts total difficulty on the wire
Under proof-of-work the canonical chain is the one with the greatest accumulated work, the highest total difficulty, not the one with the most blocks. td in Status exists so that peers can identify and converge on that chain. Pre-Merge, NewBlock carried td as well (the wiki calls it the block's "score"), so a node could apply fork choice to a freshly announced block without recomputing anything.
The claim is provisional, not unforgeable, but it is the fork-choice quantity itself, so it carries no separate trust surface: the value on the wire and the value the client derives locally are the same number, continuously reconciled as headers import. This is a consensus concern, not a sync optimization. It predates fast sync (eth/63) and snap sync entirely. The wire carries td because proof-of-work defines the best chain by weight, and the network's job is to help nodes find that chain.
What removing it reopens: the long, low-difficulty chain
Replacing td with latest means ranking and discovering peers by chain length. In proof-of-work, length and weight can diverge, and an attacker can force the divergence cheaply.
Proof-of-work difficulty adjusts per block from the parent timestamp. By manipulating timestamps, an attacker with modest hashrate can mine a chain that is long but light: many blocks, each at a low difficulty target. Every one of those headers is individually valid, since each meets its own target, so per-header PoW validation passes for the entire chain. Only comparing total difficulty reveals that it carries less work than the honest chain.
This is the asymmetry that makes length dangerous as a ranking signal:
Under eth/68, the honest heavy chain advertises the higher
td. An attacker can claim a highertd, but cannot deliver headers that recompute to it: the lie fails on download. The heaviest chain a client can actually obtain wins.Under eth/69, the attacker's long-light chain advertises the higher
latest, and can deliver it, because every header is valid. A client ranking by length prioritizes downloading the attacker's chain, while the honest heavy-but-shorter chain, advertising a lower number, is deprioritized. Nothing on the wire says it is lighter. The client only learns that by computingtdlocally and comparing against an alternative it may have ranked below the attacker.
Who is actually exposed. A node that already holds the canonical heavy chain is safe: local fork choice never reorganizes to a lower-td chain regardless of what peers advertise. The exposure is for nodes that are syncing or behind and deciding which chain to download in the first place. It is amplified by sybil or eclipse pressure: an attacker does not need to fully eclipse a node, only to out-advertise on length, which is free, while the honest heavy chain naturally presents fewer blocks in this scenario. For a network with Ethereum Classic's history of 51% incidents, the heaviest-chain rule is load-bearing, and length is precisely the wrong primitive to expose at the discovery layer.
Where it bites hardest: snap sync
Snap sync is the worst case. It selects a pivot near the head from peer-claimed heights and downloads the state at that pivot without executing the chain that leads to it. It validates the pivot header's proof-of-work and the state trie against that header's stateRoot, but it does not verify that the pivot sits on the heaviest chain. If discovery is biased by length, the pivot can land on the attacker's long-light chain. The client then downloads gigabytes of state for a non-canonical chain, and only discovers the problem late, when it switches to block-by-block sync near the head, having wasted the entire state download, or worse, having served non-canonical state in the meantime. In full sync the damage is biased, slower convergence; in snap sync it is a wrong commitment of the pivot and the state that hangs off it.
Historical note: eth/62 chose td for exactly this, before fast or snap sync existed
The latest field eth/69 introduces is not new. A block number lived in Status once before, and was deliberately removed, for reasons specific to proof-of-work, and well before any of the sync machinery people now associate with the question existed.
The timeline:
eth/61 (2015) added the latest block number to
Status.eth/62 (2015) removed it again and replaced the chain-comparison mechanism with total difficulty. From then through eth/68,
Statuscarriedtdplus the best-block hash, never a number. The change is recorded tersely in the spec history: "The block number was added in eth/61 and removed in eth/62" (ethereum/devp2p#91). The eth/62 redesign was the PV62 "New Model syncing" spec referenced by go-ethereum#1380. That Ethereum Wiki page, deleted along with theethereum/wikirepo but recoverable from mirror clones, defines the synced chain explicitly by weight, not height:bestHashis "the hash of the best (i.e. highest TD) known block," and its "Basic Chain Syncing" section runs offtd, stating that "Status includes the Total Difficulty (TD) & hash of their best block … the client with the worst TD asks peer for full chain." PV62 is also the revision that eliminated the number-indexed messages (BlockHashesFromNumber,GetBlockHashes/BlockHashes).
The timing matters here: in 2015 there was no fast sync and no snap sync. Fast sync arrived with eth/63, snap years later. So td was not chosen to protect a pivot. It was chosen because proof-of-work's fork-choice rule is heaviest-chain, and length had just been shown to be the wrong signal to put on the wire. The pivot-selection failure described above is a later symptom of using length; the original reason to prefer td is older and more fundamental than the sync mode it now happens to hurt most.
eth/69 reverses the 2015 decision. It removes td and reintroduces a block number as the chain hint, the same field and the same "length as a proxy for chain quality" assumption that proof-of-work clients discarded then. The justification is sound for the network it targets: per EIP-7642, *"after the merge, the TDTD** field of the StatusStatus** message became meaningless since the difficulty of post-merge blocks are 0."* That sentence is true for proof-of-stake and false for proof-of-work.
Sources
ethereum/devp2p#91: "The block number was added in eth/61 and removed in eth/62."
go-ethereum#1380: eth/62 "New Model syncing" server implementation, citing the Ethereum Wiki wire-protocol spec.
Ethereum Wiki, Ethereum Wire Protocol: the original
ethereum/wikipage (repo since deleted), preserved in mirror clones such as Sberex/wiki. DefinesbestHashas "the hash of the best (i.e. highest TD) known block";NewBlockcarriestotalDifficulty"(aka score)"; syncing runs bytdcomparison.go-ethereum v1.3.3:
eth/protocol.go(statusData:tdplus best-block hash, no number);eth/sync.go(sync gated onpeer.Td()exceeding localtd).EIP-7642 (eth/69):
Statusformat change andtd-removal rationale. Discussion: eth-magicians.
The dilemma eth/69 forces, that eth/68 never did
After adopting eth/69, a proof-of-work client faces a fork in the road:
Bolt verification onto the length signal: fetch and PoW-check claimed heads, track claimed-versus-verified height, and still lack a wire weight signal, because a verified head does not tell you the chain is heaviest. You add work and remain worse off than eth/68.
Skip it: rank and discover by raw
latest, biasing syncing nodes toward long, low-difficulty chains, cheaply amplified by sybils, with snap sync committing its pivot and state to whatever length advertises.
eth/68 presented neither horn, because the signal it carries is the fork-choice quantity. The decision to adopt eth/69 manufactures a dilemma that did not previously exist.
The only real motivation, and why it doesn't hold
The real argument for adopting eth/69 is not interoperability with Ethereum. Post-Merge Ethereum nodes will not peer with a proof-of-work chain anyway: different ForkID, different network. The actual motivation is narrower: not wanting to maintain a divergent eth/68 stack of one's own. Stay on the version everyone upstream is moving to, and inherit the maintenance for free.
That argument is self-defeating on two counts.
First, adopting eth/69 increases the maintenance burden, not decreases it. To make it safe on proof-of-work you must add and maintain head-verification and claimed-versus-verified tracking, code with no upstream counterpart, because upstream is proof-of-stake and does not need it. You do not avoid maintaining a divergence; you take on a new one, and a security-relevant one.
Second, and more important: the upstream path is not merely a dead end, it is actively trending toward a protocol a proof-of-work chain cannot run. The eth specification already declares, in its own text, that block-propagation messages, NewBlock and NewBlockHashes, "will be removed from the protocol in a future version." These are the only mechanism by which a proof-of-work network disseminates newly mined blocks. Post-Merge Ethereum does not need them: its consensus layer gossips blocks out-of-band. A proof-of-work chain has no consensus layer; wire-level block propagation is load-bearing and irreplaceable.
So "tracking upstream" is not a stable strategy with a one-step cost. It is stepping onto a staircase whose announced destination is the removal of the very messages proof-of-work operation depends on. eth/69, which strips the weight signal, is one step down it. The version that strips block propagation is the bottom, already written into the spec as future intent. A network that commits to following the eth version line is committing to a protocol that has openly stated it is leaving proof-of-work behind.
The receipts-size change in eth/70 is a comparatively weak example of unfitness: a proof-of-work chain's gas schedule could conceivably grow into that condition someday. The block-propagation removal is not weak. It is a structural incompatibility, announced in advance, with no path to coexistence.
What eth/69 gets right
Listing the problems can make eth/69 sound like all cost. It is not. Several of its changes are good engineering, and the point about them is that they are separable from the premise that breaks proof-of-work:
Dropping the bloom filter from receipts removes data every client already regenerates. This one has immediate value and can be adopted today.
Advertising the block range a node serves (
BlockRangeUpdate) is useful wherever some nodes do not carry full history. That is already partly the case with pruning, and would matter more if the network ever chose to expire history. Not urgent today, but not inapplicable either.Trimming stale or redundant fields from the wire is sound maintenance in general.
None of these required removing total difficulty, and none of them are tied to proof-of-stake. They are mechanisms. The premise bundled alongside them, that chain weight no longer matters, is the only part that does not transfer. The constructive move is therefore neither to reject eth/69 wholesale nor to swallow it wholesale, but to take the mechanisms into a protocol defined on the network's own terms.
Worth considering: an ETC-native baseline (etc/1)
Less a formal proposal than a direction worth thinking about. If the goal were to own a minimal wire baseline rather than perpetually shadow a proof-of-stake roadmap, one option would be to namespace a protocol of one's own, call it etc/1, along these lines:
etc/1 = eth/68 semantics, minus the bloom filter in receipts.
This captures the immediately useful eth/69 mechanism (dropping the redundant bloom) while keeping everything that actually serves a proof-of-work network:
tdstays in-band, so the heaviest-chain signal remains the fork-choice quantity itself: self-correcting, with no head-verification bolted on, no claimed-versus-verified bookkeeping, and no length-versus-weight gap.No history-expiry machinery for now (no
BlockRangeUpdate), since the network is not expiring history today. If that ever changes, it is exactly the kind of mechanism a lateretc/Nadds deliberately.A self-owned namespace stops proof-of-stake-driven changes from dragging the proof-of-work baseline. The protocol evolves on the network's terms, not as a downstream of decisions made for a different consensus model.
A note on numbering: Ethereum's eth/NN lineage is a historical artifact. It climbed out of the proof-of-concept phase through the high fifties into eth/60 and onward. A proof-of-work chain inherits none of that history and has no reason to continue the sequence. Starting fresh at etc/1 is both honest about the lineage and a clean signal that this is an independent protocol, not a fork of someone else's version counter.
The network layer should evolve, on its own terms
Owning the namespace is not a vote for protocol stasis. The eth line will keep producing useful network-layer ideas, and a proof-of-work chain should be free to take them, the day its scale or needs call for each, whether in state synchronization, discovery, transaction propagation, or receipts. The point is to take them deliberately, under the network's own governance, the same way consensus rules already advance, through a hard-fork schedule and ECIP review that adopt what serves the chain and decline what does not. The wire is not a fixed substrate that must either track an external version counter verbatim or be abandoned; it is a living layer that can have its own versioned line, etc/1, then etc/2, and onward.
The discipline is simple: adopt mechanisms, reject premises. The bloom removal is a mechanism, adoptable when it fits. "Total difficulty is meaningless" is a premise, false under proof-of-work. The coming removal of block propagation is a premise made concrete, that the wire need not disseminate blocks because a consensus layer will, which is false on a chain that has no such layer. An independently-versioned etc/N line lets each of these be a deliberate decision rather than an inherited default.
A wire protocol version is a coordination decision
A wire protocol version is a shared interface, and that changes who gets to decide it. Unlike an internal optimization, a version only has meaning if peers agree on it: the eth/NN capability is negotiated in the Hello handshake precisely because a version "exists" on the network only when more than one party speaks it. That puts a version bump in the same family as a consensus change. It does not alter the state transition, but it defines how independent implementations must talk to each other to remain one network.
Ethereum treats it that way. Every wire version is paired with a Networking-category EIP, specified in the ethereum/devp2p repository, discussed in the open (Ethereum Magicians, All Core Devs), and implemented across clients in a coordinated way rather than shipped first and reconciled later:
eth/64: EIP-2364 (ForkID, from EIP-2124)
eth/65: EIP-2464 (pooled-transaction announcements)
eth/66: EIP-2481 (request ids)
eth/67: EIP-4938 (removal of GetNodeData)
eth/68: EIP-5793 (typed and sized tx announcements)
eth/69: EIP-7642
eth/70: EIP-7975
The pattern is consistent: propose, review across implementations, then adopt. The review is not ceremony. It is where assumptions get checked against every network that will run the change, which is exactly the step where a premise that holds for proof-of-stake but not for proof-of-work gets caught before a client ships it.
Ethereum Classic has the same kind of process in the ECIP track, and a network-layer change belongs there: proposed, reviewed by the client implementations and the community, and adopted once there is agreement that it serves the chain. Shipping a new wire version unilaterally in a single client, with no proposal and no cross-client discussion, skips that step. Whether or not the change turns out to be a good idea, doing it that way is a process failure. It substitutes one team's judgment for the coordination a shared interface requires, and it removes the one checkpoint designed to catch a premise that does not transfer. The objection is not to the ambition of evolving the wire. It is to evolving it without the discussion that makes the result legitimate and safe.
Closing
A protocol change designed for one consensus model should not be adopted wholesale by a chain running a different one without auditing the assumptions baked into it. eth/69 optimizes for a world where chain weight no longer matters, on a version line that has already announced it will stop carrying block propagation at all. A proof-of-work network lives in neither of those futures. A minimal alternative would be to take the one good idea, dropping the redundant bloom, into a baseline of our own, keep the weight signal proof-of-work actually needs, and stop treating a proof-of-stake roadmap as something we are obliged to follow off the edge.


Very well written Diego. Thanks for sharing!