forked from cerc-io/plugeth
cmd, eth, internal, les: add txfee cap (#21212)
* cmd, eth, internal, les: add gasprice cap * cmd/utils, eth: add default value for gasprice cap * all: use txfee cap * cmd, eth: add fix * cmd, internal: address comments
This commit is contained in:
parent
bcf19bc4be
commit
56a319b9da
@ -186,6 +186,7 @@ var (
|
|||||||
utils.IPCPathFlag,
|
utils.IPCPathFlag,
|
||||||
utils.InsecureUnlockAllowedFlag,
|
utils.InsecureUnlockAllowedFlag,
|
||||||
utils.RPCGlobalGasCap,
|
utils.RPCGlobalGasCap,
|
||||||
|
utils.RPCGlobalTxFeeCap,
|
||||||
}
|
}
|
||||||
|
|
||||||
whisperFlags = []cli.Flag{
|
whisperFlags = []cli.Flag{
|
||||||
|
@ -176,6 +176,7 @@ var AppHelpFlagGroups = []flagGroup{
|
|||||||
utils.GraphQLCORSDomainFlag,
|
utils.GraphQLCORSDomainFlag,
|
||||||
utils.GraphQLVirtualHostsFlag,
|
utils.GraphQLVirtualHostsFlag,
|
||||||
utils.RPCGlobalGasCap,
|
utils.RPCGlobalGasCap,
|
||||||
|
utils.RPCGlobalTxFeeCap,
|
||||||
utils.JSpathFlag,
|
utils.JSpathFlag,
|
||||||
utils.ExecFlag,
|
utils.ExecFlag,
|
||||||
utils.PreloadJSFlag,
|
utils.PreloadJSFlag,
|
||||||
|
@ -478,6 +478,11 @@ var (
|
|||||||
Name: "rpc.gascap",
|
Name: "rpc.gascap",
|
||||||
Usage: "Sets a cap on gas that can be used in eth_call/estimateGas",
|
Usage: "Sets a cap on gas that can be used in eth_call/estimateGas",
|
||||||
}
|
}
|
||||||
|
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
|
// Logging and debug settings
|
||||||
EthStatsURLFlag = cli.StringFlag{
|
EthStatsURLFlag = cli.StringFlag{
|
||||||
Name: "ethstats",
|
Name: "ethstats",
|
||||||
@ -1560,6 +1565,9 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) {
|
|||||||
if ctx.GlobalIsSet(RPCGlobalGasCap.Name) {
|
if ctx.GlobalIsSet(RPCGlobalGasCap.Name) {
|
||||||
cfg.RPCGasCap = new(big.Int).SetUint64(ctx.GlobalUint64(RPCGlobalGasCap.Name))
|
cfg.RPCGasCap = new(big.Int).SetUint64(ctx.GlobalUint64(RPCGlobalGasCap.Name))
|
||||||
}
|
}
|
||||||
|
if ctx.GlobalIsSet(RPCGlobalTxFeeCap.Name) {
|
||||||
|
cfg.RPCTxFeeCap = ctx.GlobalFloat64(RPCGlobalTxFeeCap.Name)
|
||||||
|
}
|
||||||
if ctx.GlobalIsSet(DNSDiscoveryFlag.Name) {
|
if ctx.GlobalIsSet(DNSDiscoveryFlag.Name) {
|
||||||
urls := ctx.GlobalString(DNSDiscoveryFlag.Name)
|
urls := ctx.GlobalString(DNSDiscoveryFlag.Name)
|
||||||
if urls == "" {
|
if urls == "" {
|
||||||
|
@ -293,6 +293,10 @@ func (b *EthAPIBackend) RPCGasCap() *big.Int {
|
|||||||
return b.eth.config.RPCGasCap
|
return b.eth.config.RPCGasCap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *EthAPIBackend) RPCTxFeeCap() float64 {
|
||||||
|
return b.eth.config.RPCTxFeeCap
|
||||||
|
}
|
||||||
|
|
||||||
func (b *EthAPIBackend) BloomStatus() (uint64, uint64) {
|
func (b *EthAPIBackend) BloomStatus() (uint64, uint64) {
|
||||||
sections, _, _ := b.eth.bloomIndexer.Sections()
|
sections, _, _ := b.eth.bloomIndexer.Sections()
|
||||||
return params.BloomBitsBlocks, sections
|
return params.BloomBitsBlocks, sections
|
||||||
|
@ -64,6 +64,7 @@ var DefaultConfig = Config{
|
|||||||
Blocks: 20,
|
Blocks: 20,
|
||||||
Percentile: 60,
|
Percentile: 60,
|
||||||
},
|
},
|
||||||
|
RPCTxFeeCap: 1, // 1 ether
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -159,6 +160,10 @@ type Config struct {
|
|||||||
// RPCGasCap is the global gas cap for eth-call variants.
|
// RPCGasCap is the global gas cap for eth-call variants.
|
||||||
RPCGasCap *big.Int `toml:",omitempty"`
|
RPCGasCap *big.Int `toml:",omitempty"`
|
||||||
|
|
||||||
|
// RPCTxFeeCap is the global transaction fee(price * gaslimit) cap for
|
||||||
|
// send-transction variants. The unit is ether.
|
||||||
|
RPCTxFeeCap float64 `toml:",omitempty"`
|
||||||
|
|
||||||
// Checkpoint is a hardcoded checkpoint which can be nil.
|
// Checkpoint is a hardcoded checkpoint which can be nil.
|
||||||
Checkpoint *params.TrustedCheckpoint `toml:",omitempty"`
|
Checkpoint *params.TrustedCheckpoint `toml:",omitempty"`
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ func (c Config) MarshalTOML() (interface{}, error) {
|
|||||||
TrieCleanCache int
|
TrieCleanCache int
|
||||||
TrieDirtyCache int
|
TrieDirtyCache int
|
||||||
TrieTimeout time.Duration
|
TrieTimeout time.Duration
|
||||||
|
SnapshotCache int
|
||||||
Miner miner.Config
|
Miner miner.Config
|
||||||
Ethash ethash.Config
|
Ethash ethash.Config
|
||||||
TxPool core.TxPoolConfig
|
TxPool core.TxPoolConfig
|
||||||
@ -49,10 +50,9 @@ func (c Config) MarshalTOML() (interface{}, error) {
|
|||||||
EWASMInterpreter string
|
EWASMInterpreter string
|
||||||
EVMInterpreter string
|
EVMInterpreter string
|
||||||
RPCGasCap *big.Int `toml:",omitempty"`
|
RPCGasCap *big.Int `toml:",omitempty"`
|
||||||
|
RPCTxFeeCap float64 `toml:",omitempty"`
|
||||||
Checkpoint *params.TrustedCheckpoint `toml:",omitempty"`
|
Checkpoint *params.TrustedCheckpoint `toml:",omitempty"`
|
||||||
CheckpointOracle *params.CheckpointOracleConfig `toml:",omitempty"`
|
CheckpointOracle *params.CheckpointOracleConfig `toml:",omitempty"`
|
||||||
OverrideIstanbul *big.Int `toml:",omitempty"`
|
|
||||||
OverrideMuirGlacier *big.Int `toml:",omitempty"`
|
|
||||||
}
|
}
|
||||||
var enc Config
|
var enc Config
|
||||||
enc.Genesis = c.Genesis
|
enc.Genesis = c.Genesis
|
||||||
@ -77,6 +77,7 @@ func (c Config) MarshalTOML() (interface{}, error) {
|
|||||||
enc.TrieCleanCache = c.TrieCleanCache
|
enc.TrieCleanCache = c.TrieCleanCache
|
||||||
enc.TrieDirtyCache = c.TrieDirtyCache
|
enc.TrieDirtyCache = c.TrieDirtyCache
|
||||||
enc.TrieTimeout = c.TrieTimeout
|
enc.TrieTimeout = c.TrieTimeout
|
||||||
|
enc.SnapshotCache = c.SnapshotCache
|
||||||
enc.Miner = c.Miner
|
enc.Miner = c.Miner
|
||||||
enc.Ethash = c.Ethash
|
enc.Ethash = c.Ethash
|
||||||
enc.TxPool = c.TxPool
|
enc.TxPool = c.TxPool
|
||||||
@ -86,6 +87,7 @@ func (c Config) MarshalTOML() (interface{}, error) {
|
|||||||
enc.EWASMInterpreter = c.EWASMInterpreter
|
enc.EWASMInterpreter = c.EWASMInterpreter
|
||||||
enc.EVMInterpreter = c.EVMInterpreter
|
enc.EVMInterpreter = c.EVMInterpreter
|
||||||
enc.RPCGasCap = c.RPCGasCap
|
enc.RPCGasCap = c.RPCGasCap
|
||||||
|
enc.RPCTxFeeCap = c.RPCTxFeeCap
|
||||||
enc.Checkpoint = c.Checkpoint
|
enc.Checkpoint = c.Checkpoint
|
||||||
enc.CheckpointOracle = c.CheckpointOracle
|
enc.CheckpointOracle = c.CheckpointOracle
|
||||||
return &enc, nil
|
return &enc, nil
|
||||||
@ -116,6 +118,7 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
|
|||||||
TrieCleanCache *int
|
TrieCleanCache *int
|
||||||
TrieDirtyCache *int
|
TrieDirtyCache *int
|
||||||
TrieTimeout *time.Duration
|
TrieTimeout *time.Duration
|
||||||
|
SnapshotCache *int
|
||||||
Miner *miner.Config
|
Miner *miner.Config
|
||||||
Ethash *ethash.Config
|
Ethash *ethash.Config
|
||||||
TxPool *core.TxPoolConfig
|
TxPool *core.TxPoolConfig
|
||||||
@ -125,10 +128,9 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
|
|||||||
EWASMInterpreter *string
|
EWASMInterpreter *string
|
||||||
EVMInterpreter *string
|
EVMInterpreter *string
|
||||||
RPCGasCap *big.Int `toml:",omitempty"`
|
RPCGasCap *big.Int `toml:",omitempty"`
|
||||||
|
RPCTxFeeCap *float64 `toml:",omitempty"`
|
||||||
Checkpoint *params.TrustedCheckpoint `toml:",omitempty"`
|
Checkpoint *params.TrustedCheckpoint `toml:",omitempty"`
|
||||||
CheckpointOracle *params.CheckpointOracleConfig `toml:",omitempty"`
|
CheckpointOracle *params.CheckpointOracleConfig `toml:",omitempty"`
|
||||||
OverrideIstanbul *big.Int `toml:",omitempty"`
|
|
||||||
OverrideMuirGlacier *big.Int `toml:",omitempty"`
|
|
||||||
}
|
}
|
||||||
var dec Config
|
var dec Config
|
||||||
if err := unmarshal(&dec); err != nil {
|
if err := unmarshal(&dec); err != nil {
|
||||||
@ -200,6 +202,9 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
|
|||||||
if dec.TrieTimeout != nil {
|
if dec.TrieTimeout != nil {
|
||||||
c.TrieTimeout = *dec.TrieTimeout
|
c.TrieTimeout = *dec.TrieTimeout
|
||||||
}
|
}
|
||||||
|
if dec.SnapshotCache != nil {
|
||||||
|
c.SnapshotCache = *dec.SnapshotCache
|
||||||
|
}
|
||||||
if dec.Miner != nil {
|
if dec.Miner != nil {
|
||||||
c.Miner = *dec.Miner
|
c.Miner = *dec.Miner
|
||||||
}
|
}
|
||||||
@ -227,6 +232,9 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
|
|||||||
if dec.RPCGasCap != nil {
|
if dec.RPCGasCap != nil {
|
||||||
c.RPCGasCap = dec.RPCGasCap
|
c.RPCGasCap = dec.RPCGasCap
|
||||||
}
|
}
|
||||||
|
if dec.RPCTxFeeCap != nil {
|
||||||
|
c.RPCTxFeeCap = *dec.RPCTxFeeCap
|
||||||
|
}
|
||||||
if dec.Checkpoint != nil {
|
if dec.Checkpoint != nil {
|
||||||
c.Checkpoint = dec.Checkpoint
|
c.Checkpoint = dec.Checkpoint
|
||||||
}
|
}
|
||||||
|
@ -1520,6 +1520,13 @@ func (args *SendTxArgs) toTransaction() *types.Transaction {
|
|||||||
|
|
||||||
// SubmitTransaction is a helper function that submits tx to txPool and logs a message.
|
// SubmitTransaction is a helper function that submits tx to txPool and logs a message.
|
||||||
func SubmitTransaction(ctx context.Context, b Backend, tx *types.Transaction) (common.Hash, error) {
|
func SubmitTransaction(ctx context.Context, b Backend, tx *types.Transaction) (common.Hash, error) {
|
||||||
|
// 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 {
|
if err := b.SendTx(ctx, tx); err != nil {
|
||||||
return common.Hash{}, err
|
return common.Hash{}, err
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,8 @@ type Backend interface {
|
|||||||
ChainDb() ethdb.Database
|
ChainDb() ethdb.Database
|
||||||
AccountManager() *accounts.Manager
|
AccountManager() *accounts.Manager
|
||||||
ExtRPCEnabled() bool
|
ExtRPCEnabled() bool
|
||||||
RPCGasCap() *big.Int // global gas cap for eth_call over rpc: DoS protection
|
RPCGasCap() *big.Int // global gas cap for eth_call over rpc: DoS protection
|
||||||
|
RPCTxFeeCap() float64 // global tx fee cap for all transaction related APIs
|
||||||
|
|
||||||
// Blockchain API
|
// Blockchain API
|
||||||
SetHead(number uint64)
|
SetHead(number uint64)
|
||||||
|
@ -262,6 +262,10 @@ func (b *LesApiBackend) RPCGasCap() *big.Int {
|
|||||||
return b.eth.config.RPCGasCap
|
return b.eth.config.RPCGasCap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *LesApiBackend) RPCTxFeeCap() float64 {
|
||||||
|
return b.eth.config.RPCTxFeeCap
|
||||||
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) BloomStatus() (uint64, uint64) {
|
func (b *LesApiBackend) BloomStatus() (uint64, uint64) {
|
||||||
if b.eth.bloomIndexer == nil {
|
if b.eth.bloomIndexer == nil {
|
||||||
return 0, 0
|
return 0, 0
|
||||||
|
Loading…
Reference in New Issue
Block a user