diff --git a/docs/release-notes/release-notes-0.22.0.md b/docs/release-notes/release-notes-0.22.0.md index c3367af9cc7..64ffe8a3a5b 100644 --- a/docs/release-notes/release-notes-0.22.0.md +++ b/docs/release-notes/release-notes-0.22.0.md @@ -27,6 +27,22 @@ ## RPC Additions +* `QueryRoutesRequest` now accepts a + [`payment_addr`](https://github.com/lightningnetwork/lnd/issues/9952) + field (the invoice payment secret). When set, an MPP record is injected + into the final hop of the returned route as required by the BOLT 11 spec. + An optional `amp_record` field is also added for AMP payments. + +* `BuildRouteRequest` now accepts an + [`amp_record`](https://github.com/lightningnetwork/lnd/issues/9952) + field to allow building routes for AMP payments. `payment_addr` is now + required by `BuildRoute`. + +* `SendToRouteV2` now + [enforces](https://github.com/lightningnetwork/lnd/issues/9952) that the + final hop of the provided route includes an MPP record, as `payment_secret` + is mandatory per the BOLT 11 spec. + ## lncli Additions # Improvements diff --git a/lnrpc/lightning.pb.go b/lnrpc/lightning.pb.go index 59d01914159..ec3d46ec20f 100644 --- a/lnrpc/lightning.pb.go +++ b/lnrpc/lightning.pb.go @@ -10079,8 +10079,14 @@ type QueryRoutesRequest struct { // The channel ids of the channels allowed for the first hop. If empty, any // channel may be used. OutgoingChanIds []uint64 `protobuf:"varint,20,rep,packed,name=outgoing_chan_ids,json=outgoingChanIds,proto3" json:"outgoing_chan_ids,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + // 32 byte random value included in the invoice. + // The receiver only accepts HTLSs that include this. + PaymentAddr []byte `protobuf:"bytes,21,opt,name=payment_addr,json=paymentAddr,proto3" json:"payment_addr,omitempty"` + // An optional AMP record to be included within the last hop of the route. + // If set, payment_addr must also be set. See AMPRecord for details. + AmpRecord *AMPRecord `protobuf:"bytes,22,opt,name=amp_record,json=ampRecord,proto3" json:"amp_record,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *QueryRoutesRequest) Reset() { @@ -10248,6 +10254,20 @@ func (x *QueryRoutesRequest) GetOutgoingChanIds() []uint64 { return nil } +func (x *QueryRoutesRequest) GetPaymentAddr() []byte { + if x != nil { + return x.PaymentAddr + } + return nil +} + +func (x *QueryRoutesRequest) GetAmpRecord() *AMPRecord { + if x != nil { + return x.AmpRecord + } + return nil +} + type NodePair struct { state protoimpl.MessageState `protogen:"open.v1"` // The sending node of the pair. When using REST, this field must be encoded as @@ -19621,7 +19641,7 @@ const file_lightning_proto_rawDesc = "" + "\x18unsettled_remote_balance\x18\x06 \x01(\v2\r.lnrpc.AmountR\x16unsettledRemoteBalance\x12J\n" + "\x1apending_open_local_balance\x18\a \x01(\v2\r.lnrpc.AmountR\x17pendingOpenLocalBalance\x12L\n" + "\x1bpending_open_remote_balance\x18\b \x01(\v2\r.lnrpc.AmountR\x18pendingOpenRemoteBalance\x12.\n" + - "\x13custom_channel_data\x18\t \x01(\fR\x11customChannelData\"\xc8\a\n" + + "\x13custom_channel_data\x18\t \x01(\fR\x11customChannelData\"\x9c\b\n" + "\x12QueryRoutesRequest\x12\x17\n" + "\apub_key\x18\x01 \x01(\tR\x06pubKey\x12\x10\n" + "\x03amt\x18\x02 \x01(\x03R\x03amt\x12\x19\n" + @@ -19644,7 +19664,10 @@ const file_lightning_proto_rawDesc = "" + "\x15blinded_payment_paths\x18\x13 \x03(\v2\x19.lnrpc.BlindedPaymentPathR\x13blindedPaymentPaths\x126\n" + "\rdest_features\x18\x11 \x03(\x0e2\x11.lnrpc.FeatureBitR\fdestFeatures\x12\x1b\n" + "\ttime_pref\x18\x12 \x01(\x01R\btimePref\x12*\n" + - "\x11outgoing_chan_ids\x18\x14 \x03(\x04R\x0foutgoingChanIds\x1aD\n" + + "\x11outgoing_chan_ids\x18\x14 \x03(\x04R\x0foutgoingChanIds\x12!\n" + + "\fpayment_addr\x18\x15 \x01(\fR\vpaymentAddr\x12/\n" + + "\n" + + "amp_record\x18\x16 \x01(\v2\x10.lnrpc.AMPRecordR\tampRecord\x1aD\n" + "\x16DestCustomRecordsEntry\x12\x10\n" + "\x03key\x18\x01 \x01(\x04R\x03key\x12\x14\n" + "\x05value\x18\x02 \x01(\fR\x05value:\x028\x01J\x04\b\x03\x10\x04\".\n" + @@ -20907,254 +20930,255 @@ var file_lightning_proto_depIdxs = []int32{ 157, // 100: lnrpc.QueryRoutesRequest.route_hints:type_name -> lnrpc.RouteHint 158, // 101: lnrpc.QueryRoutesRequest.blinded_payment_paths:type_name -> lnrpc.BlindedPaymentPath 11, // 102: lnrpc.QueryRoutesRequest.dest_features:type_name -> lnrpc.FeatureBit - 132, // 103: lnrpc.QueryRoutesResponse.routes:type_name -> lnrpc.Route - 130, // 104: lnrpc.Hop.mpp_record:type_name -> lnrpc.MPPRecord - 131, // 105: lnrpc.Hop.amp_record:type_name -> lnrpc.AMPRecord - 246, // 106: lnrpc.Hop.custom_records:type_name -> lnrpc.Hop.CustomRecordsEntry - 129, // 107: lnrpc.Route.hops:type_name -> lnrpc.Hop - 135, // 108: lnrpc.NodeInfo.node:type_name -> lnrpc.LightningNode - 139, // 109: lnrpc.NodeInfo.channels:type_name -> lnrpc.ChannelEdge - 136, // 110: lnrpc.LightningNode.addresses:type_name -> lnrpc.NodeAddress - 247, // 111: lnrpc.LightningNode.features:type_name -> lnrpc.LightningNode.FeaturesEntry - 248, // 112: lnrpc.LightningNode.custom_records:type_name -> lnrpc.LightningNode.CustomRecordsEntry - 249, // 113: lnrpc.RoutingPolicy.custom_records:type_name -> lnrpc.RoutingPolicy.CustomRecordsEntry - 137, // 114: lnrpc.ChannelEdge.node1_policy:type_name -> lnrpc.RoutingPolicy - 137, // 115: lnrpc.ChannelEdge.node2_policy:type_name -> lnrpc.RoutingPolicy - 250, // 116: lnrpc.ChannelEdge.custom_records:type_name -> lnrpc.ChannelEdge.CustomRecordsEntry - 138, // 117: lnrpc.ChannelEdge.auth_proof:type_name -> lnrpc.ChannelAuthProof - 135, // 118: lnrpc.ChannelGraph.nodes:type_name -> lnrpc.LightningNode - 139, // 119: lnrpc.ChannelGraph.edges:type_name -> lnrpc.ChannelEdge - 8, // 120: lnrpc.NodeMetricsRequest.types:type_name -> lnrpc.NodeMetricType - 251, // 121: lnrpc.NodeMetricsResponse.betweenness_centrality:type_name -> lnrpc.NodeMetricsResponse.BetweennessCentralityEntry - 152, // 122: lnrpc.GraphTopologyUpdate.node_updates:type_name -> lnrpc.NodeUpdate - 153, // 123: lnrpc.GraphTopologyUpdate.channel_updates:type_name -> lnrpc.ChannelEdgeUpdate - 154, // 124: lnrpc.GraphTopologyUpdate.closed_chans:type_name -> lnrpc.ClosedChannelUpdate - 136, // 125: lnrpc.NodeUpdate.node_addresses:type_name -> lnrpc.NodeAddress - 252, // 126: lnrpc.NodeUpdate.features:type_name -> lnrpc.NodeUpdate.FeaturesEntry - 43, // 127: lnrpc.ChannelEdgeUpdate.chan_point:type_name -> lnrpc.ChannelPoint - 137, // 128: lnrpc.ChannelEdgeUpdate.routing_policy:type_name -> lnrpc.RoutingPolicy - 43, // 129: lnrpc.ClosedChannelUpdate.chan_point:type_name -> lnrpc.ChannelPoint - 155, // 130: lnrpc.RouteHint.hop_hints:type_name -> lnrpc.HopHint - 159, // 131: lnrpc.BlindedPaymentPath.blinded_path:type_name -> lnrpc.BlindedPath - 11, // 132: lnrpc.BlindedPaymentPath.features:type_name -> lnrpc.FeatureBit - 160, // 133: lnrpc.BlindedPath.blinded_hops:type_name -> lnrpc.BlindedHop - 9, // 134: lnrpc.AMPInvoiceState.state:type_name -> lnrpc.InvoiceHTLCState - 157, // 135: lnrpc.Invoice.route_hints:type_name -> lnrpc.RouteHint - 18, // 136: lnrpc.Invoice.state:type_name -> lnrpc.Invoice.InvoiceState - 164, // 137: lnrpc.Invoice.htlcs:type_name -> lnrpc.InvoiceHTLC - 253, // 138: lnrpc.Invoice.features:type_name -> lnrpc.Invoice.FeaturesEntry - 254, // 139: lnrpc.Invoice.amp_invoice_state:type_name -> lnrpc.Invoice.AmpInvoiceStateEntry - 163, // 140: lnrpc.Invoice.blinded_path_config:type_name -> lnrpc.BlindedPathConfig - 9, // 141: lnrpc.InvoiceHTLC.state:type_name -> lnrpc.InvoiceHTLCState - 255, // 142: lnrpc.InvoiceHTLC.custom_records:type_name -> lnrpc.InvoiceHTLC.CustomRecordsEntry - 165, // 143: lnrpc.InvoiceHTLC.amp:type_name -> lnrpc.AMP - 162, // 144: lnrpc.ListInvoiceResponse.invoices:type_name -> lnrpc.Invoice - 19, // 145: lnrpc.Payment.status:type_name -> lnrpc.Payment.PaymentStatus - 174, // 146: lnrpc.Payment.htlcs:type_name -> lnrpc.HTLCAttempt - 10, // 147: lnrpc.Payment.failure_reason:type_name -> lnrpc.PaymentFailureReason - 256, // 148: lnrpc.Payment.first_hop_custom_records:type_name -> lnrpc.Payment.FirstHopCustomRecordsEntry - 20, // 149: lnrpc.HTLCAttempt.status:type_name -> lnrpc.HTLCAttempt.HTLCStatus - 132, // 150: lnrpc.HTLCAttempt.route:type_name -> lnrpc.Route - 218, // 151: lnrpc.HTLCAttempt.failure:type_name -> lnrpc.Failure - 173, // 152: lnrpc.ListPaymentsResponse.payments:type_name -> lnrpc.Payment - 43, // 153: lnrpc.AbandonChannelRequest.channel_point:type_name -> lnrpc.ChannelPoint - 157, // 154: lnrpc.PayReq.route_hints:type_name -> lnrpc.RouteHint - 257, // 155: lnrpc.PayReq.features:type_name -> lnrpc.PayReq.FeaturesEntry - 158, // 156: lnrpc.PayReq.blinded_paths:type_name -> lnrpc.BlindedPaymentPath - 189, // 157: lnrpc.FeeReportResponse.channel_fees:type_name -> lnrpc.ChannelFeeReport - 43, // 158: lnrpc.PolicyUpdateRequest.chan_point:type_name -> lnrpc.ChannelPoint - 191, // 159: lnrpc.PolicyUpdateRequest.inbound_fee:type_name -> lnrpc.InboundFee - 44, // 160: lnrpc.FailedUpdate.outpoint:type_name -> lnrpc.OutPoint - 12, // 161: lnrpc.FailedUpdate.reason:type_name -> lnrpc.UpdateFailure - 193, // 162: lnrpc.PolicyUpdateResponse.failed_updates:type_name -> lnrpc.FailedUpdate - 196, // 163: lnrpc.ForwardingHistoryResponse.forwarding_events:type_name -> lnrpc.ForwardingEvent - 43, // 164: lnrpc.ExportChannelBackupRequest.chan_point:type_name -> lnrpc.ChannelPoint - 43, // 165: lnrpc.ChannelBackup.chan_point:type_name -> lnrpc.ChannelPoint - 43, // 166: lnrpc.MultiChanBackup.chan_points:type_name -> lnrpc.ChannelPoint - 203, // 167: lnrpc.ChanBackupSnapshot.single_chan_backups:type_name -> lnrpc.ChannelBackups - 200, // 168: lnrpc.ChanBackupSnapshot.multi_chan_backup:type_name -> lnrpc.MultiChanBackup - 199, // 169: lnrpc.ChannelBackups.chan_backups:type_name -> lnrpc.ChannelBackup - 203, // 170: lnrpc.RestoreChanBackupRequest.chan_backups:type_name -> lnrpc.ChannelBackups - 208, // 171: lnrpc.BakeMacaroonRequest.permissions:type_name -> lnrpc.MacaroonPermission - 208, // 172: lnrpc.MacaroonPermissionList.permissions:type_name -> lnrpc.MacaroonPermission - 258, // 173: lnrpc.ListPermissionsResponse.method_permissions:type_name -> lnrpc.ListPermissionsResponse.MethodPermissionsEntry - 21, // 174: lnrpc.Failure.code:type_name -> lnrpc.Failure.FailureCode - 219, // 175: lnrpc.Failure.channel_update:type_name -> lnrpc.ChannelUpdate - 221, // 176: lnrpc.MacaroonId.ops:type_name -> lnrpc.Op - 208, // 177: lnrpc.CheckMacPermRequest.permissions:type_name -> lnrpc.MacaroonPermission - 226, // 178: lnrpc.RPCMiddlewareRequest.stream_auth:type_name -> lnrpc.StreamAuth - 227, // 179: lnrpc.RPCMiddlewareRequest.request:type_name -> lnrpc.RPCMessage - 227, // 180: lnrpc.RPCMiddlewareRequest.response:type_name -> lnrpc.RPCMessage - 259, // 181: lnrpc.RPCMiddlewareRequest.metadata_pairs:type_name -> lnrpc.RPCMiddlewareRequest.MetadataPairsEntry - 229, // 182: lnrpc.RPCMiddlewareResponse.register:type_name -> lnrpc.MiddlewareRegistration - 230, // 183: lnrpc.RPCMiddlewareResponse.feedback:type_name -> lnrpc.InterceptFeedback - 187, // 184: lnrpc.Peer.FeaturesEntry.value:type_name -> lnrpc.Feature - 187, // 185: lnrpc.GetInfoResponse.FeaturesEntry.value:type_name -> lnrpc.Feature - 4, // 186: lnrpc.PendingChannelsResponse.PendingChannel.initiator:type_name -> lnrpc.Initiator - 3, // 187: lnrpc.PendingChannelsResponse.PendingChannel.commitment_type:type_name -> lnrpc.CommitmentType - 238, // 188: lnrpc.PendingChannelsResponse.PendingOpenChannel.channel:type_name -> lnrpc.PendingChannelsResponse.PendingChannel - 238, // 189: lnrpc.PendingChannelsResponse.WaitingCloseChannel.channel:type_name -> lnrpc.PendingChannelsResponse.PendingChannel - 241, // 190: lnrpc.PendingChannelsResponse.WaitingCloseChannel.commitments:type_name -> lnrpc.PendingChannelsResponse.Commitments - 238, // 191: lnrpc.PendingChannelsResponse.ClosedChannel.channel:type_name -> lnrpc.PendingChannelsResponse.PendingChannel - 238, // 192: lnrpc.PendingChannelsResponse.ForceClosedChannel.channel:type_name -> lnrpc.PendingChannelsResponse.PendingChannel - 113, // 193: lnrpc.PendingChannelsResponse.ForceClosedChannel.pending_htlcs:type_name -> lnrpc.PendingHTLC - 16, // 194: lnrpc.PendingChannelsResponse.ForceClosedChannel.anchor:type_name -> lnrpc.PendingChannelsResponse.ForceClosedChannel.AnchorState - 119, // 195: lnrpc.WalletBalanceResponse.AccountBalanceEntry.value:type_name -> lnrpc.WalletAccountBalance - 187, // 196: lnrpc.LightningNode.FeaturesEntry.value:type_name -> lnrpc.Feature - 144, // 197: lnrpc.NodeMetricsResponse.BetweennessCentralityEntry.value:type_name -> lnrpc.FloatMetric - 187, // 198: lnrpc.NodeUpdate.FeaturesEntry.value:type_name -> lnrpc.Feature - 187, // 199: lnrpc.Invoice.FeaturesEntry.value:type_name -> lnrpc.Feature - 161, // 200: lnrpc.Invoice.AmpInvoiceStateEntry.value:type_name -> lnrpc.AMPInvoiceState - 187, // 201: lnrpc.PayReq.FeaturesEntry.value:type_name -> lnrpc.Feature - 215, // 202: lnrpc.ListPermissionsResponse.MethodPermissionsEntry.value:type_name -> lnrpc.MacaroonPermissionList - 225, // 203: lnrpc.RPCMiddlewareRequest.MetadataPairsEntry.value:type_name -> lnrpc.MetadataValues - 120, // 204: lnrpc.Lightning.WalletBalance:input_type -> lnrpc.WalletBalanceRequest - 123, // 205: lnrpc.Lightning.ChannelBalance:input_type -> lnrpc.ChannelBalanceRequest - 35, // 206: lnrpc.Lightning.GetTransactions:input_type -> lnrpc.GetTransactionsRequest - 47, // 207: lnrpc.Lightning.EstimateFee:input_type -> lnrpc.EstimateFeeRequest - 51, // 208: lnrpc.Lightning.SendCoins:input_type -> lnrpc.SendCoinsRequest - 53, // 209: lnrpc.Lightning.ListUnspent:input_type -> lnrpc.ListUnspentRequest - 35, // 210: lnrpc.Lightning.SubscribeTransactions:input_type -> lnrpc.GetTransactionsRequest - 49, // 211: lnrpc.Lightning.SendMany:input_type -> lnrpc.SendManyRequest - 55, // 212: lnrpc.Lightning.NewAddress:input_type -> lnrpc.NewAddressRequest - 57, // 213: lnrpc.Lightning.SignMessage:input_type -> lnrpc.SignMessageRequest - 59, // 214: lnrpc.Lightning.VerifyMessage:input_type -> lnrpc.VerifyMessageRequest - 61, // 215: lnrpc.Lightning.ConnectPeer:input_type -> lnrpc.ConnectPeerRequest - 63, // 216: lnrpc.Lightning.DisconnectPeer:input_type -> lnrpc.DisconnectPeerRequest - 79, // 217: lnrpc.Lightning.ListPeers:input_type -> lnrpc.ListPeersRequest - 81, // 218: lnrpc.Lightning.SubscribePeerEvents:input_type -> lnrpc.PeerEventSubscription - 83, // 219: lnrpc.Lightning.GetInfo:input_type -> lnrpc.GetInfoRequest - 85, // 220: lnrpc.Lightning.GetDebugInfo:input_type -> lnrpc.GetDebugInfoRequest - 87, // 221: lnrpc.Lightning.GetRecoveryInfo:input_type -> lnrpc.GetRecoveryInfoRequest - 114, // 222: lnrpc.Lightning.PendingChannels:input_type -> lnrpc.PendingChannelsRequest - 68, // 223: lnrpc.Lightning.ListChannels:input_type -> lnrpc.ListChannelsRequest - 116, // 224: lnrpc.Lightning.SubscribeChannelEvents:input_type -> lnrpc.ChannelEventSubscription - 75, // 225: lnrpc.Lightning.ClosedChannels:input_type -> lnrpc.ClosedChannelsRequest - 101, // 226: lnrpc.Lightning.OpenChannelSync:input_type -> lnrpc.OpenChannelRequest - 101, // 227: lnrpc.Lightning.OpenChannel:input_type -> lnrpc.OpenChannelRequest - 98, // 228: lnrpc.Lightning.BatchOpenChannel:input_type -> lnrpc.BatchOpenChannelRequest - 111, // 229: lnrpc.Lightning.FundingStateStep:input_type -> lnrpc.FundingTransitionMsg - 42, // 230: lnrpc.Lightning.ChannelAcceptor:input_type -> lnrpc.ChannelAcceptResponse - 93, // 231: lnrpc.Lightning.CloseChannel:input_type -> lnrpc.CloseChannelRequest - 181, // 232: lnrpc.Lightning.AbandonChannel:input_type -> lnrpc.AbandonChannelRequest - 38, // 233: lnrpc.Lightning.SendPayment:input_type -> lnrpc.SendRequest - 38, // 234: lnrpc.Lightning.SendPaymentSync:input_type -> lnrpc.SendRequest - 40, // 235: lnrpc.Lightning.SendToRoute:input_type -> lnrpc.SendToRouteRequest - 40, // 236: lnrpc.Lightning.SendToRouteSync:input_type -> lnrpc.SendToRouteRequest - 162, // 237: lnrpc.Lightning.AddInvoice:input_type -> lnrpc.Invoice - 168, // 238: lnrpc.Lightning.ListInvoices:input_type -> lnrpc.ListInvoiceRequest - 167, // 239: lnrpc.Lightning.LookupInvoice:input_type -> lnrpc.PaymentHash - 170, // 240: lnrpc.Lightning.SubscribeInvoices:input_type -> lnrpc.InvoiceSubscription - 171, // 241: lnrpc.Lightning.DeleteCanceledInvoice:input_type -> lnrpc.DelCanceledInvoiceReq - 185, // 242: lnrpc.Lightning.DecodePayReq:input_type -> lnrpc.PayReqString - 175, // 243: lnrpc.Lightning.ListPayments:input_type -> lnrpc.ListPaymentsRequest - 177, // 244: lnrpc.Lightning.DeletePayment:input_type -> lnrpc.DeletePaymentRequest - 178, // 245: lnrpc.Lightning.DeleteAllPayments:input_type -> lnrpc.DeleteAllPaymentsRequest - 140, // 246: lnrpc.Lightning.DescribeGraph:input_type -> lnrpc.ChannelGraphRequest - 142, // 247: lnrpc.Lightning.GetNodeMetrics:input_type -> lnrpc.NodeMetricsRequest - 145, // 248: lnrpc.Lightning.GetChanInfo:input_type -> lnrpc.ChanInfoRequest - 133, // 249: lnrpc.Lightning.GetNodeInfo:input_type -> lnrpc.NodeInfoRequest - 125, // 250: lnrpc.Lightning.QueryRoutes:input_type -> lnrpc.QueryRoutesRequest - 146, // 251: lnrpc.Lightning.GetNetworkInfo:input_type -> lnrpc.NetworkInfoRequest - 148, // 252: lnrpc.Lightning.StopDaemon:input_type -> lnrpc.StopRequest - 150, // 253: lnrpc.Lightning.SubscribeChannelGraph:input_type -> lnrpc.GraphTopologySubscription - 183, // 254: lnrpc.Lightning.DebugLevel:input_type -> lnrpc.DebugLevelRequest - 188, // 255: lnrpc.Lightning.FeeReport:input_type -> lnrpc.FeeReportRequest - 192, // 256: lnrpc.Lightning.UpdateChannelPolicy:input_type -> lnrpc.PolicyUpdateRequest - 195, // 257: lnrpc.Lightning.ForwardingHistory:input_type -> lnrpc.ForwardingHistoryRequest - 198, // 258: lnrpc.Lightning.ExportChannelBackup:input_type -> lnrpc.ExportChannelBackupRequest - 201, // 259: lnrpc.Lightning.ExportAllChannelBackups:input_type -> lnrpc.ChanBackupExportRequest - 202, // 260: lnrpc.Lightning.VerifyChanBackup:input_type -> lnrpc.ChanBackupSnapshot - 204, // 261: lnrpc.Lightning.RestoreChannelBackups:input_type -> lnrpc.RestoreChanBackupRequest - 206, // 262: lnrpc.Lightning.SubscribeChannelBackups:input_type -> lnrpc.ChannelBackupSubscription - 209, // 263: lnrpc.Lightning.BakeMacaroon:input_type -> lnrpc.BakeMacaroonRequest - 211, // 264: lnrpc.Lightning.ListMacaroonIDs:input_type -> lnrpc.ListMacaroonIDsRequest - 213, // 265: lnrpc.Lightning.DeleteMacaroonID:input_type -> lnrpc.DeleteMacaroonIDRequest - 216, // 266: lnrpc.Lightning.ListPermissions:input_type -> lnrpc.ListPermissionsRequest - 222, // 267: lnrpc.Lightning.CheckMacaroonPermissions:input_type -> lnrpc.CheckMacPermRequest - 228, // 268: lnrpc.Lightning.RegisterRPCMiddleware:input_type -> lnrpc.RPCMiddlewareResponse - 26, // 269: lnrpc.Lightning.SendCustomMessage:input_type -> lnrpc.SendCustomMessageRequest - 24, // 270: lnrpc.Lightning.SubscribeCustomMessages:input_type -> lnrpc.SubscribeCustomMessagesRequest - 30, // 271: lnrpc.Lightning.SendOnionMessage:input_type -> lnrpc.SendOnionMessageRequest - 28, // 272: lnrpc.Lightning.SubscribeOnionMessages:input_type -> lnrpc.SubscribeOnionMessagesRequest - 71, // 273: lnrpc.Lightning.ListAliases:input_type -> lnrpc.ListAliasesRequest - 22, // 274: lnrpc.Lightning.LookupHtlcResolution:input_type -> lnrpc.LookupHtlcResolutionRequest - 121, // 275: lnrpc.Lightning.WalletBalance:output_type -> lnrpc.WalletBalanceResponse - 124, // 276: lnrpc.Lightning.ChannelBalance:output_type -> lnrpc.ChannelBalanceResponse - 36, // 277: lnrpc.Lightning.GetTransactions:output_type -> lnrpc.TransactionDetails - 48, // 278: lnrpc.Lightning.EstimateFee:output_type -> lnrpc.EstimateFeeResponse - 52, // 279: lnrpc.Lightning.SendCoins:output_type -> lnrpc.SendCoinsResponse - 54, // 280: lnrpc.Lightning.ListUnspent:output_type -> lnrpc.ListUnspentResponse - 34, // 281: lnrpc.Lightning.SubscribeTransactions:output_type -> lnrpc.Transaction - 50, // 282: lnrpc.Lightning.SendMany:output_type -> lnrpc.SendManyResponse - 56, // 283: lnrpc.Lightning.NewAddress:output_type -> lnrpc.NewAddressResponse - 58, // 284: lnrpc.Lightning.SignMessage:output_type -> lnrpc.SignMessageResponse - 60, // 285: lnrpc.Lightning.VerifyMessage:output_type -> lnrpc.VerifyMessageResponse - 62, // 286: lnrpc.Lightning.ConnectPeer:output_type -> lnrpc.ConnectPeerResponse - 64, // 287: lnrpc.Lightning.DisconnectPeer:output_type -> lnrpc.DisconnectPeerResponse - 80, // 288: lnrpc.Lightning.ListPeers:output_type -> lnrpc.ListPeersResponse - 82, // 289: lnrpc.Lightning.SubscribePeerEvents:output_type -> lnrpc.PeerEvent - 84, // 290: lnrpc.Lightning.GetInfo:output_type -> lnrpc.GetInfoResponse - 86, // 291: lnrpc.Lightning.GetDebugInfo:output_type -> lnrpc.GetDebugInfoResponse - 88, // 292: lnrpc.Lightning.GetRecoveryInfo:output_type -> lnrpc.GetRecoveryInfoResponse - 115, // 293: lnrpc.Lightning.PendingChannels:output_type -> lnrpc.PendingChannelsResponse - 69, // 294: lnrpc.Lightning.ListChannels:output_type -> lnrpc.ListChannelsResponse - 118, // 295: lnrpc.Lightning.SubscribeChannelEvents:output_type -> lnrpc.ChannelEventUpdate - 76, // 296: lnrpc.Lightning.ClosedChannels:output_type -> lnrpc.ClosedChannelsResponse - 43, // 297: lnrpc.Lightning.OpenChannelSync:output_type -> lnrpc.ChannelPoint - 102, // 298: lnrpc.Lightning.OpenChannel:output_type -> lnrpc.OpenStatusUpdate - 100, // 299: lnrpc.Lightning.BatchOpenChannel:output_type -> lnrpc.BatchOpenChannelResponse - 112, // 300: lnrpc.Lightning.FundingStateStep:output_type -> lnrpc.FundingStateStepResp - 41, // 301: lnrpc.Lightning.ChannelAcceptor:output_type -> lnrpc.ChannelAcceptRequest - 94, // 302: lnrpc.Lightning.CloseChannel:output_type -> lnrpc.CloseStatusUpdate - 182, // 303: lnrpc.Lightning.AbandonChannel:output_type -> lnrpc.AbandonChannelResponse - 39, // 304: lnrpc.Lightning.SendPayment:output_type -> lnrpc.SendResponse - 39, // 305: lnrpc.Lightning.SendPaymentSync:output_type -> lnrpc.SendResponse - 39, // 306: lnrpc.Lightning.SendToRoute:output_type -> lnrpc.SendResponse - 39, // 307: lnrpc.Lightning.SendToRouteSync:output_type -> lnrpc.SendResponse - 166, // 308: lnrpc.Lightning.AddInvoice:output_type -> lnrpc.AddInvoiceResponse - 169, // 309: lnrpc.Lightning.ListInvoices:output_type -> lnrpc.ListInvoiceResponse - 162, // 310: lnrpc.Lightning.LookupInvoice:output_type -> lnrpc.Invoice - 162, // 311: lnrpc.Lightning.SubscribeInvoices:output_type -> lnrpc.Invoice - 172, // 312: lnrpc.Lightning.DeleteCanceledInvoice:output_type -> lnrpc.DelCanceledInvoiceResp - 186, // 313: lnrpc.Lightning.DecodePayReq:output_type -> lnrpc.PayReq - 176, // 314: lnrpc.Lightning.ListPayments:output_type -> lnrpc.ListPaymentsResponse - 179, // 315: lnrpc.Lightning.DeletePayment:output_type -> lnrpc.DeletePaymentResponse - 180, // 316: lnrpc.Lightning.DeleteAllPayments:output_type -> lnrpc.DeleteAllPaymentsResponse - 141, // 317: lnrpc.Lightning.DescribeGraph:output_type -> lnrpc.ChannelGraph - 143, // 318: lnrpc.Lightning.GetNodeMetrics:output_type -> lnrpc.NodeMetricsResponse - 139, // 319: lnrpc.Lightning.GetChanInfo:output_type -> lnrpc.ChannelEdge - 134, // 320: lnrpc.Lightning.GetNodeInfo:output_type -> lnrpc.NodeInfo - 128, // 321: lnrpc.Lightning.QueryRoutes:output_type -> lnrpc.QueryRoutesResponse - 147, // 322: lnrpc.Lightning.GetNetworkInfo:output_type -> lnrpc.NetworkInfo - 149, // 323: lnrpc.Lightning.StopDaemon:output_type -> lnrpc.StopResponse - 151, // 324: lnrpc.Lightning.SubscribeChannelGraph:output_type -> lnrpc.GraphTopologyUpdate - 184, // 325: lnrpc.Lightning.DebugLevel:output_type -> lnrpc.DebugLevelResponse - 190, // 326: lnrpc.Lightning.FeeReport:output_type -> lnrpc.FeeReportResponse - 194, // 327: lnrpc.Lightning.UpdateChannelPolicy:output_type -> lnrpc.PolicyUpdateResponse - 197, // 328: lnrpc.Lightning.ForwardingHistory:output_type -> lnrpc.ForwardingHistoryResponse - 199, // 329: lnrpc.Lightning.ExportChannelBackup:output_type -> lnrpc.ChannelBackup - 202, // 330: lnrpc.Lightning.ExportAllChannelBackups:output_type -> lnrpc.ChanBackupSnapshot - 207, // 331: lnrpc.Lightning.VerifyChanBackup:output_type -> lnrpc.VerifyChanBackupResponse - 205, // 332: lnrpc.Lightning.RestoreChannelBackups:output_type -> lnrpc.RestoreBackupResponse - 202, // 333: lnrpc.Lightning.SubscribeChannelBackups:output_type -> lnrpc.ChanBackupSnapshot - 210, // 334: lnrpc.Lightning.BakeMacaroon:output_type -> lnrpc.BakeMacaroonResponse - 212, // 335: lnrpc.Lightning.ListMacaroonIDs:output_type -> lnrpc.ListMacaroonIDsResponse - 214, // 336: lnrpc.Lightning.DeleteMacaroonID:output_type -> lnrpc.DeleteMacaroonIDResponse - 217, // 337: lnrpc.Lightning.ListPermissions:output_type -> lnrpc.ListPermissionsResponse - 223, // 338: lnrpc.Lightning.CheckMacaroonPermissions:output_type -> lnrpc.CheckMacPermResponse - 224, // 339: lnrpc.Lightning.RegisterRPCMiddleware:output_type -> lnrpc.RPCMiddlewareRequest - 27, // 340: lnrpc.Lightning.SendCustomMessage:output_type -> lnrpc.SendCustomMessageResponse - 25, // 341: lnrpc.Lightning.SubscribeCustomMessages:output_type -> lnrpc.CustomMessage - 31, // 342: lnrpc.Lightning.SendOnionMessage:output_type -> lnrpc.SendOnionMessageResponse - 29, // 343: lnrpc.Lightning.SubscribeOnionMessages:output_type -> lnrpc.OnionMessageUpdate - 72, // 344: lnrpc.Lightning.ListAliases:output_type -> lnrpc.ListAliasesResponse - 23, // 345: lnrpc.Lightning.LookupHtlcResolution:output_type -> lnrpc.LookupHtlcResolutionResponse - 275, // [275:346] is the sub-list for method output_type - 204, // [204:275] is the sub-list for method input_type - 204, // [204:204] is the sub-list for extension type_name - 204, // [204:204] is the sub-list for extension extendee - 0, // [0:204] is the sub-list for field type_name + 131, // 103: lnrpc.QueryRoutesRequest.amp_record:type_name -> lnrpc.AMPRecord + 132, // 104: lnrpc.QueryRoutesResponse.routes:type_name -> lnrpc.Route + 130, // 105: lnrpc.Hop.mpp_record:type_name -> lnrpc.MPPRecord + 131, // 106: lnrpc.Hop.amp_record:type_name -> lnrpc.AMPRecord + 246, // 107: lnrpc.Hop.custom_records:type_name -> lnrpc.Hop.CustomRecordsEntry + 129, // 108: lnrpc.Route.hops:type_name -> lnrpc.Hop + 135, // 109: lnrpc.NodeInfo.node:type_name -> lnrpc.LightningNode + 139, // 110: lnrpc.NodeInfo.channels:type_name -> lnrpc.ChannelEdge + 136, // 111: lnrpc.LightningNode.addresses:type_name -> lnrpc.NodeAddress + 247, // 112: lnrpc.LightningNode.features:type_name -> lnrpc.LightningNode.FeaturesEntry + 248, // 113: lnrpc.LightningNode.custom_records:type_name -> lnrpc.LightningNode.CustomRecordsEntry + 249, // 114: lnrpc.RoutingPolicy.custom_records:type_name -> lnrpc.RoutingPolicy.CustomRecordsEntry + 137, // 115: lnrpc.ChannelEdge.node1_policy:type_name -> lnrpc.RoutingPolicy + 137, // 116: lnrpc.ChannelEdge.node2_policy:type_name -> lnrpc.RoutingPolicy + 250, // 117: lnrpc.ChannelEdge.custom_records:type_name -> lnrpc.ChannelEdge.CustomRecordsEntry + 138, // 118: lnrpc.ChannelEdge.auth_proof:type_name -> lnrpc.ChannelAuthProof + 135, // 119: lnrpc.ChannelGraph.nodes:type_name -> lnrpc.LightningNode + 139, // 120: lnrpc.ChannelGraph.edges:type_name -> lnrpc.ChannelEdge + 8, // 121: lnrpc.NodeMetricsRequest.types:type_name -> lnrpc.NodeMetricType + 251, // 122: lnrpc.NodeMetricsResponse.betweenness_centrality:type_name -> lnrpc.NodeMetricsResponse.BetweennessCentralityEntry + 152, // 123: lnrpc.GraphTopologyUpdate.node_updates:type_name -> lnrpc.NodeUpdate + 153, // 124: lnrpc.GraphTopologyUpdate.channel_updates:type_name -> lnrpc.ChannelEdgeUpdate + 154, // 125: lnrpc.GraphTopologyUpdate.closed_chans:type_name -> lnrpc.ClosedChannelUpdate + 136, // 126: lnrpc.NodeUpdate.node_addresses:type_name -> lnrpc.NodeAddress + 252, // 127: lnrpc.NodeUpdate.features:type_name -> lnrpc.NodeUpdate.FeaturesEntry + 43, // 128: lnrpc.ChannelEdgeUpdate.chan_point:type_name -> lnrpc.ChannelPoint + 137, // 129: lnrpc.ChannelEdgeUpdate.routing_policy:type_name -> lnrpc.RoutingPolicy + 43, // 130: lnrpc.ClosedChannelUpdate.chan_point:type_name -> lnrpc.ChannelPoint + 155, // 131: lnrpc.RouteHint.hop_hints:type_name -> lnrpc.HopHint + 159, // 132: lnrpc.BlindedPaymentPath.blinded_path:type_name -> lnrpc.BlindedPath + 11, // 133: lnrpc.BlindedPaymentPath.features:type_name -> lnrpc.FeatureBit + 160, // 134: lnrpc.BlindedPath.blinded_hops:type_name -> lnrpc.BlindedHop + 9, // 135: lnrpc.AMPInvoiceState.state:type_name -> lnrpc.InvoiceHTLCState + 157, // 136: lnrpc.Invoice.route_hints:type_name -> lnrpc.RouteHint + 18, // 137: lnrpc.Invoice.state:type_name -> lnrpc.Invoice.InvoiceState + 164, // 138: lnrpc.Invoice.htlcs:type_name -> lnrpc.InvoiceHTLC + 253, // 139: lnrpc.Invoice.features:type_name -> lnrpc.Invoice.FeaturesEntry + 254, // 140: lnrpc.Invoice.amp_invoice_state:type_name -> lnrpc.Invoice.AmpInvoiceStateEntry + 163, // 141: lnrpc.Invoice.blinded_path_config:type_name -> lnrpc.BlindedPathConfig + 9, // 142: lnrpc.InvoiceHTLC.state:type_name -> lnrpc.InvoiceHTLCState + 255, // 143: lnrpc.InvoiceHTLC.custom_records:type_name -> lnrpc.InvoiceHTLC.CustomRecordsEntry + 165, // 144: lnrpc.InvoiceHTLC.amp:type_name -> lnrpc.AMP + 162, // 145: lnrpc.ListInvoiceResponse.invoices:type_name -> lnrpc.Invoice + 19, // 146: lnrpc.Payment.status:type_name -> lnrpc.Payment.PaymentStatus + 174, // 147: lnrpc.Payment.htlcs:type_name -> lnrpc.HTLCAttempt + 10, // 148: lnrpc.Payment.failure_reason:type_name -> lnrpc.PaymentFailureReason + 256, // 149: lnrpc.Payment.first_hop_custom_records:type_name -> lnrpc.Payment.FirstHopCustomRecordsEntry + 20, // 150: lnrpc.HTLCAttempt.status:type_name -> lnrpc.HTLCAttempt.HTLCStatus + 132, // 151: lnrpc.HTLCAttempt.route:type_name -> lnrpc.Route + 218, // 152: lnrpc.HTLCAttempt.failure:type_name -> lnrpc.Failure + 173, // 153: lnrpc.ListPaymentsResponse.payments:type_name -> lnrpc.Payment + 43, // 154: lnrpc.AbandonChannelRequest.channel_point:type_name -> lnrpc.ChannelPoint + 157, // 155: lnrpc.PayReq.route_hints:type_name -> lnrpc.RouteHint + 257, // 156: lnrpc.PayReq.features:type_name -> lnrpc.PayReq.FeaturesEntry + 158, // 157: lnrpc.PayReq.blinded_paths:type_name -> lnrpc.BlindedPaymentPath + 189, // 158: lnrpc.FeeReportResponse.channel_fees:type_name -> lnrpc.ChannelFeeReport + 43, // 159: lnrpc.PolicyUpdateRequest.chan_point:type_name -> lnrpc.ChannelPoint + 191, // 160: lnrpc.PolicyUpdateRequest.inbound_fee:type_name -> lnrpc.InboundFee + 44, // 161: lnrpc.FailedUpdate.outpoint:type_name -> lnrpc.OutPoint + 12, // 162: lnrpc.FailedUpdate.reason:type_name -> lnrpc.UpdateFailure + 193, // 163: lnrpc.PolicyUpdateResponse.failed_updates:type_name -> lnrpc.FailedUpdate + 196, // 164: lnrpc.ForwardingHistoryResponse.forwarding_events:type_name -> lnrpc.ForwardingEvent + 43, // 165: lnrpc.ExportChannelBackupRequest.chan_point:type_name -> lnrpc.ChannelPoint + 43, // 166: lnrpc.ChannelBackup.chan_point:type_name -> lnrpc.ChannelPoint + 43, // 167: lnrpc.MultiChanBackup.chan_points:type_name -> lnrpc.ChannelPoint + 203, // 168: lnrpc.ChanBackupSnapshot.single_chan_backups:type_name -> lnrpc.ChannelBackups + 200, // 169: lnrpc.ChanBackupSnapshot.multi_chan_backup:type_name -> lnrpc.MultiChanBackup + 199, // 170: lnrpc.ChannelBackups.chan_backups:type_name -> lnrpc.ChannelBackup + 203, // 171: lnrpc.RestoreChanBackupRequest.chan_backups:type_name -> lnrpc.ChannelBackups + 208, // 172: lnrpc.BakeMacaroonRequest.permissions:type_name -> lnrpc.MacaroonPermission + 208, // 173: lnrpc.MacaroonPermissionList.permissions:type_name -> lnrpc.MacaroonPermission + 258, // 174: lnrpc.ListPermissionsResponse.method_permissions:type_name -> lnrpc.ListPermissionsResponse.MethodPermissionsEntry + 21, // 175: lnrpc.Failure.code:type_name -> lnrpc.Failure.FailureCode + 219, // 176: lnrpc.Failure.channel_update:type_name -> lnrpc.ChannelUpdate + 221, // 177: lnrpc.MacaroonId.ops:type_name -> lnrpc.Op + 208, // 178: lnrpc.CheckMacPermRequest.permissions:type_name -> lnrpc.MacaroonPermission + 226, // 179: lnrpc.RPCMiddlewareRequest.stream_auth:type_name -> lnrpc.StreamAuth + 227, // 180: lnrpc.RPCMiddlewareRequest.request:type_name -> lnrpc.RPCMessage + 227, // 181: lnrpc.RPCMiddlewareRequest.response:type_name -> lnrpc.RPCMessage + 259, // 182: lnrpc.RPCMiddlewareRequest.metadata_pairs:type_name -> lnrpc.RPCMiddlewareRequest.MetadataPairsEntry + 229, // 183: lnrpc.RPCMiddlewareResponse.register:type_name -> lnrpc.MiddlewareRegistration + 230, // 184: lnrpc.RPCMiddlewareResponse.feedback:type_name -> lnrpc.InterceptFeedback + 187, // 185: lnrpc.Peer.FeaturesEntry.value:type_name -> lnrpc.Feature + 187, // 186: lnrpc.GetInfoResponse.FeaturesEntry.value:type_name -> lnrpc.Feature + 4, // 187: lnrpc.PendingChannelsResponse.PendingChannel.initiator:type_name -> lnrpc.Initiator + 3, // 188: lnrpc.PendingChannelsResponse.PendingChannel.commitment_type:type_name -> lnrpc.CommitmentType + 238, // 189: lnrpc.PendingChannelsResponse.PendingOpenChannel.channel:type_name -> lnrpc.PendingChannelsResponse.PendingChannel + 238, // 190: lnrpc.PendingChannelsResponse.WaitingCloseChannel.channel:type_name -> lnrpc.PendingChannelsResponse.PendingChannel + 241, // 191: lnrpc.PendingChannelsResponse.WaitingCloseChannel.commitments:type_name -> lnrpc.PendingChannelsResponse.Commitments + 238, // 192: lnrpc.PendingChannelsResponse.ClosedChannel.channel:type_name -> lnrpc.PendingChannelsResponse.PendingChannel + 238, // 193: lnrpc.PendingChannelsResponse.ForceClosedChannel.channel:type_name -> lnrpc.PendingChannelsResponse.PendingChannel + 113, // 194: lnrpc.PendingChannelsResponse.ForceClosedChannel.pending_htlcs:type_name -> lnrpc.PendingHTLC + 16, // 195: lnrpc.PendingChannelsResponse.ForceClosedChannel.anchor:type_name -> lnrpc.PendingChannelsResponse.ForceClosedChannel.AnchorState + 119, // 196: lnrpc.WalletBalanceResponse.AccountBalanceEntry.value:type_name -> lnrpc.WalletAccountBalance + 187, // 197: lnrpc.LightningNode.FeaturesEntry.value:type_name -> lnrpc.Feature + 144, // 198: lnrpc.NodeMetricsResponse.BetweennessCentralityEntry.value:type_name -> lnrpc.FloatMetric + 187, // 199: lnrpc.NodeUpdate.FeaturesEntry.value:type_name -> lnrpc.Feature + 187, // 200: lnrpc.Invoice.FeaturesEntry.value:type_name -> lnrpc.Feature + 161, // 201: lnrpc.Invoice.AmpInvoiceStateEntry.value:type_name -> lnrpc.AMPInvoiceState + 187, // 202: lnrpc.PayReq.FeaturesEntry.value:type_name -> lnrpc.Feature + 215, // 203: lnrpc.ListPermissionsResponse.MethodPermissionsEntry.value:type_name -> lnrpc.MacaroonPermissionList + 225, // 204: lnrpc.RPCMiddlewareRequest.MetadataPairsEntry.value:type_name -> lnrpc.MetadataValues + 120, // 205: lnrpc.Lightning.WalletBalance:input_type -> lnrpc.WalletBalanceRequest + 123, // 206: lnrpc.Lightning.ChannelBalance:input_type -> lnrpc.ChannelBalanceRequest + 35, // 207: lnrpc.Lightning.GetTransactions:input_type -> lnrpc.GetTransactionsRequest + 47, // 208: lnrpc.Lightning.EstimateFee:input_type -> lnrpc.EstimateFeeRequest + 51, // 209: lnrpc.Lightning.SendCoins:input_type -> lnrpc.SendCoinsRequest + 53, // 210: lnrpc.Lightning.ListUnspent:input_type -> lnrpc.ListUnspentRequest + 35, // 211: lnrpc.Lightning.SubscribeTransactions:input_type -> lnrpc.GetTransactionsRequest + 49, // 212: lnrpc.Lightning.SendMany:input_type -> lnrpc.SendManyRequest + 55, // 213: lnrpc.Lightning.NewAddress:input_type -> lnrpc.NewAddressRequest + 57, // 214: lnrpc.Lightning.SignMessage:input_type -> lnrpc.SignMessageRequest + 59, // 215: lnrpc.Lightning.VerifyMessage:input_type -> lnrpc.VerifyMessageRequest + 61, // 216: lnrpc.Lightning.ConnectPeer:input_type -> lnrpc.ConnectPeerRequest + 63, // 217: lnrpc.Lightning.DisconnectPeer:input_type -> lnrpc.DisconnectPeerRequest + 79, // 218: lnrpc.Lightning.ListPeers:input_type -> lnrpc.ListPeersRequest + 81, // 219: lnrpc.Lightning.SubscribePeerEvents:input_type -> lnrpc.PeerEventSubscription + 83, // 220: lnrpc.Lightning.GetInfo:input_type -> lnrpc.GetInfoRequest + 85, // 221: lnrpc.Lightning.GetDebugInfo:input_type -> lnrpc.GetDebugInfoRequest + 87, // 222: lnrpc.Lightning.GetRecoveryInfo:input_type -> lnrpc.GetRecoveryInfoRequest + 114, // 223: lnrpc.Lightning.PendingChannels:input_type -> lnrpc.PendingChannelsRequest + 68, // 224: lnrpc.Lightning.ListChannels:input_type -> lnrpc.ListChannelsRequest + 116, // 225: lnrpc.Lightning.SubscribeChannelEvents:input_type -> lnrpc.ChannelEventSubscription + 75, // 226: lnrpc.Lightning.ClosedChannels:input_type -> lnrpc.ClosedChannelsRequest + 101, // 227: lnrpc.Lightning.OpenChannelSync:input_type -> lnrpc.OpenChannelRequest + 101, // 228: lnrpc.Lightning.OpenChannel:input_type -> lnrpc.OpenChannelRequest + 98, // 229: lnrpc.Lightning.BatchOpenChannel:input_type -> lnrpc.BatchOpenChannelRequest + 111, // 230: lnrpc.Lightning.FundingStateStep:input_type -> lnrpc.FundingTransitionMsg + 42, // 231: lnrpc.Lightning.ChannelAcceptor:input_type -> lnrpc.ChannelAcceptResponse + 93, // 232: lnrpc.Lightning.CloseChannel:input_type -> lnrpc.CloseChannelRequest + 181, // 233: lnrpc.Lightning.AbandonChannel:input_type -> lnrpc.AbandonChannelRequest + 38, // 234: lnrpc.Lightning.SendPayment:input_type -> lnrpc.SendRequest + 38, // 235: lnrpc.Lightning.SendPaymentSync:input_type -> lnrpc.SendRequest + 40, // 236: lnrpc.Lightning.SendToRoute:input_type -> lnrpc.SendToRouteRequest + 40, // 237: lnrpc.Lightning.SendToRouteSync:input_type -> lnrpc.SendToRouteRequest + 162, // 238: lnrpc.Lightning.AddInvoice:input_type -> lnrpc.Invoice + 168, // 239: lnrpc.Lightning.ListInvoices:input_type -> lnrpc.ListInvoiceRequest + 167, // 240: lnrpc.Lightning.LookupInvoice:input_type -> lnrpc.PaymentHash + 170, // 241: lnrpc.Lightning.SubscribeInvoices:input_type -> lnrpc.InvoiceSubscription + 171, // 242: lnrpc.Lightning.DeleteCanceledInvoice:input_type -> lnrpc.DelCanceledInvoiceReq + 185, // 243: lnrpc.Lightning.DecodePayReq:input_type -> lnrpc.PayReqString + 175, // 244: lnrpc.Lightning.ListPayments:input_type -> lnrpc.ListPaymentsRequest + 177, // 245: lnrpc.Lightning.DeletePayment:input_type -> lnrpc.DeletePaymentRequest + 178, // 246: lnrpc.Lightning.DeleteAllPayments:input_type -> lnrpc.DeleteAllPaymentsRequest + 140, // 247: lnrpc.Lightning.DescribeGraph:input_type -> lnrpc.ChannelGraphRequest + 142, // 248: lnrpc.Lightning.GetNodeMetrics:input_type -> lnrpc.NodeMetricsRequest + 145, // 249: lnrpc.Lightning.GetChanInfo:input_type -> lnrpc.ChanInfoRequest + 133, // 250: lnrpc.Lightning.GetNodeInfo:input_type -> lnrpc.NodeInfoRequest + 125, // 251: lnrpc.Lightning.QueryRoutes:input_type -> lnrpc.QueryRoutesRequest + 146, // 252: lnrpc.Lightning.GetNetworkInfo:input_type -> lnrpc.NetworkInfoRequest + 148, // 253: lnrpc.Lightning.StopDaemon:input_type -> lnrpc.StopRequest + 150, // 254: lnrpc.Lightning.SubscribeChannelGraph:input_type -> lnrpc.GraphTopologySubscription + 183, // 255: lnrpc.Lightning.DebugLevel:input_type -> lnrpc.DebugLevelRequest + 188, // 256: lnrpc.Lightning.FeeReport:input_type -> lnrpc.FeeReportRequest + 192, // 257: lnrpc.Lightning.UpdateChannelPolicy:input_type -> lnrpc.PolicyUpdateRequest + 195, // 258: lnrpc.Lightning.ForwardingHistory:input_type -> lnrpc.ForwardingHistoryRequest + 198, // 259: lnrpc.Lightning.ExportChannelBackup:input_type -> lnrpc.ExportChannelBackupRequest + 201, // 260: lnrpc.Lightning.ExportAllChannelBackups:input_type -> lnrpc.ChanBackupExportRequest + 202, // 261: lnrpc.Lightning.VerifyChanBackup:input_type -> lnrpc.ChanBackupSnapshot + 204, // 262: lnrpc.Lightning.RestoreChannelBackups:input_type -> lnrpc.RestoreChanBackupRequest + 206, // 263: lnrpc.Lightning.SubscribeChannelBackups:input_type -> lnrpc.ChannelBackupSubscription + 209, // 264: lnrpc.Lightning.BakeMacaroon:input_type -> lnrpc.BakeMacaroonRequest + 211, // 265: lnrpc.Lightning.ListMacaroonIDs:input_type -> lnrpc.ListMacaroonIDsRequest + 213, // 266: lnrpc.Lightning.DeleteMacaroonID:input_type -> lnrpc.DeleteMacaroonIDRequest + 216, // 267: lnrpc.Lightning.ListPermissions:input_type -> lnrpc.ListPermissionsRequest + 222, // 268: lnrpc.Lightning.CheckMacaroonPermissions:input_type -> lnrpc.CheckMacPermRequest + 228, // 269: lnrpc.Lightning.RegisterRPCMiddleware:input_type -> lnrpc.RPCMiddlewareResponse + 26, // 270: lnrpc.Lightning.SendCustomMessage:input_type -> lnrpc.SendCustomMessageRequest + 24, // 271: lnrpc.Lightning.SubscribeCustomMessages:input_type -> lnrpc.SubscribeCustomMessagesRequest + 30, // 272: lnrpc.Lightning.SendOnionMessage:input_type -> lnrpc.SendOnionMessageRequest + 28, // 273: lnrpc.Lightning.SubscribeOnionMessages:input_type -> lnrpc.SubscribeOnionMessagesRequest + 71, // 274: lnrpc.Lightning.ListAliases:input_type -> lnrpc.ListAliasesRequest + 22, // 275: lnrpc.Lightning.LookupHtlcResolution:input_type -> lnrpc.LookupHtlcResolutionRequest + 121, // 276: lnrpc.Lightning.WalletBalance:output_type -> lnrpc.WalletBalanceResponse + 124, // 277: lnrpc.Lightning.ChannelBalance:output_type -> lnrpc.ChannelBalanceResponse + 36, // 278: lnrpc.Lightning.GetTransactions:output_type -> lnrpc.TransactionDetails + 48, // 279: lnrpc.Lightning.EstimateFee:output_type -> lnrpc.EstimateFeeResponse + 52, // 280: lnrpc.Lightning.SendCoins:output_type -> lnrpc.SendCoinsResponse + 54, // 281: lnrpc.Lightning.ListUnspent:output_type -> lnrpc.ListUnspentResponse + 34, // 282: lnrpc.Lightning.SubscribeTransactions:output_type -> lnrpc.Transaction + 50, // 283: lnrpc.Lightning.SendMany:output_type -> lnrpc.SendManyResponse + 56, // 284: lnrpc.Lightning.NewAddress:output_type -> lnrpc.NewAddressResponse + 58, // 285: lnrpc.Lightning.SignMessage:output_type -> lnrpc.SignMessageResponse + 60, // 286: lnrpc.Lightning.VerifyMessage:output_type -> lnrpc.VerifyMessageResponse + 62, // 287: lnrpc.Lightning.ConnectPeer:output_type -> lnrpc.ConnectPeerResponse + 64, // 288: lnrpc.Lightning.DisconnectPeer:output_type -> lnrpc.DisconnectPeerResponse + 80, // 289: lnrpc.Lightning.ListPeers:output_type -> lnrpc.ListPeersResponse + 82, // 290: lnrpc.Lightning.SubscribePeerEvents:output_type -> lnrpc.PeerEvent + 84, // 291: lnrpc.Lightning.GetInfo:output_type -> lnrpc.GetInfoResponse + 86, // 292: lnrpc.Lightning.GetDebugInfo:output_type -> lnrpc.GetDebugInfoResponse + 88, // 293: lnrpc.Lightning.GetRecoveryInfo:output_type -> lnrpc.GetRecoveryInfoResponse + 115, // 294: lnrpc.Lightning.PendingChannels:output_type -> lnrpc.PendingChannelsResponse + 69, // 295: lnrpc.Lightning.ListChannels:output_type -> lnrpc.ListChannelsResponse + 118, // 296: lnrpc.Lightning.SubscribeChannelEvents:output_type -> lnrpc.ChannelEventUpdate + 76, // 297: lnrpc.Lightning.ClosedChannels:output_type -> lnrpc.ClosedChannelsResponse + 43, // 298: lnrpc.Lightning.OpenChannelSync:output_type -> lnrpc.ChannelPoint + 102, // 299: lnrpc.Lightning.OpenChannel:output_type -> lnrpc.OpenStatusUpdate + 100, // 300: lnrpc.Lightning.BatchOpenChannel:output_type -> lnrpc.BatchOpenChannelResponse + 112, // 301: lnrpc.Lightning.FundingStateStep:output_type -> lnrpc.FundingStateStepResp + 41, // 302: lnrpc.Lightning.ChannelAcceptor:output_type -> lnrpc.ChannelAcceptRequest + 94, // 303: lnrpc.Lightning.CloseChannel:output_type -> lnrpc.CloseStatusUpdate + 182, // 304: lnrpc.Lightning.AbandonChannel:output_type -> lnrpc.AbandonChannelResponse + 39, // 305: lnrpc.Lightning.SendPayment:output_type -> lnrpc.SendResponse + 39, // 306: lnrpc.Lightning.SendPaymentSync:output_type -> lnrpc.SendResponse + 39, // 307: lnrpc.Lightning.SendToRoute:output_type -> lnrpc.SendResponse + 39, // 308: lnrpc.Lightning.SendToRouteSync:output_type -> lnrpc.SendResponse + 166, // 309: lnrpc.Lightning.AddInvoice:output_type -> lnrpc.AddInvoiceResponse + 169, // 310: lnrpc.Lightning.ListInvoices:output_type -> lnrpc.ListInvoiceResponse + 162, // 311: lnrpc.Lightning.LookupInvoice:output_type -> lnrpc.Invoice + 162, // 312: lnrpc.Lightning.SubscribeInvoices:output_type -> lnrpc.Invoice + 172, // 313: lnrpc.Lightning.DeleteCanceledInvoice:output_type -> lnrpc.DelCanceledInvoiceResp + 186, // 314: lnrpc.Lightning.DecodePayReq:output_type -> lnrpc.PayReq + 176, // 315: lnrpc.Lightning.ListPayments:output_type -> lnrpc.ListPaymentsResponse + 179, // 316: lnrpc.Lightning.DeletePayment:output_type -> lnrpc.DeletePaymentResponse + 180, // 317: lnrpc.Lightning.DeleteAllPayments:output_type -> lnrpc.DeleteAllPaymentsResponse + 141, // 318: lnrpc.Lightning.DescribeGraph:output_type -> lnrpc.ChannelGraph + 143, // 319: lnrpc.Lightning.GetNodeMetrics:output_type -> lnrpc.NodeMetricsResponse + 139, // 320: lnrpc.Lightning.GetChanInfo:output_type -> lnrpc.ChannelEdge + 134, // 321: lnrpc.Lightning.GetNodeInfo:output_type -> lnrpc.NodeInfo + 128, // 322: lnrpc.Lightning.QueryRoutes:output_type -> lnrpc.QueryRoutesResponse + 147, // 323: lnrpc.Lightning.GetNetworkInfo:output_type -> lnrpc.NetworkInfo + 149, // 324: lnrpc.Lightning.StopDaemon:output_type -> lnrpc.StopResponse + 151, // 325: lnrpc.Lightning.SubscribeChannelGraph:output_type -> lnrpc.GraphTopologyUpdate + 184, // 326: lnrpc.Lightning.DebugLevel:output_type -> lnrpc.DebugLevelResponse + 190, // 327: lnrpc.Lightning.FeeReport:output_type -> lnrpc.FeeReportResponse + 194, // 328: lnrpc.Lightning.UpdateChannelPolicy:output_type -> lnrpc.PolicyUpdateResponse + 197, // 329: lnrpc.Lightning.ForwardingHistory:output_type -> lnrpc.ForwardingHistoryResponse + 199, // 330: lnrpc.Lightning.ExportChannelBackup:output_type -> lnrpc.ChannelBackup + 202, // 331: lnrpc.Lightning.ExportAllChannelBackups:output_type -> lnrpc.ChanBackupSnapshot + 207, // 332: lnrpc.Lightning.VerifyChanBackup:output_type -> lnrpc.VerifyChanBackupResponse + 205, // 333: lnrpc.Lightning.RestoreChannelBackups:output_type -> lnrpc.RestoreBackupResponse + 202, // 334: lnrpc.Lightning.SubscribeChannelBackups:output_type -> lnrpc.ChanBackupSnapshot + 210, // 335: lnrpc.Lightning.BakeMacaroon:output_type -> lnrpc.BakeMacaroonResponse + 212, // 336: lnrpc.Lightning.ListMacaroonIDs:output_type -> lnrpc.ListMacaroonIDsResponse + 214, // 337: lnrpc.Lightning.DeleteMacaroonID:output_type -> lnrpc.DeleteMacaroonIDResponse + 217, // 338: lnrpc.Lightning.ListPermissions:output_type -> lnrpc.ListPermissionsResponse + 223, // 339: lnrpc.Lightning.CheckMacaroonPermissions:output_type -> lnrpc.CheckMacPermResponse + 224, // 340: lnrpc.Lightning.RegisterRPCMiddleware:output_type -> lnrpc.RPCMiddlewareRequest + 27, // 341: lnrpc.Lightning.SendCustomMessage:output_type -> lnrpc.SendCustomMessageResponse + 25, // 342: lnrpc.Lightning.SubscribeCustomMessages:output_type -> lnrpc.CustomMessage + 31, // 343: lnrpc.Lightning.SendOnionMessage:output_type -> lnrpc.SendOnionMessageResponse + 29, // 344: lnrpc.Lightning.SubscribeOnionMessages:output_type -> lnrpc.OnionMessageUpdate + 72, // 345: lnrpc.Lightning.ListAliases:output_type -> lnrpc.ListAliasesResponse + 23, // 346: lnrpc.Lightning.LookupHtlcResolution:output_type -> lnrpc.LookupHtlcResolutionResponse + 276, // [276:347] is the sub-list for method output_type + 205, // [205:276] is the sub-list for method input_type + 205, // [205:205] is the sub-list for extension type_name + 205, // [205:205] is the sub-list for extension extendee + 0, // [0:205] is the sub-list for field type_name } func init() { file_lightning_proto_init() } diff --git a/lnrpc/lightning.proto b/lnrpc/lightning.proto index b60f45e0950..b6f6e1d7798 100644 --- a/lnrpc/lightning.proto +++ b/lnrpc/lightning.proto @@ -3360,6 +3360,19 @@ message QueryRoutesRequest { channel may be used. */ repeated uint64 outgoing_chan_ids = 20; + + /* + An optional payment address included in the invoice (also called payment + secret). If set, an MPP record containing this value will be included in + the final hop of the returned route. + */ + bytes payment_addr = 21; + + /* + An optional AMP record to be included within the last hop of the route. + If set, payment_addr must also be set. See AMPRecord for details. + */ + AMPRecord amp_record = 22; } message NodePair { diff --git a/lnrpc/lightning.swagger.json b/lnrpc/lightning.swagger.json index 0818132ede3..ec5e5a35d34 100644 --- a/lnrpc/lightning.swagger.json +++ b/lnrpc/lightning.swagger.json @@ -1541,6 +1541,35 @@ "format": "uint64" }, "collectionFormat": "multi" + }, + { + "name": "payment_addr", + "description": "32 byte random value included in the invoice.\nThe receiver only accepts HTLSs that include this.", + "in": "query", + "required": false, + "type": "string", + "format": "byte" + }, + { + "name": "amp_record.root_share", + "in": "query", + "required": false, + "type": "string", + "format": "byte" + }, + { + "name": "amp_record.set_id", + "in": "query", + "required": false, + "type": "string", + "format": "byte" + }, + { + "name": "amp_record.child_index", + "in": "query", + "required": false, + "type": "integer", + "format": "int64" } ], "tags": [ @@ -1692,6 +1721,15 @@ "format": "uint64" }, "description": "The channel ids of the channels allowed for the first hop. If empty, any\nchannel may be used." + }, + "payment_addr": { + "type": "string", + "format": "byte", + "description": "32 byte random value included in the invoice.\nThe receiver only accepts HTLSs that include this." + }, + "amp_record": { + "$ref": "#/definitions/lnrpcAMPRecord", + "description": "An optional AMP record to be included within the last hop of the route.\nIf set, payment_addr must also be set. See AMPRecord for details." } } } diff --git a/lnrpc/routerrpc/router.pb.go b/lnrpc/routerrpc/router.pb.go index d6d6bac7852..3fb21006efc 100644 --- a/lnrpc/routerrpc/router.pb.go +++ b/lnrpc/routerrpc/router.pb.go @@ -2151,8 +2151,11 @@ type BuildRouteRequest struct { // the custom range >= 65536. When using REST, the values must be encoded as // base64. FirstHopCustomRecords map[uint64][]byte `protobuf:"bytes,6,rep,name=first_hop_custom_records,json=firstHopCustomRecords,proto3" json:"first_hop_custom_records,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + // An optional AMP record to be included within the last hop of the route. + // If set, payment_addr must also be set. See AMPRecord for details. + AmpRecord *lnrpc.AMPRecord `protobuf:"bytes,7,opt,name=amp_record,json=ampRecord,proto3" json:"amp_record,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *BuildRouteRequest) Reset() { @@ -2227,6 +2230,13 @@ func (x *BuildRouteRequest) GetFirstHopCustomRecords() map[uint64][]byte { return nil } +func (x *BuildRouteRequest) GetAmpRecord() *lnrpc.AMPRecord { + if x != nil { + return x.AmpRecord + } + return nil +} + type BuildRouteResponse struct { state protoimpl.MessageState `protogen:"open.v1"` // Fully specified route that can be used to execute the payment. @@ -3912,7 +3922,7 @@ const file_routerrpc_router_proto_rawDesc = "" + "\bamt_msat\x18\x03 \x01(\x03R\aamtMsat\"k\n" + "\x18QueryProbabilityResponse\x12 \n" + "\vprobability\x18\x01 \x01(\x01R\vprobability\x12-\n" + - "\ahistory\x18\x02 \x01(\v2\x13.routerrpc.PairDataR\ahistory\"\x86\x03\n" + + "\ahistory\x18\x02 \x01(\v2\x13.routerrpc.PairDataR\ahistory\"\xb7\x03\n" + "\x11BuildRouteRequest\x12\x19\n" + "\bamt_msat\x18\x01 \x01(\x03R\aamtMsat\x12(\n" + "\x10final_cltv_delta\x18\x02 \x01(\x05R\x0efinalCltvDelta\x12,\n" + @@ -3920,7 +3930,9 @@ const file_routerrpc_router_proto_rawDesc = "" + "\vhop_pubkeys\x18\x04 \x03(\fR\n" + "hopPubkeys\x12!\n" + "\fpayment_addr\x18\x05 \x01(\fR\vpaymentAddr\x12p\n" + - "\x18first_hop_custom_records\x18\x06 \x03(\v27.routerrpc.BuildRouteRequest.FirstHopCustomRecordsEntryR\x15firstHopCustomRecords\x1aH\n" + + "\x18first_hop_custom_records\x18\x06 \x03(\v27.routerrpc.BuildRouteRequest.FirstHopCustomRecordsEntryR\x15firstHopCustomRecords\x12/\n" + + "\n" + + "amp_record\x18\a \x01(\v2\x10.lnrpc.AMPRecordR\tampRecord\x1aH\n" + "\x1aFirstHopCustomRecordsEntry\x12\x10\n" + "\x03key\x18\x01 \x01(\x04R\x03key\x12\x14\n" + "\x05value\x18\x02 \x01(\fR\x05value:\x028\x01\"8\n" + @@ -4193,11 +4205,12 @@ var file_routerrpc_router_proto_goTypes = []any{ (lnrpc.PaymentFailureReason)(0), // 64: lnrpc.PaymentFailureReason (*lnrpc.Route)(nil), // 65: lnrpc.Route (*lnrpc.Failure)(nil), // 66: lnrpc.Failure - (lnrpc.Failure_FailureCode)(0), // 67: lnrpc.Failure.FailureCode - (*lnrpc.HTLCAttempt)(nil), // 68: lnrpc.HTLCAttempt - (*lnrpc.ChannelPoint)(nil), // 69: lnrpc.ChannelPoint - (*lnrpc.AliasMap)(nil), // 70: lnrpc.AliasMap - (*lnrpc.Payment)(nil), // 71: lnrpc.Payment + (*lnrpc.AMPRecord)(nil), // 67: lnrpc.AMPRecord + (lnrpc.Failure_FailureCode)(0), // 68: lnrpc.Failure.FailureCode + (*lnrpc.HTLCAttempt)(nil), // 69: lnrpc.HTLCAttempt + (*lnrpc.ChannelPoint)(nil), // 70: lnrpc.ChannelPoint + (*lnrpc.AliasMap)(nil), // 71: lnrpc.AliasMap + (*lnrpc.Payment)(nil), // 72: lnrpc.Payment } var file_routerrpc_router_proto_depIdxs = []int32{ 62, // 0: routerrpc.SendPaymentRequest.route_hints:type_name -> lnrpc.RouteHint @@ -4218,82 +4231,83 @@ var file_routerrpc_router_proto_depIdxs = []int32{ 26, // 15: routerrpc.MissionControlConfig.bimodal:type_name -> routerrpc.BimodalParameters 20, // 16: routerrpc.QueryProbabilityResponse.history:type_name -> routerrpc.PairData 58, // 17: routerrpc.BuildRouteRequest.first_hop_custom_records:type_name -> routerrpc.BuildRouteRequest.FirstHopCustomRecordsEntry - 65, // 18: routerrpc.BuildRouteResponse.route:type_name -> lnrpc.Route - 5, // 19: routerrpc.HtlcEvent.event_type:type_name -> routerrpc.HtlcEvent.EventType - 35, // 20: routerrpc.HtlcEvent.forward_event:type_name -> routerrpc.ForwardEvent - 36, // 21: routerrpc.HtlcEvent.forward_fail_event:type_name -> routerrpc.ForwardFailEvent - 37, // 22: routerrpc.HtlcEvent.settle_event:type_name -> routerrpc.SettleEvent - 40, // 23: routerrpc.HtlcEvent.link_fail_event:type_name -> routerrpc.LinkFailEvent - 39, // 24: routerrpc.HtlcEvent.subscribed_event:type_name -> routerrpc.SubscribedEvent - 38, // 25: routerrpc.HtlcEvent.final_htlc_event:type_name -> routerrpc.FinalHtlcEvent - 34, // 26: routerrpc.ForwardEvent.info:type_name -> routerrpc.HtlcInfo - 34, // 27: routerrpc.LinkFailEvent.info:type_name -> routerrpc.HtlcInfo - 67, // 28: routerrpc.LinkFailEvent.wire_failure:type_name -> lnrpc.Failure.FailureCode - 0, // 29: routerrpc.LinkFailEvent.failure_detail:type_name -> routerrpc.FailureDetail - 1, // 30: routerrpc.PaymentStatus.state:type_name -> routerrpc.PaymentState - 68, // 31: routerrpc.PaymentStatus.htlcs:type_name -> lnrpc.HTLCAttempt - 42, // 32: routerrpc.ForwardHtlcInterceptRequest.incoming_circuit_key:type_name -> routerrpc.CircuitKey - 59, // 33: routerrpc.ForwardHtlcInterceptRequest.custom_records:type_name -> routerrpc.ForwardHtlcInterceptRequest.CustomRecordsEntry - 60, // 34: routerrpc.ForwardHtlcInterceptRequest.in_wire_custom_records:type_name -> routerrpc.ForwardHtlcInterceptRequest.InWireCustomRecordsEntry - 42, // 35: routerrpc.ForwardHtlcInterceptResponse.incoming_circuit_key:type_name -> routerrpc.CircuitKey - 2, // 36: routerrpc.ForwardHtlcInterceptResponse.action:type_name -> routerrpc.ResolveHoldForwardAction - 67, // 37: routerrpc.ForwardHtlcInterceptResponse.failure_code:type_name -> lnrpc.Failure.FailureCode - 61, // 38: routerrpc.ForwardHtlcInterceptResponse.out_wire_custom_records:type_name -> routerrpc.ForwardHtlcInterceptResponse.OutWireCustomRecordsEntry - 69, // 39: routerrpc.UpdateChanStatusRequest.chan_point:type_name -> lnrpc.ChannelPoint - 3, // 40: routerrpc.UpdateChanStatusRequest.action:type_name -> routerrpc.ChanStatusAction - 70, // 41: routerrpc.AddAliasesRequest.alias_maps:type_name -> lnrpc.AliasMap - 70, // 42: routerrpc.AddAliasesResponse.alias_maps:type_name -> lnrpc.AliasMap - 70, // 43: routerrpc.DeleteAliasesRequest.alias_maps:type_name -> lnrpc.AliasMap - 70, // 44: routerrpc.DeleteAliasesResponse.alias_maps:type_name -> lnrpc.AliasMap - 6, // 45: routerrpc.Router.SendPaymentV2:input_type -> routerrpc.SendPaymentRequest - 7, // 46: routerrpc.Router.TrackPaymentV2:input_type -> routerrpc.TrackPaymentRequest - 8, // 47: routerrpc.Router.TrackPayments:input_type -> routerrpc.TrackPaymentsRequest - 9, // 48: routerrpc.Router.EstimateRouteFee:input_type -> routerrpc.RouteFeeRequest - 11, // 49: routerrpc.Router.SendToRoute:input_type -> routerrpc.SendToRouteRequest - 11, // 50: routerrpc.Router.SendToRouteV2:input_type -> routerrpc.SendToRouteRequest - 13, // 51: routerrpc.Router.ResetMissionControl:input_type -> routerrpc.ResetMissionControlRequest - 15, // 52: routerrpc.Router.QueryMissionControl:input_type -> routerrpc.QueryMissionControlRequest - 17, // 53: routerrpc.Router.XImportMissionControl:input_type -> routerrpc.XImportMissionControlRequest - 21, // 54: routerrpc.Router.GetMissionControlConfig:input_type -> routerrpc.GetMissionControlConfigRequest - 23, // 55: routerrpc.Router.SetMissionControlConfig:input_type -> routerrpc.SetMissionControlConfigRequest - 28, // 56: routerrpc.Router.QueryProbability:input_type -> routerrpc.QueryProbabilityRequest - 30, // 57: routerrpc.Router.BuildRoute:input_type -> routerrpc.BuildRouteRequest - 32, // 58: routerrpc.Router.SubscribeHtlcEvents:input_type -> routerrpc.SubscribeHtlcEventsRequest - 6, // 59: routerrpc.Router.SendPayment:input_type -> routerrpc.SendPaymentRequest - 7, // 60: routerrpc.Router.TrackPayment:input_type -> routerrpc.TrackPaymentRequest - 44, // 61: routerrpc.Router.HtlcInterceptor:input_type -> routerrpc.ForwardHtlcInterceptResponse - 45, // 62: routerrpc.Router.UpdateChanStatus:input_type -> routerrpc.UpdateChanStatusRequest - 47, // 63: routerrpc.Router.XAddLocalChanAliases:input_type -> routerrpc.AddAliasesRequest - 49, // 64: routerrpc.Router.XDeleteLocalChanAliases:input_type -> routerrpc.DeleteAliasesRequest - 51, // 65: routerrpc.Router.XFindBaseLocalChanAlias:input_type -> routerrpc.FindBaseAliasRequest - 53, // 66: routerrpc.Router.DeleteForwardingHistory:input_type -> routerrpc.DeleteForwardingHistoryRequest - 71, // 67: routerrpc.Router.SendPaymentV2:output_type -> lnrpc.Payment - 71, // 68: routerrpc.Router.TrackPaymentV2:output_type -> lnrpc.Payment - 71, // 69: routerrpc.Router.TrackPayments:output_type -> lnrpc.Payment - 10, // 70: routerrpc.Router.EstimateRouteFee:output_type -> routerrpc.RouteFeeResponse - 12, // 71: routerrpc.Router.SendToRoute:output_type -> routerrpc.SendToRouteResponse - 68, // 72: routerrpc.Router.SendToRouteV2:output_type -> lnrpc.HTLCAttempt - 14, // 73: routerrpc.Router.ResetMissionControl:output_type -> routerrpc.ResetMissionControlResponse - 16, // 74: routerrpc.Router.QueryMissionControl:output_type -> routerrpc.QueryMissionControlResponse - 18, // 75: routerrpc.Router.XImportMissionControl:output_type -> routerrpc.XImportMissionControlResponse - 22, // 76: routerrpc.Router.GetMissionControlConfig:output_type -> routerrpc.GetMissionControlConfigResponse - 24, // 77: routerrpc.Router.SetMissionControlConfig:output_type -> routerrpc.SetMissionControlConfigResponse - 29, // 78: routerrpc.Router.QueryProbability:output_type -> routerrpc.QueryProbabilityResponse - 31, // 79: routerrpc.Router.BuildRoute:output_type -> routerrpc.BuildRouteResponse - 33, // 80: routerrpc.Router.SubscribeHtlcEvents:output_type -> routerrpc.HtlcEvent - 41, // 81: routerrpc.Router.SendPayment:output_type -> routerrpc.PaymentStatus - 41, // 82: routerrpc.Router.TrackPayment:output_type -> routerrpc.PaymentStatus - 43, // 83: routerrpc.Router.HtlcInterceptor:output_type -> routerrpc.ForwardHtlcInterceptRequest - 46, // 84: routerrpc.Router.UpdateChanStatus:output_type -> routerrpc.UpdateChanStatusResponse - 48, // 85: routerrpc.Router.XAddLocalChanAliases:output_type -> routerrpc.AddAliasesResponse - 50, // 86: routerrpc.Router.XDeleteLocalChanAliases:output_type -> routerrpc.DeleteAliasesResponse - 52, // 87: routerrpc.Router.XFindBaseLocalChanAlias:output_type -> routerrpc.FindBaseAliasResponse - 54, // 88: routerrpc.Router.DeleteForwardingHistory:output_type -> routerrpc.DeleteForwardingHistoryResponse - 67, // [67:89] is the sub-list for method output_type - 45, // [45:67] is the sub-list for method input_type - 45, // [45:45] is the sub-list for extension type_name - 45, // [45:45] is the sub-list for extension extendee - 0, // [0:45] is the sub-list for field type_name + 67, // 18: routerrpc.BuildRouteRequest.amp_record:type_name -> lnrpc.AMPRecord + 65, // 19: routerrpc.BuildRouteResponse.route:type_name -> lnrpc.Route + 5, // 20: routerrpc.HtlcEvent.event_type:type_name -> routerrpc.HtlcEvent.EventType + 35, // 21: routerrpc.HtlcEvent.forward_event:type_name -> routerrpc.ForwardEvent + 36, // 22: routerrpc.HtlcEvent.forward_fail_event:type_name -> routerrpc.ForwardFailEvent + 37, // 23: routerrpc.HtlcEvent.settle_event:type_name -> routerrpc.SettleEvent + 40, // 24: routerrpc.HtlcEvent.link_fail_event:type_name -> routerrpc.LinkFailEvent + 39, // 25: routerrpc.HtlcEvent.subscribed_event:type_name -> routerrpc.SubscribedEvent + 38, // 26: routerrpc.HtlcEvent.final_htlc_event:type_name -> routerrpc.FinalHtlcEvent + 34, // 27: routerrpc.ForwardEvent.info:type_name -> routerrpc.HtlcInfo + 34, // 28: routerrpc.LinkFailEvent.info:type_name -> routerrpc.HtlcInfo + 68, // 29: routerrpc.LinkFailEvent.wire_failure:type_name -> lnrpc.Failure.FailureCode + 0, // 30: routerrpc.LinkFailEvent.failure_detail:type_name -> routerrpc.FailureDetail + 1, // 31: routerrpc.PaymentStatus.state:type_name -> routerrpc.PaymentState + 69, // 32: routerrpc.PaymentStatus.htlcs:type_name -> lnrpc.HTLCAttempt + 42, // 33: routerrpc.ForwardHtlcInterceptRequest.incoming_circuit_key:type_name -> routerrpc.CircuitKey + 59, // 34: routerrpc.ForwardHtlcInterceptRequest.custom_records:type_name -> routerrpc.ForwardHtlcInterceptRequest.CustomRecordsEntry + 60, // 35: routerrpc.ForwardHtlcInterceptRequest.in_wire_custom_records:type_name -> routerrpc.ForwardHtlcInterceptRequest.InWireCustomRecordsEntry + 42, // 36: routerrpc.ForwardHtlcInterceptResponse.incoming_circuit_key:type_name -> routerrpc.CircuitKey + 2, // 37: routerrpc.ForwardHtlcInterceptResponse.action:type_name -> routerrpc.ResolveHoldForwardAction + 68, // 38: routerrpc.ForwardHtlcInterceptResponse.failure_code:type_name -> lnrpc.Failure.FailureCode + 61, // 39: routerrpc.ForwardHtlcInterceptResponse.out_wire_custom_records:type_name -> routerrpc.ForwardHtlcInterceptResponse.OutWireCustomRecordsEntry + 70, // 40: routerrpc.UpdateChanStatusRequest.chan_point:type_name -> lnrpc.ChannelPoint + 3, // 41: routerrpc.UpdateChanStatusRequest.action:type_name -> routerrpc.ChanStatusAction + 71, // 42: routerrpc.AddAliasesRequest.alias_maps:type_name -> lnrpc.AliasMap + 71, // 43: routerrpc.AddAliasesResponse.alias_maps:type_name -> lnrpc.AliasMap + 71, // 44: routerrpc.DeleteAliasesRequest.alias_maps:type_name -> lnrpc.AliasMap + 71, // 45: routerrpc.DeleteAliasesResponse.alias_maps:type_name -> lnrpc.AliasMap + 6, // 46: routerrpc.Router.SendPaymentV2:input_type -> routerrpc.SendPaymentRequest + 7, // 47: routerrpc.Router.TrackPaymentV2:input_type -> routerrpc.TrackPaymentRequest + 8, // 48: routerrpc.Router.TrackPayments:input_type -> routerrpc.TrackPaymentsRequest + 9, // 49: routerrpc.Router.EstimateRouteFee:input_type -> routerrpc.RouteFeeRequest + 11, // 50: routerrpc.Router.SendToRoute:input_type -> routerrpc.SendToRouteRequest + 11, // 51: routerrpc.Router.SendToRouteV2:input_type -> routerrpc.SendToRouteRequest + 13, // 52: routerrpc.Router.ResetMissionControl:input_type -> routerrpc.ResetMissionControlRequest + 15, // 53: routerrpc.Router.QueryMissionControl:input_type -> routerrpc.QueryMissionControlRequest + 17, // 54: routerrpc.Router.XImportMissionControl:input_type -> routerrpc.XImportMissionControlRequest + 21, // 55: routerrpc.Router.GetMissionControlConfig:input_type -> routerrpc.GetMissionControlConfigRequest + 23, // 56: routerrpc.Router.SetMissionControlConfig:input_type -> routerrpc.SetMissionControlConfigRequest + 28, // 57: routerrpc.Router.QueryProbability:input_type -> routerrpc.QueryProbabilityRequest + 30, // 58: routerrpc.Router.BuildRoute:input_type -> routerrpc.BuildRouteRequest + 32, // 59: routerrpc.Router.SubscribeHtlcEvents:input_type -> routerrpc.SubscribeHtlcEventsRequest + 6, // 60: routerrpc.Router.SendPayment:input_type -> routerrpc.SendPaymentRequest + 7, // 61: routerrpc.Router.TrackPayment:input_type -> routerrpc.TrackPaymentRequest + 44, // 62: routerrpc.Router.HtlcInterceptor:input_type -> routerrpc.ForwardHtlcInterceptResponse + 45, // 63: routerrpc.Router.UpdateChanStatus:input_type -> routerrpc.UpdateChanStatusRequest + 47, // 64: routerrpc.Router.XAddLocalChanAliases:input_type -> routerrpc.AddAliasesRequest + 49, // 65: routerrpc.Router.XDeleteLocalChanAliases:input_type -> routerrpc.DeleteAliasesRequest + 51, // 66: routerrpc.Router.XFindBaseLocalChanAlias:input_type -> routerrpc.FindBaseAliasRequest + 53, // 67: routerrpc.Router.DeleteForwardingHistory:input_type -> routerrpc.DeleteForwardingHistoryRequest + 72, // 68: routerrpc.Router.SendPaymentV2:output_type -> lnrpc.Payment + 72, // 69: routerrpc.Router.TrackPaymentV2:output_type -> lnrpc.Payment + 72, // 70: routerrpc.Router.TrackPayments:output_type -> lnrpc.Payment + 10, // 71: routerrpc.Router.EstimateRouteFee:output_type -> routerrpc.RouteFeeResponse + 12, // 72: routerrpc.Router.SendToRoute:output_type -> routerrpc.SendToRouteResponse + 69, // 73: routerrpc.Router.SendToRouteV2:output_type -> lnrpc.HTLCAttempt + 14, // 74: routerrpc.Router.ResetMissionControl:output_type -> routerrpc.ResetMissionControlResponse + 16, // 75: routerrpc.Router.QueryMissionControl:output_type -> routerrpc.QueryMissionControlResponse + 18, // 76: routerrpc.Router.XImportMissionControl:output_type -> routerrpc.XImportMissionControlResponse + 22, // 77: routerrpc.Router.GetMissionControlConfig:output_type -> routerrpc.GetMissionControlConfigResponse + 24, // 78: routerrpc.Router.SetMissionControlConfig:output_type -> routerrpc.SetMissionControlConfigResponse + 29, // 79: routerrpc.Router.QueryProbability:output_type -> routerrpc.QueryProbabilityResponse + 31, // 80: routerrpc.Router.BuildRoute:output_type -> routerrpc.BuildRouteResponse + 33, // 81: routerrpc.Router.SubscribeHtlcEvents:output_type -> routerrpc.HtlcEvent + 41, // 82: routerrpc.Router.SendPayment:output_type -> routerrpc.PaymentStatus + 41, // 83: routerrpc.Router.TrackPayment:output_type -> routerrpc.PaymentStatus + 43, // 84: routerrpc.Router.HtlcInterceptor:output_type -> routerrpc.ForwardHtlcInterceptRequest + 46, // 85: routerrpc.Router.UpdateChanStatus:output_type -> routerrpc.UpdateChanStatusResponse + 48, // 86: routerrpc.Router.XAddLocalChanAliases:output_type -> routerrpc.AddAliasesResponse + 50, // 87: routerrpc.Router.XDeleteLocalChanAliases:output_type -> routerrpc.DeleteAliasesResponse + 52, // 88: routerrpc.Router.XFindBaseLocalChanAlias:output_type -> routerrpc.FindBaseAliasResponse + 54, // 89: routerrpc.Router.DeleteForwardingHistory:output_type -> routerrpc.DeleteForwardingHistoryResponse + 68, // [68:90] is the sub-list for method output_type + 46, // [46:68] is the sub-list for method input_type + 46, // [46:46] is the sub-list for extension type_name + 46, // [46:46] is the sub-list for extension extendee + 0, // [0:46] is the sub-list for field type_name } func init() { file_routerrpc_router_proto_init() } diff --git a/lnrpc/routerrpc/router.proto b/lnrpc/routerrpc/router.proto index 5ddf9226143..0a27553a8c7 100644 --- a/lnrpc/routerrpc/router.proto +++ b/lnrpc/routerrpc/router.proto @@ -773,6 +773,12 @@ message BuildRouteRequest { base64. */ map first_hop_custom_records = 6; + + /* + An optional AMP record to be included within the last hop of the route. + If set, payment_addr must also be set. See AMPRecord for details. + */ + lnrpc.AMPRecord amp_record = 7; } message BuildRouteResponse { diff --git a/lnrpc/routerrpc/router.swagger.json b/lnrpc/routerrpc/router.swagger.json index e5b21eee0ff..13c5d130824 100644 --- a/lnrpc/routerrpc/router.swagger.json +++ b/lnrpc/routerrpc/router.swagger.json @@ -1377,6 +1377,10 @@ "format": "byte" }, "description": "An optional field that can be used to pass an arbitrary set of TLV records\nto the first hop peer of this payment. This can be used to pass application\nspecific data during the payment attempt. Record types are required to be in\nthe custom range \u003e= 65536. When using REST, the values must be encoded as\nbase64." + }, + "amp_record": { + "$ref": "#/definitions/lnrpcAMPRecord", + "description": "An optional AMP record to be included within the last hop of the route.\nIf set, payment_addr must also be set. See AMPRecord for details." } } }, diff --git a/lnrpc/routerrpc/router_backend.go b/lnrpc/routerrpc/router_backend.go index 3bb4d82e9eb..1bcad320247 100644 --- a/lnrpc/routerrpc/router_backend.go +++ b/lnrpc/routerrpc/router_backend.go @@ -220,6 +220,32 @@ func (r *RouterBackend) QueryRoutes(ctx context.Context, return nil, err } + finalHop := route.FinalHop() + + // If payment_addr was provided inject MPP into final hop + if in.PaymentAddr != nil { + if len(in.PaymentAddr) != 32 { + return nil, errors.New("payment_addr must be 32 bytes") + } + + finalHop.MPP = record.NewMPP(finalHop.AmtToForward, [32]byte(in.PaymentAddr)) + } + + // If AMP was provided inject into final hop alongside MPP record. + if in.AmpRecord != nil { + if in.PaymentAddr == nil { + return nil, errors.New("payment_addr must be set when " + + "amp_record is provided") + } + + amp, err := UnmarshalAMP(in.AmpRecord) + if err != nil { + return nil, err + } + + finalHop.AMP = amp + } + // For each valid route, we'll convert the result into the format // required by the RPC system. rpcRoute, err := r.MarshallRoute(route) diff --git a/lnrpc/routerrpc/router_backend_test.go b/lnrpc/routerrpc/router_backend_test.go index e572f8066f0..0c8f1282687 100644 --- a/lnrpc/routerrpc/router_backend_test.go +++ b/lnrpc/routerrpc/router_backend_test.go @@ -21,6 +21,7 @@ const ( destKey = "0286098b97bc843372b4426d4b276cea9aa2f48f0428d6f5b66ae101befc14f8b4" ignoreNodeKey = "02f274f48f3c0d590449a6776e3ce8825076ac376e470e992246eebc565ef8bb2a" hintNodeKey = "0274e7fb33eafd74fe1acb6db7680bb4aa78e9c839a6e954e38abfad680f645ef7" + paymentAddr = "720eb5ee68523466ee822449296273de81eeab11093f3d5e20c50d6f557b97f4" testMissionControlProb = 0.5 ) @@ -43,29 +44,29 @@ var ( // and passed onto path finding. func TestQueryRoutes(t *testing.T) { t.Run("no mission control", func(t *testing.T) { - testQueryRoutes(t, false, false, true, singleChanID) + testQueryRoutes(t, false, false, true, false, singleChanID) }) - t.Run("no mission control and msat", func(t *testing.T) { - testQueryRoutes(t, false, true, true, singleChanID) + t.Run("no mission control, using msat and MPP", func(t *testing.T) { + testQueryRoutes(t, false, true, true, true, singleChanID) }) t.Run("with mission control", func(t *testing.T) { - testQueryRoutes(t, true, false, true, singleChanID) + testQueryRoutes(t, true, false, true, false, singleChanID) }) t.Run("no mission control bad cltv limit", func(t *testing.T) { - testQueryRoutes(t, false, false, false, singleChanID) + testQueryRoutes(t, false, false, false, false, singleChanID) }) t.Run("both outgoing chan id and chan ids", func(t *testing.T) { - testQueryRoutes(t, true, false, true, bothChanIds) + testQueryRoutes(t, true, false, true, false, bothChanIds) }) t.Run("multiple outgoing chan ids", func(t *testing.T) { - testQueryRoutes(t, false, true, true, multiChanID) + testQueryRoutes(t, false, true, true, false, multiChanID) }) } -func testQueryRoutes(t *testing.T, useMissionControl bool, useMsat bool, - setTimelock bool, outgoingChanConfig string) { +func testQueryRoutes(t *testing.T, useMissionControl, useMsat, + setTimelock, useMPP bool, outgoingChanConfig string) { ignoreNodeBytes, err := hex.DecodeString(ignoreNodeKey) if err != nil { @@ -102,6 +103,14 @@ func testQueryRoutes(t *testing.T, useMissionControl bool, useMsat bool, }, } + var paymentAddrBytes []byte + if useMPP { + paymentAddrBytes, err = hex.DecodeString(paymentAddr) + if err != nil { + t.Fatal(err) + } + } + request := &lnrpc.QueryRoutesRequest{ PubKey: destKey, FinalCltvDelta: 100, @@ -118,6 +127,7 @@ func testQueryRoutes(t *testing.T, useMissionControl bool, useMsat bool, LastHopPubkey: lastHop[:], DestFeatures: []lnrpc.FeatureBit{lnrpc.FeatureBit_MPP_OPT}, RouteHints: rpcRouteHints, + PaymentAddr: paymentAddrBytes, } amtSat := int64(100000) @@ -224,6 +234,10 @@ func testQueryRoutes(t *testing.T, useMissionControl bool, useMsat bool, } hops := []*route.Hop{{}} + if useMsat { + hops = []*route.Hop{{AmtToForward: lnwire.MilliSatoshi(amtSat * 1000)}} + } + route, err := route.NewRouteFromHops( req.Amount, 144, req.Source, hops, ) @@ -285,6 +299,14 @@ func testQueryRoutes(t *testing.T, useMissionControl bool, useMsat bool, if len(resp.Routes) != 1 { t.Fatal("expected a single route response") } + + // If we are using MPP then we should expect the last hop to have one set + if useMPP { + finalHop := resp.Routes[0].Hops[len(resp.Routes[0].Hops)-1] + require.NotNil(t, finalHop.MppRecord) + require.Equal(t, request.PaymentAddr, finalHop.MppRecord.PaymentAddr) + require.Equal(t, amtSat*1000, finalHop.MppRecord.TotalAmtMsat) + } } type mockMissionControl struct { diff --git a/lnrpc/routerrpc/router_server.go b/lnrpc/routerrpc/router_server.go index e3ac207e597..994db4c4dee 100644 --- a/lnrpc/routerrpc/router_server.go +++ b/lnrpc/routerrpc/router_server.go @@ -21,6 +21,7 @@ import ( "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/macaroons" paymentsdb "github.com/lightningnetwork/lnd/payments/db" + "github.com/lightningnetwork/lnd/record" "github.com/lightningnetwork/lnd/routing" "github.com/lightningnetwork/lnd/routing/route" "github.com/lightningnetwork/lnd/zpay32" @@ -1072,6 +1073,10 @@ func (s *Server) SendToRouteV2(ctx context.Context, return nil, err } + if route.FinalHop().MPP == nil { + return nil, fmt.Errorf("unable to send, no MPP provided") + } + hash, err := lntypes.MakeHash(req.PaymentHash) if err != nil { return nil, err @@ -1675,12 +1680,23 @@ func (s *Server) BuildRoute(_ context.Context, outgoingChan = &req.OutgoingChanId } - var payAddr fn.Option[[32]byte] - if len(req.PaymentAddr) != 0 { - var backingPayAddr [32]byte - copy(backingPayAddr[:], req.PaymentAddr) + if len(req.PaymentAddr) != 32 { + return nil, errors.New("payment_addr must be 32 bytes") + } - payAddr = fn.Some(backingPayAddr) + var payAddr fn.Option[[32]byte] + var backingPayAddr [32]byte + copy(backingPayAddr[:], req.PaymentAddr) + payAddr = fn.Some(backingPayAddr) + + // Optional AMP record + var ampRecord *record.AMP + if req.AmpRecord != nil { + var err error + ampRecord, err = UnmarshalAMP(req.AmpRecord) + if err != nil { + return nil, err + } } if req.FinalCltvDelta == 0 { @@ -1708,7 +1724,7 @@ func (s *Server) BuildRoute(_ context.Context, // Build the route and return it to the caller. route, err := s.cfg.Router.BuildRoute( amt, hops, outgoingChan, req.FinalCltvDelta, payAddr, - firstHopBlob, + ampRecord, firstHopBlob, ) if err != nil { return nil, err diff --git a/routing/pathfind.go b/routing/pathfind.go index e2ae5d4caa3..824c70850b3 100644 --- a/routing/pathfind.go +++ b/routing/pathfind.go @@ -113,6 +113,7 @@ type finalHopParams struct { records record.CustomSet paymentAddr fn.Option[[32]byte] + amp *record.AMP // metadata is additional data that is sent along with the payment to // the payee. @@ -265,6 +266,12 @@ func newRoute(sourceVertex route.Vertex, mpp = record.NewMPP(finalHop.totalAmt, addr) }) + // If we're attaching an AMP record but the receiver doesn't support + // AMP, fail. + if finalHop.amp != nil && !supports(lnwire.AMPOptional) { + return nil, errors.New("cannot attach AMP record") + } + metadata = finalHop.metadata if blindedPathSet != nil { @@ -312,6 +319,7 @@ func newRoute(sourceVertex route.Vertex, OutgoingTimeLock: outgoingTimeLock, CustomRecords: customRecords, MPP: mpp, + AMP: finalHop.amp, Metadata: metadata, TotalAmtMsat: totalAmtMsatBlinded, } diff --git a/routing/pathfind_test.go b/routing/pathfind_test.go index 85689ef9ed1..d4f029af361 100644 --- a/routing/pathfind_test.go +++ b/routing/pathfind_test.go @@ -86,6 +86,14 @@ var ( lnwire.MPPOptional, ) + ampFeatures = lnwire.NewFeatureVector( + lnwire.NewRawFeatureVector( + lnwire.TLVOnionPayloadRequired, + lnwire.PaymentAddrOptional, + lnwire.AMPOptional, + ), lnwire.Features, + ) + unknownRequiredFeatures = lnwire.NewFeatureVector( lnwire.NewRawFeatureVector(100), lnwire.Features, ) @@ -1540,6 +1548,8 @@ func TestNewRoute(t *testing.T) { paymentAddr fn.Option[[32]byte] + amp *record.AMP + // metadata is the payment metadata to attach to the route. metadata []byte @@ -1569,6 +1579,7 @@ func TestNewRoute(t *testing.T) { expectError bool expectedMPP *record.MPP + expectedAMP *record.AMP }{ { // For a single hop payment, no fees are expected to be paid. @@ -1630,6 +1641,27 @@ func TestNewRoute(t *testing.T) { expectedMPP: record.NewMPP( 100000, testPaymentAddr, ), + }, { + // For a two hop payment, only the fee for the first hop + // needs to be paid. The destination hop does not require + // a fee to receive the payment. + name: "two hop single shot amp", + destFeatures: ampFeatures, + paymentAddr: fn.Some(testPaymentAddr), + amp: record.NewAMP([32]byte{1}, [32]byte{2}, 0), + paymentAmount: 100000, + hops: []*models.CachedEdgePolicy{ + createHop(0, 1000, 1000000, 10), + createHop(30, 1000, 1000000, 5), + }, + expectedFees: []lnwire.MilliSatoshi{130, 0}, + expectedTimeLocks: []uint32{1, 1}, + expectedTotalAmount: 100130, + expectedTotalTimeLock: 6, + expectedMPP: record.NewMPP( + 100000, testPaymentAddr, + ), + expectedAMP: record.NewAMP([32]byte{1}, [32]byte{2}, 0), }, { // A three hop payment where the first and second hop // will both charge 1 msat. The fee for the first hop @@ -1750,6 +1782,9 @@ func TestNewRoute(t *testing.T) { testCase.expectedMPP, finalHop.MPP) } + require.Equal(t, testCase.expectedAMP, finalHop.AMP, + "Expected final hop amp field") + if !bytes.Equal(finalHop.Metadata, testCase.metadata) { t.Errorf("Expected final metadata field: %v, "+ " but got: %v instead", @@ -1775,6 +1810,7 @@ func TestNewRoute(t *testing.T) { cltvDelta: finalHopCLTV, records: nil, paymentAddr: testCase.paymentAddr, + amp: testCase.amp, metadata: testCase.metadata, }, nil, ) diff --git a/routing/router.go b/routing/router.go index 37aeef22361..1ac14571656 100644 --- a/routing/router.go +++ b/routing/router.go @@ -1343,7 +1343,7 @@ func (e ErrNoChannel) Error() string { // outgoing channel, use the outgoingChan parameter. func (r *ChannelRouter) BuildRoute(amt fn.Option[lnwire.MilliSatoshi], hops []route.Vertex, outgoingChan *uint64, finalCltvDelta int32, - payAddr fn.Option[[32]byte], firstHopBlob fn.Option[[]byte]) ( + payAddr fn.Option[[32]byte], amp *record.AMP, firstHopBlob fn.Option[[]byte]) ( *route.Route, error) { log.Tracef("BuildRoute called: hopsCount=%v, amt=%v", len(hops), amt) @@ -1424,6 +1424,7 @@ func (r *ChannelRouter) BuildRoute(amt fn.Option[lnwire.MilliSatoshi], cltvDelta: uint16(finalCltvDelta), records: nil, paymentAddr: payAddr, + amp: amp, }, nil, ) } diff --git a/routing/router_test.go b/routing/router_test.go index e14ac199f83..88a46dc6059 100644 --- a/routing/router_test.go +++ b/routing/router_test.go @@ -1539,7 +1539,10 @@ func TestBuildRoute(t *testing.T) { // Setup a three node network. chanCapSat := btcutil.Amount(100000) paymentAddrFeatures := lnwire.NewFeatureVector( - lnwire.NewRawFeatureVector(lnwire.PaymentAddrOptional), + lnwire.NewRawFeatureVector( + lnwire.PaymentAddrOptional, + lnwire.AMPOptional, + ), lnwire.Features, ) testChannels := []*testChannel{ @@ -1647,7 +1650,7 @@ func TestBuildRoute(t *testing.T) { ctx := createTestCtxFromGraphInstance(t, startingBlockHeight, testGraph) checkHops := func(rt *route.Route, expected []uint64, - payAddr [32]byte) { + payAddr [32]byte, amp *record.AMP) { t.Helper() @@ -1660,6 +1663,7 @@ func TestBuildRoute(t *testing.T) { lastHop := rt.Hops[len(rt.Hops)-1] require.NotNil(t, lastHop.MPP) require.Equal(t, lastHop.MPP.PaymentAddr(), payAddr) + require.Equal(t, amp, lastHop.AMP) } var payAddr [32]byte @@ -1671,14 +1675,14 @@ func TestBuildRoute(t *testing.T) { // Test that we can't build a route when no hops are given. hops = []route.Vertex{} _, err = ctx.router.BuildRoute( - noAmt, hops, nil, 40, fn.None[[32]byte](), fn.None[[]byte](), + noAmt, hops, nil, 40, fn.None[[32]byte](), nil, fn.None[[]byte](), ) require.Error(t, err) // Create hop list for an unknown destination. hops := []route.Vertex{ctx.aliases["b"], ctx.aliases["y"]} _, err = ctx.router.BuildRoute( - noAmt, hops, nil, 40, fn.Some(payAddr), fn.None[[]byte](), + noAmt, hops, nil, 40, fn.Some(payAddr), nil, fn.None[[]byte](), ) noChanErr := ErrNoChannel{} require.ErrorAs(t, err, &noChanErr) @@ -1691,19 +1695,19 @@ func TestBuildRoute(t *testing.T) { // Build the route for the given amount. rt, err := ctx.router.BuildRoute( fn.Some(amt), hops, nil, 40, fn.Some(payAddr), - fn.None[[]byte](), + nil, fn.None[[]byte](), ) require.NoError(t, err) // Check that we get the expected route back. The total amount should be // the amount to deliver to hop c (100 sats) plus the max fee for the // connection b->c (6 sats). - checkHops(rt, []uint64{1, 7}, payAddr) + checkHops(rt, []uint64{1, 7}, payAddr, nil) require.Equal(t, lnwire.MilliSatoshi(106000), rt.TotalAmount) // Build the route for the minimum amount. rt, err = ctx.router.BuildRoute( - noAmt, hops, nil, 40, fn.Some(payAddr), fn.None[[]byte](), + noAmt, hops, nil, 40, fn.Some(payAddr), nil, fn.None[[]byte](), ) require.NoError(t, err) @@ -1711,7 +1715,7 @@ func TestBuildRoute(t *testing.T) { // send from b to c is 20 sats. Hop b charges 1200 msat for the // forwarding. The channel between hop a and b can carry amounts in the // range [5, 100], so 21200 msats is the minimum amount for this route. - checkHops(rt, []uint64{1, 7}, payAddr) + checkHops(rt, []uint64{1, 7}, payAddr, nil) require.Equal(t, lnwire.MilliSatoshi(21200), rt.TotalAmount) // The receiver gets sent the minimal HTLC amount. @@ -1721,7 +1725,7 @@ func TestBuildRoute(t *testing.T) { // There is no amount that can pass through both channel 5 and 4. hops = []route.Vertex{ctx.aliases["e"], ctx.aliases["c"]} _, err = ctx.router.BuildRoute( - noAmt, hops, nil, 40, fn.None[[32]byte](), fn.None[[]byte](), + noAmt, hops, nil, 40, fn.None[[32]byte](), nil, fn.None[[]byte](), ) require.Error(t, err) noChanErr = ErrNoChannel{} @@ -1741,10 +1745,10 @@ func TestBuildRoute(t *testing.T) { // policy of channel 3. hops = []route.Vertex{ctx.aliases["b"], ctx.aliases["z"]} rt, err = ctx.router.BuildRoute( - noAmt, hops, nil, 40, fn.Some(payAddr), fn.None[[]byte](), + noAmt, hops, nil, 40, fn.Some(payAddr), nil, fn.None[[]byte](), ) require.NoError(t, err) - checkHops(rt, []uint64{1, 8}, payAddr) + checkHops(rt, []uint64{1, 8}, payAddr, nil) require.Equal(t, lnwire.MilliSatoshi(21200), rt.TotalAmount) require.Equal(t, lnwire.MilliSatoshi(20000), rt.Hops[1].AmtToForward) @@ -1756,10 +1760,10 @@ func TestBuildRoute(t *testing.T) { amt = lnwire.NewMSatFromSatoshis(100) rt, err = ctx.router.BuildRoute( fn.Some(amt), hops, nil, 40, fn.Some(payAddr), - fn.None[[]byte](), + nil, fn.None[[]byte](), ) require.NoError(t, err) - checkHops(rt, []uint64{9, 10}, payAddr) + checkHops(rt, []uint64{9, 10}, payAddr, nil) require.EqualValues(t, 104894, rt.TotalAmount) // Also check the min amount with inbound fees. The min amount bumps @@ -1772,11 +1776,23 @@ func TestBuildRoute(t *testing.T) { // is a third pass through newRoute in which this gets corrected to end hops = []route.Vertex{ctx.aliases["d"], ctx.aliases["f"]} rt, err = ctx.router.BuildRoute( - noAmt, hops, nil, 40, fn.Some(payAddr), fn.None[[]byte](), + noAmt, hops, nil, 40, fn.Some(payAddr), nil, fn.None[[]byte](), ) require.NoError(t, err) - checkHops(rt, []uint64{9, 10}, payAddr) + checkHops(rt, []uint64{9, 10}, payAddr, nil) require.EqualValues(t, 20180, rt.TotalAmount, "%v", rt.TotalAmount) + + // Test that an AMP record is correctly set on the final hop alongside + // the required MPP record. + hops = []route.Vertex{ctx.aliases["b"], ctx.aliases["c"]} + ampRecord := record.NewAMP([32]byte{1}, [32]byte{2}, 0) + rt, err = ctx.router.BuildRoute( + fn.Some(amt), hops, nil, 40, fn.Some(payAddr), + ampRecord, fn.None[[]byte](), + ) + require.NoError(t, err) + checkHops(rt, []uint64{1, 7}, payAddr, ampRecord) + require.EqualValues(t, 106000, rt.TotalAmount) } // TestReceiverAmtForwardPass tests that the forward pass returns the expected