github.com/ethereum/go-ethereum@v1.16.1/tests/transaction_test_util.go (about)

     1  // Copyright 2015 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package tests
    18  
    19  import (
    20  	"fmt"
    21  	"math/big"
    22  
    23  	"github.com/ethereum/go-ethereum/common"
    24  	"github.com/ethereum/go-ethereum/common/hexutil"
    25  	"github.com/ethereum/go-ethereum/common/math"
    26  	"github.com/ethereum/go-ethereum/core"
    27  	"github.com/ethereum/go-ethereum/core/types"
    28  	"github.com/ethereum/go-ethereum/params"
    29  )
    30  
    31  // TransactionTest checks RLP decoding and sender derivation of transactions.
    32  type TransactionTest struct {
    33  	Txbytes hexutil.Bytes `json:"txbytes"`
    34  	Result  map[string]*ttFork
    35  }
    36  
    37  type ttFork struct {
    38  	Sender       *common.UnprefixedAddress `json:"sender"`
    39  	Hash         *common.UnprefixedHash    `json:"hash"`
    40  	Exception    *string                   `json:"exception"`
    41  	IntrinsicGas math.HexOrDecimal64       `json:"intrinsicGas"`
    42  }
    43  
    44  func (tt *TransactionTest) validate() error {
    45  	if tt.Txbytes == nil {
    46  		return fmt.Errorf("missing txbytes")
    47  	}
    48  	for name, fork := range tt.Result {
    49  		if err := tt.validateFork(fork); err != nil {
    50  			return fmt.Errorf("invalid %s: %v", name, err)
    51  		}
    52  	}
    53  	return nil
    54  }
    55  
    56  func (tt *TransactionTest) validateFork(fork *ttFork) error {
    57  	if fork == nil {
    58  		return nil
    59  	}
    60  	if fork.Hash == nil && fork.Exception == nil {
    61  		return fmt.Errorf("missing hash and exception")
    62  	}
    63  	if fork.Hash != nil && fork.Sender == nil {
    64  		return fmt.Errorf("missing sender")
    65  	}
    66  	return nil
    67  }
    68  
    69  func (tt *TransactionTest) Run() error {
    70  	if err := tt.validate(); err != nil {
    71  		return err
    72  	}
    73  	validateTx := func(rlpData hexutil.Bytes, signer types.Signer, rules *params.Rules) (sender common.Address, hash common.Hash, requiredGas uint64, err error) {
    74  		tx := new(types.Transaction)
    75  		if err = tx.UnmarshalBinary(rlpData); err != nil {
    76  			return
    77  		}
    78  		sender, err = types.Sender(signer, tx)
    79  		if err != nil {
    80  			return
    81  		}
    82  		// Intrinsic gas
    83  		requiredGas, err = core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.SetCodeAuthorizations(), tx.To() == nil, rules.IsHomestead, rules.IsIstanbul, rules.IsShanghai)
    84  		if err != nil {
    85  			return
    86  		}
    87  		if requiredGas > tx.Gas() {
    88  			return sender, hash, 0, fmt.Errorf("insufficient gas ( %d < %d )", tx.Gas(), requiredGas)
    89  		}
    90  
    91  		if rules.IsPrague {
    92  			var floorDataGas uint64
    93  			floorDataGas, err = core.FloorDataGas(tx.Data())
    94  			if err != nil {
    95  				return
    96  			}
    97  			if tx.Gas() < floorDataGas {
    98  				return sender, hash, 0, fmt.Errorf("%w: have %d, want %d", core.ErrFloorDataGas, tx.Gas(), floorDataGas)
    99  			}
   100  		}
   101  		hash = tx.Hash()
   102  		return sender, hash, requiredGas, nil
   103  	}
   104  	for _, testcase := range []struct {
   105  		name    string
   106  		isMerge bool
   107  	}{
   108  		{"Frontier", false},
   109  		{"Homestead", false},
   110  		{"EIP150", false},
   111  		{"EIP158", false},
   112  		{"Byzantium", false},
   113  		{"Constantinople", false},
   114  		{"Istanbul", false},
   115  		{"Berlin", false},
   116  		{"London", false},
   117  		{"Paris", true},
   118  		{"Shanghai", true},
   119  		{"Cancun", true},
   120  		{"Prague", true},
   121  	} {
   122  		expected := tt.Result[testcase.name]
   123  		if expected == nil {
   124  			continue
   125  		}
   126  		config, ok := Forks[testcase.name]
   127  		if !ok || config == nil {
   128  			return UnsupportedForkError{Name: testcase.name}
   129  		}
   130  		var (
   131  			rules  = config.Rules(new(big.Int), testcase.isMerge, 0)
   132  			signer = types.MakeSigner(config, new(big.Int), 0)
   133  		)
   134  		sender, hash, gas, err := validateTx(tt.Txbytes, signer, &rules)
   135  		if err != nil {
   136  			if expected.Hash != nil {
   137  				return fmt.Errorf("unexpected error fork %s: %v", testcase.name, err)
   138  			}
   139  			continue
   140  		}
   141  		if expected.Exception != nil {
   142  			return fmt.Errorf("expected error %v, got none (%v), fork %s", *expected.Exception, err, testcase.name)
   143  		}
   144  		if common.Hash(*expected.Hash) != hash {
   145  			return fmt.Errorf("hash mismatch: got %x, want %x", hash, common.Hash(*expected.Hash))
   146  		}
   147  		if common.Address(*expected.Sender) != sender {
   148  			return fmt.Errorf("sender mismatch: got %x, want %x", sender, expected.Sender)
   149  		}
   150  		if uint64(expected.IntrinsicGas) != gas {
   151  			return fmt.Errorf("intrinsic gas mismatch: got %d, want %d", gas, uint64(expected.IntrinsicGas))
   152  		}
   153  	}
   154  	return nil
   155  }