github.com/unicornultrafoundation/go-u2u@v1.0.0-rc1.0.20240205080301-e74a83d3fadc/native/transaction_serializer.go (about)

     1  package native
     2  
     3  import (
     4  	"errors"
     5  	"math/big"
     6  
     7  	"github.com/unicornultrafoundation/go-u2u/common"
     8  	"github.com/unicornultrafoundation/go-u2u/core/types"
     9  
    10  	"github.com/unicornultrafoundation/go-u2u/utils/cser"
    11  )
    12  
    13  var ErrUnknownTxType = errors.New("unknown tx type")
    14  
    15  func encodeSig(r, s *big.Int) (sig [64]byte) {
    16  	copy(sig[0:], cser.PaddedBytes(r.Bytes(), 32)[:32])
    17  	copy(sig[32:], cser.PaddedBytes(s.Bytes(), 32)[:32])
    18  	return sig
    19  }
    20  
    21  func decodeSig(sig [64]byte) (r, s *big.Int) {
    22  	r = new(big.Int).SetBytes(sig[:32])
    23  	s = new(big.Int).SetBytes(sig[32:64])
    24  	return
    25  }
    26  
    27  func TransactionMarshalCSER(w *cser.Writer, tx *types.Transaction) error {
    28  	if tx.Type() != types.LegacyTxType && tx.Type() != types.AccessListTxType && tx.Type() != types.DynamicFeeTxType {
    29  		return ErrUnknownTxType
    30  	}
    31  	if tx.Type() != types.LegacyTxType {
    32  		// marker of a non-standard tx
    33  		w.BitsW.Write(6, 0)
    34  		// tx type
    35  		w.U8(tx.Type())
    36  	} else if tx.Gas() <= 0xff {
    37  		return errors.New("cannot serialize legacy tx with gasLimit <= 256")
    38  	}
    39  	w.U64(tx.Nonce())
    40  	w.U64(tx.Gas())
    41  	if tx.Type() == types.DynamicFeeTxType {
    42  		w.BigInt(tx.GasTipCap())
    43  		w.BigInt(tx.GasFeeCap())
    44  	} else {
    45  		w.BigInt(tx.GasPrice())
    46  	}
    47  	w.BigInt(tx.Value())
    48  	w.Bool(tx.To() != nil)
    49  	if tx.To() != nil {
    50  		w.FixedBytes(tx.To().Bytes())
    51  	}
    52  	w.SliceBytes(tx.Data())
    53  	v, r, s := tx.RawSignatureValues()
    54  	w.BigInt(v)
    55  	sig := encodeSig(r, s)
    56  	w.FixedBytes(sig[:])
    57  	if tx.Type() == types.AccessListTxType || tx.Type() == types.DynamicFeeTxType {
    58  		w.BigInt(tx.ChainId())
    59  		w.U32(uint32(len(tx.AccessList())))
    60  		for _, tuple := range tx.AccessList() {
    61  			w.FixedBytes(tuple.Address.Bytes())
    62  			w.U32(uint32(len(tuple.StorageKeys)))
    63  			for _, h := range tuple.StorageKeys {
    64  				w.FixedBytes(h.Bytes())
    65  			}
    66  		}
    67  	}
    68  	return nil
    69  }
    70  
    71  func TransactionUnmarshalCSER(r *cser.Reader) (*types.Transaction, error) {
    72  	txType := uint8(types.LegacyTxType)
    73  	if r.BitsR.View(6) == 0 {
    74  		r.BitsR.Read(6)
    75  		txType = r.U8()
    76  	}
    77  
    78  	nonce := r.U64()
    79  	gasLimit := r.U64()
    80  	var gasPrice *big.Int
    81  	var gasTipCap *big.Int
    82  	var gasFeeCap *big.Int
    83  	if txType == types.DynamicFeeTxType {
    84  		gasTipCap = r.BigInt()
    85  		gasFeeCap = r.BigInt()
    86  	} else {
    87  		gasPrice = r.BigInt()
    88  	}
    89  	amount := r.BigInt()
    90  	toExists := r.Bool()
    91  	var to *common.Address
    92  	if toExists {
    93  		var _to common.Address
    94  		r.FixedBytes(_to[:])
    95  		to = &_to
    96  	}
    97  	data := r.SliceBytes(ProtocolMaxMsgSize)
    98  	// sig
    99  	v := r.BigInt()
   100  	var sig [64]byte
   101  	r.FixedBytes(sig[:])
   102  	_r, s := decodeSig(sig)
   103  
   104  	if txType == types.LegacyTxType {
   105  		return types.NewTx(&types.LegacyTx{
   106  			Nonce:    nonce,
   107  			GasPrice: gasPrice,
   108  			Gas:      gasLimit,
   109  			To:       to,
   110  			Value:    amount,
   111  			Data:     data,
   112  			V:        v,
   113  			R:        _r,
   114  			S:        s,
   115  		}), nil
   116  	} else if txType == types.AccessListTxType || txType == types.DynamicFeeTxType {
   117  		chainID := r.BigInt()
   118  		accessListLen := r.U32()
   119  		if accessListLen > ProtocolMaxMsgSize/24 {
   120  			return nil, cser.ErrTooLargeAlloc
   121  		}
   122  		accessList := make(types.AccessList, accessListLen)
   123  		for i := range accessList {
   124  			r.FixedBytes(accessList[i].Address[:])
   125  			keysLen := r.U32()
   126  			if keysLen > ProtocolMaxMsgSize/32 {
   127  				return nil, cser.ErrTooLargeAlloc
   128  			}
   129  			accessList[i].StorageKeys = make([]common.Hash, keysLen)
   130  			for j := range accessList[i].StorageKeys {
   131  				r.FixedBytes(accessList[i].StorageKeys[j][:])
   132  			}
   133  		}
   134  		if txType == types.AccessListTxType {
   135  			return types.NewTx(&types.AccessListTx{
   136  				ChainID:    chainID,
   137  				Nonce:      nonce,
   138  				GasPrice:   gasPrice,
   139  				Gas:        gasLimit,
   140  				To:         to,
   141  				Value:      amount,
   142  				Data:       data,
   143  				AccessList: accessList,
   144  				V:          v,
   145  				R:          _r,
   146  				S:          s,
   147  			}), nil
   148  		} else {
   149  			return types.NewTx(&types.DynamicFeeTx{
   150  				ChainID:    chainID,
   151  				Nonce:      nonce,
   152  				GasTipCap:  gasTipCap,
   153  				GasFeeCap:  gasFeeCap,
   154  				Gas:        gasLimit,
   155  				To:         to,
   156  				Value:      amount,
   157  				Data:       data,
   158  				AccessList: accessList,
   159  				V:          v,
   160  				R:          _r,
   161  				S:          s,
   162  			}), nil
   163  		}
   164  	}
   165  	return nil, ErrUnknownTxType
   166  }