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 }