diff --git a/docs/release-notes/release-notes-0.22.0.md b/docs/release-notes/release-notes-0.22.0.md index 45e76051922..14ed2ee6874 100644 --- a/docs/release-notes/release-notes-0.22.0.md +++ b/docs/release-notes/release-notes-0.22.0.md @@ -40,6 +40,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. + * The `routerrpc.EstimateRouteFee` RPC now supports [restricting fee estimates to specific first-hop outgoing channels](https://github.com/lightningnetwork/lnd/pull/10501) via the new diff --git a/lnrpc/lightning.pb.go b/lnrpc/lightning.pb.go index ebfed318025..54100962fdd 100644 --- a/lnrpc/lightning.pb.go +++ b/lnrpc/lightning.pb.go @@ -9733,8 +9733,15 @@ 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 + // 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. + 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() { @@ -9894,6 +9901,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 @@ -19235,7 +19256,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\"\x9e\a\n" + + "\x13custom_channel_data\x18\t \x01(\fR\x11customChannelData\"\xf2\a\n" + "\x12QueryRoutesRequest\x12\x17\n" + "\apub_key\x18\x01 \x01(\tR\x06pubKey\x12\x10\n" + "\x03amt\x18\x02 \x01(\x03R\x03amt\x12\x19\n" + @@ -19257,7 +19278,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\x04J\x04\b\x0e\x10\x0f\".\n" + @@ -20508,246 +20532,247 @@ var file_lightning_proto_depIdxs = []int32{ 154, // 95: lnrpc.QueryRoutesRequest.route_hints:type_name -> lnrpc.RouteHint 155, // 96: lnrpc.QueryRoutesRequest.blinded_payment_paths:type_name -> lnrpc.BlindedPaymentPath 11, // 97: lnrpc.QueryRoutesRequest.dest_features:type_name -> lnrpc.FeatureBit - 129, // 98: lnrpc.QueryRoutesResponse.routes:type_name -> lnrpc.Route - 127, // 99: lnrpc.Hop.mpp_record:type_name -> lnrpc.MPPRecord - 128, // 100: lnrpc.Hop.amp_record:type_name -> lnrpc.AMPRecord - 242, // 101: lnrpc.Hop.custom_records:type_name -> lnrpc.Hop.CustomRecordsEntry - 126, // 102: lnrpc.Route.hops:type_name -> lnrpc.Hop - 132, // 103: lnrpc.NodeInfo.node:type_name -> lnrpc.LightningNode - 136, // 104: lnrpc.NodeInfo.channels:type_name -> lnrpc.ChannelEdge - 133, // 105: lnrpc.LightningNode.addresses:type_name -> lnrpc.NodeAddress - 243, // 106: lnrpc.LightningNode.features:type_name -> lnrpc.LightningNode.FeaturesEntry - 244, // 107: lnrpc.LightningNode.custom_records:type_name -> lnrpc.LightningNode.CustomRecordsEntry - 245, // 108: lnrpc.RoutingPolicy.custom_records:type_name -> lnrpc.RoutingPolicy.CustomRecordsEntry - 134, // 109: lnrpc.ChannelEdge.node1_policy:type_name -> lnrpc.RoutingPolicy - 134, // 110: lnrpc.ChannelEdge.node2_policy:type_name -> lnrpc.RoutingPolicy - 246, // 111: lnrpc.ChannelEdge.custom_records:type_name -> lnrpc.ChannelEdge.CustomRecordsEntry - 135, // 112: lnrpc.ChannelEdge.auth_proof:type_name -> lnrpc.ChannelAuthProof - 132, // 113: lnrpc.ChannelGraph.nodes:type_name -> lnrpc.LightningNode - 136, // 114: lnrpc.ChannelGraph.edges:type_name -> lnrpc.ChannelEdge - 8, // 115: lnrpc.NodeMetricsRequest.types:type_name -> lnrpc.NodeMetricType - 247, // 116: lnrpc.NodeMetricsResponse.betweenness_centrality:type_name -> lnrpc.NodeMetricsResponse.BetweennessCentralityEntry - 149, // 117: lnrpc.GraphTopologyUpdate.node_updates:type_name -> lnrpc.NodeUpdate - 150, // 118: lnrpc.GraphTopologyUpdate.channel_updates:type_name -> lnrpc.ChannelEdgeUpdate - 151, // 119: lnrpc.GraphTopologyUpdate.closed_chans:type_name -> lnrpc.ClosedChannelUpdate - 133, // 120: lnrpc.NodeUpdate.node_addresses:type_name -> lnrpc.NodeAddress - 248, // 121: lnrpc.NodeUpdate.features:type_name -> lnrpc.NodeUpdate.FeaturesEntry - 40, // 122: lnrpc.ChannelEdgeUpdate.chan_point:type_name -> lnrpc.ChannelPoint - 134, // 123: lnrpc.ChannelEdgeUpdate.routing_policy:type_name -> lnrpc.RoutingPolicy - 40, // 124: lnrpc.ClosedChannelUpdate.chan_point:type_name -> lnrpc.ChannelPoint - 152, // 125: lnrpc.RouteHint.hop_hints:type_name -> lnrpc.HopHint - 156, // 126: lnrpc.BlindedPaymentPath.blinded_path:type_name -> lnrpc.BlindedPath - 11, // 127: lnrpc.BlindedPaymentPath.features:type_name -> lnrpc.FeatureBit - 157, // 128: lnrpc.BlindedPath.blinded_hops:type_name -> lnrpc.BlindedHop - 9, // 129: lnrpc.AMPInvoiceState.state:type_name -> lnrpc.InvoiceHTLCState - 154, // 130: lnrpc.Invoice.route_hints:type_name -> lnrpc.RouteHint - 18, // 131: lnrpc.Invoice.state:type_name -> lnrpc.Invoice.InvoiceState - 161, // 132: lnrpc.Invoice.htlcs:type_name -> lnrpc.InvoiceHTLC - 249, // 133: lnrpc.Invoice.features:type_name -> lnrpc.Invoice.FeaturesEntry - 250, // 134: lnrpc.Invoice.amp_invoice_state:type_name -> lnrpc.Invoice.AmpInvoiceStateEntry - 160, // 135: lnrpc.Invoice.blinded_path_config:type_name -> lnrpc.BlindedPathConfig - 9, // 136: lnrpc.InvoiceHTLC.state:type_name -> lnrpc.InvoiceHTLCState - 251, // 137: lnrpc.InvoiceHTLC.custom_records:type_name -> lnrpc.InvoiceHTLC.CustomRecordsEntry - 162, // 138: lnrpc.InvoiceHTLC.amp:type_name -> lnrpc.AMP - 159, // 139: lnrpc.ListInvoiceResponse.invoices:type_name -> lnrpc.Invoice - 19, // 140: lnrpc.Payment.status:type_name -> lnrpc.Payment.PaymentStatus - 171, // 141: lnrpc.Payment.htlcs:type_name -> lnrpc.HTLCAttempt - 10, // 142: lnrpc.Payment.failure_reason:type_name -> lnrpc.PaymentFailureReason - 252, // 143: lnrpc.Payment.first_hop_custom_records:type_name -> lnrpc.Payment.FirstHopCustomRecordsEntry - 20, // 144: lnrpc.HTLCAttempt.status:type_name -> lnrpc.HTLCAttempt.HTLCStatus - 129, // 145: lnrpc.HTLCAttempt.route:type_name -> lnrpc.Route - 215, // 146: lnrpc.HTLCAttempt.failure:type_name -> lnrpc.Failure - 170, // 147: lnrpc.ListPaymentsResponse.payments:type_name -> lnrpc.Payment - 40, // 148: lnrpc.AbandonChannelRequest.channel_point:type_name -> lnrpc.ChannelPoint - 154, // 149: lnrpc.PayReq.route_hints:type_name -> lnrpc.RouteHint - 253, // 150: lnrpc.PayReq.features:type_name -> lnrpc.PayReq.FeaturesEntry - 155, // 151: lnrpc.PayReq.blinded_paths:type_name -> lnrpc.BlindedPaymentPath - 186, // 152: lnrpc.FeeReportResponse.channel_fees:type_name -> lnrpc.ChannelFeeReport - 40, // 153: lnrpc.PolicyUpdateRequest.chan_point:type_name -> lnrpc.ChannelPoint - 188, // 154: lnrpc.PolicyUpdateRequest.inbound_fee:type_name -> lnrpc.InboundFee - 41, // 155: lnrpc.FailedUpdate.outpoint:type_name -> lnrpc.OutPoint - 12, // 156: lnrpc.FailedUpdate.reason:type_name -> lnrpc.UpdateFailure - 190, // 157: lnrpc.PolicyUpdateResponse.failed_updates:type_name -> lnrpc.FailedUpdate - 193, // 158: lnrpc.ForwardingHistoryResponse.forwarding_events:type_name -> lnrpc.ForwardingEvent - 40, // 159: lnrpc.ExportChannelBackupRequest.chan_point:type_name -> lnrpc.ChannelPoint - 40, // 160: lnrpc.ChannelBackup.chan_point:type_name -> lnrpc.ChannelPoint - 40, // 161: lnrpc.MultiChanBackup.chan_points:type_name -> lnrpc.ChannelPoint - 200, // 162: lnrpc.ChanBackupSnapshot.single_chan_backups:type_name -> lnrpc.ChannelBackups - 197, // 163: lnrpc.ChanBackupSnapshot.multi_chan_backup:type_name -> lnrpc.MultiChanBackup - 196, // 164: lnrpc.ChannelBackups.chan_backups:type_name -> lnrpc.ChannelBackup - 200, // 165: lnrpc.RestoreChanBackupRequest.chan_backups:type_name -> lnrpc.ChannelBackups - 205, // 166: lnrpc.BakeMacaroonRequest.permissions:type_name -> lnrpc.MacaroonPermission - 205, // 167: lnrpc.MacaroonPermissionList.permissions:type_name -> lnrpc.MacaroonPermission - 254, // 168: lnrpc.ListPermissionsResponse.method_permissions:type_name -> lnrpc.ListPermissionsResponse.MethodPermissionsEntry - 21, // 169: lnrpc.Failure.code:type_name -> lnrpc.Failure.FailureCode - 216, // 170: lnrpc.Failure.channel_update:type_name -> lnrpc.ChannelUpdate - 218, // 171: lnrpc.MacaroonId.ops:type_name -> lnrpc.Op - 205, // 172: lnrpc.CheckMacPermRequest.permissions:type_name -> lnrpc.MacaroonPermission - 223, // 173: lnrpc.RPCMiddlewareRequest.stream_auth:type_name -> lnrpc.StreamAuth - 224, // 174: lnrpc.RPCMiddlewareRequest.request:type_name -> lnrpc.RPCMessage - 224, // 175: lnrpc.RPCMiddlewareRequest.response:type_name -> lnrpc.RPCMessage - 255, // 176: lnrpc.RPCMiddlewareRequest.metadata_pairs:type_name -> lnrpc.RPCMiddlewareRequest.MetadataPairsEntry - 226, // 177: lnrpc.RPCMiddlewareResponse.register:type_name -> lnrpc.MiddlewareRegistration - 227, // 178: lnrpc.RPCMiddlewareResponse.feedback:type_name -> lnrpc.InterceptFeedback - 184, // 179: lnrpc.Peer.FeaturesEntry.value:type_name -> lnrpc.Feature - 184, // 180: lnrpc.GetInfoResponse.FeaturesEntry.value:type_name -> lnrpc.Feature - 4, // 181: lnrpc.PendingChannelsResponse.PendingChannel.initiator:type_name -> lnrpc.Initiator - 3, // 182: lnrpc.PendingChannelsResponse.PendingChannel.commitment_type:type_name -> lnrpc.CommitmentType - 234, // 183: lnrpc.PendingChannelsResponse.PendingOpenChannel.channel:type_name -> lnrpc.PendingChannelsResponse.PendingChannel - 234, // 184: lnrpc.PendingChannelsResponse.WaitingCloseChannel.channel:type_name -> lnrpc.PendingChannelsResponse.PendingChannel - 237, // 185: lnrpc.PendingChannelsResponse.WaitingCloseChannel.commitments:type_name -> lnrpc.PendingChannelsResponse.Commitments - 234, // 186: lnrpc.PendingChannelsResponse.ClosedChannel.channel:type_name -> lnrpc.PendingChannelsResponse.PendingChannel - 234, // 187: lnrpc.PendingChannelsResponse.ForceClosedChannel.channel:type_name -> lnrpc.PendingChannelsResponse.PendingChannel - 110, // 188: lnrpc.PendingChannelsResponse.ForceClosedChannel.pending_htlcs:type_name -> lnrpc.PendingHTLC - 16, // 189: lnrpc.PendingChannelsResponse.ForceClosedChannel.anchor:type_name -> lnrpc.PendingChannelsResponse.ForceClosedChannel.AnchorState - 116, // 190: lnrpc.WalletBalanceResponse.AccountBalanceEntry.value:type_name -> lnrpc.WalletAccountBalance - 184, // 191: lnrpc.LightningNode.FeaturesEntry.value:type_name -> lnrpc.Feature - 141, // 192: lnrpc.NodeMetricsResponse.BetweennessCentralityEntry.value:type_name -> lnrpc.FloatMetric - 184, // 193: lnrpc.NodeUpdate.FeaturesEntry.value:type_name -> lnrpc.Feature - 184, // 194: lnrpc.Invoice.FeaturesEntry.value:type_name -> lnrpc.Feature - 158, // 195: lnrpc.Invoice.AmpInvoiceStateEntry.value:type_name -> lnrpc.AMPInvoiceState - 184, // 196: lnrpc.PayReq.FeaturesEntry.value:type_name -> lnrpc.Feature - 212, // 197: lnrpc.ListPermissionsResponse.MethodPermissionsEntry.value:type_name -> lnrpc.MacaroonPermissionList - 222, // 198: lnrpc.RPCMiddlewareRequest.MetadataPairsEntry.value:type_name -> lnrpc.MetadataValues - 117, // 199: lnrpc.Lightning.WalletBalance:input_type -> lnrpc.WalletBalanceRequest - 120, // 200: lnrpc.Lightning.ChannelBalance:input_type -> lnrpc.ChannelBalanceRequest - 35, // 201: lnrpc.Lightning.GetTransactions:input_type -> lnrpc.GetTransactionsRequest - 44, // 202: lnrpc.Lightning.EstimateFee:input_type -> lnrpc.EstimateFeeRequest - 48, // 203: lnrpc.Lightning.SendCoins:input_type -> lnrpc.SendCoinsRequest - 50, // 204: lnrpc.Lightning.ListUnspent:input_type -> lnrpc.ListUnspentRequest - 35, // 205: lnrpc.Lightning.SubscribeTransactions:input_type -> lnrpc.GetTransactionsRequest - 46, // 206: lnrpc.Lightning.SendMany:input_type -> lnrpc.SendManyRequest - 52, // 207: lnrpc.Lightning.NewAddress:input_type -> lnrpc.NewAddressRequest - 54, // 208: lnrpc.Lightning.SignMessage:input_type -> lnrpc.SignMessageRequest - 56, // 209: lnrpc.Lightning.VerifyMessage:input_type -> lnrpc.VerifyMessageRequest - 58, // 210: lnrpc.Lightning.ConnectPeer:input_type -> lnrpc.ConnectPeerRequest - 60, // 211: lnrpc.Lightning.DisconnectPeer:input_type -> lnrpc.DisconnectPeerRequest - 76, // 212: lnrpc.Lightning.ListPeers:input_type -> lnrpc.ListPeersRequest - 78, // 213: lnrpc.Lightning.SubscribePeerEvents:input_type -> lnrpc.PeerEventSubscription - 80, // 214: lnrpc.Lightning.GetInfo:input_type -> lnrpc.GetInfoRequest - 82, // 215: lnrpc.Lightning.GetDebugInfo:input_type -> lnrpc.GetDebugInfoRequest - 84, // 216: lnrpc.Lightning.GetRecoveryInfo:input_type -> lnrpc.GetRecoveryInfoRequest - 111, // 217: lnrpc.Lightning.PendingChannels:input_type -> lnrpc.PendingChannelsRequest - 65, // 218: lnrpc.Lightning.ListChannels:input_type -> lnrpc.ListChannelsRequest - 113, // 219: lnrpc.Lightning.SubscribeChannelEvents:input_type -> lnrpc.ChannelEventSubscription - 72, // 220: lnrpc.Lightning.ClosedChannels:input_type -> lnrpc.ClosedChannelsRequest - 98, // 221: lnrpc.Lightning.OpenChannelSync:input_type -> lnrpc.OpenChannelRequest - 98, // 222: lnrpc.Lightning.OpenChannel:input_type -> lnrpc.OpenChannelRequest - 95, // 223: lnrpc.Lightning.BatchOpenChannel:input_type -> lnrpc.BatchOpenChannelRequest - 108, // 224: lnrpc.Lightning.FundingStateStep:input_type -> lnrpc.FundingTransitionMsg - 39, // 225: lnrpc.Lightning.ChannelAcceptor:input_type -> lnrpc.ChannelAcceptResponse - 90, // 226: lnrpc.Lightning.CloseChannel:input_type -> lnrpc.CloseChannelRequest - 178, // 227: lnrpc.Lightning.AbandonChannel:input_type -> lnrpc.AbandonChannelRequest - 159, // 228: lnrpc.Lightning.AddInvoice:input_type -> lnrpc.Invoice - 165, // 229: lnrpc.Lightning.ListInvoices:input_type -> lnrpc.ListInvoiceRequest - 164, // 230: lnrpc.Lightning.LookupInvoice:input_type -> lnrpc.PaymentHash - 167, // 231: lnrpc.Lightning.SubscribeInvoices:input_type -> lnrpc.InvoiceSubscription - 168, // 232: lnrpc.Lightning.DeleteCanceledInvoice:input_type -> lnrpc.DelCanceledInvoiceReq - 182, // 233: lnrpc.Lightning.DecodePayReq:input_type -> lnrpc.PayReqString - 172, // 234: lnrpc.Lightning.ListPayments:input_type -> lnrpc.ListPaymentsRequest - 174, // 235: lnrpc.Lightning.DeletePayment:input_type -> lnrpc.DeletePaymentRequest - 175, // 236: lnrpc.Lightning.DeleteAllPayments:input_type -> lnrpc.DeleteAllPaymentsRequest - 137, // 237: lnrpc.Lightning.DescribeGraph:input_type -> lnrpc.ChannelGraphRequest - 139, // 238: lnrpc.Lightning.GetNodeMetrics:input_type -> lnrpc.NodeMetricsRequest - 142, // 239: lnrpc.Lightning.GetChanInfo:input_type -> lnrpc.ChanInfoRequest - 130, // 240: lnrpc.Lightning.GetNodeInfo:input_type -> lnrpc.NodeInfoRequest - 122, // 241: lnrpc.Lightning.QueryRoutes:input_type -> lnrpc.QueryRoutesRequest - 143, // 242: lnrpc.Lightning.GetNetworkInfo:input_type -> lnrpc.NetworkInfoRequest - 145, // 243: lnrpc.Lightning.StopDaemon:input_type -> lnrpc.StopRequest - 147, // 244: lnrpc.Lightning.SubscribeChannelGraph:input_type -> lnrpc.GraphTopologySubscription - 180, // 245: lnrpc.Lightning.DebugLevel:input_type -> lnrpc.DebugLevelRequest - 185, // 246: lnrpc.Lightning.FeeReport:input_type -> lnrpc.FeeReportRequest - 189, // 247: lnrpc.Lightning.UpdateChannelPolicy:input_type -> lnrpc.PolicyUpdateRequest - 192, // 248: lnrpc.Lightning.ForwardingHistory:input_type -> lnrpc.ForwardingHistoryRequest - 195, // 249: lnrpc.Lightning.ExportChannelBackup:input_type -> lnrpc.ExportChannelBackupRequest - 198, // 250: lnrpc.Lightning.ExportAllChannelBackups:input_type -> lnrpc.ChanBackupExportRequest - 199, // 251: lnrpc.Lightning.VerifyChanBackup:input_type -> lnrpc.ChanBackupSnapshot - 201, // 252: lnrpc.Lightning.RestoreChannelBackups:input_type -> lnrpc.RestoreChanBackupRequest - 203, // 253: lnrpc.Lightning.SubscribeChannelBackups:input_type -> lnrpc.ChannelBackupSubscription - 206, // 254: lnrpc.Lightning.BakeMacaroon:input_type -> lnrpc.BakeMacaroonRequest - 208, // 255: lnrpc.Lightning.ListMacaroonIDs:input_type -> lnrpc.ListMacaroonIDsRequest - 210, // 256: lnrpc.Lightning.DeleteMacaroonID:input_type -> lnrpc.DeleteMacaroonIDRequest - 213, // 257: lnrpc.Lightning.ListPermissions:input_type -> lnrpc.ListPermissionsRequest - 219, // 258: lnrpc.Lightning.CheckMacaroonPermissions:input_type -> lnrpc.CheckMacPermRequest - 225, // 259: lnrpc.Lightning.RegisterRPCMiddleware:input_type -> lnrpc.RPCMiddlewareResponse - 26, // 260: lnrpc.Lightning.SendCustomMessage:input_type -> lnrpc.SendCustomMessageRequest - 24, // 261: lnrpc.Lightning.SubscribeCustomMessages:input_type -> lnrpc.SubscribeCustomMessagesRequest - 30, // 262: lnrpc.Lightning.SendOnionMessage:input_type -> lnrpc.SendOnionMessageRequest - 28, // 263: lnrpc.Lightning.SubscribeOnionMessages:input_type -> lnrpc.SubscribeOnionMessagesRequest - 68, // 264: lnrpc.Lightning.ListAliases:input_type -> lnrpc.ListAliasesRequest - 22, // 265: lnrpc.Lightning.LookupHtlcResolution:input_type -> lnrpc.LookupHtlcResolutionRequest - 118, // 266: lnrpc.Lightning.WalletBalance:output_type -> lnrpc.WalletBalanceResponse - 121, // 267: lnrpc.Lightning.ChannelBalance:output_type -> lnrpc.ChannelBalanceResponse - 36, // 268: lnrpc.Lightning.GetTransactions:output_type -> lnrpc.TransactionDetails - 45, // 269: lnrpc.Lightning.EstimateFee:output_type -> lnrpc.EstimateFeeResponse - 49, // 270: lnrpc.Lightning.SendCoins:output_type -> lnrpc.SendCoinsResponse - 51, // 271: lnrpc.Lightning.ListUnspent:output_type -> lnrpc.ListUnspentResponse - 34, // 272: lnrpc.Lightning.SubscribeTransactions:output_type -> lnrpc.Transaction - 47, // 273: lnrpc.Lightning.SendMany:output_type -> lnrpc.SendManyResponse - 53, // 274: lnrpc.Lightning.NewAddress:output_type -> lnrpc.NewAddressResponse - 55, // 275: lnrpc.Lightning.SignMessage:output_type -> lnrpc.SignMessageResponse - 57, // 276: lnrpc.Lightning.VerifyMessage:output_type -> lnrpc.VerifyMessageResponse - 59, // 277: lnrpc.Lightning.ConnectPeer:output_type -> lnrpc.ConnectPeerResponse - 61, // 278: lnrpc.Lightning.DisconnectPeer:output_type -> lnrpc.DisconnectPeerResponse - 77, // 279: lnrpc.Lightning.ListPeers:output_type -> lnrpc.ListPeersResponse - 79, // 280: lnrpc.Lightning.SubscribePeerEvents:output_type -> lnrpc.PeerEvent - 81, // 281: lnrpc.Lightning.GetInfo:output_type -> lnrpc.GetInfoResponse - 83, // 282: lnrpc.Lightning.GetDebugInfo:output_type -> lnrpc.GetDebugInfoResponse - 85, // 283: lnrpc.Lightning.GetRecoveryInfo:output_type -> lnrpc.GetRecoveryInfoResponse - 112, // 284: lnrpc.Lightning.PendingChannels:output_type -> lnrpc.PendingChannelsResponse - 66, // 285: lnrpc.Lightning.ListChannels:output_type -> lnrpc.ListChannelsResponse - 115, // 286: lnrpc.Lightning.SubscribeChannelEvents:output_type -> lnrpc.ChannelEventUpdate - 73, // 287: lnrpc.Lightning.ClosedChannels:output_type -> lnrpc.ClosedChannelsResponse - 40, // 288: lnrpc.Lightning.OpenChannelSync:output_type -> lnrpc.ChannelPoint - 99, // 289: lnrpc.Lightning.OpenChannel:output_type -> lnrpc.OpenStatusUpdate - 97, // 290: lnrpc.Lightning.BatchOpenChannel:output_type -> lnrpc.BatchOpenChannelResponse - 109, // 291: lnrpc.Lightning.FundingStateStep:output_type -> lnrpc.FundingStateStepResp - 38, // 292: lnrpc.Lightning.ChannelAcceptor:output_type -> lnrpc.ChannelAcceptRequest - 91, // 293: lnrpc.Lightning.CloseChannel:output_type -> lnrpc.CloseStatusUpdate - 179, // 294: lnrpc.Lightning.AbandonChannel:output_type -> lnrpc.AbandonChannelResponse - 163, // 295: lnrpc.Lightning.AddInvoice:output_type -> lnrpc.AddInvoiceResponse - 166, // 296: lnrpc.Lightning.ListInvoices:output_type -> lnrpc.ListInvoiceResponse - 159, // 297: lnrpc.Lightning.LookupInvoice:output_type -> lnrpc.Invoice - 159, // 298: lnrpc.Lightning.SubscribeInvoices:output_type -> lnrpc.Invoice - 169, // 299: lnrpc.Lightning.DeleteCanceledInvoice:output_type -> lnrpc.DelCanceledInvoiceResp - 183, // 300: lnrpc.Lightning.DecodePayReq:output_type -> lnrpc.PayReq - 173, // 301: lnrpc.Lightning.ListPayments:output_type -> lnrpc.ListPaymentsResponse - 176, // 302: lnrpc.Lightning.DeletePayment:output_type -> lnrpc.DeletePaymentResponse - 177, // 303: lnrpc.Lightning.DeleteAllPayments:output_type -> lnrpc.DeleteAllPaymentsResponse - 138, // 304: lnrpc.Lightning.DescribeGraph:output_type -> lnrpc.ChannelGraph - 140, // 305: lnrpc.Lightning.GetNodeMetrics:output_type -> lnrpc.NodeMetricsResponse - 136, // 306: lnrpc.Lightning.GetChanInfo:output_type -> lnrpc.ChannelEdge - 131, // 307: lnrpc.Lightning.GetNodeInfo:output_type -> lnrpc.NodeInfo - 125, // 308: lnrpc.Lightning.QueryRoutes:output_type -> lnrpc.QueryRoutesResponse - 144, // 309: lnrpc.Lightning.GetNetworkInfo:output_type -> lnrpc.NetworkInfo - 146, // 310: lnrpc.Lightning.StopDaemon:output_type -> lnrpc.StopResponse - 148, // 311: lnrpc.Lightning.SubscribeChannelGraph:output_type -> lnrpc.GraphTopologyUpdate - 181, // 312: lnrpc.Lightning.DebugLevel:output_type -> lnrpc.DebugLevelResponse - 187, // 313: lnrpc.Lightning.FeeReport:output_type -> lnrpc.FeeReportResponse - 191, // 314: lnrpc.Lightning.UpdateChannelPolicy:output_type -> lnrpc.PolicyUpdateResponse - 194, // 315: lnrpc.Lightning.ForwardingHistory:output_type -> lnrpc.ForwardingHistoryResponse - 196, // 316: lnrpc.Lightning.ExportChannelBackup:output_type -> lnrpc.ChannelBackup - 199, // 317: lnrpc.Lightning.ExportAllChannelBackups:output_type -> lnrpc.ChanBackupSnapshot - 204, // 318: lnrpc.Lightning.VerifyChanBackup:output_type -> lnrpc.VerifyChanBackupResponse - 202, // 319: lnrpc.Lightning.RestoreChannelBackups:output_type -> lnrpc.RestoreBackupResponse - 199, // 320: lnrpc.Lightning.SubscribeChannelBackups:output_type -> lnrpc.ChanBackupSnapshot - 207, // 321: lnrpc.Lightning.BakeMacaroon:output_type -> lnrpc.BakeMacaroonResponse - 209, // 322: lnrpc.Lightning.ListMacaroonIDs:output_type -> lnrpc.ListMacaroonIDsResponse - 211, // 323: lnrpc.Lightning.DeleteMacaroonID:output_type -> lnrpc.DeleteMacaroonIDResponse - 214, // 324: lnrpc.Lightning.ListPermissions:output_type -> lnrpc.ListPermissionsResponse - 220, // 325: lnrpc.Lightning.CheckMacaroonPermissions:output_type -> lnrpc.CheckMacPermResponse - 221, // 326: lnrpc.Lightning.RegisterRPCMiddleware:output_type -> lnrpc.RPCMiddlewareRequest - 27, // 327: lnrpc.Lightning.SendCustomMessage:output_type -> lnrpc.SendCustomMessageResponse - 25, // 328: lnrpc.Lightning.SubscribeCustomMessages:output_type -> lnrpc.CustomMessage - 31, // 329: lnrpc.Lightning.SendOnionMessage:output_type -> lnrpc.SendOnionMessageResponse - 29, // 330: lnrpc.Lightning.SubscribeOnionMessages:output_type -> lnrpc.OnionMessageUpdate - 69, // 331: lnrpc.Lightning.ListAliases:output_type -> lnrpc.ListAliasesResponse - 23, // 332: lnrpc.Lightning.LookupHtlcResolution:output_type -> lnrpc.LookupHtlcResolutionResponse - 266, // [266:333] is the sub-list for method output_type - 199, // [199:266] is the sub-list for method input_type - 199, // [199:199] is the sub-list for extension type_name - 199, // [199:199] is the sub-list for extension extendee - 0, // [0:199] is the sub-list for field type_name + 128, // 98: lnrpc.QueryRoutesRequest.amp_record:type_name -> lnrpc.AMPRecord + 129, // 99: lnrpc.QueryRoutesResponse.routes:type_name -> lnrpc.Route + 127, // 100: lnrpc.Hop.mpp_record:type_name -> lnrpc.MPPRecord + 128, // 101: lnrpc.Hop.amp_record:type_name -> lnrpc.AMPRecord + 242, // 102: lnrpc.Hop.custom_records:type_name -> lnrpc.Hop.CustomRecordsEntry + 126, // 103: lnrpc.Route.hops:type_name -> lnrpc.Hop + 132, // 104: lnrpc.NodeInfo.node:type_name -> lnrpc.LightningNode + 136, // 105: lnrpc.NodeInfo.channels:type_name -> lnrpc.ChannelEdge + 133, // 106: lnrpc.LightningNode.addresses:type_name -> lnrpc.NodeAddress + 243, // 107: lnrpc.LightningNode.features:type_name -> lnrpc.LightningNode.FeaturesEntry + 244, // 108: lnrpc.LightningNode.custom_records:type_name -> lnrpc.LightningNode.CustomRecordsEntry + 245, // 109: lnrpc.RoutingPolicy.custom_records:type_name -> lnrpc.RoutingPolicy.CustomRecordsEntry + 134, // 110: lnrpc.ChannelEdge.node1_policy:type_name -> lnrpc.RoutingPolicy + 134, // 111: lnrpc.ChannelEdge.node2_policy:type_name -> lnrpc.RoutingPolicy + 246, // 112: lnrpc.ChannelEdge.custom_records:type_name -> lnrpc.ChannelEdge.CustomRecordsEntry + 135, // 113: lnrpc.ChannelEdge.auth_proof:type_name -> lnrpc.ChannelAuthProof + 132, // 114: lnrpc.ChannelGraph.nodes:type_name -> lnrpc.LightningNode + 136, // 115: lnrpc.ChannelGraph.edges:type_name -> lnrpc.ChannelEdge + 8, // 116: lnrpc.NodeMetricsRequest.types:type_name -> lnrpc.NodeMetricType + 247, // 117: lnrpc.NodeMetricsResponse.betweenness_centrality:type_name -> lnrpc.NodeMetricsResponse.BetweennessCentralityEntry + 149, // 118: lnrpc.GraphTopologyUpdate.node_updates:type_name -> lnrpc.NodeUpdate + 150, // 119: lnrpc.GraphTopologyUpdate.channel_updates:type_name -> lnrpc.ChannelEdgeUpdate + 151, // 120: lnrpc.GraphTopologyUpdate.closed_chans:type_name -> lnrpc.ClosedChannelUpdate + 133, // 121: lnrpc.NodeUpdate.node_addresses:type_name -> lnrpc.NodeAddress + 248, // 122: lnrpc.NodeUpdate.features:type_name -> lnrpc.NodeUpdate.FeaturesEntry + 40, // 123: lnrpc.ChannelEdgeUpdate.chan_point:type_name -> lnrpc.ChannelPoint + 134, // 124: lnrpc.ChannelEdgeUpdate.routing_policy:type_name -> lnrpc.RoutingPolicy + 40, // 125: lnrpc.ClosedChannelUpdate.chan_point:type_name -> lnrpc.ChannelPoint + 152, // 126: lnrpc.RouteHint.hop_hints:type_name -> lnrpc.HopHint + 156, // 127: lnrpc.BlindedPaymentPath.blinded_path:type_name -> lnrpc.BlindedPath + 11, // 128: lnrpc.BlindedPaymentPath.features:type_name -> lnrpc.FeatureBit + 157, // 129: lnrpc.BlindedPath.blinded_hops:type_name -> lnrpc.BlindedHop + 9, // 130: lnrpc.AMPInvoiceState.state:type_name -> lnrpc.InvoiceHTLCState + 154, // 131: lnrpc.Invoice.route_hints:type_name -> lnrpc.RouteHint + 18, // 132: lnrpc.Invoice.state:type_name -> lnrpc.Invoice.InvoiceState + 161, // 133: lnrpc.Invoice.htlcs:type_name -> lnrpc.InvoiceHTLC + 249, // 134: lnrpc.Invoice.features:type_name -> lnrpc.Invoice.FeaturesEntry + 250, // 135: lnrpc.Invoice.amp_invoice_state:type_name -> lnrpc.Invoice.AmpInvoiceStateEntry + 160, // 136: lnrpc.Invoice.blinded_path_config:type_name -> lnrpc.BlindedPathConfig + 9, // 137: lnrpc.InvoiceHTLC.state:type_name -> lnrpc.InvoiceHTLCState + 251, // 138: lnrpc.InvoiceHTLC.custom_records:type_name -> lnrpc.InvoiceHTLC.CustomRecordsEntry + 162, // 139: lnrpc.InvoiceHTLC.amp:type_name -> lnrpc.AMP + 159, // 140: lnrpc.ListInvoiceResponse.invoices:type_name -> lnrpc.Invoice + 19, // 141: lnrpc.Payment.status:type_name -> lnrpc.Payment.PaymentStatus + 171, // 142: lnrpc.Payment.htlcs:type_name -> lnrpc.HTLCAttempt + 10, // 143: lnrpc.Payment.failure_reason:type_name -> lnrpc.PaymentFailureReason + 252, // 144: lnrpc.Payment.first_hop_custom_records:type_name -> lnrpc.Payment.FirstHopCustomRecordsEntry + 20, // 145: lnrpc.HTLCAttempt.status:type_name -> lnrpc.HTLCAttempt.HTLCStatus + 129, // 146: lnrpc.HTLCAttempt.route:type_name -> lnrpc.Route + 215, // 147: lnrpc.HTLCAttempt.failure:type_name -> lnrpc.Failure + 170, // 148: lnrpc.ListPaymentsResponse.payments:type_name -> lnrpc.Payment + 40, // 149: lnrpc.AbandonChannelRequest.channel_point:type_name -> lnrpc.ChannelPoint + 154, // 150: lnrpc.PayReq.route_hints:type_name -> lnrpc.RouteHint + 253, // 151: lnrpc.PayReq.features:type_name -> lnrpc.PayReq.FeaturesEntry + 155, // 152: lnrpc.PayReq.blinded_paths:type_name -> lnrpc.BlindedPaymentPath + 186, // 153: lnrpc.FeeReportResponse.channel_fees:type_name -> lnrpc.ChannelFeeReport + 40, // 154: lnrpc.PolicyUpdateRequest.chan_point:type_name -> lnrpc.ChannelPoint + 188, // 155: lnrpc.PolicyUpdateRequest.inbound_fee:type_name -> lnrpc.InboundFee + 41, // 156: lnrpc.FailedUpdate.outpoint:type_name -> lnrpc.OutPoint + 12, // 157: lnrpc.FailedUpdate.reason:type_name -> lnrpc.UpdateFailure + 190, // 158: lnrpc.PolicyUpdateResponse.failed_updates:type_name -> lnrpc.FailedUpdate + 193, // 159: lnrpc.ForwardingHistoryResponse.forwarding_events:type_name -> lnrpc.ForwardingEvent + 40, // 160: lnrpc.ExportChannelBackupRequest.chan_point:type_name -> lnrpc.ChannelPoint + 40, // 161: lnrpc.ChannelBackup.chan_point:type_name -> lnrpc.ChannelPoint + 40, // 162: lnrpc.MultiChanBackup.chan_points:type_name -> lnrpc.ChannelPoint + 200, // 163: lnrpc.ChanBackupSnapshot.single_chan_backups:type_name -> lnrpc.ChannelBackups + 197, // 164: lnrpc.ChanBackupSnapshot.multi_chan_backup:type_name -> lnrpc.MultiChanBackup + 196, // 165: lnrpc.ChannelBackups.chan_backups:type_name -> lnrpc.ChannelBackup + 200, // 166: lnrpc.RestoreChanBackupRequest.chan_backups:type_name -> lnrpc.ChannelBackups + 205, // 167: lnrpc.BakeMacaroonRequest.permissions:type_name -> lnrpc.MacaroonPermission + 205, // 168: lnrpc.MacaroonPermissionList.permissions:type_name -> lnrpc.MacaroonPermission + 254, // 169: lnrpc.ListPermissionsResponse.method_permissions:type_name -> lnrpc.ListPermissionsResponse.MethodPermissionsEntry + 21, // 170: lnrpc.Failure.code:type_name -> lnrpc.Failure.FailureCode + 216, // 171: lnrpc.Failure.channel_update:type_name -> lnrpc.ChannelUpdate + 218, // 172: lnrpc.MacaroonId.ops:type_name -> lnrpc.Op + 205, // 173: lnrpc.CheckMacPermRequest.permissions:type_name -> lnrpc.MacaroonPermission + 223, // 174: lnrpc.RPCMiddlewareRequest.stream_auth:type_name -> lnrpc.StreamAuth + 224, // 175: lnrpc.RPCMiddlewareRequest.request:type_name -> lnrpc.RPCMessage + 224, // 176: lnrpc.RPCMiddlewareRequest.response:type_name -> lnrpc.RPCMessage + 255, // 177: lnrpc.RPCMiddlewareRequest.metadata_pairs:type_name -> lnrpc.RPCMiddlewareRequest.MetadataPairsEntry + 226, // 178: lnrpc.RPCMiddlewareResponse.register:type_name -> lnrpc.MiddlewareRegistration + 227, // 179: lnrpc.RPCMiddlewareResponse.feedback:type_name -> lnrpc.InterceptFeedback + 184, // 180: lnrpc.Peer.FeaturesEntry.value:type_name -> lnrpc.Feature + 184, // 181: lnrpc.GetInfoResponse.FeaturesEntry.value:type_name -> lnrpc.Feature + 4, // 182: lnrpc.PendingChannelsResponse.PendingChannel.initiator:type_name -> lnrpc.Initiator + 3, // 183: lnrpc.PendingChannelsResponse.PendingChannel.commitment_type:type_name -> lnrpc.CommitmentType + 234, // 184: lnrpc.PendingChannelsResponse.PendingOpenChannel.channel:type_name -> lnrpc.PendingChannelsResponse.PendingChannel + 234, // 185: lnrpc.PendingChannelsResponse.WaitingCloseChannel.channel:type_name -> lnrpc.PendingChannelsResponse.PendingChannel + 237, // 186: lnrpc.PendingChannelsResponse.WaitingCloseChannel.commitments:type_name -> lnrpc.PendingChannelsResponse.Commitments + 234, // 187: lnrpc.PendingChannelsResponse.ClosedChannel.channel:type_name -> lnrpc.PendingChannelsResponse.PendingChannel + 234, // 188: lnrpc.PendingChannelsResponse.ForceClosedChannel.channel:type_name -> lnrpc.PendingChannelsResponse.PendingChannel + 110, // 189: lnrpc.PendingChannelsResponse.ForceClosedChannel.pending_htlcs:type_name -> lnrpc.PendingHTLC + 16, // 190: lnrpc.PendingChannelsResponse.ForceClosedChannel.anchor:type_name -> lnrpc.PendingChannelsResponse.ForceClosedChannel.AnchorState + 116, // 191: lnrpc.WalletBalanceResponse.AccountBalanceEntry.value:type_name -> lnrpc.WalletAccountBalance + 184, // 192: lnrpc.LightningNode.FeaturesEntry.value:type_name -> lnrpc.Feature + 141, // 193: lnrpc.NodeMetricsResponse.BetweennessCentralityEntry.value:type_name -> lnrpc.FloatMetric + 184, // 194: lnrpc.NodeUpdate.FeaturesEntry.value:type_name -> lnrpc.Feature + 184, // 195: lnrpc.Invoice.FeaturesEntry.value:type_name -> lnrpc.Feature + 158, // 196: lnrpc.Invoice.AmpInvoiceStateEntry.value:type_name -> lnrpc.AMPInvoiceState + 184, // 197: lnrpc.PayReq.FeaturesEntry.value:type_name -> lnrpc.Feature + 212, // 198: lnrpc.ListPermissionsResponse.MethodPermissionsEntry.value:type_name -> lnrpc.MacaroonPermissionList + 222, // 199: lnrpc.RPCMiddlewareRequest.MetadataPairsEntry.value:type_name -> lnrpc.MetadataValues + 117, // 200: lnrpc.Lightning.WalletBalance:input_type -> lnrpc.WalletBalanceRequest + 120, // 201: lnrpc.Lightning.ChannelBalance:input_type -> lnrpc.ChannelBalanceRequest + 35, // 202: lnrpc.Lightning.GetTransactions:input_type -> lnrpc.GetTransactionsRequest + 44, // 203: lnrpc.Lightning.EstimateFee:input_type -> lnrpc.EstimateFeeRequest + 48, // 204: lnrpc.Lightning.SendCoins:input_type -> lnrpc.SendCoinsRequest + 50, // 205: lnrpc.Lightning.ListUnspent:input_type -> lnrpc.ListUnspentRequest + 35, // 206: lnrpc.Lightning.SubscribeTransactions:input_type -> lnrpc.GetTransactionsRequest + 46, // 207: lnrpc.Lightning.SendMany:input_type -> lnrpc.SendManyRequest + 52, // 208: lnrpc.Lightning.NewAddress:input_type -> lnrpc.NewAddressRequest + 54, // 209: lnrpc.Lightning.SignMessage:input_type -> lnrpc.SignMessageRequest + 56, // 210: lnrpc.Lightning.VerifyMessage:input_type -> lnrpc.VerifyMessageRequest + 58, // 211: lnrpc.Lightning.ConnectPeer:input_type -> lnrpc.ConnectPeerRequest + 60, // 212: lnrpc.Lightning.DisconnectPeer:input_type -> lnrpc.DisconnectPeerRequest + 76, // 213: lnrpc.Lightning.ListPeers:input_type -> lnrpc.ListPeersRequest + 78, // 214: lnrpc.Lightning.SubscribePeerEvents:input_type -> lnrpc.PeerEventSubscription + 80, // 215: lnrpc.Lightning.GetInfo:input_type -> lnrpc.GetInfoRequest + 82, // 216: lnrpc.Lightning.GetDebugInfo:input_type -> lnrpc.GetDebugInfoRequest + 84, // 217: lnrpc.Lightning.GetRecoveryInfo:input_type -> lnrpc.GetRecoveryInfoRequest + 111, // 218: lnrpc.Lightning.PendingChannels:input_type -> lnrpc.PendingChannelsRequest + 65, // 219: lnrpc.Lightning.ListChannels:input_type -> lnrpc.ListChannelsRequest + 113, // 220: lnrpc.Lightning.SubscribeChannelEvents:input_type -> lnrpc.ChannelEventSubscription + 72, // 221: lnrpc.Lightning.ClosedChannels:input_type -> lnrpc.ClosedChannelsRequest + 98, // 222: lnrpc.Lightning.OpenChannelSync:input_type -> lnrpc.OpenChannelRequest + 98, // 223: lnrpc.Lightning.OpenChannel:input_type -> lnrpc.OpenChannelRequest + 95, // 224: lnrpc.Lightning.BatchOpenChannel:input_type -> lnrpc.BatchOpenChannelRequest + 108, // 225: lnrpc.Lightning.FundingStateStep:input_type -> lnrpc.FundingTransitionMsg + 39, // 226: lnrpc.Lightning.ChannelAcceptor:input_type -> lnrpc.ChannelAcceptResponse + 90, // 227: lnrpc.Lightning.CloseChannel:input_type -> lnrpc.CloseChannelRequest + 178, // 228: lnrpc.Lightning.AbandonChannel:input_type -> lnrpc.AbandonChannelRequest + 159, // 229: lnrpc.Lightning.AddInvoice:input_type -> lnrpc.Invoice + 165, // 230: lnrpc.Lightning.ListInvoices:input_type -> lnrpc.ListInvoiceRequest + 164, // 231: lnrpc.Lightning.LookupInvoice:input_type -> lnrpc.PaymentHash + 167, // 232: lnrpc.Lightning.SubscribeInvoices:input_type -> lnrpc.InvoiceSubscription + 168, // 233: lnrpc.Lightning.DeleteCanceledInvoice:input_type -> lnrpc.DelCanceledInvoiceReq + 182, // 234: lnrpc.Lightning.DecodePayReq:input_type -> lnrpc.PayReqString + 172, // 235: lnrpc.Lightning.ListPayments:input_type -> lnrpc.ListPaymentsRequest + 174, // 236: lnrpc.Lightning.DeletePayment:input_type -> lnrpc.DeletePaymentRequest + 175, // 237: lnrpc.Lightning.DeleteAllPayments:input_type -> lnrpc.DeleteAllPaymentsRequest + 137, // 238: lnrpc.Lightning.DescribeGraph:input_type -> lnrpc.ChannelGraphRequest + 139, // 239: lnrpc.Lightning.GetNodeMetrics:input_type -> lnrpc.NodeMetricsRequest + 142, // 240: lnrpc.Lightning.GetChanInfo:input_type -> lnrpc.ChanInfoRequest + 130, // 241: lnrpc.Lightning.GetNodeInfo:input_type -> lnrpc.NodeInfoRequest + 122, // 242: lnrpc.Lightning.QueryRoutes:input_type -> lnrpc.QueryRoutesRequest + 143, // 243: lnrpc.Lightning.GetNetworkInfo:input_type -> lnrpc.NetworkInfoRequest + 145, // 244: lnrpc.Lightning.StopDaemon:input_type -> lnrpc.StopRequest + 147, // 245: lnrpc.Lightning.SubscribeChannelGraph:input_type -> lnrpc.GraphTopologySubscription + 180, // 246: lnrpc.Lightning.DebugLevel:input_type -> lnrpc.DebugLevelRequest + 185, // 247: lnrpc.Lightning.FeeReport:input_type -> lnrpc.FeeReportRequest + 189, // 248: lnrpc.Lightning.UpdateChannelPolicy:input_type -> lnrpc.PolicyUpdateRequest + 192, // 249: lnrpc.Lightning.ForwardingHistory:input_type -> lnrpc.ForwardingHistoryRequest + 195, // 250: lnrpc.Lightning.ExportChannelBackup:input_type -> lnrpc.ExportChannelBackupRequest + 198, // 251: lnrpc.Lightning.ExportAllChannelBackups:input_type -> lnrpc.ChanBackupExportRequest + 199, // 252: lnrpc.Lightning.VerifyChanBackup:input_type -> lnrpc.ChanBackupSnapshot + 201, // 253: lnrpc.Lightning.RestoreChannelBackups:input_type -> lnrpc.RestoreChanBackupRequest + 203, // 254: lnrpc.Lightning.SubscribeChannelBackups:input_type -> lnrpc.ChannelBackupSubscription + 206, // 255: lnrpc.Lightning.BakeMacaroon:input_type -> lnrpc.BakeMacaroonRequest + 208, // 256: lnrpc.Lightning.ListMacaroonIDs:input_type -> lnrpc.ListMacaroonIDsRequest + 210, // 257: lnrpc.Lightning.DeleteMacaroonID:input_type -> lnrpc.DeleteMacaroonIDRequest + 213, // 258: lnrpc.Lightning.ListPermissions:input_type -> lnrpc.ListPermissionsRequest + 219, // 259: lnrpc.Lightning.CheckMacaroonPermissions:input_type -> lnrpc.CheckMacPermRequest + 225, // 260: lnrpc.Lightning.RegisterRPCMiddleware:input_type -> lnrpc.RPCMiddlewareResponse + 26, // 261: lnrpc.Lightning.SendCustomMessage:input_type -> lnrpc.SendCustomMessageRequest + 24, // 262: lnrpc.Lightning.SubscribeCustomMessages:input_type -> lnrpc.SubscribeCustomMessagesRequest + 30, // 263: lnrpc.Lightning.SendOnionMessage:input_type -> lnrpc.SendOnionMessageRequest + 28, // 264: lnrpc.Lightning.SubscribeOnionMessages:input_type -> lnrpc.SubscribeOnionMessagesRequest + 68, // 265: lnrpc.Lightning.ListAliases:input_type -> lnrpc.ListAliasesRequest + 22, // 266: lnrpc.Lightning.LookupHtlcResolution:input_type -> lnrpc.LookupHtlcResolutionRequest + 118, // 267: lnrpc.Lightning.WalletBalance:output_type -> lnrpc.WalletBalanceResponse + 121, // 268: lnrpc.Lightning.ChannelBalance:output_type -> lnrpc.ChannelBalanceResponse + 36, // 269: lnrpc.Lightning.GetTransactions:output_type -> lnrpc.TransactionDetails + 45, // 270: lnrpc.Lightning.EstimateFee:output_type -> lnrpc.EstimateFeeResponse + 49, // 271: lnrpc.Lightning.SendCoins:output_type -> lnrpc.SendCoinsResponse + 51, // 272: lnrpc.Lightning.ListUnspent:output_type -> lnrpc.ListUnspentResponse + 34, // 273: lnrpc.Lightning.SubscribeTransactions:output_type -> lnrpc.Transaction + 47, // 274: lnrpc.Lightning.SendMany:output_type -> lnrpc.SendManyResponse + 53, // 275: lnrpc.Lightning.NewAddress:output_type -> lnrpc.NewAddressResponse + 55, // 276: lnrpc.Lightning.SignMessage:output_type -> lnrpc.SignMessageResponse + 57, // 277: lnrpc.Lightning.VerifyMessage:output_type -> lnrpc.VerifyMessageResponse + 59, // 278: lnrpc.Lightning.ConnectPeer:output_type -> lnrpc.ConnectPeerResponse + 61, // 279: lnrpc.Lightning.DisconnectPeer:output_type -> lnrpc.DisconnectPeerResponse + 77, // 280: lnrpc.Lightning.ListPeers:output_type -> lnrpc.ListPeersResponse + 79, // 281: lnrpc.Lightning.SubscribePeerEvents:output_type -> lnrpc.PeerEvent + 81, // 282: lnrpc.Lightning.GetInfo:output_type -> lnrpc.GetInfoResponse + 83, // 283: lnrpc.Lightning.GetDebugInfo:output_type -> lnrpc.GetDebugInfoResponse + 85, // 284: lnrpc.Lightning.GetRecoveryInfo:output_type -> lnrpc.GetRecoveryInfoResponse + 112, // 285: lnrpc.Lightning.PendingChannels:output_type -> lnrpc.PendingChannelsResponse + 66, // 286: lnrpc.Lightning.ListChannels:output_type -> lnrpc.ListChannelsResponse + 115, // 287: lnrpc.Lightning.SubscribeChannelEvents:output_type -> lnrpc.ChannelEventUpdate + 73, // 288: lnrpc.Lightning.ClosedChannels:output_type -> lnrpc.ClosedChannelsResponse + 40, // 289: lnrpc.Lightning.OpenChannelSync:output_type -> lnrpc.ChannelPoint + 99, // 290: lnrpc.Lightning.OpenChannel:output_type -> lnrpc.OpenStatusUpdate + 97, // 291: lnrpc.Lightning.BatchOpenChannel:output_type -> lnrpc.BatchOpenChannelResponse + 109, // 292: lnrpc.Lightning.FundingStateStep:output_type -> lnrpc.FundingStateStepResp + 38, // 293: lnrpc.Lightning.ChannelAcceptor:output_type -> lnrpc.ChannelAcceptRequest + 91, // 294: lnrpc.Lightning.CloseChannel:output_type -> lnrpc.CloseStatusUpdate + 179, // 295: lnrpc.Lightning.AbandonChannel:output_type -> lnrpc.AbandonChannelResponse + 163, // 296: lnrpc.Lightning.AddInvoice:output_type -> lnrpc.AddInvoiceResponse + 166, // 297: lnrpc.Lightning.ListInvoices:output_type -> lnrpc.ListInvoiceResponse + 159, // 298: lnrpc.Lightning.LookupInvoice:output_type -> lnrpc.Invoice + 159, // 299: lnrpc.Lightning.SubscribeInvoices:output_type -> lnrpc.Invoice + 169, // 300: lnrpc.Lightning.DeleteCanceledInvoice:output_type -> lnrpc.DelCanceledInvoiceResp + 183, // 301: lnrpc.Lightning.DecodePayReq:output_type -> lnrpc.PayReq + 173, // 302: lnrpc.Lightning.ListPayments:output_type -> lnrpc.ListPaymentsResponse + 176, // 303: lnrpc.Lightning.DeletePayment:output_type -> lnrpc.DeletePaymentResponse + 177, // 304: lnrpc.Lightning.DeleteAllPayments:output_type -> lnrpc.DeleteAllPaymentsResponse + 138, // 305: lnrpc.Lightning.DescribeGraph:output_type -> lnrpc.ChannelGraph + 140, // 306: lnrpc.Lightning.GetNodeMetrics:output_type -> lnrpc.NodeMetricsResponse + 136, // 307: lnrpc.Lightning.GetChanInfo:output_type -> lnrpc.ChannelEdge + 131, // 308: lnrpc.Lightning.GetNodeInfo:output_type -> lnrpc.NodeInfo + 125, // 309: lnrpc.Lightning.QueryRoutes:output_type -> lnrpc.QueryRoutesResponse + 144, // 310: lnrpc.Lightning.GetNetworkInfo:output_type -> lnrpc.NetworkInfo + 146, // 311: lnrpc.Lightning.StopDaemon:output_type -> lnrpc.StopResponse + 148, // 312: lnrpc.Lightning.SubscribeChannelGraph:output_type -> lnrpc.GraphTopologyUpdate + 181, // 313: lnrpc.Lightning.DebugLevel:output_type -> lnrpc.DebugLevelResponse + 187, // 314: lnrpc.Lightning.FeeReport:output_type -> lnrpc.FeeReportResponse + 191, // 315: lnrpc.Lightning.UpdateChannelPolicy:output_type -> lnrpc.PolicyUpdateResponse + 194, // 316: lnrpc.Lightning.ForwardingHistory:output_type -> lnrpc.ForwardingHistoryResponse + 196, // 317: lnrpc.Lightning.ExportChannelBackup:output_type -> lnrpc.ChannelBackup + 199, // 318: lnrpc.Lightning.ExportAllChannelBackups:output_type -> lnrpc.ChanBackupSnapshot + 204, // 319: lnrpc.Lightning.VerifyChanBackup:output_type -> lnrpc.VerifyChanBackupResponse + 202, // 320: lnrpc.Lightning.RestoreChannelBackups:output_type -> lnrpc.RestoreBackupResponse + 199, // 321: lnrpc.Lightning.SubscribeChannelBackups:output_type -> lnrpc.ChanBackupSnapshot + 207, // 322: lnrpc.Lightning.BakeMacaroon:output_type -> lnrpc.BakeMacaroonResponse + 209, // 323: lnrpc.Lightning.ListMacaroonIDs:output_type -> lnrpc.ListMacaroonIDsResponse + 211, // 324: lnrpc.Lightning.DeleteMacaroonID:output_type -> lnrpc.DeleteMacaroonIDResponse + 214, // 325: lnrpc.Lightning.ListPermissions:output_type -> lnrpc.ListPermissionsResponse + 220, // 326: lnrpc.Lightning.CheckMacaroonPermissions:output_type -> lnrpc.CheckMacPermResponse + 221, // 327: lnrpc.Lightning.RegisterRPCMiddleware:output_type -> lnrpc.RPCMiddlewareRequest + 27, // 328: lnrpc.Lightning.SendCustomMessage:output_type -> lnrpc.SendCustomMessageResponse + 25, // 329: lnrpc.Lightning.SubscribeCustomMessages:output_type -> lnrpc.CustomMessage + 31, // 330: lnrpc.Lightning.SendOnionMessage:output_type -> lnrpc.SendOnionMessageResponse + 29, // 331: lnrpc.Lightning.SubscribeOnionMessages:output_type -> lnrpc.OnionMessageUpdate + 69, // 332: lnrpc.Lightning.ListAliases:output_type -> lnrpc.ListAliasesResponse + 23, // 333: lnrpc.Lightning.LookupHtlcResolution:output_type -> lnrpc.LookupHtlcResolutionResponse + 267, // [267:334] is the sub-list for method output_type + 200, // [200:267] is the sub-list for method input_type + 200, // [200:200] is the sub-list for extension type_name + 200, // [200:200] is the sub-list for extension extendee + 0, // [0:200] 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 be43c88a458..7e03bb43b08 100644 --- a/lnrpc/lightning.proto +++ b/lnrpc/lightning.proto @@ -3196,6 +3196,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 7be82853d4e..5eb0818c4a2 100644 --- a/lnrpc/lightning.swagger.json +++ b/lnrpc/lightning.swagger.json @@ -1424,6 +1424,35 @@ "format": "uint64" }, "collectionFormat": "multi" + }, + { + "name": "payment_addr", + "description": "An optional payment address included in the invoice (also called payment\nsecret). If set, an MPP record containing this value will be included in\nthe final hop of the returned route.", + "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": [ @@ -1570,6 +1599,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": "An optional payment address included in the invoice (also called payment\nsecret). If set, an MPP record containing this value will be included in\nthe final hop of the returned route." + }, + "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 f599ecca3f5..b828429de85 100644 --- a/lnrpc/routerrpc/router.pb.go +++ b/lnrpc/routerrpc/router.pb.go @@ -2025,8 +2025,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() { @@ -2101,6 +2104,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. @@ -3720,7 +3730,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" + @@ -3728,7 +3738,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" + @@ -3982,11 +3994,12 @@ var file_routerrpc_router_proto_goTypes = []any{ (lnrpc.FeatureBit)(0), // 60: lnrpc.FeatureBit (lnrpc.PaymentFailureReason)(0), // 61: lnrpc.PaymentFailureReason (*lnrpc.Route)(nil), // 62: lnrpc.Route - (lnrpc.Failure_FailureCode)(0), // 63: lnrpc.Failure.FailureCode - (*lnrpc.ChannelPoint)(nil), // 64: lnrpc.ChannelPoint - (*lnrpc.AliasMap)(nil), // 65: lnrpc.AliasMap - (*lnrpc.Payment)(nil), // 66: lnrpc.Payment - (*lnrpc.HTLCAttempt)(nil), // 67: lnrpc.HTLCAttempt + (*lnrpc.AMPRecord)(nil), // 63: lnrpc.AMPRecord + (lnrpc.Failure_FailureCode)(0), // 64: lnrpc.Failure.FailureCode + (*lnrpc.ChannelPoint)(nil), // 65: lnrpc.ChannelPoint + (*lnrpc.AliasMap)(nil), // 66: lnrpc.AliasMap + (*lnrpc.Payment)(nil), // 67: lnrpc.Payment + (*lnrpc.HTLCAttempt)(nil), // 68: lnrpc.HTLCAttempt } var file_routerrpc_router_proto_depIdxs = []int32{ 59, // 0: routerrpc.SendPaymentRequest.route_hints:type_name -> lnrpc.RouteHint @@ -4006,74 +4019,75 @@ var file_routerrpc_router_proto_depIdxs = []int32{ 24, // 14: routerrpc.MissionControlConfig.bimodal:type_name -> routerrpc.BimodalParameters 18, // 15: routerrpc.QueryProbabilityResponse.history:type_name -> routerrpc.PairData 55, // 16: routerrpc.BuildRouteRequest.first_hop_custom_records:type_name -> routerrpc.BuildRouteRequest.FirstHopCustomRecordsEntry - 62, // 17: routerrpc.BuildRouteResponse.route:type_name -> lnrpc.Route - 4, // 18: routerrpc.HtlcEvent.event_type:type_name -> routerrpc.HtlcEvent.EventType - 33, // 19: routerrpc.HtlcEvent.forward_event:type_name -> routerrpc.ForwardEvent - 34, // 20: routerrpc.HtlcEvent.forward_fail_event:type_name -> routerrpc.ForwardFailEvent - 35, // 21: routerrpc.HtlcEvent.settle_event:type_name -> routerrpc.SettleEvent - 38, // 22: routerrpc.HtlcEvent.link_fail_event:type_name -> routerrpc.LinkFailEvent - 37, // 23: routerrpc.HtlcEvent.subscribed_event:type_name -> routerrpc.SubscribedEvent - 36, // 24: routerrpc.HtlcEvent.final_htlc_event:type_name -> routerrpc.FinalHtlcEvent - 32, // 25: routerrpc.ForwardEvent.info:type_name -> routerrpc.HtlcInfo - 32, // 26: routerrpc.LinkFailEvent.info:type_name -> routerrpc.HtlcInfo - 63, // 27: routerrpc.LinkFailEvent.wire_failure:type_name -> lnrpc.Failure.FailureCode - 0, // 28: routerrpc.LinkFailEvent.failure_detail:type_name -> routerrpc.FailureDetail - 39, // 29: routerrpc.ForwardHtlcInterceptRequest.incoming_circuit_key:type_name -> routerrpc.CircuitKey - 56, // 30: routerrpc.ForwardHtlcInterceptRequest.custom_records:type_name -> routerrpc.ForwardHtlcInterceptRequest.CustomRecordsEntry - 57, // 31: routerrpc.ForwardHtlcInterceptRequest.in_wire_custom_records:type_name -> routerrpc.ForwardHtlcInterceptRequest.InWireCustomRecordsEntry - 39, // 32: routerrpc.ForwardHtlcInterceptResponse.incoming_circuit_key:type_name -> routerrpc.CircuitKey - 1, // 33: routerrpc.ForwardHtlcInterceptResponse.action:type_name -> routerrpc.ResolveHoldForwardAction - 63, // 34: routerrpc.ForwardHtlcInterceptResponse.failure_code:type_name -> lnrpc.Failure.FailureCode - 58, // 35: routerrpc.ForwardHtlcInterceptResponse.out_wire_custom_records:type_name -> routerrpc.ForwardHtlcInterceptResponse.OutWireCustomRecordsEntry - 64, // 36: routerrpc.UpdateChanStatusRequest.chan_point:type_name -> lnrpc.ChannelPoint - 2, // 37: routerrpc.UpdateChanStatusRequest.action:type_name -> routerrpc.ChanStatusAction - 65, // 38: routerrpc.AddAliasesRequest.alias_maps:type_name -> lnrpc.AliasMap - 65, // 39: routerrpc.AddAliasesResponse.alias_maps:type_name -> lnrpc.AliasMap - 65, // 40: routerrpc.DeleteAliasesRequest.alias_maps:type_name -> lnrpc.AliasMap - 65, // 41: routerrpc.DeleteAliasesResponse.alias_maps:type_name -> lnrpc.AliasMap - 5, // 42: routerrpc.Router.SendPaymentV2:input_type -> routerrpc.SendPaymentRequest - 6, // 43: routerrpc.Router.TrackPaymentV2:input_type -> routerrpc.TrackPaymentRequest - 7, // 44: routerrpc.Router.TrackPayments:input_type -> routerrpc.TrackPaymentsRequest - 8, // 45: routerrpc.Router.EstimateRouteFee:input_type -> routerrpc.RouteFeeRequest - 10, // 46: routerrpc.Router.SendToRouteV2:input_type -> routerrpc.SendToRouteRequest - 11, // 47: routerrpc.Router.ResetMissionControl:input_type -> routerrpc.ResetMissionControlRequest - 13, // 48: routerrpc.Router.QueryMissionControl:input_type -> routerrpc.QueryMissionControlRequest - 15, // 49: routerrpc.Router.XImportMissionControl:input_type -> routerrpc.XImportMissionControlRequest - 19, // 50: routerrpc.Router.GetMissionControlConfig:input_type -> routerrpc.GetMissionControlConfigRequest - 21, // 51: routerrpc.Router.SetMissionControlConfig:input_type -> routerrpc.SetMissionControlConfigRequest - 26, // 52: routerrpc.Router.QueryProbability:input_type -> routerrpc.QueryProbabilityRequest - 28, // 53: routerrpc.Router.BuildRoute:input_type -> routerrpc.BuildRouteRequest - 30, // 54: routerrpc.Router.SubscribeHtlcEvents:input_type -> routerrpc.SubscribeHtlcEventsRequest - 41, // 55: routerrpc.Router.HtlcInterceptor:input_type -> routerrpc.ForwardHtlcInterceptResponse - 42, // 56: routerrpc.Router.UpdateChanStatus:input_type -> routerrpc.UpdateChanStatusRequest - 44, // 57: routerrpc.Router.XAddLocalChanAliases:input_type -> routerrpc.AddAliasesRequest - 46, // 58: routerrpc.Router.XDeleteLocalChanAliases:input_type -> routerrpc.DeleteAliasesRequest - 48, // 59: routerrpc.Router.XFindBaseLocalChanAlias:input_type -> routerrpc.FindBaseAliasRequest - 50, // 60: routerrpc.Router.DeleteForwardingHistory:input_type -> routerrpc.DeleteForwardingHistoryRequest - 66, // 61: routerrpc.Router.SendPaymentV2:output_type -> lnrpc.Payment - 66, // 62: routerrpc.Router.TrackPaymentV2:output_type -> lnrpc.Payment - 66, // 63: routerrpc.Router.TrackPayments:output_type -> lnrpc.Payment - 9, // 64: routerrpc.Router.EstimateRouteFee:output_type -> routerrpc.RouteFeeResponse - 67, // 65: routerrpc.Router.SendToRouteV2:output_type -> lnrpc.HTLCAttempt - 12, // 66: routerrpc.Router.ResetMissionControl:output_type -> routerrpc.ResetMissionControlResponse - 14, // 67: routerrpc.Router.QueryMissionControl:output_type -> routerrpc.QueryMissionControlResponse - 16, // 68: routerrpc.Router.XImportMissionControl:output_type -> routerrpc.XImportMissionControlResponse - 20, // 69: routerrpc.Router.GetMissionControlConfig:output_type -> routerrpc.GetMissionControlConfigResponse - 22, // 70: routerrpc.Router.SetMissionControlConfig:output_type -> routerrpc.SetMissionControlConfigResponse - 27, // 71: routerrpc.Router.QueryProbability:output_type -> routerrpc.QueryProbabilityResponse - 29, // 72: routerrpc.Router.BuildRoute:output_type -> routerrpc.BuildRouteResponse - 31, // 73: routerrpc.Router.SubscribeHtlcEvents:output_type -> routerrpc.HtlcEvent - 40, // 74: routerrpc.Router.HtlcInterceptor:output_type -> routerrpc.ForwardHtlcInterceptRequest - 43, // 75: routerrpc.Router.UpdateChanStatus:output_type -> routerrpc.UpdateChanStatusResponse - 45, // 76: routerrpc.Router.XAddLocalChanAliases:output_type -> routerrpc.AddAliasesResponse - 47, // 77: routerrpc.Router.XDeleteLocalChanAliases:output_type -> routerrpc.DeleteAliasesResponse - 49, // 78: routerrpc.Router.XFindBaseLocalChanAlias:output_type -> routerrpc.FindBaseAliasResponse - 51, // 79: routerrpc.Router.DeleteForwardingHistory:output_type -> routerrpc.DeleteForwardingHistoryResponse - 61, // [61:80] is the sub-list for method output_type - 42, // [42:61] is the sub-list for method input_type - 42, // [42:42] is the sub-list for extension type_name - 42, // [42:42] is the sub-list for extension extendee - 0, // [0:42] is the sub-list for field type_name + 63, // 17: routerrpc.BuildRouteRequest.amp_record:type_name -> lnrpc.AMPRecord + 62, // 18: routerrpc.BuildRouteResponse.route:type_name -> lnrpc.Route + 4, // 19: routerrpc.HtlcEvent.event_type:type_name -> routerrpc.HtlcEvent.EventType + 33, // 20: routerrpc.HtlcEvent.forward_event:type_name -> routerrpc.ForwardEvent + 34, // 21: routerrpc.HtlcEvent.forward_fail_event:type_name -> routerrpc.ForwardFailEvent + 35, // 22: routerrpc.HtlcEvent.settle_event:type_name -> routerrpc.SettleEvent + 38, // 23: routerrpc.HtlcEvent.link_fail_event:type_name -> routerrpc.LinkFailEvent + 37, // 24: routerrpc.HtlcEvent.subscribed_event:type_name -> routerrpc.SubscribedEvent + 36, // 25: routerrpc.HtlcEvent.final_htlc_event:type_name -> routerrpc.FinalHtlcEvent + 32, // 26: routerrpc.ForwardEvent.info:type_name -> routerrpc.HtlcInfo + 32, // 27: routerrpc.LinkFailEvent.info:type_name -> routerrpc.HtlcInfo + 64, // 28: routerrpc.LinkFailEvent.wire_failure:type_name -> lnrpc.Failure.FailureCode + 0, // 29: routerrpc.LinkFailEvent.failure_detail:type_name -> routerrpc.FailureDetail + 39, // 30: routerrpc.ForwardHtlcInterceptRequest.incoming_circuit_key:type_name -> routerrpc.CircuitKey + 56, // 31: routerrpc.ForwardHtlcInterceptRequest.custom_records:type_name -> routerrpc.ForwardHtlcInterceptRequest.CustomRecordsEntry + 57, // 32: routerrpc.ForwardHtlcInterceptRequest.in_wire_custom_records:type_name -> routerrpc.ForwardHtlcInterceptRequest.InWireCustomRecordsEntry + 39, // 33: routerrpc.ForwardHtlcInterceptResponse.incoming_circuit_key:type_name -> routerrpc.CircuitKey + 1, // 34: routerrpc.ForwardHtlcInterceptResponse.action:type_name -> routerrpc.ResolveHoldForwardAction + 64, // 35: routerrpc.ForwardHtlcInterceptResponse.failure_code:type_name -> lnrpc.Failure.FailureCode + 58, // 36: routerrpc.ForwardHtlcInterceptResponse.out_wire_custom_records:type_name -> routerrpc.ForwardHtlcInterceptResponse.OutWireCustomRecordsEntry + 65, // 37: routerrpc.UpdateChanStatusRequest.chan_point:type_name -> lnrpc.ChannelPoint + 2, // 38: routerrpc.UpdateChanStatusRequest.action:type_name -> routerrpc.ChanStatusAction + 66, // 39: routerrpc.AddAliasesRequest.alias_maps:type_name -> lnrpc.AliasMap + 66, // 40: routerrpc.AddAliasesResponse.alias_maps:type_name -> lnrpc.AliasMap + 66, // 41: routerrpc.DeleteAliasesRequest.alias_maps:type_name -> lnrpc.AliasMap + 66, // 42: routerrpc.DeleteAliasesResponse.alias_maps:type_name -> lnrpc.AliasMap + 5, // 43: routerrpc.Router.SendPaymentV2:input_type -> routerrpc.SendPaymentRequest + 6, // 44: routerrpc.Router.TrackPaymentV2:input_type -> routerrpc.TrackPaymentRequest + 7, // 45: routerrpc.Router.TrackPayments:input_type -> routerrpc.TrackPaymentsRequest + 8, // 46: routerrpc.Router.EstimateRouteFee:input_type -> routerrpc.RouteFeeRequest + 10, // 47: routerrpc.Router.SendToRouteV2:input_type -> routerrpc.SendToRouteRequest + 11, // 48: routerrpc.Router.ResetMissionControl:input_type -> routerrpc.ResetMissionControlRequest + 13, // 49: routerrpc.Router.QueryMissionControl:input_type -> routerrpc.QueryMissionControlRequest + 15, // 50: routerrpc.Router.XImportMissionControl:input_type -> routerrpc.XImportMissionControlRequest + 19, // 51: routerrpc.Router.GetMissionControlConfig:input_type -> routerrpc.GetMissionControlConfigRequest + 21, // 52: routerrpc.Router.SetMissionControlConfig:input_type -> routerrpc.SetMissionControlConfigRequest + 26, // 53: routerrpc.Router.QueryProbability:input_type -> routerrpc.QueryProbabilityRequest + 28, // 54: routerrpc.Router.BuildRoute:input_type -> routerrpc.BuildRouteRequest + 30, // 55: routerrpc.Router.SubscribeHtlcEvents:input_type -> routerrpc.SubscribeHtlcEventsRequest + 41, // 56: routerrpc.Router.HtlcInterceptor:input_type -> routerrpc.ForwardHtlcInterceptResponse + 42, // 57: routerrpc.Router.UpdateChanStatus:input_type -> routerrpc.UpdateChanStatusRequest + 44, // 58: routerrpc.Router.XAddLocalChanAliases:input_type -> routerrpc.AddAliasesRequest + 46, // 59: routerrpc.Router.XDeleteLocalChanAliases:input_type -> routerrpc.DeleteAliasesRequest + 48, // 60: routerrpc.Router.XFindBaseLocalChanAlias:input_type -> routerrpc.FindBaseAliasRequest + 50, // 61: routerrpc.Router.DeleteForwardingHistory:input_type -> routerrpc.DeleteForwardingHistoryRequest + 67, // 62: routerrpc.Router.SendPaymentV2:output_type -> lnrpc.Payment + 67, // 63: routerrpc.Router.TrackPaymentV2:output_type -> lnrpc.Payment + 67, // 64: routerrpc.Router.TrackPayments:output_type -> lnrpc.Payment + 9, // 65: routerrpc.Router.EstimateRouteFee:output_type -> routerrpc.RouteFeeResponse + 68, // 66: routerrpc.Router.SendToRouteV2:output_type -> lnrpc.HTLCAttempt + 12, // 67: routerrpc.Router.ResetMissionControl:output_type -> routerrpc.ResetMissionControlResponse + 14, // 68: routerrpc.Router.QueryMissionControl:output_type -> routerrpc.QueryMissionControlResponse + 16, // 69: routerrpc.Router.XImportMissionControl:output_type -> routerrpc.XImportMissionControlResponse + 20, // 70: routerrpc.Router.GetMissionControlConfig:output_type -> routerrpc.GetMissionControlConfigResponse + 22, // 71: routerrpc.Router.SetMissionControlConfig:output_type -> routerrpc.SetMissionControlConfigResponse + 27, // 72: routerrpc.Router.QueryProbability:output_type -> routerrpc.QueryProbabilityResponse + 29, // 73: routerrpc.Router.BuildRoute:output_type -> routerrpc.BuildRouteResponse + 31, // 74: routerrpc.Router.SubscribeHtlcEvents:output_type -> routerrpc.HtlcEvent + 40, // 75: routerrpc.Router.HtlcInterceptor:output_type -> routerrpc.ForwardHtlcInterceptRequest + 43, // 76: routerrpc.Router.UpdateChanStatus:output_type -> routerrpc.UpdateChanStatusResponse + 45, // 77: routerrpc.Router.XAddLocalChanAliases:output_type -> routerrpc.AddAliasesResponse + 47, // 78: routerrpc.Router.XDeleteLocalChanAliases:output_type -> routerrpc.DeleteAliasesResponse + 49, // 79: routerrpc.Router.XFindBaseLocalChanAlias:output_type -> routerrpc.FindBaseAliasResponse + 51, // 80: routerrpc.Router.DeleteForwardingHistory:output_type -> routerrpc.DeleteForwardingHistoryResponse + 62, // [62:81] is the sub-list for method output_type + 43, // [43:62] is the sub-list for method input_type + 43, // [43:43] is the sub-list for extension type_name + 43, // [43:43] is the sub-list for extension extendee + 0, // [0:43] 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 0f7cc6b7dd8..8d61996f0ce 100644 --- a/lnrpc/routerrpc/router.proto +++ b/lnrpc/routerrpc/router.proto @@ -740,6 +740,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 d8bf6c965eb..9ae67e24c78 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 09d60aba589..f8a907f2416 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 d4ff2242002..01a39795fb8 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 ) @@ -37,21 +38,21 @@ 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) + testQueryRoutes(t, false, false, true, false) }) - t.Run("no mission control and msat", func(t *testing.T) { - testQueryRoutes(t, false, true, true) + t.Run("no mission control, using msat and MPP", func(t *testing.T) { + testQueryRoutes(t, false, true, true, true) }) t.Run("with mission control", func(t *testing.T) { - testQueryRoutes(t, true, false, true) + testQueryRoutes(t, true, false, true, false) }) t.Run("no mission control bad cltv limit", func(t *testing.T) { - testQueryRoutes(t, false, false, false) + testQueryRoutes(t, false, false, false, false) }) } -func testQueryRoutes(t *testing.T, useMissionControl bool, useMsat bool, - setTimelock bool) { +func testQueryRoutes(t *testing.T, useMissionControl, useMsat, + setTimelock, useMPP bool) { ignoreNodeBytes, err := hex.DecodeString(ignoreNodeKey) if err != nil { @@ -87,6 +88,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, @@ -103,6 +112,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) @@ -189,6 +199,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, ) @@ -243,6 +257,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 9939c3f680a..1d19d46e517 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" @@ -1098,6 +1099,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 @@ -1701,12 +1706,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 { @@ -1734,7 +1750,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