HeaderChain.writeHeadersAndSetHead (fork choice)¶
| Source (upstream v1.17.4) | Current | |
|---|---|---|
| File | core/headerchain.go |
headerchain.go |
| Symbol | HeaderChain.writeHeadersAndSetHead |
HeaderChain.writeHeadersAndSetHead |
| Ref | v1.17.4 |
etc/v1.17.4-full-node |
Modified in-place: takes a *ForkChoice and consults forker.ReorgNeeded before adopting the incoming headers, so TD fork choice (and MESS via the reorgFilter) applies at the header-insertion path too, not only at block insertion. Upstream v1.17.4 dropped the forker here (post-merge the CL drives the head); getc re-threads it, matching core-geth (which passes the forker into writeHeadersAndSetHead / InsertHeaderChain). The block is a near-verbatim port of core-geth's, guarded by
if forker != nilsince getc's forker is nil on non-PoW chains. Threaded through InsertHeaderChain -> BlockChain.InsertHeaderChain (which passes bc.forker). Guarded by TestHeaderInsertionForkChoiceTD.
Diff — vs upstream v1.17.4 (modified in-place)¶
--- a/core/headerchain.go
+++ b/core/headerchain.go
@@ -6,7 +6,7 @@
// without the real blocks. Hence, writing headers directly should only be done
// in two scenarios: pure-header mode of operation (light clients), or properly
// separated header/block phases (non-archive clients).
-func (hc *HeaderChain) writeHeadersAndSetHead(headers []*types.Header) (*headerWriteResult, error) {
+func (hc *HeaderChain) writeHeadersAndSetHead(headers []*types.Header, forker *ForkChoice) (*headerWriteResult, error) {
inserted, err := hc.WriteHeaders(headers)
if err != nil {
return nil, err
@@ -22,6 +22,17 @@
lastHeader: lastHeader,
}
)
+ // Ask the fork choicer if the reorg is necessary
+ if forker != nil {
+ if reorg, err := forker.ReorgNeeded(hc.CurrentHeader(), lastHeader); err != nil {
+ return nil, err
+ } else if !reorg {
+ if inserted != 0 {
+ result.status = SideStatTy
+ }
+ return result, nil
+ }
+ }
// Special case, all the inserted headers are already on the canonical
// header chain, skip the reorg operation.
if hc.GetCanonicalHash(lastHeader.Number.Uint64()) == lastHash && lastHeader.Number.Uint64() <= hc.CurrentHeader().Number.Uint64() {
core-geth validation — +4 -1
| | | |---|---| | File | [`headerchain.go`](https://github.com/etclabscore/core-geth/blob/v1.12.20/core/headerchain.go) | | Symbol | `HeaderChain.writeHeadersAndSetHead` | | Ref | `v1.12.20` |--- a/core-geth/core/headerchain.go
+++ b/etc/core/headerchain.go
@@ -1,5 +1,6 @@
// writeHeadersAndSetHead writes a batch of block headers and applies the last
-// header as the chain head if the fork choicer says it's ok to update the chain.
+// header as the chain head.
+//
// Note: This method is not concurrent-safe with inserting blocks simultaneously
// into the chain, as side effects caused by reorganisations cannot be emulated
// without the real blocks. Hence, writing headers directly should only be done
@@ -22,6 +23,7 @@
}
)
// Ask the fork choicer if the reorg is necessary
+ if forker != nil {
if reorg, err := forker.ReorgNeeded(hc.CurrentHeader(), lastHeader); err != nil {
return nil, err
} else if !reorg {
@@ -30,6 +32,7 @@
}
return result, nil
}
+ }
// Special case, all the inserted headers are already on the canonical
// header chain, skip the reorg operation.
if hc.GetCanonicalHash(lastHeader.Number.Uint64()) == lastHash && lastHeader.Number.Uint64() <= hc.CurrentHeader().Number.Uint64() {