diff --git a/channeldb/mp_payment.go b/channeldb/mp_payment.go index bee26759..4220e7aa 100644 --- a/channeldb/mp_payment.go +++ b/channeldb/mp_payment.go @@ -8,16 +8,15 @@ import ( "github.com/lightningnetwork/lnd/routing/route" ) -// HTLCAttempt contains information about a specific HTLC attempt for a given -// payment. This information is used by the router to handle any errors coming -// back after an attempt is made, and to query the switch about the status of a -// payment. For settled payment this will be the information for the succeeding -// payment attempt. -type HTLCAttempt struct { - // PaymentID is the unique ID used for this attempt. - PaymentID uint64 +// HTLCAttemptInfo contains static information about a specific HTLC attempt +// for a payment. This information is used by the router to handle any errors +// coming back after an attempt is made, and to query the switch about the +// status of the attempt. +type HTLCAttemptInfo struct { + // AttemptID is the unique ID used for this attempt. + AttemptID uint64 - // SessionKey is the ephemeral key used for this payment attempt. + // SessionKey is the ephemeral key used for this attempt. SessionKey *btcec.PrivateKey // Route is the route attempted to send the HTLC. @@ -25,6 +24,13 @@ type HTLCAttempt struct { // AttemptTime is the time at which this HTLC was attempted. AttemptTime time.Time +} + +// HTLCAttempt contains information about a specific HTLC attempt for a given +// payment. It contains the HTLCAttemptInfo used to send the HTLC, as well +// as a timestamp and any known outcome of the attempt. +type HTLCAttempt struct { + HTLCAttemptInfo // Settle is the preimage of a successful payment. This serves as a // proof of payment. It will only be non-nil for settled payments. diff --git a/channeldb/payment_control.go b/channeldb/payment_control.go index 63be23a2..b6bcd5a1 100644 --- a/channeldb/payment_control.go +++ b/channeldb/payment_control.go @@ -143,14 +143,14 @@ func (p *PaymentControl) InitPayment(paymentHash lntypes.Hash, return updateErr } -// RegisterAttempt atomically records the provided PaymentAttemptInfo to the +// RegisterAttempt atomically records the provided HTLCAttemptInfo to the // DB. func (p *PaymentControl) RegisterAttempt(paymentHash lntypes.Hash, - attempt *PaymentAttemptInfo) error { + attempt *HTLCAttemptInfo) error { // Serialize the information before opening the db transaction. var a bytes.Buffer - if err := serializePaymentAttemptInfo(&a, attempt); err != nil { + if err := serializeHTLCAttemptInfo(&a, attempt); err != nil { return err } attemptBytes := a.Bytes() @@ -405,14 +405,14 @@ func ensureInFlight(bucket *bbolt.Bucket) error { } // fetchPaymentAttempt fetches the payment attempt from the bucket. -func fetchPaymentAttempt(bucket *bbolt.Bucket) (*PaymentAttemptInfo, error) { +func fetchPaymentAttempt(bucket *bbolt.Bucket) (*HTLCAttemptInfo, error) { attemptData := bucket.Get(paymentAttemptInfoKey) if attemptData == nil { return nil, errNoAttemptInfo } r := bytes.NewReader(attemptData) - return deserializePaymentAttemptInfo(r) + return deserializeHTLCAttemptInfo(r) } // InFlightPayment is a wrapper around a payment that has status InFlight. @@ -424,7 +424,7 @@ type InFlightPayment struct { // made to this payment hash. // // NOTE: Might be nil. - Attempt *PaymentAttemptInfo + Attempt *HTLCAttemptInfo } // FetchInFlightPayments returns all payments with status InFlight. diff --git a/channeldb/payment_control_test.go b/channeldb/payment_control_test.go index bb1458ae..29100631 100644 --- a/channeldb/payment_control_test.go +++ b/channeldb/payment_control_test.go @@ -38,7 +38,7 @@ func genPreimage() ([32]byte, error) { return preimage, nil } -func genInfo() (*PaymentCreationInfo, *PaymentAttemptInfo, +func genInfo() (*PaymentCreationInfo, *HTLCAttemptInfo, lntypes.Preimage, error) { preimage, err := genPreimage() @@ -54,8 +54,8 @@ func genInfo() (*PaymentCreationInfo, *PaymentAttemptInfo, CreationTime: time.Unix(time.Now().Unix(), 0), PaymentRequest: []byte("hola"), }, - &PaymentAttemptInfo{ - PaymentID: 1, + &HTLCAttemptInfo{ + AttemptID: 1, SessionKey: priv, Route: testRoute, }, preimage, nil @@ -119,7 +119,7 @@ func TestPaymentControlSwitchFail(t *testing.T) { ) // Record a new attempt. - attempt.PaymentID = 2 + attempt.AttemptID = 2 err = pControl.RegisterAttempt(info.PaymentHash, attempt) if err != nil { t.Fatalf("unable to send htlc message: %v", err) @@ -445,7 +445,7 @@ func checkPaymentCreationInfo(bucket *bbolt.Bucket, c *PaymentCreationInfo) erro return nil } -func checkPaymentAttemptInfo(bucket *bbolt.Bucket, a *PaymentAttemptInfo) error { +func checkHTLCAttemptInfo(bucket *bbolt.Bucket, a *HTLCAttemptInfo) error { b := bucket.Get(paymentAttemptInfoKey) switch { case b == nil && a == nil: @@ -457,7 +457,7 @@ func checkPaymentAttemptInfo(bucket *bbolt.Bucket, a *PaymentAttemptInfo) error } r := bytes.NewReader(b) - a2, err := deserializePaymentAttemptInfo(r) + a2, err := deserializeHTLCAttemptInfo(r) if err != nil { return err } @@ -508,7 +508,7 @@ func checkFailInfo(bucket *bbolt.Bucket, failReason *FailureReason) error { } func assertPaymentInfo(t *testing.T, db *DB, hash lntypes.Hash, - c *PaymentCreationInfo, a *PaymentAttemptInfo, s lntypes.Preimage, + c *PaymentCreationInfo, a *HTLCAttemptInfo, s lntypes.Preimage, f *FailureReason) { t.Helper() @@ -535,7 +535,7 @@ func assertPaymentInfo(t *testing.T, db *DB, hash lntypes.Hash, return err } - if err := checkPaymentAttemptInfo(bucket, a); err != nil { + if err := checkHTLCAttemptInfo(bucket, a); err != nil { return err } diff --git a/channeldb/payments.go b/channeldb/payments.go index 0800b998..ae6d8abd 100644 --- a/channeldb/payments.go +++ b/channeldb/payments.go @@ -8,7 +8,6 @@ import ( "sort" "time" - "github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/wire" "github.com/coreos/bbolt" "github.com/lightningnetwork/lnd/lntypes" @@ -185,25 +184,9 @@ type PaymentCreationInfo struct { PaymentRequest []byte } -// PaymentAttemptInfo contains information about a specific payment attempt for -// a given payment. This information is used by the router to handle any errors -// coming back after an attempt is made, and to query the switch about the -// status of a payment. For settled payment this will be the information for -// the succeeding payment attempt. -type PaymentAttemptInfo struct { - // PaymentID is the unique ID used for this attempt. - PaymentID uint64 - - // SessionKey is the ephemeral key used for this payment attempt. - SessionKey *btcec.PrivateKey - - // Route is the route attempted to send the HTLC. - Route route.Route -} - // Payment is a wrapper around a payment's PaymentCreationInfo, -// PaymentAttemptInfo, and preimage. All payments will have the -// PaymentCreationInfo set, the PaymentAttemptInfo will be set only if at least +// HTLCAttemptInfo, and preimage. All payments will have the +// PaymentCreationInfo set, the HTLCAttemptInfo will be set only if at least // one payment attempt has been made, while only completed payments will have a // non-zero payment preimage. type Payment struct { @@ -221,7 +204,7 @@ type Payment struct { // Attempt is the information about the last payment attempt made. // // NOTE: Can be nil if no attempt is yet made. - Attempt *PaymentAttemptInfo + Attempt *HTLCAttemptInfo // Preimage is the preimage of a successful payment. This serves as a // proof of payment. It will only be non-nil for settled payments. @@ -272,11 +255,9 @@ func (p *Payment) ToMPPayment() *MPPayment { // NOTE: AttemptTime is not set for legacy payments. htlcs = []HTLCAttempt{ { - PaymentID: p.Attempt.PaymentID, - SessionKey: p.Attempt.SessionKey, - Route: p.Attempt.Route, - Settle: settle, - Failure: failure, + HTLCAttemptInfo: *p.Attempt, + Settle: settle, + Failure: failure, }, } } @@ -392,11 +373,11 @@ func fetchPayment(bucket *bbolt.Bucket) (*MPPayment, error) { } - // Get the PaymentAttemptInfo. This can be unset. + // Get the HTLCAttemptInfo. This can be unset. b = bucket.Get(paymentAttemptInfoKey) if b != nil { r = bytes.NewReader(b) - p.Attempt, err = deserializePaymentAttemptInfo(r) + p.Attempt, err = deserializeHTLCAttemptInfo(r) if err != nil { return nil, err } @@ -527,8 +508,8 @@ func deserializePaymentCreationInfo(r io.Reader) (*PaymentCreationInfo, error) { return c, nil } -func serializePaymentAttemptInfo(w io.Writer, a *PaymentAttemptInfo) error { - if err := WriteElements(w, a.PaymentID, a.SessionKey); err != nil { +func serializeHTLCAttemptInfo(w io.Writer, a *HTLCAttemptInfo) error { + if err := WriteElements(w, a.AttemptID, a.SessionKey); err != nil { return err } @@ -539,9 +520,9 @@ func serializePaymentAttemptInfo(w io.Writer, a *PaymentAttemptInfo) error { return nil } -func deserializePaymentAttemptInfo(r io.Reader) (*PaymentAttemptInfo, error) { - a := &PaymentAttemptInfo{} - err := ReadElements(r, &a.PaymentID, &a.SessionKey) +func deserializeHTLCAttemptInfo(r io.Reader) (*HTLCAttemptInfo, error) { + a := &HTLCAttemptInfo{} + err := ReadElements(r, &a.AttemptID, &a.SessionKey) if err != nil { return nil, err } diff --git a/channeldb/payments_test.go b/channeldb/payments_test.go index fb3de6ce..26148a1e 100644 --- a/channeldb/payments_test.go +++ b/channeldb/payments_test.go @@ -53,7 +53,7 @@ var ( } ) -func makeFakeInfo() (*PaymentCreationInfo, *PaymentAttemptInfo) { +func makeFakeInfo() (*PaymentCreationInfo, *HTLCAttemptInfo) { var preimg lntypes.Preimage copy(preimg[:], rev[:]) @@ -66,8 +66,8 @@ func makeFakeInfo() (*PaymentCreationInfo, *PaymentAttemptInfo) { PaymentRequest: []byte(""), } - a := &PaymentAttemptInfo{ - PaymentID: 44, + a := &HTLCAttemptInfo{ + AttemptID: 44, SessionKey: priv, Route: testRoute, } @@ -109,11 +109,11 @@ func TestSentPaymentSerialization(t *testing.T) { } b.Reset() - if err := serializePaymentAttemptInfo(&b, s); err != nil { + if err := serializeHTLCAttemptInfo(&b, s); err != nil { t.Fatalf("unable to serialize info: %v", err) } - newAttemptInfo, err := deserializePaymentAttemptInfo(&b) + newAttemptInfo, err := deserializeHTLCAttemptInfo(&b) if err != nil { t.Fatalf("unable to deserialize info: %v", err) } @@ -144,7 +144,7 @@ func TestSentPaymentSerialization(t *testing.T) { // they are not equal. func assertRouteEqual(a, b *route.Route) error { if !reflect.DeepEqual(a, b) { - return fmt.Errorf("PaymentAttemptInfos don't match: %v vs %v", + return fmt.Errorf("HTLCAttemptInfos don't match: %v vs %v", spew.Sdump(a), spew.Sdump(b)) } diff --git a/routing/control_tower.go b/routing/control_tower.go index 4cf6839f..0dffa7c6 100644 --- a/routing/control_tower.go +++ b/routing/control_tower.go @@ -19,8 +19,8 @@ type ControlTower interface { // hash. InitPayment(lntypes.Hash, *channeldb.PaymentCreationInfo) error - // RegisterAttempt atomically records the provided PaymentAttemptInfo. - RegisterAttempt(lntypes.Hash, *channeldb.PaymentAttemptInfo) error + // RegisterAttempt atomically records the provided HTLCAttemptInfo. + RegisterAttempt(lntypes.Hash, *channeldb.HTLCAttemptInfo) error // Success transitions a payment into the Succeeded state. After // invoking this method, InitPayment should always return an error to @@ -91,10 +91,10 @@ func (p *controlTower) InitPayment(paymentHash lntypes.Hash, return p.db.InitPayment(paymentHash, info) } -// RegisterAttempt atomically records the provided PaymentAttemptInfo to the +// RegisterAttempt atomically records the provided HTLCAttemptInfo to the // DB. func (p *controlTower) RegisterAttempt(paymentHash lntypes.Hash, - attempt *channeldb.PaymentAttemptInfo) error { + attempt *channeldb.HTLCAttemptInfo) error { return p.db.RegisterAttempt(paymentHash, attempt) } diff --git a/routing/control_tower_test.go b/routing/control_tower_test.go index 9fa5ec5b..d4399ced 100644 --- a/routing/control_tower_test.go +++ b/routing/control_tower_test.go @@ -298,7 +298,7 @@ func initDB() (*channeldb.DB, error) { return db, err } -func genInfo() (*channeldb.PaymentCreationInfo, *channeldb.PaymentAttemptInfo, +func genInfo() (*channeldb.PaymentCreationInfo, *channeldb.HTLCAttemptInfo, lntypes.Preimage, error) { preimage, err := genPreimage() @@ -314,8 +314,8 @@ func genInfo() (*channeldb.PaymentCreationInfo, *channeldb.PaymentAttemptInfo, CreationTime: time.Unix(time.Now().Unix(), 0), PaymentRequest: []byte("hola"), }, - &channeldb.PaymentAttemptInfo{ - PaymentID: 1, + &channeldb.HTLCAttemptInfo{ + AttemptID: 1, SessionKey: priv, Route: testRoute, }, preimage, nil diff --git a/routing/mock_test.go b/routing/mock_test.go index fac67aa9..a840d738 100644 --- a/routing/mock_test.go +++ b/routing/mock_test.go @@ -178,7 +178,7 @@ type initArgs struct { } type registerArgs struct { - a *channeldb.PaymentAttemptInfo + a *channeldb.HTLCAttemptInfo } type successArgs struct { @@ -238,7 +238,7 @@ func (m *mockControlTower) InitPayment(phash lntypes.Hash, } func (m *mockControlTower) RegisterAttempt(phash lntypes.Hash, - a *channeldb.PaymentAttemptInfo) error { + a *channeldb.HTLCAttemptInfo) error { m.Lock() defer m.Unlock() diff --git a/routing/payment_lifecycle.go b/routing/payment_lifecycle.go index 2283ca05..13d59370 100644 --- a/routing/payment_lifecycle.go +++ b/routing/payment_lifecycle.go @@ -35,7 +35,7 @@ type paymentLifecycle struct { timeoutChan <-chan time.Time currentHeight int32 finalCLTVDelta uint16 - attempt *channeldb.PaymentAttemptInfo + attempt *channeldb.HTLCAttemptInfo circuit *sphinx.Circuit lastError error } @@ -97,17 +97,17 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { // Now ask the switch to return the result of the payment when // available. resultChan, err := p.router.cfg.Payer.GetPaymentResult( - p.attempt.PaymentID, p.payment.PaymentHash, errorDecryptor, + p.attempt.AttemptID, p.payment.PaymentHash, errorDecryptor, ) switch { - // If this payment ID is unknown to the Switch, it means it was + // If this attempt ID is unknown to the Switch, it means it was // never checkpointed and forwarded by the switch before a // restart. In this case we can safely send a new payment // attempt, and wait for its result to be available. case err == htlcswitch.ErrPaymentIDNotFound: log.Debugf("Payment ID %v for hash %x not found in "+ - "the Switch, retrying.", p.attempt.PaymentID, + "the Switch, retrying.", p.attempt.AttemptID, p.payment.PaymentHash) // Reset the attempt to indicate we want to make a new @@ -117,8 +117,8 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { // A critical, unexpected error was encountered. case err != nil: - log.Errorf("Failed getting result for paymentID %d "+ - "from switch: %v", p.attempt.PaymentID, err) + log.Errorf("Failed getting result for attemptID %d "+ + "from switch: %v", p.attempt.AttemptID, err) return [32]byte{}, nil, err } @@ -161,11 +161,11 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) { // We successfully got a payment result back from the switch. log.Debugf("Payment %x succeeded with pid=%v", - p.payment.PaymentHash, p.attempt.PaymentID) + p.payment.PaymentHash, p.attempt.AttemptID) // Report success to mission control. err = p.router.cfg.MissionControl.ReportPaymentSuccess( - p.attempt.PaymentID, &p.attempt.Route, + p.attempt.AttemptID, &p.attempt.Route, ) if err != nil { log.Errorf("Error reporting payment success to mc: %v", @@ -331,21 +331,21 @@ func (p *paymentLifecycle) createNewPaymentAttempt() (lnwire.ShortChannelID, // We generate a new, unique payment ID that we will use for // this HTLC. - paymentID, err := p.router.cfg.NextPaymentID() + attemptID, err := p.router.cfg.NextPaymentID() if err != nil { return lnwire.ShortChannelID{}, nil, err } // We now have all the information needed to populate // the current attempt information. - p.attempt = &channeldb.PaymentAttemptInfo{ - PaymentID: paymentID, + p.attempt = &channeldb.HTLCAttemptInfo{ + AttemptID: attemptID, SessionKey: sessionKey, Route: *rt, } // Before sending this HTLC to the switch, we checkpoint the - // fresh paymentID and route to the DB. This lets us know on + // fresh attemptID and route to the DB. This lets us know on // startup the ID of the payment that we attempted to send, // such that we can query the Switch for its whereabouts. The // route is needed to handle the result when it eventually @@ -363,7 +363,7 @@ func (p *paymentLifecycle) sendPaymentAttempt(firstHop lnwire.ShortChannelID, htlcAdd *lnwire.UpdateAddHTLC) error { log.Tracef("Attempting to send payment %x (pid=%v), "+ - "using route: %v", p.payment.PaymentHash, p.attempt.PaymentID, + "using route: %v", p.payment.PaymentHash, p.attempt.AttemptID, newLogClosure(func() string { return spew.Sdump(p.attempt.Route) }), @@ -374,17 +374,17 @@ func (p *paymentLifecycle) sendPaymentAttempt(firstHop lnwire.ShortChannelID, // such that we can resume waiting for the result after a // restart. err := p.router.cfg.Payer.SendHTLC( - firstHop, p.attempt.PaymentID, htlcAdd, + firstHop, p.attempt.AttemptID, htlcAdd, ) if err != nil { log.Errorf("Failed sending attempt %d for payment "+ - "%x to switch: %v", p.attempt.PaymentID, + "%x to switch: %v", p.attempt.AttemptID, p.payment.PaymentHash, err) return err } log.Debugf("Payment %x (pid=%v) successfully sent to switch, route: %v", - p.payment.PaymentHash, p.attempt.PaymentID, &p.attempt.Route) + p.payment.PaymentHash, p.attempt.AttemptID, &p.attempt.Route) return nil } @@ -394,7 +394,7 @@ func (p *paymentLifecycle) sendPaymentAttempt(firstHop lnwire.ShortChannelID, func (p *paymentLifecycle) handleSendError(sendErr error) error { reason := p.router.processSendError( - p.attempt.PaymentID, &p.attempt.Route, sendErr, + p.attempt.AttemptID, &p.attempt.Route, sendErr, ) if reason == nil { // Save the forwarding error so it can be returned if diff --git a/routing/router.go b/routing/router.go index d30191b5..8dbb45de 100644 --- a/routing/router.go +++ b/routing/router.go @@ -1768,7 +1768,7 @@ func (r *ChannelRouter) SendToRoute(hash lntypes.Hash, route *route.Route) ( // router will call this method for every payment still in-flight according to // the ControlTower. func (r *ChannelRouter) sendPayment( - existingAttempt *channeldb.PaymentAttemptInfo, + existingAttempt *channeldb.HTLCAttemptInfo, payment *LightningPayment, paySession PaymentSession) ( [32]byte, *route.Route, error) {