convert multisig to new actor abstractions

This commit is contained in:
Steven Allen 2020-09-21 13:13:38 -07:00
parent f9a896f6f2
commit 0ab2459fce
3 changed files with 74 additions and 71 deletions

View File

@ -3,9 +3,12 @@ package multisig
import ( import (
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/cbor" "github.com/filecoin-project/go-state-types/cbor"
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
"github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
@ -31,4 +34,10 @@ type State interface {
StartEpoch() abi.ChainEpoch StartEpoch() abi.ChainEpoch
UnlockDuration() abi.ChainEpoch UnlockDuration() abi.ChainEpoch
InitialBalance() abi.TokenAmount InitialBalance() abi.TokenAmount
Threshold() uint64
Signers() []address.Address
ForEachPendingTxn(func(id int64, txn Transaction) error) error
} }
type Transaction = msig0.Transaction

View File

@ -1,15 +1,21 @@
package multisig package multisig
import ( import (
"encoding/binary"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/specs-actors/actors/builtin/multisig" "golang.org/x/xerrors"
msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
adt0 "github.com/filecoin-project/specs-actors/actors/util/adt"
) )
var _ State = (*state0)(nil) var _ State = (*state0)(nil)
type state0 struct { type state0 struct {
multisig.State msig0.State
store adt.Store store adt.Store
} }
@ -28,3 +34,26 @@ func (s *state0) UnlockDuration() abi.ChainEpoch {
func (s *state0) InitialBalance() abi.TokenAmount { func (s *state0) InitialBalance() abi.TokenAmount {
return s.State.InitialBalance return s.State.InitialBalance
} }
func (s *state0) Threshold() uint64 {
return s.State.NumApprovalsThreshold
}
func (s *state0) Signers() []address.Address {
return s.State.Signers
}
func (s *state0) ForEachPendingTxn(cb func(id int64, txn Transaction) error) error {
arr, err := adt0.AsMap(s.store, s.State.PendingTxns)
if err != nil {
return err
}
var out msig0.Transaction
return arr.ForEach(&out, func(key string) error {
txid, n := binary.Varint([]byte(key))
if n <= 0 {
return xerrors.Errorf("invalid pending transaction key: %v", key)
}
return cb(txid, (Transaction)(out))
})
}

View File

@ -2,8 +2,6 @@ package cli
import ( import (
"bytes" "bytes"
"context"
"encoding/binary"
"encoding/hex" "encoding/hex"
"fmt" "fmt"
"os" "os"
@ -12,21 +10,21 @@ import (
"text/tabwriter" "text/tabwriter"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
cid "github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/specs-actors/actors/builtin"
init0 "github.com/filecoin-project/specs-actors/actors/builtin/init"
msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
"github.com/filecoin-project/lotus/api/apibstore" "github.com/filecoin-project/lotus/api/apibstore"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
types "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin/multisig"
"github.com/filecoin-project/lotus/chain/types"
) )
var multisigCmd = &cli.Command{ var multisigCmd = &cli.Command{
@ -146,7 +144,7 @@ var msigCreateCmd = &cli.Command{
// get address of newly created miner // get address of newly created miner
var execreturn init_.ExecReturn var execreturn init0.ExecReturn
if err := execreturn.UnmarshalCBOR(bytes.NewReader(wait.Receipt.Return)); err != nil { if err := execreturn.UnmarshalCBOR(bytes.NewReader(wait.Receipt.Return)); err != nil {
return err return err
} }
@ -179,50 +177,54 @@ var msigInspectCmd = &cli.Command{
defer closer() defer closer()
ctx := ReqContext(cctx) ctx := ReqContext(cctx)
store := adt.WrapStore(ctx, cbor.NewCborStore(apibstore.NewAPIBlockstore(api)))
maddr, err := address.NewFromString(cctx.Args().First()) maddr, err := address.NewFromString(cctx.Args().First())
if err != nil { if err != nil {
return err return err
} }
act, err := api.StateGetActor(ctx, maddr, types.EmptyTSK)
if err != nil {
return err
}
obj, err := api.ChainReadObj(ctx, act.Head)
if err != nil {
return err
}
head, err := api.ChainHead(ctx) head, err := api.ChainHead(ctx)
if err != nil { if err != nil {
return err return err
} }
var mstate msig0.State act, err := api.StateGetActor(ctx, maddr, head.Key())
if err := mstate.UnmarshalCBOR(bytes.NewReader(obj)); err != nil { if err != nil {
return err
}
mstate, err := multisig.Load(store, act)
if err != nil {
return err
}
locked, err := mstate.LockedBalance(head.Height())
if err != nil {
return err return err
} }
locked := mstate.AmountLocked(head.Height() - mstate.StartEpoch)
fmt.Printf("Balance: %s\n", types.FIL(act.Balance)) fmt.Printf("Balance: %s\n", types.FIL(act.Balance))
fmt.Printf("Spendable: %s\n", types.FIL(types.BigSub(act.Balance, locked))) fmt.Printf("Spendable: %s\n", types.FIL(types.BigSub(act.Balance, locked)))
if cctx.Bool("vesting") { if cctx.Bool("vesting") {
fmt.Printf("InitialBalance: %s\n", types.FIL(mstate.InitialBalance)) fmt.Printf("InitialBalance: %s\n", types.FIL(mstate.InitialBalance()))
fmt.Printf("StartEpoch: %d\n", mstate.StartEpoch) fmt.Printf("StartEpoch: %d\n", mstate.StartEpoch())
fmt.Printf("UnlockDuration: %d\n", mstate.UnlockDuration) fmt.Printf("UnlockDuration: %d\n", mstate.UnlockDuration())
} }
fmt.Printf("Threshold: %d / %d\n", mstate.NumApprovalsThreshold, len(mstate.Signers)) signers := mstate.Signers()
fmt.Printf("Threshold: %d / %d\n", mstate.Threshold(), len(signers))
fmt.Println("Signers:") fmt.Println("Signers:")
for _, s := range mstate.Signers { for _, s := range signers {
fmt.Printf("\t%s\n", s) fmt.Printf("\t%s\n", s)
} }
pending, err := GetMultisigPending(ctx, api, mstate.PendingTxns) pending := make(map[int64]multisig.Transaction)
if err != nil { if err := mstate.ForEachPendingTxn(func(id int64, txn multisig.Transaction) error {
return fmt.Errorf("reading pending transactions: %w", err) pending[id] = txn
return nil
}); err != nil {
return xerrors.Errorf("reading pending transactions: %w", err)
} }
fmt.Println("Transactions: ", len(pending)) fmt.Println("Transactions: ", len(pending))
@ -239,7 +241,7 @@ var msigInspectCmd = &cli.Command{
fmt.Fprintf(w, "ID\tState\tApprovals\tTo\tValue\tMethod\tParams\n") fmt.Fprintf(w, "ID\tState\tApprovals\tTo\tValue\tMethod\tParams\n")
for _, txid := range txids { for _, txid := range txids {
tx := pending[txid] tx := pending[txid]
fmt.Fprintf(w, "%d\t%s\t%d\t%s\t%s\t%d\t%x\n", txid, state(tx), len(tx.Approved), tx.To, types.FIL(tx.Value), tx.Method, tx.Params) fmt.Fprintf(w, "%d\t%s\t%d\t%s\t%s\t%d\t%x\n", txid, "pending", len(tx.Approved), tx.To, types.FIL(tx.Value), tx.Method, tx.Params)
} }
if err := w.Flush(); err != nil { if err := w.Flush(); err != nil {
return xerrors.Errorf("flushing output: %+v", err) return xerrors.Errorf("flushing output: %+v", err)
@ -251,43 +253,6 @@ var msigInspectCmd = &cli.Command{
}, },
} }
func GetMultisigPending(ctx context.Context, lapi api.FullNode, hroot cid.Cid) (map[int64]*msig0.Transaction, error) {
bs := apibstore.NewAPIBlockstore(lapi)
store := adt.WrapStore(ctx, cbor.NewCborStore(bs))
nd, err := adt.AsMap(store, hroot)
if err != nil {
return nil, err
}
txs := make(map[int64]*msig0.Transaction)
var tx msig0.Transaction
err = nd.ForEach(&tx, func(k string) error {
txid, _ := binary.Varint([]byte(k))
cpy := tx // copy so we don't clobber on future iterations.
txs[txid] = &cpy
return nil
})
if err != nil {
return nil, xerrors.Errorf("failed to iterate transactions hamt: %w", err)
}
return txs, nil
}
func state(tx *msig0.Transaction) string {
/* // TODO(why): I strongly disagree with not having these... but i need to move forward
if tx.Complete {
return "done"
}
if tx.Canceled {
return "canceled"
}
*/
return "pending"
}
var msigProposeCmd = &cli.Command{ var msigProposeCmd = &cli.Command{
Name: "propose", Name: "propose",
Usage: "Propose a multisig transaction", Usage: "Propose a multisig transaction",