paych: Api to reuse open channels for new payments
This commit is contained in:
@@ -86,26 +86,14 @@ func (a *ClientAPI) ClientStartDeal(ctx context.Context, data cid.Cid, miner add
|
||||
total := types.BigMul(price, types.NewInt(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
|
||||
extra := &types.ModVerifyParams{
|
||||
Actor: miner,
|
||||
Method: actors.MAMethods.PaymentVerifyInclusion,
|
||||
Data: voucherData,
|
||||
}
|
||||
|
||||
head := a.Chain.GetHeaviestTipSet()
|
||||
|
||||
voucher := types.SignedVoucher{ // TODO: split into smaller payments
|
||||
TimeLock: head.Height() + blocksDuration,
|
||||
Extra: &types.ModVerifyParams{
|
||||
Actor: miner,
|
||||
Method: actors.MAMethods.PaymentVerifyInclusion,
|
||||
Data: voucherData,
|
||||
},
|
||||
Lane: 0, // TODO: some api to make this easy
|
||||
Amount: total,
|
||||
MinCloseHeight: head.Height() + blocksDuration, // TODO: some way to start this after initial piece inclusion by actor? Using actors.PieceInclVoucherData?
|
||||
}
|
||||
|
||||
sv, err := a.paychVoucherCreate(ctx, paych, voucher)
|
||||
payment, err := a.PaychNewPayment(ctx, self, miner, total, extra, head.Height()+blocksDuration, head.Height()+blocksDuration)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -115,10 +103,9 @@ func (a *ClientAPI) ClientStartDeal(ctx context.Context, data cid.Cid, miner add
|
||||
TotalPrice: total,
|
||||
Duration: blocksDuration,
|
||||
Payment: actors.PaymentInfo{
|
||||
PayChActor: paych,
|
||||
Payer: self,
|
||||
ChannelMessage: paychMsg,
|
||||
Vouchers: []*types.SignedVoucher{sv},
|
||||
PayChActor: payment.Channel,
|
||||
Payer: self,
|
||||
Vouchers: []*types.SignedVoucher{payment.Voucher},
|
||||
},
|
||||
MinerAddress: miner,
|
||||
ClientAddress: self,
|
||||
|
||||
+92
-33
@@ -26,19 +26,14 @@ type PaychAPI struct {
|
||||
}
|
||||
|
||||
func (a *PaychAPI) 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 *PaychAPI) 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, cid.Undef, aerr
|
||||
return address.Undef, aerr
|
||||
}
|
||||
|
||||
nonce, err := a.MpoolGetNonce(ctx, from)
|
||||
if err != nil {
|
||||
return address.Undef, cid.Undef, err
|
||||
return address.Undef, err
|
||||
}
|
||||
|
||||
enc, err := actors.SerializeParams(&actors.ExecParams{
|
||||
@@ -57,44 +52,108 @@ func (a *PaychAPI) paychCreate(ctx context.Context, from, to address.Address, am
|
||||
GasPrice: types.NewInt(0),
|
||||
}
|
||||
|
||||
ser, err := msg.Serialize()
|
||||
smsg, err := a.WalletSignMessage(ctx, from, msg)
|
||||
if err != nil {
|
||||
return address.Undef, cid.Undef, err
|
||||
}
|
||||
|
||||
sig, err := a.WalletSign(ctx, from, ser)
|
||||
if err != nil {
|
||||
return address.Undef, cid.Undef, err
|
||||
}
|
||||
|
||||
smsg := &types.SignedMessage{
|
||||
Message: *msg,
|
||||
Signature: *sig,
|
||||
return address.Address{}, err
|
||||
}
|
||||
|
||||
if err := a.MpoolPush(ctx, smsg); err != nil {
|
||||
return address.Undef, cid.Undef, err
|
||||
return address.Undef, err
|
||||
}
|
||||
|
||||
mwait, err := a.ChainWaitMsg(ctx, smsg.Cid())
|
||||
if err != nil {
|
||||
return address.Undef, cid.Undef, err
|
||||
return address.Undef, err
|
||||
}
|
||||
|
||||
if mwait.Receipt.ExitCode != 0 {
|
||||
return address.Undef, cid.Undef, fmt.Errorf("payment channel creation failed (exit code %d)", mwait.Receipt.ExitCode)
|
||||
return address.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, cid.Undef, err
|
||||
return address.Undef, err
|
||||
}
|
||||
|
||||
if err := a.PaychMgr.TrackOutboundChannel(ctx, paychaddr); err != nil {
|
||||
return address.Undef, cid.Undef, err
|
||||
return address.Undef, err
|
||||
}
|
||||
|
||||
return paychaddr, msg.Cid(), nil
|
||||
return paychaddr, 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) {
|
||||
ch, err := a.PaychMgr.OutboundChanTo(from, to)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
// already have chanel to the destination, add funds, and open a new lane
|
||||
// TODO: track free funds in channel
|
||||
|
||||
nonce, err := a.MpoolGetNonce(ctx, from)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
msg := &types.Message{
|
||||
To: ch,
|
||||
From: from,
|
||||
Value: amount,
|
||||
Nonce: nonce,
|
||||
Method: 0,
|
||||
GasLimit: types.NewInt(1000000),
|
||||
GasPrice: types.NewInt(0),
|
||||
}
|
||||
|
||||
smsg, err := a.WalletSignMessage(ctx, from, msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := a.MpoolPush(ctx, smsg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mwait, err := a.ChainWaitMsg(ctx, smsg.Cid())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if mwait.Receipt.ExitCode != 0 {
|
||||
return nil, fmt.Errorf("voucher channel creation failed: adding funds (exit code %d)", mwait.Receipt.ExitCode)
|
||||
}
|
||||
}
|
||||
|
||||
lane, err := a.PaychMgr.AllocateLane(ch)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sv, err := a.paychVoucherCreate(ctx, ch, types.SignedVoucher{
|
||||
Amount: amount,
|
||||
Lane: lane,
|
||||
|
||||
Extra: extra,
|
||||
TimeLock: tl,
|
||||
MinCloseHeight: minClose,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &api.PaymentInfo{
|
||||
Channel: ch,
|
||||
Voucher: sv,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a *PaychAPI) PaychList(ctx context.Context) ([]address.Address, error) {
|
||||
@@ -107,7 +166,7 @@ func (a *PaychAPI) PaychStatus(ctx context.Context, pch address.Address) (*api.P
|
||||
return nil, err
|
||||
}
|
||||
return &api.PaychStatus{
|
||||
ControlAddr: ci.ControlAddr,
|
||||
ControlAddr: ci.Control,
|
||||
Direction: api.PCHDir(ci.Direction),
|
||||
}, nil
|
||||
}
|
||||
@@ -118,14 +177,14 @@ func (a *PaychAPI) PaychClose(ctx context.Context, addr address.Address) (cid.Ci
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
nonce, err := a.MpoolGetNonce(ctx, ci.ControlAddr)
|
||||
nonce, err := a.MpoolGetNonce(ctx, ci.Control)
|
||||
if err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
msg := &types.Message{
|
||||
To: addr,
|
||||
From: ci.ControlAddr,
|
||||
From: ci.Control,
|
||||
Value: types.NewInt(0),
|
||||
Method: actors.PCAMethods.Close,
|
||||
Nonce: nonce,
|
||||
@@ -134,7 +193,7 @@ func (a *PaychAPI) PaychClose(ctx context.Context, addr address.Address) (cid.Ci
|
||||
GasPrice: types.NewInt(0),
|
||||
}
|
||||
|
||||
smsg, err := a.WalletSignMessage(ctx, ci.ControlAddr, msg)
|
||||
smsg, err := a.WalletSignMessage(ctx, ci.Control, msg)
|
||||
if err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
@@ -192,7 +251,7 @@ func (a *PaychAPI) paychVoucherCreate(ctx context.Context, pch address.Address,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sig, err := a.WalletSign(ctx, ci.ControlAddr, vb)
|
||||
sig, err := a.WalletSign(ctx, ci.Control, vb)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -226,7 +285,7 @@ func (a *PaychAPI) PaychVoucherSubmit(ctx context.Context, ch address.Address, s
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
nonce, err := a.MpoolGetNonce(ctx, ci.ControlAddr)
|
||||
nonce, err := a.MpoolGetNonce(ctx, ci.Control)
|
||||
if err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
@@ -243,7 +302,7 @@ func (a *PaychAPI) PaychVoucherSubmit(ctx context.Context, ch address.Address, s
|
||||
}
|
||||
|
||||
msg := &types.Message{
|
||||
From: ci.ControlAddr,
|
||||
From: ci.Control,
|
||||
To: ch,
|
||||
Value: types.NewInt(0),
|
||||
Nonce: nonce,
|
||||
@@ -253,7 +312,7 @@ func (a *PaychAPI) PaychVoucherSubmit(ctx context.Context, ch address.Address, s
|
||||
GasPrice: types.NewInt(0),
|
||||
}
|
||||
|
||||
smsg, err := a.WalletSignMessage(ctx, ci.ControlAddr, msg)
|
||||
smsg, err := a.WalletSignMessage(ctx, ci.Control, msg)
|
||||
if err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user