@@ -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,48 @@ 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
+ // 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
+ } )
293
313
}
294
314
295
315
#[ cfg( feature = "std" ) ]
@@ -777,7 +797,7 @@ mod test {
777
797
use lightning:: routing:: router:: { PaymentParameters , RouteParameters } ;
778
798
use lightning:: util:: test_utils;
779
799
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 } ;
781
801
use std:: collections:: HashSet ;
782
802
783
803
#[ test]
@@ -1886,4 +1906,114 @@ mod test {
1886
1906
_ => panic ! ( ) ,
1887
1907
}
1888
1908
}
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
+ }
1889
2019
}
0 commit comments