From 605560a9813c64651fc2fdfd7bb7941c2980a731 Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Wed, 15 Jul 2020 20:55:27 -0400 Subject: [PATCH] SwapSigner API methods --- api/api_full.go | 12 ++ api/apistruct/struct.go | 15 +++ cli/multisig.go | 252 +++++++++++++++++++++++++++++++++++-- cli/send.go | 4 +- node/impl/full/multisig.go | 40 ++++++ 5 files changed, 309 insertions(+), 14 deletions(-) diff --git a/api/api_full.go b/api/api_full.go index 93f9d8fd4..3b7188ec4 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -321,6 +321,18 @@ type FullNode interface { // It takes the following params: , , , , // , , MsigCancel(context.Context, address.Address, uint64, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error) + // MsigSwapPropose proposes swapping 2 signers in the multisig + // It takes the following params: , , + // + MsigSwapPropose(context.Context, address.Address, address.Address, address.Address, address.Address) (cid.Cid, error) + // MsigSwapApprove approves a previously proposed SwapSigner + // It takes the following params: , , , + // , + MsigSwapApprove(context.Context, address.Address, address.Address, uint64, address.Address, address.Address, address.Address) (cid.Cid, error) + // MsigSwapCancel cancels a previously proposed SwapSigner message + // It takes the following params: , , , + // + MsigSwapCancel(context.Context, address.Address, address.Address, uint64, address.Address, address.Address) (cid.Cid, error) MarketEnsureAvailable(context.Context, address.Address, address.Address, types.BigInt) (cid.Cid, error) // MarketFreeBalance diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index fb7ed50e8..413e449e5 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -162,6 +162,9 @@ type FullNodeStruct struct { MsigPropose func(context.Context, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error) `perm:"sign"` MsigApprove func(context.Context, address.Address, uint64, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error) `perm:"sign"` MsigCancel func(context.Context, address.Address, uint64, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error) `perm:"sign"` + MsigSwapPropose func(context.Context, address.Address, address.Address, address.Address, address.Address) (cid.Cid, error) `perm:"sign"` + MsigSwapApprove func(context.Context, address.Address, address.Address, uint64, address.Address, address.Address, address.Address) (cid.Cid, error) `perm:"sign"` + MsigSwapCancel func(context.Context, address.Address, address.Address, uint64, address.Address, address.Address) (cid.Cid, error) `perm:"sign"` MarketEnsureAvailable func(context.Context, address.Address, address.Address, types.BigInt) (cid.Cid, error) `perm:"sign"` @@ -708,6 +711,18 @@ func (c *FullNodeStruct) MsigCancel(ctx context.Context, msig address.Address, t return c.Internal.MsigCancel(ctx, msig, txID, to, amt, src, method, params) } +func (c *FullNodeStruct) MsigSwapPropose(ctx context.Context, msig address.Address, src address.Address, oldAdd address.Address, newAdd address.Address) (cid.Cid, error) { + return c.Internal.MsigSwapPropose(ctx, msig, src, oldAdd, newAdd) +} + +func (c *FullNodeStruct) MsigSwapApprove(ctx context.Context, msig address.Address, src address.Address, txID uint64, proposer address.Address, oldAdd address.Address, newAdd address.Address) (cid.Cid, error) { + return c.Internal.MsigSwapApprove(ctx, msig, src, txID, proposer, oldAdd, newAdd) +} + +func (c *FullNodeStruct) MsigSwapCancel(ctx context.Context, msig address.Address, src address.Address, txID uint64, oldAdd address.Address, newAdd address.Address) (cid.Cid, error) { + return c.Internal.MsigSwapCancel(ctx, msig, src, txID, oldAdd, newAdd) +} + func (c *FullNodeStruct) MarketEnsureAvailable(ctx context.Context, addr, wallet address.Address, amt types.BigInt) (cid.Cid, error) { return c.Internal.MarketEnsureAvailable(ctx, addr, wallet, amt) } diff --git a/cli/multisig.go b/cli/multisig.go index ac3f6364d..4dd102851 100644 --- a/cli/multisig.go +++ b/cli/multisig.go @@ -31,17 +31,14 @@ import ( var multisigCmd = &cli.Command{ Name: "msig", Usage: "Interact with a multisig wallet", - Flags: []cli.Flag{ - &cli.StringFlag{ - Name: "source", - Usage: "specify the account to send propose from", - }, - }, Subcommands: []*cli.Command{ msigCreateCmd, msigInspectCmd, msigProposeCmd, msigApproveCmd, + msigSwapProposeCmd, + msigSwapApproveCmd, + msigSwapCancelCmd, }, } @@ -277,7 +274,7 @@ var msigProposeCmd = &cli.Command{ ArgsUsage: "[multisigAddress destinationAddress value (optional)]", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "source", + Name: "from", Usage: "account to send the propose message from", }, }, @@ -329,8 +326,8 @@ var msigProposeCmd = &cli.Command{ } var from address.Address - if cctx.IsSet("source") { - f, err := address.NewFromString(cctx.String("source")) + if cctx.IsSet("from") { + f, err := address.NewFromString(cctx.String("from")) if err != nil { return err } @@ -376,7 +373,7 @@ var msigApproveCmd = &cli.Command{ ArgsUsage: "[multisigAddress messageId proposerAddress destination value (optional)]", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "source", + Name: "from", Usage: "account to send the approve message from", }, }, @@ -445,8 +442,8 @@ var msigApproveCmd = &cli.Command{ } var from address.Address - if cctx.IsSet("source") { - f, err := address.NewFromString(cctx.String("source")) + if cctx.IsSet("from") { + f, err := address.NewFromString(cctx.String("from")) if err != nil { return err } @@ -478,3 +475,234 @@ var msigApproveCmd = &cli.Command{ return nil }, } + +var msigSwapProposeCmd = &cli.Command{ + Name: "swap-propose", + Usage: "Propose to swap signers", + ArgsUsage: "[multisigAddress oldAddress newAddress]", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "from", + Usage: "account to send the approve message from", + }, + }, + Action: func(cctx *cli.Context) error { + api, closer, err := GetFullNodeAPI(cctx) + if err != nil { + return err + } + defer closer() + ctx := ReqContext(cctx) + + if cctx.Args().Len() != 3 { + return fmt.Errorf("must pass multisig address, old signer address, new signer address") + } + + msig, err := address.NewFromString(cctx.Args().Get(0)) + if err != nil { + return err + } + + oldAdd, err := address.NewFromString(cctx.Args().Get(1)) + if err != nil { + return err + } + + newAdd, err := address.NewFromString(cctx.Args().Get(2)) + 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 + } + + msgCid, err := api.MsigSwapPropose(ctx, msig, from, oldAdd, newAdd) + if err != nil { + return err + } + + fmt.Println("sent swap proposal in message: ", msgCid) + + wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence) + if err != nil { + return err + } + + if wait.Receipt.ExitCode != 0 { + return fmt.Errorf("swap proposal returned exit %d", wait.Receipt.ExitCode) + } + + return nil + }, +} + +var msigSwapApproveCmd = &cli.Command{ + Name: "swap-approve", + Usage: "Approve a message to swap signers", + ArgsUsage: "[multisigAddress proposerAddress txId oldAddress newAddress]", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "from", + Usage: "account to send the approve message from", + }, + }, + Action: func(cctx *cli.Context) error { + api, closer, err := GetFullNodeAPI(cctx) + if err != nil { + return err + } + defer closer() + ctx := ReqContext(cctx) + + if cctx.Args().Len() != 5 { + return fmt.Errorf("must pass multisig address, proposer address, transaction id, old signer address, new signer address") + } + + msig, err := address.NewFromString(cctx.Args().Get(0)) + if err != nil { + return err + } + + prop, err := address.NewFromString(cctx.Args().Get(1)) + if err != nil { + return err + } + + txid, err := strconv.ParseUint(cctx.Args().Get(2), 10, 64) + if err != nil { + return err + } + + oldAdd, err := address.NewFromString(cctx.Args().Get(3)) + if err != nil { + return err + } + + newAdd, err := address.NewFromString(cctx.Args().Get(4)) + 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 + } + + msgCid, err := api.MsigSwapApprove(ctx, msig, from, txid, prop, oldAdd, newAdd) + if err != nil { + return err + } + + fmt.Println("sent swap approval in message: ", msgCid) + + wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence) + if err != nil { + return err + } + + if wait.Receipt.ExitCode != 0 { + return fmt.Errorf("swap approval returned exit %d", wait.Receipt.ExitCode) + } + + return nil + }, +} + +var msigSwapCancelCmd = &cli.Command{ + Name: "swap-cancel", + Usage: "Cancel a message to swap signers", + ArgsUsage: "[multisigAddress txId oldAddress newAddress]", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "from", + Usage: "account to send the approve message from", + }, + }, + Action: func(cctx *cli.Context) error { + api, closer, err := GetFullNodeAPI(cctx) + if err != nil { + return err + } + defer closer() + ctx := ReqContext(cctx) + + if cctx.Args().Len() != 4 { + return fmt.Errorf("must pass multisig address, transaction id, old signer address, new signer address") + } + + msig, err := address.NewFromString(cctx.Args().Get(0)) + if err != nil { + return err + } + + txid, err := strconv.ParseUint(cctx.Args().Get(1), 10, 64) + if err != nil { + return err + } + + oldAdd, err := address.NewFromString(cctx.Args().Get(2)) + if err != nil { + return err + } + + newAdd, err := address.NewFromString(cctx.Args().Get(3)) + 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 + } + + msgCid, err := api.MsigSwapCancel(ctx, msig, from, txid, oldAdd, newAdd) + if err != nil { + return err + } + + fmt.Println("sent swap approval in message: ", msgCid) + + wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence) + if err != nil { + return err + } + + if wait.Receipt.ExitCode != 0 { + return fmt.Errorf("swap approval returned exit %d", wait.Receipt.ExitCode) + } + + return nil + }, +} diff --git a/cli/send.go b/cli/send.go index 9f9c70dde..43aaebdcf 100644 --- a/cli/send.go +++ b/cli/send.go @@ -14,7 +14,7 @@ var sendCmd = &cli.Command{ ArgsUsage: "[targetAddress] [amount]", Flags: []cli.Flag{ &cli.StringFlag{ - Name: "source", + Name: "from", Usage: "optionally specify the account to send funds from", }, &cli.StringFlag{ @@ -52,7 +52,7 @@ var sendCmd = &cli.Command{ } var fromAddr address.Address - if from := cctx.String("source"); from == "" { + if from := cctx.String("from"); from == "" { defaddr, err := api.WalletDefaultAddress(ctx) if err != nil { return err diff --git a/node/impl/full/multisig.go b/node/impl/full/multisig.go index 7d450da2e..6f529d6f8 100644 --- a/node/impl/full/multisig.go +++ b/node/impl/full/multisig.go @@ -2,6 +2,7 @@ package full import ( "context" + "github.com/filecoin-project/specs-actors/actors/abi/big" "github.com/filecoin-project/go-address" "github.com/filecoin-project/lotus/api" @@ -135,6 +136,33 @@ func (a *MsigAPI) MsigPropose(ctx context.Context, msig address.Address, to addr return smsg.Cid(), nil } +func (a *MsigAPI) MsigSwapPropose(ctx context.Context, msig address.Address, src address.Address, oldAdd address.Address, newAdd address.Address) (cid.Cid, error) { + enc, actErr := serializeSwapParams(oldAdd, newAdd) + if actErr != nil { + return cid.Undef, actErr + } + + return a.MsigPropose(ctx, msig, msig, big.Zero(), src, uint64(builtin.MethodsMultisig.SwapSigner), enc) +} + +func (a *MsigAPI) MsigSwapApprove(ctx context.Context, msig address.Address, src address.Address, txID uint64, proposer address.Address, oldAdd address.Address, newAdd address.Address) (cid.Cid, error) { + enc, actErr := serializeSwapParams(oldAdd, newAdd) + if actErr != nil { + return cid.Undef, actErr + } + + return a.MsigApprove(ctx, msig, txID, proposer, msig, big.Zero(), src, uint64(builtin.MethodsMultisig.SwapSigner), enc) +} + +func (a *MsigAPI) MsigSwapCancel(ctx context.Context, msig address.Address, src address.Address, txID uint64, oldAdd address.Address, newAdd address.Address) (cid.Cid, error) { + enc, actErr := serializeSwapParams(oldAdd, newAdd) + if actErr != nil { + return cid.Undef, actErr + } + + return a.MsigCancel(ctx, msig, txID, msig, big.Zero(), src, uint64(builtin.MethodsMultisig.SwapSigner), enc) +} + func (a *MsigAPI) MsigApprove(ctx context.Context, msig address.Address, txID uint64, proposer address.Address, to address.Address, amt types.BigInt, src address.Address, method uint64, params []byte) (cid.Cid, error) { return a.msigApproveOrCancel(ctx, api.MsigApprove, msig, txID, proposer, to, amt, src, method, params) } @@ -223,3 +251,15 @@ func (a *MsigAPI) msigApproveOrCancel(ctx context.Context, operation api.MsigPro return smsg.Cid(), nil } + +func serializeSwapParams(old address.Address, new address.Address) ([]byte, error) { + enc, actErr := actors.SerializeParams(&samsig.SwapSignerParams{ + From: old, + To: new, + }) + if actErr != nil { + return nil, actErr + } + + return enc, nil +}