Skip to content

Commit 13b157a

Browse files
authored
core,params: add fork readiness indicator in logs (#31340)
closes #31310 This has been requested a few times in the past and I think it is a nice quality-of-life improvement for users. At a predetermined interval, there will now be a "Fork ready" log when a future fork is scheduled, but not yet active. It can only possibly print after block import, which kinda avoids the scenario where the client isn't progressing or is syncing and the user thinks it's "ready" because it sees a ready log. New output: ```console INFO [03-08|21:32:57.472] Imported new potential chain segment number=7 hash=aa24ee..f09e62 blocks=1 txs=0 mgas=0.000 elapsed="874.916µs" mgasps=0.000 snapdiffs=973.00B triediffs=7.05KiB triedirty=0.00B INFO [03-08|21:32:57.473] Ready for fork activation fork=Prague date="18 Mar 25 19:29 CET" remaining=237h57m0s timestamp=1,742,322,597 INFO [03-08|21:32:57.475] Chain head was updated number=7 hash=aa24ee..f09e62 root=19b0de..8d32f2 elapsed="129.125µs" ``` Easiest way to verify this behavior is to apply this patch and run `geth --dev --dev.period=12` ```patch diff --git a/params/config.go b/params/config.go index 9c7719d..030c4f80e7 100644 --- a/params/config.go +++ b/params/config.go @@ -174,7 +174,7 @@ var ( ShanghaiTime: newUint64(0), CancunTime: newUint64(0), TerminalTotalDifficulty: big.NewInt(0), - PragueTime: newUint64(0), + PragueTime: newUint64(uint64(time.Now().Add(time.Hour * 300).Unix())), BlobScheduleConfig: &BlobScheduleConfig{ Cancun: DefaultCancunBlobConfig, Prague: DefaultPragueBlobConfig, ```
1 parent 50b5f31 commit 13b157a

File tree

3 files changed

+78
-1
lines changed

3 files changed

+78
-1
lines changed

core/blockchain.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"errors"
2222
"fmt"
2323
"io"
24+
"math"
2425
"math/big"
2526
"runtime"
2627
"slices"
@@ -100,6 +101,10 @@ var (
100101
errInvalidNewChain = errors.New("invalid new chain")
101102
)
102103

104+
var (
105+
forkReadyInterval = 3 * time.Minute
106+
)
107+
103108
const (
104109
bodyCacheLimit = 256
105110
blockCacheLimit = 256
@@ -275,6 +280,8 @@ type BlockChain struct {
275280
processor Processor // Block transaction processor interface
276281
vmConfig vm.Config
277282
logger *tracing.Hooks
283+
284+
lastForkReadyAlert time.Time // Last time there was a fork readiness print out
278285
}
279286

280287
// NewBlockChain returns a fully initialised block chain using information
@@ -1884,6 +1891,9 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool, makeWitness
18841891
trieDiffNodes, trieBufNodes, _ := bc.triedb.Size()
18851892
stats.report(chain, it.index, snapDiffItems, snapBufItems, trieDiffNodes, trieBufNodes, setHead)
18861893

1894+
// Print confirmation that a future fork is scheduled, but not yet active.
1895+
bc.logForkReadiness(block)
1896+
18871897
if !setHead {
18881898
// After merge we expect few side chains. Simply count
18891899
// all blocks the CL gives us for GC processing time
@@ -1917,6 +1927,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool, makeWitness
19171927
"root", block.Root())
19181928
}
19191929
}
1930+
19201931
stats.ignored += it.remaining()
19211932
return witness, it.index, err
19221933
}
@@ -2514,6 +2525,23 @@ func (bc *BlockChain) reportBlock(block *types.Block, res *ProcessResult, err er
25142525
log.Error(summarizeBadBlock(block, receipts, bc.Config(), err))
25152526
}
25162527

2528+
// logForkReadiness will write a log when a future fork is scheduled, but not
2529+
// active. This is useful so operators know their client is ready for the fork.
2530+
func (bc *BlockChain) logForkReadiness(block *types.Block) {
2531+
c := bc.Config()
2532+
current, last := c.LatestFork(block.Time()), c.LatestFork(math.MaxUint64)
2533+
t := c.Timestamp(last)
2534+
if t == nil {
2535+
return
2536+
}
2537+
at := time.Unix(int64(*t), 0)
2538+
if current < last && time.Now().After(bc.lastForkReadyAlert.Add(forkReadyInterval)) {
2539+
log.Info("Ready for fork activation", "fork", last, "date", at.Format(time.RFC822),
2540+
"remaining", time.Until(at).Round(time.Second), "timestamp", at.Unix())
2541+
bc.lastForkReadyAlert = time.Now()
2542+
}
2543+
}
2544+
25172545
// summarizeBadBlock returns a string summarizing the bad block and other
25182546
// relevant information.
25192547
func summarizeBadBlock(block *types.Block, receipts []*types.Receipt, config *params.ChainConfig, err error) string {

params/config.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -909,6 +909,23 @@ func (c *ChainConfig) LatestFork(time uint64) forks.Fork {
909909
}
910910
}
911911

912+
// Timestamp returns the timestamp associated with the fork or returns nil if
913+
// the fork isn't defined or isn't a time-based fork.
914+
func (c *ChainConfig) Timestamp(fork forks.Fork) *uint64 {
915+
switch {
916+
case fork == forks.Osaka:
917+
return c.OsakaTime
918+
case fork == forks.Prague:
919+
return c.PragueTime
920+
case fork == forks.Cancun:
921+
return c.CancunTime
922+
case fork == forks.Shanghai:
923+
return c.ShanghaiTime
924+
default:
925+
return nil
926+
}
927+
}
928+
912929
// isForkBlockIncompatible returns true if a fork scheduled at block s1 cannot be
913930
// rescheduled to block s2 because head is already past the fork.
914931
func isForkBlockIncompatible(s1, s2, head *big.Int) bool {

params/forks/forks.go

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ package forks
2020
type Fork int
2121

2222
const (
23-
Frontier = iota
23+
Frontier Fork = iota
2424
FrontierThawing
2525
Homestead
2626
DAO
@@ -41,3 +41,35 @@ const (
4141
Prague
4242
Osaka
4343
)
44+
45+
// String implements fmt.Stringer.
46+
func (f Fork) String() string {
47+
s, ok := forkToString[f]
48+
if !ok {
49+
return "Unknown fork"
50+
}
51+
return s
52+
}
53+
54+
var forkToString = map[Fork]string{
55+
Frontier: "Frontier",
56+
FrontierThawing: "Frontier Thawing",
57+
Homestead: "Homestead",
58+
DAO: "DAO",
59+
TangerineWhistle: "Tangerine Whistle",
60+
SpuriousDragon: "Spurious Dragon",
61+
Byzantium: "Byzantium",
62+
Constantinople: "Constantinople",
63+
Petersburg: "Petersburg",
64+
Istanbul: "Istanbul",
65+
MuirGlacier: "Muir Glacier",
66+
Berlin: "Berlin",
67+
London: "London",
68+
ArrowGlacier: "Arrow Glacier",
69+
GrayGlacier: "Gray Glacier",
70+
Paris: "Paris",
71+
Shanghai: "Shanghai",
72+
Cancun: "Cancun",
73+
Prague: "Prague",
74+
Osaka: "Osaka",
75+
}

0 commit comments

Comments
 (0)