Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improve the UX of multisig approves #4398

Merged
merged 4 commits into from
Oct 15, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
200 changes: 148 additions & 52 deletions cli/multisig.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/filecoin-project/go-state-types/abi"

"github.com/filecoin-project/go-address"
cid "github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor"
"github.com/urfave/cli/v2"
"golang.org/x/xerrors"
Expand All @@ -41,6 +42,13 @@ import (
var multisigCmd = &cli.Command{
Name: "msig",
Usage: "Interact with a multisig wallet",
Flags: []cli.Flag{
&cli.IntFlag{
Name: "confidence",
Usage: "number of block confirmations to wait for",
Value: int(build.MessageConfidence),
},
},
Subcommands: []*cli.Command{
msigCreateCmd,
msigInspectCmd,
Expand All @@ -57,6 +65,7 @@ var multisigCmd = &cli.Command{
msigLockApproveCmd,
msigLockCancelCmd,
msigVestedCmd,
msigProposeThresholdCmd,
},
}

Expand Down Expand Up @@ -146,7 +155,7 @@ var msigCreateCmd = &cli.Command{
}

// wait for it to get mined into a block
wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence)
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
if err != nil {
return err
}
Expand Down Expand Up @@ -410,7 +419,7 @@ var msigProposeCmd = &cli.Command{

fmt.Println("send proposal in message: ", msgCid)

wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence)
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
if err != nil {
return err
}
Expand Down Expand Up @@ -446,14 +455,18 @@ var msigApproveCmd = &cli.Command{
},
},
Action: func(cctx *cli.Context) error {
if cctx.Args().Len() < 5 {
return ShowHelp(cctx, fmt.Errorf("must pass multisig address, message ID, proposer address, destination, and value"))
if cctx.Args().Len() < 2 {
return ShowHelp(cctx, fmt.Errorf("must pass at least multisig address and message ID"))
}

if cctx.Args().Len() > 5 && cctx.Args().Len() != 7 {
return ShowHelp(cctx, fmt.Errorf("usage: msig approve <msig addr> <message ID> <proposer address> <desination> <value> [ <method> <params> ]"))
}

if cctx.Args().Len() > 2 && cctx.Args().Len() != 5 {
return ShowHelp(cctx, fmt.Errorf("usage: msig approve <msig addr> <message ID> <proposer address> <desination> <value>"))
}

api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
Expand All @@ -471,67 +484,75 @@ var msigApproveCmd = &cli.Command{
return err
}

proposer, err := address.NewFromString(cctx.Args().Get(2))
if err != nil {
return err
}

if proposer.Protocol() != address.ID {
proposer, err = api.StateLookupID(ctx, proposer, types.EmptyTSK)
var from address.Address
if cctx.IsSet("from") {
f, err := address.NewFromString(cctx.String("from"))
if err != nil {
return err
}
from = f
} else {
defaddr, err := api.WalletDefaultAddress(ctx)
if err != nil {
return err
}
from = defaddr
}

dest, err := address.NewFromString(cctx.Args().Get(3))
if err != nil {
return err
}

value, err := types.ParseFIL(cctx.Args().Get(4))
if err != nil {
return err
}

var method uint64
var params []byte
if cctx.Args().Len() == 7 {
m, err := strconv.ParseUint(cctx.Args().Get(5), 10, 64)
var msgCid cid.Cid
if cctx.Args().Len() == 2 {
msgCid, err = api.MsigApprove(ctx, msig, txid, from)
if err != nil {
return err
}
method = m

p, err := hex.DecodeString(cctx.Args().Get(6))
} else {
proposer, err := address.NewFromString(cctx.Args().Get(2))
if err != nil {
return err
}
params = p
}

var from address.Address
if cctx.IsSet("from") {
f, err := address.NewFromString(cctx.String("from"))
if proposer.Protocol() != address.ID {
proposer, err = api.StateLookupID(ctx, proposer, types.EmptyTSK)
if err != nil {
return err
}
}

dest, err := address.NewFromString(cctx.Args().Get(3))
if err != nil {
return err
}
from = f
} else {
defaddr, err := api.WalletDefaultAddress(ctx)

value, err := types.ParseFIL(cctx.Args().Get(4))
if err != nil {
return err
}
from = defaddr
}

msgCid, err := api.MsigApproveTxnHash(ctx, msig, txid, proposer, dest, types.BigInt(value), from, method, params)
if err != nil {
return err
var method uint64
var params []byte
if cctx.Args().Len() == 7 {
m, err := strconv.ParseUint(cctx.Args().Get(5), 10, 64)
if err != nil {
return err
}
method = m

p, err := hex.DecodeString(cctx.Args().Get(6))
if err != nil {
return err
}
params = p
}

msgCid, err = api.MsigApproveTxnHash(ctx, msig, txid, proposer, dest, types.BigInt(value), from, method, params)
if err != nil {
return err
}
}

fmt.Println("sent approval in message: ", msgCid)

wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence)
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
if err != nil {
return err
}
Expand Down Expand Up @@ -602,7 +623,7 @@ var msigRemoveProposeCmd = &cli.Command{

fmt.Println("sent remove proposal in message: ", msgCid)

wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence)
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
if err != nil {
return err
}
Expand Down Expand Up @@ -680,7 +701,7 @@ var msigAddProposeCmd = &cli.Command{

fmt.Println("sent add proposal in message: ", msgCid)

wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence)
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
if err != nil {
return err
}
Expand Down Expand Up @@ -762,7 +783,7 @@ var msigAddApproveCmd = &cli.Command{

fmt.Println("sent add approval in message: ", msgCid)

wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence)
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
if err != nil {
return err
}
Expand Down Expand Up @@ -839,7 +860,7 @@ var msigAddCancelCmd = &cli.Command{

fmt.Println("sent add cancellation in message: ", msgCid)

wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence)
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
if err != nil {
return err
}
Expand Down Expand Up @@ -911,7 +932,7 @@ var msigSwapProposeCmd = &cli.Command{

fmt.Println("sent swap proposal in message: ", msgCid)

wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence)
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
if err != nil {
return err
}
Expand Down Expand Up @@ -993,7 +1014,7 @@ var msigSwapApproveCmd = &cli.Command{

fmt.Println("sent swap approval in message: ", msgCid)

wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence)
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
if err != nil {
return err
}
Expand Down Expand Up @@ -1070,7 +1091,7 @@ var msigSwapCancelCmd = &cli.Command{

fmt.Println("sent swap cancellation in message: ", msgCid)

wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence)
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
if err != nil {
return err
}
Expand Down Expand Up @@ -1157,7 +1178,7 @@ var msigLockProposeCmd = &cli.Command{

fmt.Println("sent lock proposal in message: ", msgCid)

wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence)
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
if err != nil {
return err
}
Expand Down Expand Up @@ -1254,7 +1275,7 @@ var msigLockApproveCmd = &cli.Command{

fmt.Println("sent lock approval in message: ", msgCid)

wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence)
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
if err != nil {
return err
}
Expand Down Expand Up @@ -1346,7 +1367,7 @@ var msigLockCancelCmd = &cli.Command{

fmt.Println("sent lock cancellation in message: ", msgCid)

wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence)
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
if err != nil {
return err
}
Expand Down Expand Up @@ -1420,3 +1441,78 @@ var msigVestedCmd = &cli.Command{
return nil
},
}

var msigProposeThresholdCmd = &cli.Command{
Name: "propose-threshold",
Usage: "Propose setting a different signing threshold on the account",
ArgsUsage: "<multisigAddress newM>",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "from",
Usage: "account to send the proposal from",
},
},
Action: func(cctx *cli.Context) error {
if cctx.Args().Len() != 2 {
return ShowHelp(cctx, fmt.Errorf("must pass multisig address and new threshold value"))
}

api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)

msig, err := address.NewFromString(cctx.Args().Get(0))
if err != nil {
return err
}

newM, err := strconv.ParseUint(cctx.Args().Get(1), 10, 64)
if err != nil {
return err
}

var from address.Address
if cctx.IsSet("from") {
f, err := address.NewFromString(cctx.String("from"))
if err != nil {
return err
}
from = f
} else {
defaddr, err := api.WalletDefaultAddress(ctx)
if err != nil {
return err
}
from = defaddr
}

params, actErr := actors.SerializeParams(&msig0.ChangeNumApprovalsThresholdParams{
NewThreshold: newM,
})

if actErr != nil {
return actErr
}

msgCid, err := api.MsigPropose(ctx, msig, msig, types.NewInt(0), from, uint64(builtin2.MethodsMultisig.ChangeNumApprovalsThreshold), params)
if err != nil {
return fmt.Errorf("failed to propose change of threshold: %w", err)
}

fmt.Println("sent change threshold proposal in message: ", msgCid)

wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")))
if err != nil {
return err
}

if wait.Receipt.ExitCode != 0 {
return fmt.Errorf("change threshold proposal returned exit %d", wait.Receipt.ExitCode)
}

return nil
},
}