Skip to content

Commit

Permalink
Merge branch 'develop' of https://github.com/stacks-network/stacks-core
Browse files Browse the repository at this point in the history
… into chore/clippy-assertions-assign-op-approx-constant
  • Loading branch information
jferrant committed Feb 14, 2025
2 parents 0cdc3cc + e77ce8d commit 6f8d7c6
Show file tree
Hide file tree
Showing 3 changed files with 2,334 additions and 7,348 deletions.
17 changes: 6 additions & 11 deletions testnet/stacks-node/src/tests/nakamoto_integrations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4112,7 +4112,8 @@ fn follower_bootup_across_multiple_cycles() {

debug!("Booted follower-thread");

wait_for(300, || {
// Wait a long time for the follower to catch up because CI is slow.
wait_for(600, || {
sleep_ms(1000);
let Ok(follower_node_info) = get_chain_info_result(&follower_conf) else {
return Ok(false);
Expand Down Expand Up @@ -10774,11 +10775,6 @@ fn test_tenure_extend_from_flashblocks() {
let btc_regtest_controller = &mut signer_test.running_nodes.btc_regtest_controller;
let coord_channel = signer_test.running_nodes.coord_channel.clone();
let counters = signer_test.running_nodes.counters.clone();
let nakamoto_test_skip_commit_op = signer_test
.running_nodes
.nakamoto_test_skip_commit_op
.clone();
let nakamoto_miner_directives = signer_test.running_nodes.nakamoto_miner_directives.clone();

let tx_fee = 1_000;

Expand Down Expand Up @@ -10832,7 +10828,7 @@ fn test_tenure_extend_from_flashblocks() {
next_block_and_mine_commit(btc_regtest_controller, 60, &naka_conf, &counters).unwrap();

// prevent the miner from sending another block-commit
nakamoto_test_skip_commit_op.set(true);
counters.naka_skip_commit_op.set(true);

let info_before = get_chain_info(&naka_conf);

Expand Down Expand Up @@ -10865,7 +10861,7 @@ fn test_tenure_extend_from_flashblocks() {
// mine another Bitcoin block right away, and force it to be a flash block
btc_regtest_controller.bootstrap_chain(1);

let miner_directives_before = nakamoto_miner_directives.load(Ordering::SeqCst);
let miner_directives_before = counters.naka_miner_directives.load(Ordering::SeqCst);

// unblock the relayer so it can process the flash block sortition.
// Given the above, this will be an `Extend` tenure.
Expand Down Expand Up @@ -10924,13 +10920,12 @@ fn test_tenure_extend_from_flashblocks() {
}

// unstall miner thread and allow block-commits again
nakamoto_test_skip_commit_op.set(false);
counters.naka_skip_commit_op.set(false);
TEST_MINE_STALL.set(false);

// wait for the miner directive to be processed
wait_for(60, || {
let directives_cnt = nakamoto_miner_directives.load(Ordering::SeqCst);
Ok(directives_cnt > miner_directives_before)
Ok(counters.naka_miner_directives.load(Ordering::SeqCst) > miner_directives_before)
})
.unwrap();

Expand Down
156 changes: 13 additions & 143 deletions testnet/stacks-node/src/tests/signer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@
mod v0;

use std::collections::HashSet;
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::{Duration, Instant};

use clarity::boot_util::boot_code_id;
use clarity::vm::types::PrincipalData;
use libsigner::v0::messages::{
BlockAccepted, BlockRejection, BlockResponse, MessageSlotID, PeerInfo, SignerMessage,
BlockAccepted, BlockResponse, MessageSlotID, PeerInfo, SignerMessage,
};
use libsigner::{BlockProposal, SignerEntries, SignerEventTrait};
use stacks::chainstate::coordinator::comm::CoordinatorChannels;
Expand All @@ -36,22 +36,21 @@ use stacks::net::api::postblock_proposal::{
BlockValidateOk, BlockValidateReject, BlockValidateResponse,
};
use stacks::types::chainstate::{StacksAddress, StacksPublicKey};
use stacks::types::{PrivateKey, PublicKey};
use stacks::types::PrivateKey;
use stacks::util::get_epoch_time_secs;
use stacks::util::hash::MerkleHashFunc;
use stacks::util::secp256k1::{MessageSignature, Secp256k1PublicKey};
use stacks_common::codec::StacksMessageCodec;
use stacks_common::consts::SIGNER_SLOTS_PER_USER;
use stacks_common::types::StacksEpochId;
use stacks_common::util::hash::Sha512Trunc256Sum;
use stacks_common::util::tests::TestFlag;
use stacks_signer::client::{ClientError, SignerSlotID, StackerDB, StacksClient};
use stacks_signer::config::{build_signer_config_tomls, GlobalConfig as SignerConfig, Network};
use stacks_signer::runloop::{SignerResult, State, StateInfo};
use stacks_signer::{Signer, SpawnedSigner};

use super::nakamoto_integrations::{check_nakamoto_empty_block_heuristics, wait_for};
use crate::neon::{Counters, RunLoopCounter};
use crate::neon::Counters;
use crate::run_loop::boot_nakamoto;
use crate::tests::bitcoin_regtest::BitcoinCoreController;
use crate::tests::nakamoto_integrations::{
Expand All @@ -72,17 +71,6 @@ pub struct RunningNodes {
pub btcd_controller: BitcoinCoreController,
pub run_loop_thread: thread::JoinHandle<()>,
pub run_loop_stopper: Arc<AtomicBool>,
pub vrfs_submitted: RunLoopCounter,
pub commits_submitted: RunLoopCounter,
pub last_commit_burn_height: RunLoopCounter,
pub blocks_processed: RunLoopCounter,
pub sortitions_processed: RunLoopCounter,
pub nakamoto_blocks_proposed: RunLoopCounter,
pub nakamoto_blocks_mined: RunLoopCounter,
pub nakamoto_blocks_rejected: RunLoopCounter,
pub nakamoto_blocks_signer_pushed: RunLoopCounter,
pub nakamoto_miner_directives: Arc<AtomicU64>,
pub nakamoto_test_skip_commit_op: TestFlag<bool>,
pub counters: Counters,
pub coord_channel: Arc<Mutex<CoordinatorChannels>>,
pub conf: NeonConfig,
Expand Down Expand Up @@ -334,7 +322,7 @@ impl<S: Signer<T> + Send + 'static, T: SignerEventTrait + 'static> SignerTest<Sp
/// Note: do not use nakamoto blocks mined heuristic if running a test with multiple miners
fn mine_nakamoto_block(&mut self, timeout: Duration, use_nakamoto_blocks_mined: bool) {
let mined_block_time = Instant::now();
let mined_before = self.running_nodes.nakamoto_blocks_mined.get();
let mined_before = self.running_nodes.counters.naka_mined_blocks.get();
let info_before = self.get_peer_info();
next_block_and_mine_commit(
&mut self.running_nodes.btc_regtest_controller,
Expand All @@ -346,7 +334,7 @@ impl<S: Signer<T> + Send + 'static, T: SignerEventTrait + 'static> SignerTest<Sp

wait_for(timeout.as_secs(), || {
let info_after = self.get_peer_info();
let blocks_mined = self.running_nodes.nakamoto_blocks_mined.get();
let blocks_mined = self.running_nodes.counters.naka_mined_blocks.get();
Ok(info_after.stacks_tip_height > info_before.stacks_tip_height
&& (!use_nakamoto_blocks_mined || blocks_mined > mined_before))
})
Expand Down Expand Up @@ -388,14 +376,14 @@ impl<S: Signer<T> + Send + 'static, T: SignerEventTrait + 'static> SignerTest<Sp
/// to ensure that the block was mined.
/// Note: this function does _not_ mine a BTC block.
fn wait_for_nakamoto_block(&mut self, timeout_secs: u64, f: impl FnOnce() -> ()) {
let blocks_before = self.running_nodes.nakamoto_blocks_mined.get();
let blocks_before = self.running_nodes.counters.naka_mined_blocks.get();
let info_before = self.get_peer_info();

f();

// Verify that the block was mined
wait_for(timeout_secs, || {
let blocks_mined = self.running_nodes.nakamoto_blocks_mined.get();
let blocks_mined = self.running_nodes.counters.naka_mined_blocks.get();
let info = self.get_peer_info();
Ok(blocks_mined > blocks_before
&& info.stacks_tip_height > info_before.stacks_tip_height)
Expand Down Expand Up @@ -506,7 +494,7 @@ impl<S: Signer<T> + Send + 'static, T: SignerEventTrait + 'static> SignerTest<Sp
// advance to epoch 3.0 and trigger a sign round (cannot vote on blocks in pre epoch 3.0)
run_until_burnchain_height(
&mut self.running_nodes.btc_regtest_controller,
&self.running_nodes.blocks_processed,
&self.running_nodes.counters.blocks_processed,
epoch_30_boundary,
&self.running_nodes.conf,
);
Expand Down Expand Up @@ -618,100 +606,6 @@ impl<S: Signer<T> + Send + 'static, T: SignerEventTrait + 'static> SignerTest<Sp
}
}

pub fn wait_for_block_acceptance(
&self,
timeout_secs: u64,
signer_signature_hash: &Sha512Trunc256Sum,
expected_signers: &[StacksPublicKey],
) -> Result<(), String> {
// Make sure that at least 70% of signers accepted the block proposal
wait_for(timeout_secs, || {
let signatures = test_observer::get_stackerdb_chunks()
.into_iter()
.flat_map(|chunk| chunk.modified_slots)
.filter_map(|chunk| {
let message = SignerMessage::consensus_deserialize(&mut chunk.data.as_slice())
.expect("Failed to deserialize SignerMessage");
if let SignerMessage::BlockResponse(BlockResponse::Accepted(accepted)) = message
{
if accepted.signer_signature_hash == *signer_signature_hash
&& expected_signers.iter().any(|pk| {
pk.verify(
accepted.signer_signature_hash.bits(),
&accepted.signature,
)
.expect("Failed to verify signature")
})
{
return Some(accepted.signature);
}
}
None
})
.collect::<HashSet<_>>();
Ok(signatures.len() > expected_signers.len() * 7 / 10)
})
}

pub fn wait_for_block_rejections(
&self,
timeout_secs: u64,
expected_signers: &[StacksPublicKey],
) -> Result<(), String> {
wait_for(timeout_secs, || {
let stackerdb_events = test_observer::get_stackerdb_chunks();
let block_rejections: HashSet<_> = stackerdb_events
.into_iter()
.flat_map(|chunk| chunk.modified_slots)
.filter_map(|chunk| {
let message = SignerMessage::consensus_deserialize(&mut chunk.data.as_slice())
.expect("Failed to deserialize SignerMessage");
match message {
SignerMessage::BlockResponse(BlockResponse::Rejected(rejection)) => {
let rejected_pubkey = rejection
.recover_public_key()
.expect("Failed to recover public key from rejection");
if expected_signers.contains(&rejected_pubkey) {
Some(rejected_pubkey)
} else {
None
}
}
_ => None,
}
})
.collect::<HashSet<_>>();
Ok(block_rejections.len() == expected_signers.len())
})
}

/// Get all block rejections for a given block
pub fn get_block_rejections(
&self,
signer_signature_hash: &Sha512Trunc256Sum,
) -> Vec<BlockRejection> {
let stackerdb_events = test_observer::get_stackerdb_chunks();
let block_rejections = stackerdb_events
.into_iter()
.flat_map(|chunk| chunk.modified_slots)
.filter_map(|chunk| {
let message = SignerMessage::consensus_deserialize(&mut chunk.data.as_slice())
.expect("Failed to deserialize SignerMessage");
match message {
SignerMessage::BlockResponse(BlockResponse::Rejected(rejection)) => {
if rejection.signer_signature_hash == *signer_signature_hash {
Some(rejection)
} else {
None
}
}
_ => None,
}
})
.collect::<Vec<_>>();
block_rejections
}

/// Get the latest block response from the given slot
pub fn get_latest_block_response(&self, slot_id: u32) -> BlockResponse {
let mut stackerdb = StackerDB::new_normal(
Expand Down Expand Up @@ -916,21 +810,8 @@ fn setup_stx_btc_node<G: FnMut(&mut NeonConfig)>(

let mut run_loop = boot_nakamoto::BootRunLoop::new(naka_conf.clone()).unwrap();
let run_loop_stopper = run_loop.get_termination_switch();
let Counters {
blocks_processed,
sortitions_processed,
naka_submitted_vrfs: vrfs_submitted,
naka_submitted_commits: commits_submitted,
naka_submitted_commit_last_burn_height: last_commit_burn_height,
naka_proposed_blocks: naka_blocks_proposed,
naka_mined_blocks: naka_blocks_mined,
naka_rejected_blocks: naka_blocks_rejected,
naka_miner_directives,
naka_skip_commit_op: nakamoto_test_skip_commit_op,
naka_signer_pushed_blocks,
..
} = run_loop.counters();
let counters = run_loop.counters();
let blocks_processed = counters.blocks_processed.clone();

let coord_channel = run_loop.coordinator_channels();
let run_loop_thread = thread::spawn(move || run_loop.start(None, 0));
Expand All @@ -941,32 +822,21 @@ fn setup_stx_btc_node<G: FnMut(&mut NeonConfig)>(

// First block wakes up the run loop.
info!("Mine first block...");
next_block_and_wait(&mut btc_regtest_controller, &blocks_processed);
next_block_and_wait(&mut btc_regtest_controller, &counters.blocks_processed);

// Second block will hold our VRF registration.
info!("Mine second block...");
next_block_and_wait(&mut btc_regtest_controller, &blocks_processed);
next_block_and_wait(&mut btc_regtest_controller, &counters.blocks_processed);

// Third block will be the first mined Stacks block.
info!("Mine third block...");
next_block_and_wait(&mut btc_regtest_controller, &blocks_processed);
next_block_and_wait(&mut btc_regtest_controller, &counters.blocks_processed);

RunningNodes {
btcd_controller,
btc_regtest_controller,
run_loop_thread,
run_loop_stopper,
vrfs_submitted,
commits_submitted,
last_commit_burn_height,
blocks_processed,
sortitions_processed,
nakamoto_blocks_proposed: naka_blocks_proposed,
nakamoto_blocks_mined: naka_blocks_mined,
nakamoto_blocks_rejected: naka_blocks_rejected,
nakamoto_blocks_signer_pushed: naka_signer_pushed_blocks,
nakamoto_test_skip_commit_op,
nakamoto_miner_directives: naka_miner_directives.0,
coord_channel,
counters,
conf: naka_conf,
Expand Down
Loading

0 comments on commit 6f8d7c6

Please sign in to comment.