@@ -10,6 +10,7 @@ mod common;
1010use  std:: collections:: HashSet ; 
1111use  std:: str:: FromStr ; 
1212use  std:: sync:: Arc ; 
13+ use  std:: time:: Instant ; 
1314
1415use  bitcoin:: address:: NetworkUnchecked ; 
1516use  bitcoin:: hashes:: sha256:: Hash  as  Sha256Hash ; 
@@ -23,21 +24,24 @@ use common::{
2324	generate_blocks_and_wait,  open_channel,  open_channel_push_amt,  premine_and_distribute_funds, 
2425	premine_blocks,  prepare_rbf,  random_config,  random_listening_addresses, 
2526	setup_bitcoind_and_electrsd,  setup_builder,  setup_node,  setup_node_for_async_payments, 
26- 	setup_two_nodes,  wait_for_tx,  TestChainSource ,  TestSyncStore , 
27+ 	setup_two_nodes,  setup_two_nodes_with_store ,   wait_for_tx,  TestChainSource ,  TestSyncStore , 
2728} ; 
2829use  ldk_node:: config:: { AsyncPaymentsRole ,  EsploraSyncConfig } ; 
2930use  ldk_node:: liquidity:: LSPS2ServiceConfig ; 
3031use  ldk_node:: payment:: { 
3132	ConfirmationStatus ,  PaymentDetails ,  PaymentDirection ,  PaymentKind ,  PaymentStatus , 
3233	QrPaymentResult , 
3334} ; 
34- use  ldk_node:: { Builder ,  DynStore ,  Event ,  NodeError } ; 
35+ use  ldk_node:: { Builder ,  DynStore ,  Event ,  Node ,   NodeError } ; 
3536use  lightning:: ln:: channelmanager:: PaymentId ; 
3637use  lightning:: routing:: gossip:: { NodeAlias ,  NodeId } ; 
3738use  lightning:: routing:: router:: RouteParametersConfig ; 
39+ use  lightning:: util:: hash_tables:: new_hash_map; 
3840use  lightning_invoice:: { Bolt11InvoiceDescription ,  Description } ; 
3941use  lightning_types:: payment:: { PaymentHash ,  PaymentPreimage } ; 
4042use  log:: LevelFilter ; 
43+ use  tokio:: sync:: Mutex ; 
44+ use  tokio:: task:: { self ,  JoinSet } ; 
4145
4246#[ test]  
4347fn  channel_full_cycle ( )  { 
@@ -1761,6 +1765,128 @@ fn facade_logging() {
17611765	} 
17621766} 
17631767
1768+ fn  spawn_payment ( node_a :  Arc < Node > ,  node_b :  Arc < Node > ,  cur_id :  u32 )  { 
1769+ 	let  mut  preimage_bytes = [ 0u8 ;  32 ] ; 
1770+ 
1771+ 	preimage_bytes[ 0 ..4 ] . copy_from_slice ( & cur_id. to_le_bytes ( ) ) ; 
1772+ 
1773+ 	// Spawn each payment as a separate async task 
1774+ 	task:: spawn ( async  move  { 
1775+ 		println ! ( "Starting payment {}" ,  cur_id) ; 
1776+ 		let  custom_preimage = PaymentPreimage ( preimage_bytes) ; 
1777+ 		let  amount_msat = 10_000_000 ; 
1778+ 
1779+ 		loop  { 
1780+ 			// Pre-check the HTLC slots to try to avoid the performance impact of a failed payment. 
1781+ 			while  node_a. list_channels ( ) [ 0 ] . next_outbound_htlc_limit_msat  == 0  { 
1782+ 				println ! ( "Waiting for HTLC slots to free up... ({})" ,  cur_id) ; 
1783+ 				tokio:: time:: sleep ( std:: time:: Duration :: from_millis ( 100 ) ) . await ; 
1784+ 			} 
1785+ 
1786+ 			let  payment_id = node_a. spontaneous_payment ( ) . send_with_preimage ( 
1787+ 				amount_msat, 
1788+ 				node_b. node_id ( ) , 
1789+ 				custom_preimage, 
1790+ 				None , 
1791+ 			) ; 
1792+ 
1793+ 			match  payment_id { 
1794+ 				Ok ( payment_id)  => { 
1795+ 					println ! ( "Awaiting payment {} ({})" ,  payment_id,  cur_id) ; 
1796+ 					break ; 
1797+ 				} , 
1798+ 				Err ( e)  => { 
1799+ 					println ! ( "Payment attempt failed: {:?}, retrying... ({})" ,  e,  cur_id) ; 
1800+ 
1801+ 					tokio:: time:: sleep ( std:: time:: Duration :: from_millis ( 100 ) ) . await ; 
1802+ 				} , 
1803+ 			} 
1804+ 		} 
1805+ 	} ) ; 
1806+ } 
1807+ 
1808+ #[ tokio:: test( flavor = "multi_thread" ,  worker_threads = 4 ) ]  
1809+ async  fn  payment_benchmark ( )  { 
1810+ 	let  ( bitcoind,  electrsd)  = setup_bitcoind_and_electrsd ( ) ; 
1811+ 	let  chain_source = TestChainSource :: Esplora ( & electrsd) ; 
1812+ 	let  ( node_a,  node_b)  = setup_two_nodes_with_store ( 
1813+ 		& chain_source, 
1814+ 		false , 
1815+ 		true , 
1816+ 		false , 
1817+ 		common:: TestStoreType :: Sqlite , 
1818+ 	) ; 
1819+ 
1820+ 	let  address_a = node_a. onchain_payment ( ) . new_address ( ) . unwrap ( ) ; 
1821+ 	let  premine_sat = 25_000_000 ; 
1822+ 	premine_and_distribute_funds ( 
1823+ 		& bitcoind. client , 
1824+ 		& electrsd. client , 
1825+ 		vec ! [ address_a] , 
1826+ 		Amount :: from_sat ( premine_sat) , 
1827+ 	) ; 
1828+ 	node_a. sync_wallets ( ) . unwrap ( ) ; 
1829+ 	node_b. sync_wallets ( ) . unwrap ( ) ; 
1830+ 	open_channel ( & node_a,  & node_b,  16_000_000 ,  true ,  & electrsd) ; 
1831+ 	generate_blocks_and_wait ( & bitcoind. client ,  & electrsd. client ,  6 ) ; 
1832+ 	node_a. sync_wallets ( ) . unwrap ( ) ; 
1833+ 	node_b. sync_wallets ( ) . unwrap ( ) ; 
1834+ 	expect_channel_ready_event ! ( node_a,  node_b. node_id( ) ) ; 
1835+ 	expect_channel_ready_event ! ( node_b,  node_a. node_id( ) ) ; 
1836+ 
1837+ 	let  start = Instant :: now ( ) ; 
1838+ 
1839+ 	let  node_a = Arc :: new ( node_a) ; 
1840+ 	let  node_b = Arc :: new ( node_b) ; 
1841+ 
1842+ 	let  total_payments = 1000 ; 
1843+ 	let  max_in_flight = 20 ; 
1844+ 
1845+ 	let  mut  cur_id = 0u32 ; 
1846+ 	let  mut  in_flight = 0 ; 
1847+ 	let  mut  success_count = 0 ; 
1848+ 
1849+ 	while  success_count < total_payments { 
1850+ 		// Spawn new payments if we aren't at max in-flight and haven't sent all payments yet. 
1851+ 		let  to_spawn =
1852+ 			std:: cmp:: min ( max_in_flight - in_flight,  total_payments - ( in_flight + success_count) ) ; 
1853+ 
1854+ 		println ! ( 
1855+ 			"Spawning {} new payments ({} in flight, {} successes)" , 
1856+ 			to_spawn,  in_flight,  success_count
1857+ 		) ; 
1858+ 		for  _ in  0 ..to_spawn { 
1859+ 			spawn_payment ( node_a. clone ( ) ,  node_b. clone ( ) ,  cur_id) ; 
1860+ 			cur_id += 1 ; 
1861+ 			in_flight += 1 ; 
1862+ 		} 
1863+ 
1864+ 		match  node_a. next_event_async ( ) . await  { 
1865+ 			Event :: PaymentSuccessful  {  payment_id,  .. }  => { 
1866+ 				if  let  Some ( id)  = payment_id { 
1867+ 					success_count += 1 ; 
1868+ 					in_flight -= 1 ; 
1869+ 					println ! ( "Payment {:?} completed" ,  id) ; 
1870+ 				}  else  { 
1871+ 					println ! ( "Payment completed (no payment_id)" ) ; 
1872+ 				} 
1873+ 			} , 
1874+ 			Event :: PaymentFailed  {  payment_id,  .. }  => { 
1875+ 				in_flight -= 1 ; 
1876+ 				println ! ( "Payment {:?} failed" ,  payment_id) ; 
1877+ 			} , 
1878+ 			ref  e => { 
1879+ 				println ! ( "Received non-payment event: {:?}" ,  e) ; 
1880+ 			} , 
1881+ 		} 
1882+ 
1883+ 		node_a. event_handled ( ) . unwrap ( ) ; 
1884+ 	} 
1885+ 
1886+ 	let  duration = start. elapsed ( ) ; 
1887+ 	println ! ( "Time elapsed: {:?}" ,  duration) ; 
1888+ } 
1889+ 
17641890#[ test]  
17651891fn  spontaneous_send_with_custom_preimage ( )  { 
17661892	let  ( bitcoind,  electrsd)  = setup_bitcoind_and_electrsd ( ) ; 
0 commit comments