Merge pull request #7645 from filecoin-project/asr/msig-cancel

CLI: Add a lotus multisig cancel command
This commit is contained in:
Łukasz Magiera 2021-11-22 12:14:47 +01:00 committed by GitHub
commit 7a9824f00e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 233 additions and 15 deletions

View File

@ -630,10 +630,14 @@ type FullNode interface {
// <sender address of the approve msg>, <method to call in the proposed message>, <params to include in the proposed message>
MsigApproveTxnHash(context.Context, address.Address, uint64, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (*MessagePrototype, error) //perm:sign
// MsigCancel cancels a previously-proposed multisig message
// It takes the following params: <multisig address>, <proposed transaction ID> <signer address>
MsigCancel(context.Context, address.Address, uint64, address.Address) (*MessagePrototype, error) //perm:sign
// MsigCancel cancels a previously-proposed multisig message
// It takes the following params: <multisig address>, <proposed transaction ID>, <recipient address>, <value to transfer>,
// <sender address of the cancel msg>, <method to call in the proposed message>, <params to include in the proposed message>
MsigCancel(context.Context, address.Address, uint64, address.Address, types.BigInt, address.Address, uint64, []byte) (*MessagePrototype, error) //perm:sign
MsigCancelTxnHash(context.Context, address.Address, uint64, address.Address, types.BigInt, address.Address, uint64, []byte) (*MessagePrototype, error) //perm:sign
// MsigAddPropose proposes adding a signer in the multisig
// It takes the following params: <multisig address>, <sender address of the propose msg>,

View File

@ -1428,18 +1428,33 @@ func (mr *MockFullNodeMockRecorder) MsigApproveTxnHash(arg0, arg1, arg2, arg3, a
}
// MsigCancel mocks base method.
func (m *MockFullNode) MsigCancel(arg0 context.Context, arg1 address.Address, arg2 uint64, arg3 address.Address, arg4 big.Int, arg5 address.Address, arg6 uint64, arg7 []byte) (*api.MessagePrototype, error) {
func (m *MockFullNode) MsigCancel(arg0 context.Context, arg1 address.Address, arg2 uint64, arg3 address.Address) (*api.MessagePrototype, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MsigCancel", arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
ret := m.ctrl.Call(m, "MsigCancel", arg0, arg1, arg2, arg3)
ret0, _ := ret[0].(*api.MessagePrototype)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// MsigCancel indicates an expected call of MsigCancel.
func (mr *MockFullNodeMockRecorder) MsigCancel(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7 interface{}) *gomock.Call {
func (mr *MockFullNodeMockRecorder) MsigCancel(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MsigCancel", reflect.TypeOf((*MockFullNode)(nil).MsigCancel), arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MsigCancel", reflect.TypeOf((*MockFullNode)(nil).MsigCancel), arg0, arg1, arg2, arg3)
}
// MsigCancelTxnHash mocks base method.
func (m *MockFullNode) MsigCancelTxnHash(arg0 context.Context, arg1 address.Address, arg2 uint64, arg3 address.Address, arg4 big.Int, arg5 address.Address, arg6 uint64, arg7 []byte) (*api.MessagePrototype, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MsigCancelTxnHash", arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
ret0, _ := ret[0].(*api.MessagePrototype)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// MsigCancelTxnHash indicates an expected call of MsigCancelTxnHash.
func (mr *MockFullNodeMockRecorder) MsigCancelTxnHash(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MsigCancelTxnHash", reflect.TypeOf((*MockFullNode)(nil).MsigCancelTxnHash), arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
}
// MsigCreate mocks base method.

View File

@ -270,7 +270,9 @@ type FullNodeStruct struct {
MsigApproveTxnHash func(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address, p4 address.Address, p5 types.BigInt, p6 address.Address, p7 uint64, p8 []byte) (*MessagePrototype, error) `perm:"sign"`
MsigCancel func(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address, p4 types.BigInt, p5 address.Address, p6 uint64, p7 []byte) (*MessagePrototype, error) `perm:"sign"`
MsigCancel func(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address) (*MessagePrototype, error) `perm:"sign"`
MsigCancelTxnHash func(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address, p4 types.BigInt, p5 address.Address, p6 uint64, p7 []byte) (*MessagePrototype, error) `perm:"sign"`
MsigCreate func(p0 context.Context, p1 uint64, p2 []address.Address, p3 abi.ChainEpoch, p4 types.BigInt, p5 address.Address, p6 types.BigInt) (*MessagePrototype, error) `perm:"sign"`
@ -1943,14 +1945,25 @@ func (s *FullNodeStub) MsigApproveTxnHash(p0 context.Context, p1 address.Address
return nil, ErrNotSupported
}
func (s *FullNodeStruct) MsigCancel(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address, p4 types.BigInt, p5 address.Address, p6 uint64, p7 []byte) (*MessagePrototype, error) {
func (s *FullNodeStruct) MsigCancel(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address) (*MessagePrototype, error) {
if s.Internal.MsigCancel == nil {
return nil, ErrNotSupported
}
return s.Internal.MsigCancel(p0, p1, p2, p3, p4, p5, p6, p7)
return s.Internal.MsigCancel(p0, p1, p2, p3)
}
func (s *FullNodeStub) MsigCancel(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address, p4 types.BigInt, p5 address.Address, p6 uint64, p7 []byte) (*MessagePrototype, error) {
func (s *FullNodeStub) MsigCancel(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address) (*MessagePrototype, error) {
return nil, ErrNotSupported
}
func (s *FullNodeStruct) MsigCancelTxnHash(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address, p4 types.BigInt, p5 address.Address, p6 uint64, p7 []byte) (*MessagePrototype, error) {
if s.Internal.MsigCancelTxnHash == nil {
return nil, ErrNotSupported
}
return s.Internal.MsigCancelTxnHash(p0, p1, p2, p3, p4, p5, p6, p7)
}
func (s *FullNodeStub) MsigCancelTxnHash(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address, p4 types.BigInt, p5 address.Address, p6 uint64, p7 []byte) (*MessagePrototype, error) {
return nil, ErrNotSupported
}

View File

@ -108,7 +108,7 @@ func (w *WrapperV1Full) MsigApproveTxnHash(ctx context.Context, msig address.Add
}
func (w *WrapperV1Full) MsigCancel(ctx context.Context, msig address.Address, txID uint64, to address.Address, amt types.BigInt, src address.Address, method uint64, params []byte) (cid.Cid, error) {
p, err := w.FullNode.MsigCancel(ctx, msig, txID, to, amt, src, method, params)
p, err := w.FullNode.MsigCancelTxnHash(ctx, msig, txID, to, amt, src, method, params)
if err != nil {
return cid.Undef, xerrors.Errorf("creating prototype: %w", err)
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -51,6 +51,7 @@ var multisigCmd = &cli.Command{
msigProposeCmd,
msigRemoveProposeCmd,
msigApproveCmd,
msigCancelCmd,
msigAddProposeCmd,
msigAddApproveCmd,
msigAddCancelCmd,
@ -159,6 +160,8 @@ var msigCreateCmd = &cli.Command{
msgCid := sm.Cid()
fmt.Println("sent create in message: ", msgCid)
// wait for it to get mined into a block
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")), build.Finality, true)
if err != nil {
@ -448,7 +451,7 @@ var msigProposeCmd = &cli.Command{
msgCid := sm.Cid()
fmt.Println("send proposal in message: ", msgCid)
fmt.Println("sent proposal in message: ", msgCid)
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")), build.Finality, true)
if err != nil {
@ -612,6 +615,131 @@ var msigApproveCmd = &cli.Command{
},
}
var msigCancelCmd = &cli.Command{
Name: "cancel",
Usage: "Cancel a multisig message",
ArgsUsage: "<multisigAddress messageId> [destination value [methodId methodParams]]",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "from",
Usage: "account to send the cancel message from",
},
},
Action: func(cctx *cli.Context) error {
if cctx.Args().Len() < 2 {
return ShowHelp(cctx, fmt.Errorf("must pass at least multisig address and message ID"))
}
if cctx.Args().Len() > 2 && cctx.Args().Len() < 4 {
return ShowHelp(cctx, fmt.Errorf("usage: msig cancel <msig addr> <message ID> <desination> <value>"))
}
if cctx.Args().Len() > 4 && cctx.Args().Len() != 6 {
return ShowHelp(cctx, fmt.Errorf("usage: msig cancel <msig addr> <message ID> <desination> <value> [ <method> <params> ]"))
}
srv, err := GetFullNodeServices(cctx)
if err != nil {
return err
}
defer srv.Close() //nolint:errcheck
api := srv.FullNodeAPI()
ctx := ReqContext(cctx)
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
}
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
}
var msgCid cid.Cid
if cctx.Args().Len() == 2 {
proto, err := api.MsigCancel(ctx, msig, txid, from)
if err != nil {
return err
}
sm, err := InteractiveSend(ctx, cctx, srv, proto)
if err != nil {
return err
}
msgCid = sm.Cid()
} else {
dest, err := address.NewFromString(cctx.Args().Get(2))
if err != nil {
return err
}
value, err := types.ParseFIL(cctx.Args().Get(3))
if err != nil {
return err
}
var method uint64
var params []byte
if cctx.Args().Len() == 6 {
m, err := strconv.ParseUint(cctx.Args().Get(4), 10, 64)
if err != nil {
return err
}
method = m
p, err := hex.DecodeString(cctx.Args().Get(5))
if err != nil {
return err
}
params = p
}
proto, err := api.MsigCancelTxnHash(ctx, msig, txid, dest, types.BigInt(value), from, method, params)
if err != nil {
return err
}
sm, err := InteractiveSend(ctx, cctx, srv, proto)
if err != nil {
return err
}
msgCid = sm.Cid()
}
fmt.Println("sent cancel in message: ", msgCid)
wait, err := api.StateWaitMsg(ctx, msgCid, uint64(cctx.Int("confidence")), build.Finality, true)
if err != nil {
return err
}
if wait.Receipt.ExitCode != 0 {
return fmt.Errorf("cancel returned exit %d", wait.Receipt.ExitCode)
}
return nil
},
}
var msigRemoveProposeCmd = &cli.Command{
Name: "propose-remove",
Usage: "Propose to remove a signer",
@ -1490,7 +1618,7 @@ var msigLockCancelCmd = &cli.Command{
return actErr
}
proto, err := api.MsigCancel(ctx, msig, txid, msig, big.Zero(), from, uint64(multisig.Methods.LockBalance), params)
proto, err := api.MsigCancelTxnHash(ctx, msig, txid, msig, big.Zero(), from, uint64(multisig.Methods.LockBalance), params)
if err != nil {
return err
}

View File

@ -108,6 +108,7 @@
* [MsigApprove](#MsigApprove)
* [MsigApproveTxnHash](#MsigApproveTxnHash)
* [MsigCancel](#MsigCancel)
* [MsigCancelTxnHash](#MsigCancelTxnHash)
* [MsigCreate](#MsigCreate)
* [MsigGetAvailableBalance](#MsigGetAvailableBalance)
* [MsigGetPending](#MsigGetPending)
@ -2702,6 +2703,44 @@ Response:
### MsigCancel
MsigCancel cancels a previously-proposed multisig message
It takes the following params: <multisig address>, <proposed transaction ID> <signer address>
Perms: sign
Inputs:
```json
[
"f01234",
42,
"f01234"
]
```
Response:
```json
{
"Message": {
"Version": 42,
"To": "f01234",
"From": "f01234",
"Nonce": 42,
"Value": "0",
"GasLimit": 9,
"GasFeeCap": "0",
"GasPremium": "0",
"Method": 1,
"Params": "Ynl0ZSBhcnJheQ==",
"CID": {
"/": "bafy2bzacebbpdegvr3i4cosewthysg5xkxpqfn2wfcz6mv2hmoktwbdxkax4s"
}
},
"ValidNonce": true
}
```
### MsigCancelTxnHash
MsigCancel cancels a previously-proposed multisig message
It takes the following params: <multisig address>, <proposed transaction ID>, <recipient address>, <value to transfer>,
<sender address of the cancel msg>, <method to call in the proposed message>, <params to include in the proposed message>

View File

@ -857,6 +857,7 @@ COMMANDS:
propose Propose a multisig transaction
propose-remove Propose to remove a signer
approve Approve a multisig message
cancel Cancel a multisig message
add-propose Propose to add a signer
add-approve Approve a message to add a signer
add-cancel Cancel a message to add a signer
@ -952,6 +953,20 @@ OPTIONS:
```
### lotus msig cancel
```
NAME:
lotus msig cancel - Cancel a multisig message
USAGE:
lotus msig cancel [command options] <multisigAddress messageId> [destination value [methodId methodParams]]
OPTIONS:
--from value account to send the cancel message from
--help, -h show help (default: false)
```
### lotus msig add-propose
```
NAME:

View File

@ -100,7 +100,7 @@ func (a *MsigAPI) MsigAddCancel(ctx context.Context, msig address.Address, src a
return nil, actErr
}
return a.MsigCancel(ctx, msig, txID, msig, big.Zero(), src, uint64(multisig.Methods.AddSigner), enc)
return a.MsigCancelTxnHash(ctx, msig, txID, msig, big.Zero(), src, uint64(multisig.Methods.AddSigner), enc)
}
func (a *MsigAPI) MsigSwapPropose(ctx context.Context, msig address.Address, src address.Address, oldAdd address.Address, newAdd address.Address) (*api.MessagePrototype, error) {
@ -127,7 +127,7 @@ func (a *MsigAPI) MsigSwapCancel(ctx context.Context, msig address.Address, src
return nil, actErr
}
return a.MsigCancel(ctx, msig, txID, msig, big.Zero(), src, uint64(multisig.Methods.SwapSigner), enc)
return a.MsigCancelTxnHash(ctx, msig, txID, msig, big.Zero(), src, uint64(multisig.Methods.SwapSigner), enc)
}
func (a *MsigAPI) MsigApprove(ctx context.Context, msig address.Address, txID uint64, src address.Address) (*api.MessagePrototype, error) {
@ -138,7 +138,11 @@ func (a *MsigAPI) MsigApproveTxnHash(ctx context.Context, msig address.Address,
return a.msigApproveOrCancelTxnHash(ctx, api.MsigApprove, msig, txID, proposer, to, amt, src, method, params)
}
func (a *MsigAPI) MsigCancel(ctx context.Context, msig address.Address, txID uint64, to address.Address, amt types.BigInt, src address.Address, method uint64, params []byte) (*api.MessagePrototype, error) {
func (a *MsigAPI) MsigCancel(ctx context.Context, msig address.Address, txID uint64, src address.Address) (*api.MessagePrototype, error) {
return a.msigApproveOrCancelSimple(ctx, api.MsigCancel, msig, txID, src)
}
func (a *MsigAPI) MsigCancelTxnHash(ctx context.Context, msig address.Address, txID uint64, to address.Address, amt types.BigInt, src address.Address, method uint64, params []byte) (*api.MessagePrototype, error) {
return a.msigApproveOrCancelTxnHash(ctx, api.MsigCancel, msig, txID, src, to, amt, src, method, params)
}