From 06f045fca38ca28a809cec181d7d51d3d267626a Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Tue, 30 Mar 2021 14:53:29 +0200 Subject: [PATCH] channedb/mp_payment: add Hash to individual HTLCs For AMP payments the hash used for each HTLC will differ, and we will need to retrive it after a restart. We therefore persist it with each attempt. --- channeldb/mp_payment.go | 7 +++++++ channeldb/payments.go | 34 +++++++++++++++++++++++++++++++++- channeldb/payments_test.go | 5 ++++- routing/payment_lifecycle.go | 1 + 4 files changed, 45 insertions(+), 2 deletions(-) diff --git a/channeldb/mp_payment.go b/channeldb/mp_payment.go index 74a0ece8..4d14d504 100644 --- a/channeldb/mp_payment.go +++ b/channeldb/mp_payment.go @@ -29,6 +29,13 @@ type HTLCAttemptInfo struct { // AttemptTime is the time at which this HTLC was attempted. AttemptTime time.Time + + // Hash is the hash used for this single HTLC attempt. For AMP payments + // this will differ across attempts, for non-AMP payments each attempt + // will use the same hash. This can be nil for older payment attempts, + // in which the payment's PaymentHash in the PaymentCreationInfo should + // be used. + Hash *lntypes.Hash } // HTLCAttempt contains information about a specific HTLC attempt for a given diff --git a/channeldb/payments.go b/channeldb/payments.go index 7e659d05..2ffd76a0 100644 --- a/channeldb/payments.go +++ b/channeldb/payments.go @@ -926,7 +926,20 @@ func serializeHTLCAttemptInfo(w io.Writer, a *HTLCAttemptInfo) error { return err } - return serializeTime(w, a.AttemptTime) + if err := serializeTime(w, a.AttemptTime); err != nil { + return err + } + + // If the hash is nil we can just return. + if a.Hash == nil { + return nil + } + + if _, err := w.Write(a.Hash[:]); err != nil { + return err + } + + return nil } func deserializeHTLCAttemptInfo(r io.Reader) (*HTLCAttemptInfo, error) { @@ -935,6 +948,7 @@ func deserializeHTLCAttemptInfo(r io.Reader) (*HTLCAttemptInfo, error) { if err != nil { return nil, err } + a.Route, err = DeserializeRoute(r) if err != nil { return nil, err @@ -945,6 +959,24 @@ func deserializeHTLCAttemptInfo(r io.Reader) (*HTLCAttemptInfo, error) { return nil, err } + hash := lntypes.Hash{} + _, err = io.ReadFull(r, hash[:]) + + switch { + + // Older payment attempts wouldn't have the hash set, in which case we + // can just return. + case err == io.EOF, err == io.ErrUnexpectedEOF: + return a, nil + + case err != nil: + return nil, err + + default: + } + + a.Hash = &hash + return a, nil } diff --git a/channeldb/payments_test.go b/channeldb/payments_test.go index ca84613e..8974865a 100644 --- a/channeldb/payments_test.go +++ b/channeldb/payments_test.go @@ -57,8 +57,10 @@ func makeFakeInfo() (*PaymentCreationInfo, *HTLCAttemptInfo) { var preimg lntypes.Preimage copy(preimg[:], rev[:]) + hash := preimg.Hash() + c := &PaymentCreationInfo{ - PaymentHash: preimg.Hash(), + PaymentHash: hash, Value: 1000, // Use single second precision to avoid false positive test // failures due to the monotonic time component. @@ -71,6 +73,7 @@ func makeFakeInfo() (*PaymentCreationInfo, *HTLCAttemptInfo) { SessionKey: priv, Route: testRoute, AttemptTime: time.Unix(100, 0), + Hash: &hash, } return c, a } diff --git a/routing/payment_lifecycle.go b/routing/payment_lifecycle.go index 1760488a..7829b9d1 100644 --- a/routing/payment_lifecycle.go +++ b/routing/payment_lifecycle.go @@ -684,6 +684,7 @@ func (p *shardHandler) createNewPaymentAttempt(rt *route.Route, lastShard bool) AttemptTime: p.router.cfg.Clock.Now(), SessionKey: sessionKey, Route: *rt, + Hash: &hash, } return firstHop, htlcAdd, attempt, nil