internal/ethapi: reject non-replay-protected txs over RPC (#22339)

This PR prevents users from submitting transactions without EIP-155 enabled. This behaviour can be overridden by specifying the flag --rpc.allow-unprotected-txs=true.
This commit is contained in:
Marius van der Wijden 2021-02-23 13:09:19 +01:00 committed by GitHub
parent c4a2b682ff
commit 142fbcfd6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 39 additions and 10 deletions

View File

@ -199,6 +199,7 @@ var (
utils.InsecureUnlockAllowedFlag, utils.InsecureUnlockAllowedFlag,
utils.RPCGlobalGasCapFlag, utils.RPCGlobalGasCapFlag,
utils.RPCGlobalTxFeeCapFlag, utils.RPCGlobalTxFeeCapFlag,
utils.AllowUnprotectedTxs,
} }
whisperFlags = []cli.Flag{ whisperFlags = []cli.Flag{

View File

@ -593,6 +593,10 @@ var (
Name: "preload", Name: "preload",
Usage: "Comma separated list of JavaScript files to preload into the console", Usage: "Comma separated list of JavaScript files to preload into the console",
} }
AllowUnprotectedTxs = cli.BoolFlag{
Name: "rpc.allow-unprotected-txs",
Usage: "Allow for unprotected (non EIP155 signed) transactions to be submitted via RPC",
}
// Network Settings // Network Settings
MaxPeersFlag = cli.IntFlag{ MaxPeersFlag = cli.IntFlag{
@ -966,6 +970,9 @@ func setHTTP(ctx *cli.Context, cfg *node.Config) {
if ctx.GlobalIsSet(HTTPPathPrefixFlag.Name) { if ctx.GlobalIsSet(HTTPPathPrefixFlag.Name) {
cfg.HTTPPathPrefix = ctx.GlobalString(HTTPPathPrefixFlag.Name) cfg.HTTPPathPrefix = ctx.GlobalString(HTTPPathPrefixFlag.Name)
} }
if ctx.GlobalIsSet(AllowUnprotectedTxs.Name) {
cfg.AllowUnprotectedTxs = ctx.GlobalBool(AllowUnprotectedTxs.Name)
}
} }
// setGraphQL creates the GraphQL listener interface string from the set // setGraphQL creates the GraphQL listener interface string from the set

View File

@ -42,6 +42,7 @@ import (
// EthAPIBackend implements ethapi.Backend for full nodes // EthAPIBackend implements ethapi.Backend for full nodes
type EthAPIBackend struct { type EthAPIBackend struct {
extRPCEnabled bool extRPCEnabled bool
allowUnprotectedTxs bool
eth *Ethereum eth *Ethereum
gpo *gasprice.Oracle gpo *gasprice.Oracle
} }
@ -292,6 +293,10 @@ func (b *EthAPIBackend) ExtRPCEnabled() bool {
return b.extRPCEnabled return b.extRPCEnabled
} }
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

@ -222,7 +222,10 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
eth.miner = miner.New(eth, &config.Miner, chainConfig, eth.EventMux(), eth.engine, eth.isLocalBlock) eth.miner = miner.New(eth, &config.Miner, chainConfig, eth.EventMux(), eth.engine, eth.isLocalBlock)
eth.miner.SetExtra(makeExtraData(config.Miner.ExtraData)) eth.miner.SetExtra(makeExtraData(config.Miner.ExtraData))
eth.APIBackend = &EthAPIBackend{stack.Config().ExtRPCEnabled(), eth, nil} eth.APIBackend = &EthAPIBackend{stack.Config().ExtRPCEnabled(), stack.Config().AllowUnprotectedTxs, eth, nil}
if eth.APIBackend.allowUnprotectedTxs {
log.Info("Unprotected transactions allowed")
}
gpoParams := config.GPO gpoParams := config.GPO
if gpoParams.Default == nil { if gpoParams.Default == nil {
gpoParams.Default = config.Miner.GasPrice gpoParams.Default = config.Miner.GasPrice

View File

@ -1555,6 +1555,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

@ -47,6 +47,7 @@ type Backend interface {
ExtRPCEnabled() bool ExtRPCEnabled() bool
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.
// Blockchain API // Blockchain API
SetHead(number uint64) SetHead(number uint64)

View File

@ -41,6 +41,7 @@ import (
type LesApiBackend struct { type LesApiBackend struct {
extRPCEnabled bool extRPCEnabled bool
allowUnprotectedTxs bool
eth *LightEthereum eth *LightEthereum
gpo *gasprice.Oracle gpo *gasprice.Oracle
} }
@ -263,6 +264,10 @@ func (b *LesApiBackend) ExtRPCEnabled() bool {
return b.extRPCEnabled return b.extRPCEnabled
} }
func (b *LesApiBackend) UnprotectedAllowed() bool {
return b.allowUnprotectedTxs
}
func (b *LesApiBackend) RPCGasCap() uint64 { func (b *LesApiBackend) RPCGasCap() uint64 {
return b.eth.config.RPCGasCap return b.eth.config.RPCGasCap
} }

View File

@ -157,7 +157,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*LightEthereum, error) {
rawdb.WriteChainConfig(chainDb, genesisHash, chainConfig) rawdb.WriteChainConfig(chainDb, genesisHash, chainConfig)
} }
leth.ApiBackend = &LesApiBackend{stack.Config().ExtRPCEnabled(), leth, nil} leth.ApiBackend = &LesApiBackend{stack.Config().ExtRPCEnabled(), stack.Config().AllowUnprotectedTxs, leth, nil}
gpoParams := config.GPO gpoParams := config.GPO
if gpoParams.Default == nil { if gpoParams.Default == nil {
gpoParams.Default = config.Miner.GasPrice gpoParams.Default = config.Miner.GasPrice

View File

@ -191,6 +191,9 @@ type Config struct {
staticNodesWarning bool staticNodesWarning bool
trustedNodesWarning bool trustedNodesWarning bool
oldGethResourceWarning bool oldGethResourceWarning bool
// 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