@@ -187,11 +187,41 @@ pub fn generate_test_code(args: FreenetTestArgs, input_fn: ItemFn) -> Result<Tok
187187/// Generate node configuration setup code
188188fn generate_node_setup ( args : & FreenetTestArgs ) -> TokenStream {
189189 let mut setup_code = Vec :: new ( ) ;
190+ let node_count = args. nodes . len ( ) ;
191+ let node_count_lit = LitInt :: new ( & node_count. to_string ( ) , proc_macro2:: Span :: call_site ( ) ) ;
192+
193+ // First, generate all keypairs upfront and verify uniqueness
194+ // This prevents rare RNG collisions from causing confusing test failures
195+ setup_code. push ( quote ! {
196+ // Generate all transport keypairs upfront
197+ let __keypairs: Vec <freenet:: dev_tool:: TransportKeypair > = ( 0 ..#node_count_lit)
198+ . map( |_| freenet:: dev_tool:: TransportKeypair :: new( ) )
199+ . collect( ) ;
200+
201+ // Verify all public keys are unique (sanity check against RNG issues)
202+ {
203+ let mut seen_keys = std:: collections:: HashSet :: new( ) ;
204+ for ( idx, keypair) in __keypairs. iter( ) . enumerate( ) {
205+ let key_str = format!( "{}" , keypair. public( ) ) ;
206+ if !seen_keys. insert( key_str. clone( ) ) {
207+ return Err ( anyhow:: anyhow!(
208+ "FATAL: Generated duplicate transport keypair for node {} (key: {}). \
209+ This indicates an RNG issue in the test environment. \
210+ Please report this to the Freenet developers.",
211+ idx,
212+ key_str
213+ ) ) ;
214+ }
215+ }
216+ tracing:: debug!( "Verified {} unique transport keypairs" , #node_count_lit) ;
217+ }
218+ } ) ;
190219
191220 for ( idx, node_label) in args. nodes . iter ( ) . enumerate ( ) {
192221 let config_var = format_ident ! ( "config_{}" , idx) ;
193222 let temp_var = format_ident ! ( "temp_{}" , idx) ;
194223 let is_gw = is_gateway ( args, node_label, idx) ;
224+ let idx_lit = LitInt :: new ( & idx. to_string ( ) , proc_macro2:: Span :: call_site ( ) ) ;
195225
196226 if is_gw {
197227 // Gateway node configuration
@@ -203,7 +233,7 @@ fn generate_node_setup(args: &FreenetTestArgs) -> TokenStream {
203233 let #ws_port_var_local = freenet:: test_utils:: reserve_local_port( ) ?;
204234 let ( #config_var, #temp_var) = {
205235 let temp_dir = tempfile:: tempdir( ) ?;
206- let key = freenet :: dev_tool :: TransportKeypair :: new ( ) ;
236+ let key = & __keypairs [ #idx_lit ] ;
207237 let transport_keypair = temp_dir. path( ) . join( "private.pem" ) ;
208238 key. save( & transport_keypair) ?;
209239 key. public( ) . save( temp_dir. path( ) . join( "public.pem" ) ) ?;
@@ -278,6 +308,7 @@ fn generate_node_setup(args: &FreenetTestArgs) -> TokenStream {
278308 let config_var = format_ident ! ( "config_{}" , idx) ;
279309 let temp_var = format_ident ! ( "temp_{}" , idx) ;
280310 let is_gw = is_gateway ( args, node_label, idx) ;
311+ let idx_lit = LitInt :: new ( & idx. to_string ( ) , proc_macro2:: Span :: call_site ( ) ) ;
281312
282313 if !is_gw {
283314 let location_expr = node_location ( args, idx, node_label) ;
@@ -322,7 +353,7 @@ fn generate_node_setup(args: &FreenetTestArgs) -> TokenStream {
322353 let #ws_port_var_local = freenet:: test_utils:: reserve_local_port( ) ?;
323354 let ( #config_var, #temp_var) = {
324355 let temp_dir = tempfile:: tempdir( ) ?;
325- let key = freenet :: dev_tool :: TransportKeypair :: new ( ) ;
356+ let key = & __keypairs [ #idx_lit ] ;
326357 let transport_keypair = temp_dir. path( ) . join( "private.pem" ) ;
327358 key. save( & transport_keypair) ?;
328359 key. public( ) . save( temp_dir. path( ) . join( "public.pem" ) ) ?;
0 commit comments