mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-05-24 08:49:29 +00:00
internal/ethapi: validate explicit transaction type in TransactionArgs
This commit is contained in:
parent
ecef25f384
commit
c868886ad6
2 changed files with 63 additions and 3 deletions
|
|
@ -102,7 +102,7 @@ type sidecarConfig struct {
|
|||
|
||||
// setDefaults fills in default values for unspecified tx fields.
|
||||
func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend, config sidecarConfig) error {
|
||||
if err := args.validateTxType(); err != nil {
|
||||
if err := args.validateTxTypeSupported(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := args.setBlobTxSidecar(ctx, config); err != nil {
|
||||
|
|
@ -180,6 +180,9 @@ func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend, config
|
|||
} else {
|
||||
args.ChainID = (*hexutil.Big)(want)
|
||||
}
|
||||
if err := args.validateTxTypeMatch(types.LegacyTxType); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -394,7 +397,7 @@ func (args *TransactionArgs) setBlobTxSidecar(ctx context.Context, config sideca
|
|||
// CallDefaults sanitizes the transaction arguments, often filling in zero values,
|
||||
// for the purpose of eth_call class of RPC methods.
|
||||
func (args *TransactionArgs) CallDefaults(globalGasCap uint64, baseFee *big.Int, chainID *big.Int) error {
|
||||
if err := args.validateTxType(); err != nil {
|
||||
if err := args.validateTxTypeSupported(); err != nil {
|
||||
return err
|
||||
}
|
||||
// Reject invalid combinations of pre- and post-1559 fee styles
|
||||
|
|
@ -443,11 +446,14 @@ func (args *TransactionArgs) CallDefaults(globalGasCap uint64, baseFee *big.Int,
|
|||
if args.BlobFeeCap == nil && args.BlobHashes != nil {
|
||||
args.BlobFeeCap = new(hexutil.Big)
|
||||
}
|
||||
if err := args.validateTxTypeMatch(types.LegacyTxType); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (args *TransactionArgs) validateTxType() error {
|
||||
func (args *TransactionArgs) validateTxTypeSupported() error {
|
||||
if args.Type == nil {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -459,6 +465,21 @@ func (args *TransactionArgs) validateTxType() error {
|
|||
}
|
||||
}
|
||||
|
||||
func (args *TransactionArgs) validateTxTypeMatch(defaultType int) error {
|
||||
if args.Type == nil {
|
||||
return nil
|
||||
}
|
||||
// Blob txs cannot be contract creations. ToTransaction assumes this invariant.
|
||||
if args.BlobHashes != nil && args.To == nil {
|
||||
return errors.New(`missing "to" in blob transaction`)
|
||||
}
|
||||
inferred := args.ToTransaction(defaultType).Type()
|
||||
if uint64(*args.Type) != uint64(inferred) {
|
||||
return fmt.Errorf("transaction type mismatch (requested=%d inferred=%d)", uint64(*args.Type), inferred)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ToMessage converts the transaction arguments to the Message type used by the
|
||||
// core evm. This method is used in calls and traces that do not require a real
|
||||
// live transaction.
|
||||
|
|
|
|||
|
|
@ -290,6 +290,45 @@ func TestTransactionArgsRejectUnsupportedTypeInSetDefaults(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestTransactionArgsRejectTypeMismatchInCallDefaults(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
requestedLegacy := hexutil.Uint64(types.LegacyTxType)
|
||||
args := &TransactionArgs{
|
||||
Type: &requestedLegacy,
|
||||
MaxFeePerGas: (*hexutil.Big)(big.NewInt(2)),
|
||||
}
|
||||
err := args.CallDefaults(0, big.NewInt(1), big.NewInt(1))
|
||||
if err == nil {
|
||||
t.Fatal("expected type mismatch error")
|
||||
}
|
||||
if err.Error() != "transaction type mismatch (requested=0 inferred=2)" {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTransactionArgsRejectTypeMismatchInSetDefaults(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
requestedDynamic := hexutil.Uint64(types.DynamicFeeTxType)
|
||||
gas := hexutil.Uint64(21000)
|
||||
gasPrice := (*hexutil.Big)(big.NewInt(1))
|
||||
to := common.Address{0x1}
|
||||
args := &TransactionArgs{
|
||||
To: &to,
|
||||
Gas: &gas,
|
||||
GasPrice: gasPrice,
|
||||
Type: &requestedDynamic,
|
||||
}
|
||||
err := args.setDefaults(context.Background(), newBackendMock(), sidecarConfig{})
|
||||
if err == nil {
|
||||
t.Fatal("expected type mismatch error")
|
||||
}
|
||||
if err.Error() != "transaction type mismatch (requested=2 inferred=0)" {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
type backendMock struct {
|
||||
current *types.Header
|
||||
config *params.ChainConfig
|
||||
|
|
|
|||
Loading…
Reference in a new issue