@@ -21,6 +21,7 @@ import (
21
21
"errors"
22
22
"fmt"
23
23
"io"
24
+ "math"
24
25
"math/big"
25
26
"runtime"
26
27
"slices"
98
99
errInvalidNewChain = errors .New ("invalid new chain" )
99
100
)
100
101
102
+ var (
103
+ forkReadyInterval = 3 * time .Minute
104
+ )
105
+
101
106
const (
102
107
bodyCacheLimit = 256
103
108
blockCacheLimit = 256
@@ -268,6 +273,8 @@ type BlockChain struct {
268
273
processor Processor // Block transaction processor interface
269
274
vmConfig vm.Config
270
275
logger * tracing.Hooks
276
+
277
+ lastForkReadyAlert time.Time // Last time there was a fork readiness print out
271
278
}
272
279
273
280
// NewBlockChain returns a fully initialised block chain using information
@@ -1825,6 +1832,9 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool, makeWitness
1825
1832
trieDiffNodes , trieBufNodes , _ := bc .triedb .Size ()
1826
1833
stats .report (chain , it .index , snapDiffItems , snapBufItems , trieDiffNodes , trieBufNodes , setHead )
1827
1834
1835
+ // Print confirmation that a future fork is scheduled, but not yet active.
1836
+ bc .logForkReadiness (block )
1837
+
1828
1838
if ! setHead {
1829
1839
// After merge we expect few side chains. Simply count
1830
1840
// all blocks the CL gives us for GC processing time
@@ -1858,6 +1868,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool, makeWitness
1858
1868
"root" , block .Root ())
1859
1869
}
1860
1870
}
1871
+
1861
1872
stats .ignored += it .remaining ()
1862
1873
return witness , it .index , err
1863
1874
}
@@ -2455,6 +2466,22 @@ func (bc *BlockChain) reportBlock(block *types.Block, res *ProcessResult, err er
2455
2466
log .Error (summarizeBadBlock (block , receipts , bc .Config (), err ))
2456
2467
}
2457
2468
2469
+ // logForkReadiness will write a log when a future fork is scheduled, but not
2470
+ // active. This is useful so operators know their client is ready for the fork.
2471
+ func (bc * BlockChain ) logForkReadiness (block * types.Block ) {
2472
+ c := bc .Config ()
2473
+ current , last := c .LatestFork (block .Time ()), c .LatestFork (math .MaxUint64 )
2474
+ var at time.Time
2475
+ if t := c .Timestamp (last ); t != nil {
2476
+ at = time .Unix (int64 (* t ), 0 )
2477
+ }
2478
+ if current < last && time .Now ().After (bc .lastForkReadyAlert .Add (forkReadyInterval )) {
2479
+ log .Info ("Ready for fork activation" , "fork" , last , "date" , at .Format (time .RFC822 ),
2480
+ "remaining" , time .Until (at ).Round (time .Second ), "timestamp" , at .Unix ())
2481
+ bc .lastForkReadyAlert = time .Now ()
2482
+ }
2483
+ }
2484
+
2458
2485
// summarizeBadBlock returns a string summarizing the bad block and other
2459
2486
// relevant information.
2460
2487
func summarizeBadBlock (block * types.Block , receipts []* types.Receipt , config * params.ChainConfig , err error ) string {
0 commit comments