internal/ethapi: disable sending of non eip155 replay protected tx #22339 (#971)

* internal/ethapi: disable sending of non eip155 replay protected tx #22339

* eth: optimize the initialization logic of EthAPIBackend

* fix
This commit is contained in:
JukLee0ira 2025-04-25 11:55:52 +08:00 committed by GitHub
parent 08dbbe705d
commit b4308ba733
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 41 additions and 9 deletions

View file

@ -161,6 +161,7 @@ var (
utils.IPCDisabledFlag, utils.IPCDisabledFlag,
utils.IPCPathFlag, utils.IPCPathFlag,
utils.RPCGlobalTxFeeCap, utils.RPCGlobalTxFeeCap,
utils.AllowUnprotectedTxs,
} }
metricsFlags = []cli.Flag{ metricsFlags = []cli.Flag{

View file

@ -546,6 +546,11 @@ var (
Usage: "Comma separated list of JavaScript files to preload into the console", Usage: "Comma separated list of JavaScript files to preload into the console",
Category: flags.APICategory, Category: flags.APICategory,
} }
AllowUnprotectedTxs = &cli.BoolFlag{
Name: "rpc.allow-unprotected-txs",
Usage: "Allow for unprotected (non EIP155 signed) transactions to be submitted via RPC",
Category: flags.APICategory,
}
// Network Settings // Network Settings
MaxPeersFlag = &cli.IntFlag{ MaxPeersFlag = &cli.IntFlag{
@ -1014,6 +1019,9 @@ func setHTTP(ctx *cli.Context, cfg *node.Config) {
if ctx.IsSet(HTTPIdleTimeoutFlag.Name) { if ctx.IsSet(HTTPIdleTimeoutFlag.Name) {
cfg.HTTPTimeouts.IdleTimeout = ctx.Duration(HTTPIdleTimeoutFlag.Name) cfg.HTTPTimeouts.IdleTimeout = ctx.Duration(HTTPIdleTimeoutFlag.Name)
} }
if ctx.IsSet(AllowUnprotectedTxs.Name) {
cfg.AllowUnprotectedTxs = ctx.Bool(AllowUnprotectedTxs.Name)
}
cfg.HTTPCors = SplitAndTrim(ctx.String(HTTPCORSDomainFlag.Name)) cfg.HTTPCors = SplitAndTrim(ctx.String(HTTPCORSDomainFlag.Name))
cfg.HTTPModules = SplitAndTrim(ctx.String(HTTPApiFlag.Name)) cfg.HTTPModules = SplitAndTrim(ctx.String(HTTPApiFlag.Name))
cfg.HTTPVirtualHosts = SplitAndTrim(ctx.String(HTTPVirtualHostsFlag.Name)) cfg.HTTPVirtualHosts = SplitAndTrim(ctx.String(HTTPVirtualHostsFlag.Name))

View file

@ -54,9 +54,10 @@ import (
// EthAPIBackend implements ethapi.Backend for full nodes // EthAPIBackend implements ethapi.Backend for full nodes
type EthAPIBackend struct { type EthAPIBackend struct {
eth *Ethereum allowUnprotectedTxs bool
gpo *gasprice.Oracle eth *Ethereum
XDPoS *XDPoS.XDPoS gpo *gasprice.Oracle
XDPoS *XDPoS.XDPoS
} }
func (b *EthAPIBackend) ChainConfig() *params.ChainConfig { func (b *EthAPIBackend) ChainConfig() *params.ChainConfig {
@ -369,6 +370,10 @@ func (b *EthAPIBackend) EventMux() *event.TypeMux {
return b.eth.EventMux() return b.eth.EventMux()
} }
func (b *EthAPIBackend) UnprotectedAllowed() bool {
return b.allowUnprotectedTxs
}
func (b *EthAPIBackend) RPCGasCap() uint64 { func (b *EthAPIBackend) RPCGasCap() uint64 {
return b.eth.config.RPCGasCap return b.eth.config.RPCGasCap
} }

View file

@ -244,10 +244,19 @@ func New(stack *node.Node, config *ethconfig.Config, XDCXServ *XDCx.XDCX, lendin
eth.miner = miner.New(eth, eth.chainConfig, eth.EventMux(), eth.engine, stack.Config().AnnounceTxs) eth.miner = miner.New(eth, eth.chainConfig, eth.EventMux(), eth.engine, stack.Config().AnnounceTxs)
eth.miner.SetExtra(makeExtraData(config.ExtraData)) eth.miner.SetExtra(makeExtraData(config.ExtraData))
var xdPoS *XDPoS.XDPoS = nil
if eth.chainConfig.XDPoS != nil { if eth.chainConfig.XDPoS != nil {
eth.ApiBackend = &EthAPIBackend{eth, nil, eth.engine.(*XDPoS.XDPoS)} xdPoS = eth.engine.(*XDPoS.XDPoS)
} else { }
eth.ApiBackend = &EthAPIBackend{eth, nil, nil} eth.ApiBackend = &EthAPIBackend{
allowUnprotectedTxs: stack.Config().AllowUnprotectedTxs,
eth: eth,
gpo: nil,
XDPoS: xdPoS,
}
if eth.ApiBackend.allowUnprotectedTxs {
log.Info("Unprotected transactions allowed")
} }
eth.ApiBackend.gpo = gasprice.NewOracle(eth.ApiBackend, config.GPO, config.GasPrice) eth.ApiBackend.gpo = gasprice.NewOracle(eth.ApiBackend, config.GPO, config.GasPrice)

View file

@ -2304,6 +2304,10 @@ func SubmitTransaction(ctx context.Context, b Backend, tx *types.Transaction) (c
if err := checkTxFee(tx.GasPrice(), tx.Gas(), b.RPCTxFeeCap()); err != nil { if err := checkTxFee(tx.GasPrice(), tx.Gas(), b.RPCTxFeeCap()); err != nil {
return common.Hash{}, err return common.Hash{}, err
} }
if !b.UnprotectedAllowed() && !tx.Protected() {
// Ensure only eip155 signed transactions are submitted if EIP155Required is set.
return common.Hash{}, errors.New("only replay-protected (EIP-155) transactions allowed over RPC")
}
if err := b.SendTx(ctx, tx); err != nil { if err := b.SendTx(ctx, tx); err != nil {
return common.Hash{}, err return common.Hash{}, err
} }

View file

@ -51,8 +51,10 @@ type Backend interface {
BlobBaseFee(ctx context.Context) *big.Int BlobBaseFee(ctx context.Context) *big.Int
ChainDb() ethdb.Database ChainDb() ethdb.Database
AccountManager() *accounts.Manager AccountManager() *accounts.Manager
RPCGasCap() uint64 // global gas cap for eth_call over rpc: DoS protection RPCGasCap() uint64 // global gas cap for eth_call over rpc: DoS protection
RPCTxFeeCap() float64 // global tx fee cap for all transaction related APIs RPCTxFeeCap() float64 // global tx fee cap for all transaction related APIs
UnprotectedAllowed() bool // allows only for EIP155 transactions.
XDCxService() *XDCx.XDCX XDCxService() *XDCx.XDCX
LendingService() *XDCxlending.Lending LendingService() *XDCxlending.Lending

View file

@ -171,6 +171,9 @@ type Config struct {
oldGethResourceWarning bool oldGethResourceWarning bool
AnnounceTxs bool `toml:",omitempty"` AnnounceTxs bool `toml:",omitempty"`
// AllowUnprotectedTxs allows non EIP-155 protected transactions to be send over RPC.
AllowUnprotectedTxs bool `toml:",omitempty"`
} }
// IPCEndpoint resolves an IPC endpoint based on a configured value, taking into // IPCEndpoint resolves an IPC endpoint based on a configured value, taking into

View file

@ -258,7 +258,7 @@ func baseRpcRequest(t *testing.T, url, bodyStr string, extraHeaders ...string) *
// Create the request. // Create the request.
body := bytes.NewReader([]byte(bodyStr)) body := bytes.NewReader([]byte(bodyStr))
req, err := http.NewRequest("POST", url, body) req, err := http.NewRequest(http.MethodPost, url, body)
if err != nil { if err != nil {
t.Fatal("could not create http request:", err) t.Fatal("could not create http request:", err)
} }