mirror of
https://github.com/alexgo-io/stacks-puppet-node.git
synced 2026-06-18 11:59:24 +08:00
chore: expand test coverage to cover the state machine's behavior -- both the state machine itself and the nakamoto work state machine
This commit is contained in:
@@ -633,7 +633,7 @@ fn test_sync_inv_set_blocks_microblocks_available() {
|
||||
let nk = peer_1.to_neighbor().addr;
|
||||
|
||||
let sortdb = peer_1.sortdb.take().unwrap();
|
||||
peer_1.network.init_inv_sync(&sortdb);
|
||||
peer_1.network.init_inv_sync_epoch2x(&sortdb);
|
||||
match peer_1.network.inv_state {
|
||||
Some(ref mut inv) => {
|
||||
inv.add_peer(nk.clone(), true);
|
||||
|
||||
@@ -23,7 +23,9 @@ use std::thread::JoinHandle;
|
||||
use stacks_common::address::{AddressHashMode, C32_ADDRESS_VERSION_TESTNET_SINGLESIG};
|
||||
use stacks_common::codec::{read_next, StacksMessageCodec};
|
||||
use stacks_common::types::chainstate::{StacksAddress, StacksPrivateKey, StacksPublicKey};
|
||||
use stacks_common::types::net::PeerAddress;
|
||||
use stacks_common::types::StacksEpoch;
|
||||
use stacks_common::util::hash::Hash160;
|
||||
|
||||
use crate::chainstate::burn::db::sortdb::SortitionDB;
|
||||
use crate::chainstate::burn::ConsensusHash;
|
||||
@@ -40,12 +42,13 @@ use crate::chainstate::stacks::{
|
||||
};
|
||||
use crate::clarity::vm::types::StacksAddressExtensions;
|
||||
use crate::core::StacksEpochExtension;
|
||||
use crate::net::inv::nakamoto::InvGenerator;
|
||||
use crate::net::inv::nakamoto::{InvGenerator, NakamotoInvStateMachine, NakamotoTenureInv};
|
||||
use crate::net::neighbors::comms::NeighborComms;
|
||||
use crate::net::test::{TestEventObserver, TestPeer};
|
||||
use crate::net::tests::{NakamotoBootPlan, NakamotoBootStep, NakamotoBootTenure};
|
||||
use crate::net::{
|
||||
Error as NetError, GetNakamotoInvData, HandshakeData, NakamotoInvData, StacksMessage,
|
||||
StacksMessageType,
|
||||
Error as NetError, GetNakamotoInvData, HandshakeData, NakamotoInvData, NeighborAddress,
|
||||
PeerNetworkComms, StacksMessage, StacksMessageType,
|
||||
};
|
||||
use crate::stacks_common::types::Address;
|
||||
use crate::util_lib::db::Error as DBError;
|
||||
@@ -311,13 +314,16 @@ fn test_nakamoto_inv_10_extended_tenures_10_sortitions() {
|
||||
}
|
||||
}
|
||||
|
||||
fn make_nakamoto_peer_from_invs<'a>(
|
||||
/// NOTE: The second return value does _not_ need `<'a>`, since `observer` is never installed into
|
||||
/// the peers here. However, it appears unavoidable to the borrow-checker.
|
||||
fn make_nakamoto_peers_from_invs<'a>(
|
||||
test_name: &str,
|
||||
observer: &'a TestEventObserver,
|
||||
rc_len: u32,
|
||||
prepare_len: u32,
|
||||
bitvecs: Vec<Vec<bool>>,
|
||||
) -> TestPeer<'a> {
|
||||
num_peers: usize,
|
||||
) -> (TestPeer<'a>, Vec<TestPeer<'a>>) {
|
||||
for bitvec in bitvecs.iter() {
|
||||
assert_eq!(bitvec.len() as u32, rc_len);
|
||||
}
|
||||
@@ -392,10 +398,21 @@ fn make_nakamoto_peer_from_invs<'a>(
|
||||
let plan = NakamotoBootPlan::new(test_name)
|
||||
.with_private_key(private_key)
|
||||
.with_pox_constants(rc_len, prepare_len)
|
||||
.with_initial_balances(vec![(addr.into(), 1_000_000)]);
|
||||
.with_initial_balances(vec![(addr.into(), 1_000_000)])
|
||||
.with_extra_peers(num_peers);
|
||||
|
||||
let peer = plan.boot_into_nakamoto_peer(boot_tenures, Some(observer));
|
||||
peer
|
||||
let (peer, other_peers) = plan.boot_into_nakamoto_peers(boot_tenures, Some(observer));
|
||||
(peer, other_peers)
|
||||
}
|
||||
|
||||
fn make_nakamoto_peer_from_invs<'a>(
|
||||
test_name: &str,
|
||||
observer: &'a TestEventObserver,
|
||||
rc_len: u32,
|
||||
prepare_len: u32,
|
||||
bitvecs: Vec<Vec<bool>>,
|
||||
) -> TestPeer<'a> {
|
||||
make_nakamoto_peers_from_invs(test_name, observer, rc_len, prepare_len, bitvecs, 0).0
|
||||
}
|
||||
|
||||
fn check_inv_messages(
|
||||
@@ -434,6 +451,50 @@ fn check_inv_messages(
|
||||
}
|
||||
}
|
||||
|
||||
fn check_inv_state(
|
||||
bitvecs: Vec<Vec<bool>>,
|
||||
rc_len: u32,
|
||||
nakamoto_start_burn_height: u64,
|
||||
inv_state: &NakamotoTenureInv,
|
||||
) {
|
||||
for (i, (tenure_rc, tenure_inv)) in inv_state.tenures_inv.iter().enumerate() {
|
||||
for bit in 0..(rc_len as usize) {
|
||||
let msg_bit = if bit / 8 >= tenure_inv.len() {
|
||||
// only allowed at the end
|
||||
debug!(
|
||||
"bit = {}, tenure_rc = {}, tenure_inv = {:?}",
|
||||
bit, tenure_rc, &tenure_inv
|
||||
);
|
||||
assert_eq!(i, inv_state.tenures_inv.len() - 1);
|
||||
false
|
||||
} else {
|
||||
tenure_inv[bit / 8] & (1 << (bit % 8)) != 0
|
||||
};
|
||||
|
||||
let burn_block_height = (*tenure_rc as u64) * u64::from(rc_len) + (bit as u64);
|
||||
if burn_block_height < nakamoto_start_burn_height {
|
||||
// inv doesn't cover epoch 2
|
||||
assert!(
|
||||
!msg_bit,
|
||||
"Bit {} in tenure {} is set but is before nakamoto-start height {} ({})",
|
||||
bit, tenure_rc, nakamoto_start_burn_height, burn_block_height
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
let inv_offset: u64 = burn_block_height - nakamoto_start_burn_height;
|
||||
let bitvec_idx = (inv_offset / u64::from(rc_len)) as usize;
|
||||
let expected_bit = if bitvec_idx >= bitvecs.len() {
|
||||
false
|
||||
} else {
|
||||
bitvecs[bitvec_idx][(inv_offset % u64::from(rc_len)) as usize]
|
||||
};
|
||||
assert_eq!(msg_bit, expected_bit, "Bit {} in tenure {} is {}, but expected {}. burn_block_height = {}, inv_offset = {}, bitvec_idx = {}, nakamoto_start_burn_height = {}",
|
||||
bit, tenure_rc, msg_bit, expected_bit, burn_block_height, inv_offset, bitvec_idx, nakamoto_start_burn_height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nakamoto_invs_full() {
|
||||
let observer = TestEventObserver::new();
|
||||
@@ -566,22 +627,39 @@ fn test_nakamoto_invs_different_anchor_blocks() {
|
||||
|
||||
#[test]
|
||||
fn test_nakamoto_tenure_inv() {
|
||||
let mut nakamoto_inv = NakamotoTenureInv::new(100, 100);
|
||||
let na = NeighborAddress {
|
||||
addrbytes: PeerAddress([
|
||||
0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
|
||||
0x0e, 0x0f,
|
||||
]),
|
||||
port: 65535,
|
||||
public_key_hash: Hash160([0x11; 20]),
|
||||
};
|
||||
let mut nakamoto_inv = NakamotoTenureInv::new(100, 100, na);
|
||||
assert!(!nakamoto_inv.has_ith_tenure(0));
|
||||
assert!(!nakamoto_inv.has_ith_tenure(99));
|
||||
assert!(!nakamoto_inv.has_ith_tenure(100));
|
||||
assert_eq!(nakamoto_inv.num_reward_cycles(), 0);
|
||||
assert_eq!(nakamoto_inv.highest_reward_cycle(), 0);
|
||||
|
||||
let full_tenure = NakamotoInvData::bools_to_bitvec(vec![true; 100]);
|
||||
nakamoto_inv.merge_tenure_inv(full_tenure, 100, 1);
|
||||
let full_tenure = NakamotoInvData::bools_to_bitvec(&[true; 100]);
|
||||
let learned = nakamoto_inv.merge_tenure_inv(full_tenure.clone(), 100, 1);
|
||||
assert!(learned);
|
||||
|
||||
for i in 100..200 {
|
||||
let learned = nakamoto_inv.merge_tenure_inv(full_tenure, 100, 1);
|
||||
assert!(!learned);
|
||||
|
||||
debug!("nakamoto_inv = {:?}", &nakamoto_inv);
|
||||
for i in 0..200 {
|
||||
assert!(!nakamoto_inv.has_ith_tenure(i));
|
||||
}
|
||||
for i in 200..300 {
|
||||
assert!(nakamoto_inv.has_ith_tenure(i));
|
||||
}
|
||||
assert!(!nakamoto_inv.has_ith_tenure(99));
|
||||
assert!(!nakamoto_inv.has_ith_tenure(200));
|
||||
assert!(!nakamoto_inv.has_ith_tenure(201));
|
||||
assert_eq!(nakamoto_inv.num_reward_cycles(), 1);
|
||||
assert!(!nakamoto_inv.has_ith_tenure(199));
|
||||
assert!(nakamoto_inv.has_ith_tenure(200));
|
||||
assert!(!nakamoto_inv.has_ith_tenure(300));
|
||||
assert!(!nakamoto_inv.has_ith_tenure(301));
|
||||
assert_eq!(nakamoto_inv.highest_reward_cycle(), 1);
|
||||
|
||||
let mut partial_tenure_bools = vec![];
|
||||
for i in 0..100 {
|
||||
@@ -589,34 +667,43 @@ fn test_nakamoto_tenure_inv() {
|
||||
}
|
||||
|
||||
// has_ith_tenure() works (non-triial case)
|
||||
let partial_tenure = NakamotoInvData::bools_to_bitvec(partial_tenure_bools);
|
||||
nakamoto_inv.merge_tenure_inv(partial_tenure, 100, 2);
|
||||
let partial_tenure = NakamotoInvData::bools_to_bitvec(&partial_tenure_bools);
|
||||
let learned = nakamoto_inv.merge_tenure_inv(partial_tenure.clone(), 100, 2);
|
||||
assert!(learned);
|
||||
|
||||
for i in 200..300 {
|
||||
for i in 300..400 {
|
||||
assert_eq!(nakamoto_inv.has_ith_tenure(i), i % 2 == 0);
|
||||
}
|
||||
assert!(!nakamoto_inv.has_ith_tenure(99));
|
||||
assert!(!nakamoto_inv.has_ith_tenure(300));
|
||||
assert!(!nakamoto_inv.has_ith_tenure(301));
|
||||
assert_eq!(nakamoto_inv.num_reward_cycles(), 2);
|
||||
assert!(!nakamoto_inv.has_ith_tenure(199));
|
||||
assert!(nakamoto_inv.has_ith_tenure(299));
|
||||
assert!(nakamoto_inv.has_ith_tenure(300));
|
||||
assert!(nakamoto_inv.has_ith_tenure(398));
|
||||
assert!(!nakamoto_inv.has_ith_tenure(399));
|
||||
assert!(!nakamoto_inv.has_ith_tenure(400));
|
||||
assert_eq!(nakamoto_inv.highest_reward_cycle(), 2);
|
||||
|
||||
// supports sparse updates
|
||||
let full_tenure = NakamotoInvData::bools_to_bitvec(vec![true; 100]);
|
||||
nakamoto_inv.merge_tenure_inv(full_tenure, 100, 4);
|
||||
|
||||
for i in 300..400 {
|
||||
assert_eq!(!nakamoto_inv.has_ith_tenure(i));
|
||||
}
|
||||
for i in 400..500 {
|
||||
assert_eq!(!nakamoto_inv.has_ith_tenure(i));
|
||||
}
|
||||
assert_eq!(nakamoto_inv.num_reward_cycles(), 4);
|
||||
|
||||
// can overwrite tenures
|
||||
let full_tenure = NakamotoInvData::bools_to_bitvec(vec![true; 100]);
|
||||
nakamoto_inv.merge_tenure_inv(partial_tenure, 100, 2);
|
||||
let full_tenure = NakamotoInvData::bools_to_bitvec(&[true; 100]);
|
||||
let learned = nakamoto_inv.merge_tenure_inv(full_tenure, 100, 4);
|
||||
assert!(learned);
|
||||
|
||||
for i in 200..300 {
|
||||
for i in 400..500 {
|
||||
assert!(!nakamoto_inv.has_ith_tenure(i));
|
||||
}
|
||||
for i in 500..600 {
|
||||
assert!(nakamoto_inv.has_ith_tenure(i));
|
||||
}
|
||||
assert_eq!(nakamoto_inv.highest_reward_cycle(), 4);
|
||||
|
||||
// can overwrite tenures
|
||||
let full_tenure = NakamotoInvData::bools_to_bitvec(&[true; 100]);
|
||||
let learned = nakamoto_inv.merge_tenure_inv(full_tenure.clone(), 100, 2);
|
||||
assert!(learned);
|
||||
|
||||
let learned = nakamoto_inv.merge_tenure_inv(full_tenure.clone(), 100, 2);
|
||||
assert!(!learned);
|
||||
|
||||
for i in 300..400 {
|
||||
assert!(nakamoto_inv.has_ith_tenure(i));
|
||||
}
|
||||
|
||||
@@ -628,8 +715,290 @@ fn test_nakamoto_tenure_inv() {
|
||||
|
||||
nakamoto_inv.next_reward_cycle();
|
||||
assert_eq!(nakamoto_inv.reward_cycle(), 1);
|
||||
|
||||
nakamoto_inv.try_reset_comms(0, 0);
|
||||
|
||||
nakamoto_inv.try_reset_comms(0, 0, 0);
|
||||
assert_eq!(nakamoto_inv.reward_cycle(), 0);
|
||||
assert!(nakamoto_inv.is_online());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nakamoto_inv_sync_state_machine() {
|
||||
let observer = TestEventObserver::new();
|
||||
let bitvecs = vec![
|
||||
// full rc
|
||||
vec![true, true, true, true, true, true, true, true, true, true],
|
||||
// sparse rc
|
||||
vec![
|
||||
true, false, false, false, false, false, false, true, true, true,
|
||||
],
|
||||
// atlernating rc
|
||||
vec![
|
||||
false, true, false, true, false, true, false, true, true, true,
|
||||
],
|
||||
// sparse rc
|
||||
vec![
|
||||
false, false, false, false, false, false, true, true, true, true,
|
||||
],
|
||||
// full rc
|
||||
vec![true, true, true, true, true, true, true, true, true, true],
|
||||
];
|
||||
|
||||
// boot two peers, and cannibalize the second one for its network and sortdb so we can use them
|
||||
// to directly drive a state machine.
|
||||
let (mut peer, mut other_peers) =
|
||||
make_nakamoto_peers_from_invs(function_name!(), &observer, 10, 3, bitvecs.clone(), 1);
|
||||
let mut other_peer = other_peers.pop().unwrap();
|
||||
|
||||
let nakamoto_start =
|
||||
NakamotoBootPlan::nakamoto_first_tenure_height(&peer.config.burnchain.pox_constants);
|
||||
|
||||
let tip = {
|
||||
let sort_db = peer.sortdb.as_mut().unwrap();
|
||||
SortitionDB::get_canonical_burn_chain_tip(sort_db.conn()).unwrap()
|
||||
};
|
||||
let total_rcs = peer
|
||||
.config
|
||||
.burnchain
|
||||
.block_height_to_reward_cycle(tip.block_height)
|
||||
.unwrap()
|
||||
+ 1;
|
||||
|
||||
// run peer and other_peer until they connect
|
||||
loop {
|
||||
let _ = peer.step_with_ibd(false);
|
||||
let _ = other_peer.step_with_ibd(false);
|
||||
|
||||
let event_ids: Vec<usize> = peer
|
||||
.network
|
||||
.iter_peer_event_ids()
|
||||
.map(|e_id| *e_id)
|
||||
.collect();
|
||||
let other_event_ids: Vec<usize> = other_peer
|
||||
.network
|
||||
.iter_peer_event_ids()
|
||||
.map(|e_id| *e_id)
|
||||
.collect();
|
||||
|
||||
if event_ids.len() > 0 && other_event_ids.len() > 0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
debug!("Peers are connected");
|
||||
let peer_addr = NeighborAddress::from_neighbor(&peer.to_neighbor());
|
||||
|
||||
let (sx, rx) = sync_channel(1);
|
||||
let mut inv_machine = NakamotoInvStateMachine::new(PeerNetworkComms::new());
|
||||
|
||||
// ::scope is necessary because Rust is forced to think that `other_peers` has the same lifetime
|
||||
// as `observer`, which prohibits running a bare thread in which `other_peers` outlives
|
||||
// `observer`
|
||||
std::thread::scope(|s| {
|
||||
s.spawn(|| {
|
||||
let sortdb = other_peer.sortdb.take().unwrap();
|
||||
inv_machine
|
||||
.process_getnakamotoinv_begins(&mut other_peer.network, &sortdb, false)
|
||||
.unwrap();
|
||||
other_peer.sortdb = Some(sortdb);
|
||||
|
||||
let mut last_learned_rc = 0;
|
||||
loop {
|
||||
let _ = other_peer.step_with_ibd(false);
|
||||
let ev_ids: Vec<_> = other_peer.network.iter_peer_event_ids().collect();
|
||||
if ev_ids.len() == 0 {
|
||||
// disconnected
|
||||
panic!("Disconnected");
|
||||
}
|
||||
|
||||
let (num_msgs, learned) = inv_machine
|
||||
.process_getnakamotoinv_finishes(&mut other_peer.network)
|
||||
.unwrap();
|
||||
|
||||
for (_, inv) in inv_machine.inventories.iter() {
|
||||
debug!(
|
||||
"inv is at rc {}, last learned rc is {}, total rcs = {}",
|
||||
inv.reward_cycle(),
|
||||
last_learned_rc,
|
||||
total_rcs
|
||||
);
|
||||
last_learned_rc = last_learned_rc.max(inv.reward_cycle());
|
||||
}
|
||||
|
||||
if last_learned_rc >= total_rcs {
|
||||
break;
|
||||
}
|
||||
|
||||
let sortdb = other_peer.sortdb.take().unwrap();
|
||||
inv_machine
|
||||
.process_getnakamotoinv_begins(&mut other_peer.network, &sortdb, false)
|
||||
.unwrap();
|
||||
other_peer.sortdb = Some(sortdb);
|
||||
}
|
||||
|
||||
sx.send(true).unwrap();
|
||||
});
|
||||
|
||||
loop {
|
||||
let _ = peer.step_with_ibd(false);
|
||||
if rx.try_recv().is_ok() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// inv_machine learned everything
|
||||
for (_, inv) in inv_machine.inventories.iter() {
|
||||
debug!("Check inv state: {:?}", inv);
|
||||
check_inv_state(bitvecs.clone(), 10, nakamoto_start, inv);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nakamoto_inv_sync_across_epoch_change() {
|
||||
let observer = TestEventObserver::new();
|
||||
let bitvecs = vec![
|
||||
// full rc
|
||||
vec![true, true, true, true, true, true, true, true, true, true],
|
||||
// sparse rc
|
||||
vec![
|
||||
true, false, false, false, false, false, false, true, true, true,
|
||||
],
|
||||
// atlernating rc
|
||||
vec![
|
||||
false, true, false, true, false, true, false, true, true, true,
|
||||
],
|
||||
// sparse rc
|
||||
vec![
|
||||
false, false, false, false, false, false, true, true, true, true,
|
||||
],
|
||||
// full rc
|
||||
vec![true, true, true, true, true, true, true, true, true, true],
|
||||
];
|
||||
|
||||
// boot two peers, and cannibalize the second one for its network and sortdb so we can use them
|
||||
// to directly drive a state machine.
|
||||
let (mut peer, mut other_peers) =
|
||||
make_nakamoto_peers_from_invs(function_name!(), &observer, 10, 3, bitvecs.clone(), 1);
|
||||
let mut other_peer = other_peers.pop().unwrap();
|
||||
|
||||
let nakamoto_start =
|
||||
NakamotoBootPlan::nakamoto_first_tenure_height(&peer.config.burnchain.pox_constants);
|
||||
|
||||
let tip = {
|
||||
let sort_db = peer.sortdb.as_mut().unwrap();
|
||||
SortitionDB::get_canonical_burn_chain_tip(sort_db.conn()).unwrap()
|
||||
};
|
||||
let total_rcs = peer
|
||||
.config
|
||||
.burnchain
|
||||
.block_height_to_reward_cycle(tip.block_height)
|
||||
.unwrap();
|
||||
|
||||
// run peer and other_peer until they connect
|
||||
loop {
|
||||
let _ = peer.step_with_ibd(false);
|
||||
let _ = other_peer.step_with_ibd(false);
|
||||
|
||||
let event_ids: Vec<usize> = peer
|
||||
.network
|
||||
.iter_peer_event_ids()
|
||||
.map(|e_id| *e_id)
|
||||
.collect();
|
||||
let other_event_ids: Vec<usize> = other_peer
|
||||
.network
|
||||
.iter_peer_event_ids()
|
||||
.map(|e_id| *e_id)
|
||||
.collect();
|
||||
|
||||
if event_ids.len() > 0 && other_event_ids.len() > 0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
debug!("Peers are connected");
|
||||
|
||||
// force peers to sync their epoch 2.x inventories
|
||||
let old_burn_chain_tip = peer.network.burnchain_tip.block_height;
|
||||
let num_epoch2_blocks = nakamoto_start - 26; // TestPeer starts making blocks at sortition 26
|
||||
|
||||
// check epoch 2.x state machine
|
||||
let mut round = 0;
|
||||
let mut inv_1_count = 0;
|
||||
let mut inv_2_count = 0;
|
||||
let mut highest_rc_1 = 0;
|
||||
let mut highest_rc_2 = 0;
|
||||
|
||||
let burn_tip_start = peer.network.get_current_epoch().start_height;
|
||||
|
||||
while inv_1_count < num_epoch2_blocks
|
||||
|| inv_2_count < num_epoch2_blocks
|
||||
|| highest_rc_1 < total_rcs
|
||||
|| highest_rc_2 < total_rcs
|
||||
{
|
||||
// trick the work loop into thinking that the current chain view is this
|
||||
peer.network.connection_opts.force_nakamoto_epoch_transition = true;
|
||||
other_peer
|
||||
.network
|
||||
.connection_opts
|
||||
.force_nakamoto_epoch_transition = true;
|
||||
|
||||
let _ = peer.step_with_ibd(false);
|
||||
let _ = other_peer.step_with_ibd(false);
|
||||
|
||||
inv_1_count = peer
|
||||
.network
|
||||
.inv_state
|
||||
.as_ref()
|
||||
.map(|inv| inv.get_inv_num_blocks(&other_peer.to_neighbor().addr))
|
||||
.unwrap_or(0);
|
||||
inv_2_count = other_peer
|
||||
.network
|
||||
.inv_state
|
||||
.as_ref()
|
||||
.map(|inv| inv.get_inv_num_blocks(&peer.to_neighbor().addr))
|
||||
.unwrap_or(0);
|
||||
|
||||
highest_rc_1 = peer
|
||||
.network
|
||||
.inv_state_nakamoto
|
||||
.as_ref()
|
||||
.map(|inv| inv.highest_reward_cycle())
|
||||
.unwrap_or(0);
|
||||
highest_rc_2 = other_peer
|
||||
.network
|
||||
.inv_state_nakamoto
|
||||
.as_ref()
|
||||
.map(|inv| inv.highest_reward_cycle())
|
||||
.unwrap_or(0);
|
||||
|
||||
// nothing should break
|
||||
match peer.network.inv_state {
|
||||
Some(ref inv) => {
|
||||
assert_eq!(inv.get_broken_peers().len(), 0);
|
||||
assert_eq!(inv.get_dead_peers().len(), 0);
|
||||
assert_eq!(inv.get_diverged_peers().len(), 0);
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
|
||||
match other_peer.network.inv_state {
|
||||
Some(ref inv) => {
|
||||
assert_eq!(inv.get_broken_peers().len(), 0);
|
||||
assert_eq!(inv.get_dead_peers().len(), 0);
|
||||
assert_eq!(inv.get_diverged_peers().len(), 0);
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
|
||||
round += 1;
|
||||
|
||||
info!(
|
||||
"Epoch 2.x state machine: Peer 1: {}, Peer 2: {} (total {})",
|
||||
inv_1_count, inv_2_count, num_epoch2_blocks
|
||||
);
|
||||
info!(
|
||||
"Nakamoto state machine: Peer 1: {}, Peer 2: {} (total {})",
|
||||
highest_rc_1, highest_rc_2, total_rcs
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user