internal/ethapi: add geth_fork method

This commit is contained in:
Sina Mahmoodi 2024-08-30 09:00:15 +02:00 committed by Martin Holst Swende
parent b20fef2e62
commit 5bb52e2be3
No known key found for this signature in database
GPG key ID: 683B438C05A5DDF0
5 changed files with 133 additions and 6 deletions

View file

@ -212,7 +212,7 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV2(update engine.ForkchoiceStateV1, pa
if params.BeaconRoot != nil {
return engine.STATUS_INVALID, engine.InvalidPayloadAttributes.With(errors.New("unexpected beacon root"))
}
switch api.eth.BlockChain().Config().LatestFork(params.Timestamp) {
switch api.eth.BlockChain().Config().LatestPostLondonFork(params.Timestamp) {
case forks.Paris:
if params.Withdrawals != nil {
return engine.STATUS_INVALID, engine.InvalidPayloadAttributes.With(errors.New("withdrawals before shanghai"))
@ -238,7 +238,8 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV3(update engine.ForkchoiceStateV1, pa
if params.BeaconRoot == nil {
return engine.STATUS_INVALID, engine.InvalidPayloadAttributes.With(errors.New("missing beacon root"))
}
if api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Cancun && api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Prague {
if api.eth.BlockChain().Config().LatestPostLondonFork(params.Timestamp) != forks.Cancun &&
api.eth.BlockChain().Config().LatestPostLondonFork(params.Timestamp) != forks.Prague {
return engine.STATUS_INVALID, engine.UnsupportedFork.With(errors.New("forkchoiceUpdatedV3 must only be called for cancun payloads"))
}
}
@ -568,7 +569,7 @@ func (api *ConsensusAPI) NewPayloadV2(params engine.ExecutableData) (engine.Payl
if api.eth.BlockChain().Config().IsCancun(api.eth.BlockChain().Config().LondonBlock, params.Timestamp) {
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("can't use newPayloadV2 post-cancun"))
}
if api.eth.BlockChain().Config().LatestFork(params.Timestamp) == forks.Shanghai {
if api.eth.BlockChain().Config().LatestPostLondonFork(params.Timestamp) == forks.Shanghai {
if params.Withdrawals == nil {
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil withdrawals post-shanghai"))
}
@ -605,7 +606,7 @@ func (api *ConsensusAPI) NewPayloadV3(params engine.ExecutableData, versionedHas
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil beaconRoot post-cancun"))
}
if api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Cancun {
if api.eth.BlockChain().Config().LatestPostLondonFork(params.Timestamp) != forks.Cancun {
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.UnsupportedFork.With(errors.New("newPayloadV3 must only be called for cancun payloads"))
}
return api.newPayload(params, versionedHashes, beaconRoot, nil, false)

View file

@ -1958,6 +1958,25 @@ func (api *NetAPI) Version() string {
return fmt.Sprintf("%d", api.networkVersion)
}
// GethAPI offers geth-specific API methods.
type GethAPI struct {
b Backend
}
// NewGethAPI creates a new net API instance.
func NewGethAPI(b Backend) *GethAPI {
return &GethAPI{b: b}
}
// Fork returns the latest enabled fork as of the given block.
func (api *GethAPI) Fork(ctx context.Context, num rpc.BlockNumber) (string, error) {
b, err := api.b.BlockByNumber(ctx, num)
if err != nil {
return "", fmt.Errorf("block #%d not found", num)
}
return api.b.ChainConfig().LatestFork(b.Number(), b.Time()).String(), nil
}
// checkTxFee is an internal function used to check whether the fee of
// the given transaction is _reasonable_(under the cap).
func checkTxFee(gasPrice *big.Int, gas uint64, cap float64) error {

View file

@ -720,3 +720,17 @@ web3._extend({
],
});
`
const GethJs = `
web3._extend({
property: 'geth',
methods:
[
new web3._extend.Method({
name: 'fork',
call: 'geth_fork',
params: 1
}),
],
});
`

View file

@ -505,6 +505,13 @@ func (c *ChainConfig) IsTerminalPoWBlock(parentTotalDiff *big.Int, totalDiff *bi
return parentTotalDiff.Cmp(c.TerminalTotalDifficulty) < 0 && totalDiff.Cmp(c.TerminalTotalDifficulty) >= 0
}
// IsParis returns whether the given block is either equal to the Paris (merge)
// fork or greater.
// Note: Only usable for post-merge networks where MergeNetsplitBlock has been configured.
func (c *ChainConfig) IsParis(num *big.Int) bool {
return c.IsLondon(num) && isBlockForked(c.MergeNetsplitBlock, num)
}
// IsShanghai returns whether time is either equal to the Shanghai fork time or greater.
func (c *ChainConfig) IsShanghai(num *big.Int, time uint64) bool {
return c.IsLondon(num) && isTimestampForked(c.ShanghaiTime, time)
@ -704,8 +711,8 @@ func (c *ChainConfig) ElasticityMultiplier() uint64 {
return DefaultElasticityMultiplier
}
// LatestFork returns the latest time-based fork that would be active for the given time.
func (c *ChainConfig) LatestFork(time uint64) forks.Fork {
// LatestPostLondonFork returns the latest time-based fork that would be active for the given time.
func (c *ChainConfig) LatestPostLondonFork(time uint64) forks.Fork {
// Assume last non-time-based fork has passed.
london := c.LondonBlock
@ -721,6 +728,47 @@ func (c *ChainConfig) LatestFork(time uint64) forks.Fork {
}
}
func (c *ChainConfig) LatestFork(num *big.Int, time uint64) forks.Fork {
switch {
case c.IsPrague(num, time):
return forks.Prague
case c.IsCancun(num, time):
return forks.Cancun
case c.IsShanghai(num, time):
return forks.Shanghai
case c.IsParis(num):
return forks.Paris
case c.IsGrayGlacier(num):
return forks.GrayGlacier
case c.IsArrowGlacier(num):
return forks.ArrowGlacier
case c.IsLondon(num):
return forks.London
case c.IsBerlin(num):
return forks.Berlin
case c.IsMuirGlacier(num):
return forks.MuirGlacier
case c.IsIstanbul(num):
return forks.Istanbul
case c.IsPetersburg(num):
return forks.Petersburg
case c.IsConstantinople(num):
return forks.Constantinople
case c.IsByzantium(num):
return forks.Byzantium
case c.IsEIP158(num):
return forks.SpuriousDragon
case c.IsEIP155(num):
return forks.TangerineWhistle
case c.IsEIP150(num):
return forks.DAO
case c.IsHomestead(num):
return forks.Homestead
default:
return forks.Frontier
}
}
// isForkBlockIncompatible returns true if a fork scheduled at block s1 cannot be
// rescheduled to block s2 because head is already past the fork.
func isForkBlockIncompatible(s1, s2, head *big.Int) bool {

View file

@ -40,3 +40,48 @@ const (
Cancun
Prague
)
func (f Fork) String() string {
switch f {
case Prague:
return "prague"
case Cancun:
return "cancun"
case Shanghai:
return "shanghai"
case Paris:
return "paris"
case GrayGlacier:
return "grayGlacier"
case ArrowGlacier:
return "arrowGlacier"
case London:
return "london"
case Berlin:
return "berlin"
case MuirGlacier:
return "muirGlacier"
case Istanbul:
return "istanbul"
case Petersburg:
return "petersburg"
case Constantinople:
return "constantinople"
case Byzantium:
return "byzantium"
case SpuriousDragon:
return "spuriousDragon"
case TangerineWhistle:
return "tangerineWhistle"
case DAO:
return "dao"
case Homestead:
return "homestead"
case FrontierThawing:
return "frontierThawing"
case Frontier:
return "frontier"
default:
panic("unknown fork")
}
}