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:
parent
c4a2b682ff
commit
142fbcfd6f
@ -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{
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user