Merge pull request #7174 from yyforyongyu/prepare-refactor-payment
Prepare for refactoring payment lifecycle
This commit is contained in:
15 files changed
+164
-137
No files matched your search
@@ -43,7 +43,8 @@ var (
|
|||||||
|
|
||||||
// ErrPaymentTerminal is returned if we attempt to alter a payment that
|
// ErrPaymentTerminal is returned if we attempt to alter a payment that
|
||||||
// already has reached a terminal condition.
|
// already has reached a terminal condition.
|
||||||
ErrPaymentTerminal = errors.New("payment has reached terminal condition")
|
ErrPaymentTerminal = errors.New("payment has reached terminal " +
|
||||||
|
"condition")
|
||||||
|
|
||||||
// ErrAttemptAlreadySettled is returned if we try to alter an already
|
// ErrAttemptAlreadySettled is returned if we try to alter an already
|
||||||
// settled HTLC attempt.
|
// settled HTLC attempt.
|
||||||
@@ -77,7 +78,8 @@ var (
|
|||||||
|
|
||||||
// ErrMPPTotalAmountMismatch is returned if we try to register an MPP
|
// ErrMPPTotalAmountMismatch is returned if we try to register an MPP
|
||||||
// shard where the total amount doesn't match existing shards.
|
// shard where the total amount doesn't match existing shards.
|
||||||
ErrMPPTotalAmountMismatch = errors.New("mp payment total amount mismatch")
|
ErrMPPTotalAmountMismatch = errors.New("mp payment total amount " +
|
||||||
|
"mismatch")
|
||||||
|
|
||||||
// errNoAttemptInfo is returned when no attempt info is stored yet.
|
// errNoAttemptInfo is returned when no attempt info is stored yet.
|
||||||
errNoAttemptInfo = errors.New("unable to find attempt info for " +
|
errNoAttemptInfo = errors.New("unable to find attempt info for " +
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package channeldb
|
||||||
|
|
||||||
|
// PaymentStatus represent current status of payment.
|
||||||
|
type PaymentStatus byte
|
||||||
|
|
||||||
|
const (
|
||||||
|
// StatusUnknown is the status where a payment has never been initiated
|
||||||
|
// and hence is unknown.
|
||||||
|
StatusUnknown PaymentStatus = 0
|
||||||
|
|
||||||
|
// StatusInFlight is the status where a payment has been initiated, but
|
||||||
|
// a response has not been received.
|
||||||
|
StatusInFlight PaymentStatus = 1
|
||||||
|
|
||||||
|
// StatusSucceeded is the status where a payment has been initiated and
|
||||||
|
// the payment was completed successfully.
|
||||||
|
StatusSucceeded PaymentStatus = 2
|
||||||
|
|
||||||
|
// StatusFailed is the status where a payment has been initiated and a
|
||||||
|
// failure result has come back.
|
||||||
|
StatusFailed PaymentStatus = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
// String returns readable representation of payment status.
|
||||||
|
func (ps PaymentStatus) String() string {
|
||||||
|
switch ps {
|
||||||
|
case StatusUnknown:
|
||||||
|
return "Unknown"
|
||||||
|
|
||||||
|
case StatusInFlight:
|
||||||
|
return "In Flight"
|
||||||
|
|
||||||
|
case StatusSucceeded:
|
||||||
|
return "Succeeded"
|
||||||
|
|
||||||
|
case StatusFailed:
|
||||||
|
return "Failed"
|
||||||
|
|
||||||
|
default:
|
||||||
|
return "Unknown"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -175,43 +175,6 @@ func (r FailureReason) String() string {
|
|||||||
return "unknown"
|
return "unknown"
|
||||||
}
|
}
|
||||||
|
|
||||||
// PaymentStatus represent current status of payment
|
|
||||||
type PaymentStatus byte
|
|
||||||
|
|
||||||
const (
|
|
||||||
// StatusUnknown is the status where a payment has never been initiated
|
|
||||||
// and hence is unknown.
|
|
||||||
StatusUnknown PaymentStatus = 0
|
|
||||||
|
|
||||||
// StatusInFlight is the status where a payment has been initiated, but
|
|
||||||
// a response has not been received.
|
|
||||||
StatusInFlight PaymentStatus = 1
|
|
||||||
|
|
||||||
// StatusSucceeded is the status where a payment has been initiated and
|
|
||||||
// the payment was completed successfully.
|
|
||||||
StatusSucceeded PaymentStatus = 2
|
|
||||||
|
|
||||||
// StatusFailed is the status where a payment has been initiated and a
|
|
||||||
// failure result has come back.
|
|
||||||
StatusFailed PaymentStatus = 3
|
|
||||||
)
|
|
||||||
|
|
||||||
// String returns readable representation of payment status.
|
|
||||||
func (ps PaymentStatus) String() string {
|
|
||||||
switch ps {
|
|
||||||
case StatusUnknown:
|
|
||||||
return "Unknown"
|
|
||||||
case StatusInFlight:
|
|
||||||
return "In Flight"
|
|
||||||
case StatusSucceeded:
|
|
||||||
return "Succeeded"
|
|
||||||
case StatusFailed:
|
|
||||||
return "Failed"
|
|
||||||
default:
|
|
||||||
return "Unknown"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// PaymentCreationInfo is the information necessary to have ready when
|
// PaymentCreationInfo is the information necessary to have ready when
|
||||||
// initiating a payment, moving it into state InFlight.
|
// initiating a payment, moving it into state InFlight.
|
||||||
type PaymentCreationInfo struct {
|
type PaymentCreationInfo struct {
|
||||||
|
|||||||
@@ -225,6 +225,10 @@ certain large transactions](https://github.com/lightningnetwork/lnd/pull/7100).
|
|||||||
|
|
||||||
* [CI: update test coverage library
|
* [CI: update test coverage library
|
||||||
go-acc](https://github.com/lightningnetwork/lnd/pull/7221) v0.2.6 -> v0.2.8
|
go-acc](https://github.com/lightningnetwork/lnd/pull/7221) v0.2.6 -> v0.2.8
|
||||||
|
|
||||||
|
* Payment related code [has been
|
||||||
|
refactored](https://github.com/lightningnetwork/lnd/pull/7174) to allow the
|
||||||
|
usage of new payment statuses.
|
||||||
|
|
||||||
## Watchtowers
|
## Watchtowers
|
||||||
|
|
||||||
|
|||||||
@@ -1306,7 +1306,7 @@ func TestChannelLinkMultiHopUnknownPaymentHash(t *testing.T) {
|
|||||||
)
|
)
|
||||||
require.NoError(t, err, "unable to get send payment")
|
require.NoError(t, err, "unable to get send payment")
|
||||||
|
|
||||||
resultChan, err := n.aliceServer.htlcSwitch.GetPaymentResult(
|
resultChan, err := n.aliceServer.htlcSwitch.GetAttemptResult(
|
||||||
pid, htlc.PaymentHash, newMockDeobfuscator(),
|
pid, htlc.PaymentHash, newMockDeobfuscator(),
|
||||||
)
|
)
|
||||||
require.NoError(t, err, "unable to get payment result")
|
require.NoError(t, err, "unable to get payment result")
|
||||||
@@ -3979,7 +3979,7 @@ func TestChannelLinkAcceptDuplicatePayment(t *testing.T) {
|
|||||||
)
|
)
|
||||||
require.NoError(t, err, "unable to send payment to carol")
|
require.NoError(t, err, "unable to send payment to carol")
|
||||||
|
|
||||||
resultChan, err := n.aliceServer.htlcSwitch.GetPaymentResult(
|
resultChan, err := n.aliceServer.htlcSwitch.GetAttemptResult(
|
||||||
pid, htlc.PaymentHash, newMockDeobfuscator(),
|
pid, htlc.PaymentHash, newMockDeobfuscator(),
|
||||||
)
|
)
|
||||||
require.NoError(t, err, "unable to get payment result")
|
require.NoError(t, err, "unable to get payment result")
|
||||||
|
|||||||
@@ -427,16 +427,16 @@ func (s *Switch) ProcessContractResolution(msg contractcourt.ResolutionMsg) erro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPaymentResult returns the the result of the payment attempt with the
|
// GetAttemptResult returns the result of the payment attempt with the given
|
||||||
// given attemptID. The paymentHash should be set to the payment's overall
|
// attemptID. The paymentHash should be set to the payment's overall hash, or
|
||||||
// hash, or in case of AMP payments the payment's unique identifier.
|
// in case of AMP payments the payment's unique identifier.
|
||||||
//
|
//
|
||||||
// The method returns a channel where the payment result will be sent when
|
// The method returns a channel where the payment result will be sent when
|
||||||
// available, or an error is encountered during forwarding. When a result is
|
// available, or an error is encountered during forwarding. When a result is
|
||||||
// received on the channel, the HTLC is guaranteed to no longer be in flight.
|
// received on the channel, the HTLC is guaranteed to no longer be in flight.
|
||||||
// The switch shutting down is signaled by closing the channel. If the
|
// The switch shutting down is signaled by closing the channel. If the
|
||||||
// attemptID is unknown, ErrPaymentIDNotFound will be returned.
|
// attemptID is unknown, ErrPaymentIDNotFound will be returned.
|
||||||
func (s *Switch) GetPaymentResult(attemptID uint64, paymentHash lntypes.Hash,
|
func (s *Switch) GetAttemptResult(attemptID uint64, paymentHash lntypes.Hash,
|
||||||
deobfuscator ErrorDecrypter) (<-chan *PaymentResult, error) {
|
deobfuscator ErrorDecrypter) (<-chan *PaymentResult, error) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|||||||
+10
-10
@@ -2699,7 +2699,7 @@ func TestSwitchSendPayment(t *testing.T) {
|
|||||||
|
|
||||||
// First check that the switch will correctly respond that this payment
|
// First check that the switch will correctly respond that this payment
|
||||||
// ID is unknown.
|
// ID is unknown.
|
||||||
_, err = s.GetPaymentResult(
|
_, err = s.GetAttemptResult(
|
||||||
paymentID, rhash, newMockDeobfuscator(),
|
paymentID, rhash, newMockDeobfuscator(),
|
||||||
)
|
)
|
||||||
if err != ErrPaymentIDNotFound {
|
if err != ErrPaymentIDNotFound {
|
||||||
@@ -2717,7 +2717,7 @@ func TestSwitchSendPayment(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
resultChan, err := s.GetPaymentResult(
|
resultChan, err := s.GetAttemptResult(
|
||||||
paymentID, rhash, newMockDeobfuscator(),
|
paymentID, rhash, newMockDeobfuscator(),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -3072,11 +3072,11 @@ func TestUpdateFailMalformedHTLCErrorConversion(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestSwitchGetPaymentResult tests that the switch interacts as expected with
|
// TestSwitchGetAttemptResult tests that the switch interacts as expected with
|
||||||
// the circuit map and network result store when looking up the result of a
|
// the circuit map and network result store when looking up the result of a
|
||||||
// payment ID. This is important for not to lose results under concurrent
|
// payment ID. This is important for not to lose results under concurrent
|
||||||
// lookup and receiving results.
|
// lookup and receiving results.
|
||||||
func TestSwitchGetPaymentResult(t *testing.T) {
|
func TestSwitchGetAttemptResult(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
const paymentID = 123
|
const paymentID = 123
|
||||||
@@ -3100,7 +3100,7 @@ func TestSwitchGetPaymentResult(t *testing.T) {
|
|||||||
// added anything to the store yet, ErrPaymentIDNotFound should be
|
// added anything to the store yet, ErrPaymentIDNotFound should be
|
||||||
// returned.
|
// returned.
|
||||||
lookup <- nil
|
lookup <- nil
|
||||||
_, err = s.GetPaymentResult(
|
_, err = s.GetAttemptResult(
|
||||||
paymentID, lntypes.Hash{}, newMockDeobfuscator(),
|
paymentID, lntypes.Hash{}, newMockDeobfuscator(),
|
||||||
)
|
)
|
||||||
if err != ErrPaymentIDNotFound {
|
if err != ErrPaymentIDNotFound {
|
||||||
@@ -3110,7 +3110,7 @@ func TestSwitchGetPaymentResult(t *testing.T) {
|
|||||||
// Next let the lookup find the circuit in the circuit map. It should
|
// Next let the lookup find the circuit in the circuit map. It should
|
||||||
// subscribe to payment results, and return the result when available.
|
// subscribe to payment results, and return the result when available.
|
||||||
lookup <- &PaymentCircuit{}
|
lookup <- &PaymentCircuit{}
|
||||||
resultChan, err := s.GetPaymentResult(
|
resultChan, err := s.GetAttemptResult(
|
||||||
paymentID, lntypes.Hash{}, newMockDeobfuscator(),
|
paymentID, lntypes.Hash{}, newMockDeobfuscator(),
|
||||||
)
|
)
|
||||||
require.NoError(t, err, "unable to get payment result")
|
require.NoError(t, err, "unable to get payment result")
|
||||||
@@ -3151,7 +3151,7 @@ func TestSwitchGetPaymentResult(t *testing.T) {
|
|||||||
// in the circuit map, it should be immediately available from the
|
// in the circuit map, it should be immediately available from the
|
||||||
// store.
|
// store.
|
||||||
lookup <- nil
|
lookup <- nil
|
||||||
resultChan, err = s.GetPaymentResult(
|
resultChan, err = s.GetAttemptResult(
|
||||||
paymentID, lntypes.Hash{}, newMockDeobfuscator(),
|
paymentID, lntypes.Hash{}, newMockDeobfuscator(),
|
||||||
)
|
)
|
||||||
require.NoError(t, err, "unable to get payment result")
|
require.NoError(t, err, "unable to get payment result")
|
||||||
@@ -3257,7 +3257,7 @@ func TestInvalidFailure(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
resultChan, err := s.GetPaymentResult(
|
resultChan, err := s.GetAttemptResult(
|
||||||
paymentID, rhash, &deobfuscator,
|
paymentID, rhash, &deobfuscator,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -3283,7 +3283,7 @@ func TestInvalidFailure(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
resultChan, err = s.GetPaymentResult(
|
resultChan, err = s.GetAttemptResult(
|
||||||
paymentID, rhash, &deobfuscator,
|
paymentID, rhash, &deobfuscator,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -4415,7 +4415,7 @@ func TestSwitchDustForwarding(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
carolAttemptID++
|
carolAttemptID++
|
||||||
|
|
||||||
carolResultChan, err := n.carolServer.htlcSwitch.GetPaymentResult(
|
carolResultChan, err := n.carolServer.htlcSwitch.GetAttemptResult(
|
||||||
uint64(carolAttemptID-1), carolHash, newMockDeobfuscator(),
|
uint64(carolAttemptID-1), carolHash, newMockDeobfuscator(),
|
||||||
)
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|||||||
@@ -787,7 +787,7 @@ func preparePayment(sendingPeer, receivingPeer lnpeer.Peer,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
resultChan, err := sender.htlcSwitch.GetPaymentResult(
|
resultChan, err := sender.htlcSwitch.GetAttemptResult(
|
||||||
pid, hash, newMockDeobfuscator(),
|
pid, hash, newMockDeobfuscator(),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1345,7 +1345,7 @@ func (n *twoHopNetwork) makeHoldPayment(sendingPeer, receivingPeer lnpeer.Peer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
resultChan, err := sender.htlcSwitch.GetPaymentResult(
|
resultChan, err := sender.htlcSwitch.GetAttemptResult(
|
||||||
pid, rhash, newMockDeobfuscator(),
|
pid, rhash, newMockDeobfuscator(),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -46,13 +46,13 @@ type ControlTower interface {
|
|||||||
// hash.
|
// hash.
|
||||||
FetchPayment(paymentHash lntypes.Hash) (*channeldb.MPPayment, error)
|
FetchPayment(paymentHash lntypes.Hash) (*channeldb.MPPayment, error)
|
||||||
|
|
||||||
// Fail transitions a payment into the Failed state, and records the
|
// FailPayment transitions a payment into the Failed state, and records
|
||||||
// ultimate reason the payment failed. Note that this should only be
|
// the ultimate reason the payment failed. Note that this should only
|
||||||
// called when all active active attempts are already failed. After
|
// be called when all active attempts are already failed. After
|
||||||
// invoking this method, InitPayment should return nil on its next call
|
// invoking this method, InitPayment should return nil on its next call
|
||||||
// for this payment hash, allowing the user to make a subsequent
|
// for this payment hash, allowing the user to make a subsequent
|
||||||
// payment.
|
// payment.
|
||||||
Fail(lntypes.Hash, channeldb.FailureReason) error
|
FailPayment(lntypes.Hash, channeldb.FailureReason) error
|
||||||
|
|
||||||
// FetchInFlightPayments returns all payments with status InFlight.
|
// FetchInFlightPayments returns all payments with status InFlight.
|
||||||
FetchInFlightPayments() ([]*channeldb.MPPayment, error)
|
FetchInFlightPayments() ([]*channeldb.MPPayment, error)
|
||||||
@@ -229,11 +229,11 @@ func (p *controlTower) FetchPayment(paymentHash lntypes.Hash) (
|
|||||||
return p.db.FetchPayment(paymentHash)
|
return p.db.FetchPayment(paymentHash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fail transitions a payment into the Failed state, and records the reason the
|
// FailPayment transitions a payment into the Failed state, and records the
|
||||||
// payment failed. After invoking this method, InitPayment should return nil on
|
// reason the payment failed. After invoking this method, InitPayment should
|
||||||
// its next call for this payment hash, allowing the switch to make a
|
// return nil on its next call for this payment hash, allowing the switch to
|
||||||
// subsequent payment.
|
// make a subsequent payment.
|
||||||
func (p *controlTower) Fail(paymentHash lntypes.Hash,
|
func (p *controlTower) FailPayment(paymentHash lntypes.Hash,
|
||||||
reason channeldb.FailureReason) error {
|
reason channeldb.FailureReason) error {
|
||||||
|
|
||||||
p.paymentsMtx.Lock(paymentHash)
|
p.paymentsMtx.Lock(paymentHash)
|
||||||
|
|||||||
@@ -457,7 +457,10 @@ func testPaymentControlSubscribeFail(t *testing.T, registerAttempt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Mark the payment as failed.
|
// Mark the payment as failed.
|
||||||
if err := pControl.Fail(info.PaymentIdentifier, channeldb.FailureReasonTimeout); err != nil {
|
err = pControl.FailPayment(
|
||||||
|
info.PaymentIdentifier, channeldb.FailureReasonTimeout,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ func (m *mockPaymentAttemptDispatcherOld) SendHTLC(
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockPaymentAttemptDispatcherOld) GetPaymentResult(paymentID uint64,
|
func (m *mockPaymentAttemptDispatcherOld) GetAttemptResult(paymentID uint64,
|
||||||
_ lntypes.Hash, _ htlcswitch.ErrorDecrypter) (
|
_ lntypes.Hash, _ htlcswitch.ErrorDecrypter) (
|
||||||
<-chan *htlcswitch.PaymentResult, error) {
|
<-chan *htlcswitch.PaymentResult, error) {
|
||||||
|
|
||||||
@@ -205,7 +205,7 @@ func (m *mockPayerOld) SendHTLC(_ lnwire.ShortChannelID,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockPayerOld) GetPaymentResult(paymentID uint64, _ lntypes.Hash,
|
func (m *mockPayerOld) GetAttemptResult(paymentID uint64, _ lntypes.Hash,
|
||||||
_ htlcswitch.ErrorDecrypter) (<-chan *htlcswitch.PaymentResult, error) {
|
_ htlcswitch.ErrorDecrypter) (<-chan *htlcswitch.PaymentResult, error) {
|
||||||
|
|
||||||
select {
|
select {
|
||||||
@@ -469,7 +469,7 @@ func (m *mockControlTowerOld) FailAttempt(phash lntypes.Hash, pid uint64,
|
|||||||
return nil, fmt.Errorf("pid not found")
|
return nil, fmt.Errorf("pid not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockControlTowerOld) Fail(phash lntypes.Hash,
|
func (m *mockControlTowerOld) FailPayment(phash lntypes.Hash,
|
||||||
reason channeldb.FailureReason) error {
|
reason channeldb.FailureReason) error {
|
||||||
|
|
||||||
m.Lock()
|
m.Lock()
|
||||||
@@ -578,7 +578,7 @@ func (m *mockPaymentAttemptDispatcher) SendHTLC(firstHop lnwire.ShortChannelID,
|
|||||||
return args.Error(0)
|
return args.Error(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockPaymentAttemptDispatcher) GetPaymentResult(attemptID uint64,
|
func (m *mockPaymentAttemptDispatcher) GetAttemptResult(attemptID uint64,
|
||||||
paymentHash lntypes.Hash, deobfuscator htlcswitch.ErrorDecrypter) (
|
paymentHash lntypes.Hash, deobfuscator htlcswitch.ErrorDecrypter) (
|
||||||
<-chan *htlcswitch.PaymentResult, error) {
|
<-chan *htlcswitch.PaymentResult, error) {
|
||||||
|
|
||||||
@@ -733,7 +733,7 @@ func (m *mockControlTower) FailAttempt(phash lntypes.Hash, pid uint64,
|
|||||||
return args.Get(0).(*channeldb.HTLCAttempt), args.Error(1)
|
return args.Get(0).(*channeldb.HTLCAttempt), args.Error(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockControlTower) Fail(phash lntypes.Hash,
|
func (m *mockControlTower) FailPayment(phash lntypes.Hash,
|
||||||
reason channeldb.FailureReason) error {
|
reason channeldb.FailureReason) error {
|
||||||
|
|
||||||
m.Lock()
|
m.Lock()
|
||||||
@@ -758,6 +758,7 @@ func (m *mockControlTower) FetchPayment(phash lntypes.Hash) (
|
|||||||
// Make a copy of the payment here to avoid data race.
|
// Make a copy of the payment here to avoid data race.
|
||||||
p := args.Get(0).(*channeldb.MPPayment)
|
p := args.Get(0).(*channeldb.MPPayment)
|
||||||
payment := &channeldb.MPPayment{
|
payment := &channeldb.MPPayment{
|
||||||
|
Info: p.Info,
|
||||||
FailureReason: p.FailureReason,
|
FailureReason: p.FailureReason,
|
||||||
}
|
}
|
||||||
payment.HTLCs = make([]channeldb.HTLCAttempt, len(p.HTLCs))
|
payment.HTLCs = make([]channeldb.HTLCAttempt, len(p.HTLCs))
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ var errShardHandlerExiting = fmt.Errorf("shard handler exiting")
|
|||||||
// needed to resume if from any point.
|
// needed to resume if from any point.
|
||||||
type paymentLifecycle struct {
|
type paymentLifecycle struct {
|
||||||
router *ChannelRouter
|
router *ChannelRouter
|
||||||
totalAmount lnwire.MilliSatoshi
|
|
||||||
feeLimit lnwire.MilliSatoshi
|
feeLimit lnwire.MilliSatoshi
|
||||||
identifier lntypes.Hash
|
identifier lntypes.Hash
|
||||||
paySession PaymentSession
|
paySession PaymentSession
|
||||||
@@ -83,9 +82,10 @@ func (p *paymentLifecycle) fetchPaymentState() (*channeldb.MPPayment,
|
|||||||
sentAmt, fees := payment.SentAmt()
|
sentAmt, fees := payment.SentAmt()
|
||||||
|
|
||||||
// Sanity check we haven't sent a value larger than the payment amount.
|
// Sanity check we haven't sent a value larger than the payment amount.
|
||||||
if sentAmt > p.totalAmount {
|
totalAmt := payment.Info.Value
|
||||||
|
if sentAmt > totalAmt {
|
||||||
return nil, nil, fmt.Errorf("amount sent %v exceeds "+
|
return nil, nil, fmt.Errorf("amount sent %v exceeds "+
|
||||||
"total amount %v", sentAmt, p.totalAmount)
|
"total amount %v", sentAmt, totalAmt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// We'll subtract the used fee from our fee budget, but allow the fees
|
// We'll subtract the used fee from our fee budget, but allow the fees
|
||||||
@@ -109,7 +109,7 @@ func (p *paymentLifecycle) fetchPaymentState() (*channeldb.MPPayment,
|
|||||||
// Update the payment state.
|
// Update the payment state.
|
||||||
state := &paymentState{
|
state := &paymentState{
|
||||||
numShardsInFlight: len(payment.InFlightHTLCs()),
|
numShardsInFlight: len(payment.InFlightHTLCs()),
|
||||||
remainingAmt: p.totalAmount - sentAmt,
|
remainingAmt: totalAmt - sentAmt,
|
||||||
remainingFees: feeBudget,
|
remainingFees: feeBudget,
|
||||||
terminate: terminate,
|
terminate: terminate,
|
||||||
}
|
}
|
||||||
@@ -233,7 +233,7 @@ lifecycle:
|
|||||||
// tower, no further shards will be launched and we'll
|
// tower, no further shards will be launched and we'll
|
||||||
// return with an error the moment all active shards
|
// return with an error the moment all active shards
|
||||||
// have finished.
|
// have finished.
|
||||||
saveErr := p.router.cfg.Control.Fail(
|
saveErr := p.router.cfg.Control.FailPayment(
|
||||||
p.identifier, channeldb.FailureReasonTimeout,
|
p.identifier, channeldb.FailureReasonTimeout,
|
||||||
)
|
)
|
||||||
if saveErr != nil {
|
if saveErr != nil {
|
||||||
@@ -273,7 +273,7 @@ lifecycle:
|
|||||||
"failed with no route: %v",
|
"failed with no route: %v",
|
||||||
p.identifier, failureCode)
|
p.identifier, failureCode)
|
||||||
|
|
||||||
saveErr := p.router.cfg.Control.Fail(
|
saveErr := p.router.cfg.Control.FailPayment(
|
||||||
p.identifier, failureCode,
|
p.identifier, failureCode,
|
||||||
)
|
)
|
||||||
if saveErr != nil {
|
if saveErr != nil {
|
||||||
@@ -337,7 +337,6 @@ lifecycle:
|
|||||||
// Now that the shard was successfully sent, launch a go
|
// Now that the shard was successfully sent, launch a go
|
||||||
// routine that will handle its result when its back.
|
// routine that will handle its result when its back.
|
||||||
shardHandler.collectResultAsync(attempt)
|
shardHandler.collectResultAsync(attempt)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -563,7 +562,7 @@ func (p *shardHandler) collectResult(attempt *channeldb.HTLCAttemptInfo) (
|
|||||||
|
|
||||||
// Now ask the switch to return the result of the payment when
|
// Now ask the switch to return the result of the payment when
|
||||||
// available.
|
// available.
|
||||||
resultChan, err := p.router.cfg.Payer.GetPaymentResult(
|
resultChan, err := p.router.cfg.Payer.GetAttemptResult(
|
||||||
attempt.AttemptID, p.identifier, errorDecryptor,
|
attempt.AttemptID, p.identifier, errorDecryptor,
|
||||||
)
|
)
|
||||||
switch {
|
switch {
|
||||||
@@ -785,7 +784,7 @@ func (p *shardHandler) handleSendError(attempt *channeldb.HTLCAttemptInfo,
|
|||||||
p.identifier, *reason, sendErr)
|
p.identifier, *reason, sendErr)
|
||||||
|
|
||||||
// Fail the payment via control tower.
|
// Fail the payment via control tower.
|
||||||
if err := p.router.cfg.Control.Fail(
|
if err := p.router.cfg.Control.FailPayment(
|
||||||
p.identifier, *reason,
|
p.identifier, *reason,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
log.Errorf("unable to report failure to control "+
|
log.Errorf("unable to report failure to control "+
|
||||||
|
|||||||
@@ -107,20 +107,20 @@ const (
|
|||||||
sendToSwitchResultFailure = "SendToSwitch:failure"
|
sendToSwitchResultFailure = "SendToSwitch:failure"
|
||||||
|
|
||||||
// getPaymentResultSuccess is a test step where we expect the
|
// getPaymentResultSuccess is a test step where we expect the
|
||||||
// router to call the GetPaymentResult method, and we will
|
// router to call the GetAttemptResult method, and we will
|
||||||
// respond with a successful payment result.
|
// respond with a successful payment result.
|
||||||
getPaymentResultSuccess = "GetPaymentResult:success"
|
getPaymentResultSuccess = "GetAttemptResult:success"
|
||||||
|
|
||||||
// getPaymentResultTempFailure is a test step where we expect the
|
// getPaymentResultTempFailure is a test step where we expect the
|
||||||
// router to call the GetPaymentResult method, and we will
|
// router to call the GetAttemptResult method, and we will
|
||||||
// respond with a forwarding error, expecting the router to retry.
|
// respond with a forwarding error, expecting the router to retry.
|
||||||
getPaymentResultTempFailure = "GetPaymentResult:temp-failure"
|
getPaymentResultTempFailure = "GetAttemptResult:temp-failure"
|
||||||
|
|
||||||
// getPaymentResultTerminalFailure is a test step where we
|
// getPaymentResultTerminalFailure is a test step where we
|
||||||
// expect the router to call the GetPaymentResult method, and
|
// expect the router to call the GetAttemptResult method, and
|
||||||
// we will respond with a terminal error, expecting the router
|
// we will respond with a terminal error, expecting the router
|
||||||
// to stop making payment attempts.
|
// to stop making payment attempts.
|
||||||
getPaymentResultTerminalFailure = "GetPaymentResult:terminal-failure"
|
getPaymentResultTerminalFailure = "GetAttemptResult:terminal-failure"
|
||||||
|
|
||||||
// resendPayment is a test step where we manually try to resend
|
// resendPayment is a test step where we manually try to resend
|
||||||
// the same payment, making sure the router responds with an
|
// the same payment, making sure the router responds with an
|
||||||
@@ -652,7 +652,7 @@ func testPaymentLifecycle(t *testing.T, test paymentLifecycleTestCase,
|
|||||||
fatal("unable to send result")
|
fatal("unable to send result")
|
||||||
}
|
}
|
||||||
|
|
||||||
// In this step we expect the GetPaymentResult method
|
// In this step we expect the GetAttemptResult method
|
||||||
// to be called, and we respond with the preimage to
|
// to be called, and we respond with the preimage to
|
||||||
// complete the payment.
|
// complete the payment.
|
||||||
case getPaymentResultSuccess:
|
case getPaymentResultSuccess:
|
||||||
@@ -664,7 +664,7 @@ func testPaymentLifecycle(t *testing.T, test paymentLifecycleTestCase,
|
|||||||
fatal("unable to send result")
|
fatal("unable to send result")
|
||||||
}
|
}
|
||||||
|
|
||||||
// In this state we expect the GetPaymentResult method
|
// In this state we expect the GetAttemptResult method
|
||||||
// to be called, and we respond with a forwarding
|
// to be called, and we respond with a forwarding
|
||||||
// error, indicating that the router should retry.
|
// error, indicating that the router should retry.
|
||||||
case getPaymentResultTempFailure:
|
case getPaymentResultTempFailure:
|
||||||
@@ -682,7 +682,7 @@ func testPaymentLifecycle(t *testing.T, test paymentLifecycleTestCase,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// In this state we expect the router to call the
|
// In this state we expect the router to call the
|
||||||
// GetPaymentResult method, and we will respond with a
|
// GetAttemptResult method, and we will respond with a
|
||||||
// terminal error, indicating the router should stop
|
// terminal error, indicating the router should stop
|
||||||
// making payment attempts.
|
// making payment attempts.
|
||||||
case getPaymentResultTerminalFailure:
|
case getPaymentResultTerminalFailure:
|
||||||
@@ -1052,10 +1052,9 @@ func TestUpdatePaymentState(t *testing.T) {
|
|||||||
ct := &mockControlTower{}
|
ct := &mockControlTower{}
|
||||||
rt := &ChannelRouter{cfg: &Config{Control: ct}}
|
rt := &ChannelRouter{cfg: &Config{Control: ct}}
|
||||||
pl := &paymentLifecycle{
|
pl := &paymentLifecycle{
|
||||||
router: rt,
|
router: rt,
|
||||||
identifier: paymentHash,
|
identifier: paymentHash,
|
||||||
totalAmount: lnwire.MilliSatoshi(tc.totalAmt),
|
feeLimit: lnwire.MilliSatoshi(tc.feeLimit),
|
||||||
feeLimit: lnwire.MilliSatoshi(tc.feeLimit),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if tc.payment == nil {
|
if tc.payment == nil {
|
||||||
@@ -1066,6 +1065,12 @@ func TestUpdatePaymentState(t *testing.T) {
|
|||||||
nil, dummyErr,
|
nil, dummyErr,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
// Attach the payment info.
|
||||||
|
info := &channeldb.PaymentCreationInfo{
|
||||||
|
Value: lnwire.MilliSatoshi(tc.totalAmt),
|
||||||
|
}
|
||||||
|
tc.payment.Info = info
|
||||||
|
|
||||||
// Otherwise we will return the payment.
|
// Otherwise we will return the payment.
|
||||||
ct.On("FetchPayment", paymentHash).Return(
|
ct.On("FetchPayment", paymentHash).Return(
|
||||||
tc.payment, nil,
|
tc.payment, nil,
|
||||||
|
|||||||
+14
-14
@@ -169,7 +169,7 @@ type PaymentAttemptDispatcher interface {
|
|||||||
attemptID uint64,
|
attemptID uint64,
|
||||||
htlcAdd *lnwire.UpdateAddHTLC) error
|
htlcAdd *lnwire.UpdateAddHTLC) error
|
||||||
|
|
||||||
// GetPaymentResult returns the result of the payment attempt with
|
// GetAttemptResult returns the result of the payment attempt with
|
||||||
// the given attemptID. The paymentHash should be set to the payment's
|
// the given attemptID. The paymentHash should be set to the payment's
|
||||||
// overall hash, or in case of AMP payments the payment's unique
|
// overall hash, or in case of AMP payments the payment's unique
|
||||||
// identifier.
|
// identifier.
|
||||||
@@ -180,7 +180,7 @@ type PaymentAttemptDispatcher interface {
|
|||||||
// longer be in flight. The switch shutting down is signaled by
|
// longer be in flight. The switch shutting down is signaled by
|
||||||
// closing the channel. If the attemptID is unknown,
|
// closing the channel. If the attemptID is unknown,
|
||||||
// ErrPaymentIDNotFound will be returned.
|
// ErrPaymentIDNotFound will be returned.
|
||||||
GetPaymentResult(attemptID uint64, paymentHash lntypes.Hash,
|
GetAttemptResult(attemptID uint64, paymentHash lntypes.Hash,
|
||||||
deobfuscator htlcswitch.ErrorDecrypter) (
|
deobfuscator htlcswitch.ErrorDecrypter) (
|
||||||
<-chan *htlcswitch.PaymentResult, error)
|
<-chan *htlcswitch.PaymentResult, error)
|
||||||
|
|
||||||
@@ -667,9 +667,8 @@ func (r *ChannelRouter) Start() error {
|
|||||||
// also set a zero fee limit, as no more routes should
|
// also set a zero fee limit, as no more routes should
|
||||||
// be tried.
|
// be tried.
|
||||||
_, _, err := r.sendPayment(
|
_, _, err := r.sendPayment(
|
||||||
payment.Info.Value, 0,
|
0, payment.Info.PaymentIdentifier, 0,
|
||||||
payment.Info.PaymentIdentifier, 0, paySession,
|
paySession, shardTracker,
|
||||||
shardTracker,
|
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Resuming payment %v failed: %v.",
|
log.Errorf("Resuming payment %v failed: %v.",
|
||||||
@@ -2048,7 +2047,7 @@ func (r *ChannelRouter) SendPayment(payment *LightningPayment) ([32]byte,
|
|||||||
// Since this is the first time this payment is being made, we pass nil
|
// Since this is the first time this payment is being made, we pass nil
|
||||||
// for the existing attempt.
|
// for the existing attempt.
|
||||||
return r.sendPayment(
|
return r.sendPayment(
|
||||||
payment.Amount, payment.FeeLimit, payment.Identifier(),
|
payment.FeeLimit, payment.Identifier(),
|
||||||
payment.PayAttemptTimeout, paySession, shardTracker,
|
payment.PayAttemptTimeout, paySession, shardTracker,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -2071,7 +2070,7 @@ func (r *ChannelRouter) SendPaymentAsync(payment *LightningPayment) error {
|
|||||||
spewPayment(payment))
|
spewPayment(payment))
|
||||||
|
|
||||||
_, _, err := r.sendPayment(
|
_, _, err := r.sendPayment(
|
||||||
payment.Amount, payment.FeeLimit, payment.Identifier(),
|
payment.FeeLimit, payment.Identifier(),
|
||||||
payment.PayAttemptTimeout, paySession, shardTracker,
|
payment.PayAttemptTimeout, paySession, shardTracker,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -2253,7 +2252,7 @@ func (r *ChannelRouter) sendToRoute(htlcHash lntypes.Hash, rt *route.Route,
|
|||||||
log.Debugf("Invalid route provided for payment %x: %v",
|
log.Debugf("Invalid route provided for payment %x: %v",
|
||||||
paymentIdentifier, err)
|
paymentIdentifier, err)
|
||||||
|
|
||||||
controlErr := r.cfg.Control.Fail(
|
controlErr := r.cfg.Control.FailPayment(
|
||||||
paymentIdentifier, channeldb.FailureReasonError,
|
paymentIdentifier, channeldb.FailureReasonError,
|
||||||
)
|
)
|
||||||
if controlErr != nil {
|
if controlErr != nil {
|
||||||
@@ -2301,14 +2300,16 @@ func (r *ChannelRouter) sendToRoute(htlcHash lntypes.Hash, rt *route.Route,
|
|||||||
// If a non-terminal error is returned and `skipTempErr` is false, then
|
// If a non-terminal error is returned and `skipTempErr` is false, then
|
||||||
// we'll use the normal no route error.
|
// we'll use the normal no route error.
|
||||||
case err == nil && !skipTempErr:
|
case err == nil && !skipTempErr:
|
||||||
err = r.cfg.Control.Fail(
|
err = r.cfg.Control.FailPayment(
|
||||||
paymentIdentifier, channeldb.FailureReasonNoRoute,
|
paymentIdentifier, channeldb.FailureReasonNoRoute,
|
||||||
)
|
)
|
||||||
|
|
||||||
// If this is a failure reason, then we'll apply the failure directly
|
// If this is a failure reason, then we'll apply the failure directly
|
||||||
// to the control tower, and return the normal response to the caller.
|
// to the control tower, and return the normal response to the caller.
|
||||||
case goErrors.As(err, &failureReason):
|
case goErrors.As(err, &failureReason):
|
||||||
err = r.cfg.Control.Fail(paymentIdentifier, *failureReason)
|
err = r.cfg.Control.FailPayment(
|
||||||
|
paymentIdentifier, *failureReason,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -2333,9 +2334,9 @@ func (r *ChannelRouter) sendToRoute(htlcHash lntypes.Hash, rt *route.Route,
|
|||||||
// carry out its execution. After restarts it is safe, and assumed, that the
|
// carry out its execution. After restarts it is safe, and assumed, that the
|
||||||
// router will call this method for every payment still in-flight according to
|
// router will call this method for every payment still in-flight according to
|
||||||
// the ControlTower.
|
// the ControlTower.
|
||||||
func (r *ChannelRouter) sendPayment(
|
func (r *ChannelRouter) sendPayment(feeLimit lnwire.MilliSatoshi,
|
||||||
totalAmt, feeLimit lnwire.MilliSatoshi, identifier lntypes.Hash,
|
identifier lntypes.Hash, timeout time.Duration,
|
||||||
timeout time.Duration, paySession PaymentSession,
|
paySession PaymentSession,
|
||||||
shardTracker shards.ShardTracker) ([32]byte, *route.Route, error) {
|
shardTracker shards.ShardTracker) ([32]byte, *route.Route, error) {
|
||||||
|
|
||||||
// We'll also fetch the current block height so we can properly
|
// We'll also fetch the current block height so we can properly
|
||||||
@@ -2349,7 +2350,6 @@ func (r *ChannelRouter) sendPayment(
|
|||||||
// can resume the payment from the current state.
|
// can resume the payment from the current state.
|
||||||
p := &paymentLifecycle{
|
p := &paymentLifecycle{
|
||||||
router: r,
|
router: r,
|
||||||
totalAmount: totalAmt,
|
|
||||||
feeLimit: feeLimit,
|
feeLimit: feeLimit,
|
||||||
identifier: identifier,
|
identifier: identifier,
|
||||||
paySession: paySession,
|
paySession: paySession,
|
||||||
|
|||||||
+37
-29
@@ -3421,7 +3421,9 @@ func TestSendMPPaymentSucceed(t *testing.T) {
|
|||||||
// The following mocked methods are called inside resumePayment. Note
|
// The following mocked methods are called inside resumePayment. Note
|
||||||
// that the payment object below will determine the state of the
|
// that the payment object below will determine the state of the
|
||||||
// paymentLifecycle.
|
// paymentLifecycle.
|
||||||
payment := &channeldb.MPPayment{}
|
payment := &channeldb.MPPayment{
|
||||||
|
Info: &channeldb.PaymentCreationInfo{Value: paymentAmt},
|
||||||
|
}
|
||||||
controlTower.On("FetchPayment", identifier).Return(payment, nil)
|
controlTower.On("FetchPayment", identifier).Return(payment, nil)
|
||||||
|
|
||||||
// Create a route that can send 1/4 of the total amount. This value
|
// Create a route that can send 1/4 of the total amount. This value
|
||||||
@@ -3441,9 +3443,9 @@ func TestSendMPPaymentSucceed(t *testing.T) {
|
|||||||
payment.HTLCs = append(payment.HTLCs, activeAttempt)
|
payment.HTLCs = append(payment.HTLCs, activeAttempt)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Create a buffered chan and it will be returned by GetPaymentResult.
|
// Create a buffered chan and it will be returned by GetAttemptResult.
|
||||||
payer.resultChan = make(chan *htlcswitch.PaymentResult, 10)
|
payer.resultChan = make(chan *htlcswitch.PaymentResult, 10)
|
||||||
payer.On("GetPaymentResult",
|
payer.On("GetAttemptResult",
|
||||||
mock.Anything, identifier, mock.Anything,
|
mock.Anything, identifier, mock.Anything,
|
||||||
).Run(func(args mock.Arguments) {
|
).Run(func(args mock.Arguments) {
|
||||||
// Before the mock method is returned, we send the result to
|
// Before the mock method is returned, we send the result to
|
||||||
@@ -3588,7 +3590,9 @@ func TestSendMPPaymentSucceedOnExtraShards(t *testing.T) {
|
|||||||
// The following mocked methods are called inside resumePayment. Note
|
// The following mocked methods are called inside resumePayment. Note
|
||||||
// that the payment object below will determine the state of the
|
// that the payment object below will determine the state of the
|
||||||
// paymentLifecycle.
|
// paymentLifecycle.
|
||||||
payment := &channeldb.MPPayment{}
|
payment := &channeldb.MPPayment{
|
||||||
|
Info: &channeldb.PaymentCreationInfo{Value: paymentAmt},
|
||||||
|
}
|
||||||
controlTower.On("FetchPayment", identifier).Return(payment, nil)
|
controlTower.On("FetchPayment", identifier).Return(payment, nil)
|
||||||
|
|
||||||
// Create a route that can send 1/4 of the total amount. This value
|
// Create a route that can send 1/4 of the total amount. This value
|
||||||
@@ -3608,14 +3612,14 @@ func TestSendMPPaymentSucceedOnExtraShards(t *testing.T) {
|
|||||||
payment.HTLCs = append(payment.HTLCs, activeAttempt)
|
payment.HTLCs = append(payment.HTLCs, activeAttempt)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Create a buffered chan and it will be returned by GetPaymentResult.
|
// Create a buffered chan and it will be returned by GetAttemptResult.
|
||||||
payer.resultChan = make(chan *htlcswitch.PaymentResult, 10)
|
payer.resultChan = make(chan *htlcswitch.PaymentResult, 10)
|
||||||
|
|
||||||
// We use the failAttemptCount to track how many attempts we want to
|
// We use the failAttemptCount to track how many attempts we want to
|
||||||
// fail. Each time the following mock method is called, the count gets
|
// fail. Each time the following mock method is called, the count gets
|
||||||
// updated.
|
// updated.
|
||||||
failAttemptCount := 0
|
failAttemptCount := 0
|
||||||
payer.On("GetPaymentResult",
|
payer.On("GetAttemptResult",
|
||||||
mock.Anything, identifier, mock.Anything,
|
mock.Anything, identifier, mock.Anything,
|
||||||
).Run(func(args mock.Arguments) {
|
).Run(func(args mock.Arguments) {
|
||||||
// Before the mock method is returned, we send the result to
|
// Before the mock method is returned, we send the result to
|
||||||
@@ -3800,7 +3804,9 @@ func TestSendMPPaymentFailed(t *testing.T) {
|
|||||||
// The following mocked methods are called inside resumePayment. Note
|
// The following mocked methods are called inside resumePayment. Note
|
||||||
// that the payment object below will determine the state of the
|
// that the payment object below will determine the state of the
|
||||||
// paymentLifecycle.
|
// paymentLifecycle.
|
||||||
payment := &channeldb.MPPayment{}
|
payment := &channeldb.MPPayment{
|
||||||
|
Info: &channeldb.PaymentCreationInfo{Value: paymentAmt},
|
||||||
|
}
|
||||||
controlTower.On("FetchPayment", identifier).Return(payment, nil)
|
controlTower.On("FetchPayment", identifier).Return(payment, nil)
|
||||||
|
|
||||||
// Create a route that can send 1/4 of the total amount. This value
|
// Create a route that can send 1/4 of the total amount. This value
|
||||||
@@ -3820,14 +3826,14 @@ func TestSendMPPaymentFailed(t *testing.T) {
|
|||||||
payment.HTLCs = append(payment.HTLCs, activeAttempt)
|
payment.HTLCs = append(payment.HTLCs, activeAttempt)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Create a buffered chan and it will be returned by GetPaymentResult.
|
// Create a buffered chan and it will be returned by GetAttemptResult.
|
||||||
payer.resultChan = make(chan *htlcswitch.PaymentResult, 10)
|
payer.resultChan = make(chan *htlcswitch.PaymentResult, 10)
|
||||||
|
|
||||||
// We use the failAttemptCount to track how many attempts we want to
|
// We use the failAttemptCount to track how many attempts we want to
|
||||||
// fail. Each time the following mock method is called, the count gets
|
// fail. Each time the following mock method is called, the count gets
|
||||||
// updated.
|
// updated.
|
||||||
failAttemptCount := 0
|
failAttemptCount := 0
|
||||||
payer.On("GetPaymentResult",
|
payer.On("GetAttemptResult",
|
||||||
mock.Anything, identifier, mock.Anything,
|
mock.Anything, identifier, mock.Anything,
|
||||||
).Run(func(args mock.Arguments) {
|
).Run(func(args mock.Arguments) {
|
||||||
// Before the mock method is returned, we send the result to
|
// Before the mock method is returned, we send the result to
|
||||||
@@ -3896,7 +3902,7 @@ func TestSendMPPaymentFailed(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Simple mocking the rest.
|
// Simple mocking the rest.
|
||||||
controlTower.On("Fail", identifier, failureReason).Return(nil)
|
controlTower.On("FailPayment", identifier, failureReason).Return(nil)
|
||||||
payer.On("SendHTLC",
|
payer.On("SendHTLC",
|
||||||
mock.Anything, mock.Anything, mock.Anything,
|
mock.Anything, mock.Anything, mock.Anything,
|
||||||
).Return(nil)
|
).Return(nil)
|
||||||
@@ -4004,7 +4010,9 @@ func TestSendMPPaymentFailedWithShardsInFlight(t *testing.T) {
|
|||||||
// The following mocked methods are called inside resumePayment. Note
|
// The following mocked methods are called inside resumePayment. Note
|
||||||
// that the payment object below will determine the state of the
|
// that the payment object below will determine the state of the
|
||||||
// paymentLifecycle.
|
// paymentLifecycle.
|
||||||
payment := &channeldb.MPPayment{}
|
payment := &channeldb.MPPayment{
|
||||||
|
Info: &channeldb.PaymentCreationInfo{Value: paymentAmt},
|
||||||
|
}
|
||||||
controlTower.On("FetchPayment", identifier).Return(payment, nil)
|
controlTower.On("FetchPayment", identifier).Return(payment, nil)
|
||||||
|
|
||||||
// Create a route that can send 1/4 of the total amount. This value
|
// Create a route that can send 1/4 of the total amount. This value
|
||||||
@@ -4024,18 +4032,18 @@ func TestSendMPPaymentFailedWithShardsInFlight(t *testing.T) {
|
|||||||
payment.HTLCs = append(payment.HTLCs, activeAttempt)
|
payment.HTLCs = append(payment.HTLCs, activeAttempt)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Create a buffered chan and it will be returned by GetPaymentResult.
|
// Create a buffered chan and it will be returned by GetAttemptResult.
|
||||||
payer.resultChan = make(chan *htlcswitch.PaymentResult, 10)
|
payer.resultChan = make(chan *htlcswitch.PaymentResult, 10)
|
||||||
|
|
||||||
// We use the getPaymentResultCnt to track how many times we called
|
// We use the getPaymentResultCnt to track how many times we called
|
||||||
// GetPaymentResult. As shard launch is sequential, and we fail the
|
// GetAttemptResult. As shard launch is sequential, and we fail the
|
||||||
// first shard that calls GetPaymentResult, we may end up with different
|
// first shard that calls GetAttemptResult, we may end up with different
|
||||||
// counts since the lifecycle itself is asynchronous. To avoid flakes
|
// counts since the lifecycle itself is asynchronous. To avoid flakes
|
||||||
// due to this undeterminsitic behavior, we'll compare the final
|
// due to this undeterminsitic behavior, we'll compare the final
|
||||||
// getPaymentResultCnt with other counters to create a final test
|
// getPaymentResultCnt with other counters to create a final test
|
||||||
// expectation.
|
// expectation.
|
||||||
getPaymentResultCnt := 0
|
getPaymentResultCnt := 0
|
||||||
payer.On("GetPaymentResult",
|
payer.On("GetAttemptResult",
|
||||||
mock.Anything, identifier, mock.Anything,
|
mock.Anything, identifier, mock.Anything,
|
||||||
).Run(func(args mock.Arguments) {
|
).Run(func(args mock.Arguments) {
|
||||||
// Before the mock method is returned, we send the result to
|
// Before the mock method is returned, we send the result to
|
||||||
@@ -4091,7 +4099,7 @@ func TestSendMPPaymentFailedWithShardsInFlight(t *testing.T) {
|
|||||||
|
|
||||||
// Simple mocking the rest.
|
// Simple mocking the rest.
|
||||||
cntFail := 0
|
cntFail := 0
|
||||||
controlTower.On("Fail", identifier, failureReason).Return(nil)
|
controlTower.On("FailPayment", identifier, failureReason).Return(nil)
|
||||||
payer.On("SendHTLC",
|
payer.On("SendHTLC",
|
||||||
mock.Anything, mock.Anything, mock.Anything,
|
mock.Anything, mock.Anything, mock.Anything,
|
||||||
).Return(nil).Run(func(args mock.Arguments) {
|
).Return(nil).Run(func(args mock.Arguments) {
|
||||||
@@ -4254,9 +4262,9 @@ func TestSendToRouteSkipTempErrSuccess(t *testing.T) {
|
|||||||
mock.Anything, mock.Anything, mock.Anything,
|
mock.Anything, mock.Anything, mock.Anything,
|
||||||
).Return(nil)
|
).Return(nil)
|
||||||
|
|
||||||
// Create a buffered chan and it will be returned by GetPaymentResult.
|
// Create a buffered chan and it will be returned by GetAttemptResult.
|
||||||
payer.resultChan = make(chan *htlcswitch.PaymentResult, 1)
|
payer.resultChan = make(chan *htlcswitch.PaymentResult, 1)
|
||||||
payer.On("GetPaymentResult",
|
payer.On("GetAttemptResult",
|
||||||
mock.Anything, mock.Anything, mock.Anything,
|
mock.Anything, mock.Anything, mock.Anything,
|
||||||
).Run(func(_ mock.Arguments) {
|
).Run(func(_ mock.Arguments) {
|
||||||
// Send a successful payment result.
|
// Send a successful payment result.
|
||||||
@@ -4329,7 +4337,7 @@ func TestSendToRouteSkipTempErrTempFailure(t *testing.T) {
|
|||||||
mock.Anything, mock.Anything, mock.Anything,
|
mock.Anything, mock.Anything, mock.Anything,
|
||||||
).Return(nil)
|
).Return(nil)
|
||||||
|
|
||||||
// Create a buffered chan and it will be returned by GetPaymentResult.
|
// Create a buffered chan and it will be returned by GetAttemptResult.
|
||||||
payer.resultChan = make(chan *htlcswitch.PaymentResult, 1)
|
payer.resultChan = make(chan *htlcswitch.PaymentResult, 1)
|
||||||
|
|
||||||
// Create the error to be returned.
|
// Create the error to be returned.
|
||||||
@@ -4338,8 +4346,8 @@ func TestSendToRouteSkipTempErrTempFailure(t *testing.T) {
|
|||||||
1,
|
1,
|
||||||
)
|
)
|
||||||
|
|
||||||
// Mock GetPaymentResult to return a failure.
|
// Mock GetAttemptResult to return a failure.
|
||||||
payer.On("GetPaymentResult",
|
payer.On("GetAttemptResult",
|
||||||
mock.Anything, mock.Anything, mock.Anything,
|
mock.Anything, mock.Anything, mock.Anything,
|
||||||
).Run(func(_ mock.Arguments) {
|
).Run(func(_ mock.Arguments) {
|
||||||
// Send an attempt failure.
|
// Send an attempt failure.
|
||||||
@@ -4412,13 +4420,13 @@ func TestSendToRouteSkipTempErrPermanentFailure(t *testing.T) {
|
|||||||
).Return(testAttempt, nil)
|
).Return(testAttempt, nil)
|
||||||
|
|
||||||
// Expect the payment to be failed.
|
// Expect the payment to be failed.
|
||||||
controlTower.On("Fail", payHash, mock.Anything).Return(nil)
|
controlTower.On("FailPayment", payHash, mock.Anything).Return(nil)
|
||||||
|
|
||||||
payer.On("SendHTLC",
|
payer.On("SendHTLC",
|
||||||
mock.Anything, mock.Anything, mock.Anything,
|
mock.Anything, mock.Anything, mock.Anything,
|
||||||
).Return(nil)
|
).Return(nil)
|
||||||
|
|
||||||
// Create a buffered chan and it will be returned by GetPaymentResult.
|
// Create a buffered chan and it will be returned by GetAttemptResult.
|
||||||
payer.resultChan = make(chan *htlcswitch.PaymentResult, 1)
|
payer.resultChan = make(chan *htlcswitch.PaymentResult, 1)
|
||||||
|
|
||||||
// Create the error to be returned.
|
// Create the error to be returned.
|
||||||
@@ -4426,8 +4434,8 @@ func TestSendToRouteSkipTempErrPermanentFailure(t *testing.T) {
|
|||||||
&lnwire.FailIncorrectDetails{}, 1,
|
&lnwire.FailIncorrectDetails{}, 1,
|
||||||
)
|
)
|
||||||
|
|
||||||
// Mock GetPaymentResult to return a failure.
|
// Mock GetAttemptResult to return a failure.
|
||||||
payer.On("GetPaymentResult",
|
payer.On("GetAttemptResult",
|
||||||
mock.Anything, mock.Anything, mock.Anything,
|
mock.Anything, mock.Anything, mock.Anything,
|
||||||
).Run(func(_ mock.Arguments) {
|
).Run(func(_ mock.Arguments) {
|
||||||
// Send a permanent failure.
|
// Send a permanent failure.
|
||||||
@@ -4501,13 +4509,13 @@ func TestSendToRouteTempFailure(t *testing.T) {
|
|||||||
).Return(testAttempt, nil)
|
).Return(testAttempt, nil)
|
||||||
|
|
||||||
// Expect the payment to be failed.
|
// Expect the payment to be failed.
|
||||||
controlTower.On("Fail", payHash, mock.Anything).Return(nil)
|
controlTower.On("FailPayment", payHash, mock.Anything).Return(nil)
|
||||||
|
|
||||||
payer.On("SendHTLC",
|
payer.On("SendHTLC",
|
||||||
mock.Anything, mock.Anything, mock.Anything,
|
mock.Anything, mock.Anything, mock.Anything,
|
||||||
).Return(nil)
|
).Return(nil)
|
||||||
|
|
||||||
// Create a buffered chan and it will be returned by GetPaymentResult.
|
// Create a buffered chan and it will be returned by GetAttemptResult.
|
||||||
payer.resultChan = make(chan *htlcswitch.PaymentResult, 1)
|
payer.resultChan = make(chan *htlcswitch.PaymentResult, 1)
|
||||||
|
|
||||||
// Create the error to be returned.
|
// Create the error to be returned.
|
||||||
@@ -4516,8 +4524,8 @@ func TestSendToRouteTempFailure(t *testing.T) {
|
|||||||
1,
|
1,
|
||||||
)
|
)
|
||||||
|
|
||||||
// Mock GetPaymentResult to return a failure.
|
// Mock GetAttemptResult to return a failure.
|
||||||
payer.On("GetPaymentResult",
|
payer.On("GetAttemptResult",
|
||||||
mock.Anything, mock.Anything, mock.Anything,
|
mock.Anything, mock.Anything, mock.Anything,
|
||||||
).Run(func(_ mock.Arguments) {
|
).Run(func(_ mock.Arguments) {
|
||||||
// Send an attempt failure.
|
// Send an attempt failure.
|
||||||
|
|||||||
Reference in new issue
Block a user