forked from cerc-io/plugeth
all: make timestamp-based fork checks based on uint64 (#26474)
This PR changes the API so that uint64 is used for fork timestamps. It's a good choice because types.Header also uses uint64 for time. Co-authored-by: Felix Lange <fjl@twurst.com>
This commit is contained in:
co-authored by
Felix Lange
parent
59a48e0289
commit
2b57a27d9e
+25
-25
@@ -383,7 +383,7 @@ var (
|
||||
Ethash: new(EthashConfig),
|
||||
Clique: nil,
|
||||
}
|
||||
TestRules = TestChainConfig.Rules(new(big.Int), false, new(big.Int))
|
||||
TestRules = TestChainConfig.Rules(new(big.Int), false, 0)
|
||||
)
|
||||
|
||||
// NetworkNames are user friendly names to use in the chain spec banner.
|
||||
@@ -476,9 +476,9 @@ type ChainConfig struct {
|
||||
|
||||
// Fork scheduling was switched from blocks to timestamps here
|
||||
|
||||
ShanghaiTime *big.Int `json:"shanghaiTime,omitempty"` // Shanghai switch time (nil = no fork, 0 = already on shanghai)
|
||||
CancunTime *big.Int `json:"cancunTime,omitempty"` // Cancun switch time (nil = no fork, 0 = already on cancun)
|
||||
PragueTime *big.Int `json:"pragueTime,omitempty"` // Prague switch time (nil = no fork, 0 = already on prague)
|
||||
ShanghaiTime *uint64 `json:"shanghaiTime,omitempty"` // Shanghai switch time (nil = no fork, 0 = already on shanghai)
|
||||
CancunTime *uint64 `json:"cancunTime,omitempty"` // Cancun switch time (nil = no fork, 0 = already on cancun)
|
||||
PragueTime *uint64 `json:"pragueTime,omitempty"` // Prague switch time (nil = no fork, 0 = already on prague)
|
||||
|
||||
// TerminalTotalDifficulty is the amount of total difficulty reached by
|
||||
// the network that triggers the consensus upgrade.
|
||||
@@ -683,17 +683,17 @@ func (c *ChainConfig) IsTerminalPoWBlock(parentTotalDiff *big.Int, totalDiff *bi
|
||||
}
|
||||
|
||||
// IsShanghai returns whether time is either equal to the Shanghai fork time or greater.
|
||||
func (c *ChainConfig) IsShanghai(time *big.Int) bool {
|
||||
func (c *ChainConfig) IsShanghai(time uint64) bool {
|
||||
return isTimestampForked(c.ShanghaiTime, time)
|
||||
}
|
||||
|
||||
// IsCancun returns whether num is either equal to the Cancun fork time or greater.
|
||||
func (c *ChainConfig) IsCancun(time *big.Int) bool {
|
||||
func (c *ChainConfig) IsCancun(time uint64) bool {
|
||||
return isTimestampForked(c.CancunTime, time)
|
||||
}
|
||||
|
||||
// IsPrague returns whether num is either equal to the Prague fork time or greater.
|
||||
func (c *ChainConfig) IsPrague(time *big.Int) bool {
|
||||
func (c *ChainConfig) IsPrague(time uint64) bool {
|
||||
return isTimestampForked(c.PragueTime, time)
|
||||
}
|
||||
|
||||
@@ -702,7 +702,7 @@ func (c *ChainConfig) IsPrague(time *big.Int) bool {
|
||||
func (c *ChainConfig) CheckCompatible(newcfg *ChainConfig, height uint64, time uint64) *ConfigCompatError {
|
||||
var (
|
||||
bhead = new(big.Int).SetUint64(height)
|
||||
btime = new(big.Int).SetUint64(time)
|
||||
btime = time
|
||||
)
|
||||
// Iterate checkCompatible to find the lowest conflict.
|
||||
var lasterr *ConfigCompatError
|
||||
@@ -714,7 +714,7 @@ func (c *ChainConfig) CheckCompatible(newcfg *ChainConfig, height uint64, time u
|
||||
lasterr = err
|
||||
|
||||
if err.RewindToTime > 0 {
|
||||
btime.SetUint64(err.RewindToTime)
|
||||
btime = err.RewindToTime
|
||||
} else {
|
||||
bhead.SetUint64(err.RewindToBlock)
|
||||
}
|
||||
@@ -728,7 +728,7 @@ func (c *ChainConfig) CheckConfigForkOrder() error {
|
||||
type fork struct {
|
||||
name string
|
||||
block *big.Int // forks up to - and including the merge - were defined with block numbers
|
||||
timestamp *big.Int // forks after the merge are scheduled using timestamps
|
||||
timestamp *uint64 // forks after the merge are scheduled using timestamps
|
||||
optional bool // if true, the fork may be nil and next fork is still allowed
|
||||
}
|
||||
var lastFork fork
|
||||
@@ -769,7 +769,7 @@ func (c *ChainConfig) CheckConfigForkOrder() error {
|
||||
if lastFork.block != nil && lastFork.block.Cmp(cur.block) > 0 {
|
||||
return fmt.Errorf("unsupported fork ordering: %v enabled at block %v, but %v enabled at block %v",
|
||||
lastFork.name, lastFork.block, cur.name, cur.block)
|
||||
} else if lastFork.timestamp != nil && lastFork.timestamp.Cmp(cur.timestamp) > 0 {
|
||||
} else if lastFork.timestamp != nil && *lastFork.timestamp > *cur.timestamp {
|
||||
return fmt.Errorf("unsupported fork ordering: %v enabled at timestamp %v, but %v enabled at timestamp %v",
|
||||
lastFork.name, lastFork.timestamp, cur.name, cur.timestamp)
|
||||
}
|
||||
@@ -789,7 +789,7 @@ func (c *ChainConfig) CheckConfigForkOrder() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, headNumber *big.Int, headTimestamp *big.Int) *ConfigCompatError {
|
||||
func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, headNumber *big.Int, headTimestamp uint64) *ConfigCompatError {
|
||||
if isForkBlockIncompatible(c.HomesteadBlock, newcfg.HomesteadBlock, headNumber) {
|
||||
return newBlockCompatError("Homestead fork block", c.HomesteadBlock, newcfg.HomesteadBlock)
|
||||
}
|
||||
@@ -895,28 +895,28 @@ func configBlockEqual(x, y *big.Int) bool {
|
||||
|
||||
// isForkTimestampIncompatible returns true if a fork scheduled at timestamp s1
|
||||
// cannot be rescheduled to timestamp s2 because head is already past the fork.
|
||||
func isForkTimestampIncompatible(s1, s2, head *big.Int) bool {
|
||||
func isForkTimestampIncompatible(s1, s2 *uint64, head uint64) bool {
|
||||
return (isTimestampForked(s1, head) || isTimestampForked(s2, head)) && !configTimestampEqual(s1, s2)
|
||||
}
|
||||
|
||||
// isTimestampForked returns whether a fork scheduled at timestamp s is active
|
||||
// at the given head timestamp. Whilst this method is the same as isBlockForked,
|
||||
// they are explicitly separate for clearer reading.
|
||||
func isTimestampForked(s, head *big.Int) bool {
|
||||
if s == nil || head == nil {
|
||||
func isTimestampForked(s *uint64, head uint64) bool {
|
||||
if s == nil {
|
||||
return false
|
||||
}
|
||||
return s.Cmp(head) <= 0
|
||||
return *s <= head
|
||||
}
|
||||
|
||||
func configTimestampEqual(x, y *big.Int) bool {
|
||||
func configTimestampEqual(x, y *uint64) bool {
|
||||
if x == nil {
|
||||
return y == nil
|
||||
}
|
||||
if y == nil {
|
||||
return x == nil
|
||||
}
|
||||
return x.Cmp(y) == 0
|
||||
return *x == *y
|
||||
}
|
||||
|
||||
// ConfigCompatError is raised if the locally-stored blockchain is initialised with a
|
||||
@@ -928,7 +928,7 @@ type ConfigCompatError struct {
|
||||
StoredBlock, NewBlock *big.Int
|
||||
|
||||
// timestamps of the stored and new configurations if time based forking
|
||||
StoredTime, NewTime *big.Int
|
||||
StoredTime, NewTime *uint64
|
||||
|
||||
// the block number to which the local chain must be rewound to correct the error
|
||||
RewindToBlock uint64
|
||||
@@ -959,12 +959,12 @@ func newBlockCompatError(what string, storedblock, newblock *big.Int) *ConfigCom
|
||||
return err
|
||||
}
|
||||
|
||||
func newTimestampCompatError(what string, storedtime, newtime *big.Int) *ConfigCompatError {
|
||||
var rew *big.Int
|
||||
func newTimestampCompatError(what string, storedtime, newtime *uint64) *ConfigCompatError {
|
||||
var rew *uint64
|
||||
switch {
|
||||
case storedtime == nil:
|
||||
rew = newtime
|
||||
case newtime == nil || storedtime.Cmp(newtime) < 0:
|
||||
case newtime == nil || *storedtime < *newtime:
|
||||
rew = storedtime
|
||||
default:
|
||||
rew = newtime
|
||||
@@ -975,8 +975,8 @@ func newTimestampCompatError(what string, storedtime, newtime *big.Int) *ConfigC
|
||||
NewTime: newtime,
|
||||
RewindToTime: 0,
|
||||
}
|
||||
if rew != nil && rew.Sign() > 0 {
|
||||
err.RewindToTime = rew.Uint64() - 1
|
||||
if rew != nil {
|
||||
err.RewindToTime = *rew - 1
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -1002,7 +1002,7 @@ type Rules struct {
|
||||
}
|
||||
|
||||
// Rules ensures c's ChainID is not nil.
|
||||
func (c *ChainConfig) Rules(num *big.Int, isMerge bool, timestamp *big.Int) Rules {
|
||||
func (c *ChainConfig) Rules(num *big.Int, isMerge bool, timestamp uint64) Rules {
|
||||
chainID := c.ChainID
|
||||
if chainID == nil {
|
||||
chainID = new(big.Int)
|
||||
|
||||
+28
-6
@@ -21,8 +21,12 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/math"
|
||||
)
|
||||
|
||||
func u64(val uint64) *uint64 { return &val }
|
||||
|
||||
func TestCheckCompatible(t *testing.T) {
|
||||
type test struct {
|
||||
stored, new *ChainConfig
|
||||
@@ -91,19 +95,19 @@ func TestCheckCompatible(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
stored: &ChainConfig{ShanghaiTime: big.NewInt(10)},
|
||||
new: &ChainConfig{ShanghaiTime: big.NewInt(20)},
|
||||
stored: &ChainConfig{ShanghaiTime: u64(10)},
|
||||
new: &ChainConfig{ShanghaiTime: u64(20)},
|
||||
headTimestamp: 9,
|
||||
wantErr: nil,
|
||||
},
|
||||
{
|
||||
stored: &ChainConfig{ShanghaiTime: big.NewInt(10)},
|
||||
new: &ChainConfig{ShanghaiTime: big.NewInt(20)},
|
||||
stored: &ChainConfig{ShanghaiTime: u64(10)},
|
||||
new: &ChainConfig{ShanghaiTime: u64(20)},
|
||||
headTimestamp: 25,
|
||||
wantErr: &ConfigCompatError{
|
||||
What: "Shanghai fork timestamp",
|
||||
StoredTime: big.NewInt(10),
|
||||
NewTime: big.NewInt(20),
|
||||
StoredTime: u64(10),
|
||||
NewTime: u64(20),
|
||||
RewindToTime: 9,
|
||||
},
|
||||
},
|
||||
@@ -116,3 +120,21 @@ func TestCheckCompatible(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigRules(t *testing.T) {
|
||||
c := &ChainConfig{
|
||||
ShanghaiTime: u64(500),
|
||||
}
|
||||
var stamp uint64
|
||||
if r := c.Rules(big.NewInt(0), true, stamp); r.IsShanghai {
|
||||
t.Errorf("expected %v to not be shanghai", stamp)
|
||||
}
|
||||
stamp = 500
|
||||
if r := c.Rules(big.NewInt(0), true, stamp); !r.IsShanghai {
|
||||
t.Errorf("expected %v to be shanghai", stamp)
|
||||
}
|
||||
stamp = math.MaxInt64
|
||||
if r := c.Rules(big.NewInt(0), true, stamp); !r.IsShanghai {
|
||||
t.Errorf("expected %v to be shanghai", stamp)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user