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, &param)
   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, &param)
   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, &param)
   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, &param)
   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, &param)
   395  	if err != nil {
   396  		return err
   397  	}
   398  	return printRawTx(tx)
   399  }