github.com/neatlab/neatio@v1.7.3-0.20220425043230-d903e92fcc75/tests/transaction_test_util.go (about)

     1  package tests
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"fmt"
     7  	"math/big"
     8  
     9  	"github.com/neatlab/neatio/chain/core/types"
    10  	"github.com/neatlab/neatio/params"
    11  	"github.com/neatlab/neatio/utilities/common"
    12  	"github.com/neatlab/neatio/utilities/common/hexutil"
    13  	"github.com/neatlab/neatio/utilities/common/math"
    14  	"github.com/neatlab/neatio/utilities/rlp"
    15  )
    16  
    17  type TransactionTest struct {
    18  	json ttJSON
    19  }
    20  
    21  type ttJSON struct {
    22  	BlockNumber math.HexOrDecimal64 `json:"blockNumber"`
    23  	RLP         hexutil.Bytes       `json:"rlp"`
    24  	Sender      hexutil.Bytes       `json:"sender"`
    25  	Transaction *ttTransaction      `json:"transaction"`
    26  }
    27  
    28  type ttTransaction struct {
    29  	Data     []byte         `gencodec:"required"`
    30  	GasLimit uint64         `gencodec:"required"`
    31  	GasPrice *big.Int       `gencodec:"required"`
    32  	Nonce    uint64         `gencodec:"required"`
    33  	Value    *big.Int       `gencodec:"required"`
    34  	R        *big.Int       `gencodec:"required"`
    35  	S        *big.Int       `gencodec:"required"`
    36  	V        *big.Int       `gencodec:"required"`
    37  	To       common.Address `gencodec:"required"`
    38  }
    39  
    40  type ttTransactionMarshaling struct {
    41  	Data     hexutil.Bytes
    42  	GasLimit math.HexOrDecimal64
    43  	GasPrice *math.HexOrDecimal256
    44  	Nonce    math.HexOrDecimal64
    45  	Value    *math.HexOrDecimal256
    46  	R        *math.HexOrDecimal256
    47  	S        *math.HexOrDecimal256
    48  	V        *math.HexOrDecimal256
    49  }
    50  
    51  func (tt *TransactionTest) Run(config *params.ChainConfig) error {
    52  	tx := new(types.Transaction)
    53  	if err := rlp.DecodeBytes(tt.json.RLP, tx); err != nil {
    54  		if tt.json.Transaction == nil {
    55  			return nil
    56  		} else {
    57  			return fmt.Errorf("RLP decoding failed: %v", err)
    58  		}
    59  	}
    60  
    61  	signer := types.MakeSigner(config, new(big.Int).SetUint64(uint64(tt.json.BlockNumber)))
    62  	sender, err := types.Sender(signer, tx)
    63  	if err != nil {
    64  		return err
    65  	}
    66  	if sender != common.BytesToAddress(tt.json.Sender) {
    67  		return fmt.Errorf("Sender mismatch: got %x, want %x", sender, tt.json.Sender)
    68  	}
    69  
    70  	err = tt.json.Transaction.verify(signer, tx)
    71  	if tt.json.Sender == nil && err == nil {
    72  		return errors.New("field validations succeeded but should fail")
    73  	}
    74  	if tt.json.Sender != nil && err != nil {
    75  		return fmt.Errorf("field validations failed after RLP decoding: %s", err)
    76  	}
    77  	return nil
    78  }
    79  
    80  func (tt *ttTransaction) verify(signer types.Signer, tx *types.Transaction) error {
    81  	if !bytes.Equal(tx.Data(), tt.Data) {
    82  		return fmt.Errorf("Tx input data mismatch: got %x want %x", tx.Data(), tt.Data)
    83  	}
    84  	if tx.Gas() != tt.GasLimit {
    85  		return fmt.Errorf("GasLimit mismatch: got %d, want %d", tx.Gas(), tt.GasLimit)
    86  	}
    87  	if tx.GasPrice().Cmp(tt.GasPrice) != 0 {
    88  		return fmt.Errorf("GasPrice mismatch: got %v, want %v", tx.GasPrice(), tt.GasPrice)
    89  	}
    90  	if tx.Nonce() != tt.Nonce {
    91  		return fmt.Errorf("Nonce mismatch: got %v, want %v", tx.Nonce(), tt.Nonce)
    92  	}
    93  	v, r, s := tx.RawSignatureValues()
    94  	if r.Cmp(tt.R) != 0 {
    95  		return fmt.Errorf("R mismatch: got %v, want %v", r, tt.R)
    96  	}
    97  	if s.Cmp(tt.S) != 0 {
    98  		return fmt.Errorf("S mismatch: got %v, want %v", s, tt.S)
    99  	}
   100  	if v.Cmp(tt.V) != 0 {
   101  		return fmt.Errorf("V mismatch: got %v, want %v", v, tt.V)
   102  	}
   103  	if tx.To() == nil {
   104  		if tt.To != (common.Address{}) {
   105  			return fmt.Errorf("To mismatch when recipient is nil (contract creation): %x", tt.To)
   106  		}
   107  	} else if *tx.To() != tt.To {
   108  		return fmt.Errorf("To mismatch: got %x, want %x", *tx.To(), tt.To)
   109  	}
   110  	if tx.Value().Cmp(tt.Value) != 0 {
   111  		return fmt.Errorf("Value mismatch: got %x, want %x", tx.Value(), tt.Value)
   112  	}
   113  	return nil
   114  }