abstract multisig calls

This commit is contained in:
Steven Allen
2020-09-30 12:30:02 -07:00
parent 2e9915ac28
commit b01a1d457a
7 changed files with 314 additions and 112 deletions
+31 -112
View File
@@ -9,15 +9,13 @@ import (
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/actors"
init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init"
"github.com/filecoin-project/lotus/chain/actors/builtin/multisig"
"github.com/filecoin-project/lotus/chain/types"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
init0 "github.com/filecoin-project/specs-actors/actors/builtin/init"
multisig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
"github.com/ipfs/go-cid"
"github.com/minio/blake2b-simd"
"go.uber.org/fx"
"golang.org/x/xerrors"
)
@@ -30,58 +28,31 @@ type MsigAPI struct {
MpoolAPI MpoolAPI
}
func (a *MsigAPI) messageBuilder(ctx context.Context, from address.Address) (multisig.MessageBuilder, error) {
nver, err := a.StateAPI.StateNetworkVersion(ctx, types.EmptyTSK)
if err != nil {
return nil, err
}
return multisig.Message(actors.VersionForNetwork(nver), from), nil
}
// TODO: remove gp (gasPrice) from arguments
// TODO: Add "vesting start" to arguments.
func (a *MsigAPI) MsigCreate(ctx context.Context, req uint64, addrs []address.Address, duration abi.ChainEpoch, val types.BigInt, src address.Address, gp types.BigInt) (cid.Cid, error) {
lenAddrs := uint64(len(addrs))
if lenAddrs < req {
return cid.Undef, xerrors.Errorf("cannot require signing of more addresses than provided for multisig")
mb, err := a.messageBuilder(ctx, src)
if err != nil {
return cid.Undef, err
}
if req == 0 {
req = lenAddrs
}
if src == address.Undef {
return cid.Undef, xerrors.Errorf("must provide source address")
}
// Set up constructor parameters for multisig
msigParams := &multisig0.ConstructorParams{
Signers: addrs,
NumApprovalsThreshold: req,
UnlockDuration: duration,
}
enc, actErr := actors.SerializeParams(msigParams)
if actErr != nil {
return cid.Undef, actErr
}
// new actors are created by invoking 'exec' on the init actor with the constructor params
// TODO: network upgrade?
execParams := &init0.ExecParams{
CodeCID: builtin0.MultisigActorCodeID,
ConstructorParams: enc,
}
enc, actErr = actors.SerializeParams(execParams)
if actErr != nil {
return cid.Undef, actErr
}
// now we create the message to send this with
msg := types.Message{
To: init_.Address,
From: src,
Method: builtin0.MethodsInit.Exec,
Params: enc,
Value: val,
msg, err := mb.Create(addrs, req, 0, duration, val)
if err != nil {
return cid.Undef, err
}
// send the message out to the network
smsg, err := a.MpoolAPI.MpoolPushMessage(ctx, &msg, nil)
smsg, err := a.MpoolAPI.MpoolPushMessage(ctx, msg, nil)
if err != nil {
return cid.Undef, err
}
@@ -91,38 +62,14 @@ func (a *MsigAPI) MsigCreate(ctx context.Context, req uint64, addrs []address.Ad
func (a *MsigAPI) MsigPropose(ctx context.Context, msig address.Address, to address.Address, amt types.BigInt, src address.Address, method uint64, params []byte) (cid.Cid, error) {
if msig == address.Undef {
return cid.Undef, xerrors.Errorf("must provide a multisig address for proposal")
mb, err := a.messageBuilder(ctx, src)
if err != nil {
return cid.Undef, err
}
if to == address.Undef {
return cid.Undef, xerrors.Errorf("must provide a target address for proposal")
}
if amt.Sign() == -1 {
return cid.Undef, xerrors.Errorf("must provide a positive amount for proposed send")
}
if src == address.Undef {
return cid.Undef, xerrors.Errorf("must provide source address")
}
enc, actErr := actors.SerializeParams(&multisig0.ProposeParams{
To: to,
Value: amt,
Method: abi.MethodNum(method),
Params: params,
})
if actErr != nil {
return cid.Undef, xerrors.Errorf("failed to serialize parameters: %w", actErr)
}
msg := &types.Message{
To: msig,
From: src,
Value: types.NewInt(0),
Method: builtin0.MethodsMultisig.Propose,
Params: enc,
msg, err := mb.Propose(msig, to, amt, abi.MethodNum(method), params)
if err != nil {
return cid.Undef, xerrors.Errorf("failed to create proposal: %w", err)
}
smsg, err := a.MpoolAPI.MpoolPushMessage(ctx, msg, nil)
@@ -200,14 +147,6 @@ func (a *MsigAPI) msigApproveOrCancel(ctx context.Context, operation api.MsigPro
return cid.Undef, xerrors.Errorf("must provide multisig address")
}
if to == address.Undef {
return cid.Undef, xerrors.Errorf("must provide proposed target address")
}
if amt.Sign() == -1 {
return cid.Undef, xerrors.Errorf("must provide the positive amount that was proposed")
}
if src == address.Undef {
return cid.Undef, xerrors.Errorf("must provide source address")
}
@@ -220,7 +159,7 @@ func (a *MsigAPI) msigApproveOrCancel(ctx context.Context, operation api.MsigPro
proposer = proposerID
}
p := multisig0.ProposalHashData{
p := multisig.ProposalHashData{
Requester: proposer,
To: to,
Value: amt,
@@ -228,42 +167,22 @@ func (a *MsigAPI) msigApproveOrCancel(ctx context.Context, operation api.MsigPro
Params: params,
}
pser, err := p.Serialize()
if err != nil {
return cid.Undef, err
}
phash := blake2b.Sum256(pser)
enc, err := actors.SerializeParams(&multisig0.TxnIDParams{
ID: multisig0.TxnID(txID),
ProposalHash: phash[:],
})
mb, err := a.messageBuilder(ctx, src)
if err != nil {
return cid.Undef, err
}
var msigResponseMethod abi.MethodNum
/*
We pass in a MsigProposeResponse instead of MethodNum to
tighten the possible inputs to just Approve and Cancel.
*/
var msg *types.Message
switch operation {
case api.MsigApprove:
msigResponseMethod = builtin0.MethodsMultisig.Approve
msg, err = mb.Approve(msig, txID, &p)
case api.MsigCancel:
msigResponseMethod = builtin0.MethodsMultisig.Cancel
msg, err = mb.Cancel(msig, txID, &p)
default:
return cid.Undef, xerrors.Errorf("Invalid operation for msigApproveOrCancel")
}
msg := &types.Message{
To: msig,
From: src,
Value: types.NewInt(0),
Method: msigResponseMethod,
Params: enc,
if err != nil {
return cid.Undef, err
}
smsg, err := a.MpoolAPI.MpoolPushMessage(ctx, msg, nil)