github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/evm/types/tx_data.go (about)

     1  package types
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"math/big"
     7  
     8  	"github.com/tendermint/go-amino"
     9  
    10  	"github.com/fibonacci-chain/fbc/app/utils"
    11  
    12  	ethcmn "github.com/ethereum/go-ethereum/common"
    13  )
    14  
    15  // TxData implements the Ethereum transaction data structure. It is used
    16  // solely as intended in Ethereum abiding by the protocol.
    17  type TxData struct {
    18  	AccountNonce uint64          `json:"nonce"`
    19  	Price        *big.Int        `json:"gasPrice"`
    20  	GasLimit     uint64          `json:"gas"`
    21  	Recipient    *ethcmn.Address `json:"to" rlp:"nil"` // nil means contract creation
    22  	Amount       *big.Int        `json:"value"`
    23  	Payload      []byte          `json:"input"`
    24  
    25  	// signature values
    26  	V *big.Int `json:"v"`
    27  	R *big.Int `json:"r"`
    28  	S *big.Int `json:"s"`
    29  
    30  	// hash is only used when marshaling to JSON
    31  	Hash *ethcmn.Hash `json:"hash" rlp:"-"`
    32  }
    33  
    34  // encodableTxData implements the Ethereum transaction data structure. It is used
    35  // solely as intended in Ethereum abiding by the protocol.
    36  type encodableTxData struct {
    37  	AccountNonce uint64          `json:"nonce"`
    38  	Price        string          `json:"gasPrice"`
    39  	GasLimit     uint64          `json:"gas"`
    40  	Recipient    *ethcmn.Address `json:"to" rlp:"nil"` // nil means contract creation
    41  	Amount       string          `json:"value"`
    42  	Payload      []byte          `json:"input"`
    43  
    44  	// signature values
    45  	V string `json:"v"`
    46  	R string `json:"r"`
    47  	S string `json:"s"`
    48  
    49  	// hash is only used when marshaling to JSON
    50  	Hash *ethcmn.Hash `json:"hash" rlp:"-"`
    51  }
    52  
    53  func (tx *encodableTxData) UnmarshalFromAmino(_ *amino.Codec, data []byte) error {
    54  	var dataLen uint64 = 0
    55  	var subData []byte
    56  
    57  	for {
    58  		data = data[dataLen:]
    59  
    60  		if len(data) == 0 {
    61  			break
    62  		}
    63  
    64  		pos, pbType, err := amino.ParseProtoPosAndTypeMustOneByte(data[0])
    65  		if err != nil {
    66  			return err
    67  		}
    68  		data = data[1:]
    69  
    70  		if pbType == amino.Typ3_ByteLength {
    71  			var n int
    72  			dataLen, n, err = amino.DecodeUvarint(data)
    73  			if err != nil {
    74  				return err
    75  			}
    76  			data = data[n:]
    77  			if len(data) < int(dataLen) {
    78  				return fmt.Errorf("invalid tx data")
    79  			}
    80  			subData = data[:dataLen]
    81  		}
    82  
    83  		switch pos {
    84  		case 1:
    85  			var n int
    86  			tx.AccountNonce, n, err = amino.DecodeUvarint(data)
    87  			if err != nil {
    88  				return err
    89  			}
    90  			dataLen = uint64(n)
    91  		case 2:
    92  			tx.Price = string(subData)
    93  		case 3:
    94  			var n int
    95  			tx.GasLimit, n, err = amino.DecodeUvarint(data)
    96  			if err != nil {
    97  				return err
    98  			}
    99  			dataLen = uint64(n)
   100  		case 4:
   101  			if dataLen != ethcmn.AddressLength {
   102  				return errors.New("eth addr len error")
   103  			}
   104  			tx.Recipient = new(ethcmn.Address)
   105  			copy(tx.Recipient[:], subData)
   106  		case 5:
   107  			tx.Amount = string(subData)
   108  		case 6:
   109  			tx.Payload = make([]byte, dataLen)
   110  			copy(tx.Payload, subData)
   111  		case 7:
   112  			tx.V = string(subData)
   113  		case 8:
   114  			tx.R = string(subData)
   115  		case 9:
   116  			tx.S = string(subData)
   117  		case 10:
   118  			if dataLen != ethcmn.HashLength {
   119  				return errors.New("hash len error")
   120  			}
   121  			tx.Hash = new(ethcmn.Hash)
   122  			copy(tx.Hash[:], subData)
   123  		default:
   124  			return fmt.Errorf("unexpect feild num %d", pos)
   125  		}
   126  	}
   127  	return nil
   128  }
   129  
   130  func (td TxData) String() string {
   131  	if td.Recipient != nil {
   132  		return fmt.Sprintf("nonce=%d price=%s gasLimit=%d recipient=%s amount=%s data=0x%x v=%s r=%s s=%s",
   133  			td.AccountNonce, td.Price, td.GasLimit, td.Recipient.Hex(), td.Amount, td.Payload, td.V, td.R, td.S)
   134  	}
   135  
   136  	return fmt.Sprintf("nonce=%d price=%s gasLimit=%d recipient=nil amount=%s data=0x%x v=%s r=%s s=%s",
   137  		td.AccountNonce, td.Price, td.GasLimit, td.Amount, td.Payload, td.V, td.R, td.S)
   138  }
   139  
   140  // MarshalAmino defines custom encoding scheme for TxData
   141  func (td TxData) MarshalAmino() ([]byte, error) {
   142  	gasPrice, err := utils.MarshalBigInt(td.Price)
   143  	if err != nil {
   144  		return nil, err
   145  	}
   146  
   147  	amount, err := utils.MarshalBigInt(td.Amount)
   148  	if err != nil {
   149  		return nil, err
   150  	}
   151  
   152  	v, err := utils.MarshalBigInt(td.V)
   153  	if err != nil {
   154  		return nil, err
   155  	}
   156  
   157  	r, err := utils.MarshalBigInt(td.R)
   158  	if err != nil {
   159  		return nil, err
   160  	}
   161  
   162  	s, err := utils.MarshalBigInt(td.S)
   163  	if err != nil {
   164  		return nil, err
   165  	}
   166  
   167  	e := encodableTxData{
   168  		AccountNonce: td.AccountNonce,
   169  		Price:        gasPrice,
   170  		GasLimit:     td.GasLimit,
   171  		Recipient:    td.Recipient,
   172  		Amount:       amount,
   173  		Payload:      td.Payload,
   174  		V:            v,
   175  		R:            r,
   176  		S:            s,
   177  		Hash:         td.Hash,
   178  	}
   179  
   180  	return ModuleCdc.MarshalBinaryBare(e)
   181  }
   182  
   183  // UnmarshalAmino defines custom decoding scheme for TxData
   184  func (td *TxData) UnmarshalAmino(data []byte) error {
   185  	var e encodableTxData
   186  	err := ModuleCdc.UnmarshalBinaryBare(data, &e)
   187  	if err != nil {
   188  		return err
   189  	}
   190  
   191  	td.AccountNonce = e.AccountNonce
   192  	td.GasLimit = e.GasLimit
   193  	td.Recipient = e.Recipient
   194  	td.Payload = e.Payload
   195  	td.Hash = e.Hash
   196  
   197  	price, err := utils.UnmarshalBigInt(e.Price)
   198  	if err != nil {
   199  		return err
   200  	}
   201  
   202  	if td.Price != nil {
   203  		td.Price.Set(price)
   204  	} else {
   205  		td.Price = price
   206  	}
   207  
   208  	amt, err := utils.UnmarshalBigInt(e.Amount)
   209  	if err != nil {
   210  		return err
   211  	}
   212  
   213  	if td.Amount != nil {
   214  		td.Amount.Set(amt)
   215  	} else {
   216  		td.Amount = amt
   217  	}
   218  
   219  	v, err := utils.UnmarshalBigInt(e.V)
   220  	if err != nil {
   221  		return err
   222  	}
   223  
   224  	if td.V != nil {
   225  		td.V.Set(v)
   226  	} else {
   227  		td.V = v
   228  	}
   229  
   230  	r, err := utils.UnmarshalBigInt(e.R)
   231  	if err != nil {
   232  		return err
   233  	}
   234  
   235  	if td.R != nil {
   236  		td.R.Set(r)
   237  	} else {
   238  		td.R = r
   239  	}
   240  
   241  	s, err := utils.UnmarshalBigInt(e.S)
   242  	if err != nil {
   243  		return err
   244  	}
   245  
   246  	if td.S != nil {
   247  		td.S.Set(s)
   248  	} else {
   249  		td.S = s
   250  	}
   251  
   252  	return nil
   253  }
   254  
   255  func (td *TxData) unmarshalFromAmino(cdc *amino.Codec, data []byte) error {
   256  	var e encodableTxData
   257  	err := e.UnmarshalFromAmino(cdc, data)
   258  	if err != nil {
   259  		return err
   260  	}
   261  	td.AccountNonce = e.AccountNonce
   262  	td.GasLimit = e.GasLimit
   263  	td.Recipient = e.Recipient
   264  	td.Payload = e.Payload
   265  	td.Hash = e.Hash
   266  
   267  	price, err := utils.UnmarshalBigInt(e.Price)
   268  	if err != nil {
   269  		return err
   270  	}
   271  
   272  	if td.Price != nil {
   273  		td.Price.Set(price)
   274  	} else {
   275  		td.Price = price
   276  	}
   277  
   278  	amt, err := utils.UnmarshalBigInt(e.Amount)
   279  	if err != nil {
   280  		return err
   281  	}
   282  
   283  	if td.Amount != nil {
   284  		td.Amount.Set(amt)
   285  	} else {
   286  		td.Amount = amt
   287  	}
   288  
   289  	v, err := utils.UnmarshalBigInt(e.V)
   290  	if err != nil {
   291  		return err
   292  	}
   293  
   294  	if td.V != nil {
   295  		td.V.Set(v)
   296  	} else {
   297  		td.V = v
   298  	}
   299  
   300  	r, err := utils.UnmarshalBigInt(e.R)
   301  	if err != nil {
   302  		return err
   303  	}
   304  
   305  	if td.R != nil {
   306  		td.R.Set(r)
   307  	} else {
   308  		td.R = r
   309  	}
   310  
   311  	s, err := utils.UnmarshalBigInt(e.S)
   312  	if err != nil {
   313  		return err
   314  	}
   315  
   316  	if td.S != nil {
   317  		td.S.Set(s)
   318  	} else {
   319  		td.S = s
   320  	}
   321  
   322  	return nil
   323  }
   324  
   325  func (td *TxData) UnmarshalFromAmino(cdc *amino.Codec, data []byte) error {
   326  	err := td.unmarshalFromAmino(cdc, data)
   327  	if err != nil {
   328  		u64, n, err := amino.DecodeUvarint(data)
   329  		if err == nil && int(u64) == (len(data)-n) {
   330  			return td.unmarshalFromAmino(cdc, data[n:])
   331  		} else {
   332  			return err
   333  		}
   334  	}
   335  	return nil
   336  }
   337  
   338  // TODO: Implement JSON marshaling/ unmarshaling for this type
   339  
   340  // TODO: Implement YAML marshaling/ unmarshaling for this type