github.com/FUSIONFoundation/efsn@v3.6.2-0.20200916075423-dbb5dd5d2cc7+incompatible/cmd/efsn/rawtx.go (about) 1 package main 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "math/big" 8 "strconv" 9 10 "github.com/FusionFoundation/efsn/cmd/utils" 11 "github.com/FusionFoundation/efsn/common" 12 "github.com/FusionFoundation/efsn/common/hexutil" 13 "github.com/FusionFoundation/efsn/consensus/datong" 14 "github.com/FusionFoundation/efsn/core/types" 15 "github.com/FusionFoundation/efsn/rlp" 16 17 "gopkg.in/urfave/cli.v1" 18 ) 19 20 var ( 21 rawTxCommand = cli.Command{ 22 Name: "rawtx", 23 Usage: "Process raw transaction", 24 Category: "RAWTX COMMANDS", 25 Description: ` 26 27 Process raw transaction.`, 28 Subcommands: []cli.Command{ 29 { 30 Name: "decodeRawTx", 31 Usage: "Decode transaction from rawtx hex data", 32 Action: utils.MigrateFlags(decodeRawTx), 33 Flags: []cli.Flag{}, 34 ArgsUsage: "<hexstr> [decodeinput]", 35 Description: ` 36 rawtx decodeRawTx <hexstr> [decodeinput] 37 decodeinput defaults to true, you can specify false to ignore it.`, 38 }, 39 { 40 Name: "decodeTxInput", 41 Usage: "Decode fsn call param from tx input hex data", 42 Action: utils.MigrateFlags(decodeTxInput), 43 Flags: []cli.Flag{}, 44 ArgsUsage: "<hexstr>", 45 Description: ` 46 rawtx decodeTxInput <hexstr>`, 47 }, 48 { 49 Name: "decodeLogData", 50 Usage: "Decode log data from tx receipt log hex data", 51 Action: utils.MigrateFlags(decodeLogData), 52 Flags: []cli.Flag{}, 53 ArgsUsage: "<hexstr>", 54 Description: ` 55 rawtx decodeLogData <hexstr>`, 56 }, 57 { 58 Name: "sendAsset", 59 Usage: "Create a 'sendAsset' raw transaction", 60 Action: utils.MigrateFlags(createSendAssetRawTx), 61 Flags: []cli.Flag{}, 62 ArgsUsage: "<asset> <to> <value>", 63 Description: ` 64 rawtx sendAsset <asset> <to> <value>`, 65 }, 66 { 67 Name: "assetToTimeLock", 68 Usage: "Create a 'assetToTimeLock' raw transaction", 69 Action: utils.MigrateFlags(createAssetToTimeLockRawTx), 70 Flags: []cli.Flag{}, 71 ArgsUsage: "<asset> <to> <start> <end> <value>", 72 Description: ` 73 rawtx assetToTimeLock <asset> <to> <start> <end> <value>`, 74 }, 75 { 76 Name: "timeLockToTimeLock", 77 Usage: "Create a 'timeLockToTimeLock' raw transaction", 78 Action: utils.MigrateFlags(createTimeLockToTimeLockRawTx), 79 Flags: []cli.Flag{}, 80 ArgsUsage: "<asset> <to> <start> <end> <value>", 81 Description: ` 82 rawtx timeLockToTimeLock <asset> <to> <start> <end> <value>`, 83 }, 84 { 85 Name: "timeLockToAsset", 86 Usage: "Create a 'timeLockToAsset' raw transaction", 87 Action: utils.MigrateFlags(createTimeLockToAssetRawTx), 88 Flags: []cli.Flag{}, 89 ArgsUsage: "<asset> <to> <value>", 90 Description: ` 91 rawtx timeLockToAsset <asset> <to> <value>`, 92 }, 93 { 94 Name: "genNotation", 95 Usage: "Create a 'genNotation' raw transaction", 96 Action: utils.MigrateFlags(createGenNotationRawTx), 97 Flags: []cli.Flag{}, 98 ArgsUsage: "", 99 Description: ` 100 rawtx genNotation`, 101 }, 102 { 103 Name: "buyTicket", 104 Usage: "Create a 'buyTicket' raw transaction", 105 Action: utils.MigrateFlags(createBuyTicketRawTx), 106 Flags: []cli.Flag{}, 107 ArgsUsage: "<start> <end>", 108 Description: ` 109 rawtx buyTicket <start> <end>`, 110 }, 111 }, 112 } 113 ) 114 115 func printTx(tx *types.Transaction, decodeInput bool) error { 116 var bs []byte 117 var err error 118 if decodeInput { 119 fsnTxInput, err := datong.DecodeTxInput(tx.Data()) 120 if err != nil { 121 return fmt.Errorf("decode FSNCallParam err %v", err) 122 } 123 txExt := &struct { 124 Tx *types.Transaction `json:"tx"` 125 FsnTxInput interface{} `json:"fsnTxInput,omitempty"` 126 }{ 127 Tx: tx, 128 FsnTxInput: fsnTxInput, 129 } 130 bs, err = json.Marshal(txExt) 131 if err != nil { 132 return fmt.Errorf("json marshal err %v", err) 133 } 134 } else { 135 bs, err = tx.MarshalJSON() 136 if err != nil { 137 return fmt.Errorf("json marshal err %v", err) 138 } 139 } 140 fmt.Println(string(bs)) 141 return nil 142 } 143 144 func printRawTx(tx *types.Transaction) error { 145 bs, err := json.Marshal(&struct { 146 Recipient *common.Address `json:"to" rlp:"nil"` 147 Payload hexutil.Bytes `json:"input" gencodec:"required"` 148 }{ 149 Recipient: tx.To(), 150 Payload: tx.Data(), 151 }) 152 if err != nil { 153 return fmt.Errorf("json marshal err %v", err) 154 } 155 fmt.Println(string(bs)) 156 return nil 157 } 158 159 func decodeRawTx(ctx *cli.Context) error { 160 args := ctx.Args() 161 if len(args) < 1 || len(args) > 2 { 162 return fmt.Errorf("wrong number of arguments") 163 } 164 decodeInput := true 165 if len(args) > 1 && args[1] == "false" { 166 decodeInput = false 167 } 168 data, err := hexutil.Decode(args.First()) 169 if err != nil { 170 return fmt.Errorf("wrong arguments %v", err) 171 } 172 var tx types.Transaction 173 err = rlp.Decode(bytes.NewReader(data), &tx) 174 if err != nil { 175 return fmt.Errorf("decode rawTx err %v", err) 176 } 177 return printTx(&tx, decodeInput) 178 } 179 180 func decodeTxInput(ctx *cli.Context) error { 181 args := ctx.Args() 182 if len(args) != 1 { 183 return fmt.Errorf("wrong number of arguments") 184 } 185 data, err := hexutil.Decode(args.First()) 186 if err != nil { 187 return fmt.Errorf("wrong arguments %v", err) 188 } 189 res, err := datong.DecodeTxInput(data) 190 if err != nil { 191 return fmt.Errorf("decode FSNCallParam err %v", err) 192 } 193 bs, err := json.Marshal(res) 194 if err != nil { 195 return fmt.Errorf("json marshal err %v", err) 196 } 197 fmt.Println(string(bs)) 198 return nil 199 } 200 201 func decodeLogData(ctx *cli.Context) error { 202 args := ctx.Args() 203 if len(args) != 1 { 204 return fmt.Errorf("wrong number of arguments") 205 } 206 data, err := hexutil.Decode(args.First()) 207 if err != nil { 208 return fmt.Errorf("wrong arguments %v", err) 209 } 210 res, err := datong.DecodeLogData(data) 211 if err != nil { 212 return fmt.Errorf("decode log data err %v", err) 213 } 214 bs, err := json.Marshal(res) 215 if err != nil { 216 return fmt.Errorf("json marshal err %v", err) 217 } 218 fmt.Println(string(bs)) 219 return nil 220 } 221 222 type ParamInterface interface { 223 ToBytes() ([]byte, error) 224 } 225 226 func toRawTx(funcType common.FSNCallFunc, funcParam ParamInterface) (*types.Transaction, error) { 227 funcData, err := funcParam.ToBytes() 228 if err != nil { 229 return nil, err 230 } 231 var param = common.FSNCallParam{Func: funcType, Data: funcData} 232 input, err := param.ToBytes() 233 if err != nil { 234 return nil, err 235 } 236 tx := types.NewTransaction( 237 0, 238 common.FSNCallAddress, 239 big.NewInt(0), 240 0, 241 big.NewInt(0), 242 input, 243 ) 244 return tx, nil 245 } 246 247 func createSendAssetRawTx(ctx *cli.Context) error { 248 args := ctx.Args() 249 if len(args) != 3 { 250 return fmt.Errorf("wrong number of arguments") 251 } 252 asset := common.HexToHash(args[0]) 253 to := common.HexToAddress(args[1]) 254 value, ok := new(big.Int).SetString(args[2], 0) 255 if !ok { 256 return fmt.Errorf(args[2] + " is not a right big number") 257 } 258 259 param := common.SendAssetParam{ 260 AssetID: asset, 261 To: to, 262 Value: value, 263 } 264 tx, err := toRawTx(common.SendAssetFunc, ¶m) 265 if err != nil { 266 return err 267 } 268 return printRawTx(tx) 269 } 270 271 func createAssetToTimeLockRawTx(ctx *cli.Context) error { 272 args := ctx.Args() 273 if len(args) != 5 { 274 return fmt.Errorf("wrong number of arguments") 275 } 276 asset := common.HexToHash(args[0]) 277 to := common.HexToAddress(args[1]) 278 start, err := strconv.ParseUint(args[2], 0, 64) 279 if err != nil { 280 return fmt.Errorf("Invalid start number: %v", err) 281 } 282 end, err := strconv.ParseUint(args[3], 0, 64) 283 if err != nil { 284 return fmt.Errorf("Invalid end number: %v", err) 285 } 286 value, ok := new(big.Int).SetString(args[4], 0) 287 if !ok { 288 return fmt.Errorf(args[4] + " is not a right big number") 289 } 290 291 param := common.TimeLockParam{ 292 Type: common.AssetToTimeLock, 293 AssetID: asset, 294 To: to, 295 StartTime: start, 296 EndTime: end, 297 Value: value, 298 } 299 tx, err := toRawTx(common.TimeLockFunc, ¶m) 300 if err != nil { 301 return err 302 } 303 return printRawTx(tx) 304 } 305 306 func createTimeLockToTimeLockRawTx(ctx *cli.Context) error { 307 args := ctx.Args() 308 if len(args) != 5 { 309 return fmt.Errorf("wrong number of arguments") 310 } 311 asset := common.HexToHash(args[0]) 312 to := common.HexToAddress(args[1]) 313 start, err := strconv.ParseUint(args[2], 0, 64) 314 if err != nil { 315 return fmt.Errorf("Invalid start number: %v", err) 316 } 317 end, err := strconv.ParseUint(args[3], 0, 64) 318 if err != nil { 319 return fmt.Errorf("Invalid end number: %v", err) 320 } 321 value, ok := new(big.Int).SetString(args[4], 0) 322 if !ok { 323 return fmt.Errorf(args[4] + " is not a right big number") 324 } 325 326 param := common.TimeLockParam{ 327 Type: common.TimeLockToTimeLock, 328 AssetID: asset, 329 To: to, 330 StartTime: start, 331 EndTime: end, 332 Value: value, 333 } 334 tx, err := toRawTx(common.TimeLockFunc, ¶m) 335 if err != nil { 336 return err 337 } 338 return printRawTx(tx) 339 } 340 341 func createTimeLockToAssetRawTx(ctx *cli.Context) error { 342 args := ctx.Args() 343 if len(args) != 3 { 344 return fmt.Errorf("wrong number of arguments") 345 } 346 asset := common.HexToHash(args[0]) 347 to := common.HexToAddress(args[1]) 348 value, ok := new(big.Int).SetString(args[2], 0) 349 if !ok { 350 return fmt.Errorf(args[2] + " is not a right big number") 351 } 352 353 param := common.TimeLockParam{ 354 Type: common.TimeLockToAsset, 355 AssetID: asset, 356 To: to, 357 StartTime: common.TimeLockNow, 358 EndTime: common.TimeLockForever, 359 Value: value, 360 } 361 tx, err := toRawTx(common.TimeLockFunc, ¶m) 362 if err != nil { 363 return err 364 } 365 return printRawTx(tx) 366 } 367 368 func createGenNotationRawTx(ctx *cli.Context) error { 369 tx, err := toRawTx(common.GenNotationFunc, &common.EmptyParam{}) 370 if err != nil { 371 return err 372 } 373 return printRawTx(tx) 374 } 375 376 func createBuyTicketRawTx(ctx *cli.Context) error { 377 args := ctx.Args() 378 if len(args) != 2 { 379 return fmt.Errorf("wrong number of arguments") 380 } 381 start, err := strconv.ParseUint(args[0], 0, 64) 382 if err != nil { 383 return fmt.Errorf("Invalid start number: %v", err) 384 } 385 end, err := strconv.ParseUint(args[1], 0, 64) 386 if err != nil { 387 return fmt.Errorf("Invalid end number: %v", err) 388 } 389 390 param := common.BuyTicketParam{ 391 Start: start, 392 End: end, 393 } 394 tx, err := toRawTx(common.BuyTicketFunc, ¶m) 395 if err != nil { 396 return err 397 } 398 return printRawTx(tx) 399 }