Skip to content

core/forkchoice_pow.go — Version Comparison

v1.16.8 v1.17.3
Branch etc/v1.16.8-full-node etc/v1.17.3-full-node
Delta +133 -0 +152 -0

Diff between branches

diff --git a/core/forkchoice_pow.go b/core/forkchoice_pow.go
index c6e69fd57..c8e8eb849 100644
--- a/core/forkchoice_pow.go
+++ b/core/forkchoice_pow.go
@@ -32,6 +32,7 @@ import (

    "github.com/ethereum/go-ethereum/common"
    "github.com/ethereum/go-ethereum/core/types"
+   "github.com/ethereum/go-ethereum/event"
    "github.com/ethereum/go-ethereum/log"
    "github.com/ethereum/go-ethereum/params"
 )
@@ -66,6 +67,17 @@ type ForkChoice struct {
    // warranted by TD should actually be applied.  Returns nil if allowed,
    // non-nil error if the reorg must be rejected.
    reorgFilter func(current, extern *types.Header) error
+
+   // sideBlockFeed delivers the headers of blocks that lost the fork choice
+   // (were not adopted as canonical) to subscribers — namely the PoW miner,
+   // which collects them as uncle candidates.
+   sideBlockFeed event.Feed
+}
+
+// SubscribeSideBlocks registers a subscription for side-block headers (uncle
+// candidates) surfaced by the fork choice.
+func (f *ForkChoice) SubscribeSideBlocks(ch chan<- ChainSideEvent) event.Subscription {
+   return f.sideBlockFeed.Subscribe(ch)
 }

 func NewForkChoice(chainReader ChainReader, preserve func(header *types.Header) bool) *ForkChoice {
@@ -86,7 +98,14 @@ func NewForkChoice(chainReader ChainReader, preserve func(header *types.Header)
 // 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())
← Back to Version Comparison