github.com/0xPolygon/supernets2-node@v0.0.0-20230711153321-2fe574524eaa/tools/rlp/main.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"math/big"
     6  	"os"
     7  	"strconv"
     8  	"strings"
     9  
    10  	"github.com/0xPolygon/supernets2-node/encoding"
    11  	"github.com/0xPolygon/supernets2-node/etherman/smartcontracts/supernets2"
    12  	"github.com/0xPolygon/supernets2-node/hex"
    13  	"github.com/0xPolygon/supernets2-node/log"
    14  	"github.com/0xPolygon/supernets2-node/state"
    15  	"github.com/ethereum/go-ethereum/accounts/abi"
    16  	"github.com/ethereum/go-ethereum/common"
    17  	"github.com/ethereum/go-ethereum/core/types"
    18  	"github.com/urfave/cli/v2"
    19  )
    20  
    21  func main() {
    22  	app := cli.NewApp()
    23  	app.Name = "RlpTool"
    24  	app.Version = "v0.0.1"
    25  	app.Commands = []*cli.Command{
    26  		{
    27  			Name:    "decodeFull",
    28  			Aliases: []string{},
    29  			Usage:   "decode full callData rlp",
    30  			Action:  decodeFull,
    31  		},
    32  		{
    33  			Name:    "decode",
    34  			Aliases: []string{},
    35  			Usage:   "decode rlp",
    36  			Action:  decode,
    37  		},
    38  		{
    39  			Name:    "encode",
    40  			Aliases: []string{},
    41  			Usage:   "encode tx with rlp",
    42  			Action:  encode,
    43  		},
    44  	}
    45  	err := app.Run(os.Args)
    46  	if err != nil {
    47  		log.Errorf("\nError: %v\n", err)
    48  		os.Exit(1)
    49  	}
    50  }
    51  
    52  func decodeFull(ctx *cli.Context) error {
    53  	callData := ctx.Args().First()
    54  	bytesCallData, err := hex.DecodeHex(callData)
    55  	if err != nil {
    56  		log.Error("error decoding callData: ", err)
    57  		return err
    58  	}
    59  	txs, rawTxs, err := decodeFullCallDataToTxs(bytesCallData)
    60  	if err != nil {
    61  		return err
    62  	}
    63  	printTxs(txs, rawTxs)
    64  	return nil
    65  }
    66  
    67  func decode(ctx *cli.Context) error {
    68  	rawTxs := ctx.Args().First()
    69  	bytesRawTxs, err := hex.DecodeHex(rawTxs)
    70  	if err != nil {
    71  		log.Error("error decoding rawTxs: ", err)
    72  		return err
    73  	}
    74  	txs, _, err := state.DecodeTxs(bytesRawTxs)
    75  	if err != nil {
    76  		log.Error("error decoding tx callData: ", err)
    77  		return err
    78  	}
    79  	printTxs(txs, bytesRawTxs)
    80  	return nil
    81  }
    82  
    83  func encode(ctx *cli.Context) error {
    84  	fmt.Print("Nonce : ")
    85  	var nonceS string
    86  	if _, err := fmt.Scanln(&nonceS); err != nil {
    87  		return err
    88  	}
    89  	nonce, err := strconv.ParseUint(nonceS, encoding.Base10, 64) //nolint:gomnd
    90  	if err != nil {
    91  		log.Error("error decoding nonce: ", err)
    92  		return err
    93  	}
    94  	log.Info("Nonce: ", nonce)
    95  
    96  	fmt.Print("GasPrice : ")
    97  	var gasPriceS string
    98  	if _, err := fmt.Scanln(&gasPriceS); err != nil {
    99  		return err
   100  	}
   101  	gasPrice, _ := new(big.Int).SetString(gasPriceS, encoding.Base10)
   102  	log.Info("GasPrice: ", gasPrice)
   103  
   104  	fmt.Print("Gas : ")
   105  	var gasS string
   106  	if _, err := fmt.Scanln(&gasS); err != nil {
   107  		return err
   108  	}
   109  	gas, err := strconv.ParseUint(gasS, encoding.Base10, 64) //nolint:gomnd
   110  	if err != nil {
   111  		log.Error("error decoding gas: ", err)
   112  		return err
   113  	}
   114  	log.Info("Gas: ", gas)
   115  
   116  	fmt.Print("To : ")
   117  	var toS string
   118  	if _, err := fmt.Scanln(&toS); err != nil {
   119  		return err
   120  	}
   121  	to := common.HexToAddress(toS)
   122  	log.Info("To: ", to)
   123  
   124  	fmt.Print("Value : ")
   125  	var valueS string
   126  	if _, err := fmt.Scanln(&valueS); err != nil {
   127  		return err
   128  	}
   129  	value, _ := new(big.Int).SetString(valueS, encoding.Base10)
   130  	log.Info("Value: ", value)
   131  
   132  	fmt.Print("Data : ")
   133  	var dataS string
   134  	if _, err := fmt.Scanln(&dataS); err != nil {
   135  		if err.Error() != "unexpected newline" {
   136  			return err
   137  		}
   138  	}
   139  	var data []byte
   140  	if dataS != "" {
   141  		data, err = hex.DecodeHex(dataS)
   142  		if err != nil {
   143  			log.Error("error decoding data: ", err)
   144  			return err
   145  		}
   146  	}
   147  	log.Info("Data: ", data)
   148  
   149  	fmt.Print("V: ")
   150  	var vS string
   151  	if _, err := fmt.Scanln(&vS); err != nil {
   152  		return err
   153  	}
   154  	v, _ := new(big.Int).SetString(vS, encoding.Base10)
   155  	log.Info("V: ", v)
   156  
   157  	fmt.Print("R: ")
   158  	var rS string
   159  	if _, err := fmt.Scanln(&rS); err != nil {
   160  		return err
   161  	}
   162  	r, _ := new(big.Int).SetString(rS, encoding.Base10)
   163  	log.Info("R: ", r)
   164  
   165  	fmt.Print("S: ")
   166  	var sS string
   167  	if _, err := fmt.Scanln(&sS); err != nil {
   168  		return err
   169  	}
   170  	s, _ := new(big.Int).SetString(sS, encoding.Base10)
   171  	log.Info("S: ", s)
   172  
   173  	var txLegacy = types.LegacyTx{
   174  		Nonce:    nonce,
   175  		GasPrice: gasPrice,
   176  		Gas:      gas,
   177  		To:       &to,
   178  		Value:    value,
   179  		Data:     data,
   180  		V:        v,
   181  		R:        r,
   182  		S:        s,
   183  	}
   184  	tx := types.NewTx(&txLegacy)
   185  
   186  	rawBytes, err := state.EncodeTransactions([]types.Transaction{*tx})
   187  	if err != nil {
   188  		log.Error("error encoding txs: ", err)
   189  		return err
   190  	}
   191  	log.Info("encoded tx with signature using RLP in []byte: ", rawBytes)
   192  	log.Info("rawtx with signature using RLP in hex: ", hex.EncodeToString(rawBytes))
   193  
   194  	return nil
   195  }
   196  
   197  func printTxs(txs []types.Transaction, rawTxs []byte) {
   198  	log.Info("RawTxs: ", hex.EncodeToHex(rawTxs))
   199  	for _, tx := range txs {
   200  		log.Info("#######################################################################")
   201  		log.Info("#######################################################################")
   202  		log.Infof("Decoded tx: %+v", tx)
   203  		log.Info("ChainID: ", tx.ChainId())
   204  		log.Info("Cost: ", tx.Cost())
   205  		log.Info("Data: ", hex.EncodeToString(tx.Data()))
   206  		log.Info("Gas: ", tx.Gas())
   207  		log.Info("GasPrice: ", tx.GasPrice())
   208  		log.Info("Hash: ", tx.Hash())
   209  		log.Info("Nonce: ", tx.Nonce())
   210  		v, r, s := tx.RawSignatureValues()
   211  		log.Info("V: ", v)
   212  		log.Info("R: ", r)
   213  		log.Info("S: ", s)
   214  		log.Info("To: ", tx.To())
   215  		log.Info("Type: ", tx.Type())
   216  		log.Info("Value: ", tx.Value())
   217  	}
   218  }
   219  
   220  func decodeFullCallDataToTxs(txsData []byte) ([]types.Transaction, []byte, error) {
   221  	// The first 4 bytes are the function hash bytes. These bytes has to be ripped.
   222  	// After that, the unpack method is used to read the call data.
   223  	// The txs data is a chunk of concatenated rawTx. This rawTx is the encoded tx information in rlp + the signature information (v, r, s).
   224  	//So, txs data will look like: txRLP+r+s+v+txRLP2+r2+s2+v2
   225  
   226  	// Extract coded txs.
   227  	// Load contract ABI
   228  	abi, err := abi.JSON(strings.NewReader(supernets2.Supernets2ABI))
   229  	if err != nil {
   230  		log.Fatal("error reading smart contract abi: ", err)
   231  	}
   232  
   233  	// Recover Method from signature and ABI
   234  	method, err := abi.MethodById(txsData[:4])
   235  	if err != nil {
   236  		log.Fatal("error getting abi method: ", err)
   237  	}
   238  
   239  	// Unpack method inputs
   240  	data, err := method.Inputs.Unpack(txsData[4:])
   241  	if err != nil {
   242  		log.Fatal("error reading call data: ", err)
   243  	}
   244  
   245  	txsData = data[0].([]byte)
   246  
   247  	txs, _, err := state.DecodeTxs(txsData)
   248  	return txs, txsData, err
   249  }