Merge pull request #1665 from aagdere/aa/Add-Msig-Send-RPC
Added RPC calls for MsigCreate, MsigPropose, MsigApprove, and MsigCancel
This commit is contained in:
commit
728ae01012
@ -147,6 +147,10 @@ type FullNode interface {
|
|||||||
StateCompute(context.Context, abi.ChainEpoch, []*types.Message, types.TipSetKey) (*ComputeStateOutput, error)
|
StateCompute(context.Context, abi.ChainEpoch, []*types.Message, types.TipSetKey) (*ComputeStateOutput, error)
|
||||||
|
|
||||||
MsigGetAvailableBalance(context.Context, address.Address, types.TipSetKey) (types.BigInt, error)
|
MsigGetAvailableBalance(context.Context, address.Address, types.TipSetKey) (types.BigInt, error)
|
||||||
|
MsigCreate(context.Context, int64, []address.Address, types.BigInt, address.Address, types.BigInt) (cid.Cid, error)
|
||||||
|
MsigPropose(context.Context, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error)
|
||||||
|
MsigApprove(context.Context, address.Address, uint64, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error)
|
||||||
|
MsigCancel(context.Context, address.Address, uint64, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error)
|
||||||
|
|
||||||
MarketEnsureAvailable(context.Context, address.Address, address.Address, types.BigInt) (cid.Cid, error)
|
MarketEnsureAvailable(context.Context, address.Address, address.Address, types.BigInt) (cid.Cid, error)
|
||||||
// MarketFreeBalance
|
// MarketFreeBalance
|
||||||
@ -413,3 +417,10 @@ type HeadChange struct {
|
|||||||
Type string
|
Type string
|
||||||
Val *types.TipSet
|
Val *types.TipSet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type MsigProposeResponse int
|
||||||
|
|
||||||
|
const (
|
||||||
|
MsigApprove MsigProposeResponse = iota
|
||||||
|
MsigCancel
|
||||||
|
)
|
||||||
|
@ -145,7 +145,11 @@ type FullNodeStruct struct {
|
|||||||
StateListMessages func(ctx context.Context, match *types.Message, tsk types.TipSetKey, toht abi.ChainEpoch) ([]cid.Cid, error) `perm:"read"`
|
StateListMessages func(ctx context.Context, match *types.Message, tsk types.TipSetKey, toht abi.ChainEpoch) ([]cid.Cid, error) `perm:"read"`
|
||||||
StateCompute func(context.Context, abi.ChainEpoch, []*types.Message, types.TipSetKey) (*api.ComputeStateOutput, error) `perm:"read"`
|
StateCompute func(context.Context, abi.ChainEpoch, []*types.Message, types.TipSetKey) (*api.ComputeStateOutput, error) `perm:"read"`
|
||||||
|
|
||||||
MsigGetAvailableBalance func(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) `perm:"read"`
|
MsigGetAvailableBalance func(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) `perm:"read"`
|
||||||
|
MsigCreate func(context.Context, int64, []address.Address, types.BigInt, address.Address, types.BigInt) (cid.Cid, error) `perm:"sign"`
|
||||||
|
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, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error) `perm:"sign"`
|
||||||
|
|
||||||
MarketEnsureAvailable func(context.Context, address.Address, address.Address, types.BigInt) (cid.Cid, error) `perm:"sign"`
|
MarketEnsureAvailable func(context.Context, address.Address, address.Address, types.BigInt) (cid.Cid, error) `perm:"sign"`
|
||||||
|
|
||||||
@ -233,6 +237,8 @@ type WorkerStruct struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CommonStruct
|
||||||
|
|
||||||
func (c *CommonStruct) AuthVerify(ctx context.Context, token string) ([]api.Permission, error) {
|
func (c *CommonStruct) AuthVerify(ctx context.Context, token string) ([]api.Permission, error) {
|
||||||
return c.Internal.AuthVerify(ctx, token)
|
return c.Internal.AuthVerify(ctx, token)
|
||||||
}
|
}
|
||||||
@ -283,6 +289,8 @@ func (c *CommonStruct) LogSetLevel(ctx context.Context, group, level string) err
|
|||||||
return c.Internal.LogSetLevel(ctx, group, level)
|
return c.Internal.LogSetLevel(ctx, group, level)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FullNodeStruct
|
||||||
|
|
||||||
func (c *FullNodeStruct) ClientListImports(ctx context.Context) ([]api.Import, error) {
|
func (c *FullNodeStruct) ClientListImports(ctx context.Context) ([]api.Import, error) {
|
||||||
return c.Internal.ClientListImports(ctx)
|
return c.Internal.ClientListImports(ctx)
|
||||||
}
|
}
|
||||||
@ -621,6 +629,22 @@ func (c *FullNodeStruct) MsigGetAvailableBalance(ctx context.Context, a address.
|
|||||||
return c.Internal.MsigGetAvailableBalance(ctx, a, tsk)
|
return c.Internal.MsigGetAvailableBalance(ctx, a, tsk)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *FullNodeStruct) MsigCreate(ctx context.Context, req int64, addrs []address.Address, val types.BigInt, src address.Address, gp types.BigInt) (cid.Cid, error) {
|
||||||
|
return c.Internal.MsigCreate(ctx, req, addrs, val, src, gp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *FullNodeStruct) MsigPropose(ctx context.Context, msig address.Address, to address.Address, amt types.BigInt, src address.Address, method uint64, params []byte) (cid.Cid, error) {
|
||||||
|
return c.Internal.MsigPropose(ctx, msig, to, amt, src, method, params)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *FullNodeStruct) 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 c.Internal.MsigApprove(ctx, msig, txID, proposer, to, amt, src, method, params)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *FullNodeStruct) MsigCancel(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 c.Internal.MsigCancel(ctx, msig, txID, proposer, to, amt, src, method, params)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *FullNodeStruct) MarketEnsureAvailable(ctx context.Context, addr, wallet address.Address, amt types.BigInt) (cid.Cid, error) {
|
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)
|
return c.Internal.MarketEnsureAvailable(ctx, addr, wallet, amt)
|
||||||
}
|
}
|
||||||
@ -673,6 +697,8 @@ func (c *FullNodeStruct) PaychVoucherSubmit(ctx context.Context, ch address.Addr
|
|||||||
return c.Internal.PaychVoucherSubmit(ctx, ch, sv)
|
return c.Internal.PaychVoucherSubmit(ctx, ch, sv)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StorageMinerStruct
|
||||||
|
|
||||||
func (c *StorageMinerStruct) ActorAddress(ctx context.Context) (address.Address, error) {
|
func (c *StorageMinerStruct) ActorAddress(ctx context.Context) (address.Address, error) {
|
||||||
return c.Internal.ActorAddress(ctx)
|
return c.Internal.ActorAddress(ctx)
|
||||||
}
|
}
|
||||||
@ -783,6 +809,8 @@ func (c *StorageMinerStruct) StorageAddLocal(ctx context.Context, path string) e
|
|||||||
return c.Internal.StorageAddLocal(ctx, path)
|
return c.Internal.StorageAddLocal(ctx, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WorkerStruct
|
||||||
|
|
||||||
func (w *WorkerStruct) Version(ctx context.Context) (build.Version, error) {
|
func (w *WorkerStruct) Version(ctx context.Context) (build.Version, error) {
|
||||||
return w.Internal.Version(ctx)
|
return w.Internal.Version(ctx)
|
||||||
}
|
}
|
||||||
|
109
cli/multisig.go
109
cli/multisig.go
@ -6,15 +6,12 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/minio/blake2b-simd"
|
|
||||||
"os"
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
|
||||||
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
|
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
|
||||||
samsig "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
|
samsig "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
|
||||||
cid "github.com/ipfs/go-cid"
|
cid "github.com/ipfs/go-cid"
|
||||||
@ -26,7 +23,6 @@ import (
|
|||||||
|
|
||||||
"github.com/filecoin-project/lotus/api"
|
"github.com/filecoin-project/lotus/api"
|
||||||
"github.com/filecoin-project/lotus/api/apibstore"
|
"github.com/filecoin-project/lotus/api/apibstore"
|
||||||
actors "github.com/filecoin-project/lotus/chain/actors"
|
|
||||||
types "github.com/filecoin-project/lotus/chain/types"
|
types "github.com/filecoin-project/lotus/chain/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -106,52 +102,22 @@ var msigCreateCmd = &cli.Command{
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
intVal := types.BigInt(filval)
|
||||||
|
|
||||||
required := cctx.Int64("required")
|
required := cctx.Int64("required")
|
||||||
if required == 0 {
|
if required == 0 {
|
||||||
required = int64(len(addrs))
|
required = int64(len(addrs))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up constructor parameters for multisig
|
gp := types.NewInt(1)
|
||||||
msigParams := &samsig.ConstructorParams{
|
|
||||||
Signers: addrs,
|
|
||||||
NumApprovalsThreshold: required,
|
|
||||||
}
|
|
||||||
|
|
||||||
enc, err := actors.SerializeParams(msigParams)
|
msgCid, err := api.MsigCreate(ctx, required, addrs, intVal, sendAddr, gp)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// new actors are created by invoking 'exec' on the init actor with the constructor params
|
|
||||||
execParams := &init_.ExecParams{
|
|
||||||
CodeCID: builtin.MultisigActorCodeID,
|
|
||||||
ConstructorParams: enc,
|
|
||||||
}
|
|
||||||
|
|
||||||
enc, err = actors.SerializeParams(execParams)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// now we create the message to send this with
|
|
||||||
msg := types.Message{
|
|
||||||
To: builtin.InitActorAddr,
|
|
||||||
From: sendAddr,
|
|
||||||
Method: builtin.MethodsInit.Exec,
|
|
||||||
Params: enc,
|
|
||||||
GasPrice: types.NewInt(1),
|
|
||||||
GasLimit: 1000000,
|
|
||||||
Value: types.BigInt(filval),
|
|
||||||
}
|
|
||||||
|
|
||||||
// send the message out to the network
|
|
||||||
smsg, err := api.MpoolPushMessage(ctx, &msg)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait for it to get mined into a block
|
// wait for it to get mined into a block
|
||||||
wait, err := api.StateWaitMsg(ctx, smsg.Cid())
|
wait, err := api.StateWaitMsg(ctx, msgCid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -345,16 +311,6 @@ var msigProposeCmd = &cli.Command{
|
|||||||
params = p
|
params = p
|
||||||
}
|
}
|
||||||
|
|
||||||
enc, err := actors.SerializeParams(&samsig.ProposeParams{
|
|
||||||
To: dest,
|
|
||||||
Value: types.BigInt(value),
|
|
||||||
Method: abi.MethodNum(method),
|
|
||||||
Params: params,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var from address.Address
|
var from address.Address
|
||||||
if cctx.IsSet("source") {
|
if cctx.IsSet("source") {
|
||||||
f, err := address.NewFromString(cctx.String("source"))
|
f, err := address.NewFromString(cctx.String("source"))
|
||||||
@ -370,24 +326,14 @@ var msigProposeCmd = &cli.Command{
|
|||||||
from = defaddr
|
from = defaddr
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := &types.Message{
|
msgCid, err := api.MsigPropose(ctx, msig, dest, types.BigInt(value), from, method, params)
|
||||||
To: msig,
|
|
||||||
From: from,
|
|
||||||
Value: types.NewInt(0),
|
|
||||||
Method: builtin.MethodsMultisig.Propose,
|
|
||||||
Params: enc,
|
|
||||||
GasLimit: 100000,
|
|
||||||
GasPrice: types.NewInt(1),
|
|
||||||
}
|
|
||||||
|
|
||||||
smsg, err := api.MpoolPushMessage(ctx, msg)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("send proposal in message: ", smsg.Cid())
|
fmt.Println("send proposal in message: ", msgCid)
|
||||||
|
|
||||||
wait, err := api.StateWaitMsg(ctx, smsg.Cid())
|
wait, err := api.StateWaitMsg(ctx, msgCid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -481,29 +427,6 @@ var msigApproveCmd = &cli.Command{
|
|||||||
params = p
|
params = p
|
||||||
}
|
}
|
||||||
|
|
||||||
p := samsig.ProposalHashData{
|
|
||||||
Requester: proposer,
|
|
||||||
To: dest,
|
|
||||||
Value: types.BigInt(value),
|
|
||||||
Method: abi.MethodNum(method),
|
|
||||||
Params: params,
|
|
||||||
}
|
|
||||||
|
|
||||||
pser, err := p.Serialize()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
phash := blake2b.Sum256(pser)
|
|
||||||
|
|
||||||
enc, err := actors.SerializeParams(&samsig.TxnIDParams{
|
|
||||||
ID: samsig.TxnID(txid),
|
|
||||||
ProposalHash: phash[:],
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var from address.Address
|
var from address.Address
|
||||||
if cctx.IsSet("source") {
|
if cctx.IsSet("source") {
|
||||||
f, err := address.NewFromString(cctx.String("source"))
|
f, err := address.NewFromString(cctx.String("source"))
|
||||||
@ -519,24 +442,14 @@ var msigApproveCmd = &cli.Command{
|
|||||||
from = defaddr
|
from = defaddr
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := &types.Message{
|
msgCid, err := api.MsigApprove(ctx, msig, txid, proposer, dest, types.BigInt(value), from, method, params)
|
||||||
To: msig,
|
|
||||||
From: from,
|
|
||||||
Value: types.NewInt(0),
|
|
||||||
Method: builtin.MethodsMultisig.Approve,
|
|
||||||
Params: enc,
|
|
||||||
GasLimit: 100000,
|
|
||||||
GasPrice: types.NewInt(1),
|
|
||||||
}
|
|
||||||
|
|
||||||
smsg, err := api.MpoolPushMessage(ctx, msg)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("sent approval in message: ", smsg.Cid())
|
fmt.Println("sent approval in message: ", msgCid)
|
||||||
|
|
||||||
wait, err := api.StateWaitMsg(ctx, smsg.Cid())
|
wait, err := api.StateWaitMsg(ctx, msgCid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ type FullNodeAPI struct {
|
|||||||
market.MarketAPI
|
market.MarketAPI
|
||||||
paych.PaychAPI
|
paych.PaychAPI
|
||||||
full.StateAPI
|
full.StateAPI
|
||||||
|
full.MsigAPI
|
||||||
full.WalletAPI
|
full.WalletAPI
|
||||||
full.SyncAPI
|
full.SyncAPI
|
||||||
}
|
}
|
||||||
|
224
node/impl/full/multisig.go
Normal file
224
node/impl/full/multisig.go
Normal file
@ -0,0 +1,224 @@
|
|||||||
|
package full
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-address"
|
||||||
|
"github.com/filecoin-project/lotus/api"
|
||||||
|
"github.com/filecoin-project/lotus/chain/actors"
|
||||||
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
|
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||||
|
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||||
|
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
|
||||||
|
samsig "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"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MsigAPI struct {
|
||||||
|
fx.In
|
||||||
|
|
||||||
|
WalletAPI WalletAPI
|
||||||
|
StateAPI StateAPI
|
||||||
|
MpoolAPI MpoolAPI
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *MsigAPI) MsigCreate(ctx context.Context, req int64, addrs []address.Address, val types.BigInt, src address.Address, gp types.BigInt) (cid.Cid, error) {
|
||||||
|
|
||||||
|
lenAddrs := int64(len(addrs))
|
||||||
|
|
||||||
|
if lenAddrs < req {
|
||||||
|
return cid.Undef, xerrors.Errorf("cannot require signing of more addresses than provided for multisig")
|
||||||
|
}
|
||||||
|
|
||||||
|
if req == 0 {
|
||||||
|
req = lenAddrs
|
||||||
|
}
|
||||||
|
|
||||||
|
if src == address.Undef {
|
||||||
|
return cid.Undef, xerrors.Errorf("must provide source address")
|
||||||
|
}
|
||||||
|
|
||||||
|
if gp == types.EmptyInt {
|
||||||
|
gp = types.NewInt(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up constructor parameters for multisig
|
||||||
|
msigParams := &samsig.ConstructorParams{
|
||||||
|
Signers: addrs,
|
||||||
|
NumApprovalsThreshold: req,
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
execParams := &init_.ExecParams{
|
||||||
|
CodeCID: builtin.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: builtin.InitActorAddr,
|
||||||
|
From: src,
|
||||||
|
Method: builtin.MethodsInit.Exec,
|
||||||
|
Params: enc,
|
||||||
|
GasPrice: gp,
|
||||||
|
GasLimit: 1000000,
|
||||||
|
Value: val,
|
||||||
|
}
|
||||||
|
|
||||||
|
// send the message out to the network
|
||||||
|
smsg, err := a.MpoolAPI.MpoolPushMessage(ctx, &msg)
|
||||||
|
if err != nil {
|
||||||
|
return cid.Undef, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return smsg.Cid(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
|
||||||
|
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(&samsig.ProposeParams{
|
||||||
|
To: to,
|
||||||
|
Value: amt,
|
||||||
|
Method: abi.MethodNum(method),
|
||||||
|
Params: params,
|
||||||
|
})
|
||||||
|
if actErr != nil {
|
||||||
|
return cid.Undef, actErr
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := &types.Message{
|
||||||
|
To: msig,
|
||||||
|
From: src,
|
||||||
|
Value: types.NewInt(0),
|
||||||
|
Method: builtin.MethodsMultisig.Propose,
|
||||||
|
Params: enc,
|
||||||
|
GasLimit: 100000,
|
||||||
|
GasPrice: types.NewInt(1),
|
||||||
|
}
|
||||||
|
|
||||||
|
smsg, err := a.MpoolAPI.MpoolPushMessage(ctx, msg)
|
||||||
|
if err != nil {
|
||||||
|
return cid.Undef, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return smsg.Cid(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *MsigAPI) MsigCancel(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.MsigCancel, msig, txID, proposer, to, amt, src, method, params)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *MsigAPI) msigApproveOrCancel(ctx context.Context, operation api.MsigProposeResponse, msig address.Address, txID uint64, proposer 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 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")
|
||||||
|
}
|
||||||
|
|
||||||
|
if proposer.Protocol() != address.ID {
|
||||||
|
proposerID, err := a.StateAPI.StateLookupID(ctx, proposer, types.EmptyTSK)
|
||||||
|
if err != nil {
|
||||||
|
return cid.Undef, err
|
||||||
|
}
|
||||||
|
proposer = proposerID
|
||||||
|
}
|
||||||
|
|
||||||
|
p := samsig.ProposalHashData{
|
||||||
|
Requester: proposer,
|
||||||
|
To: to,
|
||||||
|
Value: amt,
|
||||||
|
Method: abi.MethodNum(method),
|
||||||
|
Params: params,
|
||||||
|
}
|
||||||
|
|
||||||
|
pser, err := p.Serialize()
|
||||||
|
if err != nil {
|
||||||
|
return cid.Undef, err
|
||||||
|
}
|
||||||
|
phash := blake2b.Sum256(pser)
|
||||||
|
|
||||||
|
enc, err := actors.SerializeParams(&samsig.TxnIDParams{
|
||||||
|
ID: samsig.TxnID(txID),
|
||||||
|
ProposalHash: phash[:],
|
||||||
|
})
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
switch operation {
|
||||||
|
case api.MsigApprove:
|
||||||
|
msigResponseMethod = builtin.MethodsMultisig.Approve
|
||||||
|
case api.MsigCancel:
|
||||||
|
msigResponseMethod = builtin.MethodsMultisig.Cancel
|
||||||
|
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,
|
||||||
|
GasLimit: 100000,
|
||||||
|
GasPrice: types.NewInt(1),
|
||||||
|
}
|
||||||
|
|
||||||
|
smsg, err := a.MpoolAPI.MpoolPushMessage(ctx, msg)
|
||||||
|
if err != nil {
|
||||||
|
return cid.Undef, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return smsg.Cid(), nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user