Merge pull request #3499 from cfromknecht/mpp-payments-rpc
channeldb+rpcserver: expose legacy payments as multi-path payments
This commit is contained in:
16 files changed
+1377
-831
No files matched your search
@@ -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
|
||||||
|
}
|
||||||
@@ -8,7 +8,6 @@ import (
|
|||||||
|
|
||||||
"github.com/coreos/bbolt"
|
"github.com/coreos/bbolt"
|
||||||
"github.com/lightningnetwork/lnd/lntypes"
|
"github.com/lightningnetwork/lnd/lntypes"
|
||||||
"github.com/lightningnetwork/lnd/routing/route"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -192,16 +191,17 @@ func (p *PaymentControl) RegisterAttempt(paymentHash lntypes.Hash,
|
|||||||
// duplicate payments to the same payment hash. The provided preimage is
|
// duplicate payments to the same payment hash. The provided preimage is
|
||||||
// atomically saved to the DB for record keeping.
|
// atomically saved to the DB for record keeping.
|
||||||
func (p *PaymentControl) Success(paymentHash lntypes.Hash,
|
func (p *PaymentControl) Success(paymentHash lntypes.Hash,
|
||||||
preimage lntypes.Preimage) (*route.Route, error) {
|
preimage lntypes.Preimage) (*MPPayment, error) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
updateErr error
|
updateErr error
|
||||||
route *route.Route
|
payment *MPPayment
|
||||||
)
|
)
|
||||||
err := p.db.Batch(func(tx *bbolt.Tx) error {
|
err := p.db.Batch(func(tx *bbolt.Tx) error {
|
||||||
// Reset the update error, to avoid carrying over an error
|
// Reset the update error, to avoid carrying over an error
|
||||||
// from a previous execution of the batched db transaction.
|
// from a previous execution of the batched db transaction.
|
||||||
updateErr = nil
|
updateErr = nil
|
||||||
|
payment = nil
|
||||||
|
|
||||||
bucket, err := fetchPaymentBucket(tx, paymentHash)
|
bucket, err := fetchPaymentBucket(tx, paymentHash)
|
||||||
if err == ErrPaymentNotInitiated {
|
if err == ErrPaymentNotInitiated {
|
||||||
@@ -225,20 +225,14 @@ func (p *PaymentControl) Success(paymentHash lntypes.Hash,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve attempt info for the notification.
|
// Retrieve attempt info for the notification.
|
||||||
attempt, err := fetchPaymentAttempt(bucket)
|
payment, err = fetchPayment(bucket)
|
||||||
if err != nil {
|
return err
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
route = &attempt.Route
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return route, updateErr
|
return payment, updateErr
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fail transitions a payment into the Failed state, and records the reason the
|
// Fail transitions a payment into the Failed state, and records the reason the
|
||||||
@@ -246,16 +240,17 @@ func (p *PaymentControl) Success(paymentHash lntypes.Hash,
|
|||||||
// its next call for this payment hash, allowing the switch to make a
|
// its next call for this payment hash, allowing the switch to make a
|
||||||
// subsequent payment.
|
// subsequent payment.
|
||||||
func (p *PaymentControl) Fail(paymentHash lntypes.Hash,
|
func (p *PaymentControl) Fail(paymentHash lntypes.Hash,
|
||||||
reason FailureReason) (*route.Route, error) {
|
reason FailureReason) (*MPPayment, error) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
updateErr error
|
updateErr error
|
||||||
route *route.Route
|
payment *MPPayment
|
||||||
)
|
)
|
||||||
err := p.db.Batch(func(tx *bbolt.Tx) error {
|
err := p.db.Batch(func(tx *bbolt.Tx) error {
|
||||||
// Reset the update error, to avoid carrying over an error
|
// Reset the update error, to avoid carrying over an error
|
||||||
// from a previous execution of the batched db transaction.
|
// from a previous execution of the batched db transaction.
|
||||||
updateErr = nil
|
updateErr = nil
|
||||||
|
payment = nil
|
||||||
|
|
||||||
bucket, err := fetchPaymentBucket(tx, paymentHash)
|
bucket, err := fetchPaymentBucket(tx, paymentHash)
|
||||||
if err == ErrPaymentNotInitiated {
|
if err == ErrPaymentNotInitiated {
|
||||||
@@ -279,28 +274,21 @@ func (p *PaymentControl) Fail(paymentHash lntypes.Hash,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve attempt info for the notification, if available.
|
// Retrieve attempt info for the notification, if available.
|
||||||
attempt, err := fetchPaymentAttempt(bucket)
|
payment, err = fetchPayment(bucket)
|
||||||
if err != nil && err != errNoAttemptInfo {
|
return err
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err != errNoAttemptInfo {
|
|
||||||
route = &attempt.Route
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return route, updateErr
|
return payment, updateErr
|
||||||
}
|
}
|
||||||
|
|
||||||
// FetchPayment returns information about a payment from the database.
|
// FetchPayment returns information about a payment from the database.
|
||||||
func (p *PaymentControl) FetchPayment(paymentHash lntypes.Hash) (
|
func (p *PaymentControl) FetchPayment(paymentHash lntypes.Hash) (
|
||||||
*Payment, error) {
|
*MPPayment, error) {
|
||||||
|
|
||||||
var payment *Payment
|
var payment *MPPayment
|
||||||
err := p.db.View(func(tx *bbolt.Tx) error {
|
err := p.db.View(func(tx *bbolt.Tx) error {
|
||||||
bucket, err := fetchPaymentBucket(tx, paymentHash)
|
bucket, err := fetchPaymentBucket(tx, paymentHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import (
|
|||||||
"github.com/coreos/bbolt"
|
"github.com/coreos/bbolt"
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/lightningnetwork/lnd/lntypes"
|
"github.com/lightningnetwork/lnd/lntypes"
|
||||||
"github.com/lightningnetwork/lnd/routing/route"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func initDB() (*DB, error) {
|
func initDB() (*DB, error) {
|
||||||
@@ -132,16 +131,22 @@ func TestPaymentControlSwitchFail(t *testing.T) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Verifies that status was changed to StatusSucceeded.
|
// Verifies that status was changed to StatusSucceeded.
|
||||||
var route *route.Route
|
var payment *MPPayment
|
||||||
route, err = pControl.Success(info.PaymentHash, preimg)
|
payment, err = pControl.Success(info.PaymentHash, preimg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error shouldn't have been received, got: %v", err)
|
t.Fatalf("error shouldn't have been received, got: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = assertRouteEqual(route, &attempt.Route)
|
if len(payment.HTLCs) != 1 {
|
||||||
|
t.Fatalf("payment should have one htlc, got: %d",
|
||||||
|
len(payment.HTLCs))
|
||||||
|
}
|
||||||
|
|
||||||
|
err = assertRouteEqual(&payment.HTLCs[0].Route, &attempt.Route)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected route returned: %v vs %v: %v",
|
t.Fatalf("unexpected route returned: %v vs %v: %v",
|
||||||
spew.Sdump(attempt.Route), spew.Sdump(*route), err)
|
spew.Sdump(attempt.Route),
|
||||||
|
spew.Sdump(payment.HTLCs[0].Route), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
assertPaymentStatus(t, db, info.PaymentHash, StatusSucceeded)
|
assertPaymentStatus(t, db, info.PaymentHash, StatusSucceeded)
|
||||||
|
|||||||
+74
-13
@@ -101,9 +101,9 @@ const (
|
|||||||
// payment.
|
// payment.
|
||||||
FailureReasonError FailureReason = 2
|
FailureReasonError FailureReason = 2
|
||||||
|
|
||||||
// FailureReasonIncorrectPaymentDetails indicates that either the hash
|
// FailureReasonPaymentDetails indicates that either the hash is unknown
|
||||||
// is unknown or the final cltv delta or amount is incorrect.
|
// or the final cltv delta or amount is incorrect.
|
||||||
FailureReasonIncorrectPaymentDetails FailureReason = 3
|
FailureReasonPaymentDetails FailureReason = 3
|
||||||
|
|
||||||
// TODO(halseth): cancel state.
|
// TODO(halseth): cancel state.
|
||||||
|
|
||||||
@@ -120,7 +120,7 @@ func (r FailureReason) String() string {
|
|||||||
return "no_route"
|
return "no_route"
|
||||||
case FailureReasonError:
|
case FailureReasonError:
|
||||||
return "error"
|
return "error"
|
||||||
case FailureReasonIncorrectPaymentDetails:
|
case FailureReasonPaymentDetails:
|
||||||
return "incorrect_payment_details"
|
return "incorrect_payment_details"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,11 +239,11 @@ type Payment struct {
|
|||||||
// NOTE: Can be nil if no attempt is yet made.
|
// NOTE: Can be nil if no attempt is yet made.
|
||||||
Attempt *PaymentAttemptInfo
|
Attempt *PaymentAttemptInfo
|
||||||
|
|
||||||
// PaymentPreimage is the preimage of a successful payment. This serves
|
// Preimage is the preimage of a successful payment. This serves as a
|
||||||
// as a proof of payment. It will only be non-nil for settled payments.
|
// proof of payment. It will only be non-nil for settled payments.
|
||||||
//
|
//
|
||||||
// NOTE: Can be nil if payment is not settled.
|
// NOTE: Can be nil if payment is not settled.
|
||||||
PaymentPreimage *lntypes.Preimage
|
Preimage *lntypes.Preimage
|
||||||
|
|
||||||
// Failure is a failure reason code indicating the reason the payment
|
// Failure is a failure reason code indicating the reason the payment
|
||||||
// failed. It is only non-nil for failed payments.
|
// failed. It is only non-nil for failed payments.
|
||||||
@@ -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)
|
||||||
@@ -318,7 +379,7 @@ func (db *DB) FetchPayments() ([]*Payment, error) {
|
|||||||
return payments, nil
|
return payments, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchPayment(bucket *bbolt.Bucket) (*Payment, error) {
|
func fetchPayment(bucket *bbolt.Bucket) (*MPPayment, error) {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
p = &Payment{}
|
p = &Payment{}
|
||||||
@@ -363,7 +424,7 @@ func fetchPayment(bucket *bbolt.Bucket) (*Payment, error) {
|
|||||||
if b != nil {
|
if b != nil {
|
||||||
var preimg lntypes.Preimage
|
var preimg lntypes.Preimage
|
||||||
copy(preimg[:], b[:])
|
copy(preimg[:], b[:])
|
||||||
p.PaymentPreimage = &preimg
|
p.Preimage = &preimg
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get failure reason if available.
|
// Get failure reason if available.
|
||||||
@@ -373,7 +434,7 @@ func fetchPayment(bucket *bbolt.Bucket) (*Payment, error) {
|
|||||||
p.Failure = &reason
|
p.Failure = &reason
|
||||||
}
|
}
|
||||||
|
|
||||||
return p, nil
|
return p.ToMPPayment(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeletePayments deletes all completed and failed payments from the DB.
|
// DeletePayments deletes all completed and failed payments from the DB.
|
||||||
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+136
-125
@@ -422,10 +422,13 @@ type PaymentStatus struct {
|
|||||||
Preimage []byte `protobuf:"bytes,2,opt,name=preimage,proto3" json:"preimage,omitempty"`
|
Preimage []byte `protobuf:"bytes,2,opt,name=preimage,proto3" json:"preimage,omitempty"`
|
||||||
//*
|
//*
|
||||||
//The taken route when state is SUCCEEDED.
|
//The taken route when state is SUCCEEDED.
|
||||||
Route *lnrpc.Route `protobuf:"bytes,3,opt,name=route,proto3" json:"route,omitempty"`
|
Route *lnrpc.Route `protobuf:"bytes,3,opt,name=route,proto3" json:"route,omitempty"`
|
||||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
//*
|
||||||
XXX_unrecognized []byte `json:"-"`
|
//The HTLCs made in attempt to settle the payment [EXPERIMENTAL].
|
||||||
XXX_sizecache int32 `json:"-"`
|
Htlcs []*lnrpc.HTLCAttempt `protobuf:"bytes,4,rep,name=htlcs,proto3" json:"htlcs,omitempty"`
|
||||||
|
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||||
|
XXX_unrecognized []byte `json:"-"`
|
||||||
|
XXX_sizecache int32 `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PaymentStatus) Reset() { *m = PaymentStatus{} }
|
func (m *PaymentStatus) Reset() { *m = PaymentStatus{} }
|
||||||
@@ -474,6 +477,13 @@ func (m *PaymentStatus) GetRoute() *lnrpc.Route {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *PaymentStatus) GetHtlcs() []*lnrpc.HTLCAttempt {
|
||||||
|
if m != nil {
|
||||||
|
return m.Htlcs
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type RouteFeeRequest struct {
|
type RouteFeeRequest struct {
|
||||||
//*
|
//*
|
||||||
//The destination once wishes to obtain a routing fee quote to.
|
//The destination once wishes to obtain a routing fee quote to.
|
||||||
@@ -1455,131 +1465,132 @@ func init() {
|
|||||||
func init() { proto.RegisterFile("routerrpc/router.proto", fileDescriptor_7a0613f69d37b0a5) }
|
func init() { proto.RegisterFile("routerrpc/router.proto", fileDescriptor_7a0613f69d37b0a5) }
|
||||||
|
|
||||||
var fileDescriptor_7a0613f69d37b0a5 = []byte{
|
var fileDescriptor_7a0613f69d37b0a5 = []byte{
|
||||||
// 1975 bytes of a gzipped FileDescriptorProto
|
// 1993 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x58, 0x4f, 0x73, 0x1a, 0xc9,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x58, 0x4f, 0x73, 0x1a, 0xc9,
|
||||||
0x15, 0xdf, 0x11, 0x20, 0xe0, 0x01, 0xd2, 0xa8, 0xa5, 0x95, 0xc7, 0x48, 0x5a, 0x6b, 0xc7, 0x8e,
|
0x15, 0xdf, 0x11, 0x20, 0xe0, 0x01, 0xd2, 0xa8, 0xa5, 0x95, 0xc7, 0x48, 0x5a, 0x6b, 0xc7, 0x8e,
|
||||||
0x57, 0xe5, 0xf2, 0x4a, 0x8e, 0x52, 0xbb, 0xe5, 0xda, 0x43, 0x52, 0x18, 0x86, 0xd5, 0xc8, 0x30,
|
0x57, 0xe5, 0xf2, 0x4a, 0x8e, 0x52, 0xbb, 0xe5, 0xda, 0x43, 0x52, 0x18, 0x86, 0xd5, 0xc8, 0x30,
|
||||||
0xc8, 0x0d, 0x78, 0xd7, 0xd9, 0x43, 0x57, 0x0b, 0x5a, 0x62, 0x4a, 0xc3, 0x0c, 0x3b, 0xd3, 0x38,
|
0xc8, 0x0d, 0x78, 0xd7, 0xd9, 0x43, 0x57, 0x0b, 0x5a, 0x62, 0x4a, 0xc3, 0x0c, 0x3b, 0xd3, 0x38,
|
||||||
0x56, 0x0e, 0xf9, 0x04, 0xc9, 0x35, 0x5f, 0x21, 0x97, 0xe4, 0x94, 0xef, 0x94, 0x54, 0xe5, 0x9e,
|
0x56, 0x3e, 0x43, 0x72, 0xcd, 0x57, 0x48, 0x0e, 0xc9, 0x29, 0xdf, 0x29, 0xa9, 0xca, 0x3d, 0xf7,
|
||||||
0x7b, 0xaa, 0xbb, 0x67, 0x60, 0x40, 0x48, 0x9b, 0x93, 0xe8, 0xdf, 0x7b, 0xfd, 0x5e, 0xcf, 0xfb,
|
0x54, 0x77, 0xcf, 0xc0, 0x80, 0x90, 0x36, 0x27, 0xa6, 0x7f, 0xef, 0x75, 0xbf, 0xee, 0xf7, 0xe7,
|
||||||
0xf3, 0xeb, 0xd7, 0x82, 0xdd, 0x30, 0x98, 0x72, 0x16, 0x86, 0x93, 0xc1, 0x89, 0xfa, 0x75, 0x3c,
|
0xd7, 0xaf, 0x81, 0xdd, 0x30, 0x98, 0x72, 0x16, 0x86, 0x93, 0xc1, 0x89, 0xfa, 0x3a, 0x9e, 0x84,
|
||||||
0x09, 0x03, 0x1e, 0xa0, 0xe2, 0x0c, 0xaf, 0x16, 0xc3, 0xc9, 0x40, 0xa1, 0xe6, 0x7f, 0xb2, 0x80,
|
0x01, 0x0f, 0x50, 0x71, 0x86, 0x57, 0x8b, 0xe1, 0x64, 0xa0, 0x50, 0xf3, 0x3f, 0x59, 0x40, 0x5d,
|
||||||
0xba, 0xcc, 0x1f, 0x5e, 0xd0, 0xdb, 0x31, 0xf3, 0x39, 0x66, 0x3f, 0x4f, 0x59, 0xc4, 0x11, 0x82,
|
0xe6, 0x0f, 0x2f, 0xe8, 0xed, 0x98, 0xf9, 0x1c, 0xb3, 0x9f, 0xa7, 0x2c, 0xe2, 0x08, 0x41, 0x76,
|
||||||
0xec, 0x90, 0x45, 0xdc, 0xd0, 0x0e, 0xb5, 0xa3, 0x32, 0x96, 0xbf, 0x91, 0x0e, 0x19, 0x3a, 0xe6,
|
0xc8, 0x22, 0x6e, 0x68, 0x87, 0xda, 0x51, 0x19, 0xcb, 0x6f, 0xa4, 0x43, 0x86, 0x8e, 0xb9, 0xb1,
|
||||||
0xc6, 0xda, 0xa1, 0x76, 0x94, 0xc1, 0xe2, 0x27, 0x7a, 0x0c, 0x05, 0x3a, 0xe6, 0x64, 0x1c, 0x51,
|
0x76, 0xa8, 0x1d, 0x65, 0xb0, 0xf8, 0x44, 0x8f, 0xa1, 0x40, 0xc7, 0x9c, 0x8c, 0x23, 0xca, 0x8d,
|
||||||
0x6e, 0x94, 0x25, 0x9c, 0xa7, 0x63, 0xde, 0x8e, 0x28, 0x47, 0x5f, 0x42, 0x79, 0xa2, 0x4c, 0x92,
|
0xb2, 0x84, 0xf3, 0x74, 0xcc, 0xdb, 0x11, 0xe5, 0xe8, 0x4b, 0x28, 0x4f, 0xd4, 0x92, 0x64, 0x44,
|
||||||
0x11, 0x8d, 0x46, 0x46, 0x46, 0x1a, 0x2a, 0xc5, 0xd8, 0x19, 0x8d, 0x46, 0xe8, 0x08, 0xf4, 0x2b,
|
0xa3, 0x91, 0x91, 0x91, 0x0b, 0x95, 0x62, 0xec, 0x8c, 0x46, 0x23, 0x74, 0x04, 0xfa, 0x95, 0xeb,
|
||||||
0xd7, 0xa7, 0x1e, 0x19, 0x78, 0xfc, 0x23, 0x19, 0x32, 0x8f, 0x53, 0x23, 0x7b, 0xa8, 0x1d, 0xe5,
|
0x53, 0x8f, 0x0c, 0x3c, 0xfe, 0x91, 0x0c, 0x99, 0xc7, 0xa9, 0x91, 0x3d, 0xd4, 0x8e, 0x72, 0x78,
|
||||||
0xf0, 0x86, 0xc4, 0xeb, 0x1e, 0xff, 0xd8, 0x10, 0x28, 0xfa, 0x0a, 0x36, 0x13, 0x63, 0xa1, 0x3a,
|
0x43, 0xe2, 0x75, 0x8f, 0x7f, 0x6c, 0x08, 0x14, 0x7d, 0x05, 0x9b, 0xc9, 0x62, 0xa1, 0xda, 0xa0,
|
||||||
0xa0, 0x91, 0x3b, 0xd4, 0x8e, 0x8a, 0x78, 0x63, 0xb2, 0x78, 0xec, 0xaf, 0x60, 0x93, 0xbb, 0x63,
|
0x91, 0x3b, 0xd4, 0x8e, 0x8a, 0x78, 0x63, 0xb2, 0xb8, 0xed, 0xaf, 0x60, 0x93, 0xbb, 0x63, 0x16,
|
||||||
0x16, 0x4c, 0x39, 0x89, 0xd8, 0x20, 0xf0, 0x87, 0x91, 0xb1, 0xae, 0x2c, 0xc6, 0x70, 0x57, 0xa1,
|
0x4c, 0x39, 0x89, 0xd8, 0x20, 0xf0, 0x87, 0x91, 0xb1, 0xae, 0x56, 0x8c, 0xe1, 0xae, 0x42, 0x91,
|
||||||
0xc8, 0x84, 0xca, 0x15, 0x63, 0xc4, 0x73, 0xc7, 0x2e, 0x27, 0xe2, 0xf8, 0x79, 0x79, 0xfc, 0xd2,
|
0x09, 0x95, 0x2b, 0xc6, 0x88, 0xe7, 0x8e, 0x5d, 0x4e, 0xc4, 0xf6, 0xf3, 0x72, 0xfb, 0xa5, 0x2b,
|
||||||
0x15, 0x63, 0x2d, 0x81, 0x75, 0x29, 0x47, 0xcf, 0x60, 0x63, 0xae, 0x23, 0xbf, 0xb1, 0x22, 0x95,
|
0xc6, 0x5a, 0x02, 0xeb, 0x52, 0x8e, 0x9e, 0xc1, 0xc6, 0x5c, 0x47, 0x9e, 0xb1, 0x22, 0x95, 0xca,
|
||||||
0xca, 0x89, 0x92, 0xfc, 0xd0, 0x97, 0xa0, 0x07, 0x53, 0x7e, 0x1d, 0xb8, 0xfe, 0x35, 0x19, 0x8c,
|
0x89, 0x92, 0x3c, 0xe8, 0x4b, 0xd0, 0x83, 0x29, 0xbf, 0x0e, 0x5c, 0xff, 0x9a, 0x0c, 0x46, 0xd4,
|
||||||
0xa8, 0x4f, 0xdc, 0xa1, 0x51, 0x38, 0xd4, 0x8e, 0xb2, 0x6f, 0xd6, 0x5e, 0x69, 0x78, 0x23, 0x91,
|
0x27, 0xee, 0xd0, 0x28, 0x1c, 0x6a, 0x47, 0xd9, 0x37, 0x6b, 0xaf, 0x34, 0xbc, 0x91, 0xc8, 0xea,
|
||||||
0xd5, 0x47, 0xd4, 0xb7, 0x87, 0xe8, 0x39, 0x6c, 0x7a, 0x34, 0xe2, 0x64, 0x14, 0x4c, 0xc8, 0x64,
|
0x23, 0xea, 0xdb, 0x43, 0xf4, 0x1c, 0x36, 0x3d, 0x1a, 0x71, 0x32, 0x0a, 0x26, 0x64, 0x32, 0xbd,
|
||||||
0x7a, 0x79, 0xc3, 0x6e, 0x8d, 0x0d, 0x19, 0x99, 0x8a, 0x80, 0xcf, 0x82, 0xc9, 0x85, 0x04, 0xd1,
|
0xbc, 0x61, 0xb7, 0xc6, 0x86, 0xf4, 0x4c, 0x45, 0xc0, 0x67, 0xc1, 0xe4, 0x42, 0x82, 0xe8, 0x00,
|
||||||
0x01, 0x80, 0x8c, 0x8a, 0x74, 0x6e, 0x14, 0xe5, 0x37, 0x14, 0x05, 0x22, 0x1d, 0xa3, 0x53, 0x28,
|
0x40, 0x7a, 0x45, 0x1a, 0x37, 0x8a, 0xf2, 0x0c, 0x45, 0x81, 0x48, 0xc3, 0xe8, 0x14, 0x4a, 0x32,
|
||||||
0xc9, 0x6c, 0x92, 0x91, 0xeb, 0xf3, 0xc8, 0x80, 0xc3, 0xcc, 0x51, 0xe9, 0x54, 0x3f, 0xf6, 0x7c,
|
0x9a, 0x64, 0xe4, 0xfa, 0x3c, 0x32, 0xe0, 0x30, 0x73, 0x54, 0x3a, 0xd5, 0x8f, 0x3d, 0x5f, 0x04,
|
||||||
0x91, 0x58, 0x2c, 0x24, 0x67, 0xae, 0xcf, 0x71, 0x5a, 0x09, 0x59, 0x50, 0x10, 0x69, 0x24, 0xdc,
|
0x16, 0x0b, 0xc9, 0x99, 0xeb, 0x73, 0x9c, 0x56, 0x42, 0x16, 0x14, 0x44, 0x18, 0x09, 0xf7, 0x3e,
|
||||||
0xfb, 0x68, 0x94, 0xe4, 0x86, 0x17, 0xc7, 0xb3, 0x92, 0x38, 0xbe, 0x5b, 0x03, 0xc7, 0x0d, 0x16,
|
0x1a, 0x25, 0x39, 0xe1, 0xc5, 0xf1, 0x2c, 0x25, 0x8e, 0xef, 0xe6, 0xc0, 0x71, 0x83, 0x45, 0xbc,
|
||||||
0xf1, 0x9e, 0xf7, 0xd1, 0xf2, 0x79, 0x78, 0x8b, 0xf3, 0x43, 0xb5, 0xaa, 0x7e, 0x07, 0xe5, 0xb4,
|
0xe7, 0x7d, 0xb4, 0x7c, 0x1e, 0xde, 0xe2, 0xfc, 0x50, 0x8d, 0xaa, 0xdf, 0x41, 0x39, 0x2d, 0x10,
|
||||||
0x40, 0x54, 0x85, 0xf8, 0x0a, 0x51, 0x28, 0x59, 0x2c, 0x7e, 0xa2, 0x1d, 0xc8, 0x7d, 0xa4, 0xde,
|
0x59, 0x21, 0x4e, 0x21, 0x12, 0x25, 0x8b, 0xc5, 0x27, 0xda, 0x81, 0xdc, 0x47, 0xea, 0x4d, 0x99,
|
||||||
0x94, 0xc9, 0x4a, 0x29, 0x63, 0xb5, 0xf8, 0x6e, 0xed, 0xb5, 0x66, 0xbe, 0x86, 0xed, 0x5e, 0x48,
|
0xcc, 0x94, 0x32, 0x56, 0x83, 0xef, 0xd6, 0x5e, 0x6b, 0xe6, 0x6b, 0xd8, 0xee, 0x85, 0x74, 0x70,
|
||||||
0x07, 0x37, 0x4b, 0xc5, 0xb6, 0x5c, 0x2b, 0xda, 0x9d, 0x5a, 0x31, 0xff, 0x04, 0x95, 0x78, 0x53,
|
0xb3, 0x94, 0x6c, 0xcb, 0xb9, 0xa2, 0xdd, 0xc9, 0x15, 0xf3, 0x6f, 0x1a, 0x54, 0xe2, 0x59, 0x5d,
|
||||||
0x97, 0x53, 0x3e, 0x8d, 0xd0, 0xd7, 0x90, 0x8b, 0x38, 0xe5, 0x4c, 0x2a, 0x6f, 0x9c, 0x3e, 0x4a,
|
0x4e, 0xf9, 0x34, 0x42, 0x5f, 0x43, 0x2e, 0xe2, 0x94, 0x33, 0xa9, 0xbd, 0x71, 0xfa, 0x28, 0x75,
|
||||||
0x7d, 0x4a, 0x4a, 0x91, 0x61, 0xa5, 0x85, 0xaa, 0x50, 0x98, 0x84, 0xcc, 0x1d, 0xd3, 0xeb, 0xe4,
|
0x96, 0x94, 0x22, 0xc3, 0x4a, 0x0b, 0x55, 0xa1, 0x30, 0x09, 0x99, 0x3b, 0xa6, 0xd7, 0xc9, 0xbe,
|
||||||
0x58, 0xb3, 0x35, 0x32, 0x21, 0x27, 0x37, 0xcb, 0x1a, 0x2d, 0x9d, 0x96, 0xd3, 0x61, 0xc4, 0x4a,
|
0x66, 0x63, 0x64, 0x42, 0x4e, 0x4e, 0x96, 0x49, 0x5a, 0x3a, 0x2d, 0xa7, 0xfd, 0x88, 0x95, 0x08,
|
||||||
0x64, 0xfe, 0x16, 0x36, 0xe5, 0xba, 0xc9, 0xd8, 0x43, 0x2d, 0xf2, 0x08, 0x44, 0x03, 0xc8, 0x82,
|
0x1d, 0x41, 0x6e, 0xc4, 0xbd, 0x41, 0x64, 0x64, 0xa5, 0xeb, 0x50, 0xac, 0x73, 0xd6, 0x6b, 0xd5,
|
||||||
0x52, 0x6d, 0xb2, 0x4e, 0xc7, 0xa2, 0x96, 0xcc, 0x21, 0xe8, 0xf3, 0xfd, 0xd1, 0x24, 0xf0, 0x23,
|
0x6b, 0x9c, 0xb3, 0xf1, 0x84, 0x63, 0xa5, 0x60, 0xfe, 0x16, 0x36, 0xe5, 0xcc, 0x26, 0x63, 0x0f,
|
||||||
0x26, 0xea, 0x5f, 0x18, 0x17, 0x85, 0x23, 0xea, 0x4c, 0x56, 0x98, 0x26, 0x77, 0x6d, 0xc4, 0x78,
|
0x55, 0xd3, 0x23, 0x10, 0xb5, 0x22, 0x73, 0x4f, 0x55, 0xd4, 0x3a, 0x1d, 0x8b, 0xb4, 0x33, 0x87,
|
||||||
0x93, 0x31, 0x59, 0x63, 0xcf, 0x55, 0x59, 0x13, 0x2f, 0x18, 0xdc, 0x88, 0x46, 0xa1, 0xb7, 0xb1,
|
0xa0, 0xcf, 0xe7, 0x47, 0x93, 0xc0, 0x8f, 0x84, 0x75, 0x5d, 0x6c, 0x43, 0xe4, 0x98, 0x48, 0x49,
|
||||||
0xf9, 0x8a, 0x80, 0x5b, 0xc1, 0xe0, 0xa6, 0x21, 0x40, 0xf3, 0x27, 0xd5, 0xcb, 0xbd, 0x40, 0x9d,
|
0x99, 0x8c, 0x9a, 0x9c, 0xb5, 0x11, 0xe3, 0x4d, 0xc6, 0x64, 0x3a, 0x3e, 0x57, 0x15, 0x40, 0xbc,
|
||||||
0xfd, 0xff, 0x0e, 0xef, 0x3c, 0x04, 0x6b, 0xf7, 0x87, 0x80, 0xc0, 0xf6, 0x82, 0xf1, 0xf8, 0x2b,
|
0x60, 0x70, 0x23, 0x6a, 0x8a, 0xde, 0xc6, 0xcb, 0x57, 0x04, 0xdc, 0x0a, 0x06, 0x37, 0x0d, 0x01,
|
||||||
0xd2, 0x91, 0xd5, 0x96, 0x22, 0xfb, 0x12, 0xf2, 0x57, 0xd4, 0xf5, 0xa6, 0x61, 0x62, 0x18, 0xa5,
|
0x9a, 0x3f, 0xa9, 0xb2, 0xef, 0x05, 0xea, 0x94, 0xff, 0x77, 0x24, 0xe6, 0xce, 0x5a, 0xbb, 0xd7,
|
||||||
0xd2, 0xd4, 0x54, 0x12, 0x9c, 0xa8, 0x98, 0xff, 0xcd, 0x43, 0x3e, 0x06, 0xd1, 0x29, 0x64, 0x07,
|
0x59, 0x26, 0x81, 0xed, 0x85, 0xc5, 0xe3, 0x53, 0xa4, 0x63, 0xa0, 0x2d, 0xc5, 0xe0, 0x25, 0xe4,
|
||||||
0xc1, 0x30, 0xc9, 0xee, 0x17, 0x77, 0xb7, 0x25, 0x7f, 0xeb, 0xc1, 0x90, 0x61, 0xa9, 0x8b, 0x7e,
|
0xaf, 0xa8, 0xeb, 0x4d, 0xc3, 0x64, 0x61, 0x94, 0x0a, 0x68, 0x53, 0x49, 0x70, 0xa2, 0x62, 0xfe,
|
||||||
0x07, 0x1b, 0xa2, 0x01, 0x7d, 0xe6, 0x91, 0xe9, 0x64, 0x48, 0x67, 0x09, 0x35, 0x52, 0xbb, 0xeb,
|
0x37, 0x0f, 0xf9, 0x18, 0x44, 0xa7, 0x90, 0x1d, 0x04, 0xc3, 0x24, 0x0f, 0xbe, 0xb8, 0x3b, 0x2d,
|
||||||
0x4a, 0xa1, 0x2f, 0xe5, 0xb8, 0x32, 0x48, 0x2f, 0xd1, 0x1e, 0x14, 0x47, 0xdc, 0x1b, 0xa8, 0x4c,
|
0xf9, 0xad, 0x07, 0x43, 0x86, 0xa5, 0x2e, 0xfa, 0x1d, 0x6c, 0x88, 0x5a, 0xf5, 0x99, 0x47, 0xa6,
|
||||||
0x64, 0x65, 0x41, 0x17, 0x04, 0x20, 0x73, 0x60, 0x42, 0x25, 0xf0, 0xdd, 0xc0, 0x27, 0xd1, 0x88,
|
0x93, 0x21, 0x9d, 0x85, 0xde, 0x48, 0xcd, 0xae, 0x2b, 0x85, 0xbe, 0x94, 0xe3, 0xca, 0x20, 0x3d,
|
||||||
0x92, 0xd3, 0x6f, 0xbe, 0x95, 0x0c, 0x54, 0xc6, 0x25, 0x09, 0x76, 0x47, 0xf4, 0xf4, 0x9b, 0x6f,
|
0x44, 0x7b, 0x50, 0x14, 0xd1, 0x56, 0x91, 0xc8, 0xca, 0xdc, 0x2f, 0x08, 0x40, 0xc6, 0xc0, 0x84,
|
||||||
0xd1, 0x13, 0x28, 0xc9, 0xae, 0x65, 0x9f, 0x26, 0x6e, 0x78, 0x2b, 0xa9, 0xa7, 0x82, 0x65, 0x23,
|
0x4a, 0xe0, 0xbb, 0x81, 0x4f, 0xa2, 0x11, 0x25, 0xa7, 0xdf, 0x7c, 0x2b, 0xc9, 0xaa, 0x8c, 0x4b,
|
||||||
0x5b, 0x12, 0x11, 0xad, 0x71, 0xe5, 0xd1, 0xeb, 0x48, 0xd2, 0x4d, 0x05, 0xab, 0x05, 0x7a, 0x05,
|
0x12, 0xec, 0x8e, 0xe8, 0xe9, 0x37, 0xdf, 0xa2, 0x27, 0x50, 0x92, 0x05, 0xce, 0x3e, 0x4d, 0xdc,
|
||||||
0x3b, 0x71, 0x0c, 0x48, 0x14, 0x4c, 0xc3, 0x01, 0x23, 0xae, 0x3f, 0x64, 0x9f, 0x24, 0x8d, 0x54,
|
0xf0, 0x56, 0xb2, 0x54, 0x05, 0xcb, 0x9a, 0xb7, 0x24, 0x22, 0xaa, 0xe8, 0xca, 0xa3, 0xd7, 0x91,
|
||||||
0x30, 0x8a, 0x65, 0x5d, 0x29, 0xb2, 0x85, 0x04, 0xed, 0xc2, 0xfa, 0x88, 0xb9, 0xd7, 0x23, 0x45,
|
0x64, 0xa6, 0x0a, 0x56, 0x03, 0xf4, 0x0a, 0x76, 0x62, 0x1f, 0x90, 0x28, 0x98, 0x86, 0x03, 0x46,
|
||||||
0x0d, 0x15, 0x1c, 0xaf, 0xcc, 0xbf, 0xe7, 0xa0, 0x94, 0x0a, 0x0c, 0x2a, 0x43, 0x01, 0x5b, 0x5d,
|
0x5c, 0x7f, 0xc8, 0x3e, 0x49, 0xc6, 0xa9, 0x60, 0x14, 0xcb, 0xba, 0x52, 0x64, 0x0b, 0x09, 0xda,
|
||||||
0x0b, 0xbf, 0xb7, 0x1a, 0xfa, 0x67, 0xe8, 0x08, 0x9e, 0xd9, 0x4e, 0xbd, 0x83, 0xb1, 0x55, 0xef,
|
0x85, 0xf5, 0x11, 0x73, 0xaf, 0x47, 0x8a, 0x45, 0x2a, 0x38, 0x1e, 0x99, 0x7f, 0xcf, 0x41, 0x29,
|
||||||
0x91, 0x0e, 0x26, 0x7d, 0xe7, 0xad, 0xd3, 0xf9, 0xc1, 0x21, 0x17, 0xb5, 0x0f, 0x6d, 0xcb, 0xe9,
|
0xe5, 0x18, 0x54, 0x86, 0x02, 0xb6, 0xba, 0x16, 0x7e, 0x6f, 0x35, 0xf4, 0xcf, 0xd0, 0x11, 0x3c,
|
||||||
0x91, 0x86, 0xd5, 0xab, 0xd9, 0xad, 0xae, 0xae, 0xa1, 0x7d, 0x30, 0xe6, 0x9a, 0x89, 0xb8, 0xd6,
|
0xb3, 0x9d, 0x7a, 0x07, 0x63, 0xab, 0xde, 0x23, 0x1d, 0x4c, 0xfa, 0xce, 0x5b, 0xa7, 0xf3, 0x83,
|
||||||
0xee, 0xf4, 0x9d, 0x9e, 0xbe, 0x86, 0x9e, 0xc0, 0x5e, 0xd3, 0x76, 0x6a, 0x2d, 0x32, 0xd7, 0xa9,
|
0x43, 0x2e, 0x6a, 0x1f, 0xda, 0x96, 0xd3, 0x23, 0x0d, 0xab, 0x57, 0xb3, 0x5b, 0x5d, 0x5d, 0x43,
|
||||||
0xb7, 0x7a, 0xef, 0x89, 0xf5, 0xe3, 0x85, 0x8d, 0x3f, 0xe8, 0x99, 0x55, 0x0a, 0x67, 0xbd, 0x56,
|
0xfb, 0x60, 0xcc, 0x35, 0x13, 0x71, 0xad, 0xdd, 0xe9, 0x3b, 0x3d, 0x7d, 0x0d, 0x3d, 0x81, 0xbd,
|
||||||
0x3d, 0xb1, 0x90, 0x45, 0x8f, 0xe1, 0x73, 0xa5, 0xa0, 0xb6, 0x90, 0x5e, 0xa7, 0x43, 0xba, 0x9d,
|
0xa6, 0xed, 0xd4, 0x5a, 0x64, 0xae, 0x53, 0x6f, 0xf5, 0xde, 0x13, 0xeb, 0xc7, 0x0b, 0x1b, 0x7f,
|
||||||
0x8e, 0xa3, 0xe7, 0xd0, 0x16, 0x54, 0x6c, 0xe7, 0x7d, 0xad, 0x65, 0x37, 0x08, 0xb6, 0x6a, 0xad,
|
0xd0, 0x33, 0xab, 0x14, 0x44, 0x4d, 0x25, 0x2b, 0x64, 0xd1, 0x63, 0xf8, 0x5c, 0x29, 0xa8, 0x29,
|
||||||
0xb6, 0xbe, 0x8e, 0xb6, 0x61, 0x73, 0x59, 0x2f, 0x2f, 0x4c, 0x24, 0x7a, 0x1d, 0xc7, 0xee, 0x38,
|
0xa4, 0xd7, 0xe9, 0x90, 0x6e, 0xa7, 0xe3, 0xe8, 0x39, 0xb4, 0x05, 0x15, 0xdb, 0x79, 0x5f, 0x6b,
|
||||||
0xe4, 0xbd, 0x85, 0xbb, 0x76, 0xc7, 0xd1, 0x0b, 0x68, 0x17, 0xd0, 0xa2, 0xe8, 0xac, 0x5d, 0xab,
|
0xd9, 0x0d, 0x82, 0xad, 0x5a, 0xab, 0xad, 0xaf, 0xa3, 0x6d, 0xd8, 0x5c, 0xd6, 0xcb, 0x8b, 0x25,
|
||||||
0xeb, 0x45, 0xf4, 0x39, 0x6c, 0x2d, 0xe2, 0x6f, 0xad, 0x0f, 0x3a, 0x20, 0x03, 0x76, 0xd4, 0xc1,
|
0x12, 0xbd, 0x8e, 0x63, 0x77, 0x1c, 0xf2, 0xde, 0xc2, 0x5d, 0xbb, 0xe3, 0xe8, 0x05, 0xb4, 0x0b,
|
||||||
0xc8, 0x1b, 0xab, 0xd5, 0xf9, 0x81, 0xb4, 0x6d, 0xc7, 0x6e, 0xf7, 0xdb, 0x7a, 0x09, 0xed, 0x80,
|
0x68, 0x51, 0x74, 0xd6, 0xae, 0xd5, 0xf5, 0x22, 0xfa, 0x1c, 0xb6, 0x16, 0xf1, 0xb7, 0xd6, 0x07,
|
||||||
0xde, 0xb4, 0x2c, 0x62, 0x3b, 0xdd, 0x7e, 0xb3, 0x69, 0xd7, 0x6d, 0xcb, 0xe9, 0xe9, 0x65, 0xe5,
|
0x1d, 0x90, 0x01, 0x3b, 0x6a, 0x63, 0xe4, 0x8d, 0xd5, 0xea, 0xfc, 0x40, 0xda, 0xb6, 0x63, 0xb7,
|
||||||
0x79, 0xd5, 0x87, 0x57, 0xc4, 0x86, 0xfa, 0x59, 0xcd, 0x71, 0xac, 0x16, 0x69, 0xd8, 0xdd, 0xda,
|
0xfb, 0x6d, 0xbd, 0x84, 0x76, 0x40, 0x6f, 0x5a, 0x16, 0xb1, 0x9d, 0x6e, 0xbf, 0xd9, 0xb4, 0xeb,
|
||||||
0x9b, 0x96, 0xd5, 0xd0, 0x37, 0xd0, 0x01, 0x3c, 0xee, 0x59, 0xed, 0x8b, 0x0e, 0xae, 0xe1, 0x0f,
|
0xb6, 0xe5, 0xf4, 0xf4, 0xb2, 0xb2, 0xbc, 0xea, 0xe0, 0x15, 0x31, 0xa1, 0x7e, 0x56, 0x73, 0x1c,
|
||||||
0x24, 0x91, 0x37, 0x6b, 0x76, 0xab, 0x8f, 0x2d, 0x7d, 0x13, 0x7d, 0x09, 0x07, 0xd8, 0x7a, 0xd7,
|
0xab, 0x45, 0x1a, 0x76, 0xb7, 0xf6, 0xa6, 0x65, 0x35, 0xf4, 0x0d, 0x74, 0x00, 0x8f, 0x7b, 0x56,
|
||||||
0xb7, 0xb1, 0xd5, 0x20, 0x4e, 0xa7, 0x61, 0x91, 0xa6, 0x55, 0xeb, 0xf5, 0xb1, 0x45, 0xda, 0x76,
|
0xfb, 0xa2, 0x83, 0x6b, 0xf8, 0x03, 0x49, 0xe4, 0xcd, 0x9a, 0xdd, 0xea, 0x63, 0x4b, 0xdf, 0x44,
|
||||||
0xb7, 0x6b, 0x3b, 0xdf, 0xeb, 0x3a, 0x7a, 0x06, 0x87, 0x33, 0x95, 0x99, 0x81, 0x25, 0xad, 0x2d,
|
0x5f, 0xc2, 0x01, 0xb6, 0xde, 0xf5, 0x6d, 0x6c, 0x35, 0x88, 0xd3, 0x69, 0x58, 0xa4, 0x69, 0xd5,
|
||||||
0xf1, 0x7d, 0x49, 0x4a, 0x1d, 0xeb, 0xc7, 0x1e, 0xb9, 0xb0, 0x2c, 0xac, 0x23, 0x54, 0x85, 0xdd,
|
0x7a, 0x7d, 0x6c, 0x91, 0xb6, 0xdd, 0xed, 0xda, 0xce, 0xf7, 0xba, 0x8e, 0x9e, 0xc1, 0xe1, 0x4c,
|
||||||
0xb9, 0x7b, 0xe5, 0x20, 0xf6, 0xbd, 0x2d, 0x64, 0x17, 0x16, 0x6e, 0xd7, 0x1c, 0x91, 0xe0, 0x05,
|
0x65, 0xb6, 0xc0, 0x92, 0xd6, 0x96, 0x38, 0x5f, 0x12, 0x52, 0xc7, 0xfa, 0xb1, 0x47, 0x2e, 0x2c,
|
||||||
0xd9, 0x8e, 0x38, 0xf6, 0x5c, 0xb6, 0x7c, 0xec, 0xcf, 0x11, 0x82, 0x8d, 0x54, 0x56, 0x9a, 0x35,
|
0x0b, 0xeb, 0x08, 0x55, 0x61, 0x77, 0x6e, 0x5e, 0x19, 0x88, 0x6d, 0x6f, 0x0b, 0xd9, 0x85, 0x85,
|
||||||
0xac, 0xef, 0xa2, 0x1d, 0xd8, 0x4c, 0x4e, 0x90, 0x28, 0xfe, 0x2b, 0x8f, 0x1e, 0x01, 0xea, 0x3b,
|
0xdb, 0x35, 0x47, 0x04, 0x78, 0x41, 0xb6, 0x23, 0xb6, 0x3d, 0x97, 0x2d, 0x6f, 0xfb, 0x73, 0x84,
|
||||||
0xd8, 0xaa, 0x35, 0x44, 0x40, 0x66, 0x82, 0x7f, 0xe7, 0xcf, 0xb3, 0x85, 0x35, 0x3d, 0x63, 0xfe,
|
0x60, 0x23, 0x15, 0x95, 0x66, 0x0d, 0xeb, 0xbb, 0x68, 0x07, 0x36, 0x93, 0x1d, 0x24, 0x8a, 0xff,
|
||||||
0x33, 0x03, 0x95, 0x85, 0xbe, 0x44, 0xfb, 0x50, 0x8c, 0xdc, 0x6b, 0x9f, 0x72, 0xc1, 0x1c, 0x8a,
|
0xca, 0xa3, 0x47, 0x80, 0xfa, 0x0e, 0xb6, 0x6a, 0x0d, 0xe1, 0x90, 0x99, 0xe0, 0xdf, 0xf9, 0xf3,
|
||||||
0x54, 0xe6, 0x80, 0xbc, 0x1b, 0x47, 0xd4, 0xf5, 0x15, 0x9b, 0x29, 0x36, 0x2f, 0x4a, 0x44, 0x72,
|
0x6c, 0x61, 0x4d, 0xcf, 0x98, 0xff, 0xcc, 0x40, 0x65, 0xa1, 0x2e, 0xd1, 0x3e, 0x14, 0x23, 0xf7,
|
||||||
0xd9, 0x1e, 0xe4, 0x93, 0x7b, 0x38, 0x33, 0xbb, 0x87, 0xd7, 0x07, 0xea, 0xfe, 0xdd, 0x87, 0xa2,
|
0xda, 0xa7, 0x5c, 0x30, 0x87, 0x22, 0x95, 0x39, 0x20, 0xaf, 0xd1, 0x11, 0x75, 0x7d, 0xc5, 0x66,
|
||||||
0xa0, 0xcc, 0x88, 0xd3, 0xf1, 0x44, 0xb6, 0x78, 0x05, 0xcf, 0x01, 0xf4, 0x14, 0x2a, 0x63, 0x16,
|
0x8a, 0xf7, 0x8b, 0x12, 0x91, 0x5c, 0xb6, 0x07, 0xf9, 0xe4, 0xca, 0xce, 0xcc, 0xae, 0xec, 0xf5,
|
||||||
0x45, 0xf4, 0x9a, 0x11, 0xd5, 0xa6, 0x20, 0x35, 0xca, 0x31, 0xd8, 0x94, 0xdd, 0xfa, 0x14, 0x12,
|
0x81, 0xba, 0xaa, 0xf7, 0xa1, 0x28, 0x28, 0x33, 0xe2, 0x74, 0x3c, 0x91, 0x25, 0x5e, 0xc1, 0x73,
|
||||||
0xda, 0x88, 0x95, 0x72, 0x4a, 0x29, 0x06, 0x95, 0xd2, 0x32, 0x63, 0x73, 0x1a, 0xb3, 0x41, 0x9a,
|
0x00, 0x3d, 0x85, 0xca, 0x98, 0x45, 0x11, 0xbd, 0x66, 0x44, 0x95, 0x29, 0x48, 0x8d, 0x72, 0x0c,
|
||||||
0xb1, 0x39, 0x45, 0x2f, 0x60, 0x4b, 0x51, 0x8e, 0xeb, 0xbb, 0xe3, 0xe9, 0x58, 0x51, 0x4f, 0x5e,
|
0x36, 0x65, 0xb5, 0x3e, 0x85, 0x84, 0x36, 0x62, 0xa5, 0x9c, 0x52, 0x8a, 0x41, 0xa5, 0xb4, 0xcc,
|
||||||
0x52, 0xcf, 0xa6, 0xa4, 0x1e, 0x85, 0x4b, 0x06, 0x7a, 0x0c, 0x85, 0x4b, 0x1a, 0x31, 0x71, 0x59,
|
0xd8, 0x9c, 0xc6, 0x6c, 0x90, 0x66, 0x6c, 0x4e, 0xd1, 0x0b, 0xd8, 0x52, 0x94, 0xe3, 0xfa, 0xee,
|
||||||
0xc4, 0xd4, 0x90, 0x17, 0xeb, 0x26, 0x63, 0x42, 0x24, 0xae, 0x90, 0x50, 0x90, 0x9e, 0x62, 0x84,
|
0x78, 0x3a, 0x56, 0xd4, 0x93, 0x97, 0xd4, 0xb3, 0x29, 0xa9, 0x47, 0xe1, 0x92, 0x81, 0x1e, 0x43,
|
||||||
0xfc, 0x15, 0x63, 0x58, 0xc4, 0x72, 0xe6, 0x81, 0x7e, 0x9a, 0x7b, 0x28, 0xa5, 0x3c, 0x28, 0x5c,
|
0xe1, 0x92, 0x46, 0x4c, 0x5c, 0x16, 0x31, 0x35, 0xe4, 0xc5, 0xb8, 0xc9, 0x98, 0x10, 0x89, 0x2b,
|
||||||
0x7a, 0x78, 0x01, 0x5b, 0xec, 0x13, 0x0f, 0x29, 0x09, 0x26, 0xf4, 0xe7, 0x29, 0x23, 0x43, 0xca,
|
0x24, 0x14, 0xa4, 0xa7, 0x18, 0x21, 0x7f, 0xc5, 0x18, 0x16, 0xbe, 0x9c, 0x59, 0xa0, 0x9f, 0xe6,
|
||||||
0xa9, 0x1c, 0xec, 0xca, 0x78, 0x53, 0x0a, 0x3a, 0x12, 0x6f, 0x50, 0x4e, 0xcd, 0x7d, 0xa8, 0x62,
|
0x16, 0x4a, 0x29, 0x0b, 0x0a, 0x97, 0x16, 0x5e, 0xc0, 0x16, 0xfb, 0xc4, 0x43, 0x4a, 0x82, 0x09,
|
||||||
0x16, 0x31, 0xde, 0x76, 0xa3, 0xc8, 0x0d, 0xfc, 0x7a, 0xe0, 0xf3, 0x30, 0xf0, 0xe2, 0x3b, 0xc7,
|
0xfd, 0x79, 0xca, 0xc8, 0x90, 0x72, 0x2a, 0x7b, 0xc0, 0x32, 0xde, 0x94, 0x82, 0x8e, 0xc4, 0x1b,
|
||||||
0x3c, 0x80, 0xbd, 0x95, 0x52, 0x75, 0x69, 0x88, 0xcd, 0xef, 0xa6, 0x2c, 0xbc, 0x5d, 0xbd, 0xf9,
|
0x94, 0x53, 0x73, 0x1f, 0xaa, 0x98, 0x45, 0x8c, 0xb7, 0xdd, 0x28, 0x72, 0x03, 0xbf, 0x1e, 0xf8,
|
||||||
0x1d, 0xec, 0xad, 0x94, 0xc6, 0x37, 0xce, 0x4b, 0xc8, 0x4d, 0xa8, 0x1b, 0x46, 0xc6, 0x9a, 0x9c,
|
0x3c, 0x0c, 0xbc, 0xf8, 0xce, 0x31, 0x0f, 0x60, 0x6f, 0xa5, 0x54, 0x5d, 0x1a, 0x62, 0xf2, 0xbb,
|
||||||
0x62, 0x76, 0x17, 0xae, 0x7e, 0x37, 0x3c, 0x73, 0x23, 0x1e, 0x84, 0xb7, 0x58, 0x29, 0x9d, 0x67,
|
0x29, 0x0b, 0x6f, 0x57, 0x4f, 0x7e, 0x07, 0x7b, 0x2b, 0xa5, 0xf1, 0x8d, 0xf3, 0x12, 0x72, 0x13,
|
||||||
0x0b, 0x9a, 0xbe, 0x66, 0xfe, 0x59, 0x83, 0x52, 0x4a, 0x28, 0xea, 0xc0, 0x0f, 0x86, 0x8c, 0x5c,
|
0xea, 0x86, 0x91, 0xb1, 0x26, 0x6f, 0xed, 0xdd, 0x85, 0x26, 0xc1, 0x0d, 0xcf, 0xdc, 0x88, 0x07,
|
||||||
0x85, 0xc1, 0x38, 0xa9, 0xb0, 0x19, 0x80, 0x0c, 0xc8, 0xcb, 0x05, 0x0f, 0xe2, 0xf2, 0x4a, 0x96,
|
0xe1, 0x2d, 0x56, 0x4a, 0xe7, 0xd9, 0x82, 0xa6, 0xaf, 0x99, 0x7f, 0xd2, 0xa0, 0x94, 0x12, 0x8a,
|
||||||
0xe8, 0x6b, 0xc8, 0x8f, 0x94, 0x09, 0x99, 0xa5, 0xd2, 0xe9, 0xf6, 0x92, 0x77, 0x11, 0x1b, 0x9c,
|
0x3c, 0xf0, 0x83, 0x21, 0x23, 0x57, 0x61, 0x30, 0x4e, 0x32, 0x6c, 0x06, 0x20, 0x03, 0xf2, 0x72,
|
||||||
0xe8, 0x9c, 0x67, 0x0b, 0x19, 0x3d, 0x7b, 0x9e, 0x2d, 0x64, 0xf5, 0xdc, 0x79, 0xb6, 0x90, 0xd3,
|
0xc0, 0x83, 0x38, 0xbd, 0x92, 0x21, 0xfa, 0x1a, 0xf2, 0x23, 0xb5, 0x84, 0x8c, 0x52, 0xe9, 0x74,
|
||||||
0xd7, 0xcf, 0xb3, 0x85, 0x75, 0x3d, 0x6f, 0xfe, 0x55, 0x83, 0x42, 0xa2, 0xbd, 0x58, 0x93, 0x6a,
|
0x7b, 0xc9, 0xba, 0xf0, 0x0d, 0x4e, 0x74, 0xce, 0xb3, 0x85, 0x8c, 0x9e, 0x3d, 0xcf, 0x16, 0xb2,
|
||||||
0x00, 0x48, 0xd5, 0xe4, 0x29, 0xec, 0x8c, 0x5d, 0x9f, 0x4c, 0x98, 0x4f, 0x3d, 0xf7, 0x8f, 0x8c,
|
0x7a, 0xee, 0x3c, 0x5b, 0xc8, 0xe9, 0xeb, 0xe7, 0xd9, 0xc2, 0xba, 0x9e, 0x37, 0xff, 0xa2, 0x41,
|
||||||
0x2c, 0xce, 0x17, 0x2b, 0x65, 0xe8, 0x35, 0x3c, 0x92, 0x53, 0x26, 0xe5, 0x9c, 0x8d, 0x27, 0x9c,
|
0x21, 0xd1, 0x5e, 0xcc, 0x49, 0xd5, 0x00, 0xa4, 0x72, 0xf2, 0x14, 0x76, 0xc6, 0xae, 0x4f, 0x26,
|
||||||
0x44, 0xd3, 0xc1, 0x80, 0x45, 0xd1, 0xd5, 0xd4, 0x93, 0x2d, 0x51, 0xc0, 0xf7, 0x89, 0xcd, 0x31,
|
0xcc, 0xa7, 0x9e, 0xfb, 0x47, 0x46, 0x16, 0xfb, 0x8b, 0x95, 0x32, 0xf4, 0x1a, 0x1e, 0xc9, 0x86,
|
||||||
0x3c, 0x92, 0xa1, 0xbf, 0x08, 0x83, 0x4b, 0x7a, 0xe9, 0x7a, 0x2e, 0xbf, 0x4d, 0xc6, 0x88, 0x7d,
|
0x94, 0xaa, 0x26, 0x86, 0x44, 0xd3, 0xc1, 0x80, 0x45, 0xd1, 0xd5, 0xd4, 0x93, 0x25, 0x51, 0xc0,
|
||||||
0x28, 0x8a, 0xe0, 0x10, 0x3f, 0xb9, 0x97, 0xcb, 0x78, 0x0e, 0x88, 0x90, 0xf1, 0x40, 0xc9, 0xe2,
|
0xf7, 0x89, 0xcd, 0x31, 0x3c, 0x92, 0xae, 0xbf, 0x08, 0x83, 0x4b, 0x7a, 0xe9, 0x7a, 0x2e, 0xbf,
|
||||||
0x90, 0xc5, 0x4b, 0x31, 0x20, 0xcc, 0x1e, 0x09, 0x19, 0x79, 0xe8, 0xd9, 0xda, 0xbc, 0x01, 0xe3,
|
0x4d, 0xda, 0x88, 0x7d, 0x28, 0x0a, 0xe7, 0x10, 0x3f, 0xb9, 0x97, 0xcb, 0x78, 0x0e, 0x08, 0x97,
|
||||||
0xae, 0xbb, 0x38, 0xcd, 0x87, 0x50, 0x9a, 0xcc, 0x61, 0xe9, 0x51, 0xc3, 0x69, 0x28, 0x9d, 0x8c,
|
0xf1, 0x40, 0xc9, 0x62, 0x97, 0xc5, 0x43, 0xd1, 0x20, 0xcc, 0xde, 0x13, 0x19, 0xb9, 0xe9, 0xd9,
|
||||||
0xb5, 0x5f, 0x4e, 0x86, 0xf9, 0x37, 0x0d, 0xb6, 0xde, 0x4c, 0x5d, 0x6f, 0xb8, 0x30, 0x1d, 0xa5,
|
0xd8, 0xbc, 0x01, 0xe3, 0xae, 0xb9, 0x38, 0xcc, 0x87, 0x50, 0x9a, 0xcc, 0x61, 0x69, 0x51, 0xc3,
|
||||||
0xdf, 0x30, 0xda, 0xe2, 0x1b, 0x66, 0xd5, 0x03, 0x65, 0x6d, 0xe5, 0x03, 0x65, 0xd5, 0x23, 0x20,
|
0x69, 0x28, 0x1d, 0x8c, 0xb5, 0x5f, 0x0e, 0x86, 0xf9, 0x57, 0x0d, 0xb6, 0xde, 0x4c, 0x5d, 0x6f,
|
||||||
0x73, 0xef, 0x23, 0xe0, 0x09, 0x94, 0xe6, 0xf3, 0x7f, 0x64, 0x64, 0x0f, 0x33, 0x47, 0x65, 0x0c,
|
0xb8, 0xd0, 0x1d, 0xa5, 0x9f, 0x3b, 0xda, 0xe2, 0x73, 0x67, 0xd5, 0x5b, 0x66, 0x6d, 0xe5, 0x5b,
|
||||||
0xa3, 0x64, 0xf8, 0x8f, 0xcc, 0xd7, 0x80, 0xd2, 0x07, 0x8d, 0x03, 0x32, 0x1b, 0xd2, 0xb4, 0x7b,
|
0x66, 0xd5, 0x7b, 0x21, 0x73, 0xef, 0x7b, 0xe1, 0x09, 0x94, 0xe6, 0x4f, 0x05, 0xd5, 0x7c, 0x96,
|
||||||
0x87, 0xb4, 0x17, 0x7f, 0xd1, 0xa0, 0x9c, 0x9e, 0x7f, 0x51, 0x05, 0x8a, 0xb6, 0x43, 0x9a, 0x2d,
|
0x31, 0x8c, 0x92, 0x77, 0x42, 0x64, 0xbe, 0x06, 0x94, 0xde, 0x68, 0xec, 0x90, 0x59, 0x93, 0xa6,
|
||||||
0xfb, 0xfb, 0xb3, 0x9e, 0xfe, 0x99, 0x58, 0x76, 0xfb, 0xf5, 0xba, 0x65, 0x35, 0xac, 0x86, 0xae,
|
0xdd, 0xdb, 0xa4, 0xbd, 0xf8, 0xb3, 0x06, 0xe5, 0x74, 0xa7, 0x8c, 0x2a, 0x50, 0xb4, 0x1d, 0xd2,
|
||||||
0x09, 0x0e, 0x17, 0x74, 0x6c, 0x35, 0x48, 0xcf, 0x6e, 0x5b, 0x9d, 0xbe, 0xb8, 0xdd, 0xb7, 0x61,
|
0x6c, 0xd9, 0xdf, 0x9f, 0xf5, 0xf4, 0xcf, 0xc4, 0xb0, 0xdb, 0xaf, 0xd7, 0x2d, 0xab, 0x61, 0x35,
|
||||||
0x33, 0xc6, 0x9c, 0x0e, 0xc1, 0x9d, 0x7e, 0xcf, 0xd2, 0x33, 0x48, 0x87, 0x72, 0x0c, 0x5a, 0x18,
|
0x74, 0x4d, 0x70, 0xb8, 0xa0, 0x63, 0xab, 0x41, 0x7a, 0x76, 0xdb, 0xea, 0xf4, 0xc5, 0xed, 0xbe,
|
||||||
0x77, 0xb0, 0x9e, 0x15, 0x57, 0x52, 0x8c, 0xdc, 0x9d, 0x14, 0x92, 0x41, 0x22, 0x77, 0xfa, 0x8f,
|
0x0d, 0x9b, 0x31, 0xe6, 0x74, 0x08, 0xee, 0xf4, 0x7b, 0x96, 0x9e, 0x41, 0x3a, 0x94, 0x63, 0xd0,
|
||||||
0x1c, 0xac, 0xcb, 0x03, 0x86, 0xe8, 0x0c, 0x4a, 0xa9, 0x47, 0x06, 0x3a, 0x78, 0xf0, 0xf1, 0x51,
|
0xc2, 0xb8, 0x83, 0xf5, 0xac, 0xb8, 0x92, 0x62, 0xe4, 0x6e, 0xa7, 0x90, 0x34, 0x12, 0xb9, 0xd3,
|
||||||
0x35, 0x56, 0x0f, 0xf4, 0xd3, 0xe8, 0x95, 0x86, 0xce, 0xa1, 0x9c, 0x7e, 0x46, 0xa0, 0xf4, 0x78,
|
0x7f, 0xe4, 0x60, 0x5d, 0x6e, 0x30, 0x44, 0x67, 0x50, 0x4a, 0xbd, 0x47, 0xd0, 0xc1, 0x83, 0xef,
|
||||||
0xb8, 0xe2, 0x7d, 0xf1, 0xa0, 0xad, 0xb7, 0xa0, 0x5b, 0x11, 0x77, 0xc7, 0x62, 0x1c, 0x8c, 0x07,
|
0x94, 0xaa, 0xb1, 0xba, 0xf5, 0x9f, 0x46, 0xaf, 0x34, 0x74, 0x0e, 0xe5, 0xf4, 0x8b, 0x03, 0xa5,
|
||||||
0x74, 0x54, 0x4d, 0xe9, 0x2f, 0x4d, 0xfd, 0xd5, 0xbd, 0x95, 0xb2, 0x38, 0x43, 0x2d, 0xf5, 0x89,
|
0xdb, 0xc3, 0x15, 0x4f, 0x91, 0x07, 0xd7, 0x7a, 0x0b, 0xba, 0x15, 0x71, 0x77, 0x2c, 0xda, 0xc1,
|
||||||
0xf1, 0x88, 0x7c, 0xe7, 0x13, 0x17, 0xe7, 0xf2, 0xea, 0x17, 0xf7, 0x89, 0x63, 0x6b, 0x43, 0xd8,
|
0xb8, 0x41, 0x47, 0xd5, 0x94, 0xfe, 0x52, 0xd7, 0x5f, 0xdd, 0x5b, 0x29, 0x8b, 0x23, 0xd4, 0x52,
|
||||||
0x5e, 0xc1, 0xa1, 0xe8, 0x57, 0xe9, 0x13, 0xdc, 0xcb, 0xc0, 0xd5, 0xe7, 0xbf, 0xa4, 0x36, 0xf7,
|
0x47, 0x8c, 0x5b, 0xe4, 0x3b, 0x47, 0x5c, 0xec, 0xcb, 0xab, 0x5f, 0xdc, 0x27, 0x8e, 0x57, 0x1b,
|
||||||
0xb2, 0x82, 0x6c, 0x17, 0xbc, 0xdc, 0x4f, 0xd5, 0x0b, 0x5e, 0x1e, 0xe2, 0xec, 0x9f, 0x40, 0x5f,
|
0xc2, 0xf6, 0x0a, 0x0e, 0x45, 0xbf, 0x4a, 0xef, 0xe0, 0x5e, 0x06, 0xae, 0x3e, 0xff, 0x25, 0xb5,
|
||||||
0x6e, 0x74, 0x64, 0x2e, 0xef, 0xbd, 0x4b, 0x3a, 0xd5, 0xa7, 0x0f, 0xea, 0xc4, 0xc6, 0x6d, 0x80,
|
0xb9, 0x95, 0x15, 0x64, 0xbb, 0x60, 0xe5, 0x7e, 0xaa, 0x5e, 0xb0, 0xf2, 0x10, 0x67, 0xff, 0x04,
|
||||||
0x79, 0xbb, 0xa0, 0xfd, 0xd4, 0x96, 0x3b, 0xed, 0x5e, 0x3d, 0xb8, 0x47, 0xaa, 0x4c, 0xbd, 0xf9,
|
0xfa, 0x72, 0xa1, 0x23, 0x73, 0x79, 0xee, 0x5d, 0xd2, 0xa9, 0x3e, 0x7d, 0x50, 0x27, 0x5e, 0xdc,
|
||||||
0xf5, 0xef, 0x4f, 0xae, 0x5d, 0x3e, 0x9a, 0x5e, 0x1e, 0x0f, 0x82, 0xf1, 0x89, 0x27, 0x86, 0x6a,
|
0x06, 0x98, 0x97, 0x0b, 0xda, 0x4f, 0x4d, 0xb9, 0x53, 0xee, 0xd5, 0x83, 0x7b, 0xa4, 0x6a, 0xa9,
|
||||||
0xdf, 0xf5, 0xaf, 0x7d, 0xc6, 0xff, 0x10, 0x84, 0x37, 0x27, 0x9e, 0x3f, 0x3c, 0x91, 0x5d, 0x77,
|
0x37, 0xbf, 0xfe, 0xfd, 0xc9, 0xb5, 0xcb, 0x47, 0xd3, 0xcb, 0xe3, 0x41, 0x30, 0x3e, 0xf1, 0x44,
|
||||||
0x32, 0xb3, 0x72, 0xb9, 0x2e, 0xff, 0x91, 0xf2, 0x9b, 0xff, 0x05, 0x00, 0x00, 0xff, 0xff, 0x1f,
|
0x53, 0xed, 0xbb, 0xfe, 0xb5, 0xcf, 0xf8, 0x1f, 0x82, 0xf0, 0xe6, 0xc4, 0xf3, 0x87, 0x27, 0xb2,
|
||||||
0xb3, 0x05, 0x24, 0x78, 0x11, 0x00, 0x00,
|
0xea, 0x4e, 0x66, 0xab, 0x5c, 0xae, 0xcb, 0xff, 0x5c, 0x7e, 0xf3, 0xbf, 0x00, 0x00, 0x00, 0xff,
|
||||||
|
0xff, 0x78, 0xac, 0xbb, 0x04, 0xa3, 0x11, 0x00, 0x00,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reference imports to suppress errors if they are not otherwise used.
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
|||||||
@@ -155,6 +155,11 @@ message PaymentStatus {
|
|||||||
The taken route when state is SUCCEEDED.
|
The taken route when state is SUCCEEDED.
|
||||||
*/
|
*/
|
||||||
lnrpc.Route route = 3;
|
lnrpc.Route route = 3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
The HTLCs made in attempt to settle the payment [EXPERIMENTAL].
|
||||||
|
*/
|
||||||
|
repeated lnrpc.HTLCAttempt htlcs = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
|
|
||||||
"github.com/btcsuite/btcd/chaincfg"
|
"github.com/btcsuite/btcd/chaincfg"
|
||||||
"github.com/btcsuite/btcutil"
|
"github.com/btcsuite/btcutil"
|
||||||
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntypes"
|
"github.com/lightningnetwork/lnd/lntypes"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
@@ -779,3 +780,48 @@ func UnmarshalMPP(reqMPP *lnrpc.MPPRecord) (*record.MPP, error) {
|
|||||||
|
|
||||||
return record.NewMPP(total, addr), nil
|
return record.NewMPP(total, addr), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MarshalHTLCAttempt constructs an RPC HTLCAttempt from the db representation.
|
||||||
|
func (r *RouterBackend) MarshalHTLCAttempt(
|
||||||
|
htlc channeldb.HTLCAttempt) (*lnrpc.HTLCAttempt, error) {
|
||||||
|
|
||||||
|
var (
|
||||||
|
status lnrpc.HTLCAttempt_HTLCStatus
|
||||||
|
resolveTime int64
|
||||||
|
)
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case htlc.Settle != nil:
|
||||||
|
status = lnrpc.HTLCAttempt_SUCCEEDED
|
||||||
|
resolveTime = MarshalTimeNano(htlc.Settle.SettleTime)
|
||||||
|
|
||||||
|
case htlc.Failure != nil:
|
||||||
|
status = lnrpc.HTLCAttempt_FAILED
|
||||||
|
resolveTime = MarshalTimeNano(htlc.Failure.FailTime)
|
||||||
|
|
||||||
|
default:
|
||||||
|
status = lnrpc.HTLCAttempt_IN_FLIGHT
|
||||||
|
}
|
||||||
|
|
||||||
|
route, err := r.MarshallRoute(&htlc.Route)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &lnrpc.HTLCAttempt{
|
||||||
|
Status: status,
|
||||||
|
Route: route,
|
||||||
|
AttemptTimeNs: MarshalTimeNano(htlc.AttemptTime),
|
||||||
|
ResolveTimeNs: resolveTime,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalTimeNano converts a time.Time into its nanosecond representation. If
|
||||||
|
// the time is zero, this method simply returns 0, since calling UnixNano() on a
|
||||||
|
// zero-valued time is undefined.
|
||||||
|
func MarshalTimeNano(t time.Time) int64 {
|
||||||
|
if t.IsZero() {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return t.UnixNano()
|
||||||
|
}
|
||||||
@@ -584,19 +584,12 @@ func (s *Server) trackPayment(paymentHash lntypes.Hash,
|
|||||||
case result := <-resultChan:
|
case result := <-resultChan:
|
||||||
// Marshall result to rpc type.
|
// Marshall result to rpc type.
|
||||||
var status PaymentStatus
|
var status PaymentStatus
|
||||||
|
|
||||||
if result.Success {
|
if result.Success {
|
||||||
log.Debugf("Payment %v successfully completed",
|
log.Debugf("Payment %v successfully completed",
|
||||||
paymentHash)
|
paymentHash)
|
||||||
|
|
||||||
status.State = PaymentState_SUCCEEDED
|
status.State = PaymentState_SUCCEEDED
|
||||||
status.Preimage = result.Preimage[:]
|
status.Preimage = result.Preimage[:]
|
||||||
status.Route, err = router.MarshallRoute(
|
|
||||||
result.Route,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
state, err := marshallFailureReason(
|
state, err := marshallFailureReason(
|
||||||
result.FailureReason,
|
result.FailureReason,
|
||||||
@@ -605,15 +598,49 @@ func (s *Server) trackPayment(paymentHash lntypes.Hash,
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
status.State = state
|
status.State = state
|
||||||
if result.Route != nil {
|
}
|
||||||
status.Route, err = router.MarshallRoute(
|
|
||||||
result.Route,
|
// Extract the last route from the given list of HTLCs. This
|
||||||
)
|
// will populate the legacy route field for backwards
|
||||||
if err != nil {
|
// compatibility.
|
||||||
return err
|
//
|
||||||
}
|
// NOTE: For now there will be at most one HTLC, this code
|
||||||
|
// should be revisted or the field removed when multiple HTLCs
|
||||||
|
// are permitted.
|
||||||
|
var legacyRoute *route.Route
|
||||||
|
for _, htlc := range result.HTLCs {
|
||||||
|
switch {
|
||||||
|
case htlc.Settle != nil:
|
||||||
|
legacyRoute = &htlc.Route
|
||||||
|
|
||||||
|
// Only display the route for failed payments if we got
|
||||||
|
// an incorrect payment details error, so that it can be
|
||||||
|
// used for probing or fee estimation.
|
||||||
|
case htlc.Failure != nil && result.FailureReason ==
|
||||||
|
channeldb.FailureReasonPaymentDetails:
|
||||||
|
|
||||||
|
legacyRoute = &htlc.Route
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if legacyRoute != nil {
|
||||||
|
status.Route, err = router.MarshallRoute(legacyRoute)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Marshal our list of HTLCs that have been tried for this
|
||||||
|
// payment.
|
||||||
|
htlcs := make([]*lnrpc.HTLCAttempt, 0, len(result.HTLCs))
|
||||||
|
for _, dbHtlc := range result.HTLCs {
|
||||||
|
htlc, err := router.MarshalHTLCAttempt(dbHtlc)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
htlcs = append(htlcs, htlc)
|
||||||
|
}
|
||||||
|
status.Htlcs = htlcs
|
||||||
|
|
||||||
// Send event to the client.
|
// Send event to the client.
|
||||||
err = stream.Send(&status)
|
err = stream.Send(&status)
|
||||||
@@ -645,7 +672,7 @@ func marshallFailureReason(reason channeldb.FailureReason) (
|
|||||||
case channeldb.FailureReasonError:
|
case channeldb.FailureReasonError:
|
||||||
return PaymentState_FAILED_ERROR, nil
|
return PaymentState_FAILED_ERROR, nil
|
||||||
|
|
||||||
case channeldb.FailureReasonIncorrectPaymentDetails:
|
case channeldb.FailureReasonPaymentDetails:
|
||||||
return PaymentState_FAILED_INCORRECT_PAYMENT_DETAILS, nil
|
return PaymentState_FAILED_INCORRECT_PAYMENT_DETAILS, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+712
-586
File diff suppressed because it is too large.
Load diff
+33
-4
@@ -2478,11 +2478,11 @@ message Payment {
|
|||||||
/// Deprecated, use value_sat or value_msat.
|
/// Deprecated, use value_sat or value_msat.
|
||||||
int64 value = 2 [json_name = "value", deprecated = true];
|
int64 value = 2 [json_name = "value", deprecated = true];
|
||||||
|
|
||||||
/// The date of this payment
|
/// Deprecated, use creation_time_ns
|
||||||
int64 creation_date = 3 [json_name = "creation_date"];
|
int64 creation_date = 3 [json_name = "creation_date", deprecated = true];
|
||||||
|
|
||||||
/// The path this payment took
|
/// The path this payment took.
|
||||||
repeated string path = 4 [ json_name = "path" ];
|
repeated string path = 4 [json_name = "path", deprecated = true];
|
||||||
|
|
||||||
/// Deprecated, use fee_sat or fee_msat.
|
/// Deprecated, use fee_sat or fee_msat.
|
||||||
int64 fee = 5 [json_name = "fee", deprecated = true];
|
int64 fee = 5 [json_name = "fee", deprecated = true];
|
||||||
@@ -2514,6 +2514,35 @@ message Payment {
|
|||||||
|
|
||||||
/// The fee paid for this payment in milli-satoshis
|
/// The fee paid for this payment in milli-satoshis
|
||||||
int64 fee_msat = 12 [json_name = "fee_msat"];
|
int64 fee_msat = 12 [json_name = "fee_msat"];
|
||||||
|
|
||||||
|
/// The time in UNIX nanoseconds at which the payment was created.
|
||||||
|
int64 creation_time_ns = 13 [json_name = "creation_time_ns"];
|
||||||
|
|
||||||
|
/// The HTLCs made in attempt to settle the payment [EXPERIMENTAL].
|
||||||
|
repeated HTLCAttempt htlcs = 14 [json_name = "htlcs"];
|
||||||
|
}
|
||||||
|
|
||||||
|
message HTLCAttempt {
|
||||||
|
enum HTLCStatus {
|
||||||
|
IN_FLIGHT = 0;
|
||||||
|
SUCCEEDED = 1;
|
||||||
|
FAILED = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The status of the HTLC.
|
||||||
|
HTLCStatus status = 1 [json_name = "status"];
|
||||||
|
|
||||||
|
/// The route taken by this HTLC.
|
||||||
|
Route route = 2 [json_name = "route"];
|
||||||
|
|
||||||
|
/// The time in UNIX nanonseconds at which this HTLC was sent.
|
||||||
|
int64 attempt_time_ns = 3 [json_name = "attempt_time_ns"];
|
||||||
|
|
||||||
|
/**
|
||||||
|
The time in UNIX nanonseconds at which this HTLC was settled or failed.
|
||||||
|
This value will not be set if the HTLC is still IN_FLIGHT.
|
||||||
|
*/
|
||||||
|
int64 resolve_time_ns = 4 [json_name = "resolve_time_ns"];
|
||||||
}
|
}
|
||||||
|
|
||||||
message ListPaymentsRequest {
|
message ListPaymentsRequest {
|
||||||
|
|||||||
+46
-2
@@ -1418,6 +1418,15 @@
|
|||||||
],
|
],
|
||||||
"default": "OPEN_CHANNEL"
|
"default": "OPEN_CHANNEL"
|
||||||
},
|
},
|
||||||
|
"HTLCAttemptHTLCStatus": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"IN_FLIGHT",
|
||||||
|
"SUCCEEDED",
|
||||||
|
"FAILED"
|
||||||
|
],
|
||||||
|
"default": "IN_FLIGHT"
|
||||||
|
},
|
||||||
"InvoiceInvoiceState": {
|
"InvoiceInvoiceState": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": [
|
"enum": [
|
||||||
@@ -2511,6 +2520,29 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"lnrpcHTLCAttempt": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"status": {
|
||||||
|
"$ref": "#/definitions/HTLCAttemptHTLCStatus",
|
||||||
|
"description": "/ The status of the HTLC."
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"$ref": "#/definitions/lnrpcRoute",
|
||||||
|
"description": "/ The route taken by this HTLC."
|
||||||
|
},
|
||||||
|
"attempt_time_ns": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "int64",
|
||||||
|
"description": "/ The time in UNIX nanonseconds at which this HTLC was sent."
|
||||||
|
},
|
||||||
|
"resolve_time_ns": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "int64",
|
||||||
|
"description": "*\nThe time in UNIX nanonseconds at which this HTLC was settled or failed.\nThis value will not be set if the HTLC is still IN_FLIGHT."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"lnrpcHop": {
|
"lnrpcHop": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
@@ -3231,14 +3263,14 @@
|
|||||||
"creation_date": {
|
"creation_date": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "int64",
|
"format": "int64",
|
||||||
"title": "/ The date of this payment"
|
"title": "/ Deprecated, use creation_time_ns"
|
||||||
},
|
},
|
||||||
"path": {
|
"path": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"title": "/ The path this payment took"
|
"description": "/ The path this payment took."
|
||||||
},
|
},
|
||||||
"fee": {
|
"fee": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -3276,6 +3308,18 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "int64",
|
"format": "int64",
|
||||||
"title": "/ The fee paid for this payment in milli-satoshis"
|
"title": "/ The fee paid for this payment in milli-satoshis"
|
||||||
|
},
|
||||||
|
"creation_time_ns": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "int64",
|
||||||
|
"description": "/ The time in UNIX nanoseconds at which the payment was created."
|
||||||
|
},
|
||||||
|
"htlcs": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/lnrpcHTLCAttempt"
|
||||||
|
},
|
||||||
|
"description": "/ The HTLCs made in attempt to settle the payment [EXPERIMENTAL]."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -4737,6 +4737,50 @@ func testSingleHopSendToRouteCase(net *lntest.NetworkHarness, t *harnessTest,
|
|||||||
"want: %d, got: %d",
|
"want: %d, got: %d",
|
||||||
i, paymentAmtSat, p.ValueSat)
|
i, paymentAmtSat, p.ValueSat)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Assert exactly one htlc was made.
|
||||||
|
if len(p.Htlcs) != 1 {
|
||||||
|
t.Fatalf("expected 1 htlc for payment %d, got: %d",
|
||||||
|
i, len(p.Htlcs))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assert the htlc's route is populated.
|
||||||
|
htlc := p.Htlcs[0]
|
||||||
|
if htlc.Route == nil {
|
||||||
|
t.Fatalf("expected route for payment %d", i)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assert the hop has exactly one hop.
|
||||||
|
if len(htlc.Route.Hops) != 1 {
|
||||||
|
t.Fatalf("expected 1 hop for payment %d, got: %d",
|
||||||
|
i, len(htlc.Route.Hops))
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this is an MPP test, assert the MPP record's fields are
|
||||||
|
// properly populated. Otherwise the hop should not have an MPP
|
||||||
|
// record.
|
||||||
|
hop := htlc.Route.Hops[0]
|
||||||
|
if test.mpp {
|
||||||
|
if hop.MppRecord == nil {
|
||||||
|
t.Fatalf("expected mpp record for mpp payment")
|
||||||
|
}
|
||||||
|
|
||||||
|
if hop.MppRecord.TotalAmtMsat != paymentAmtSat*1000 {
|
||||||
|
t.Fatalf("incorrect mpp total msat for payment %d "+
|
||||||
|
"want: %d, got: %d",
|
||||||
|
i, paymentAmtSat*1000,
|
||||||
|
hop.MppRecord.TotalAmtMsat)
|
||||||
|
}
|
||||||
|
|
||||||
|
expAddr := [32]byte{byte(i)}
|
||||||
|
if !bytes.Equal(hop.MppRecord.PaymentAddr, expAddr[:]) {
|
||||||
|
t.Fatalf("incorrect mpp payment addr for payment %d "+
|
||||||
|
"want: %x, got: %x",
|
||||||
|
i, expAddr, hop.MppRecord.PaymentAddr)
|
||||||
|
}
|
||||||
|
} else if hop.MppRecord != nil {
|
||||||
|
t.Fatalf("unexpected mpp record for non-mpp payment")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that the invoices's from Dave's PoV have the correct payment
|
// Verify that the invoices's from Dave's PoV have the correct payment
|
||||||
|
|||||||
+29
-34
@@ -6,7 +6,6 @@ import (
|
|||||||
|
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
"github.com/lightningnetwork/lnd/lntypes"
|
"github.com/lightningnetwork/lnd/lntypes"
|
||||||
"github.com/lightningnetwork/lnd/routing/route"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ControlTower tracks all outgoing payments made, whose primary purpose is to
|
// ControlTower tracks all outgoing payments made, whose primary purpose is to
|
||||||
@@ -52,17 +51,17 @@ type PaymentResult struct {
|
|||||||
// Success indicates whether the payment was successful.
|
// Success indicates whether the payment was successful.
|
||||||
Success bool
|
Success bool
|
||||||
|
|
||||||
// Route is the (last) route attempted to send the HTLC. It is only set
|
// Preimage is the preimage of a successful payment. This serves as a
|
||||||
// for successful payments.
|
// proof of payment. It is only set for successful payments.
|
||||||
Route *route.Route
|
|
||||||
|
|
||||||
// PaymentPreimage is the preimage of a successful payment. This serves
|
|
||||||
// as a proof of payment. It is only set for successful payments.
|
|
||||||
Preimage lntypes.Preimage
|
Preimage lntypes.Preimage
|
||||||
|
|
||||||
// Failure is a failure reason code indicating the reason the payment
|
// FailureReason is a failure reason code indicating the reason the
|
||||||
// failed. It is only set for failed payments.
|
// payment failed. It is only set for failed payments.
|
||||||
FailureReason channeldb.FailureReason
|
FailureReason channeldb.FailureReason
|
||||||
|
|
||||||
|
// HTLCs is a list of HTLCs that have been attempted in order to settle
|
||||||
|
// the payment.
|
||||||
|
HTLCs []channeldb.HTLCAttempt
|
||||||
}
|
}
|
||||||
|
|
||||||
// controlTower is persistent implementation of ControlTower to restrict
|
// controlTower is persistent implementation of ControlTower to restrict
|
||||||
@@ -107,46 +106,46 @@ func (p *controlTower) RegisterAttempt(paymentHash lntypes.Hash,
|
|||||||
func (p *controlTower) Success(paymentHash lntypes.Hash,
|
func (p *controlTower) Success(paymentHash lntypes.Hash,
|
||||||
preimage lntypes.Preimage) error {
|
preimage lntypes.Preimage) error {
|
||||||
|
|
||||||
route, err := p.db.Success(paymentHash, preimage)
|
payment, err := p.db.Success(paymentHash, preimage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify subscribers of success event.
|
// Notify subscribers of success event.
|
||||||
p.notifyFinalEvent(
|
p.notifyFinalEvent(
|
||||||
paymentHash, createSuccessResult(route, preimage),
|
paymentHash, createSuccessResult(payment.HTLCs),
|
||||||
)
|
)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// createSuccessResult creates a success result to send to subscribers.
|
// createSuccessResult creates a success result to send to subscribers.
|
||||||
func createSuccessResult(rt *route.Route,
|
func createSuccessResult(htlcs []channeldb.HTLCAttempt) *PaymentResult {
|
||||||
preimage lntypes.Preimage) *PaymentResult {
|
// Extract any preimage from the list of HTLCs.
|
||||||
|
var preimage lntypes.Preimage
|
||||||
|
for _, htlc := range htlcs {
|
||||||
|
if htlc.Settle != nil {
|
||||||
|
preimage = htlc.Settle.Preimage
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return &PaymentResult{
|
return &PaymentResult{
|
||||||
Success: true,
|
Success: true,
|
||||||
Preimage: preimage,
|
Preimage: preimage,
|
||||||
Route: rt,
|
HTLCs: htlcs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// createFailResult creates a failed result to send to subscribers.
|
// createFailResult creates a failed result to send to subscribers.
|
||||||
func createFailedResult(rt *route.Route,
|
func createFailedResult(htlcs []channeldb.HTLCAttempt,
|
||||||
reason channeldb.FailureReason) *PaymentResult {
|
reason channeldb.FailureReason) *PaymentResult {
|
||||||
|
|
||||||
result := &PaymentResult{
|
return &PaymentResult{
|
||||||
Success: false,
|
Success: false,
|
||||||
FailureReason: reason,
|
FailureReason: reason,
|
||||||
|
HTLCs: htlcs,
|
||||||
}
|
}
|
||||||
|
|
||||||
// In case of incorrect payment details, set the route. This can be used
|
|
||||||
// for probing and to extract a fee estimate from the route.
|
|
||||||
if reason == channeldb.FailureReasonIncorrectPaymentDetails {
|
|
||||||
result.Route = rt
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fail transitions a payment into the Failed state, and records the reason the
|
// Fail transitions a payment into the Failed state, and records the reason the
|
||||||
@@ -156,14 +155,16 @@ func createFailedResult(rt *route.Route,
|
|||||||
func (p *controlTower) Fail(paymentHash lntypes.Hash,
|
func (p *controlTower) Fail(paymentHash lntypes.Hash,
|
||||||
reason channeldb.FailureReason) error {
|
reason channeldb.FailureReason) error {
|
||||||
|
|
||||||
route, err := p.db.Fail(paymentHash, reason)
|
payment, err := p.db.Fail(paymentHash, reason)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify subscribers of fail event.
|
// Notify subscribers of fail event.
|
||||||
p.notifyFinalEvent(
|
p.notifyFinalEvent(
|
||||||
paymentHash, createFailedResult(route, reason),
|
paymentHash, createFailedResult(
|
||||||
|
payment.HTLCs, reason,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -213,20 +214,14 @@ func (p *controlTower) SubscribePayment(paymentHash lntypes.Hash) (
|
|||||||
// a subscriber, because we can send the result on the channel
|
// a subscriber, because we can send the result on the channel
|
||||||
// immediately.
|
// immediately.
|
||||||
case channeldb.StatusSucceeded:
|
case channeldb.StatusSucceeded:
|
||||||
event = *createSuccessResult(
|
event = *createSuccessResult(payment.HTLCs)
|
||||||
&payment.Attempt.Route, *payment.PaymentPreimage,
|
|
||||||
)
|
|
||||||
|
|
||||||
// Payment already failed. It is not necessary to register as a
|
// Payment already failed. It is not necessary to register as a
|
||||||
// subscriber, because we can send the result on the channel
|
// subscriber, because we can send the result on the channel
|
||||||
// immediately.
|
// immediately.
|
||||||
case channeldb.StatusFailed:
|
case channeldb.StatusFailed:
|
||||||
var route *route.Route
|
|
||||||
if payment.Attempt != nil {
|
|
||||||
route = &payment.Attempt.Route
|
|
||||||
}
|
|
||||||
event = *createFailedResult(
|
event = *createFailedResult(
|
||||||
route, *payment.Failure,
|
payment.HTLCs, *payment.FailureReason,
|
||||||
)
|
)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -144,10 +144,13 @@ func TestControlTowerSubscribeSuccess(t *testing.T) {
|
|||||||
if result.Preimage != preimg {
|
if result.Preimage != preimg {
|
||||||
t.Fatal("unexpected preimage")
|
t.Fatal("unexpected preimage")
|
||||||
}
|
}
|
||||||
|
if len(result.HTLCs) != 1 {
|
||||||
if !reflect.DeepEqual(result.Route, &attempt.Route) {
|
t.Fatalf("expected one htlc, got %d", len(result.HTLCs))
|
||||||
t.Fatalf("unexpected route: %v vs %v",
|
}
|
||||||
spew.Sdump(result.Route),
|
htlc := result.HTLCs[0]
|
||||||
|
if !reflect.DeepEqual(htlc.Route, attempt.Route) {
|
||||||
|
t.Fatalf("unexpected htlc route: %v vs %v",
|
||||||
|
spew.Sdump(htlc.Route),
|
||||||
spew.Sdump(attempt.Route))
|
spew.Sdump(attempt.Route))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,6 +171,15 @@ func TestControlTowerSubscribeSuccess(t *testing.T) {
|
|||||||
func TestPaymentControlSubscribeFail(t *testing.T) {
|
func TestPaymentControlSubscribeFail(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
t.Run("register attempt", func(t *testing.T) {
|
||||||
|
testPaymentControlSubscribeFail(t, true)
|
||||||
|
})
|
||||||
|
t.Run("no register attempt", func(t *testing.T) {
|
||||||
|
testPaymentControlSubscribeFail(t, false)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testPaymentControlSubscribeFail(t *testing.T, registerAttempt bool) {
|
||||||
db, err := initDB()
|
db, err := initDB()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to init db: %v", err)
|
t.Fatalf("unable to init db: %v", err)
|
||||||
@@ -176,7 +188,7 @@ func TestPaymentControlSubscribeFail(t *testing.T) {
|
|||||||
pControl := NewControlTower(channeldb.NewPaymentControl(db))
|
pControl := NewControlTower(channeldb.NewPaymentControl(db))
|
||||||
|
|
||||||
// Initiate a payment.
|
// Initiate a payment.
|
||||||
info, _, _, err := genInfo()
|
info, attempt, _, err := genInfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -192,6 +204,17 @@ func TestPaymentControlSubscribeFail(t *testing.T) {
|
|||||||
t.Fatalf("expected subscribe to succeed, but got: %v", err)
|
t.Fatalf("expected subscribe to succeed, but got: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Conditionally register the attempt based on the test type. This
|
||||||
|
// allows us to simulate failing after attempting with an htlc or before
|
||||||
|
// making any attempts at all.
|
||||||
|
if registerAttempt {
|
||||||
|
// Register an attempt.
|
||||||
|
err = pControl.RegisterAttempt(info.PaymentHash, attempt)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Mark the payment as failed.
|
// Mark the payment as failed.
|
||||||
if err := pControl.Fail(info.PaymentHash, channeldb.FailureReasonTimeout); err != nil {
|
if err := pControl.Fail(info.PaymentHash, channeldb.FailureReasonTimeout); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -223,9 +246,28 @@ func TestPaymentControlSubscribeFail(t *testing.T) {
|
|||||||
if result.Success {
|
if result.Success {
|
||||||
t.Fatal("unexpected payment state")
|
t.Fatal("unexpected payment state")
|
||||||
}
|
}
|
||||||
if result.Route != nil {
|
|
||||||
t.Fatal("expected no route")
|
// There will either be one or zero htlcs depending on whether
|
||||||
|
// or not the attempt was registered. Assert the correct number
|
||||||
|
// is present, and the route taken if the attempt was
|
||||||
|
// registered.
|
||||||
|
if registerAttempt {
|
||||||
|
if len(result.HTLCs) != 1 {
|
||||||
|
t.Fatalf("expected 1 htlc, got: %d",
|
||||||
|
len(result.HTLCs))
|
||||||
|
}
|
||||||
|
|
||||||
|
htlc := result.HTLCs[0]
|
||||||
|
if !reflect.DeepEqual(htlc.Route, testRoute) {
|
||||||
|
t.Fatalf("unexpected htlc route: %v vs %v",
|
||||||
|
spew.Sdump(htlc.Route),
|
||||||
|
spew.Sdump(testRoute))
|
||||||
|
}
|
||||||
|
} else if len(result.HTLCs) != 0 {
|
||||||
|
t.Fatalf("expected 0 htlcs, got: %d",
|
||||||
|
len(result.HTLCs))
|
||||||
}
|
}
|
||||||
|
|
||||||
if result.FailureReason != channeldb.FailureReasonTimeout {
|
if result.FailureReason != channeldb.FailureReasonTimeout {
|
||||||
t.Fatal("unexpected failure reason")
|
t.Fatal("unexpected failure reason")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
// Instantiate variables to allow taking a reference from the failure reason.
|
// Instantiate variables to allow taking a reference from the failure reason.
|
||||||
var (
|
var (
|
||||||
reasonError = channeldb.FailureReasonError
|
reasonError = channeldb.FailureReasonError
|
||||||
reasonIncorrectDetails = channeldb.FailureReasonIncorrectPaymentDetails
|
reasonIncorrectDetails = channeldb.FailureReasonPaymentDetails
|
||||||
)
|
)
|
||||||
|
|
||||||
// pairResult contains the result of the interpretation of a payment attempt for
|
// pairResult contains the result of the interpretation of a payment attempt for
|
||||||
|
|||||||
+31
-13
@@ -4398,24 +4398,29 @@ func (r *rpcServer) ListPayments(ctx context.Context,
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// If a payment attempt has been made we can fetch the route.
|
// Fetch the payment's route and preimage. If no HTLC was
|
||||||
// Otherwise we'll just populate the RPC response with an empty
|
// successful, an empty route and preimage will be used.
|
||||||
// one.
|
var (
|
||||||
var route route.Route
|
route route.Route
|
||||||
if payment.Attempt != nil {
|
preimage lntypes.Preimage
|
||||||
route = payment.Attempt.Route
|
)
|
||||||
|
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[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this payment is settled, the preimage will be available.
|
|
||||||
var preimage lntypes.Preimage
|
|
||||||
if payment.PaymentPreimage != nil {
|
|
||||||
preimage = *payment.PaymentPreimage
|
|
||||||
}
|
|
||||||
|
|
||||||
msatValue := int64(payment.Info.Value)
|
msatValue := int64(payment.Info.Value)
|
||||||
satValue := int64(payment.Info.Value.ToSatoshis())
|
satValue := int64(payment.Info.Value.ToSatoshis())
|
||||||
|
|
||||||
@@ -4424,13 +4429,25 @@ func (r *rpcServer) ListPayments(ctx context.Context,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
htlcs := make([]*lnrpc.HTLCAttempt, 0, len(payment.HTLCs))
|
||||||
|
for _, dbHTLC := range payment.HTLCs {
|
||||||
|
htlc, err := r.routerBackend.MarshalHTLCAttempt(dbHTLC)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
htlcs = append(htlcs, htlc)
|
||||||
|
}
|
||||||
|
|
||||||
paymentHash := payment.Info.PaymentHash
|
paymentHash := payment.Info.PaymentHash
|
||||||
|
creationTimeNS := routerrpc.MarshalTimeNano(payment.Info.CreationTime)
|
||||||
paymentsResp.Payments = append(paymentsResp.Payments, &lnrpc.Payment{
|
paymentsResp.Payments = append(paymentsResp.Payments, &lnrpc.Payment{
|
||||||
PaymentHash: hex.EncodeToString(paymentHash[:]),
|
PaymentHash: hex.EncodeToString(paymentHash[:]),
|
||||||
Value: satValue,
|
Value: satValue,
|
||||||
ValueMsat: msatValue,
|
ValueMsat: msatValue,
|
||||||
ValueSat: satValue,
|
ValueSat: satValue,
|
||||||
CreationDate: payment.Info.CreationDate.Unix(),
|
CreationDate: payment.Info.CreationTime.Unix(),
|
||||||
|
CreationTimeNs: creationTimeNS,
|
||||||
Path: path,
|
Path: path,
|
||||||
Fee: int64(route.TotalFees().ToSatoshis()),
|
Fee: int64(route.TotalFees().ToSatoshis()),
|
||||||
FeeSat: int64(route.TotalFees().ToSatoshis()),
|
FeeSat: int64(route.TotalFees().ToSatoshis()),
|
||||||
@@ -4438,6 +4455,7 @@ func (r *rpcServer) ListPayments(ctx context.Context,
|
|||||||
PaymentPreimage: hex.EncodeToString(preimage[:]),
|
PaymentPreimage: hex.EncodeToString(preimage[:]),
|
||||||
PaymentRequest: string(payment.Info.PaymentRequest),
|
PaymentRequest: string(payment.Info.PaymentRequest),
|
||||||
Status: status,
|
Status: status,
|
||||||
|
Htlcs: htlcs,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user