@@ -18,6 +18,7 @@ use lightning::util::logger::Logger;
1818use secp256k1:: PublicKey ;
1919use core:: ops:: Deref ;
2020use core:: time:: Duration ;
21+ use core:: iter:: Iterator ;
2122
2223/// Utility to create an invoice that can be paid to one of multiple nodes, or a "phantom invoice."
2324/// See [`PhantomKeysManager`] for more information on phantom node payments.
@@ -229,7 +230,7 @@ where
229230///
230231/// [`PhantomKeysManager`]: lightning::sign::PhantomKeysManager
231232fn select_phantom_hints < L : Deref > ( amt_msat : Option < u64 > , phantom_route_hints : Vec < PhantomRouteHints > ,
232- logger : L ) -> Vec < RouteHint >
233+ logger : L ) -> impl Iterator < Item = RouteHint >
233234where
234235 L :: Target : Logger ,
235236{
@@ -267,29 +268,47 @@ where
267268 // the hints across our real nodes we add one hint from each in turn until no node has any hints
268269 // left (if one node has more hints than any other, these will accumulate at the end of the
269270 // vector).
270- let mut invoice_hints: Vec < RouteHint > = Vec :: new ( ) ;
271- let mut hint_idx = 0 ;
271+ const MAX_HINTS : usize = 3 ;
272272
273- loop {
274- let mut remaining_hints = false ;
273+ zip_nested_vectors ( phantom_hints, MAX_HINTS )
275274
276- for hints in phantom_hints. iter ( ) {
277- if invoice_hints. len ( ) == 3 {
278- return invoice_hints
279- }
280-
281- if hint_idx < hints. len ( ) {
282- invoice_hints. push ( hints[ hint_idx] . clone ( ) ) ;
283- remaining_hints = true
284- }
285- }
286-
287- if !remaining_hints {
288- return invoice_hints
289- }
275+ }
290276
291- hint_idx +=1 ;
292- }
277+ // Zip multiple nested vectors
278+ // Similar to the zip method on a vector, it combines the vectors by index - zero index comes first
279+ // then second, etc.
280+ // The difference is that this function handles many or just one vector, whereas the builtin method
281+ // works on just two vectors.
282+ fn zip_nested_vectors < T : Clone > ( vecs : Vec < Vec < T > > , result_size : usize ) -> impl Iterator < Item = T > {
283+ let max_vector_length: usize = vecs. iter ( ) . map ( |x| x. len ( ) ) . max ( ) . unwrap ( ) ;
284+ let mut hint_index = 0 ;
285+ let mut vector_index = 0 ;
286+ let number_inner_vectors: usize = vecs. len ( ) ;
287+ let mut total_hints_returned = 0 ;
288+
289+ core:: iter:: from_fn ( move || loop {
290+ let return_value = loop {
291+ if total_hints_returned == result_size || hint_index == max_vector_length {
292+ break None ;
293+ } ;
294+ let my_value =
295+ if vecs[ vector_index] . len ( ) != 0 && vecs[ vector_index] . len ( ) >= hint_index {
296+ Some ( vecs[ vector_index] [ hint_index] . clone ( ) )
297+ } else {
298+ None // no value retrieved - continue looping
299+ } ;
300+ vector_index += 1 ;
301+ if hint_index < max_vector_length && vector_index == number_inner_vectors {
302+ vector_index = 0 ;
303+ hint_index += 1 ;
304+ } ;
305+ if !my_value. is_none ( ) {
306+ total_hints_returned += 1 ;
307+ break my_value;
308+ } ;
309+ } ;
310+ return return_value;
311+ } )
293312}
294313
295314#[ cfg( feature = "std" ) ]
@@ -777,7 +796,7 @@ mod test {
777796 use lightning:: routing:: router:: { PaymentParameters , RouteParameters } ;
778797 use lightning:: util:: test_utils;
779798 use lightning:: util:: config:: UserConfig ;
780- use crate :: utils:: create_invoice_from_channelmanager_and_duration_since_epoch;
799+ use crate :: utils:: { create_invoice_from_channelmanager_and_duration_since_epoch, zip_nested_vectors } ;
781800 use std:: collections:: HashSet ;
782801
783802 #[ test]
@@ -1886,4 +1905,106 @@ mod test {
18861905 _ => panic ! ( ) ,
18871906 }
18881907 }
1908+
1909+
1910+ #[ test]
1911+ fn test_zip_nested_vectors ( ) {
1912+ const TEST_RESULT_SIZE : usize = 3 ;
1913+
1914+ // two nested vectors
1915+ let a = vec ! [ vec![ "a0" , "b0" , "c0" ] , vec![ "a1" , "b1" ] ] ;
1916+ let result = zip_nested_vectors ( a, TEST_RESULT_SIZE ) . collect :: < Vec < _ > > ( ) ;
1917+
1918+ let expected = vec ! [ "a0" , "a1" , "b0" ] ;
1919+ assert_eq ! ( expected, result) ;
1920+
1921+ // test single nested vector
1922+ let a = vec ! [ vec![ "a0" , "b0" , "c0" ] ] ;
1923+ let result = zip_nested_vectors ( a, TEST_RESULT_SIZE ) . collect :: < Vec < _ > > ( ) ;
1924+
1925+ let expected = vec ! [ "a0" , "b0" , "c0" ] ;
1926+ assert_eq ! ( expected, result) ;
1927+
1928+ // test second vector with only one element
1929+ let a = vec ! [ vec![ "a0" , "b0" , "c0" ] , vec![ "a1" ] ] ;
1930+ let result = zip_nested_vectors ( a, TEST_RESULT_SIZE ) . collect :: < Vec < _ > > ( ) ;
1931+
1932+ let expected = vec ! [ "a0" , "a1" , "b0" ] ;
1933+ assert_eq ! ( expected, result) ;
1934+
1935+ // test three nestend vectors
1936+ let a = vec ! [ vec![ "a0" ] , vec![ "a1" , "b1" , "c1" ] , vec![ "a2" ] ] ;
1937+ let result = zip_nested_vectors ( a, TEST_RESULT_SIZE ) . collect :: < Vec < _ > > ( ) ;
1938+
1939+ let expected = vec ! [ "a0" , "a1" , "a2" ] ;
1940+ assert_eq ! ( expected, result) ;
1941+
1942+ // test single nested vector with a single value
1943+ let a = vec ! [ vec![ "a0" ] ] ;
1944+ let result = zip_nested_vectors ( a, TEST_RESULT_SIZE ) . collect :: < Vec < _ > > ( ) ;
1945+
1946+ let expected = vec ! [ "a0" ] ;
1947+ assert_eq ! ( expected, result) ;
1948+
1949+ // test single empty nested vector
1950+ let a: Vec < Vec < & str > > = vec ! [ vec![ ] ] ;
1951+ let result = zip_nested_vectors ( a, TEST_RESULT_SIZE ) . collect :: < Vec < _ > > ( ) ;
1952+ let expected: Vec < & str > = vec ! [ ] ;
1953+
1954+ assert_eq ! ( expected, result) ;
1955+
1956+ // test first nested vector is empty
1957+ let a = vec ! [ vec![ ] , vec![ "a1" , "b1" , "c1" ] ] ;
1958+ let result = zip_nested_vectors ( a, TEST_RESULT_SIZE ) . collect :: < Vec < _ > > ( ) ;
1959+
1960+ let expected = vec ! [ "a1" , "b1" , "c1" ] ;
1961+ assert_eq ! ( expected, result) ;
1962+
1963+ // test two empty vectors
1964+ let a: Vec < Vec < & str > > = vec ! [ vec![ ] , vec![ ] ] ;
1965+ let result = zip_nested_vectors ( a, TEST_RESULT_SIZE ) . collect :: < Vec < _ > > ( ) ;
1966+
1967+ let expected: Vec < & str > = vec ! [ ] ;
1968+ assert_eq ! ( expected, result) ;
1969+
1970+ // test an empty vector amongst other filled vectors
1971+ let a = vec ! [
1972+ vec![ "a0" , "b0" , "c0" ] ,
1973+ vec![ ] ,
1974+ vec![ "a1" , "b1" , "c1" ] ,
1975+ vec![ "a2" , "b2" , "c2" ] ,
1976+ ] ;
1977+ let result = zip_nested_vectors ( a, TEST_RESULT_SIZE ) . collect :: < Vec < _ > > ( ) ;
1978+
1979+ let expected = vec ! [ "a0" , "a1" , "a2" ] ;
1980+ assert_eq ! ( expected, result) ;
1981+
1982+ // test a filled vector between two empty vectors
1983+ let a = vec ! [ vec![ ] , vec![ "a1" , "b1" , "c1" ] , vec![ ] ] ;
1984+ let result = zip_nested_vectors ( a, TEST_RESULT_SIZE ) . collect :: < Vec < _ > > ( ) ;
1985+
1986+ let expected = vec ! [ "a1" , "b1" , "c1" ] ;
1987+ assert_eq ! ( expected, result) ;
1988+
1989+ // test an empty vector at the end of the vectors
1990+ let a = vec ! [ vec![ "a0" , "b0" , "c0" ] , vec![ ] ] ;
1991+ let result = zip_nested_vectors ( a, TEST_RESULT_SIZE ) . collect :: < Vec < _ > > ( ) ;
1992+
1993+ let expected = vec ! [ "a0" , "b0" , "c0" ] ;
1994+ assert_eq ! ( expected, result) ;
1995+
1996+ // test multiple empty vectors amongst multiple filled vectors
1997+ let a = vec ! [
1998+ vec![ ] ,
1999+ vec![ "a1" , "b1" , "c1" ] ,
2000+ vec![ ] ,
2001+ vec![ "a3" , "b3" ] ,
2002+ vec![ ] ,
2003+ ] ;
2004+
2005+ let result = zip_nested_vectors ( a, TEST_RESULT_SIZE ) . collect :: < Vec < _ > > ( ) ;
2006+
2007+ let expected = vec ! [ "a1" , "a3" , "b1" ] ;
2008+ assert_eq ! ( expected, result) ;
2009+ }
18892010}
0 commit comments