deals: Wait for channel messagi in handler

This commit is contained in:
Łukasz Magiera 2019-09-13 16:11:40 +02:00
parent c121d9b8af
commit 6a31ff2f2e
10 changed files with 53 additions and 30 deletions

View File

@ -94,7 +94,6 @@ dist-clean:
.PHONY: dist-clean
type-gen:
rm -f ./chain/types/cbor_gen.go
go run ./gen/main.go
print-%:

View File

@ -107,7 +107,7 @@ type FullNode interface {
StateGetActor(ctx context.Context, actor address.Address, ts *types.TipSet) (*types.Actor, error)
StateReadState(ctx context.Context, act *types.Actor, ts *types.TipSet) (*ActorState, error)
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) (*ChannelInfo, error)
PaychList(context.Context) ([]address.Address, error)
PaychStatus(context.Context, address.Address) (*PaychStatus, error)
PaychClose(context.Context, address.Address) (cid.Cid, error)
@ -208,9 +208,15 @@ type PaychStatus struct {
Direction PCHDir
}
type ChannelInfo struct {
Channel address.Address
ChannelMessage cid.Cid
}
type PaymentInfo struct {
Channel address.Address
Voucher *types.SignedVoucher
Channel address.Address
ChannelMessage *cid.Cid
Voucher *types.SignedVoucher
}
type MinerPower struct {

View File

@ -81,7 +81,7 @@ type FullNodeStruct struct {
StateGetActor func(context.Context, address.Address, *types.TipSet) (*types.Actor, error) `perm:"read"`
StateReadState func(context.Context, *types.Actor, *types.TipSet) (*ActorState, error) `perm:"read"`
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) (*ChannelInfo, error) `perm:"sign"`
PaychList func(context.Context) ([]address.Address, error) `perm:"read"`
PaychStatus func(context.Context, address.Address) (*PaychStatus, error) `perm:"read"`
PaychClose func(context.Context, address.Address) (cid.Cid, error) `perm:"sign"`
@ -294,7 +294,7 @@ func (c *FullNodeStruct) StateReadState(ctx context.Context, act *types.Actor, t
return c.Internal.StateReadState(ctx, act, ts)
}
func (c *FullNodeStruct) PaychCreate(ctx context.Context, from, to address.Address, amt types.BigInt) (address.Address, error) {
func (c *FullNodeStruct) PaychCreate(ctx context.Context, from, to address.Address, amt types.BigInt) (*ChannelInfo, error) {
return c.Internal.PaychCreate(ctx, from, to, amt)
}

View File

@ -4,6 +4,8 @@ import (
"bytes"
"fmt"
"github.com/ipfs/go-cid"
"github.com/filecoin-project/go-lotus/build"
"github.com/filecoin-project/go-lotus/chain/actors/aerrors"
"github.com/filecoin-project/go-lotus/chain/address"
@ -13,9 +15,9 @@ import (
type PaymentChannelActor struct{}
type PaymentInfo struct {
PayChActor address.Address
Payer address.Address
// TODO: update spec to not include channel msg
PayChActor address.Address
Payer address.Address
ChannelMessage *cid.Cid
Vouchers []*types.SignedVoucher
}

View File

@ -2195,7 +2195,7 @@ func (t *PaymentInfo) MarshalCBOR(w io.Writer) error {
}
// t.t.ChannelMessage (cid.Cid)
if err := cbg.WriteCid(w, t.ChannelMessage); err != nil {
if err := cbg.WriteCid(w, *t.ChannelMessage); err != nil {
return xerrors.Errorf("failed to write cid field t.ChannelMessage: %w", err)
}
@ -2251,7 +2251,7 @@ func (t *PaymentInfo) UnmarshalCBOR(r io.Reader) error {
if err != nil {
return xerrors.Errorf("failed to read cid field t.ChannelMessage: %w", err)
}
t.ChannelMessage = c
t.ChannelMessage = &c
}
// t.t.Vouchers ([]*types.SignedVoucher)

View File

@ -107,6 +107,11 @@ func (h *Handler) accept(ctx context.Context, deal MinerDeal) (func(*MinerDeal),
return nil, xerrors.Errorf("deal proposal with unsupported serialization: %s", deal.Proposal.SerializationMode)
}
if deal.Proposal.Payment.ChannelMessage != nil {
log.Info("waiting for channel message to appear on chain")
h.full.ChainWaitMsg(ctx, *deal.Proposal.Payment.ChannelMessage)
}
if err := h.validateVouchers(ctx, deal); err != nil {
return nil, err
}

View File

@ -48,12 +48,12 @@ var paychCreateCmd = &cli.Command{
ctx := ReqContext(cctx)
addr, err := api.PaychCreate(ctx, from, to, amt)
info, err := api.PaychCreate(ctx, from, to, amt)
if err != nil {
return err
}
fmt.Println(addr.String())
fmt.Println(info.Channel.String())
return nil
},
}

View File

@ -50,6 +50,8 @@ func (a *ChainAPI) ChainGetRandomness(ctx context.Context, pts *types.TipSet, ti
}
func (a *ChainAPI) ChainWaitMsg(ctx context.Context, msg cid.Cid) (*api.MsgWait, error) {
// TODO: consider using event system for this, expose confidence
blkcid, recpt, err := a.Chain.WaitForMessage(ctx, msg)
if err != nil {
return nil, err

View File

@ -103,9 +103,10 @@ func (a *ClientAPI) ClientStartDeal(ctx context.Context, data cid.Cid, miner add
TotalPrice: total,
Duration: blocksDuration,
Payment: actors.PaymentInfo{
PayChActor: payment.Channel,
Payer: self,
Vouchers: []*types.SignedVoucher{payment.Voucher},
PayChActor: payment.Channel,
Payer: self,
ChannelMessage: payment.ChannelMessage,
Vouchers: []*types.SignedVoucher{payment.Voucher},
},
MinerAddress: miner,
ClientAddress: self,

View File

@ -25,15 +25,15 @@ type PaychAPI struct {
PaychMgr *paych.Manager
}
func (a *PaychAPI) PaychCreate(ctx context.Context, from, to address.Address, amt types.BigInt) (address.Address, error) {
func (a *PaychAPI) PaychCreate(ctx context.Context, from, to address.Address, amt types.BigInt) (*api.ChannelInfo, error) {
params, aerr := actors.SerializeParams(&actors.PCAConstructorParams{To: to})
if aerr != nil {
return address.Undef, aerr
return nil, aerr
}
nonce, err := a.MpoolGetNonce(ctx, from)
if err != nil {
return address.Undef, err
return nil, err
}
enc, err := actors.SerializeParams(&actors.ExecParams{
@ -54,32 +54,36 @@ func (a *PaychAPI) PaychCreate(ctx context.Context, from, to address.Address, am
smsg, err := a.WalletSignMessage(ctx, from, msg)
if err != nil {
return address.Address{}, err
return nil, err
}
if err := a.MpoolPush(ctx, smsg); err != nil {
return address.Undef, err
return nil, err
}
mwait, err := a.ChainWaitMsg(ctx, smsg.Cid())
mcid := smsg.Cid()
mwait, err := a.ChainWaitMsg(ctx, mcid)
if err != nil {
return address.Undef, err
return nil, err
}
if mwait.Receipt.ExitCode != 0 {
return address.Undef, fmt.Errorf("payment channel creation failed (exit code %d)", mwait.Receipt.ExitCode)
return nil, fmt.Errorf("payment channel creation failed (exit code %d)", mwait.Receipt.ExitCode)
}
paychaddr, err := address.NewFromBytes(mwait.Receipt.Return)
if err != nil {
return address.Undef, err
return nil, err
}
if err := a.PaychMgr.TrackOutboundChannel(ctx, paychaddr); err != nil {
return address.Undef, err
return nil, err
}
return paychaddr, nil
return &api.ChannelInfo{
Channel: paychaddr,
ChannelMessage: mcid,
}, nil
}
func (a *PaychAPI) PaychNewPayment(ctx context.Context, from, to address.Address, amount types.BigInt, extra *types.ModVerifyParams, tl uint64, minClose uint64) (*api.PaymentInfo, error) {
@ -87,14 +91,17 @@ func (a *PaychAPI) PaychNewPayment(ctx context.Context, from, to address.Address
if err != nil {
return nil, err
}
var chMsg *cid.Cid
if ch == address.Undef {
// don't have matching channel, open new
// TODO: this should be more atomic
ch, err = a.PaychCreate(ctx, from, to, amount)
chInfo, err := a.PaychCreate(ctx, from, to, amount)
if err != nil {
return nil, err
}
ch = chInfo.Channel
chMsg = &chInfo.ChannelMessage
} else {
// already have chanel to the destination, add funds, and open a new lane
// TODO: track free funds in channel
@ -151,8 +158,9 @@ func (a *PaychAPI) PaychNewPayment(ctx context.Context, from, to address.Address
}
return &api.PaymentInfo{
Channel: ch,
Voucher: sv,
Channel: ch,
ChannelMessage: chMsg,
Voucher: sv,
}, nil
}