From 0063c14ed39349c38cc96a473ed1f3ce21755734 Mon Sep 17 00:00:00 2001 From: Daniel Liu Date: Thu, 13 Jun 2024 11:26:12 +0800 Subject: [PATCH] cmd, eth, internal, les: add gasprice cap (#21212) --- cmd/XDC/main.go | 1 + cmd/XDC/usage.go | 1 + cmd/utils/flags.go | 8 ++++++++ eth/api_backend.go | 4 ++++ eth/config.go | 5 +++++ eth/gen_config.go | 6 ++++++ internal/ethapi/api.go | 8 ++++++++ internal/ethapi/backend.go | 1 + les/api_backend.go | 4 ++++ 9 files changed, 38 insertions(+) diff --git a/cmd/XDC/main.go b/cmd/XDC/main.go index 419978ba6e..cf21779c6d 100644 --- a/cmd/XDC/main.go +++ b/cmd/XDC/main.go @@ -148,6 +148,7 @@ var ( utils.WSAllowedOriginsFlag, utils.IPCDisabledFlag, utils.IPCPathFlag, + utils.RPCGlobalTxFeeCap, } whisperFlags = []cli.Flag{ diff --git a/cmd/XDC/usage.go b/cmd/XDC/usage.go index e6b2fc961f..0bea6301db 100644 --- a/cmd/XDC/usage.go +++ b/cmd/XDC/usage.go @@ -156,6 +156,7 @@ var AppHelpFlagGroups = []flagGroup{ utils.IPCPathFlag, utils.RPCCORSDomainFlag, utils.RPCVirtualHostsFlag, + utils.RPCGlobalTxFeeCap, utils.JSpathFlag, utils.ExecFlag, utils.PreloadJSFlag, diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index a9fd25c492..f981cce29b 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -363,6 +363,11 @@ var ( Usage: "Sets a cap on gas that can be used in eth_call/estimateGas (0=infinite)", Value: eth.DefaultConfig.RPCGasCap, } + RPCGlobalTxFeeCap = cli.Float64Flag{ + Name: "rpc.txfeecap", + Usage: "Sets a cap on transaction fee (in ether) that can be sent via the RPC APIs (0 = no cap)", + Value: eth.DefaultConfig.RPCTxFeeCap, + } // Logging and debug settings EthStatsURLFlag = cli.StringFlag{ Name: "ethstats", @@ -1171,6 +1176,9 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) { if ctx.GlobalIsSet(DocRootFlag.Name) { cfg.DocRoot = ctx.GlobalString(DocRootFlag.Name) } + if ctx.GlobalIsSet(RPCGlobalTxFeeCap.Name) { + cfg.RPCTxFeeCap = ctx.GlobalFloat64(RPCGlobalTxFeeCap.Name) + } if ctx.GlobalIsSet(ExtraDataFlag.Name) { cfg.ExtraData = []byte(ctx.GlobalString(ExtraDataFlag.Name)) } diff --git a/eth/api_backend.go b/eth/api_backend.go index c087ec2d38..161ee5ddfb 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -356,6 +356,10 @@ func (b *EthApiBackend) AccountManager() *accounts.Manager { return b.eth.AccountManager() } +func (b *EthApiBackend) RPCTxFeeCap() float64 { + return b.eth.config.RPCTxFeeCap +} + func (b *EthApiBackend) BloomStatus() (uint64, uint64) { sections, _, _ := b.eth.bloomIndexer.Sections() return params.BloomBitsBlocks, sections diff --git a/eth/config.go b/eth/config.go index 73a95aa675..79fb0220a5 100644 --- a/eth/config.go +++ b/eth/config.go @@ -56,6 +56,7 @@ var DefaultConfig = Config{ Blocks: 20, Percentile: 60, }, + RPCTxFeeCap: 1, // 1 ether } func init() { @@ -118,6 +119,10 @@ type Config struct { // RPCGasCap is the global gas cap for eth-call variants. RPCGasCap uint64 + + // RPCTxFeeCap is the global transaction fee(price * gaslimit) cap for + // send-transction variants. The unit is ether. + RPCTxFeeCap float64 } type configMarshaling struct { diff --git a/eth/gen_config.go b/eth/gen_config.go index 1959ee559d..abfed29e35 100644 --- a/eth/gen_config.go +++ b/eth/gen_config.go @@ -37,6 +37,7 @@ func (c Config) MarshalTOML() (interface{}, error) { EnablePreimageRecording bool DocRoot string `toml:"-"` RPCGasCap uint64 + RPCTxFeeCap float64 } var enc Config enc.Genesis = c.Genesis @@ -60,6 +61,7 @@ func (c Config) MarshalTOML() (interface{}, error) { enc.EnablePreimageRecording = c.EnablePreimageRecording enc.DocRoot = c.DocRoot enc.RPCGasCap = c.RPCGasCap + enc.RPCTxFeeCap = c.RPCTxFeeCap return &enc, nil } @@ -87,6 +89,7 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { EnablePreimageRecording *bool DocRoot *string `toml:"-"` RPCGasCap *uint64 + RPCTxFeeCap *float64 } var dec Config if err := unmarshal(&dec); err != nil { @@ -155,5 +158,8 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { if dec.RPCGasCap != nil { c.RPCGasCap = *dec.RPCGasCap } + if dec.RPCTxFeeCap != nil { + c.RPCTxFeeCap = *dec.RPCTxFeeCap + } return nil } diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 650135e067..d94ec30f34 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -2372,6 +2372,14 @@ func SubmitTransaction(ctx context.Context, b Backend, tx *types.Transaction) (c if tx.To() != nil && tx.IsSpecialTransaction() { return common.Hash{}, errors.New("Dont allow transaction sent to BlockSigners & RandomizeSMC smart contract via API") } + + // If the transaction fee cap is already specified, ensure the + // fee of the given transaction is _reasonable_. + feeEth := new(big.Float).Quo(new(big.Float).SetInt(new(big.Int).Mul(tx.GasPrice(), new(big.Int).SetUint64(tx.Gas()))), new(big.Float).SetInt(big.NewInt(params.Ether))) + feeFloat, _ := feeEth.Float64() + if b.RPCTxFeeCap() != 0 && feeFloat > b.RPCTxFeeCap() { + return common.Hash{}, fmt.Errorf("tx fee (%.2f ether) exceeds the configured cap (%.2f ether)", feeFloat, b.RPCTxFeeCap()) + } if err := b.SendTx(ctx, tx); err != nil { return common.Hash{}, err } diff --git a/internal/ethapi/backend.go b/internal/ethapi/backend.go index 00a9aea8ac..d862977d2c 100644 --- a/internal/ethapi/backend.go +++ b/internal/ethapi/backend.go @@ -52,6 +52,7 @@ type Backend interface { EventMux() *event.TypeMux AccountManager() *accounts.Manager RPCGasCap() uint64 // global gas cap for eth_call over rpc: DoS protection + RPCTxFeeCap() float64 // global tx fee cap for all transaction related APIs XDCxService() *XDCx.XDCX LendingService() *XDCxlending.Lending diff --git a/les/api_backend.go b/les/api_backend.go index abdd952a6e..3e93efe960 100644 --- a/les/api_backend.go +++ b/les/api_backend.go @@ -273,6 +273,10 @@ func (b *LesApiBackend) RPCGasCap() uint64 { return b.eth.config.RPCGasCap } +func (b *LesApiBackend) RPCTxFeeCap() float64 { + return b.eth.config.RPCTxFeeCap +} + func (b *LesApiBackend) BloomStatus() (uint64, uint64) { if b.eth.bloomIndexer == nil { return 0, 0