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 .PHONY: dist-clean
type-gen: type-gen:
rm -f ./chain/types/cbor_gen.go
go run ./gen/main.go go run ./gen/main.go
print-%: print-%:

View File

@ -107,7 +107,7 @@ type FullNode interface {
StateGetActor(ctx context.Context, actor address.Address, ts *types.TipSet) (*types.Actor, error) 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) 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) 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) (cid.Cid, error) PaychClose(context.Context, address.Address) (cid.Cid, error)
@ -208,9 +208,15 @@ type PaychStatus struct {
Direction PCHDir Direction PCHDir
} }
type ChannelInfo struct {
Channel address.Address
ChannelMessage cid.Cid
}
type PaymentInfo struct { type PaymentInfo struct {
Channel address.Address Channel address.Address
Voucher *types.SignedVoucher ChannelMessage *cid.Cid
Voucher *types.SignedVoucher
} }
type MinerPower struct { 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"` 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"` 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"` 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) (cid.Cid, error) `perm:"sign"` 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) 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) return c.Internal.PaychCreate(ctx, from, to, amt)
} }

View File

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

View File

@ -2195,7 +2195,7 @@ func (t *PaymentInfo) MarshalCBOR(w io.Writer) error {
} }
// t.t.ChannelMessage (cid.Cid) // 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) 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 { if err != nil {
return xerrors.Errorf("failed to read cid field t.ChannelMessage: %w", err) return xerrors.Errorf("failed to read cid field t.ChannelMessage: %w", err)
} }
t.ChannelMessage = c t.ChannelMessage = &c
} }
// t.t.Vouchers ([]*types.SignedVoucher) // 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) 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 { if err := h.validateVouchers(ctx, deal); err != nil {
return nil, err return nil, err
} }

View File

@ -48,12 +48,12 @@ var paychCreateCmd = &cli.Command{
ctx := ReqContext(cctx) ctx := ReqContext(cctx)
addr, err := api.PaychCreate(ctx, from, to, amt) info, err := api.PaychCreate(ctx, from, to, amt)
if err != nil { if err != nil {
return err return err
} }
fmt.Println(addr.String()) fmt.Println(info.Channel.String())
return nil 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) { 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) blkcid, recpt, err := a.Chain.WaitForMessage(ctx, msg)
if err != nil { if err != nil {
return nil, err return nil, err

View File

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

View File

@ -25,15 +25,15 @@ type PaychAPI struct {
PaychMgr *paych.Manager 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}) params, aerr := actors.SerializeParams(&actors.PCAConstructorParams{To: to})
if aerr != nil { if aerr != nil {
return address.Undef, aerr return nil, aerr
} }
nonce, err := a.MpoolGetNonce(ctx, from) nonce, err := a.MpoolGetNonce(ctx, from)
if err != nil { if err != nil {
return address.Undef, err return nil, err
} }
enc, err := actors.SerializeParams(&actors.ExecParams{ 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) smsg, err := a.WalletSignMessage(ctx, from, msg)
if err != nil { if err != nil {
return address.Address{}, err return nil, err
} }
if err := a.MpoolPush(ctx, smsg); err != nil { 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 { if err != nil {
return address.Undef, err return nil, err
} }
if mwait.Receipt.ExitCode != 0 { 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) paychaddr, err := address.NewFromBytes(mwait.Receipt.Return)
if err != nil { if err != nil {
return address.Undef, err return nil, err
} }
if err := a.PaychMgr.TrackOutboundChannel(ctx, paychaddr); err != nil { 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) { 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 { if err != nil {
return nil, err return nil, err
} }
var chMsg *cid.Cid
if ch == address.Undef { if ch == address.Undef {
// don't have matching channel, open new // don't have matching channel, open new
// TODO: this should be more atomic // 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 { if err != nil {
return nil, err return nil, err
} }
ch = chInfo.Channel
chMsg = &chInfo.ChannelMessage
} else { } else {
// already have chanel to the destination, add funds, and open a new lane // already have chanel to the destination, add funds, and open a new lane
// TODO: track free funds in channel // TODO: track free funds in channel
@ -151,8 +158,9 @@ func (a *PaychAPI) PaychNewPayment(ctx context.Context, from, to address.Address
} }
return &api.PaymentInfo{ return &api.PaymentInfo{
Channel: ch, Channel: ch,
Voucher: sv, ChannelMessage: chMsg,
Voucher: sv,
}, nil }, nil
} }