From 0efb4ca3a7c75b4ebdc6f78b2e81c5b7ef088eb9 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Wed, 3 Feb 2021 20:46:10 -0800 Subject: [PATCH] add an api endpoint to get pending transactions for multisigs --- api/api_full.go | 16 ++++++++++++++++ api/api_gateway.go | 1 + api/apistruct/struct.go | 10 ++++++++++ cmd/lotus-gateway/api.go | 9 +++++++++ node/impl/full/state.go | 35 +++++++++++++++++++++++++++++++++++ 5 files changed, 71 insertions(+) diff --git a/api/api_full.go b/api/api_full.go index 12b3ecf63..a84d393ad 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -460,6 +460,12 @@ type FullNode interface { // MsigGetVested returns the amount of FIL that vested in a multisig in a certain period. // It takes the following params: , , MsigGetVested(context.Context, address.Address, types.TipSetKey, types.TipSetKey) (types.BigInt, error) + + //MsigGetPending returns pending transactions for the given multisig + //wallet. Once pending transactions are fully approved, they will no longer + //appear here. + MsigGetPending(context.Context, address.Address, types.TipSetKey) ([]*MsigTransaction, error) + // MsigCreate creates a multisig wallet // It takes the following params: , , //, , @@ -982,3 +988,13 @@ type MessageMatch struct { To address.Address From address.Address } + +type MsigTransaction struct { + ID int64 + To address.Address + Value abi.TokenAmount + Method abi.MethodNum + Params []byte + + Approved []address.Address +} diff --git a/api/api_gateway.go b/api/api_gateway.go index 2be0e057a..a53ac221a 100644 --- a/api/api_gateway.go +++ b/api/api_gateway.go @@ -27,6 +27,7 @@ type GatewayAPI interface { MpoolPush(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error) MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error) MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error) + MsigGetPending(context.Context, address.Address, types.TipSetKey) ([]*MsigTransaction, error) StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (DealCollateralBounds, error) StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error) diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index 656357c1b..855ba6f59 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -232,6 +232,7 @@ type FullNodeStruct struct { MsigGetAvailableBalance func(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) `perm:"read"` MsigGetVestingSchedule func(context.Context, address.Address, types.TipSetKey) (api.MsigVesting, error) `perm:"read"` MsigGetVested func(context.Context, address.Address, types.TipSetKey, types.TipSetKey) (types.BigInt, error) `perm:"read"` + MsigGetPending func(context.Context, address.Address, types.TipSetKey) ([]*api.MsigTransaction, error) `perm:"read"` MsigCreate func(context.Context, uint64, []address.Address, abi.ChainEpoch, 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) (cid.Cid, error) `perm:"sign"` @@ -434,6 +435,7 @@ type GatewayStruct struct { MpoolPush func(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error) MsigGetAvailableBalance func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error) MsigGetVested func(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error) + MsigGetPending func(context.Context, address.Address, types.TipSetKey) ([]*api.MsigTransaction, error) StateAccountKey func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) StateDealProviderCollateralBounds func(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (api.DealCollateralBounds, error) StateGetActor func(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error) @@ -1112,6 +1114,10 @@ func (c *FullNodeStruct) MsigGetVested(ctx context.Context, a address.Address, s return c.Internal.MsigGetVested(ctx, a, sTsk, eTsk) } +func (c *FullNodeStruct) MsigGetPending(ctx context.Context, a address.Address, tsk types.TipSetKey) ([]*api.MsigTransaction, error) { + return c.Internal.MsigGetPending(ctx, a, tsk) +} + func (c *FullNodeStruct) MsigCreate(ctx context.Context, req uint64, addrs []address.Address, duration abi.ChainEpoch, val types.BigInt, src address.Address, gp types.BigInt) (cid.Cid, error) { return c.Internal.MsigCreate(ctx, req, addrs, duration, val, src, gp) } @@ -1738,6 +1744,10 @@ func (g GatewayStruct) MsigGetVested(ctx context.Context, addr address.Address, return g.Internal.MsigGetVested(ctx, addr, start, end) } +func (g GatewayStruct) MsigGetPending(ctx context.Context, addr address.Address, tsk types.TipSetKey) ([]*api.MsigTransaction, error) { + return g.Internal.MsigGetPending(ctx, addr, tsk) +} + func (g GatewayStruct) StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) { return g.Internal.StateAccountKey(ctx, addr, tsk) } diff --git a/cmd/lotus-gateway/api.go b/cmd/lotus-gateway/api.go index 2b5023739..11e78a606 100644 --- a/cmd/lotus-gateway/api.go +++ b/cmd/lotus-gateway/api.go @@ -48,6 +48,7 @@ type gatewayDepsAPI interface { MpoolPushUntrusted(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error) MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error) MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error) + MsigGetPending(ctx context.Context, addr address.Address, ts types.TipSetKey) ([]*api.MsigTransaction, error) StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (api.DealCollateralBounds, error) StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error) @@ -228,6 +229,14 @@ func (a *GatewayAPI) MsigGetVested(ctx context.Context, addr address.Address, st return a.api.MsigGetVested(ctx, addr, start, end) } +func (a *GatewayAPI) MsigGetPending(ctx context.Context, addr address.Address, tsk types.TipSetKey) ([]*api.MsigTransaction, error) { + if err := a.checkTipsetKey(ctx, tsk); err != nil { + return nil, err + } + + return a.api.MsigGetPending(ctx, addr, tsk) +} + func (a *GatewayAPI) StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) { if err := a.checkTipsetKey(ctx, tsk); err != nil { return address.Undef, err diff --git a/node/impl/full/state.go b/node/impl/full/state.go index bfe1ed0e8..4377571ae 100644 --- a/node/impl/full/state.go +++ b/node/impl/full/state.go @@ -42,6 +42,7 @@ import ( type StateModuleAPI interface { MsigGetAvailableBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (types.BigInt, error) MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error) + MsigGetPending(ctx context.Context, addr address.Address, tsk types.TipSetKey) ([]*api.MsigTransaction, error) StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (api.DealCollateralBounds, error) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) @@ -1008,6 +1009,40 @@ func (m *StateModule) MsigGetVested(ctx context.Context, addr address.Address, s return types.BigSub(startLk, endLk), nil } +func (m *StateModule) MsigGetPending(ctx context.Context, addr address.Address, tsk types.TipSetKey) ([]*api.MsigTransaction, error) { + ts, err := m.Chain.GetTipSetFromKey(tsk) + if err != nil { + return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err) + } + + act, err := m.StateManager.LoadActor(ctx, addr, ts) + if err != nil { + return nil, xerrors.Errorf("failed to load multisig actor: %w", err) + } + msas, err := multisig.Load(m.Chain.Store(ctx), act) + if err != nil { + return nil, xerrors.Errorf("failed to load multisig actor state: %w", err) + } + + var out = []*api.MsigTransaction{} + if err := msas.ForEachPendingTxn(func(id int64, txn multisig.Transaction) error { + out = append(out, &api.MsigTransaction{ + ID: id, + To: txn.To, + Value: txn.Value, + Method: txn.Method, + Params: txn.Params, + + Approved: txn.Approved, + }) + return nil + }); err != nil { + return nil, err + } + + return out, nil +} + var initialPledgeNum = types.NewInt(110) var initialPledgeDen = types.NewInt(100)