Skip to content

Commit 4eb625a

Browse files
committed
chore: test that a peer with a stale view will not be acknowledged, but it will once its view converges
1 parent adba578 commit 4eb625a

File tree

1 file changed

+195
-1
lines changed
  • stackslib/src/net/stackerdb/tests

1 file changed

+195
-1
lines changed

stackslib/src/net/stackerdb/tests/sync.rs

Lines changed: 195 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,12 @@ use stacks_common::address::{
2626
AddressHashMode, C32_ADDRESS_VERSION_MAINNET_MULTISIG, C32_ADDRESS_VERSION_MAINNET_SINGLESIG,
2727
};
2828
use stacks_common::types::chainstate::{
29-
ConsensusHash, StacksAddress, StacksPrivateKey, StacksPublicKey,
29+
BlockHeaderHash, ConsensusHash, StacksAddress, StacksPrivateKey, StacksPublicKey,
3030
};
3131
use stacks_common::util::hash::{Hash160, Sha512Trunc256Sum};
3232
use stacks_common::util::secp256k1::{MessageSignature, Secp256k1PrivateKey};
3333

34+
use crate::chainstate::burn::db::sortdb::SortitionDB;
3435
use crate::net::relay::Relayer;
3536
use crate::net::stackerdb::db::SlotValidation;
3637
use crate::net::stackerdb::{StackerDBConfig, StackerDBs};
@@ -280,6 +281,199 @@ fn test_stackerdb_replica_2_neighbors_1_chunk() {
280281
})
281282
}
282283

284+
#[test]
285+
fn test_stackerdb_replica_2_neighbors_1_chunk_stale_view() {
286+
with_timeout(600, || {
287+
std::env::set_var("STACKS_TEST_DISABLE_EDGE_TRIGGER_TEST", "1");
288+
let mut peer_1_config = TestPeerConfig::from_port(BASE_PORT);
289+
let mut peer_2_config = TestPeerConfig::from_port(BASE_PORT + 2);
290+
291+
peer_1_config.allowed = -1;
292+
peer_2_config.allowed = -1;
293+
294+
// short-lived walks...
295+
peer_1_config.connection_opts.walk_max_duration = 10;
296+
peer_2_config.connection_opts.walk_max_duration = 10;
297+
298+
// peer 1 crawls peer 2, and peer 2 crawls peer 1
299+
peer_1_config.add_neighbor(&peer_2_config.to_neighbor());
300+
peer_2_config.add_neighbor(&peer_1_config.to_neighbor());
301+
302+
// set up stacker DBs for both peers
303+
let idx_1 = add_stackerdb(&mut peer_1_config, Some(StackerDBConfig::template()));
304+
let idx_2 = add_stackerdb(&mut peer_2_config, Some(StackerDBConfig::template()));
305+
306+
let mut peer_1 = TestPeer::new(peer_1_config);
307+
let mut peer_2 = TestPeer::new(peer_2_config);
308+
309+
// peer 1 gets the DB
310+
setup_stackerdb(&mut peer_1, idx_1, true, 1);
311+
setup_stackerdb(&mut peer_2, idx_2, false, 1);
312+
313+
// verify that peer 1 got the data
314+
let peer_1_db_chunks = load_stackerdb(&peer_1, idx_1);
315+
assert_eq!(peer_1_db_chunks.len(), 1);
316+
assert_eq!(peer_1_db_chunks[0].0.slot_id, 0);
317+
assert_eq!(peer_1_db_chunks[0].0.slot_version, 1);
318+
assert!(peer_1_db_chunks[0].1.len() > 0);
319+
320+
// verify that peer 2 did NOT get the data
321+
let peer_2_db_chunks = load_stackerdb(&peer_2, idx_2);
322+
assert_eq!(peer_2_db_chunks.len(), 1);
323+
assert_eq!(peer_2_db_chunks[0].0.slot_id, 0);
324+
assert_eq!(peer_2_db_chunks[0].0.slot_version, 0);
325+
assert!(peer_2_db_chunks[0].1.len() == 0);
326+
327+
let peer_1_db_configs = peer_1.config.get_stacker_db_configs();
328+
let peer_2_db_configs = peer_2.config.get_stacker_db_configs();
329+
330+
// force peer 2 to have a stale view
331+
let (old_tip_ch, old_tip_bh) = {
332+
let sortdb = peer_1.sortdb();
333+
let (tip_bh, tip_ch) =
334+
SortitionDB::get_canonical_stacks_chain_tip_hash(sortdb.conn()).unwrap();
335+
SortitionDB::set_canonical_stacks_chain_tip(
336+
sortdb.conn(),
337+
&ConsensusHash([0x22; 20]),
338+
&BlockHeaderHash([0x33; 32]),
339+
45,
340+
)
341+
.unwrap();
342+
(tip_bh, tip_ch)
343+
};
344+
345+
let mut i = 0;
346+
let mut peer_1_stale = false;
347+
let mut peer_2_stale = false;
348+
loop {
349+
// run peer network state-machines
350+
peer_1.network.stacker_db_configs = peer_1_db_configs.clone();
351+
peer_2.network.stacker_db_configs = peer_2_db_configs.clone();
352+
353+
let res_1 = peer_1.step_with_ibd(false);
354+
let res_2 = peer_2.step_with_ibd(false);
355+
356+
if let Ok(mut res) = res_1 {
357+
for sync_res in res.stacker_db_sync_results.iter() {
358+
assert_eq!(sync_res.chunks_to_store.len(), 0);
359+
if sync_res.stale.len() > 0 {
360+
peer_1_stale = true;
361+
}
362+
}
363+
Relayer::process_stacker_db_chunks(
364+
&mut peer_1.network.stackerdbs,
365+
&peer_1_db_configs,
366+
res.stacker_db_sync_results,
367+
None,
368+
)
369+
.unwrap();
370+
Relayer::process_pushed_stacker_db_chunks(
371+
&mut peer_1.network.stackerdbs,
372+
&peer_1_db_configs,
373+
&mut res.unhandled_messages,
374+
None,
375+
)
376+
.unwrap();
377+
}
378+
379+
if let Ok(mut res) = res_2 {
380+
for sync_res in res.stacker_db_sync_results.iter() {
381+
assert_eq!(sync_res.chunks_to_store.len(), 0);
382+
if sync_res.stale.len() > 0 {
383+
peer_2_stale = true;
384+
}
385+
}
386+
Relayer::process_stacker_db_chunks(
387+
&mut peer_2.network.stackerdbs,
388+
&peer_2_db_configs,
389+
res.stacker_db_sync_results,
390+
None,
391+
)
392+
.unwrap();
393+
Relayer::process_pushed_stacker_db_chunks(
394+
&mut peer_2.network.stackerdbs,
395+
&peer_2_db_configs,
396+
&mut res.unhandled_messages,
397+
None,
398+
)
399+
.unwrap();
400+
}
401+
402+
if peer_1_stale && peer_2_stale {
403+
break;
404+
}
405+
406+
i += 1;
407+
}
408+
409+
debug!("Completed stacker DB stale detection in {} step(s)", i);
410+
411+
// fix and re-run
412+
{
413+
let sortdb = peer_1.sortdb();
414+
SortitionDB::set_canonical_stacks_chain_tip(sortdb.conn(), &old_tip_ch, &old_tip_bh, 0)
415+
.unwrap();
416+
417+
// force chain view refresh
418+
peer_1.network.num_state_machine_passes = 0;
419+
}
420+
421+
let mut i = 0;
422+
loop {
423+
// run peer network state-machines
424+
peer_1.network.stacker_db_configs = peer_1_db_configs.clone();
425+
peer_2.network.stacker_db_configs = peer_2_db_configs.clone();
426+
427+
let res_1 = peer_1.step_with_ibd(false);
428+
let res_2 = peer_2.step_with_ibd(false);
429+
430+
if let Ok(mut res) = res_1 {
431+
Relayer::process_stacker_db_chunks(
432+
&mut peer_1.network.stackerdbs,
433+
&peer_1_db_configs,
434+
res.stacker_db_sync_results,
435+
None,
436+
)
437+
.unwrap();
438+
Relayer::process_pushed_stacker_db_chunks(
439+
&mut peer_1.network.stackerdbs,
440+
&peer_1_db_configs,
441+
&mut res.unhandled_messages,
442+
None,
443+
)
444+
.unwrap();
445+
}
446+
447+
if let Ok(mut res) = res_2 {
448+
Relayer::process_stacker_db_chunks(
449+
&mut peer_2.network.stackerdbs,
450+
&peer_2_db_configs,
451+
res.stacker_db_sync_results,
452+
None,
453+
)
454+
.unwrap();
455+
Relayer::process_pushed_stacker_db_chunks(
456+
&mut peer_2.network.stackerdbs,
457+
&peer_2_db_configs,
458+
&mut res.unhandled_messages,
459+
None,
460+
)
461+
.unwrap();
462+
}
463+
464+
let db1 = load_stackerdb(&peer_1, idx_1);
465+
let db2 = load_stackerdb(&peer_2, idx_2);
466+
467+
if db1 == db2 {
468+
break;
469+
}
470+
i += 1;
471+
}
472+
473+
debug!("Completed stacker DB sync in {} step(s)", i);
474+
})
475+
}
476+
283477
#[test]
284478
#[ignore]
285479
fn test_stackerdb_replica_2_neighbors_10_chunks() {

0 commit comments

Comments
 (0)