@@ -18,6 +18,7 @@ use lightning::util::logger::Logger;
18
18
use secp256k1:: PublicKey ;
19
19
use core:: ops:: Deref ;
20
20
use core:: time:: Duration ;
21
+ use core:: iter:: Iterator ;
21
22
22
23
/// Utility to create an invoice that can be paid to one of multiple nodes, or a "phantom invoice."
23
24
/// See [`PhantomKeysManager`] for more information on phantom node payments.
@@ -229,7 +230,7 @@ where
229
230
///
230
231
/// [`PhantomKeysManager`]: lightning::sign::PhantomKeysManager
231
232
fn 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 >
233
234
where
234
235
L :: Target : Logger ,
235
236
{
@@ -267,29 +268,47 @@ where
267
268
// the hints across our real nodes we add one hint from each in turn until no node has any hints
268
269
// left (if one node has more hints than any other, these will accumulate at the end of the
269
270
// vector).
270
- let mut invoice_hints: Vec < RouteHint > = Vec :: new ( ) ;
271
- let mut hint_idx = 0 ;
271
+ const MAX_HINTS : usize = 3 ;
272
272
273
- loop {
274
- let mut remaining_hints = false ;
273
+ zip_nested_vectors ( phantom_hints, MAX_HINTS )
275
274
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
+ }
290
276
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
+ } )
293
312
}
294
313
295
314
#[ cfg( feature = "std" ) ]
@@ -777,7 +796,7 @@ mod test {
777
796
use lightning:: routing:: router:: { PaymentParameters , RouteParameters } ;
778
797
use lightning:: util:: test_utils;
779
798
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 } ;
781
800
use std:: collections:: HashSet ;
782
801
783
802
#[ test]
@@ -1886,4 +1905,106 @@ mod test {
1886
1905
_ => panic ! ( ) ,
1887
1906
}
1888
1907
}
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
+ }
1889
2010
}
0 commit comments