internal/ethapi: add geth_fork method

pull/30451/head
Sina Mahmoodi 2 months ago
parent 9b5d1412cc
commit d91a2abc9e
  1. 8
      eth/catalyst/api.go
  2. 19
      internal/ethapi/api.go
  3. 3
      internal/ethapi/backend.go
  4. 15
      internal/web3ext/web3ext.go
  5. 52
      params/config.go
  6. 45
      params/forks/forks.go

@ -194,7 +194,7 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV2(update engine.ForkchoiceStateV1, pa
if params.BeaconRoot != nil { if params.BeaconRoot != nil {
return engine.STATUS_INVALID, engine.InvalidPayloadAttributes.With(errors.New("unexpected beacon root")) 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: case forks.Paris:
if params.Withdrawals != nil { if params.Withdrawals != nil {
return engine.STATUS_INVALID, engine.InvalidPayloadAttributes.With(errors.New("withdrawals before shanghai")) return engine.STATUS_INVALID, engine.InvalidPayloadAttributes.With(errors.New("withdrawals before shanghai"))
@ -220,7 +220,7 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV3(update engine.ForkchoiceStateV1, pa
if params.BeaconRoot == nil { if params.BeaconRoot == nil {
return engine.STATUS_INVALID, engine.InvalidPayloadAttributes.With(errors.New("missing beacon root")) return engine.STATUS_INVALID, engine.InvalidPayloadAttributes.With(errors.New("missing beacon root"))
} }
if api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Cancun { if api.eth.BlockChain().Config().LatestPostLondonFork(params.Timestamp) != forks.Cancun {
return engine.STATUS_INVALID, engine.UnsupportedFork.With(errors.New("forkchoiceUpdatedV3 must only be called for cancun payloads")) return engine.STATUS_INVALID, engine.UnsupportedFork.With(errors.New("forkchoiceUpdatedV3 must only be called for cancun payloads"))
} }
} }
@ -465,7 +465,7 @@ func (api *ConsensusAPI) NewPayloadV2(params engine.ExecutableData) (engine.Payl
if api.eth.BlockChain().Config().IsCancun(api.eth.BlockChain().Config().LondonBlock, params.Timestamp) { 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")) 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 { if params.Withdrawals == nil {
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil withdrawals post-shanghai")) return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil withdrawals post-shanghai"))
} }
@ -502,7 +502,7 @@ func (api *ConsensusAPI) NewPayloadV3(params engine.ExecutableData, versionedHas
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil beaconRoot post-cancun")) 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 engine.PayloadStatusV1{Status: engine.INVALID}, engine.UnsupportedFork.With(errors.New("newPayloadV3 must only be called for cancun payloads"))
} }
return api.newPayload(params, versionedHashes, beaconRoot) return api.newPayload(params, versionedHashes, beaconRoot)

@ -2164,6 +2164,25 @@ func (api *NetAPI) Version() string {
return fmt.Sprintf("%d", api.networkVersion) 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 // checkTxFee is an internal function used to check whether the fee of
// the given transaction is _reasonable_(under the cap). // the given transaction is _reasonable_(under the cap).
func checkTxFee(gasPrice *big.Int, gas uint64, cap float64) error { func checkTxFee(gasPrice *big.Int, gas uint64, cap float64) error {

@ -123,6 +123,9 @@ func GetAPIs(apiBackend Backend) []rpc.API {
}, { }, {
Namespace: "personal", Namespace: "personal",
Service: NewPersonalAccountAPI(apiBackend, nonceLock), Service: NewPersonalAccountAPI(apiBackend, nonceLock),
}, {
Namespace: "geth",
Service: NewGethAPI(apiBackend),
}, },
} }
} }

@ -31,6 +31,7 @@ var Modules = map[string]string{
"les": LESJs, "les": LESJs,
"vflux": VfluxJs, "vflux": VfluxJs,
"dev": DevJs, "dev": DevJs,
"geth": GethJs,
} }
const CliqueJs = ` const CliqueJs = `
@ -887,3 +888,17 @@ web3._extend({
], ],
}); });
` `
const GethJs = `
web3._extend({
property: 'geth',
methods:
[
new web3._extend.Method({
name: 'fork',
call: 'geth_fork',
params: 1
}),
],
});
`

@ -533,6 +533,13 @@ func (c *ChainConfig) IsTerminalPoWBlock(parentTotalDiff *big.Int, totalDiff *bi
return parentTotalDiff.Cmp(c.TerminalTotalDifficulty) < 0 && totalDiff.Cmp(c.TerminalTotalDifficulty) >= 0 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. // IsShanghai returns whether time is either equal to the Shanghai fork time or greater.
func (c *ChainConfig) IsShanghai(num *big.Int, time uint64) bool { func (c *ChainConfig) IsShanghai(num *big.Int, time uint64) bool {
return c.IsLondon(num) && isTimestampForked(c.ShanghaiTime, time) return c.IsLondon(num) && isTimestampForked(c.ShanghaiTime, time)
@ -732,8 +739,8 @@ func (c *ChainConfig) ElasticityMultiplier() uint64 {
return DefaultElasticityMultiplier return DefaultElasticityMultiplier
} }
// LatestFork returns the latest time-based fork that would be active for the given time. // LatestPostLondonFork returns the latest time-based fork that would be active for the given time.
func (c *ChainConfig) LatestFork(time uint64) forks.Fork { func (c *ChainConfig) LatestPostLondonFork(time uint64) forks.Fork {
// Assume last non-time-based fork has passed. // Assume last non-time-based fork has passed.
london := c.LondonBlock london := c.LondonBlock
@ -749,6 +756,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 // isForkBlockIncompatible returns true if a fork scheduled at block s1 cannot be
// rescheduled to block s2 because head is already past the fork. // rescheduled to block s2 because head is already past the fork.
func isForkBlockIncompatible(s1, s2, head *big.Int) bool { func isForkBlockIncompatible(s1, s2, head *big.Int) bool {

@ -40,3 +40,48 @@ const (
Cancun Cancun
Prague 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")
}
}

Loading…
Cancel
Save