@@ -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,48 @@ 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+ // todo : change name
295+ let hint_value =
296+ if vecs[ vector_index] . len ( ) != 0 && vecs[ vector_index] . len ( ) > hint_index {
297+ Some ( vecs[ vector_index] [ hint_index] . clone ( ) )
298+ } else {
299+ None // no value retrieved - continue looping
300+ } ;
301+ vector_index += 1 ;
302+ if hint_index < max_vector_length && vector_index == number_inner_vectors {
303+ vector_index = 0 ;
304+ hint_index += 1 ;
305+ } ;
306+ if !hint_value. is_none ( ) {
307+ total_hints_returned += 1 ;
308+ break hint_value;
309+ } ;
310+ } ;
311+ return return_value;
312+ } )
293313}
294314
295315#[ cfg( feature = "std" ) ]
@@ -777,7 +797,7 @@ mod test {
777797 use lightning:: routing:: router:: { PaymentParameters , RouteParameters } ;
778798 use lightning:: util:: test_utils;
779799 use lightning:: util:: config:: UserConfig ;
780- use crate :: utils:: create_invoice_from_channelmanager_and_duration_since_epoch;
800+ use crate :: utils:: { create_invoice_from_channelmanager_and_duration_since_epoch, zip_nested_vectors } ;
781801 use std:: collections:: HashSet ;
782802
783803 #[ test]
@@ -1886,4 +1906,114 @@ mod test {
18861906 _ => panic ! ( ) ,
18871907 }
18881908 }
1909+
1910+
1911+ #[ test]
1912+ fn test_zip_nested_vectors ( ) {
1913+ const TEST_RESULT_SIZE : usize = 3 ;
1914+
1915+ // two nested vectors
1916+ let a = vec ! [ vec![ "a0" , "b0" , "c0" ] , vec![ "a1" , "b1" ] ] ;
1917+ let result = zip_nested_vectors ( a, TEST_RESULT_SIZE ) . collect :: < Vec < _ > > ( ) ;
1918+
1919+ let expected = vec ! [ "a0" , "a1" , "b0" ] ;
1920+ assert_eq ! ( expected, result) ;
1921+
1922+ // test single nested vector
1923+ let a = vec ! [ vec![ "a0" , "b0" , "c0" ] ] ;
1924+ let result = zip_nested_vectors ( a, TEST_RESULT_SIZE ) . collect :: < Vec < _ > > ( ) ;
1925+
1926+ let expected = vec ! [ "a0" , "b0" , "c0" ] ;
1927+ assert_eq ! ( expected, result) ;
1928+
1929+ // test second vector with only one element
1930+ let a = vec ! [ vec![ "a0" , "b0" , "c0" ] , vec![ "a1" ] ] ;
1931+ let result = zip_nested_vectors ( a, TEST_RESULT_SIZE ) . collect :: < Vec < _ > > ( ) ;
1932+
1933+ let expected = vec ! [ "a0" , "a1" , "b0" ] ;
1934+ assert_eq ! ( expected, result) ;
1935+
1936+ // test three nestend vectors
1937+ let a = vec ! [ vec![ "a0" ] , vec![ "a1" , "b1" , "c1" ] , vec![ "a2" ] ] ;
1938+ let result = zip_nested_vectors ( a, TEST_RESULT_SIZE ) . collect :: < Vec < _ > > ( ) ;
1939+
1940+ let expected = vec ! [ "a0" , "a1" , "a2" ] ;
1941+ assert_eq ! ( expected, result) ;
1942+
1943+ // test single nested vector with a single value
1944+ let a = vec ! [ vec![ "a0" ] ] ;
1945+ let result = zip_nested_vectors ( a, TEST_RESULT_SIZE ) . collect :: < Vec < _ > > ( ) ;
1946+
1947+ let expected = vec ! [ "a0" ] ;
1948+ assert_eq ! ( expected, result) ;
1949+
1950+ // test single empty nested vector
1951+ let a: Vec < Vec < & str > > = vec ! [ vec![ ] ] ;
1952+ let result = zip_nested_vectors ( a, TEST_RESULT_SIZE ) . collect :: < Vec < _ > > ( ) ;
1953+ let expected: Vec < & str > = vec ! [ ] ;
1954+
1955+ assert_eq ! ( expected, result) ;
1956+
1957+ // test first nested vector is empty
1958+ let a = vec ! [ vec![ ] , vec![ "a1" , "b1" , "c1" ] ] ;
1959+ let result = zip_nested_vectors ( a, TEST_RESULT_SIZE ) . collect :: < Vec < _ > > ( ) ;
1960+
1961+ let expected = vec ! [ "a1" , "b1" , "c1" ] ;
1962+ assert_eq ! ( expected, result) ;
1963+
1964+ // test two empty vectors
1965+ let a: Vec < Vec < & str > > = vec ! [ vec![ ] , vec![ ] ] ;
1966+ let result = zip_nested_vectors ( a, TEST_RESULT_SIZE ) . collect :: < Vec < _ > > ( ) ;
1967+
1968+ let expected: Vec < & str > = vec ! [ ] ;
1969+ assert_eq ! ( expected, result) ;
1970+
1971+ // test an empty vector amongst other filled vectors
1972+ let a = vec ! [
1973+ vec![ "a0" , "b0" , "c0" ] ,
1974+ vec![ ] ,
1975+ vec![ "a1" , "b1" , "c1" ] ,
1976+ vec![ "a2" , "b2" , "c2" ] ,
1977+ ] ;
1978+ let result = zip_nested_vectors ( a, TEST_RESULT_SIZE ) . collect :: < Vec < _ > > ( ) ;
1979+
1980+ let expected = vec ! [ "a0" , "a1" , "a2" ] ;
1981+ assert_eq ! ( expected, result) ;
1982+
1983+ // test a filled vector between two empty vectors
1984+ let a = vec ! [ vec![ ] , vec![ "a1" , "b1" , "c1" ] , vec![ ] ] ;
1985+ let result = zip_nested_vectors ( a, TEST_RESULT_SIZE ) . collect :: < Vec < _ > > ( ) ;
1986+
1987+ let expected = vec ! [ "a1" , "b1" , "c1" ] ;
1988+ assert_eq ! ( expected, result) ;
1989+
1990+ // test an empty vector at the end of the vectors
1991+ let a = vec ! [ vec![ "a0" , "b0" , "c0" ] , vec![ ] ] ;
1992+ let result = zip_nested_vectors ( a, TEST_RESULT_SIZE ) . collect :: < Vec < _ > > ( ) ;
1993+
1994+ let expected = vec ! [ "a0" , "b0" , "c0" ] ;
1995+ assert_eq ! ( expected, result) ;
1996+
1997+ // test multiple empty vectors amongst multiple filled vectors
1998+ let a = vec ! [
1999+ vec![ ] ,
2000+ vec![ "a1" , "b1" , "c1" ] ,
2001+ vec![ ] ,
2002+ vec![ "a3" , "b3" ] ,
2003+ vec![ ] ,
2004+ ] ;
2005+
2006+ let result = zip_nested_vectors ( a, TEST_RESULT_SIZE ) . collect :: < Vec < _ > > ( ) ;
2007+
2008+ let expected = vec ! [ "a1" , "a3" , "b1" ] ;
2009+ assert_eq ! ( expected, result) ;
2010+
2011+ // test one element in the first nested vectore and two elements in the second nested
2012+ // vector
2013+ let a = vec ! [ vec![ "a0" ] , vec![ "a1" , "b1" ] ] ;
2014+ let result = zip_nested_vectors ( a, TEST_RESULT_SIZE ) . collect :: < Vec < _ > > ( ) ;
2015+
2016+ let expected = vec ! [ "a0" , "a1" , "b1" ] ;
2017+ assert_eq ! ( expected, result) ;
2018+ }
18892019}
0 commit comments