deals: setup payment channel for deals

This commit is contained in:
Łukasz Magiera 2019-08-15 02:28:52 +02:00
parent 1ed701db18
commit 4c5ffb185e
2 changed files with 68 additions and 29 deletions

View File

@ -183,43 +183,49 @@ func (c *Client) waitAccept(s inet.Stream, proposal StorageDealProposal, minerID
}, nil }, nil
} }
func (c *Client) Start(ctx context.Context, data cid.Cid, totalPrice types.BigInt, from address.Address, miner address.Address, minerID peer.ID, blocksDuration uint64) (cid.Cid, error) { type ClientDealProposal struct {
commP, size, err := c.commP(ctx, data) Data cid.Cid
TotalPrice types.BigInt
Duration uint64
Payment actors.PaymentInfo
MinerAddress address.Address
ClientAddress address.Address
MinerID peer.ID
}
func (c *Client) Start(ctx context.Context, p ClientDealProposal) (cid.Cid, error) {
commP, size, err := c.commP(ctx, p.Data)
if err != nil { if err != nil {
return cid.Undef, err return cid.Undef, err
} }
dummyCid, _ := cid.Parse("bafkqaaa")
// TODO: use data // TODO: use data
proposal := StorageDealProposal{ proposal := StorageDealProposal{
PieceRef: data.String(), PieceRef: p.Data.String(),
SerializationMode: SerializationUnixFs, SerializationMode: SerializationUnixFs,
CommP: commP[:], CommP: commP[:],
Size: uint64(size), Size: uint64(size),
TotalPrice: totalPrice, TotalPrice: p.TotalPrice,
Duration: blocksDuration, Duration: p.Duration,
Payment: actors.PaymentInfo{ Payment: p.Payment,
PayChActor: address.Address{}, MinerAddress: p.MinerAddress,
Payer: address.Address{}, ClientAddress: p.ClientAddress,
ChannelMessage: dummyCid,
Vouchers: nil,
},
MinerAddress: miner,
ClientAddress: from,
} }
s, err := c.h.NewStream(ctx, minerID, ProtocolID) s, err := c.h.NewStream(ctx, p.MinerID, ProtocolID)
if err != nil { if err != nil {
return cid.Undef, err return cid.Undef, err
} }
defer s.Reset() // TODO: handle other updates defer s.Reset() // TODO: handle other updates
if err := c.sendProposal(s, proposal, from); err != nil { if err := c.sendProposal(s, proposal, p.ClientAddress); err != nil {
return cid.Undef, err return cid.Undef, err
} }
deal, err := c.waitAccept(s, proposal, minerID) deal, err := c.waitAccept(s, proposal, p.MinerID)
if err != nil { if err != nil {
return cid.Undef, err return cid.Undef, err
} }

View File

@ -47,11 +47,13 @@ type FullNodeAPI struct {
} }
func (a *FullNodeAPI) ClientStartDeal(ctx context.Context, data cid.Cid, miner address.Address, price types.BigInt, blocksDuration uint64) (*cid.Cid, error) { func (a *FullNodeAPI) ClientStartDeal(ctx context.Context, data cid.Cid, miner address.Address, price types.BigInt, blocksDuration uint64) (*cid.Cid, error) {
// TODO: make this a param
self, err := a.WalletDefaultAddress(ctx) self, err := a.WalletDefaultAddress(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// get miner peerID
msg := &types.Message{ msg := &types.Message{
To: miner, To: miner,
From: miner, From: miner,
@ -67,8 +69,35 @@ func (a *FullNodeAPI) ClientStartDeal(ctx context.Context, data cid.Cid, miner a
return nil, err return nil, err
} }
// setup payments
total := types.BigMul(price, types.NewInt(blocksDuration)) total := types.BigMul(price, types.NewInt(blocksDuration))
c, err := a.DealClient.Start(ctx, data, total, self, miner, pid, blocksDuration)
// TODO: at least ping the miner before creating paych / locking the money
paych, paychMsg, err := a.paychCreate(ctx, self, miner, total)
if err != nil {
return nil, err
}
sv, err := a.PaychVoucherCreate(ctx, paych, total, 0)
if err != nil {
return nil, err
}
proposal := deals.ClientDealProposal{
Data: data,
TotalPrice: total,
Duration: blocksDuration,
Payment: actors.PaymentInfo{
PayChActor: paych,
Payer: self,
ChannelMessage: paychMsg,
Vouchers: []types.SignedVoucher{*sv},
},
MinerAddress: miner,
ClientAddress: self,
MinerID: pid,
}
c, err := a.DealClient.Start(ctx, proposal)
return &c, err return &c, err
} }
@ -420,15 +449,19 @@ func (a *FullNodeAPI) StateMinerProvingSet(ctx context.Context, addr address.Add
} }
func (a *FullNodeAPI) PaychCreate(ctx context.Context, from, to address.Address, amt types.BigInt) (address.Address, error) { func (a *FullNodeAPI) PaychCreate(ctx context.Context, from, to address.Address, amt types.BigInt) (address.Address, error) {
act, _, err := a.paychCreate(ctx, from, to, amt)
return act, err
}
func (a *FullNodeAPI) paychCreate(ctx context.Context, from, to address.Address, amt types.BigInt) (address.Address, cid.Cid, 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 address.Undef, cid.Undef, aerr
} }
nonce, err := a.MpoolGetNonce(ctx, from) nonce, err := a.MpoolGetNonce(ctx, from)
if err != nil { if err != nil {
return address.Undef, err return address.Undef, cid.Undef, err
} }
enc, err := actors.SerializeParams(&actors.ExecParams{ enc, err := actors.SerializeParams(&actors.ExecParams{
@ -449,12 +482,12 @@ func (a *FullNodeAPI) PaychCreate(ctx context.Context, from, to address.Address,
ser, err := msg.Serialize() ser, err := msg.Serialize()
if err != nil { if err != nil {
return address.Undef, err return address.Undef, cid.Undef, err
} }
sig, err := a.WalletSign(ctx, from, ser) sig, err := a.WalletSign(ctx, from, ser)
if err != nil { if err != nil {
return address.Undef, err return address.Undef, cid.Undef, err
} }
smsg := &types.SignedMessage{ smsg := &types.SignedMessage{
@ -463,28 +496,28 @@ func (a *FullNodeAPI) PaychCreate(ctx context.Context, from, to address.Address,
} }
if err := a.MpoolPush(ctx, smsg); err != nil { if err := a.MpoolPush(ctx, smsg); err != nil {
return address.Undef, err return address.Undef, cid.Undef, err
} }
mwait, err := a.ChainWaitMsg(ctx, smsg.Cid()) mwait, err := a.ChainWaitMsg(ctx, smsg.Cid())
if err != nil { if err != nil {
return address.Undef, err return address.Undef, cid.Undef, 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 address.Undef, cid.Undef, 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 address.Undef, cid.Undef, err
} }
if err := a.PaychMgr.TrackOutboundChannel(ctx, paychaddr); err != nil { if err := a.PaychMgr.TrackOutboundChannel(ctx, paychaddr); err != nil {
return address.Undef, err return address.Undef, cid.Undef, err
} }
return paychaddr, nil return paychaddr, msg.Cid(), nil
} }
func (a *FullNodeAPI) PaychList(ctx context.Context) ([]address.Address, error) { func (a *FullNodeAPI) PaychList(ctx context.Context) ([]address.Address, error) {