diff --git a/chain/actors/actor_multisig.go b/chain/actors/actor_multisig.go index 765f13b4c..2b2c5dec5 100644 --- a/chain/actors/actor_multisig.go +++ b/chain/actors/actor_multisig.go @@ -14,10 +14,11 @@ func init() { cbor.RegisterCborType(MultiSigConstructorParams{}) cbor.RegisterCborType(MultiSigProposeParams{}) cbor.RegisterCborType(MultiSigTxID{}) - cbor.RegisterCborType(MultiSigSigner{}) cbor.RegisterCborType(MultiSigSwapSignerParams{}) cbor.RegisterCborType(MultiSigChangeReqParams{}) cbor.RegisterCborType(MTransaction{}) + cbor.RegisterCborType(MultiSigRemoveSignerParam{}) + cbor.RegisterCborType(MultiSigAddSignerParam{}) } type MultiSigActor struct{} @@ -262,12 +263,13 @@ func (msa MultiSigActor) Cancel(act *types.Actor, vmctx types.VMContext, return nil, msa.save(vmctx, head, self) } -type MultiSigSigner struct { - Signer address.Address +type MultiSigAddSignerParam struct { + Signer address.Address + Increase bool } func (msa MultiSigActor) AddSigner(act *types.Actor, vmctx types.VMContext, - params *MultiSigSigner) ([]byte, ActorError) { + params *MultiSigAddSignerParam) ([]byte, ActorError) { head, self, err := msa.load(vmctx) if err != nil { @@ -281,13 +283,22 @@ func (msa MultiSigActor) AddSigner(act *types.Actor, vmctx types.VMContext, if self.isSigner(params.Signer) { return nil, aerrors.New(5, "new address is already a signer") } + self.Signers = append(self.Signers, params.Signer) + if params.Increase { + self.Required = self.Required + 1 + } return nil, msa.save(vmctx, head, self) } +type MultiSigRemoveSignerParam struct { + Signer address.Address + Decrease bool +} + func (msa MultiSigActor) RemoveSigner(act *types.Actor, vmctx types.VMContext, - params *MultiSigSigner) ([]byte, ActorError) { + params *MultiSigRemoveSignerParam) ([]byte, ActorError) { head, self, err := msa.load(vmctx) if err != nil { @@ -308,6 +319,10 @@ func (msa MultiSigActor) RemoveSigner(act *types.Actor, vmctx types.VMContext, newSigners = append(newSigners, s) } } + if params.Decrease || uint32(len(self.Signers)-1) < self.Required { + self.Required = self.Required - 1 + } + self.Signers = newSigners return nil, msa.save(vmctx, head, self) diff --git a/chain/actors/actor_multisig_test.go b/chain/actors/actor_multisig_test.go index 57be8666c..8dc636f2d 100644 --- a/chain/actors/actor_multisig_test.go +++ b/chain/actors/actor_multisig_test.go @@ -53,7 +53,7 @@ func TestMultiSigOps(t *testing.T) { HarnessAddr(&creatorAddr, 10000), HarnessAddr(&sig1Addr, 10000), HarnessAddr(&sig2Addr, 10000), - HarnessAddr(&outsideAddr, 0), + HarnessAddr(&outsideAddr, 1000), HarnessActor(&multSigAddr, &creatorAddr, actors.MultisigActorCodeCid, func() interface{} { return actors.MultiSigConstructorParams{ @@ -66,6 +66,7 @@ func TestMultiSigOps(t *testing.T) { curVal := types.NewInt(2000) h := NewHarness2(t, opts...) { + // Send funds into the multisig ret, state := h.SendFunds(t, creatorAddr, multSigAddr, curVal) ApplyOK(t, ret) ms, err := state.GetActor(multSigAddr) @@ -74,6 +75,7 @@ func TestMultiSigOps(t *testing.T) { } { + // Transfer funds outside of multsig sendVal := types.NewInt(100) ret, _ := h.Invoke(t, creatorAddr, multSigAddr, actors.MultiSigMethods.Propose, actors.MultiSigProposeParams{ @@ -84,14 +86,19 @@ func TestMultiSigOps(t *testing.T) { var txIDParam actors.MultiSigTxID err := cbor.DecodeInto(ret.Return, &txIDParam.TxID) assert.NoError(t, err, "decoding txid") + + ret, _ = h.Invoke(t, outsideAddr, multSigAddr, actors.MultiSigMethods.Approve, + txIDParam) + assert.Equal(t, uint8(1), ret.ExitCode, "outsideAddr should not approve") + ret, state := h.Invoke(t, sig1Addr, multSigAddr, actors.MultiSigMethods.Approve, txIDParam) + outAct, err := state.GetActor(outsideAddr) ApplyOK(t, ret) curVal = types.BigSub(curVal, sendVal) - outAct, err := state.GetActor(outsideAddr) assert.NoError(t, err) - assert.Equal(t, sendVal, outAct.Balance) + assert.Equal(t, types.NewInt(1099), outAct.Balance) msAct, err := state.GetActor(multSigAddr) assert.NoError(t, err) diff --git a/chain/vm/vm.go b/chain/vm/vm.go index 95110b6f0..1ec5c184a 100644 --- a/chain/vm/vm.go +++ b/chain/vm/vm.go @@ -242,7 +242,7 @@ func (vm *VM) ApplyMessage(ctx context.Context, msg *types.Message) (*ApplyRet, gascost := types.BigMul(msg.GasLimit, msg.GasPrice) totalCost := types.BigAdd(gascost, msg.Value) if types.BigCmp(fromActor.Balance, totalCost) < 0 { - return nil, xerrors.Errorf("not enough funds") + return nil, xerrors.Errorf("not enough funds (%s < %s)", fromActor.Balance, totalCost) } if err := DeductFunds(fromActor, gascost); err != nil { return nil, xerrors.Errorf("failed to deduct funds: %w", err)