add payment channel CLI and finish up commands
This commit is contained in:
parent
c986267a2e
commit
12acee5242
@ -100,12 +100,13 @@ type FullNode interface {
|
|||||||
PaychCreate(ctx context.Context, from, to address.Address, amt types.BigInt) (address.Address, error)
|
PaychCreate(ctx context.Context, from, to address.Address, amt types.BigInt) (address.Address, error)
|
||||||
PaychList(context.Context) ([]address.Address, error)
|
PaychList(context.Context) ([]address.Address, error)
|
||||||
PaychStatus(context.Context, address.Address) (*PaychStatus, error)
|
PaychStatus(context.Context, address.Address) (*PaychStatus, error)
|
||||||
PaychClose(context.Context, address.Address) error
|
PaychClose(context.Context, address.Address) (cid.Cid, error)
|
||||||
PaychVoucherCheckValid(context.Context, address.Address, *types.SignedVoucher) error
|
PaychVoucherCheckValid(context.Context, address.Address, *types.SignedVoucher) error
|
||||||
PaychVoucherCheckSpendable(context.Context, address.Address, *types.SignedVoucher, []byte, []byte) (bool, error)
|
PaychVoucherCheckSpendable(context.Context, address.Address, *types.SignedVoucher, []byte, []byte) (bool, error)
|
||||||
PaychVoucherCreate(context.Context, address.Address, types.BigInt, uint64) (*types.SignedVoucher, error)
|
PaychVoucherCreate(context.Context, address.Address, types.BigInt, uint64) (*types.SignedVoucher, error)
|
||||||
PaychVoucherAdd(context.Context, address.Address, *types.SignedVoucher) error
|
PaychVoucherAdd(context.Context, address.Address, *types.SignedVoucher) error
|
||||||
PaychVoucherList(context.Context, address.Address) ([]*types.SignedVoucher, error)
|
PaychVoucherList(context.Context, address.Address) ([]*types.SignedVoucher, error)
|
||||||
|
PaychVoucherSubmit(context.Context, address.Address, *types.SignedVoucher) (cid.Cid, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Full API is a low-level interface to the Filecoin network storage miner node
|
// Full API is a low-level interface to the Filecoin network storage miner node
|
||||||
|
@ -76,13 +76,14 @@ type FullNodeStruct struct {
|
|||||||
PaychCreate func(ctx context.Context, from, to address.Address, amt types.BigInt) (address.Address, error) `perm:"sign"`
|
PaychCreate func(ctx context.Context, from, to address.Address, amt types.BigInt) (address.Address, error) `perm:"sign"`
|
||||||
PaychList func(context.Context) ([]address.Address, error) `perm:"read"`
|
PaychList func(context.Context) ([]address.Address, error) `perm:"read"`
|
||||||
PaychStatus func(context.Context, address.Address) (*PaychStatus, error) `perm:"read"`
|
PaychStatus func(context.Context, address.Address) (*PaychStatus, error) `perm:"read"`
|
||||||
PaychClose func(context.Context, address.Address) error `perm:"sign"`
|
PaychClose func(context.Context, address.Address) (cid.Cid, error) `perm:"sign"`
|
||||||
PaychVoucherCheck func(context.Context, *types.SignedVoucher) error `perm:"read"`
|
PaychVoucherCheck func(context.Context, *types.SignedVoucher) error `perm:"read"`
|
||||||
PaychVoucherCheckValid func(context.Context, address.Address, *types.SignedVoucher) error `perm:"read"`
|
PaychVoucherCheckValid func(context.Context, address.Address, *types.SignedVoucher) error `perm:"read"`
|
||||||
PaychVoucherCheckSpendable func(context.Context, address.Address, *types.SignedVoucher, []byte, []byte) (bool, error) `perm:"read"`
|
PaychVoucherCheckSpendable func(context.Context, address.Address, *types.SignedVoucher, []byte, []byte) (bool, error) `perm:"read"`
|
||||||
PaychVoucherAdd func(context.Context, address.Address, *types.SignedVoucher) error `perm:"write"`
|
PaychVoucherAdd func(context.Context, address.Address, *types.SignedVoucher) error `perm:"write"`
|
||||||
PaychVoucherCreate func(context.Context, address.Address, types.BigInt, uint64) (*types.SignedVoucher, error) `perm:"sign"`
|
PaychVoucherCreate func(context.Context, address.Address, types.BigInt, uint64) (*types.SignedVoucher, error) `perm:"sign"`
|
||||||
PaychVoucherList func(context.Context, address.Address) ([]*types.SignedVoucher, error) `perm:"write"`
|
PaychVoucherList func(context.Context, address.Address) ([]*types.SignedVoucher, error) `perm:"write"`
|
||||||
|
PaychVoucherSubmit func(context.Context, address.Address, *types.SignedVoucher) (cid.Cid, error) `perm:"sign"`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,10 +283,14 @@ func (c *FullNodeStruct) PaychVoucherList(ctx context.Context, pch address.Addre
|
|||||||
return c.Internal.PaychVoucherList(ctx, pch)
|
return c.Internal.PaychVoucherList(ctx, pch)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *FullNodeStruct) PaychClose(ctx context.Context, a address.Address) error {
|
func (c *FullNodeStruct) PaychClose(ctx context.Context, a address.Address) (cid.Cid, error) {
|
||||||
return c.Internal.PaychClose(ctx, a)
|
return c.Internal.PaychClose(ctx, a)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *FullNodeStruct) PaychVoucherSubmit(ctx context.Context, ch address.Address, sv *types.SignedVoucher) (cid.Cid, error) {
|
||||||
|
return c.Internal.PaychVoucherSubmit(ctx, ch, sv)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *StorageMinerStruct) ActorAddresses(ctx context.Context) ([]address.Address, error) {
|
func (c *StorageMinerStruct) ActorAddresses(ctx context.Context) ([]address.Address, error) {
|
||||||
return c.Internal.ActorAddresses(ctx)
|
return c.Internal.ActorAddresses(ctx)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-lotus/chain/address"
|
"github.com/filecoin-project/go-lotus/chain/address"
|
||||||
cbor "github.com/ipfs/go-ipld-cbor"
|
cbor "github.com/ipfs/go-ipld-cbor"
|
||||||
)
|
)
|
||||||
@ -31,6 +33,29 @@ func (sv *SignedVoucher) SigningBytes() ([]byte, error) {
|
|||||||
return cbor.DumpObject(osv)
|
return cbor.DumpObject(osv)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (sv *SignedVoucher) EncodedString() (string, error) {
|
||||||
|
data, err := cbor.DumpObject(sv)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return base64.RawURLEncoding.EncodeToString(data), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func DecodeSignedVoucher(s string) (*SignedVoucher, error) {
|
||||||
|
data, err := base64.RawURLEncoding.DecodeString(s)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var sv SignedVoucher
|
||||||
|
if err := cbor.DecodeInto(data, &sv); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &sv, nil
|
||||||
|
}
|
||||||
|
|
||||||
type Merge struct {
|
type Merge struct {
|
||||||
Lane uint64
|
Lane uint64
|
||||||
Nonce uint64
|
Nonce uint64
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package chain
|
package vm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -6,7 +6,6 @@ import (
|
|||||||
"github.com/filecoin-project/go-lotus/chain/actors"
|
"github.com/filecoin-project/go-lotus/chain/actors"
|
||||||
"github.com/filecoin-project/go-lotus/chain/store"
|
"github.com/filecoin-project/go-lotus/chain/store"
|
||||||
"github.com/filecoin-project/go-lotus/chain/types"
|
"github.com/filecoin-project/go-lotus/chain/types"
|
||||||
"github.com/filecoin-project/go-lotus/chain/vm"
|
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -19,7 +18,7 @@ func Call(ctx context.Context, cs *store.ChainStore, msg *types.Message, ts *typ
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
vmi, err := vm.NewVM(state, ts.Height(), ts.Blocks()[0].Miner, cs)
|
vmi, err := NewVM(state, ts.Height(), ts.Blocks()[0].Miner, cs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("failed to set up vm: %w", err)
|
return nil, xerrors.Errorf("failed to set up vm: %w", err)
|
||||||
}
|
}
|
||||||
@ -40,10 +39,21 @@ func Call(ctx context.Context, cs *store.ChainStore, msg *types.Message, ts *typ
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fromActor, err := vmi.cstate.GetActor(msg.From)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
msg.Nonce = fromActor.Nonce
|
||||||
|
|
||||||
// TODO: maybe just use the invoker directly?
|
// TODO: maybe just use the invoker directly?
|
||||||
ret, err := vmi.ApplyMessage(ctx, msg)
|
ret, err := vmi.ApplyMessage(ctx, msg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, xerrors.Errorf("apply message failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
if ret.ActorErr != nil {
|
if ret.ActorErr != nil {
|
||||||
log.Warnf("chain call failed: %s", ret.ActorErr)
|
log.Warnf("chain call failed: %s", ret.ActorErr)
|
||||||
}
|
}
|
||||||
return &ret.MessageReceipt, err
|
return &ret.MessageReceipt, nil
|
||||||
}
|
}
|
@ -116,12 +116,13 @@ func ReqContext(cctx *cli.Context) context.Context {
|
|||||||
var Commands = []*cli.Command{
|
var Commands = []*cli.Command{
|
||||||
chainCmd,
|
chainCmd,
|
||||||
clientCmd,
|
clientCmd,
|
||||||
|
createMinerCmd,
|
||||||
minerCmd,
|
minerCmd,
|
||||||
mpoolCmd,
|
mpoolCmd,
|
||||||
netCmd,
|
netCmd,
|
||||||
|
paychCmd,
|
||||||
|
sendCmd,
|
||||||
|
stateCmd,
|
||||||
versionCmd,
|
versionCmd,
|
||||||
walletCmd,
|
walletCmd,
|
||||||
createMinerCmd,
|
|
||||||
stateCmd,
|
|
||||||
sendCmd,
|
|
||||||
}
|
}
|
||||||
|
342
cli/paych.go
Normal file
342
cli/paych.go
Normal file
@ -0,0 +1,342 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-lotus/chain/address"
|
||||||
|
types "github.com/filecoin-project/go-lotus/chain/types"
|
||||||
|
"gopkg.in/urfave/cli.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
var paychCmd = &cli.Command{
|
||||||
|
Name: "paych",
|
||||||
|
Usage: "Manage payment channels",
|
||||||
|
Subcommands: []*cli.Command{
|
||||||
|
paychCreateCmd,
|
||||||
|
paychListCmd,
|
||||||
|
paychVoucherCmd,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var paychCreateCmd = &cli.Command{
|
||||||
|
Name: "create",
|
||||||
|
Usage: "Create a new payment channel",
|
||||||
|
Action: func(cctx *cli.Context) error {
|
||||||
|
if cctx.Args().Len() != 3 {
|
||||||
|
return fmt.Errorf("must pass three arguments: <from> <to> <amount>")
|
||||||
|
}
|
||||||
|
|
||||||
|
from, err := address.NewFromString(cctx.Args().Get(0))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to parse from address: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
to, err := address.NewFromString(cctx.Args().Get(1))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to parse to address: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
amt, err := types.BigFromString(cctx.Args().Get(2))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("parsing amount failed: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
api, err := GetFullNodeAPI(cctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := ReqContext(cctx)
|
||||||
|
|
||||||
|
addr, err := api.PaychCreate(ctx, from, to, amt)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(addr.String())
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var paychListCmd = &cli.Command{
|
||||||
|
Name: "list",
|
||||||
|
Usage: "List all locally registered payment channels",
|
||||||
|
Action: func(cctx *cli.Context) error {
|
||||||
|
api, err := GetFullNodeAPI(cctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := ReqContext(cctx)
|
||||||
|
|
||||||
|
chs, err := api.PaychList(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range chs {
|
||||||
|
fmt.Println(v.String())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var paychVoucherCmd = &cli.Command{
|
||||||
|
Name: "voucher",
|
||||||
|
Usage: "Interact with payment channel vouchers",
|
||||||
|
Subcommands: []*cli.Command{
|
||||||
|
paychVoucherCreateCmd,
|
||||||
|
paychVoucherCheckCmd,
|
||||||
|
paychVoucherAddCmd,
|
||||||
|
paychVoucherListCmd,
|
||||||
|
paychVoucherBestSpendableCmd,
|
||||||
|
paychVoucherSubmitCmd,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var paychVoucherCreateCmd = &cli.Command{
|
||||||
|
Name: "create",
|
||||||
|
Usage: "Create a signed payment channel voucher",
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
&cli.IntFlag{
|
||||||
|
Name: "lane",
|
||||||
|
Value: 0,
|
||||||
|
Usage: "specify payment channel lane to use",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Action: func(cctx *cli.Context) error {
|
||||||
|
if cctx.Args().Len() != 2 {
|
||||||
|
return fmt.Errorf("must pass two arguments: <channel> <amount>")
|
||||||
|
}
|
||||||
|
|
||||||
|
ch, err := address.NewFromString(cctx.Args().Get(0))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
amt, err := types.BigFromString(cctx.Args().Get(1))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
lane := cctx.Int("lane")
|
||||||
|
|
||||||
|
api, err := GetFullNodeAPI(cctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := ReqContext(cctx)
|
||||||
|
|
||||||
|
sv, err := api.PaychVoucherCreate(ctx, ch, amt, uint64(lane))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
enc, err := sv.EncodedString()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(enc)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var paychVoucherCheckCmd = &cli.Command{
|
||||||
|
Name: "check",
|
||||||
|
Usage: "Check validity of payment channel voucher",
|
||||||
|
Action: func(cctx *cli.Context) error {
|
||||||
|
if cctx.Args().Len() != 2 {
|
||||||
|
return fmt.Errorf("must pass payment channel address and voucher to validate")
|
||||||
|
}
|
||||||
|
|
||||||
|
ch, err := address.NewFromString(cctx.Args().Get(0))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
sv, err := types.DecodeSignedVoucher(cctx.Args().Get(1))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
api, err := GetFullNodeAPI(cctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := ReqContext(cctx)
|
||||||
|
|
||||||
|
if err := api.PaychVoucherCheckValid(ctx, ch, sv); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("voucher is valid")
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var paychVoucherAddCmd = &cli.Command{
|
||||||
|
Name: "add",
|
||||||
|
Usage: "Add payment channel voucher to local datastore",
|
||||||
|
Action: func(cctx *cli.Context) error {
|
||||||
|
if cctx.Args().Len() != 2 {
|
||||||
|
return fmt.Errorf("must pass payment channel address and voucher")
|
||||||
|
}
|
||||||
|
|
||||||
|
ch, err := address.NewFromString(cctx.Args().Get(0))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
sv, err := types.DecodeSignedVoucher(cctx.Args().Get(1))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
api, err := GetFullNodeAPI(cctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := ReqContext(cctx)
|
||||||
|
|
||||||
|
if err := api.PaychVoucherAdd(ctx, ch, sv); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var paychVoucherListCmd = &cli.Command{
|
||||||
|
Name: "list",
|
||||||
|
Usage: "List stored vouchers for a given payment channel",
|
||||||
|
Action: func(cctx *cli.Context) error {
|
||||||
|
if cctx.Args().Len() != 1 {
|
||||||
|
return fmt.Errorf("must pass payment channel address")
|
||||||
|
}
|
||||||
|
|
||||||
|
ch, err := address.NewFromString(cctx.Args().Get(0))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
api, err := GetFullNodeAPI(cctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := ReqContext(cctx)
|
||||||
|
|
||||||
|
vouchers, err := api.PaychVoucherList(ctx, ch)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range vouchers {
|
||||||
|
fmt.Printf("Lane %d, Nonce %d: %s\n", v.Lane, v.Nonce, v.Amount.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var paychVoucherBestSpendableCmd = &cli.Command{
|
||||||
|
Name: "best-spendable",
|
||||||
|
Usage: "Print voucher with highest value that is currently spendable",
|
||||||
|
Action: func(cctx *cli.Context) error {
|
||||||
|
if cctx.Args().Len() != 1 {
|
||||||
|
return fmt.Errorf("must pass payment channel address")
|
||||||
|
}
|
||||||
|
|
||||||
|
ch, err := address.NewFromString(cctx.Args().Get(0))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
api, err := GetFullNodeAPI(cctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := ReqContext(cctx)
|
||||||
|
|
||||||
|
vouchers, err := api.PaychVoucherList(ctx, ch)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var best *types.SignedVoucher
|
||||||
|
for _, v := range vouchers {
|
||||||
|
spendable, err := api.PaychVoucherCheckSpendable(ctx, ch, v, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if spendable {
|
||||||
|
if best == nil || types.BigCmp(v.Amount, best.Amount) > 0 {
|
||||||
|
best = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if best == nil {
|
||||||
|
return fmt.Errorf("No spendable vouchers for that channel")
|
||||||
|
}
|
||||||
|
|
||||||
|
enc, err := best.EncodedString()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(enc)
|
||||||
|
fmt.Printf("Amount: %s\n", best.Amount)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var paychVoucherSubmitCmd = &cli.Command{
|
||||||
|
Name: "submit",
|
||||||
|
Usage: "Submit voucher to chain to update payment channel state",
|
||||||
|
Action: func(cctx *cli.Context) error {
|
||||||
|
if cctx.Args().Len() != 2 {
|
||||||
|
return fmt.Errorf("must pass payment channel address and voucher")
|
||||||
|
}
|
||||||
|
|
||||||
|
ch, err := address.NewFromString(cctx.Args().Get(0))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
sv, err := types.DecodeSignedVoucher(cctx.Args().Get(1))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
api, err := GetFullNodeAPI(cctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := ReqContext(cctx)
|
||||||
|
|
||||||
|
mcid, err := api.PaychVoucherSubmit(ctx, ch, sv)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
mwait, err := api.ChainWaitMsg(ctx, mcid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if mwait.Receipt.ExitCode != 0 {
|
||||||
|
return fmt.Errorf("message execution failed (exit code %d)", mwait.Receipt.ExitCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("channel updated succesfully")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
@ -16,6 +16,7 @@ import (
|
|||||||
"github.com/filecoin-project/go-lotus/chain/state"
|
"github.com/filecoin-project/go-lotus/chain/state"
|
||||||
"github.com/filecoin-project/go-lotus/chain/store"
|
"github.com/filecoin-project/go-lotus/chain/store"
|
||||||
"github.com/filecoin-project/go-lotus/chain/types"
|
"github.com/filecoin-project/go-lotus/chain/types"
|
||||||
|
"github.com/filecoin-project/go-lotus/chain/vm"
|
||||||
"github.com/filecoin-project/go-lotus/chain/wallet"
|
"github.com/filecoin-project/go-lotus/chain/wallet"
|
||||||
"github.com/filecoin-project/go-lotus/miner"
|
"github.com/filecoin-project/go-lotus/miner"
|
||||||
"github.com/filecoin-project/go-lotus/node/client"
|
"github.com/filecoin-project/go-lotus/node/client"
|
||||||
@ -157,7 +158,7 @@ func (a *FullNodeAPI) ChainGetBlockReceipts(ctx context.Context, bcid cid.Cid) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *FullNodeAPI) ChainCall(ctx context.Context, msg *types.Message, ts *types.TipSet) (*types.MessageReceipt, error) {
|
func (a *FullNodeAPI) ChainCall(ctx context.Context, msg *types.Message, ts *types.TipSet) (*types.MessageReceipt, error) {
|
||||||
return chain.Call(ctx, a.Chain, msg, ts)
|
return vm.Call(ctx, a.Chain, msg, ts)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *FullNodeAPI) stateForTs(ts *types.TipSet) (*state.StateTree, error) {
|
func (a *FullNodeAPI) stateForTs(ts *types.TipSet) (*state.StateTree, error) {
|
||||||
@ -479,7 +480,10 @@ func (a *FullNodeAPI) PaychCreate(ctx context.Context, from, to address.Address,
|
|||||||
return address.Undef, err
|
return address.Undef, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: track this somewhere?
|
if err := a.PaychMgr.TrackOutboundChannel(ctx, paychaddr); err != nil {
|
||||||
|
return address.Undef, err
|
||||||
|
}
|
||||||
|
|
||||||
return paychaddr, nil
|
return paychaddr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -491,15 +495,15 @@ func (a *FullNodeAPI) PaychStatus(ctx context.Context, pch address.Address) (*ap
|
|||||||
panic("nyi")
|
panic("nyi")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *FullNodeAPI) PaychClose(ctx context.Context, addr address.Address) error {
|
func (a *FullNodeAPI) PaychClose(ctx context.Context, addr address.Address) (cid.Cid, error) {
|
||||||
ci, err := a.PaychMgr.GetChannelInfo(addr)
|
ci, err := a.PaychMgr.GetChannelInfo(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return cid.Undef, err
|
||||||
}
|
}
|
||||||
|
|
||||||
nonce, err := a.MpoolGetNonce(ctx, ci.ControlAddr)
|
nonce, err := a.MpoolGetNonce(ctx, ci.ControlAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return cid.Undef, err
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := &types.Message{
|
msg := &types.Message{
|
||||||
@ -513,23 +517,16 @@ func (a *FullNodeAPI) PaychClose(ctx context.Context, addr address.Address) erro
|
|||||||
GasPrice: types.NewInt(0),
|
GasPrice: types.NewInt(0),
|
||||||
}
|
}
|
||||||
|
|
||||||
b, err := msg.Serialize()
|
smsg, err := a.WalletSignMessage(ctx, ci.ControlAddr, msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return cid.Undef, err
|
||||||
}
|
}
|
||||||
|
|
||||||
sig, err := a.WalletSign(ctx, ci.ControlAddr, b)
|
if err := a.MpoolPush(ctx, smsg); err != nil {
|
||||||
if err != nil {
|
return cid.Undef, err
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
smsg := &types.SignedMessage{
|
return smsg.Cid(), nil
|
||||||
Message: *msg,
|
|
||||||
Signature: *sig,
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: should this block and wait?
|
|
||||||
return a.MpoolPush(ctx, smsg)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *FullNodeAPI) PaychVoucherCheckValid(ctx context.Context, ch address.Address, sv *types.SignedVoucher) error {
|
func (a *FullNodeAPI) PaychVoucherCheckValid(ctx context.Context, ch address.Address, sv *types.SignedVoucher) error {
|
||||||
@ -591,4 +588,50 @@ func (a *FullNodeAPI) PaychVoucherList(ctx context.Context, pch address.Address)
|
|||||||
return a.PaychMgr.ListVouchers(ctx, pch)
|
return a.PaychMgr.ListVouchers(ctx, pch)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *FullNodeAPI) PaychVoucherSubmit(ctx context.Context, ch address.Address, sv *types.SignedVoucher) (cid.Cid, error) {
|
||||||
|
ci, err := a.PaychMgr.GetChannelInfo(ch)
|
||||||
|
if err != nil {
|
||||||
|
return cid.Undef, err
|
||||||
|
}
|
||||||
|
|
||||||
|
nonce, err := a.MpoolGetNonce(ctx, ci.ControlAddr)
|
||||||
|
if err != nil {
|
||||||
|
return cid.Undef, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if sv.Extra != nil || len(sv.SecretPreimage) > 0 {
|
||||||
|
return cid.Undef, fmt.Errorf("cant handle more advanced payment channel stuff yet")
|
||||||
|
}
|
||||||
|
|
||||||
|
enc, err := actors.SerializeParams(&actors.PCAUpdateChannelStateParams{
|
||||||
|
Sv: *sv,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return cid.Undef, err
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := &types.Message{
|
||||||
|
From: ci.ControlAddr,
|
||||||
|
To: ch,
|
||||||
|
Value: types.NewInt(0),
|
||||||
|
Nonce: nonce,
|
||||||
|
Method: actors.PCAMethods.UpdateChannelState,
|
||||||
|
Params: enc,
|
||||||
|
GasLimit: types.NewInt(100000),
|
||||||
|
GasPrice: types.NewInt(0),
|
||||||
|
}
|
||||||
|
|
||||||
|
smsg, err := a.WalletSignMessage(ctx, ci.ControlAddr, msg)
|
||||||
|
if err != nil {
|
||||||
|
return cid.Undef, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := a.MpoolPush(ctx, smsg); err != nil {
|
||||||
|
return cid.Undef, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: should we wait for it...?
|
||||||
|
return smsg.Cid(), nil
|
||||||
|
}
|
||||||
|
|
||||||
var _ api.FullNode = &FullNodeAPI{}
|
var _ api.FullNode = &FullNodeAPI{}
|
||||||
|
@ -4,12 +4,12 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-lotus/chain"
|
|
||||||
"github.com/filecoin-project/go-lotus/chain/actors"
|
"github.com/filecoin-project/go-lotus/chain/actors"
|
||||||
"github.com/filecoin-project/go-lotus/chain/address"
|
"github.com/filecoin-project/go-lotus/chain/address"
|
||||||
"github.com/filecoin-project/go-lotus/chain/state"
|
"github.com/filecoin-project/go-lotus/chain/state"
|
||||||
"github.com/filecoin-project/go-lotus/chain/store"
|
"github.com/filecoin-project/go-lotus/chain/store"
|
||||||
"github.com/filecoin-project/go-lotus/chain/types"
|
"github.com/filecoin-project/go-lotus/chain/types"
|
||||||
|
"github.com/filecoin-project/go-lotus/chain/vm"
|
||||||
|
|
||||||
hamt "github.com/ipfs/go-hamt-ipld"
|
hamt "github.com/ipfs/go-hamt-ipld"
|
||||||
)
|
)
|
||||||
@ -123,7 +123,7 @@ func (pm *Manager) CheckVoucherSpendable(ctx context.Context, ch address.Address
|
|||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
ret, err := chain.Call(ctx, pm.chain, &types.Message{
|
ret, err := vm.Call(ctx, pm.chain, &types.Message{
|
||||||
From: owner,
|
From: owner,
|
||||||
To: ch,
|
To: ch,
|
||||||
Method: actors.PCAMethods.UpdateChannelState,
|
Method: actors.PCAMethods.UpdateChannelState,
|
||||||
@ -166,7 +166,7 @@ func (pm *Manager) loadPaychState(ctx context.Context, ch address.Address) (*typ
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (pm *Manager) getPaychOwner(ctx context.Context, ch address.Address) (address.Address, error) {
|
func (pm *Manager) getPaychOwner(ctx context.Context, ch address.Address) (address.Address, error) {
|
||||||
ret, err := chain.Call(ctx, pm.chain, &types.Message{
|
ret, err := vm.Call(ctx, pm.chain, &types.Message{
|
||||||
From: ch,
|
From: ch,
|
||||||
To: ch,
|
To: ch,
|
||||||
Method: actors.PCAMethods.GetOwner,
|
Method: actors.PCAMethods.GetOwner,
|
||||||
@ -211,5 +211,5 @@ func (pm *Manager) NextNonceForLane(ctx context.Context, ch address.Address, lan
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return maxnonce, nil
|
return maxnonce + 1, nil
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package paych
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-lotus/chain/address"
|
"github.com/filecoin-project/go-lotus/chain/address"
|
||||||
"github.com/filecoin-project/go-lotus/chain/types"
|
"github.com/filecoin-project/go-lotus/chain/types"
|
||||||
@ -10,6 +11,7 @@ import (
|
|||||||
dsq "github.com/ipfs/go-datastore/query"
|
dsq "github.com/ipfs/go-datastore/query"
|
||||||
|
|
||||||
cbor "github.com/ipfs/go-ipld-cbor"
|
cbor "github.com/ipfs/go-ipld-cbor"
|
||||||
|
"golang.org/x/xerrors"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -95,11 +97,15 @@ func (ps *Store) ListChannels() ([]address.Address, error) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
addr, err := address.NewFromString(res.Key)
|
if res.Error != nil {
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addr, err := address.NewFromString(strings.TrimPrefix(res.Key, "/"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, xerrors.Errorf("failed reading paych key (%q) from datastore: %w", res.Key, err)
|
||||||
|
}
|
||||||
|
|
||||||
out = append(out, addr)
|
out = append(out, addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user