@@ -17,6 +17,8 @@ use lightning::ln::channelmanager::{
17
17
use lightning:: ln:: msgs:: SocketAddress ;
18
18
use lightning:: ln:: types:: ChannelId ;
19
19
use lightning:: offers:: offer:: { self , Offer } ;
20
+ use lightning:: onion_message:: dns_resolution:: HumanReadableName ;
21
+ use lightning:: onion_message:: messenger:: Destination ;
20
22
use lightning:: routing:: gossip:: NodeId ;
21
23
use lightning:: routing:: router:: { PaymentParameters , RouteParameters } ;
22
24
use lightning:: sign:: { EntropySource , KeysManager } ;
@@ -142,9 +144,10 @@ pub(crate) fn poll_for_user_input(
142
144
"sendpayment" => {
143
145
let invoice_str = words. next ( ) ;
144
146
if invoice_str. is_none ( ) {
145
- println ! ( "ERROR: sendpayment requires an invoice: `sendpayment <invoice>`" ) ;
147
+ println ! ( "ERROR: sendpayment requires an invoice: `sendpayment <invoice> [amount_msat] `" ) ;
146
148
continue ;
147
149
}
150
+ let invoice_str = invoice_str. unwrap ( ) ;
148
151
149
152
let mut user_provided_amt: Option < u64 > = None ;
150
153
if let Some ( amt_msat_str) = words. next ( ) {
@@ -157,7 +160,7 @@ pub(crate) fn poll_for_user_input(
157
160
} ;
158
161
}
159
162
160
- if let Ok ( offer) = Offer :: from_str ( invoice_str. unwrap ( ) ) {
163
+ if let Ok ( offer) = Offer :: from_str ( invoice_str) {
161
164
let random_bytes = keys_manager. get_secure_random_bytes ( ) ;
162
165
let payment_id = PaymentId ( random_bytes) ;
163
166
@@ -213,11 +216,77 @@ pub(crate) fn poll_for_user_input(
213
216
let amt = Some ( amt_msat) ;
214
217
let pay = channel_manager
215
218
. pay_for_offer ( & offer, None , amt, None , payment_id, retry, None ) ;
216
- if pay. is_err ( ) {
219
+ if pay. is_ok ( ) {
220
+ println ! ( "Payment in flight" ) ;
221
+ } else {
217
222
println ! ( "ERROR: Failed to pay: {:?}" , pay) ;
218
223
}
224
+ } else if let Ok ( hrn) = HumanReadableName :: from_encoded ( invoice_str) {
225
+ let random_bytes = keys_manager. get_secure_random_bytes ( ) ;
226
+ let payment_id = PaymentId ( random_bytes) ;
227
+
228
+ if user_provided_amt. is_none ( ) {
229
+ println ! ( "Can't pay to a human-readable-name without an amount" ) ;
230
+ continue ;
231
+ }
232
+
233
+ // We need some nodes that will resolve DNS for us in order to pay a Human
234
+ // Readable Name. They don't need to be trusted, but until onion message
235
+ // forwarding is widespread we'll directly connect to them, revealing who
236
+ // we intend to pay.
237
+ let mut dns_resolvers = Vec :: new ( ) ;
238
+ for ( node_id, node) in network_graph. read_only ( ) . nodes ( ) . unordered_iter ( ) {
239
+ if let Some ( info) = & node. announcement_info {
240
+ // Sadly, 31 nodes currently squat on the DNS Resolver feature bit
241
+ // without speaking it.
242
+ // Its unclear why they're doing so, but none of them currently
243
+ // also have the onion messaging feature bit set, so here we check
244
+ // for both.
245
+ let supports_dns = info. features ( ) . supports_dns_resolution ( ) ;
246
+ let supports_om = info. features ( ) . supports_onion_messages ( ) ;
247
+ if supports_dns && supports_om {
248
+ if let Ok ( pubkey) = node_id. as_pubkey ( ) {
249
+ dns_resolvers. push ( Destination :: Node ( pubkey) ) ;
250
+ }
251
+ }
252
+ }
253
+ if dns_resolvers. len ( ) > 5 {
254
+ break ;
255
+ }
256
+ }
257
+ if dns_resolvers. is_empty ( ) {
258
+ println ! (
259
+ "Failed to find any DNS resolving nodes, check your network graph is synced"
260
+ ) ;
261
+ continue ;
262
+ }
263
+
264
+ let amt_msat = user_provided_amt. unwrap ( ) ;
265
+ outbound_payments. lock ( ) . unwrap ( ) . payments . insert (
266
+ payment_id,
267
+ PaymentInfo {
268
+ preimage : None ,
269
+ secret : None ,
270
+ status : HTLCStatus :: Pending ,
271
+ amt_msat : MillisatAmount ( Some ( amt_msat) ) ,
272
+ } ,
273
+ ) ;
274
+ fs_store
275
+ . write ( "" , "" , OUTBOUND_PAYMENTS_FNAME , & outbound_payments. encode ( ) )
276
+ . unwrap ( ) ;
277
+
278
+ let retry = Retry :: Timeout ( Duration :: from_secs ( 10 ) ) ;
279
+ let pay = |a, b, c, d, e, f| {
280
+ channel_manager. pay_for_offer_from_human_readable_name ( a, b, c, d, e, f)
281
+ } ;
282
+ let pay = pay ( hrn, amt_msat, payment_id, retry, None , dns_resolvers) ;
283
+ if pay. is_ok ( ) {
284
+ println ! ( "Payment in flight" ) ;
285
+ } else {
286
+ println ! ( "ERROR: Failed to pay" ) ;
287
+ }
219
288
} else {
220
- match Bolt11Invoice :: from_str ( invoice_str. unwrap ( ) ) {
289
+ match Bolt11Invoice :: from_str ( invoice_str) {
221
290
Ok ( invoice) => send_payment (
222
291
& channel_manager,
223
292
& invoice,
@@ -505,7 +574,7 @@ fn help() {
505
574
println ! ( " disconnectpeer <peer_pubkey>" ) ;
506
575
println ! ( " listpeers" ) ;
507
576
println ! ( "\n Payments:" ) ;
508
- println ! ( " sendpayment <invoice|offer> [<amount_msat>]" ) ;
577
+ println ! ( " sendpayment <invoice|offer|human readable name > [<amount_msat>]" ) ;
509
578
println ! ( " keysend <dest_pubkey> <amt_msats>" ) ;
510
579
println ! ( " listpayments" ) ;
511
580
println ! ( "\n Invoices:" ) ;
0 commit comments