mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-02-22 06:21:40 +01:00
channeldb+routing: add new interface method TerminalInfo
This commit adds a new interface method `TerminalInfo` and changes its implementation to return an `*HTLCAttempt` so it includes the route for a successful payment. Method `GetFailureReason` is now removed as its returned value can be found in the above method.
This commit is contained in:
parent
3c5c37b693
commit
da8f1c084a
7 changed files with 59 additions and 60 deletions
|
@ -219,10 +219,10 @@ func (m *MPPayment) Terminated() bool {
|
||||||
// TerminalInfo returns any HTLC settle info recorded. If no settle info is
|
// TerminalInfo returns any HTLC settle info recorded. If no settle info is
|
||||||
// recorded, any payment level failure will be returned. If neither a settle
|
// recorded, any payment level failure will be returned. If neither a settle
|
||||||
// nor a failure is recorded, both return values will be nil.
|
// nor a failure is recorded, both return values will be nil.
|
||||||
func (m *MPPayment) TerminalInfo() (*HTLCSettleInfo, *FailureReason) {
|
func (m *MPPayment) TerminalInfo() (*HTLCAttempt, *FailureReason) {
|
||||||
for _, h := range m.HTLCs {
|
for _, h := range m.HTLCs {
|
||||||
if h.Settle != nil {
|
if h.Settle != nil {
|
||||||
return h.Settle, nil
|
return &h, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -464,11 +464,6 @@ func (m *MPPayment) GetHTLCs() []HTLCAttempt {
|
||||||
return m.HTLCs
|
return m.HTLCs
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetFailureReason returns the failure reason.
|
|
||||||
func (m *MPPayment) GetFailureReason() *FailureReason {
|
|
||||||
return m.FailureReason
|
|
||||||
}
|
|
||||||
|
|
||||||
// AllowMoreAttempts is used to decide whether we can safely attempt more HTLCs
|
// AllowMoreAttempts is used to decide whether we can safely attempt more HTLCs
|
||||||
// for a given payment state. Return an error if the payment is in an
|
// for a given payment state. Return an error if the payment is in an
|
||||||
// unexpected state.
|
// unexpected state.
|
||||||
|
|
|
@ -31,13 +31,14 @@ type dbMPPayment interface {
|
||||||
// InFlightHTLCs returns all HTLCs that are in flight.
|
// InFlightHTLCs returns all HTLCs that are in flight.
|
||||||
InFlightHTLCs() []channeldb.HTLCAttempt
|
InFlightHTLCs() []channeldb.HTLCAttempt
|
||||||
|
|
||||||
// GetFailureReason returns the reason the payment failed.
|
|
||||||
GetFailureReason() *channeldb.FailureReason
|
|
||||||
|
|
||||||
// AllowMoreAttempts is used to decide whether we can safely attempt
|
// AllowMoreAttempts is used to decide whether we can safely attempt
|
||||||
// more HTLCs for a given payment state. Return an error if the payment
|
// more HTLCs for a given payment state. Return an error if the payment
|
||||||
// is in an unexpected state.
|
// is in an unexpected state.
|
||||||
AllowMoreAttempts() (bool, error)
|
AllowMoreAttempts() (bool, error)
|
||||||
|
|
||||||
|
// TerminalInfo returns the settled HTLC attempt or the payment's
|
||||||
|
// failure reason.
|
||||||
|
TerminalInfo() (*channeldb.HTLCAttempt, *channeldb.FailureReason)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ControlTower tracks all outgoing payments made, whose primary purpose is to
|
// ControlTower tracks all outgoing payments made, whose primary purpose is to
|
||||||
|
|
|
@ -134,8 +134,8 @@ func TestControlTowerSubscribeSuccess(t *testing.T) {
|
||||||
"subscriber %v failed, want %s, got %s", i,
|
"subscriber %v failed, want %s, got %s", i,
|
||||||
channeldb.StatusSucceeded, result.GetStatus())
|
channeldb.StatusSucceeded, result.GetStatus())
|
||||||
|
|
||||||
settle, _ := result.TerminalInfo()
|
attempt, _ := result.TerminalInfo()
|
||||||
if settle.Preimage != preimg {
|
if attempt.Settle.Preimage != preimg {
|
||||||
t.Fatal("unexpected preimage")
|
t.Fatal("unexpected preimage")
|
||||||
}
|
}
|
||||||
if len(result.HTLCs) != 1 {
|
if len(result.HTLCs) != 1 {
|
||||||
|
@ -264,9 +264,8 @@ func TestPaymentControlSubscribeAllSuccess(t *testing.T) {
|
||||||
)
|
)
|
||||||
|
|
||||||
settle1, _ := result1.TerminalInfo()
|
settle1, _ := result1.TerminalInfo()
|
||||||
require.Equal(
|
require.Equal(t, preimg1, settle1.Settle.Preimage,
|
||||||
t, preimg1, settle1.Preimage, "unexpected preimage payment 1",
|
"unexpected preimage payment 1")
|
||||||
)
|
|
||||||
|
|
||||||
require.Len(
|
require.Len(
|
||||||
t, result1.HTLCs, 1, "expect 1 htlc for payment 1, got %d",
|
t, result1.HTLCs, 1, "expect 1 htlc for payment 1, got %d",
|
||||||
|
@ -283,9 +282,8 @@ func TestPaymentControlSubscribeAllSuccess(t *testing.T) {
|
||||||
)
|
)
|
||||||
|
|
||||||
settle2, _ := result2.TerminalInfo()
|
settle2, _ := result2.TerminalInfo()
|
||||||
require.Equal(
|
require.Equal(t, preimg2, settle2.Settle.Preimage,
|
||||||
t, preimg2, settle2.Preimage, "unexpected preimage payment 2",
|
"unexpected preimage payment 2")
|
||||||
)
|
|
||||||
require.Len(
|
require.Len(
|
||||||
t, result2.HTLCs, 1, "expect 1 htlc for payment 2, got %d",
|
t, result2.HTLCs, 1, "expect 1 htlc for payment 2, got %d",
|
||||||
len(result2.HTLCs),
|
len(result2.HTLCs),
|
||||||
|
|
|
@ -828,22 +828,34 @@ func (m *mockMPPayment) InFlightHTLCs() []channeldb.HTLCAttempt {
|
||||||
return args.Get(0).([]channeldb.HTLCAttempt)
|
return args.Get(0).([]channeldb.HTLCAttempt)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockMPPayment) GetFailureReason() *channeldb.FailureReason {
|
|
||||||
args := m.Called()
|
|
||||||
|
|
||||||
reason := args.Get(0)
|
|
||||||
if reason == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return reason.(*channeldb.FailureReason)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mockMPPayment) AllowMoreAttempts() (bool, error) {
|
func (m *mockMPPayment) AllowMoreAttempts() (bool, error) {
|
||||||
args := m.Called()
|
args := m.Called()
|
||||||
return args.Bool(0), args.Error(1)
|
return args.Bool(0), args.Error(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *mockMPPayment) TerminalInfo() (*channeldb.HTLCAttempt,
|
||||||
|
*channeldb.FailureReason) {
|
||||||
|
|
||||||
|
args := m.Called()
|
||||||
|
|
||||||
|
var (
|
||||||
|
settleInfo *channeldb.HTLCAttempt
|
||||||
|
failureInfo *channeldb.FailureReason
|
||||||
|
)
|
||||||
|
|
||||||
|
settle := args.Get(0)
|
||||||
|
if settle != nil {
|
||||||
|
settleInfo = settle.(*channeldb.HTLCAttempt)
|
||||||
|
}
|
||||||
|
|
||||||
|
reason := args.Get(1)
|
||||||
|
if reason != nil {
|
||||||
|
failureInfo = reason.(*channeldb.FailureReason)
|
||||||
|
}
|
||||||
|
|
||||||
|
return settleInfo, failureInfo
|
||||||
|
}
|
||||||
|
|
||||||
type mockLink struct {
|
type mockLink struct {
|
||||||
htlcswitch.ChannelLink
|
htlcswitch.ChannelLink
|
||||||
bandwidth lnwire.MilliSatoshi
|
bandwidth lnwire.MilliSatoshi
|
||||||
|
|
|
@ -201,10 +201,10 @@ lifecycle:
|
||||||
ps := payment.GetState()
|
ps := payment.GetState()
|
||||||
remainingFees := p.calcFeeBudget(ps.FeesPaid)
|
remainingFees := p.calcFeeBudget(ps.FeesPaid)
|
||||||
|
|
||||||
log.Debugf("Payment %v in state terminate=%v, "+
|
log.Debugf("Payment %v: status=%v, active_shards=%v, "+
|
||||||
"active_shards=%v, rem_value=%v, fee_limit=%v",
|
"rem_value=%v, fee_limit=%v", p.identifier,
|
||||||
p.identifier, payment.Terminated(),
|
payment.GetStatus(), ps.NumAttemptsInFlight,
|
||||||
ps.NumAttemptsInFlight, ps.RemainingAmt, remainingFees)
|
ps.RemainingAmt, remainingFees)
|
||||||
|
|
||||||
// We now proceed our lifecycle with the following tasks in
|
// We now proceed our lifecycle with the following tasks in
|
||||||
// order,
|
// order,
|
||||||
|
@ -291,15 +291,13 @@ lifecycle:
|
||||||
"%v: %v", p.identifier, err)
|
"%v: %v", p.identifier, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the first successful shard and return the preimage and route.
|
htlc, failure := payment.TerminalInfo()
|
||||||
for _, a := range payment.GetHTLCs() {
|
if htlc != nil {
|
||||||
if a.Settle != nil {
|
return htlc.Settle.Preimage, &htlc.Route, nil
|
||||||
return a.Settle.Preimage, &a.Route, nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise return the payment failure reason.
|
// Otherwise return the payment failure reason.
|
||||||
return [32]byte{}, nil, *payment.GetFailureReason()
|
return [32]byte{}, nil, *failure
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkTimeout checks whether the payment has reached its timeout.
|
// checkTimeout checks whether the payment has reached its timeout.
|
||||||
|
|
|
@ -2532,7 +2532,8 @@ func (r *ChannelRouter) sendToRoute(htlcHash lntypes.Hash, rt *route.Route,
|
||||||
// Exit if the above error has caused the payment to be failed, we also
|
// Exit if the above error has caused the payment to be failed, we also
|
||||||
// return the error from sending attempt to mimic the old behavior of
|
// return the error from sending attempt to mimic the old behavior of
|
||||||
// this method.
|
// this method.
|
||||||
if payment.GetFailureReason() != nil {
|
_, failedReason := payment.TerminalInfo()
|
||||||
|
if failedReason != nil {
|
||||||
return result.attempt, result.err
|
return result.attempt, result.err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3482,7 +3482,7 @@ func TestSendMPPaymentSucceed(t *testing.T) {
|
||||||
payment := &mockMPPayment{}
|
payment := &mockMPPayment{}
|
||||||
payment.On("InFlightHTLCs").Return(htlcs).
|
payment.On("InFlightHTLCs").Return(htlcs).
|
||||||
On("GetState").Return(&channeldb.MPPaymentState{FeesPaid: 0}).
|
On("GetState").Return(&channeldb.MPPaymentState{FeesPaid: 0}).
|
||||||
On("Terminated").Return(false)
|
On("GetStatus").Return(channeldb.StatusInFlight)
|
||||||
controlTower.On("FetchPayment", identifier).Return(payment, nil).Once()
|
controlTower.On("FetchPayment", identifier).Return(payment, nil).Once()
|
||||||
|
|
||||||
// Mock FetchPayment to return the payment.
|
// Mock FetchPayment to return the payment.
|
||||||
|
@ -3518,9 +3518,6 @@ func TestSendMPPaymentSucceed(t *testing.T) {
|
||||||
controlTower.On("SettleAttempt",
|
controlTower.On("SettleAttempt",
|
||||||
identifier, mock.Anything, mock.Anything,
|
identifier, mock.Anything, mock.Anything,
|
||||||
).Return(&settledAttempt, nil).Run(func(args mock.Arguments) {
|
).Return(&settledAttempt, nil).Run(func(args mock.Arguments) {
|
||||||
payment.On("GetHTLCs").Return(
|
|
||||||
[]channeldb.HTLCAttempt{settledAttempt},
|
|
||||||
)
|
|
||||||
// We want to at least wait for one settlement.
|
// We want to at least wait for one settlement.
|
||||||
if numAttempts.Load() > 1 {
|
if numAttempts.Load() > 1 {
|
||||||
settled.Store(true)
|
settled.Store(true)
|
||||||
|
@ -3566,6 +3563,8 @@ func TestSendMPPaymentSucceed(t *testing.T) {
|
||||||
|
|
||||||
controlTower.On("DeleteFailedAttempts", identifier).Return(nil)
|
controlTower.On("DeleteFailedAttempts", identifier).Return(nil)
|
||||||
|
|
||||||
|
payment.On("TerminalInfo").Return(&settledAttempt, nil)
|
||||||
|
|
||||||
// Call the actual method SendPayment on router. This is place inside a
|
// Call the actual method SendPayment on router. This is place inside a
|
||||||
// goroutine so we can set a timeout for the whole test, in case
|
// goroutine so we can set a timeout for the whole test, in case
|
||||||
// anything goes wrong and the test never finishes.
|
// anything goes wrong and the test never finishes.
|
||||||
|
@ -3683,7 +3682,7 @@ func TestSendMPPaymentSucceedOnExtraShards(t *testing.T) {
|
||||||
payment := &mockMPPayment{}
|
payment := &mockMPPayment{}
|
||||||
payment.On("InFlightHTLCs").Return(htlcs).
|
payment.On("InFlightHTLCs").Return(htlcs).
|
||||||
On("GetState").Return(&channeldb.MPPaymentState{FeesPaid: 0}).
|
On("GetState").Return(&channeldb.MPPaymentState{FeesPaid: 0}).
|
||||||
On("Terminated").Return(false)
|
On("GetStatus").Return(channeldb.StatusInFlight)
|
||||||
controlTower.On("FetchPayment", identifier).Return(payment, nil).Once()
|
controlTower.On("FetchPayment", identifier).Return(payment, nil).Once()
|
||||||
|
|
||||||
// Mock FetchPayment to return the payment.
|
// Mock FetchPayment to return the payment.
|
||||||
|
@ -3787,12 +3786,6 @@ func TestSendMPPaymentSucceedOnExtraShards(t *testing.T) {
|
||||||
controlTower.On("SettleAttempt",
|
controlTower.On("SettleAttempt",
|
||||||
identifier, mock.Anything, mock.Anything,
|
identifier, mock.Anything, mock.Anything,
|
||||||
).Return(&settledAttempt, nil).Run(func(args mock.Arguments) {
|
).Return(&settledAttempt, nil).Run(func(args mock.Arguments) {
|
||||||
// Whenever this method is invoked, we will mock the payment's
|
|
||||||
// GetHTLCs() to return the settled htlc.
|
|
||||||
payment.On("GetHTLCs").Return(
|
|
||||||
[]channeldb.HTLCAttempt{settledAttempt},
|
|
||||||
)
|
|
||||||
|
|
||||||
if numAttempts.Load() > 1 {
|
if numAttempts.Load() > 1 {
|
||||||
settled.Store(true)
|
settled.Store(true)
|
||||||
}
|
}
|
||||||
|
@ -3800,6 +3793,8 @@ func TestSendMPPaymentSucceedOnExtraShards(t *testing.T) {
|
||||||
|
|
||||||
controlTower.On("DeleteFailedAttempts", identifier).Return(nil)
|
controlTower.On("DeleteFailedAttempts", identifier).Return(nil)
|
||||||
|
|
||||||
|
payment.On("TerminalInfo").Return(&settledAttempt, nil)
|
||||||
|
|
||||||
// Call the actual method SendPayment on router. This is place inside a
|
// Call the actual method SendPayment on router. This is place inside a
|
||||||
// goroutine so we can set a timeout for the whole test, in case
|
// goroutine so we can set a timeout for the whole test, in case
|
||||||
// anything goes wrong and the test never finishes.
|
// anything goes wrong and the test never finishes.
|
||||||
|
@ -3913,8 +3908,8 @@ func TestSendMPPaymentFailed(t *testing.T) {
|
||||||
// Make a mock MPPayment.
|
// Make a mock MPPayment.
|
||||||
payment := &mockMPPayment{}
|
payment := &mockMPPayment{}
|
||||||
payment.On("InFlightHTLCs").Return(htlcs).Once()
|
payment.On("InFlightHTLCs").Return(htlcs).Once()
|
||||||
payment.On("GetState").Return(&channeldb.MPPaymentState{})
|
payment.On("GetState").Return(&channeldb.MPPaymentState{}).
|
||||||
payment.On("Terminated").Return(false)
|
On("GetStatus").Return(channeldb.StatusInFlight)
|
||||||
controlTower.On("FetchPayment", identifier).Return(payment, nil).Once()
|
controlTower.On("FetchPayment", identifier).Return(payment, nil).Once()
|
||||||
|
|
||||||
// Mock the sequential FetchPayment to return the payment.
|
// Mock the sequential FetchPayment to return the payment.
|
||||||
|
@ -3935,7 +3930,6 @@ func TestSendMPPaymentFailed(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
payment.On("AllowMoreAttempts").Return(false, nil).
|
payment.On("AllowMoreAttempts").Return(false, nil).
|
||||||
On("GetHTLCs").Return(htlcs).Once().
|
|
||||||
On("NeedWaitAttempts").Return(false, nil).Once()
|
On("NeedWaitAttempts").Return(false, nil).Once()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -4011,12 +4005,12 @@ func TestSendMPPaymentFailed(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
// Mock the payment to return the failure reason.
|
// Mock the payment to return the failure reason.
|
||||||
payment.On("GetFailureReason").Return(&failureReason)
|
|
||||||
|
|
||||||
payer.On("SendHTLC",
|
payer.On("SendHTLC",
|
||||||
mock.Anything, mock.Anything, mock.Anything,
|
mock.Anything, mock.Anything, mock.Anything,
|
||||||
).Return(nil)
|
).Return(nil)
|
||||||
|
|
||||||
|
payment.On("TerminalInfo").Return(nil, &failureReason)
|
||||||
|
|
||||||
controlTower.On("DeleteFailedAttempts", identifier).Return(nil)
|
controlTower.On("DeleteFailedAttempts", identifier).Return(nil)
|
||||||
|
|
||||||
// Call the actual method SendPayment on router. This is place inside a
|
// Call the actual method SendPayment on router. This is place inside a
|
||||||
|
@ -4194,7 +4188,7 @@ func TestSendToRouteSkipTempErrSuccess(t *testing.T) {
|
||||||
controlTower.On("FetchPayment", payHash).Return(payment, nil).Once()
|
controlTower.On("FetchPayment", payHash).Return(payment, nil).Once()
|
||||||
|
|
||||||
// Mock the payment to return nil failrue reason.
|
// Mock the payment to return nil failrue reason.
|
||||||
payment.On("GetFailureReason").Return(nil)
|
payment.On("TerminalInfo").Return(nil, nil)
|
||||||
|
|
||||||
// Expect a successful send to route.
|
// Expect a successful send to route.
|
||||||
attempt, err := router.SendToRouteSkipTempErr(payHash, rt)
|
attempt, err := router.SendToRouteSkipTempErr(payHash, rt)
|
||||||
|
@ -4289,7 +4283,7 @@ func TestSendToRouteSkipTempErrTempFailure(t *testing.T) {
|
||||||
).Return(nil, nil)
|
).Return(nil, nil)
|
||||||
|
|
||||||
// Mock the payment to return nil failrue reason.
|
// Mock the payment to return nil failrue reason.
|
||||||
payment.On("GetFailureReason").Return(nil)
|
payment.On("TerminalInfo").Return(nil, nil)
|
||||||
|
|
||||||
// Expect a failed send to route.
|
// Expect a failed send to route.
|
||||||
attempt, err := router.SendToRouteSkipTempErr(payHash, rt)
|
attempt, err := router.SendToRouteSkipTempErr(payHash, rt)
|
||||||
|
@ -4374,7 +4368,7 @@ func TestSendToRouteSkipTempErrPermanentFailure(t *testing.T) {
|
||||||
controlTower.On("FetchPayment", payHash).Return(payment, nil).Once()
|
controlTower.On("FetchPayment", payHash).Return(payment, nil).Once()
|
||||||
|
|
||||||
// Mock the payment to return a failrue reason.
|
// Mock the payment to return a failrue reason.
|
||||||
payment.On("GetFailureReason").Return(&failureReason)
|
payment.On("TerminalInfo").Return(nil, &failureReason)
|
||||||
|
|
||||||
// Expect a failed send to route.
|
// Expect a failed send to route.
|
||||||
attempt, err := router.SendToRouteSkipTempErr(payHash, rt)
|
attempt, err := router.SendToRouteSkipTempErr(payHash, rt)
|
||||||
|
@ -4452,7 +4446,7 @@ func TestSendToRouteTempFailure(t *testing.T) {
|
||||||
controlTower.On("FetchPayment", payHash).Return(payment, nil).Once()
|
controlTower.On("FetchPayment", payHash).Return(payment, nil).Once()
|
||||||
|
|
||||||
// Mock the payment to return nil failrue reason.
|
// Mock the payment to return nil failrue reason.
|
||||||
payment.On("GetFailureReason").Return(nil)
|
payment.On("TerminalInfo").Return(nil, nil)
|
||||||
|
|
||||||
// Return a nil reason to mock a temporary failure.
|
// Return a nil reason to mock a temporary failure.
|
||||||
missionControl.On("ReportPaymentFail",
|
missionControl.On("ReportPaymentFail",
|
||||||
|
|
Loading…
Add table
Reference in a new issue