Skip to content

HeaderChain.WriteHeaders (TD)

Source (upstream v1.17.3) Current
File core/headerchain.go headerchain.go
Symbol HeaderChain.WriteHeaders HeaderChain.WriteHeaders
Ref v1.17.3 etc/v1.17.3-full-node

Modified in-place on upstream v1.17.3: reject PoW headers whose parent TD is missing, advance the running TD per header, and write rawdb.WriteTd + tdCache for newly inserted headers — reviving the TD bookkeeping upstream removed when it nuked total difficulty.

Diff — vs upstream v1.17.3 (modified in-place)

--- a/core/headerchain.go
+++ b/core/headerchain.go
@@ -9,6 +9,15 @@
    if !hc.HasHeader(headers[0].ParentHash, headers[0].Number.Uint64()-1) {
        return 0, consensus.ErrUnknownAncestor
    }
+   // Get parent TD for chain sync. For PoW chains (ETC), parent TD must
+   // exist — reject headers without it (cf. core-geth WriteHeaders).
+   // Post-merge chains don't use TD so nil is acceptable. Gate on IsPow()
+   // rather than Ethash != nil so PoS configs that retain an Ethash block
+   // (upstream merge configs) aren't tripped by a missing TD.
+   parentTd := hc.GetTd(headers[0].ParentHash, headers[0].Number.Uint64()-1)
+   if parentTd == nil && hc.config.IsPow() {
+       return 0, consensus.ErrUnknownAncestor
+   }
    var (
        inserted    []rawdb.NumberHash // Ephemeral lookup of number/hash for the chain
        parentKnown = true             // Set to true to force hc.HasHeader check the first iteration
@@ -25,12 +34,22 @@
            hash = header.Hash()
        }
        number := header.Number.Uint64()
+       // Advance the running TD for every header, regardless of whether it
+       // is already known. Otherwise a batch shaped like [known, new] would
+       // persist the new header's TD without the known sibling's difficulty.
+       if parentTd != nil {
+           parentTd = new(big.Int).Add(parentTd, header.Difficulty)
+       }

        // If the parent was not present, store it
        // If the header is already known, skip it, otherwise store
        alreadyKnown := parentKnown && hc.HasHeader(hash, number)
        if !alreadyKnown {
            rawdb.WriteHeader(batch, header)
+           if parentTd != nil {
+               rawdb.WriteTd(batch, hash, number, parentTd)
+               hc.tdCache.Add(hash, new(big.Int).Set(parentTd))
+           }
            inserted = append(inserted, rawdb.NumberHash{Number: number, Hash: hash})
            hc.headerCache.Add(hash, header)
            hc.numberCache.Add(hash, number)

← Total Difficulty (TD)