13
13
//
14
14
// You should have received a copy of the GNU General Public License
15
15
// along with this program. If not, see <http://www.gnu.org/licenses/>.
16
- use std:: collections:: HashMap ;
16
+ use std:: collections:: { HashMap , HashSet } ;
17
17
use std:: sync:: atomic:: AtomicU64 ;
18
- use std:: sync:: Arc ;
18
+ use std:: sync:: { Arc , Mutex } ;
19
19
20
20
use clarity:: vm:: costs:: ExecutionCost ;
21
21
use clarity:: vm:: database:: BurnStateDB ;
22
22
use clarity:: vm:: events:: STXEventType ;
23
23
use clarity:: vm:: types:: PrincipalData ;
24
24
use clarity:: vm:: { ClarityName , ClarityVersion , ContractName , Value } ;
25
25
use lazy_static:: lazy_static;
26
- use rand:: RngCore ;
26
+ use rand:: Rng ;
27
27
use stacks:: chainstate:: burn:: ConsensusHash ;
28
28
use stacks:: chainstate:: stacks:: db:: StacksChainState ;
29
29
use stacks:: chainstate:: stacks:: events:: StacksTransactionEvent ;
@@ -99,6 +99,34 @@ lazy_static! {
99
99
) ;
100
100
}
101
101
102
+ lazy_static ! {
103
+ static ref USED_PORTS : Mutex <HashSet <u16 >> = Mutex :: new( HashSet :: new( ) ) ;
104
+ }
105
+
106
+ /// Generate a random port number between 1024 and 65534 (inclusive) and insert it into the USED_PORTS set.
107
+ /// Returns the generated port number.
108
+ pub fn gen_random_port ( ) -> u16 {
109
+ let mut rng = rand:: thread_rng ( ) ;
110
+ let range_len = ( 1024 ..u16:: MAX ) . len ( ) ;
111
+ loop {
112
+ assert ! (
113
+ USED_PORTS . lock( ) . unwrap( ) . len( ) < range_len,
114
+ "No more available ports"
115
+ ) ;
116
+ let port = rng. gen_range ( 1024 ..u16:: MAX ) ; // use a non-privileged port between 1024 and 65534
117
+ if insert_new_port ( port) {
118
+ return port;
119
+ }
120
+ }
121
+ }
122
+
123
+ // Add a port to the USED_PORTS set. This is used to ensure that we don't try to bind to the same port in tests
124
+ // Returns true if the port was inserted, false if it was already in the set.
125
+ pub fn insert_new_port ( port : u16 ) -> bool {
126
+ let mut ports = USED_PORTS . lock ( ) . unwrap ( ) ;
127
+ ports. insert ( port)
128
+ }
129
+
102
130
pub fn serialize_sign_sponsored_sig_tx_anchor_mode_version (
103
131
payload : TransactionPayload ,
104
132
sender : & StacksPrivateKey ,
@@ -294,14 +322,13 @@ pub fn new_test_conf() -> Config {
294
322
// secretKey: "b1cf9cee5083f421c84d7cb53be5edf2801c3c78d63d53917aee0bdc8bd160ee01",
295
323
// publicKey: "03e2ed46873d0db820e8c6001aabc082d72b5b900b53b7a1b9714fe7bde3037b81",
296
324
// stacksAddress: "ST2VHM28V9E5QCRD6C73215KAPSBKQGPWTEE5CMQT"
297
- let mut rng = rand:: thread_rng ( ) ;
298
- let mut buf = [ 0u8 ; 8 ] ;
299
- rng. fill_bytes ( & mut buf) ;
325
+ let rpc_port = gen_random_port ( ) ;
326
+ let p2p_port = gen_random_port ( ) ;
300
327
301
328
let mut conf = Config :: default ( ) ;
302
329
conf. node . working_dir = format ! (
303
330
"/tmp/stacks-node-tests/integrations-neon/{}-{}" ,
304
- to_hex( & buf ) ,
331
+ to_hex( format! ( "{rpc_port}{p2p_port}" ) . as_bytes ( ) ) ,
305
332
get_epoch_time_secs( )
306
333
) ;
307
334
conf. node . seed =
@@ -313,19 +340,17 @@ pub fn new_test_conf() -> Config {
313
340
314
341
conf. burnchain . epochs = Some ( StacksEpoch :: all ( 0 , 0 , 0 ) ) ;
315
342
316
- let rpc_port = u16:: from_be_bytes ( buf[ 0 ..2 ] . try_into ( ) . unwrap ( ) ) . saturating_add ( 1025 ) - 1 ; // use a non-privileged port between 1024 and 65534
317
- let p2p_port = u16:: from_be_bytes ( buf[ 2 ..4 ] . try_into ( ) . unwrap ( ) ) . saturating_add ( 1025 ) - 1 ; // use a non-privileged port between 1024 and 65534
318
-
319
343
let localhost = "127.0.0.1" ;
320
- conf. node . rpc_bind = format ! ( "{}:{}" , localhost , rpc_port ) ;
321
- conf. node . p2p_bind = format ! ( "{}:{}" , localhost , p2p_port ) ;
322
- conf. node . data_url = format ! ( "http://{}:{}" , localhost , rpc_port ) ;
323
- conf. node . p2p_address = format ! ( "{}:{}" , localhost , p2p_port ) ;
344
+ conf. node . rpc_bind = format ! ( "{localhost }:{rpc_port}" ) ;
345
+ conf. node . p2p_bind = format ! ( "{localhost }:{p2p_port}" ) ;
346
+ conf. node . data_url = format ! ( "http://{localhost }:{rpc_port}" ) ;
347
+ conf. node . p2p_address = format ! ( "{localhost }:{p2p_port}" ) ;
324
348
conf
325
349
}
326
350
327
351
/// Randomly change the config's network ports to new ports.
328
352
pub fn set_random_binds ( config : & mut Config ) {
353
+ // Just in case prior config was not created with `new_test_conf`, we need to add the prior generated ports
329
354
let prior_rpc_port: u16 = config
330
355
. node
331
356
. rpc_bind
@@ -342,16 +367,10 @@ pub fn set_random_binds(config: &mut Config) {
342
367
. unwrap ( )
343
368
. parse ( )
344
369
. unwrap ( ) ;
345
- let ( rpc_port, p2p_port) = loop {
346
- let mut rng = rand:: thread_rng ( ) ;
347
- let mut buf = [ 0u8 ; 8 ] ;
348
- rng. fill_bytes ( & mut buf) ;
349
- let rpc_port = u16:: from_be_bytes ( buf[ 0 ..2 ] . try_into ( ) . unwrap ( ) ) . saturating_add ( 1025 ) - 1 ; // use a non-privileged port between 1024 and 65534
350
- let p2p_port = u16:: from_be_bytes ( buf[ 2 ..4 ] . try_into ( ) . unwrap ( ) ) . saturating_add ( 1025 ) - 1 ; // use a non-privileged port between 1024 and 65534
351
- if rpc_port != prior_rpc_port && p2p_port != prior_p2p_port {
352
- break ( rpc_port, p2p_port) ;
353
- }
354
- } ;
370
+ insert_new_port ( prior_rpc_port) ;
371
+ insert_new_port ( prior_p2p_port) ;
372
+ let rpc_port = gen_random_port ( ) ;
373
+ let p2p_port = gen_random_port ( ) ;
355
374
let localhost = "127.0.0.1" ;
356
375
config. node . rpc_bind = format ! ( "{}:{}" , localhost, rpc_port) ;
357
376
config. node . p2p_bind = format ! ( "{}:{}" , localhost, p2p_port) ;
0 commit comments