Merge pull request #8177 from yyforyongyu/payment-status

routerrpc: optionally return the new payment status
This commit is contained in:
Yong 2023-11-30 17:15:23 +08:00 committed by GitHub
commit 9f42459036
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 371 additions and 216 deletions

View File

@ -63,6 +63,11 @@
* A new config value, * A new config value,
[http-header-timeout](https://github.com/lightningnetwork/lnd/pull/7715), is added so users can specify the amount of time the http server will wait for a request to complete before closing the connection. The default value is 5 seconds. [http-header-timeout](https://github.com/lightningnetwork/lnd/pull/7715), is added so users can specify the amount of time the http server will wait for a request to complete before closing the connection. The default value is 5 seconds.
* [`routerrpc.usestatusinitiated` is
introduced](https://github.com/lightningnetwork/lnd/pull/8177) to signal that
the new payment status `Payment_INITIATED` should be used for payment-related
RPCs. It's recommended to use it to provide granular controls over payments.
## RPC Additions ## RPC Additions
* [Deprecated](https://github.com/lightningnetwork/lnd/pull/7175) * [Deprecated](https://github.com/lightningnetwork/lnd/pull/7175)

View File

@ -490,6 +490,10 @@ var allTestCases = []*lntest.TestCase{
Name: "trackpayments", Name: "trackpayments",
TestFunc: testTrackPayments, TestFunc: testTrackPayments,
}, },
{
Name: "trackpayments compatible",
TestFunc: testTrackPaymentsCompatible,
},
{ {
Name: "open channel fee policy", Name: "open channel fee policy",
TestFunc: testOpenChannelUpdateFeePolicy, TestFunc: testOpenChannelUpdateFeePolicy,

View File

@ -20,6 +20,17 @@ func testMaxHtlcPathfind(ht *lntest.HarnessTest) {
maxHtlcs := 5 maxHtlcs := 5
alice, bob := ht.Alice, ht.Bob alice, bob := ht.Alice, ht.Bob
// Restart nodes with the new flag so they understand the new payment
// status.
ht.RestartNodeWithExtraArgs(alice, []string{
"--routerrpc.usestatusinitiated",
})
ht.RestartNodeWithExtraArgs(bob, []string{
"--routerrpc.usestatusinitiated",
})
ht.EnsureConnected(alice, bob)
chanPoint := ht.OpenChannel( chanPoint := ht.OpenChannel(
alice, bob, lntest.OpenChannelParams{ alice, bob, lntest.OpenChannelParams{
Amt: 1000000, Amt: 1000000,

View File

@ -14,8 +14,16 @@ import (
// testTrackPayments tests whether a client that calls the TrackPayments api // testTrackPayments tests whether a client that calls the TrackPayments api
// receives payment updates. // receives payment updates.
func testTrackPayments(ht *lntest.HarnessTest) { func testTrackPayments(ht *lntest.HarnessTest) {
// Open a channel between alice and bob.
alice, bob := ht.Alice, ht.Bob alice, bob := ht.Alice, ht.Bob
// Restart Alice with the new flag so she understands the new payment
// status.
ht.RestartNodeWithExtraArgs(alice, []string{
"--routerrpc.usestatusinitiated",
})
// Open a channel between alice and bob.
ht.EnsureConnected(alice, bob)
channel := ht.OpenChannel( channel := ht.OpenChannel(
alice, bob, lntest.OpenChannelParams{ alice, bob, lntest.OpenChannelParams{
Amt: btcutil.Amount(300000), Amt: btcutil.Amount(300000),
@ -47,35 +55,114 @@ func testTrackPayments(ht *lntest.HarnessTest) {
// Make sure the payment doesn't error due to invalid parameters or so. // Make sure the payment doesn't error due to invalid parameters or so.
_, err := paymentClient.Recv() _, err := paymentClient.Recv()
require.NoError(ht, err, "unable to get payment update.") require.NoError(ht, err, "unable to get payment update")
// Assert the first payment update is an inflight update. // Assert the first payment update is an initiated update.
update1, err := tracker.Recv() update1, err := tracker.Recv()
require.NoError(ht, err, "unable to receive payment update 1.") require.NoError(ht, err, "unable to receive payment update 1")
require.Equal( require.Equal(ht, lnrpc.Payment_INITIATED, update1.Status)
ht, lnrpc.PaymentFailureReason_FAILURE_REASON_NONE, require.Equal(ht, lnrpc.PaymentFailureReason_FAILURE_REASON_NONE,
update1.FailureReason, update1.FailureReason)
)
require.Equal(ht, lnrpc.Payment_IN_FLIGHT, update1.Status)
require.Equal(ht, invoice.PaymentRequest, update1.PaymentRequest) require.Equal(ht, invoice.PaymentRequest, update1.PaymentRequest)
require.Equal(ht, amountMsat, update1.ValueMsat) require.Equal(ht, amountMsat, update1.ValueMsat)
// Assert the second payment update is a payment success update. // Assert the first payment update is an inflight update.
update2, err := tracker.Recv() update2, err := tracker.Recv()
require.NoError(ht, err, "unable to receive payment update 2.") require.NoError(ht, err, "unable to receive payment update 2")
require.Equal( require.Equal(ht, lnrpc.Payment_IN_FLIGHT, update2.Status)
ht, lnrpc.PaymentFailureReason_FAILURE_REASON_NONE, require.Equal(ht, lnrpc.PaymentFailureReason_FAILURE_REASON_NONE,
update2.FailureReason, update2.FailureReason)
)
require.Equal(ht, lnrpc.Payment_SUCCEEDED, update2.Status)
require.Equal(ht, invoice.PaymentRequest, update2.PaymentRequest) require.Equal(ht, invoice.PaymentRequest, update2.PaymentRequest)
require.Equal(ht, amountMsat, update2.ValueMsat) require.Equal(ht, amountMsat, update2.ValueMsat)
require.Equal(
ht, hex.EncodeToString(invoice.RPreimage), // Assert the third payment update is a payment success update.
update2.PaymentPreimage, update3, err := tracker.Recv()
) require.NoError(ht, err, "unable to receive payment update 3")
require.Equal(ht, lnrpc.Payment_SUCCEEDED, update3.Status)
require.Equal(ht, lnrpc.PaymentFailureReason_FAILURE_REASON_NONE,
update3.FailureReason)
require.Equal(ht, invoice.PaymentRequest, update3.PaymentRequest)
require.Equal(ht, amountMsat, update3.ValueMsat)
require.Equal(ht, hex.EncodeToString(invoice.RPreimage),
update3.PaymentPreimage)
// TODO(yy): remove the sleep once the following bug is fixed.
// When the invoice is reported settled, the commitment dance is not
// yet finished, which can cause an error when closing the channel,
// saying there's active HTLCs. We need to investigate this issue and
// reverse the order to, first finish the commitment dance, then report
// the invoice as settled.
time.Sleep(2 * time.Second)
ht.CloseChannel(alice, channel)
}
// testTrackPaymentsCompatible checks that when `routerrpc.usestatusinitiated`
// is not set, the new Payment_INITIATED is replaced with Payment_IN_FLIGHT.
func testTrackPaymentsCompatible(ht *lntest.HarnessTest) {
// Open a channel between alice and bob.
alice, bob := ht.Alice, ht.Bob
channel := ht.OpenChannel(
alice, bob, lntest.OpenChannelParams{
Amt: btcutil.Amount(300000),
},
)
// Call the TrackPayments api to listen for payment updates.
req := &routerrpc.TrackPaymentsRequest{
NoInflightUpdates: false,
}
tracker := alice.RPC.TrackPayments(req)
// Create an invoice from bob.
var amountMsat int64 = 1000
invoiceResp := bob.RPC.AddInvoice(
&lnrpc.Invoice{
ValueMsat: amountMsat,
},
)
invoice := bob.RPC.LookupInvoice(invoiceResp.RHash)
// Send payment from alice to bob.
paymentClient := alice.RPC.SendPayment(
&routerrpc.SendPaymentRequest{
PaymentRequest: invoice.PaymentRequest,
TimeoutSeconds: 60,
},
)
// Assert the first track payment update is an inflight update.
update1, err := tracker.Recv()
require.NoError(ht, err, "unable to receive payment update 1")
require.Equal(ht, lnrpc.Payment_IN_FLIGHT, update1.Status)
// Assert the first track payment update is an inflight update.
update2, err := tracker.Recv()
require.NoError(ht, err, "unable to receive payment update 2")
require.Equal(ht, lnrpc.Payment_IN_FLIGHT, update2.Status)
// Assert the third track payment update is a payment success update.
update3, err := tracker.Recv()
require.NoError(ht, err, "unable to receive payment update 3")
require.Equal(ht, lnrpc.Payment_SUCCEEDED, update3.Status)
// Assert the first payment client update is an inflight update.
payment1, err := paymentClient.Recv()
require.NoError(ht, err, "unable to get payment update")
require.Equal(ht, lnrpc.Payment_IN_FLIGHT, payment1.Status)
// Assert the second payment client update is an inflight update.
payment2, err := paymentClient.Recv()
require.NoError(ht, err, "unable to get payment update")
require.Equal(ht, lnrpc.Payment_IN_FLIGHT, payment2.Status)
// Assert the third payment client update is a success update.
payment3, err := paymentClient.Recv()
require.NoError(ht, err, "unable to get payment update")
require.Equal(ht, lnrpc.Payment_SUCCEEDED, payment3.Status)
// TODO(yy): remove the sleep once the following bug is fixed. // TODO(yy): remove the sleep once the following bug is fixed.
// When the invoice is reported settled, the commitment dance is not // When the invoice is reported settled, the commitment dance is not

View File

@ -10,9 +10,18 @@ import (
// The fields with struct tags are meant to be parsed as normal configuration // The fields with struct tags are meant to be parsed as normal configuration
// options, while if able to be populated, the latter fields MUST also be // options, while if able to be populated, the latter fields MUST also be
// specified. // specified.
//
//nolint:lll
type Config struct { type Config struct {
RoutingConfig RoutingConfig
// UseStatusInitiated is a boolean that indicates whether the router
// should use the new status code `Payment_INITIATED`.
//
// TODO(yy): remove this config after the new status code is fully
// deployed to the network(v0.20.0).
UseStatusInitiated bool `long:"usestatusinitiated" description:"If true, the router will send Payment_INITIATED for new payments, otherwise Payment_In_FLIGHT will be sent for compatibility concerns."`
// RouterMacPath is the path for the router macaroon. If unspecified // RouterMacPath is the path for the router macaroon. If unspecified
// then we assume that the macaroon will be found under the network // then we assume that the macaroon will be found under the network
// directory, named DefaultRouterMacFilename. // directory, named DefaultRouterMacFilename.

View File

@ -407,17 +407,11 @@ type SendPaymentRequest struct {
// //
// The fields amt and amt_msat are mutually exclusive. // The fields amt and amt_msat are mutually exclusive.
Amt int64 `protobuf:"varint,2,opt,name=amt,proto3" json:"amt,omitempty"` Amt int64 `protobuf:"varint,2,opt,name=amt,proto3" json:"amt,omitempty"`
// Number of millisatoshis to send.
//
// The fields amt and amt_msat are mutually exclusive.
AmtMsat int64 `protobuf:"varint,12,opt,name=amt_msat,json=amtMsat,proto3" json:"amt_msat,omitempty"`
// The hash to use within the payment's HTLC // The hash to use within the payment's HTLC
PaymentHash []byte `protobuf:"bytes,3,opt,name=payment_hash,json=paymentHash,proto3" json:"payment_hash,omitempty"` PaymentHash []byte `protobuf:"bytes,3,opt,name=payment_hash,json=paymentHash,proto3" json:"payment_hash,omitempty"`
// The CLTV delta from the current height that should be used to set the // The CLTV delta from the current height that should be used to set the
// timelock for the final hop. // timelock for the final hop.
FinalCltvDelta int32 `protobuf:"varint,4,opt,name=final_cltv_delta,json=finalCltvDelta,proto3" json:"final_cltv_delta,omitempty"` FinalCltvDelta int32 `protobuf:"varint,4,opt,name=final_cltv_delta,json=finalCltvDelta,proto3" json:"final_cltv_delta,omitempty"`
// An optional payment addr to be included within the last hop of the route.
PaymentAddr []byte `protobuf:"bytes,20,opt,name=payment_addr,json=paymentAddr,proto3" json:"payment_addr,omitempty"`
// A bare-bones invoice for a payment within the Lightning Network. With the // A bare-bones invoice for a payment within the Lightning Network. With the
// details of the invoice, the sender has all the data necessary to send a // details of the invoice, the sender has all the data necessary to send a
// payment to the recipient. The amount in the payment request may be zero. In // payment to the recipient. The amount in the payment request may be zero. In
@ -436,27 +430,14 @@ type SendPaymentRequest struct {
// //
// The fields fee_limit_sat and fee_limit_msat are mutually exclusive. // The fields fee_limit_sat and fee_limit_msat are mutually exclusive.
FeeLimitSat int64 `protobuf:"varint,7,opt,name=fee_limit_sat,json=feeLimitSat,proto3" json:"fee_limit_sat,omitempty"` FeeLimitSat int64 `protobuf:"varint,7,opt,name=fee_limit_sat,json=feeLimitSat,proto3" json:"fee_limit_sat,omitempty"`
// The maximum number of millisatoshis that will be paid as a fee of the
// payment. If this field is left to the default value of 0, only zero-fee
// routes will be considered. This usually means single hop routes connecting
// directly to the destination. To send the payment without a fee limit, use
// max int here.
//
// The fields fee_limit_sat and fee_limit_msat are mutually exclusive.
FeeLimitMsat int64 `protobuf:"varint,13,opt,name=fee_limit_msat,json=feeLimitMsat,proto3" json:"fee_limit_msat,omitempty"`
// Deprecated, use outgoing_chan_ids. The channel id of the channel that must // Deprecated, use outgoing_chan_ids. The channel id of the channel that must
// be taken to the first hop. If zero, any channel may be used (unless // be taken to the first hop. If zero, any channel may be used (unless
// outgoing_chan_ids are set). // outgoing_chan_ids are set).
// //
// Deprecated: Marked as deprecated in routerrpc/router.proto. // Deprecated: Marked as deprecated in routerrpc/router.proto.
OutgoingChanId uint64 `protobuf:"varint,8,opt,name=outgoing_chan_id,json=outgoingChanId,proto3" json:"outgoing_chan_id,omitempty"` OutgoingChanId uint64 `protobuf:"varint,8,opt,name=outgoing_chan_id,json=outgoingChanId,proto3" json:"outgoing_chan_id,omitempty"`
// The channel ids of the channels are allowed for the first hop. If empty, // An optional maximum total time lock for the route. This should not
// any channel may be used. // exceed lnd's `--max-cltv-expiry` setting. If zero, then the value of
OutgoingChanIds []uint64 `protobuf:"varint,19,rep,packed,name=outgoing_chan_ids,json=outgoingChanIds,proto3" json:"outgoing_chan_ids,omitempty"`
// The pubkey of the last hop of the route. If empty, any hop may be used.
LastHopPubkey []byte `protobuf:"bytes,14,opt,name=last_hop_pubkey,json=lastHopPubkey,proto3" json:"last_hop_pubkey,omitempty"`
// An optional maximum total time lock for the route. This should not exceed
// lnd's `--max-cltv-expiry` setting. If zero, then the value of
// `--max-cltv-expiry` is enforced. // `--max-cltv-expiry` is enforced.
CltvLimit int32 `protobuf:"varint,9,opt,name=cltv_limit,json=cltvLimit,proto3" json:"cltv_limit,omitempty"` CltvLimit int32 `protobuf:"varint,9,opt,name=cltv_limit,json=cltvLimit,proto3" json:"cltv_limit,omitempty"`
// Optional route hints to reach the destination through private channels. // Optional route hints to reach the destination through private channels.
@ -467,6 +448,20 @@ type SendPaymentRequest struct {
// required to be in the custom range >= 65536. When using REST, the values // required to be in the custom range >= 65536. When using REST, the values
// must be encoded as base64. // must be encoded as base64.
DestCustomRecords map[uint64][]byte `protobuf:"bytes,11,rep,name=dest_custom_records,json=destCustomRecords,proto3" json:"dest_custom_records,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` DestCustomRecords map[uint64][]byte `protobuf:"bytes,11,rep,name=dest_custom_records,json=destCustomRecords,proto3" json:"dest_custom_records,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
// Number of millisatoshis to send.
//
// The fields amt and amt_msat are mutually exclusive.
AmtMsat int64 `protobuf:"varint,12,opt,name=amt_msat,json=amtMsat,proto3" json:"amt_msat,omitempty"`
// The maximum number of millisatoshis that will be paid as a fee of the
// payment. If this field is left to the default value of 0, only zero-fee
// routes will be considered. This usually means single hop routes connecting
// directly to the destination. To send the payment without a fee limit, use
// max int here.
//
// The fields fee_limit_sat and fee_limit_msat are mutually exclusive.
FeeLimitMsat int64 `protobuf:"varint,13,opt,name=fee_limit_msat,json=feeLimitMsat,proto3" json:"fee_limit_msat,omitempty"`
// The pubkey of the last hop of the route. If empty, any hop may be used.
LastHopPubkey []byte `protobuf:"bytes,14,opt,name=last_hop_pubkey,json=lastHopPubkey,proto3" json:"last_hop_pubkey,omitempty"`
// If set, circular payments to self are permitted. // If set, circular payments to self are permitted.
AllowSelfPayment bool `protobuf:"varint,15,opt,name=allow_self_payment,json=allowSelfPayment,proto3" json:"allow_self_payment,omitempty"` AllowSelfPayment bool `protobuf:"varint,15,opt,name=allow_self_payment,json=allowSelfPayment,proto3" json:"allow_self_payment,omitempty"`
// Features assumed to be supported by the final node. All transitive feature // Features assumed to be supported by the final node. All transitive feature
@ -481,6 +476,11 @@ type SendPaymentRequest struct {
// If set, only the final payment update is streamed back. Intermediate updates // If set, only the final payment update is streamed back. Intermediate updates
// that show which htlcs are still in flight are suppressed. // that show which htlcs are still in flight are suppressed.
NoInflightUpdates bool `protobuf:"varint,18,opt,name=no_inflight_updates,json=noInflightUpdates,proto3" json:"no_inflight_updates,omitempty"` NoInflightUpdates bool `protobuf:"varint,18,opt,name=no_inflight_updates,json=noInflightUpdates,proto3" json:"no_inflight_updates,omitempty"`
// The channel ids of the channels are allowed for the first hop. If empty,
// any channel may be used.
OutgoingChanIds []uint64 `protobuf:"varint,19,rep,packed,name=outgoing_chan_ids,json=outgoingChanIds,proto3" json:"outgoing_chan_ids,omitempty"`
// An optional payment addr to be included within the last hop of the route.
PaymentAddr []byte `protobuf:"bytes,20,opt,name=payment_addr,json=paymentAddr,proto3" json:"payment_addr,omitempty"`
// The largest payment split that should be attempted when making a payment if // The largest payment split that should be attempted when making a payment if
// splitting is necessary. Setting this value will effectively cause lnd to // splitting is necessary. Setting this value will effectively cause lnd to
// split more aggressively, vs only when it thinks it needs to. Note that this // split more aggressively, vs only when it thinks it needs to. Note that this
@ -539,13 +539,6 @@ func (x *SendPaymentRequest) GetAmt() int64 {
return 0 return 0
} }
func (x *SendPaymentRequest) GetAmtMsat() int64 {
if x != nil {
return x.AmtMsat
}
return 0
}
func (x *SendPaymentRequest) GetPaymentHash() []byte { func (x *SendPaymentRequest) GetPaymentHash() []byte {
if x != nil { if x != nil {
return x.PaymentHash return x.PaymentHash
@ -560,13 +553,6 @@ func (x *SendPaymentRequest) GetFinalCltvDelta() int32 {
return 0 return 0
} }
func (x *SendPaymentRequest) GetPaymentAddr() []byte {
if x != nil {
return x.PaymentAddr
}
return nil
}
func (x *SendPaymentRequest) GetPaymentRequest() string { func (x *SendPaymentRequest) GetPaymentRequest() string {
if x != nil { if x != nil {
return x.PaymentRequest return x.PaymentRequest
@ -588,13 +574,6 @@ func (x *SendPaymentRequest) GetFeeLimitSat() int64 {
return 0 return 0
} }
func (x *SendPaymentRequest) GetFeeLimitMsat() int64 {
if x != nil {
return x.FeeLimitMsat
}
return 0
}
// Deprecated: Marked as deprecated in routerrpc/router.proto. // Deprecated: Marked as deprecated in routerrpc/router.proto.
func (x *SendPaymentRequest) GetOutgoingChanId() uint64 { func (x *SendPaymentRequest) GetOutgoingChanId() uint64 {
if x != nil { if x != nil {
@ -603,20 +582,6 @@ func (x *SendPaymentRequest) GetOutgoingChanId() uint64 {
return 0 return 0
} }
func (x *SendPaymentRequest) GetOutgoingChanIds() []uint64 {
if x != nil {
return x.OutgoingChanIds
}
return nil
}
func (x *SendPaymentRequest) GetLastHopPubkey() []byte {
if x != nil {
return x.LastHopPubkey
}
return nil
}
func (x *SendPaymentRequest) GetCltvLimit() int32 { func (x *SendPaymentRequest) GetCltvLimit() int32 {
if x != nil { if x != nil {
return x.CltvLimit return x.CltvLimit
@ -638,6 +603,27 @@ func (x *SendPaymentRequest) GetDestCustomRecords() map[uint64][]byte {
return nil return nil
} }
func (x *SendPaymentRequest) GetAmtMsat() int64 {
if x != nil {
return x.AmtMsat
}
return 0
}
func (x *SendPaymentRequest) GetFeeLimitMsat() int64 {
if x != nil {
return x.FeeLimitMsat
}
return 0
}
func (x *SendPaymentRequest) GetLastHopPubkey() []byte {
if x != nil {
return x.LastHopPubkey
}
return nil
}
func (x *SendPaymentRequest) GetAllowSelfPayment() bool { func (x *SendPaymentRequest) GetAllowSelfPayment() bool {
if x != nil { if x != nil {
return x.AllowSelfPayment return x.AllowSelfPayment
@ -666,6 +652,20 @@ func (x *SendPaymentRequest) GetNoInflightUpdates() bool {
return false return false
} }
func (x *SendPaymentRequest) GetOutgoingChanIds() []uint64 {
if x != nil {
return x.OutgoingChanIds
}
return nil
}
func (x *SendPaymentRequest) GetPaymentAddr() []byte {
if x != nil {
return x.PaymentAddr
}
return nil
}
func (x *SendPaymentRequest) GetMaxShardSizeMsat() uint64 { func (x *SendPaymentRequest) GetMaxShardSizeMsat() uint64 {
if x != nil { if x != nil {
return x.MaxShardSizeMsat return x.MaxShardSizeMsat
@ -3298,56 +3298,56 @@ var file_routerrpc_router_proto_rawDesc = []byte{
0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x64,
0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x65, 0x73, 0x74, 0x12, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x65, 0x73, 0x74, 0x12,
0x10, 0x0a, 0x03, 0x61, 0x6d, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x61, 0x6d, 0x10, 0x0a, 0x03, 0x61, 0x6d, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x61, 0x6d,
0x74, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x6d, 0x74, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, 0x0c, 0x20, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x68, 0x61, 0x73,
0x01, 0x28, 0x03, 0x52, 0x07, 0x61, 0x6d, 0x74, 0x4d, 0x73, 0x61, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74,
0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x48, 0x61, 0x73, 0x68, 0x12, 0x28, 0x0a, 0x10, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x63, 0x6c,
0x28, 0x0c, 0x52, 0x0b, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x74, 0x76, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e,
0x28, 0x0a, 0x10, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x63, 0x6c, 0x74, 0x76, 0x5f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x43, 0x6c, 0x74, 0x76, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x12, 0x27,
0x6c, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x0a, 0x0f, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73,
0x43, 0x6c, 0x74, 0x76, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x79, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74,
0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x74, 0x69, 0x6d, 0x65, 0x6f,
0x0b, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x41, 0x64, 0x64, 0x72, 0x12, 0x27, 0x0a, 0x0f, 0x75, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05,
0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x52, 0x0e, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73,
0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x66, 0x65, 0x65, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x5f, 0x73, 0x61,
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x66, 0x65, 0x65, 0x4c, 0x69, 0x6d, 0x69,
0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x74, 0x53, 0x61, 0x74, 0x12, 0x2e, 0x0a, 0x10, 0x6f, 0x75, 0x74, 0x67, 0x6f, 0x69, 0x6e, 0x67,
0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x22, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x42, 0x04,
0x0a, 0x0d, 0x66, 0x65, 0x65, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x5f, 0x73, 0x61, 0x74, 0x18, 0x18, 0x01, 0x30, 0x01, 0x52, 0x0e, 0x6f, 0x75, 0x74, 0x67, 0x6f, 0x69, 0x6e, 0x67, 0x43, 0x68,
0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x66, 0x65, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x53, 0x61, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x74, 0x76, 0x5f, 0x6c, 0x69, 0x6d,
0x61, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x66, 0x65, 0x65, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x5f, 0x69, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x63, 0x6c, 0x74, 0x76, 0x4c, 0x69,
0x6d, 0x73, 0x61, 0x74, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x66, 0x65, 0x65, 0x4c, 0x6d, 0x69, 0x74, 0x12, 0x31, 0x0a, 0x0b, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x68, 0x69, 0x6e,
0x69, 0x6d, 0x69, 0x74, 0x4d, 0x73, 0x61, 0x74, 0x12, 0x2e, 0x0a, 0x10, 0x6f, 0x75, 0x74, 0x67, 0x74, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63,
0x6f, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x48, 0x69, 0x6e, 0x74, 0x52, 0x0a, 0x72, 0x6f, 0x75, 0x74,
0x28, 0x04, 0x42, 0x04, 0x18, 0x01, 0x30, 0x01, 0x52, 0x0e, 0x6f, 0x75, 0x74, 0x67, 0x6f, 0x69, 0x65, 0x48, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x64, 0x0a, 0x13, 0x64, 0x65, 0x73, 0x74, 0x5f, 0x63,
0x6e, 0x67, 0x43, 0x68, 0x61, 0x6e, 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x6f, 0x75, 0x74, 0x67, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x18, 0x0b, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e,
0x53, 0x65, 0x6e, 0x64, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65, 0x63,
0x6f, 0x72, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x11, 0x64, 0x65, 0x73, 0x74, 0x43,
0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x12, 0x19, 0x0a, 0x08,
0x61, 0x6d, 0x74, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07,
0x61, 0x6d, 0x74, 0x4d, 0x73, 0x61, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x66, 0x65, 0x65, 0x5f, 0x6c,
0x69, 0x6d, 0x69, 0x74, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03, 0x52,
0x0c, 0x66, 0x65, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x4d, 0x73, 0x61, 0x74, 0x12, 0x26, 0x0a,
0x0f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x68, 0x6f, 0x70, 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79,
0x18, 0x0e, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x6c, 0x61, 0x73, 0x74, 0x48, 0x6f, 0x70, 0x50,
0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x2c, 0x0a, 0x12, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x73,
0x65, 0x6c, 0x66, 0x5f, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28,
0x08, 0x52, 0x10, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x53, 0x65, 0x6c, 0x66, 0x50, 0x61, 0x79, 0x6d,
0x65, 0x6e, 0x74, 0x12, 0x36, 0x0a, 0x0d, 0x64, 0x65, 0x73, 0x74, 0x5f, 0x66, 0x65, 0x61, 0x74,
0x75, 0x72, 0x65, 0x73, 0x18, 0x10, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x6c, 0x6e, 0x72,
0x70, 0x63, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x42, 0x69, 0x74, 0x52, 0x0c, 0x64,
0x65, 0x73, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6d,
0x61, 0x78, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08,
0x6d, 0x61, 0x78, 0x50, 0x61, 0x72, 0x74, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x6e, 0x6f, 0x5f, 0x69,
0x6e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x18,
0x12, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x6e, 0x6f, 0x49, 0x6e, 0x66, 0x6c, 0x69, 0x67, 0x68,
0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x6f, 0x75, 0x74, 0x67,
0x6f, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x13, 0x20, 0x6f, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x13, 0x20,
0x03, 0x28, 0x04, 0x52, 0x0f, 0x6f, 0x75, 0x74, 0x67, 0x6f, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x61, 0x03, 0x28, 0x04, 0x52, 0x0f, 0x6f, 0x75, 0x74, 0x67, 0x6f, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x61,
0x6e, 0x49, 0x64, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x68, 0x6f, 0x70, 0x6e, 0x49, 0x64, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f,
0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x6c, 0x61, 0x64, 0x64, 0x72, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x70, 0x61, 0x79, 0x6d,
0x61, 0x73, 0x74, 0x48, 0x6f, 0x70, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x6e, 0x74, 0x41, 0x64, 0x64, 0x72, 0x12, 0x2d, 0x0a, 0x13, 0x6d, 0x61, 0x78, 0x5f, 0x73,
0x63, 0x6c, 0x74, 0x76, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x05,
0x52, 0x09, 0x63, 0x6c, 0x74, 0x76, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x31, 0x0a, 0x0b, 0x72,
0x6f, 0x75, 0x74, 0x65, 0x5f, 0x68, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b,
0x32, 0x10, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x48, 0x69,
0x6e, 0x74, 0x52, 0x0a, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x48, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x64,
0x0a, 0x13, 0x64, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x72, 0x65,
0x63, 0x6f, 0x72, 0x64, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x72, 0x6f,
0x75, 0x74, 0x65, 0x72, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x50, 0x61, 0x79, 0x6d,
0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x43,
0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72,
0x79, 0x52, 0x11, 0x64, 0x65, 0x73, 0x74, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65, 0x63,
0x6f, 0x72, 0x64, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x73, 0x65,
0x6c, 0x66, 0x5f, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x08,
0x52, 0x10, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x53, 0x65, 0x6c, 0x66, 0x50, 0x61, 0x79, 0x6d, 0x65,
0x6e, 0x74, 0x12, 0x36, 0x0a, 0x0d, 0x64, 0x65, 0x73, 0x74, 0x5f, 0x66, 0x65, 0x61, 0x74, 0x75,
0x72, 0x65, 0x73, 0x18, 0x10, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x6c, 0x6e, 0x72, 0x70,
0x63, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x42, 0x69, 0x74, 0x52, 0x0c, 0x64, 0x65,
0x73, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61,
0x78, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x6d,
0x61, 0x78, 0x50, 0x61, 0x72, 0x74, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x6e, 0x6f, 0x5f, 0x69, 0x6e,
0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x18, 0x12,
0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x6e, 0x6f, 0x49, 0x6e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74,
0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x12, 0x2d, 0x0a, 0x13, 0x6d, 0x61, 0x78, 0x5f, 0x73,
0x68, 0x61, 0x72, 0x64, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, 0x15, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, 0x15,
0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x6d, 0x61, 0x78, 0x53, 0x68, 0x61, 0x72, 0x64, 0x53, 0x69, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x6d, 0x61, 0x78, 0x53, 0x68, 0x61, 0x72, 0x64, 0x53, 0x69,
0x7a, 0x65, 0x4d, 0x73, 0x61, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x6d, 0x70, 0x18, 0x16, 0x20, 0x7a, 0x65, 0x4d, 0x73, 0x61, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x6d, 0x70, 0x18, 0x16, 0x20,

View File

@ -182,13 +182,6 @@ message SendPaymentRequest {
*/ */
int64 amt = 2; int64 amt = 2;
/*
Number of millisatoshis to send.
The fields amt and amt_msat are mutually exclusive.
*/
int64 amt_msat = 12;
// The hash to use within the payment's HTLC // The hash to use within the payment's HTLC
bytes payment_hash = 3; bytes payment_hash = 3;
@ -198,9 +191,6 @@ message SendPaymentRequest {
*/ */
int32 final_cltv_delta = 4; int32 final_cltv_delta = 4;
// An optional payment addr to be included within the last hop of the route.
bytes payment_addr = 20;
/* /*
A bare-bones invoice for a payment within the Lightning Network. With the A bare-bones invoice for a payment within the Lightning Network. With the
details of the invoice, the sender has all the data necessary to send a details of the invoice, the sender has all the data necessary to send a
@ -228,17 +218,6 @@ message SendPaymentRequest {
*/ */
int64 fee_limit_sat = 7; int64 fee_limit_sat = 7;
/*
The maximum number of millisatoshis that will be paid as a fee of the
payment. If this field is left to the default value of 0, only zero-fee
routes will be considered. This usually means single hop routes connecting
directly to the destination. To send the payment without a fee limit, use
max int here.
The fields fee_limit_sat and fee_limit_msat are mutually exclusive.
*/
int64 fee_limit_msat = 13;
/* /*
Deprecated, use outgoing_chan_ids. The channel id of the channel that must Deprecated, use outgoing_chan_ids. The channel id of the channel that must
be taken to the first hop. If zero, any channel may be used (unless be taken to the first hop. If zero, any channel may be used (unless
@ -247,19 +226,8 @@ message SendPaymentRequest {
uint64 outgoing_chan_id = 8 [jstype = JS_STRING, deprecated = true]; uint64 outgoing_chan_id = 8 [jstype = JS_STRING, deprecated = true];
/* /*
The channel ids of the channels are allowed for the first hop. If empty, An optional maximum total time lock for the route. This should not
any channel may be used. exceed lnd's `--max-cltv-expiry` setting. If zero, then the value of
*/
repeated uint64 outgoing_chan_ids = 19;
/*
The pubkey of the last hop of the route. If empty, any hop may be used.
*/
bytes last_hop_pubkey = 14;
/*
An optional maximum total time lock for the route. This should not exceed
lnd's `--max-cltv-expiry` setting. If zero, then the value of
`--max-cltv-expiry` is enforced. `--max-cltv-expiry` is enforced.
*/ */
int32 cltv_limit = 9; int32 cltv_limit = 9;
@ -278,6 +246,29 @@ message SendPaymentRequest {
*/ */
map<uint64, bytes> dest_custom_records = 11; map<uint64, bytes> dest_custom_records = 11;
/*
Number of millisatoshis to send.
The fields amt and amt_msat are mutually exclusive.
*/
int64 amt_msat = 12;
/*
The maximum number of millisatoshis that will be paid as a fee of the
payment. If this field is left to the default value of 0, only zero-fee
routes will be considered. This usually means single hop routes connecting
directly to the destination. To send the payment without a fee limit, use
max int here.
The fields fee_limit_sat and fee_limit_msat are mutually exclusive.
*/
int64 fee_limit_msat = 13;
/*
The pubkey of the last hop of the route. If empty, any hop may be used.
*/
bytes last_hop_pubkey = 14;
// If set, circular payments to self are permitted. // If set, circular payments to self are permitted.
bool allow_self_payment = 15; bool allow_self_payment = 15;
@ -302,6 +293,15 @@ message SendPaymentRequest {
*/ */
bool no_inflight_updates = 18; bool no_inflight_updates = 18;
/*
The channel ids of the channels are allowed for the first hop. If empty,
any channel may be used.
*/
repeated uint64 outgoing_chan_ids = 19;
// An optional payment addr to be included within the last hop of the route.
bytes payment_addr = 20;
/* /*
The largest payment split that should be attempted when making a payment if The largest payment split that should be attempted when making a payment if
splitting is necessary. Setting this value will effectively cause lnd to splitting is necessary. Setting this value will effectively cause lnd to

View File

@ -1678,11 +1678,6 @@
"format": "int64", "format": "int64",
"description": "Number of satoshis to send.\n\nThe fields amt and amt_msat are mutually exclusive." "description": "Number of satoshis to send.\n\nThe fields amt and amt_msat are mutually exclusive."
}, },
"amt_msat": {
"type": "string",
"format": "int64",
"description": "Number of millisatoshis to send.\n\nThe fields amt and amt_msat are mutually exclusive."
},
"payment_hash": { "payment_hash": {
"type": "string", "type": "string",
"format": "byte", "format": "byte",
@ -1693,11 +1688,6 @@
"format": "int32", "format": "int32",
"description": "The CLTV delta from the current height that should be used to set the\ntimelock for the final hop." "description": "The CLTV delta from the current height that should be used to set the\ntimelock for the final hop."
}, },
"payment_addr": {
"type": "string",
"format": "byte",
"description": "An optional payment addr to be included within the last hop of the route."
},
"payment_request": { "payment_request": {
"type": "string", "type": "string",
"description": "A bare-bones invoice for a payment within the Lightning Network. With the\ndetails of the invoice, the sender has all the data necessary to send a\npayment to the recipient. The amount in the payment request may be zero. In\nthat case it is required to set the amt field as well. If no payment request\nis specified, the following fields are required: dest, amt and payment_hash." "description": "A bare-bones invoice for a payment within the Lightning Network. With the\ndetails of the invoice, the sender has all the data necessary to send a\npayment to the recipient. The amount in the payment request may be zero. In\nthat case it is required to set the amt field as well. If no payment request\nis specified, the following fields are required: dest, amt and payment_hash."
@ -1712,33 +1702,15 @@
"format": "int64", "format": "int64",
"description": "The maximum number of satoshis that will be paid as a fee of the payment.\nIf this field is left to the default value of 0, only zero-fee routes will\nbe considered. This usually means single hop routes connecting directly to\nthe destination. To send the payment without a fee limit, use max int here.\n\nThe fields fee_limit_sat and fee_limit_msat are mutually exclusive." "description": "The maximum number of satoshis that will be paid as a fee of the payment.\nIf this field is left to the default value of 0, only zero-fee routes will\nbe considered. This usually means single hop routes connecting directly to\nthe destination. To send the payment without a fee limit, use max int here.\n\nThe fields fee_limit_sat and fee_limit_msat are mutually exclusive."
}, },
"fee_limit_msat": {
"type": "string",
"format": "int64",
"description": "The maximum number of millisatoshis that will be paid as a fee of the\npayment. If this field is left to the default value of 0, only zero-fee\nroutes will be considered. This usually means single hop routes connecting\ndirectly to the destination. To send the payment without a fee limit, use\nmax int here.\n\nThe fields fee_limit_sat and fee_limit_msat are mutually exclusive."
},
"outgoing_chan_id": { "outgoing_chan_id": {
"type": "string", "type": "string",
"format": "uint64", "format": "uint64",
"description": "Deprecated, use outgoing_chan_ids. The channel id of the channel that must\nbe taken to the first hop. If zero, any channel may be used (unless\noutgoing_chan_ids are set)." "description": "Deprecated, use outgoing_chan_ids. The channel id of the channel that must\nbe taken to the first hop. If zero, any channel may be used (unless\noutgoing_chan_ids are set)."
}, },
"outgoing_chan_ids": {
"type": "array",
"items": {
"type": "string",
"format": "uint64"
},
"description": "The channel ids of the channels are allowed for the first hop. If empty,\nany channel may be used."
},
"last_hop_pubkey": {
"type": "string",
"format": "byte",
"description": "The pubkey of the last hop of the route. If empty, any hop may be used."
},
"cltv_limit": { "cltv_limit": {
"type": "integer", "type": "integer",
"format": "int32", "format": "int32",
"description": "An optional maximum total time lock for the route. This should not exceed\nlnd's `--max-cltv-expiry` setting. If zero, then the value of\n`--max-cltv-expiry` is enforced." "description": "An optional maximum total time lock for the route. This should not\nexceed lnd's `--max-cltv-expiry` setting. If zero, then the value of\n`--max-cltv-expiry` is enforced."
}, },
"route_hints": { "route_hints": {
"type": "array", "type": "array",
@ -1755,6 +1727,21 @@
}, },
"description": "An optional field that can be used to pass an arbitrary set of TLV records\nto a peer which understands the new records. This can be used to pass\napplication specific data during the payment attempt. Record types are\nrequired to be in the custom range \u003e= 65536. When using REST, the values\nmust be encoded as base64." "description": "An optional field that can be used to pass an arbitrary set of TLV records\nto a peer which understands the new records. This can be used to pass\napplication specific data during the payment attempt. Record types are\nrequired to be in the custom range \u003e= 65536. When using REST, the values\nmust be encoded as base64."
}, },
"amt_msat": {
"type": "string",
"format": "int64",
"description": "Number of millisatoshis to send.\n\nThe fields amt and amt_msat are mutually exclusive."
},
"fee_limit_msat": {
"type": "string",
"format": "int64",
"description": "The maximum number of millisatoshis that will be paid as a fee of the\npayment. If this field is left to the default value of 0, only zero-fee\nroutes will be considered. This usually means single hop routes connecting\ndirectly to the destination. To send the payment without a fee limit, use\nmax int here.\n\nThe fields fee_limit_sat and fee_limit_msat are mutually exclusive."
},
"last_hop_pubkey": {
"type": "string",
"format": "byte",
"description": "The pubkey of the last hop of the route. If empty, any hop may be used."
},
"allow_self_payment": { "allow_self_payment": {
"type": "boolean", "type": "boolean",
"description": "If set, circular payments to self are permitted." "description": "If set, circular payments to self are permitted."
@ -1775,6 +1762,19 @@
"type": "boolean", "type": "boolean",
"description": "If set, only the final payment update is streamed back. Intermediate updates\nthat show which htlcs are still in flight are suppressed." "description": "If set, only the final payment update is streamed back. Intermediate updates\nthat show which htlcs are still in flight are suppressed."
}, },
"outgoing_chan_ids": {
"type": "array",
"items": {
"type": "string",
"format": "uint64"
},
"description": "The channel ids of the channels are allowed for the first hop. If empty,\nany channel may be used."
},
"payment_addr": {
"type": "string",
"format": "byte",
"description": "An optional payment addr to be included within the last hop of the route."
},
"max_shard_size_msat": { "max_shard_size_msat": {
"type": "string", "type": "string",
"format": "uint64", "format": "uint64",

View File

@ -98,6 +98,13 @@ type RouterBackend struct {
// SetChannelAuto exposes the ability to restore automatic channel state // SetChannelAuto exposes the ability to restore automatic channel state
// management after manually setting channel status. // management after manually setting channel status.
SetChannelAuto func(wire.OutPoint) error SetChannelAuto func(wire.OutPoint) error
// UseStatusInitiated is a boolean that indicates whether the router
// should use the new status code `Payment_INITIATED`.
//
// TODO(yy): remove this config after the new status code is fully
// deployed to the network(v0.20.0).
UseStatusInitiated bool
} }
// MissionControl defines the mission control dependencies of routerrpc. // MissionControl defines the mission control dependencies of routerrpc.
@ -1542,7 +1549,9 @@ func (r *RouterBackend) MarshallPayment(payment *channeldb.MPPayment) (
msatValue := int64(payment.Info.Value) msatValue := int64(payment.Info.Value)
satValue := int64(payment.Info.Value.ToSatoshis()) satValue := int64(payment.Info.Value.ToSatoshis())
status, err := convertPaymentStatus(payment.Status) status, err := convertPaymentStatus(
payment.Status, r.UseStatusInitiated,
)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -1589,12 +1598,18 @@ func (r *RouterBackend) MarshallPayment(payment *channeldb.MPPayment) (
// convertPaymentStatus converts a channeldb.PaymentStatus to the type expected // convertPaymentStatus converts a channeldb.PaymentStatus to the type expected
// by the RPC. // by the RPC.
func convertPaymentStatus(dbStatus channeldb.PaymentStatus) ( func convertPaymentStatus(dbStatus channeldb.PaymentStatus, useInit bool) (
lnrpc.Payment_PaymentStatus, error) { lnrpc.Payment_PaymentStatus, error) {
switch dbStatus { switch dbStatus {
case channeldb.StatusInitiated: case channeldb.StatusInitiated:
return lnrpc.Payment_INITIATED, nil // If the client understands the new status, return it.
if useInit {
return lnrpc.Payment_INITIATED, nil
}
// Otherwise remain the old behavior.
return lnrpc.Payment_IN_FLIGHT, nil
case channeldb.StatusInFlight: case channeldb.StatusInFlight:
return lnrpc.Payment_IN_FLIGHT, nil return lnrpc.Payment_IN_FLIGHT, nil

View File

@ -940,11 +940,17 @@ func (s *Server) trackPaymentStream(context context.Context,
} }
result := item.(*channeldb.MPPayment) result := item.(*channeldb.MPPayment)
// Skip in-flight updates unless requested. log.Tracef("Payment %v updated to state %v",
if noInflightUpdates && result.Info.PaymentIdentifier, result.Status)
result.Status == channeldb.StatusInFlight {
continue // Skip in-flight updates unless requested.
if noInflightUpdates {
if result.Status == channeldb.StatusInitiated {
continue
}
if result.Status == channeldb.StatusInFlight {
continue
}
} }
rpcPayment, err := s.cfg.RouterBackend.MarshallPayment( rpcPayment, err := s.cfg.RouterBackend.MarshallPayment(

View File

@ -181,12 +181,29 @@ func NewControlTower(db *channeldb.PaymentControl) ControlTower {
// InitPayment checks or records the given PaymentCreationInfo with the DB, // InitPayment checks or records the given PaymentCreationInfo with the DB,
// making sure it does not already exist as an in-flight payment. Then this // making sure it does not already exist as an in-flight payment. Then this
// method returns successfully, the payment is guaranteed to be in the InFlight // method returns successfully, the payment is guaranteed to be in the
// state. // Initiated state.
func (p *controlTower) InitPayment(paymentHash lntypes.Hash, func (p *controlTower) InitPayment(paymentHash lntypes.Hash,
info *channeldb.PaymentCreationInfo) error { info *channeldb.PaymentCreationInfo) error {
return p.db.InitPayment(paymentHash, info) err := p.db.InitPayment(paymentHash, info)
if err != nil {
return err
}
// Take lock before querying the db to prevent missing or duplicating
// an update.
p.paymentsMtx.Lock(paymentHash)
defer p.paymentsMtx.Unlock(paymentHash)
payment, err := p.db.FetchPayment(paymentHash)
if err != nil {
return err
}
p.notifySubscribers(paymentHash, payment)
return nil
} }
// DeleteFailedAttempts deletes all failed htlcs if the payment was // DeleteFailedAttempts deletes all failed htlcs if the payment was

View File

@ -196,7 +196,7 @@ func TestPaymentControlSubscribeAllSuccess(t *testing.T) {
err = pControl.InitPayment(info1.PaymentIdentifier, info1) err = pControl.InitPayment(info1.PaymentIdentifier, info1)
require.NoError(t, err) require.NoError(t, err)
// Subscription should succeed and immediately report the InFlight // Subscription should succeed and immediately report the Initiated
// status. // status.
subscription, err := pControl.SubscribeAllPayments() subscription, err := pControl.SubscribeAllPayments()
require.NoError(t, err, "expected subscribe to succeed, but got: %v") require.NoError(t, err, "expected subscribe to succeed, but got: %v")
@ -246,8 +246,8 @@ func TestPaymentControlSubscribeAllSuccess(t *testing.T) {
// for each payment. // for each payment.
results := make(map[lntypes.Hash]*channeldb.MPPayment) results := make(map[lntypes.Hash]*channeldb.MPPayment)
// After exactly 5 updates both payments will/should have completed. // After exactly 6 updates both payments will/should have completed.
for i := 0; i < 5; i++ { for i := 0; i < 6; i++ {
select { select {
case item := <-subscription.Updates(): case item := <-subscription.Updates():
id := item.(*channeldb.MPPayment).Info.PaymentIdentifier id := item.(*channeldb.MPPayment).Info.PaymentIdentifier
@ -354,10 +354,6 @@ func TestPaymentControlUnsubscribeSuccess(t *testing.T) {
err = pControl.InitPayment(info.PaymentIdentifier, info) err = pControl.InitPayment(info.PaymentIdentifier, info)
require.NoError(t, err) require.NoError(t, err)
// Register a payment update.
err = pControl.RegisterAttempt(info.PaymentIdentifier, attempt)
require.NoError(t, err)
// Assert all subscriptions receive the update. // Assert all subscriptions receive the update.
select { select {
case update1 := <-subscription1.Updates(): case update1 := <-subscription1.Updates():
@ -376,14 +372,9 @@ func TestPaymentControlUnsubscribeSuccess(t *testing.T) {
// Close the first subscription. // Close the first subscription.
subscription1.Close() subscription1.Close()
// Register another update. // Register a payment update.
failInfo := channeldb.HTLCFailInfo{ err = pControl.RegisterAttempt(info.PaymentIdentifier, attempt)
Reason: channeldb.HTLCFailInternal, require.NoError(t, err)
}
_, err = pControl.FailAttempt(
info.PaymentIdentifier, attempt.AttemptID, &failInfo,
)
require.NoError(t, err, "unable to fail htlc")
// Assert only subscription 2 receives the update. // Assert only subscription 2 receives the update.
select { select {
@ -398,9 +389,14 @@ func TestPaymentControlUnsubscribeSuccess(t *testing.T) {
// Close the second subscription. // Close the second subscription.
subscription2.Close() subscription2.Close()
// Register a last update. // Register another update.
err = pControl.RegisterAttempt(info.PaymentIdentifier, attempt) failInfo := channeldb.HTLCFailInfo{
require.NoError(t, err) Reason: channeldb.HTLCFailInternal,
}
_, err = pControl.FailAttempt(
info.PaymentIdentifier, attempt.AttemptID, &failInfo,
)
require.NoError(t, err, "unable to fail htlc")
// Assert no subscriptions receive the update. // Assert no subscriptions receive the update.
require.Len(t, subscription1.Updates(), 0) require.Len(t, subscription1.Updates(), 0)

View File

@ -715,7 +715,8 @@ func (r *rpcServer) addDeps(s *server, macService *macaroons.Service,
SetChannelDisabled: func(outpoint wire.OutPoint) error { SetChannelDisabled: func(outpoint wire.OutPoint) error {
return s.chanStatusMgr.RequestDisable(outpoint, true) return s.chanStatusMgr.RequestDisable(outpoint, true)
}, },
SetChannelAuto: s.chanStatusMgr.RequestAuto, SetChannelAuto: s.chanStatusMgr.RequestAuto,
UseStatusInitiated: subServerCgs.RouterRPC.UseStatusInitiated,
} }
genInvoiceFeatures := func() *lnwire.FeatureVector { genInvoiceFeatures := func() *lnwire.FeatureVector {

View File

@ -1201,6 +1201,10 @@
; failures in channels. ; failures in channels.
; routerrpc.bimodal.decaytime=168h ; routerrpc.bimodal.decaytime=168h
; If set, the router will send `Payment_INITIATED` for new payments, otherwise
; `Payment_In_FLIGHT` will be sent for compatibility concerns.
; routerrpc.usestatusinitiated=false
[workers] [workers]