From 5f1da94971feed8874a3fca8eedbaf44404c01a1 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Wed, 22 Jul 2020 19:30:51 -0700 Subject: [PATCH] implement method and parameter specification for send --- cli/send.go | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/cli/send.go b/cli/send.go index ce7879a97..12c16ece3 100644 --- a/cli/send.go +++ b/cli/send.go @@ -1,11 +1,20 @@ package cli import ( + "bytes" + "context" + "encoding/hex" + "encoding/json" "fmt" + "reflect" "github.com/filecoin-project/go-address" + "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/specs-actors/actors/abi" "github.com/urfave/cli/v2" + cbg "github.com/whyrusleeping/cbor-gen" ) var sendCmd = &cli.Command{ @@ -27,6 +36,19 @@ var sendCmd = &cli.Command{ Usage: "specify the nonce to use", Value: -1, }, + &cli.Uint64Flag{ + Name: "method", + Usage: "specify method to invoke", + Value: 0, + }, + &cli.StringFlag{ + Name: "params-json", + Usage: "specify invocation parameters in json", + }, + &cli.StringFlag{ + Name: "params-hex", + Usage: "specify invocation parameters in hex", + }, }, Action: func(cctx *cli.Context) error { api, closer, err := GetFullNodeAPI(cctx) @@ -73,11 +95,34 @@ var sendCmd = &cli.Command{ return err } + method := abi.MethodNum(cctx.Uint64("method")) + + var params []byte + if cctx.IsSet("params-json") { + decparams, err := decodeTypedParams(ctx, api, toAddr, method, cctx.String("params-json")) + if err != nil { + return fmt.Errorf("failed to decode json params: %w", err) + } + params = decparams + } + if cctx.IsSet("params-hex") { + if params != nil { + return fmt.Errorf("can only specify one of 'params-json' and 'params-hex'") + } + decparams, err := hex.DecodeString(cctx.String("params-hex")) + if err != nil { + return fmt.Errorf("failed to decode hex params: %w", err) + } + params = decparams + } + msg := &types.Message{ From: fromAddr, To: toAddr, Value: types.BigInt(val), GasPrice: gp, + Method: method, + Params: params, } if cctx.Int64("nonce") > 0 { @@ -103,3 +148,22 @@ var sendCmd = &cli.Command{ return nil }, } + +func decodeTypedParams(ctx context.Context, fapi api.FullNode, to address.Address, method abi.MethodNum, paramstr string) ([]byte, error) { + act, err := fapi.StateGetActor(ctx, to, types.EmptyTSK) + if err != nil { + return nil, err + } + + p := reflect.New(stmgr.MethodsMap[act.Code][method].Params.Elem()).Interface().(cbg.CBORMarshaler) + + if err := json.Unmarshal([]byte(paramstr), p); err != nil { + return nil, fmt.Errorf("unmarshaling input into params type: %w", err) + } + + buf := new(bytes.Buffer) + if err := p.MarshalCBOR(buf); err != nil { + return nil, err + } + return buf.Bytes(), nil +}