channeldb: add MPPayment from FetchPayments
This commit is contained in:
parent
9e019407fb
commit
77602451b8
105
channeldb/mp_payment.go
Normal file
105
channeldb/mp_payment.go
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
package channeldb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/btcsuite/btcd/btcec"
|
||||||
|
"github.com/lightningnetwork/lnd/lntypes"
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
"github.com/lightningnetwork/lnd/routing/route"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MPPaymentCreationInfo is the information necessary to have ready when
|
||||||
|
// initiating a payment, moving it into state InFlight.
|
||||||
|
type MPPaymentCreationInfo struct {
|
||||||
|
// PaymentHash is the hash this payment is paying to.
|
||||||
|
PaymentHash lntypes.Hash
|
||||||
|
|
||||||
|
// Value is the amount we are paying.
|
||||||
|
Value lnwire.MilliSatoshi
|
||||||
|
|
||||||
|
// CreatingTime is the time at which this payment was started.
|
||||||
|
CreationTime time.Time
|
||||||
|
|
||||||
|
// PaymentRequest is the full payment request, if any.
|
||||||
|
PaymentRequest []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
||||||
|
// AttemptTime is the time at which this HTLC was attempted.
|
||||||
|
AttemptTime time.Time
|
||||||
|
|
||||||
|
// Settle is the preimage of a successful payment. This serves as a
|
||||||
|
// proof of payment. It will only be non-nil for settled payments.
|
||||||
|
//
|
||||||
|
// NOTE: Can be nil if payment is not settled.
|
||||||
|
Settle *HTLCSettleInfo
|
||||||
|
|
||||||
|
// Fail is a failure reason code indicating the reason the payment
|
||||||
|
// failed. It is only non-nil for failed payments.
|
||||||
|
//
|
||||||
|
// NOTE: Can be nil if payment is not failed.
|
||||||
|
Failure *HTLCFailInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
// HTLCSettleInfo encapsulates the information that augments an HTLCAttempt in
|
||||||
|
// the event that the HTLC is successful.
|
||||||
|
type HTLCSettleInfo struct {
|
||||||
|
// Preimage is the preimage of a successful HTLC. This serves as a proof
|
||||||
|
// of payment.
|
||||||
|
Preimage lntypes.Preimage
|
||||||
|
|
||||||
|
// SettleTime is the time at which this HTLC was settled.
|
||||||
|
SettleTime time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
// HTLCFailInfo encapsulates the information that augments an HTLCAttempt in the
|
||||||
|
// event that the HTLC fails.
|
||||||
|
type HTLCFailInfo struct {
|
||||||
|
// FailTime is the time at which this HTLC was failed.
|
||||||
|
FailTime time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
// MPPayment is a wrapper around a payment's MPPaymentCreationInfo and
|
||||||
|
// HTLCAttempts. All payments will have the MPPPaymentCreationInfo set, any
|
||||||
|
// HTLCs made in attempts to be completed will populated in the HTLCs slice.
|
||||||
|
// Each populated HTLCAttempt represents an attempted HTLC, each of which may
|
||||||
|
// have the associated Settle or Fail struct populated if the HTLC is no longer
|
||||||
|
// in-flight.
|
||||||
|
type MPPayment struct {
|
||||||
|
// sequenceNum is a unique identifier used to sort the payments in
|
||||||
|
// order of creation.
|
||||||
|
sequenceNum uint64
|
||||||
|
|
||||||
|
// Info holds all static information about this payment, and is
|
||||||
|
// populated when the payment is initiated.
|
||||||
|
Info *MPPaymentCreationInfo
|
||||||
|
|
||||||
|
// HTLCs holds the information about individual HTLCs that we send in
|
||||||
|
// order to make the payment.
|
||||||
|
HTLCs []HTLCAttempt
|
||||||
|
|
||||||
|
// FailureReason is the failure reason code indicating the reason the
|
||||||
|
// payment failed.
|
||||||
|
//
|
||||||
|
// NOTE: Will only be set once the daemon has given up on the payment
|
||||||
|
// altogether.
|
||||||
|
FailureReason *FailureReason
|
||||||
|
|
||||||
|
// Status is the current PaymentStatus of this payment.
|
||||||
|
Status PaymentStatus
|
||||||
|
}
|
@ -252,9 +252,70 @@ type Payment struct {
|
|||||||
Failure *FailureReason
|
Failure *FailureReason
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToMPPayment converts a legacy payment into an MPPayment.
|
||||||
|
func (p *Payment) ToMPPayment() *MPPayment {
|
||||||
|
var (
|
||||||
|
htlcs []HTLCAttempt
|
||||||
|
reason *FailureReason
|
||||||
|
settle *HTLCSettleInfo
|
||||||
|
failure *HTLCFailInfo
|
||||||
|
)
|
||||||
|
|
||||||
|
// Promote the payment failure to a proper fail struct, if it exists.
|
||||||
|
if p.Failure != nil {
|
||||||
|
// NOTE: FailTime is not set for legacy payments.
|
||||||
|
failure = &HTLCFailInfo{}
|
||||||
|
reason = p.Failure
|
||||||
|
}
|
||||||
|
|
||||||
|
// Promote the payment preimage to proper settle struct, if it exists.
|
||||||
|
if p.Preimage != nil {
|
||||||
|
// NOTE: SettleTime is not set for legacy payments.
|
||||||
|
settle = &HTLCSettleInfo{
|
||||||
|
Preimage: *p.Preimage,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Either a settle or a failure may be set, but not both.
|
||||||
|
if settle != nil && failure != nil {
|
||||||
|
panic("htlc attempt has both settle and failure info")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Populate a single HTLC on the MPPayment if an attempt exists on the
|
||||||
|
// legacy payment. If none exists we will leave the attempt info blank
|
||||||
|
// since we cannot recover it.
|
||||||
|
if p.Attempt != nil {
|
||||||
|
// 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,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &MPPayment{
|
||||||
|
sequenceNum: p.sequenceNum,
|
||||||
|
Info: &MPPaymentCreationInfo{
|
||||||
|
PaymentHash: p.Info.PaymentHash,
|
||||||
|
Value: p.Info.Value,
|
||||||
|
CreationTime: p.Info.CreationDate,
|
||||||
|
PaymentRequest: p.Info.PaymentRequest,
|
||||||
|
},
|
||||||
|
HTLCs: htlcs,
|
||||||
|
FailureReason: reason,
|
||||||
|
Status: p.Status,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// FetchPayments returns all sent payments found in the DB.
|
// FetchPayments returns all sent payments found in the DB.
|
||||||
func (db *DB) FetchPayments() ([]*Payment, error) {
|
//
|
||||||
var payments []*Payment
|
// nolint: dupl
|
||||||
|
func (db *DB) FetchPayments() ([]*MPPayment, error) {
|
||||||
|
var payments []*MPPayment
|
||||||
|
|
||||||
err := db.View(func(tx *bbolt.Tx) error {
|
err := db.View(func(tx *bbolt.Tx) error {
|
||||||
paymentsBucket := tx.Bucket(paymentsRootBucket)
|
paymentsBucket := tx.Bucket(paymentsRootBucket)
|
||||||
@ -276,7 +337,7 @@ func (db *DB) FetchPayments() ([]*Payment, error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
payments = append(payments, p)
|
payments = append(payments, p.ToMPPayment())
|
||||||
|
|
||||||
// For older versions of lnd, duplicate payments to a
|
// For older versions of lnd, duplicate payments to a
|
||||||
// payment has was possible. These will be found in a
|
// payment has was possible. These will be found in a
|
||||||
@ -301,7 +362,7 @@ func (db *DB) FetchPayments() ([]*Payment, error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
payments = append(payments, p)
|
payments = append(payments, p.ToMPPayment())
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -473,7 +534,7 @@ func deserializePaymentCreationInfo(r io.Reader) (*PaymentCreationInfo, error) {
|
|||||||
reqLen := uint32(byteOrder.Uint32(scratch[:4]))
|
reqLen := uint32(byteOrder.Uint32(scratch[:4]))
|
||||||
payReq := make([]byte, reqLen)
|
payReq := make([]byte, reqLen)
|
||||||
if reqLen > 0 {
|
if reqLen > 0 {
|
||||||
if _, err := io.ReadFull(r, payReq[:]); err != nil {
|
if _, err := io.ReadFull(r, payReq); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
31
rpcserver.go
31
rpcserver.go
@ -4348,24 +4348,29 @@ func (r *rpcServer) ListPayments(ctx context.Context,
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch the payment's route, which will be empty if an attempt
|
// Fetch the payment's route and preimage. If no HTLC was
|
||||||
// has not been made.
|
// successful, an empty route and preimage will be used.
|
||||||
var route route.Route
|
var (
|
||||||
if payment.Attempt != nil {
|
route route.Route
|
||||||
route = payment.Attempt.Route
|
preimage lntypes.Preimage
|
||||||
|
)
|
||||||
|
for _, htlc := range payment.HTLCs {
|
||||||
|
// Display the last route attempted.
|
||||||
|
route = htlc.Route
|
||||||
|
|
||||||
|
// If any of the htlcs have settled, extract a valid
|
||||||
|
// preimage.
|
||||||
|
if htlc.Settle != nil {
|
||||||
|
preimage = htlc.Settle.Preimage
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Encode the hops from the successful route, if any.
|
||||||
path := make([]string, len(route.Hops))
|
path := make([]string, len(route.Hops))
|
||||||
for i, hop := range route.Hops {
|
for i, hop := range route.Hops {
|
||||||
path[i] = hex.EncodeToString(hop.PubKeyBytes[:])
|
path[i] = hex.EncodeToString(hop.PubKeyBytes[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch the preimage if the payment was successful, otherwise a
|
|
||||||
// zero-value preimage will be used.
|
|
||||||
var preimage lntypes.Preimage
|
|
||||||
if payment.Preimage != nil {
|
|
||||||
preimage = *payment.Preimage
|
|
||||||
}
|
|
||||||
|
|
||||||
msatValue := int64(payment.Info.Value)
|
msatValue := int64(payment.Info.Value)
|
||||||
satValue := int64(payment.Info.Value.ToSatoshis())
|
satValue := int64(payment.Info.Value.ToSatoshis())
|
||||||
|
|
||||||
@ -4380,7 +4385,7 @@ func (r *rpcServer) ListPayments(ctx context.Context,
|
|||||||
Value: satValue,
|
Value: satValue,
|
||||||
ValueMsat: msatValue,
|
ValueMsat: msatValue,
|
||||||
ValueSat: satValue,
|
ValueSat: satValue,
|
||||||
CreationDate: payment.Info.CreationDate.Unix(),
|
CreationDate: payment.Info.CreationTime.Unix(),
|
||||||
Path: path,
|
Path: path,
|
||||||
Fee: int64(route.TotalFees().ToSatoshis()),
|
Fee: int64(route.TotalFees().ToSatoshis()),
|
||||||
FeeSat: int64(route.TotalFees().ToSatoshis()),
|
FeeSat: int64(route.TotalFees().ToSatoshis()),
|
||||||
|
Loading…
Reference in New Issue
Block a user