routing/payment_session: make RequestRoute take max amt, fee limit and
active shards In preparation for doing pathfinding for routes sending a value less than the total payment amount, we let the payment session take the max amount to send and the fee limit as arguments to RequestRoute.
This commit is contained in:
parent
f9eeb6b41f
commit
00903ef9f5
@ -122,7 +122,9 @@ type mockPaymentSession struct {
|
||||
|
||||
var _ PaymentSession = (*mockPaymentSession)(nil)
|
||||
|
||||
func (m *mockPaymentSession) RequestRoute(height uint32) (*route.Route, error) {
|
||||
func (m *mockPaymentSession) RequestRoute(_, _ lnwire.MilliSatoshi,
|
||||
_, height uint32) (*route.Route, error) {
|
||||
|
||||
if len(m.routes) == 0 {
|
||||
return nil, fmt.Errorf("no routes")
|
||||
}
|
||||
|
@ -31,6 +31,8 @@ func (e errNoRoute) Error() string {
|
||||
// needed to resume if from any point.
|
||||
type paymentLifecycle struct {
|
||||
router *ChannelRouter
|
||||
totalAmount lnwire.MilliSatoshi
|
||||
feeLimit lnwire.MilliSatoshi
|
||||
paymentHash lntypes.Hash
|
||||
paySession PaymentSession
|
||||
timeoutChan <-chan time.Time
|
||||
@ -267,7 +269,9 @@ func (p *paymentLifecycle) createNewPaymentAttempt() (lnwire.ShortChannelID,
|
||||
}
|
||||
|
||||
// Create a new payment attempt from the given payment session.
|
||||
rt, err := p.paySession.RequestRoute(uint32(p.currentHeight))
|
||||
rt, err := p.paySession.RequestRoute(
|
||||
p.totalAmount, p.feeLimit, 0, uint32(p.currentHeight),
|
||||
)
|
||||
if err != nil {
|
||||
log.Warnf("Failed to find route for payment %x: %v",
|
||||
p.paymentHash, err)
|
||||
|
@ -23,8 +23,14 @@ var (
|
||||
// information learned during the previous attempts.
|
||||
type PaymentSession interface {
|
||||
// RequestRoute returns the next route to attempt for routing the
|
||||
// specified HTLC payment to the target node.
|
||||
RequestRoute(height uint32) (*route.Route, error)
|
||||
// specified HTLC payment to the target node. The returned route should
|
||||
// carry at most maxAmt to the target node, and pay at most feeLimit in
|
||||
// fees. It can carry less if the payment is MPP. The activeShards
|
||||
// argument should be set to instruct the payment session about the
|
||||
// number of in flight HTLCS for the payment, such that it can choose
|
||||
// splitting strategy accordingly.
|
||||
RequestRoute(maxAmt, feeLimit lnwire.MilliSatoshi,
|
||||
activeShards, height uint32) (*route.Route, error)
|
||||
}
|
||||
|
||||
// paymentSession is used during an HTLC routings session to prune the local
|
||||
@ -59,7 +65,8 @@ type paymentSession struct {
|
||||
//
|
||||
// NOTE: This function is safe for concurrent access.
|
||||
// NOTE: Part of the PaymentSession interface.
|
||||
func (p *paymentSession) RequestRoute(height uint32) (*route.Route, error) {
|
||||
func (p *paymentSession) RequestRoute(maxAmt, feeLimit lnwire.MilliSatoshi,
|
||||
activeShards, height uint32) (*route.Route, error) {
|
||||
|
||||
switch {
|
||||
|
||||
@ -94,7 +101,7 @@ func (p *paymentSession) RequestRoute(height uint32) (*route.Route, error) {
|
||||
|
||||
restrictions := &RestrictParams{
|
||||
ProbabilitySource: ss.MissionControl.GetProbability,
|
||||
FeeLimit: p.payment.FeeLimit,
|
||||
FeeLimit: feeLimit,
|
||||
OutgoingChannelID: p.payment.OutgoingChannelID,
|
||||
LastHop: p.payment.LastHop,
|
||||
CltvLimit: cltvLimit,
|
||||
@ -124,7 +131,7 @@ func (p *paymentSession) RequestRoute(height uint32) (*route.Route, error) {
|
||||
},
|
||||
restrictions, &ss.PathFindingConfig,
|
||||
ss.SelfNode.PubKeyBytes, p.payment.Target,
|
||||
p.payment.Amount, finalHtlcExpiry,
|
||||
maxAmt, finalHtlcExpiry,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -136,7 +143,7 @@ func (p *paymentSession) RequestRoute(height uint32) (*route.Route, error) {
|
||||
route, err := newRoute(
|
||||
sourceVertex, path, height,
|
||||
finalHopParams{
|
||||
amt: p.payment.Amount,
|
||||
amt: maxAmt,
|
||||
cltvDelta: finalCltvDelta,
|
||||
records: p.payment.DestCustomRecords,
|
||||
paymentAddr: p.payment.PaymentAddr,
|
||||
|
@ -50,6 +50,8 @@ func TestRequestRoute(t *testing.T) {
|
||||
payment := &LightningPayment{
|
||||
CltvLimit: cltvLimit,
|
||||
FinalCLTVDelta: finalCltvDelta,
|
||||
Amount: 1000,
|
||||
FeeLimit: 1000,
|
||||
}
|
||||
|
||||
session := &paymentSession{
|
||||
@ -63,7 +65,9 @@ func TestRequestRoute(t *testing.T) {
|
||||
pathFinder: findPath,
|
||||
}
|
||||
|
||||
route, err := session.RequestRoute(height)
|
||||
route, err := session.RequestRoute(
|
||||
payment.Amount, payment.FeeLimit, 0, height,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -542,9 +542,11 @@ func (r *ChannelRouter) Start() error {
|
||||
|
||||
// We pass in a zero timeout value, to indicate we
|
||||
// don't need it to timeout. It will stop immediately
|
||||
// after the existing attempt has finished anyway.
|
||||
// after the existing attempt has finished anyway. We
|
||||
// also set a zero fee limit, as no more routes should
|
||||
// be tried.
|
||||
_, _, err := r.sendPayment(
|
||||
attempt,
|
||||
attempt, payment.Info.Value, 0,
|
||||
payment.Info.PaymentHash, 0, paySession,
|
||||
)
|
||||
if err != nil {
|
||||
@ -1644,7 +1646,7 @@ func (r *ChannelRouter) SendPayment(payment *LightningPayment) ([32]byte,
|
||||
// Since this is the first time this payment is being made, we pass nil
|
||||
// for the existing attempt.
|
||||
return r.sendPayment(
|
||||
nil, payment.PaymentHash,
|
||||
nil, payment.Amount, payment.FeeLimit, payment.PaymentHash,
|
||||
payment.PayAttemptTimeout, paySession,
|
||||
)
|
||||
}
|
||||
@ -1667,8 +1669,9 @@ func (r *ChannelRouter) SendPaymentAsync(payment *LightningPayment) error {
|
||||
spewPayment(payment))
|
||||
|
||||
_, _, err := r.sendPayment(
|
||||
nil, payment.PaymentHash,
|
||||
payment.PayAttemptTimeout, paySession,
|
||||
nil, payment.Amount, payment.FeeLimit,
|
||||
payment.PaymentHash, payment.PayAttemptTimeout,
|
||||
paySession,
|
||||
)
|
||||
if err != nil {
|
||||
log.Errorf("Payment with hash %x failed: %v",
|
||||
@ -1769,7 +1772,13 @@ func (r *ChannelRouter) SendToRoute(hash lntypes.Hash, route *route.Route) (
|
||||
// timeout. It is only a single attempt, so no more attempts will be
|
||||
// done anyway. Since this is the first time this payment is being
|
||||
// made, we pass nil for the existing attempt.
|
||||
preimage, _, err := r.sendPayment(nil, hash, 0, paySession)
|
||||
// We pass the route receiver amount as the total payment amount such
|
||||
// that the payment loop will request a route for this amount. As fee
|
||||
// limit we pass the route's total fees, since we already know this is
|
||||
// the route that is going to be used.
|
||||
preimage, _, err := r.sendPayment(
|
||||
nil, amt, route.TotalFees(), hash, 0, paySession,
|
||||
)
|
||||
if err != nil {
|
||||
// SendToRoute should return a structured error. In case the
|
||||
// provided route fails, payment lifecycle will return a
|
||||
@ -1807,7 +1816,7 @@ func (r *ChannelRouter) SendToRoute(hash lntypes.Hash, route *route.Route) (
|
||||
// the ControlTower.
|
||||
func (r *ChannelRouter) sendPayment(
|
||||
existingAttempt *channeldb.HTLCAttemptInfo,
|
||||
paymentHash lntypes.Hash,
|
||||
totalAmt, feeLimit lnwire.MilliSatoshi, paymentHash lntypes.Hash,
|
||||
timeout time.Duration,
|
||||
paySession PaymentSession) ([32]byte, *route.Route, error) {
|
||||
|
||||
@ -1822,6 +1831,8 @@ func (r *ChannelRouter) sendPayment(
|
||||
// can resume the payment from the current state.
|
||||
p := &paymentLifecycle{
|
||||
router: r,
|
||||
totalAmount: totalAmt,
|
||||
feeLimit: feeLimit,
|
||||
paymentHash: paymentHash,
|
||||
paySession: paySession,
|
||||
currentHeight: currentHeight,
|
||||
|
Loading…
Reference in New Issue
Block a user