Skip to content

Commit 44a849f

Browse files
authored
Merge branch 'develop' into test/fast-blocks-epoch3-change
2 parents a3d4d42 + 0146ba2 commit 44a849f

File tree

6 files changed

+117
-58
lines changed

6 files changed

+117
-58
lines changed

.github/workflows/bitcoin-tests.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ jobs:
7474
- tests::neon_integrations::min_txs
7575
- tests::neon_integrations::vote_for_aggregate_key_burn_op_test
7676
- tests::neon_integrations::mock_miner_replay
77+
- tests::neon_integrations::listunspent_max_utxos
7778
- tests::epoch_25::microblocks_disabled
7879
- tests::should_succeed_handling_malformed_and_valid_txs
7980
- tests::nakamoto_integrations::simple_neon_integration

testnet/stacks-node/src/burnchains/bitcoin_regtest_controller.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2314,6 +2314,10 @@ impl UTXOSet {
23142314
pub fn total_available(&self) -> u64 {
23152315
self.utxos.iter().map(|o| o.amount).sum()
23162316
}
2317+
2318+
pub fn num_utxos(&self) -> usize {
2319+
self.utxos.len()
2320+
}
23172321
}
23182322

23192323
#[derive(Debug, Clone)]
@@ -2607,7 +2611,7 @@ impl BitcoinRPCRequest {
26072611
max_conf.into(),
26082612
addresses.into(),
26092613
include_unsafe.into(),
2610-
json!({ "minimumAmount": minimum_amount }),
2614+
json!({ "minimumAmount": minimum_amount, "maximumCount": config.burnchain.max_unspent_utxos }),
26112615
],
26122616
id: "stacks".to_string(),
26132617
jsonrpc: "2.0".to_string(),

testnet/stacks-node/src/config.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1446,6 +1446,10 @@ pub struct BurnchainConfig {
14461446
/// fault injection to simulate a slow burnchain peer.
14471447
/// Delay burnchain block downloads by the given number of millseconds
14481448
pub fault_injection_burnchain_block_delay: u64,
1449+
/// The maximum number of unspent UTXOs to request from the bitcoin node.
1450+
/// This value is passed as the `maximumCount` query option to the
1451+
/// `listunspent` RPC call.
1452+
pub max_unspent_utxos: Option<u64>,
14491453
}
14501454

14511455
impl BurnchainConfig {
@@ -1486,6 +1490,7 @@ impl BurnchainConfig {
14861490
ast_precheck_size_height: None,
14871491
affirmation_overrides: HashMap::new(),
14881492
fault_injection_burnchain_block_delay: 0,
1493+
max_unspent_utxos: Some(1024),
14891494
}
14901495
}
14911496
pub fn get_rpc_url(&self, wallet: Option<String>) -> String {
@@ -1582,6 +1587,7 @@ pub struct BurnchainConfigFile {
15821587
pub ast_precheck_size_height: Option<u64>,
15831588
pub affirmation_overrides: Option<Vec<AffirmationOverride>>,
15841589
pub fault_injection_burnchain_block_delay: Option<u64>,
1590+
pub max_unspent_utxos: Option<u64>,
15851591
}
15861592

15871593
impl BurnchainConfigFile {
@@ -1797,6 +1803,13 @@ impl BurnchainConfigFile {
17971803
fault_injection_burnchain_block_delay: self
17981804
.fault_injection_burnchain_block_delay
17991805
.unwrap_or(default_burnchain_config.fault_injection_burnchain_block_delay),
1806+
max_unspent_utxos: self
1807+
.max_unspent_utxos
1808+
.map(|val| {
1809+
assert!(val <= 1024, "Value for max_unspent_utxos should be <= 1024");
1810+
val
1811+
})
1812+
.or(default_burnchain_config.max_unspent_utxos),
18001813
};
18011814

18021815
if let BitcoinNetworkType::Mainnet = config.get_bitcoin_network().1 {

testnet/stacks-node/src/tests/nakamoto_integrations.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2674,8 +2674,6 @@ fn correct_burn_outs() {
26742674

26752675
let mut last_block_time = None;
26762676
for block in new_blocks_with_reward_set.iter() {
2677-
let cycle_number = block["cycle_number"].as_u64().unwrap();
2678-
let reward_set = block["reward_set"].as_object().unwrap();
26792677
if let Some(block_time) = block["block_time"].as_u64() {
26802678
if let Some(last) = last_block_time {
26812679
assert!(block_time > last, "Block times should be increasing");

testnet/stacks-node/src/tests/neon_integrations.rs

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ use stacks::net::atlas::{
6262
AtlasConfig, AtlasDB, GetAttachmentResponse, GetAttachmentsInvResponse,
6363
MAX_ATTACHMENT_INV_PAGES_PER_REQUEST,
6464
};
65+
use stacks::types::PublicKey;
6566
use stacks::util_lib::boot::{boot_code_addr, boot_code_id};
6667
use stacks::util_lib::db::{query_row_columns, query_rows, u64_to_sql};
6768
use stacks::util_lib::signed_structured_data::pox4::{
@@ -82,7 +83,7 @@ use super::{
8283
make_microblock, make_stacks_transfer, make_stacks_transfer_mblock_only, to_addr, ADDR_4, SK_1,
8384
SK_2, SK_3,
8485
};
85-
use crate::burnchains::bitcoin_regtest_controller::{self, BitcoinRPCRequest, UTXO};
86+
use crate::burnchains::bitcoin_regtest_controller::{self, addr2str, BitcoinRPCRequest, UTXO};
8687
use crate::config::{EventKeyType, EventObserverConfig, FeeEstimatorName, InitialBalance};
8788
use crate::neon_node::RelayerThread;
8889
use crate::operations::BurnchainOpSigner;
@@ -12794,3 +12795,49 @@ fn mock_miner_replay() {
1279412795
miner_channel.stop_chains_coordinator();
1279512796
follower_channel.stop_chains_coordinator();
1279612797
}
12798+
12799+
#[test]
12800+
#[ignore]
12801+
/// Verify that the config option, `burnchain.max_unspent_utxos`, is respected.
12802+
fn listunspent_max_utxos() {
12803+
if env::var("BITCOIND_TEST") != Ok("1".into()) {
12804+
return;
12805+
}
12806+
12807+
let (mut conf, _miner_account) = neon_integration_test_conf();
12808+
let prom_bind = format!("{}:{}", "127.0.0.1", 6000);
12809+
conf.node.prometheus_bind = Some(prom_bind.clone());
12810+
12811+
conf.burnchain.max_rbf = 1000000;
12812+
conf.burnchain.max_unspent_utxos = Some(10);
12813+
12814+
let mut btcd_controller = BitcoinCoreController::new(conf.clone());
12815+
btcd_controller
12816+
.start_bitcoind()
12817+
.map_err(|_e| ())
12818+
.expect("Failed starting bitcoind");
12819+
12820+
let mut btc_regtest_controller = BitcoinRegtestController::new(conf.clone(), None);
12821+
12822+
btc_regtest_controller.bootstrap_chain(201);
12823+
12824+
eprintln!("Chain bootstrapped...");
12825+
12826+
let keychain = Keychain::default(conf.node.seed.clone());
12827+
let mut op_signer = keychain.generate_op_signer();
12828+
12829+
let (_, network_id) = conf.burnchain.get_bitcoin_network();
12830+
let hash160 = Hash160::from_data(&op_signer.get_public_key().to_bytes());
12831+
let address = BitcoinAddress::from_bytes_legacy(
12832+
network_id,
12833+
LegacyBitcoinAddressType::PublicKeyHash,
12834+
&hash160.0,
12835+
)
12836+
.expect("Public key incorrect");
12837+
12838+
let filter_addresses = vec![addr2str(&address)];
12839+
12840+
let res = BitcoinRPCRequest::list_unspent(&conf, filter_addresses, false, 1, &None, 0);
12841+
let utxos = res.expect("Failed to get utxos");
12842+
assert_eq!(utxos.num_utxos(), 10);
12843+
}

testnet/stacks-node/src/tests/signer/v0.rs

Lines changed: 50 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,11 @@ impl SignerTest<SpawnedSigner> {
264264
info!("Signers initialized");
265265

266266
self.run_until_epoch_3_boundary();
267+
std::thread::sleep(Duration::from_secs(1));
268+
wait_for(60, || {
269+
Ok(get_chain_info_opt(&self.running_nodes.conf).is_some())
270+
})
271+
.expect("Timed out waiting for network to restart after 3.0 boundary reached");
267272

268273
// Wait until we see the first block of epoch 3.0.
269274
// Note, we don't use `nakamoto_blocks_mined` counter, because there
@@ -4128,25 +4133,24 @@ fn locally_rejected_blocks_overriden_by_global_acceptance() {
41284133
signer_test.boot_to_epoch_3();
41294134
info!("------------------------- Test Mine Nakamoto Block N -------------------------");
41304135
let mined_blocks = signer_test.running_nodes.nakamoto_blocks_mined.clone();
4131-
let blocks_before = mined_blocks.load(Ordering::SeqCst);
41324136
let info_before = signer_test
41334137
.stacks_client
41344138
.get_peer_info()
41354139
.expect("Failed to get peer info");
4136-
let start_time = Instant::now();
41374140
// submit a tx so that the miner will mine a stacks block
41384141
let mut sender_nonce = 0;
41394142
let transfer_tx =
41404143
make_stacks_transfer(&sender_sk, sender_nonce, send_fee, &recipient, send_amt);
41414144
let tx = submit_tx(&http_origin, &transfer_tx);
41424145
info!("Submitted tx {tx} in to mine block N");
4143-
while mined_blocks.load(Ordering::SeqCst) <= blocks_before {
4144-
assert!(
4145-
start_time.elapsed() < short_timeout,
4146-
"FAIL: Test timed out while waiting for block production",
4147-
);
4148-
thread::sleep(Duration::from_secs(1));
4149-
}
4146+
wait_for(short_timeout.as_secs(), || {
4147+
let info_after = signer_test
4148+
.stacks_client
4149+
.get_peer_info()
4150+
.expect("Failed to get peer info");
4151+
Ok(info_after.stacks_tip_height > info_before.stacks_tip_height)
4152+
})
4153+
.expect("Timed out waiting for block to be mined and processed");
41504154

41514155
sender_nonce += 1;
41524156
let info_after = signer_test
@@ -4196,13 +4200,14 @@ fn locally_rejected_blocks_overriden_by_global_acceptance() {
41964200
.stacks_client
41974201
.get_peer_info()
41984202
.expect("Failed to get peer info");
4199-
while mined_blocks.load(Ordering::SeqCst) <= blocks_before {
4200-
assert!(
4201-
start_time.elapsed() < short_timeout,
4202-
"FAIL: Test timed out while waiting for block production",
4203-
);
4204-
thread::sleep(Duration::from_secs(1));
4205-
}
4203+
wait_for(short_timeout.as_secs(), || {
4204+
let info_after = signer_test
4205+
.stacks_client
4206+
.get_peer_info()
4207+
.expect("Failed to get peer info");
4208+
Ok(info_after.stacks_tip_height > info_before.stacks_tip_height)
4209+
})
4210+
.expect("Timed out waiting for block to be mined and processed");
42064211
loop {
42074212
let stackerdb_events = test_observer::get_stackerdb_chunks();
42084213
let block_rejections = stackerdb_events
@@ -4274,13 +4279,14 @@ fn locally_rejected_blocks_overriden_by_global_acceptance() {
42744279
make_stacks_transfer(&sender_sk, sender_nonce, send_fee, &recipient, send_amt);
42754280
let tx = submit_tx(&http_origin, &transfer_tx);
42764281
info!("Submitted tx {tx} in to mine block N+2");
4277-
while mined_blocks.load(Ordering::SeqCst) <= blocks_before {
4278-
assert!(
4279-
start_time.elapsed() < short_timeout,
4280-
"FAIL: Test timed out while waiting for block production",
4281-
);
4282-
thread::sleep(Duration::from_secs(1));
4283-
}
4282+
wait_for(short_timeout.as_secs(), || {
4283+
let info_after = signer_test
4284+
.stacks_client
4285+
.get_peer_info()
4286+
.expect("Failed to get peer info");
4287+
Ok(info_after.stacks_tip_height > info_before.stacks_tip_height)
4288+
})
4289+
.expect("Timed out waiting for block to be mined and processed");
42844290
let blocks_after = mined_blocks.load(Ordering::SeqCst);
42854291
assert_eq!(blocks_after, blocks_before + 1);
42864292

@@ -4348,31 +4354,31 @@ fn reorg_locally_accepted_blocks_across_tenures_succeeds() {
43484354
info!("------------------------- Starting Tenure A -------------------------");
43494355
info!("------------------------- Test Mine Nakamoto Block N -------------------------");
43504356
let mined_blocks = signer_test.running_nodes.nakamoto_blocks_mined.clone();
4351-
let blocks_before = mined_blocks.load(Ordering::SeqCst);
43524357
let info_before = signer_test
43534358
.stacks_client
43544359
.get_peer_info()
43554360
.expect("Failed to get peer info");
4356-
let start_time = Instant::now();
43574361
// submit a tx so that the miner will mine a stacks block
43584362
let mut sender_nonce = 0;
43594363
let transfer_tx =
43604364
make_stacks_transfer(&sender_sk, sender_nonce, send_fee, &recipient, send_amt);
43614365
let tx = submit_tx(&http_origin, &transfer_tx);
43624366
info!("Submitted tx {tx} in to mine block N");
4363-
while mined_blocks.load(Ordering::SeqCst) <= blocks_before {
4364-
assert!(
4365-
start_time.elapsed() < short_timeout,
4366-
"FAIL: Test timed out while waiting for block production",
4367-
);
4368-
thread::sleep(Duration::from_secs(1));
4369-
}
4367+
wait_for(short_timeout.as_secs(), || {
4368+
let info_after = signer_test
4369+
.stacks_client
4370+
.get_peer_info()
4371+
.expect("Failed to get peer info");
4372+
Ok(info_after.stacks_tip_height > info_before.stacks_tip_height)
4373+
})
4374+
.expect("Timed out waiting for block to be mined and processed");
43704375

43714376
sender_nonce += 1;
43724377
let info_after = signer_test
43734378
.stacks_client
43744379
.get_peer_info()
43754380
.expect("Failed to get peer info");
4381+
43764382
assert_eq!(
43774383
info_before.stacks_tip_height + 1,
43784384
info_after.stacks_tip_height
@@ -4400,13 +4406,12 @@ fn reorg_locally_accepted_blocks_across_tenures_succeeds() {
44004406
make_stacks_transfer(&sender_sk, sender_nonce, send_fee, &recipient, send_amt);
44014407
let tx = submit_tx(&http_origin, &transfer_tx);
44024408
info!("Submitted tx {tx} in to attempt to mine block N+1");
4403-
let start_time = Instant::now();
44044409
let blocks_before = mined_blocks.load(Ordering::SeqCst);
44054410
let info_before = signer_test
44064411
.stacks_client
44074412
.get_peer_info()
44084413
.expect("Failed to get peer info");
4409-
loop {
4414+
wait_for(short_timeout.as_secs(), || {
44104415
let ignored_signers = test_observer::get_stackerdb_chunks()
44114416
.into_iter()
44124417
.flat_map(|chunk| chunk.modified_slots)
@@ -4423,15 +4428,9 @@ fn reorg_locally_accepted_blocks_across_tenures_succeeds() {
44234428
}
44244429
})
44254430
.collect::<Vec<_>>();
4426-
if ignored_signers.len() + ignoring_signers.len() == num_signers {
4427-
break;
4428-
}
4429-
assert!(
4430-
start_time.elapsed() < short_timeout,
4431-
"FAIL: Test timed out while waiting for block proposal acceptance",
4432-
);
4433-
sleep_ms(1000);
4434-
}
4431+
Ok(ignored_signers.len() + ignoring_signers.len() == num_signers)
4432+
})
4433+
.expect("FAIL: Timed out waiting for block proposal acceptance");
44354434
let blocks_after = mined_blocks.load(Ordering::SeqCst);
44364435
let info_after = signer_test
44374436
.stacks_client
@@ -4464,25 +4463,23 @@ fn reorg_locally_accepted_blocks_across_tenures_succeeds() {
44644463
.lock()
44654464
.unwrap()
44664465
.replace(Vec::new());
4467-
let mined_blocks = signer_test.running_nodes.nakamoto_blocks_mined.clone();
4468-
let blocks_before = mined_blocks.load(Ordering::SeqCst);
44694466
let info_before = signer_test
44704467
.stacks_client
44714468
.get_peer_info()
44724469
.expect("Failed to get peer info");
4473-
let start_time = Instant::now();
44744470
// submit a tx so that the miner will mine a stacks block
44754471
let transfer_tx =
44764472
make_stacks_transfer(&sender_sk, sender_nonce, send_fee, &recipient, send_amt);
44774473
let tx = submit_tx(&http_origin, &transfer_tx);
44784474
info!("Submitted tx {tx} in to mine block N");
4479-
while mined_blocks.load(Ordering::SeqCst) <= blocks_before {
4480-
assert!(
4481-
start_time.elapsed() < short_timeout,
4482-
"FAIL: Test timed out while waiting for block production",
4483-
);
4484-
thread::sleep(Duration::from_secs(1));
4485-
}
4475+
wait_for(short_timeout.as_secs(), || {
4476+
let info_after = signer_test
4477+
.stacks_client
4478+
.get_peer_info()
4479+
.expect("Failed to get peer info");
4480+
Ok(info_after.stacks_tip_height > info_before.stacks_tip_height)
4481+
})
4482+
.expect("Timed out waiting for block to be mined and processed");
44864483

44874484
let info_after = signer_test
44884485
.stacks_client
@@ -4796,7 +4793,6 @@ fn miner_recovers_when_broadcast_block_delay_across_tenures_occurs() {
47964793
// Induce block N+2 to get mined
47974794
let transfer_tx =
47984795
make_stacks_transfer(&sender_sk, sender_nonce, send_fee, &recipient, send_amt);
4799-
sender_nonce += 1;
48004796

48014797
let tx = submit_tx(&http_origin, &transfer_tx);
48024798
info!("Submitted tx {tx} in to attempt to mine block N+2");

0 commit comments

Comments
 (0)