@@ -27,12 +27,16 @@ import (
2727 "github.com/ethereum/go-ethereum/common/math"
2828 "github.com/ethereum/go-ethereum/core/types"
2929 "github.com/ethereum/go-ethereum/log"
30+ "github.com/ethereum/go-ethereum/params"
3031)
3132
3233// ChainReader defines a small collection of methods needed to access the local
3334// blockchain during header verification. It's implemented by both blockchain
3435// and lightchain.
3536type ChainReader interface {
37+ // Config retrieves the header chain's chain configuration.
38+ Config () * params.ChainConfig
39+
3640 // GetTd returns the total difficulty of a local block.
3741 GetTd (common.Hash , uint64 ) * big.Int
3842}
@@ -45,12 +49,7 @@ type ChainReader interface {
4549type ForkChoice struct {
4650 chain ChainReader
4751 rand * mrand.Rand
48-
49- // transitioned is the flag whether the chain has started(or finished)
50- // the transition. It's triggered by receiving the first "NewHead" message
51- // from the external consensus engine.
52- transitioned bool
53- lock sync.RWMutex
52+ lock sync.RWMutex
5453
5554 // preserve is a helper function used in td fork choice.
5655 // Miners will prefer to choose the local mined block if the
@@ -59,17 +58,16 @@ type ForkChoice struct {
5958 preserve func (header * types.Header ) bool
6059}
6160
62- func NewForkChoice (chainReader ChainReader , transitioned bool , preserve func (header * types.Header ) bool ) * ForkChoice {
61+ func NewForkChoice (chainReader ChainReader , preserve func (header * types.Header ) bool ) * ForkChoice {
6362 // Seed a fast but crypto originating random generator
6463 seed , err := crand .Int (crand .Reader , big .NewInt (math .MaxInt64 ))
6564 if err != nil {
6665 log .Crit ("Failed to initialize random seed" , "err" , err )
6766 }
6867 return & ForkChoice {
69- chain : chainReader ,
70- rand : mrand .New (mrand .NewSource (seed .Int64 ())),
71- transitioned : transitioned ,
72- preserve : preserve ,
68+ chain : chainReader ,
69+ rand : mrand .New (mrand .NewSource (seed .Int64 ())),
70+ preserve : preserve ,
7371 }
7472}
7573
@@ -82,19 +80,19 @@ func (f *ForkChoice) Reorg(current *types.Header, header *types.Header) (bool, e
8280 f .lock .RLock ()
8381 defer f .lock .RUnlock ()
8482
85- // Accept the new header as the chain head if the transition
86- // is already triggered. We assume all the headers after the
87- // transition come from the trusted consensus layer.
88- if f .transitioned {
89- return true , nil
90- }
9183 var (
9284 localTD = f .chain .GetTd (current .Hash (), current .Number .Uint64 ())
9385 externTd = f .chain .GetTd (header .Hash (), header .Number .Uint64 ())
9486 )
9587 if localTD == nil || externTd == nil {
9688 return false , errors .New ("missing td" )
9789 }
90+ // Accept the new header as the chain head if the transition
91+ // is already triggered. We assume all the headers after the
92+ // transition come from the trusted consensus layer.
93+ if ttd := f .chain .Config ().TerminalTotalDifficulty ; ttd != nil && ttd .Cmp (externTd ) <= 0 {
94+ return true , nil
95+ }
9896 // If the total difficulty is higher than our known, add it to the canonical chain
9997 // Second clause in the if statement reduces the vulnerability to selfish mining.
10098 // Please refer to http://www.cs.cornell.edu/~ie53/publications/btcProcFC.pdf
@@ -113,11 +111,3 @@ func (f *ForkChoice) Reorg(current *types.Header, header *types.Header) (bool, e
113111 }
114112 return reorg , nil
115113}
116-
117- // MarkTransitioned marks the transition has started.
118- func (f * ForkChoice ) MarkTransitioned () {
119- f .lock .Lock ()
120- defer f .lock .Unlock ()
121-
122- f .transitioned = true
123- }
0 commit comments