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
}
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) {
commP, size, err := c.commP(ctx, data)
type ClientDealProposal struct {
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 {
return cid.Undef, err
}
dummyCid, _ := cid.Parse("bafkqaaa")
// TODO: use data
proposal := StorageDealProposal{
PieceRef: data.String(),
PieceRef: p.Data.String(),
SerializationMode: SerializationUnixFs,
CommP: commP[:],
Size: uint64(size),
TotalPrice: totalPrice,
Duration: blocksDuration,
Payment: actors.PaymentInfo{
PayChActor: address.Address{},
Payer: address.Address{},
ChannelMessage: dummyCid,
Vouchers: nil,
},
MinerAddress: miner,
ClientAddress: from,
TotalPrice: p.TotalPrice,
Duration: p.Duration,
Payment: p.Payment,
MinerAddress: p.MinerAddress,
ClientAddress: p.ClientAddress,
}
s, err := c.h.NewStream(ctx, minerID, ProtocolID)
s, err := c.h.NewStream(ctx, p.MinerID, ProtocolID)
if err != nil {
return cid.Undef, err
}
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
}
deal, err := c.waitAccept(s, proposal, minerID)
deal, err := c.waitAccept(s, proposal, p.MinerID)
if err != nil {
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) {
// TODO: make this a param
self, err := a.WalletDefaultAddress(ctx)
if err != nil {
return nil, err
}
// get miner peerID
msg := &types.Message{
To: miner,
From: miner,
@ -67,8 +69,35 @@ func (a *FullNodeAPI) ClientStartDeal(ctx context.Context, data cid.Cid, miner a
return nil, err
}
// setup payments
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
}
@ -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) {
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})
if aerr != nil {
return address.Undef, aerr
return address.Undef, cid.Undef, aerr
}
nonce, err := a.MpoolGetNonce(ctx, from)
if err != nil {
return address.Undef, err
return address.Undef, cid.Undef, err
}
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()
if err != nil {
return address.Undef, err
return address.Undef, cid.Undef, err
}
sig, err := a.WalletSign(ctx, from, ser)
if err != nil {
return address.Undef, err
return address.Undef, cid.Undef, err
}
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 {
return address.Undef, err
return address.Undef, cid.Undef, err
}
mwait, err := a.ChainWaitMsg(ctx, smsg.Cid())
if err != nil {
return address.Undef, err
return address.Undef, cid.Undef, err
}
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)
if err != nil {
return address.Undef, err
return address.Undef, cid.Undef, err
}
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) {