Skip to content

Commit 351f9e6

Browse files
jferrantkantai
authored andcommitted
Do not assume every signers signature makes it before miner quits waiting for unnecessary signatures
Signed-off-by: Jacinta Ferrant <[email protected]>
1 parent 218bd0b commit 351f9e6

File tree

1 file changed

+95
-61
lines changed
  • testnet/stacks-node/src/tests/signer

1 file changed

+95
-61
lines changed

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

Lines changed: 95 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -4130,31 +4130,34 @@ fn locally_rejected_blocks_overriden_by_global_acceptance() {
41304130
vec![(sender_addr.clone(), (send_amt + send_fee) * nmb_txs)],
41314131
);
41324132
let http_origin = format!("http://{}", &signer_test.running_nodes.conf.node.rpc_bind);
4133-
let long_timeout = Duration::from_secs(200);
4134-
let short_timeout = Duration::from_secs(30);
4133+
let long_timeout = 60;
4134+
let short_timeout = 30;
41354135
signer_test.boot_to_epoch_3();
4136+
41364137
info!("------------------------- Test Mine Nakamoto Block N -------------------------");
41374138
let mined_blocks = signer_test.running_nodes.nakamoto_blocks_mined.clone();
41384139
let info_before = signer_test
41394140
.stacks_client
41404141
.get_peer_info()
41414142
.expect("Failed to get peer info");
4142-
// submit a tx so that the miner will mine a stacks block
4143+
4144+
// submit a tx so that the miner will mine a stacks block N
41434145
let mut sender_nonce = 0;
41444146
let transfer_tx =
41454147
make_stacks_transfer(&sender_sk, sender_nonce, send_fee, &recipient, send_amt);
41464148
let tx = submit_tx(&http_origin, &transfer_tx);
4149+
sender_nonce += 1;
41474150
info!("Submitted tx {tx} in to mine block N");
4148-
wait_for(short_timeout.as_secs(), || {
4151+
4152+
wait_for(short_timeout, || {
41494153
let info_after = signer_test
41504154
.stacks_client
41514155
.get_peer_info()
41524156
.expect("Failed to get peer info");
41534157
Ok(info_after.stacks_tip_height > info_before.stacks_tip_height)
41544158
})
4155-
.expect("Timed out waiting for block to be mined and processed");
4159+
.expect("Timed out waiting for N to be mined and processed");
41564160

4157-
sender_nonce += 1;
41584161
let info_after = signer_test
41594162
.stacks_client
41604163
.get_peer_info()
@@ -4173,13 +4176,13 @@ fn locally_rejected_blocks_overriden_by_global_acceptance() {
41734176
.len();
41744177
assert_eq!(nmb_signatures, num_signers);
41754178

4176-
// Ensure that the block was accepted globally so the stacks tip has not advanced to N
4179+
// Ensure that the block was accepted globally so the stacks tip has advanced to N
41774180
let nakamoto_blocks = test_observer::get_mined_nakamoto_blocks();
41784181
let block_n = nakamoto_blocks.last().unwrap();
41794182
assert_eq!(info_after.stacks_tip.to_string(), block_n.block_hash);
41804183

41814184
info!("------------------------- Mine Nakamoto Block N+1 -------------------------");
4182-
// Make less than 30% of the signers reject the block to ensure it is marked globally accepted
4185+
// Make less than 30% of the signers reject the block and ensure it is STILL marked globally accepted
41834186
let rejecting_signers: Vec<_> = signer_test
41844187
.signer_stacks_private_keys
41854188
.iter()
@@ -4191,26 +4194,28 @@ fn locally_rejected_blocks_overriden_by_global_acceptance() {
41914194
.unwrap()
41924195
.replace(rejecting_signers.clone());
41934196
test_observer::clear();
4194-
let transfer_tx =
4195-
make_stacks_transfer(&sender_sk, sender_nonce, send_fee, &recipient, send_amt);
4196-
let tx = submit_tx(&http_origin, &transfer_tx);
4197-
sender_nonce += 1;
4198-
info!("Submitted tx {tx} in to mine block N+1");
4199-
let start_time = Instant::now();
4197+
4198+
// submit a tx so that the miner will mine a stacks block N+1
42004199
let blocks_before = mined_blocks.load(Ordering::SeqCst);
42014200
let info_before = signer_test
42024201
.stacks_client
42034202
.get_peer_info()
42044203
.expect("Failed to get peer info");
4205-
wait_for(short_timeout.as_secs(), || {
4204+
let transfer_tx =
4205+
make_stacks_transfer(&sender_sk, sender_nonce, send_fee, &recipient, send_amt);
4206+
let tx = submit_tx(&http_origin, &transfer_tx);
4207+
sender_nonce += 1;
4208+
info!("Submitted tx {tx} in to mine block N+1");
4209+
4210+
wait_for(short_timeout, || {
42064211
let info_after = signer_test
42074212
.stacks_client
42084213
.get_peer_info()
42094214
.expect("Failed to get peer info");
42104215
Ok(info_after.stacks_tip_height > info_before.stacks_tip_height)
42114216
})
42124217
.expect("Timed out waiting for block to be mined and processed");
4213-
loop {
4218+
wait_for(long_timeout, || {
42144219
let stackerdb_events = test_observer::get_stackerdb_chunks();
42154220
let block_rejections = stackerdb_events
42164221
.into_iter()
@@ -4235,14 +4240,10 @@ fn locally_rejected_blocks_overriden_by_global_acceptance() {
42354240
}
42364241
})
42374242
.collect::<Vec<_>>();
4238-
if block_rejections.len() == rejecting_signers.len() {
4239-
break;
4240-
}
4241-
assert!(
4242-
start_time.elapsed() < long_timeout,
4243-
"FAIL: Test timed out while waiting for block proposal rejections",
4244-
);
4245-
}
4243+
Ok(block_rejections.len() == rejecting_signers.len())
4244+
})
4245+
.expect("Timed out waiting for block proposal rejections");
4246+
42464247
// Assert the block was mined
42474248
let info_after = signer_test
42484249
.stacks_client
@@ -4263,25 +4264,27 @@ fn locally_rejected_blocks_overriden_by_global_acceptance() {
42634264
.len();
42644265
assert_eq!(nmb_signatures, num_signers - rejecting_signers.len());
42654266

4266-
// Ensure that the block was accepted globally so the stacks tip has advanced to N+1
4267+
// Ensure that the block was still accepted globally so the stacks tip has advanced to N+1
42674268
let nakamoto_blocks = test_observer::get_mined_nakamoto_blocks();
42684269
let block_n_1 = nakamoto_blocks.last().unwrap();
42694270
assert_eq!(info_after.stacks_tip.to_string(), block_n_1.block_hash);
42704271
assert_ne!(block_n_1, block_n);
42714272

42724273
info!("------------------------- Test Mine Nakamoto Block N+2 -------------------------");
4274+
// Ensure that all signers accept the block proposal N+2
42734275
let info_before = signer_test.stacks_client.get_peer_info().unwrap();
42744276
let blocks_before = mined_blocks.load(Ordering::SeqCst);
42754277
TEST_REJECT_ALL_BLOCK_PROPOSAL
42764278
.lock()
42774279
.unwrap()
42784280
.replace(Vec::new());
42794281

4282+
// submit a tx so that the miner will mine a stacks block N+2 and ensure ALL signers accept it
42804283
let transfer_tx =
42814284
make_stacks_transfer(&sender_sk, sender_nonce, send_fee, &recipient, send_amt);
42824285
let tx = submit_tx(&http_origin, &transfer_tx);
42834286
info!("Submitted tx {tx} in to mine block N+2");
4284-
wait_for(short_timeout.as_secs(), || {
4287+
wait_for(short_timeout, || {
42854288
let info_after = signer_test
42864289
.stacks_client
42874290
.get_peer_info()
@@ -4297,20 +4300,35 @@ fn locally_rejected_blocks_overriden_by_global_acceptance() {
42974300
info_before.stacks_tip_height + 1,
42984301
info_after.stacks_tip_height,
42994302
);
4300-
let nmb_signatures = signer_test
4301-
.stacks_client
4302-
.get_tenure_tip(&info_after.stacks_tip_consensus_hash)
4303-
.expect("Failed to get tip")
4304-
.as_stacks_nakamoto()
4305-
.expect("Not a Nakamoto block")
4306-
.signer_signature
4307-
.len();
4308-
assert_eq!(nmb_signatures, num_signers);
43094303
// Ensure that the block was accepted globally so the stacks tip has advanced to N+2
43104304
let nakamoto_blocks = test_observer::get_mined_nakamoto_blocks();
43114305
let block_n_2 = nakamoto_blocks.last().unwrap();
43124306
assert_eq!(info_after.stacks_tip.to_string(), block_n_2.block_hash);
43134307
assert_ne!(block_n_2, block_n_1);
4308+
4309+
// Make sure that ALL signers accepted the block proposal
4310+
wait_for(short_timeout, || {
4311+
let signatures = test_observer::get_stackerdb_chunks()
4312+
.into_iter()
4313+
.flat_map(|chunk| chunk.modified_slots)
4314+
.filter_map(|chunk| {
4315+
let message = SignerMessage::consensus_deserialize(&mut chunk.data.as_slice())
4316+
.expect("Failed to deserialize SignerMessage");
4317+
match message {
4318+
SignerMessage::BlockResponse(BlockResponse::Accepted((hash, signature))) => {
4319+
if hash == block_n_2.signer_signature_hash {
4320+
Some(signature)
4321+
} else {
4322+
None
4323+
}
4324+
}
4325+
_ => None,
4326+
}
4327+
})
4328+
.collect::<Vec<_>>();
4329+
Ok(signatures.len() == num_signers)
4330+
})
4331+
.expect("FAIL: Timed out waiting for block proposal acceptance by ALL signers");
43144332
}
43154333

43164334
#[test]
@@ -4351,7 +4369,7 @@ fn reorg_locally_accepted_blocks_across_tenures_succeeds() {
43514369
vec![(sender_addr.clone(), (send_amt + send_fee) * nmb_txs)],
43524370
);
43534371
let http_origin = format!("http://{}", &signer_test.running_nodes.conf.node.rpc_bind);
4354-
let short_timeout = Duration::from_secs(30);
4372+
let short_timeout = 30;
43554373
signer_test.boot_to_epoch_3();
43564374
info!("------------------------- Starting Tenure A -------------------------");
43574375
info!("------------------------- Test Mine Nakamoto Block N -------------------------");
@@ -4360,13 +4378,15 @@ fn reorg_locally_accepted_blocks_across_tenures_succeeds() {
43604378
.stacks_client
43614379
.get_peer_info()
43624380
.expect("Failed to get peer info");
4381+
43634382
// submit a tx so that the miner will mine a stacks block
43644383
let mut sender_nonce = 0;
43654384
let transfer_tx =
43664385
make_stacks_transfer(&sender_sk, sender_nonce, send_fee, &recipient, send_amt);
43674386
let tx = submit_tx(&http_origin, &transfer_tx);
4387+
sender_nonce += 1;
43684388
info!("Submitted tx {tx} in to mine block N");
4369-
wait_for(short_timeout.as_secs(), || {
4389+
wait_for(short_timeout, || {
43704390
let info_after = signer_test
43714391
.stacks_client
43724392
.get_peer_info()
@@ -4375,17 +4395,15 @@ fn reorg_locally_accepted_blocks_across_tenures_succeeds() {
43754395
})
43764396
.expect("Timed out waiting for block to be mined and processed");
43774397

4378-
sender_nonce += 1;
4398+
// Ensure that the block was accepted globally so the stacks tip has advanced to N
43794399
let info_after = signer_test
43804400
.stacks_client
43814401
.get_peer_info()
43824402
.expect("Failed to get peer info");
4383-
43844403
assert_eq!(
43854404
info_before.stacks_tip_height + 1,
43864405
info_after.stacks_tip_height
43874406
);
4388-
43894407
let nakamoto_blocks = test_observer::get_mined_nakamoto_blocks();
43904408
let block_n = nakamoto_blocks.last().unwrap();
43914409
assert_eq!(info_after.stacks_tip.to_string(), block_n.block_hash);
@@ -4404,16 +4422,19 @@ fn reorg_locally_accepted_blocks_across_tenures_succeeds() {
44044422
.replace(ignoring_signers.clone());
44054423
// Clear the stackerdb chunks
44064424
test_observer::clear();
4425+
4426+
// submit a tx so that the miner will ATTEMPT to mine a stacks block N+1
44074427
let transfer_tx =
44084428
make_stacks_transfer(&sender_sk, sender_nonce, send_fee, &recipient, send_amt);
44094429
let tx = submit_tx(&http_origin, &transfer_tx);
4430+
44104431
info!("Submitted tx {tx} in to attempt to mine block N+1");
44114432
let blocks_before = mined_blocks.load(Ordering::SeqCst);
44124433
let info_before = signer_test
44134434
.stacks_client
44144435
.get_peer_info()
44154436
.expect("Failed to get peer info");
4416-
wait_for(short_timeout.as_secs(), || {
4437+
wait_for(short_timeout, || {
44174438
let ignored_signers = test_observer::get_stackerdb_chunks()
44184439
.into_iter()
44194440
.flat_map(|chunk| chunk.modified_slots)
@@ -4433,20 +4454,22 @@ fn reorg_locally_accepted_blocks_across_tenures_succeeds() {
44334454
Ok(ignored_signers.len() + ignoring_signers.len() == num_signers)
44344455
})
44354456
.expect("FAIL: Timed out waiting for block proposal acceptance");
4457+
44364458
let blocks_after = mined_blocks.load(Ordering::SeqCst);
44374459
let info_after = signer_test
44384460
.stacks_client
44394461
.get_peer_info()
44404462
.expect("Failed to get peer info");
44414463
assert_eq!(blocks_after, blocks_before);
44424464
assert_eq!(info_after, info_before);
4443-
// Ensure that the block was not accepted globally so the stacks tip has not advanced to N+1
4465+
// Ensure that the block was NOT accepted globally so the stacks tip has NOT advanced to N+1
44444466
let nakamoto_blocks = test_observer::get_mined_nakamoto_blocks();
44454467
let block_n_1 = nakamoto_blocks.last().unwrap();
44464468
assert_ne!(block_n_1, block_n);
44474469
assert_ne!(info_after.stacks_tip.to_string(), block_n_1.block_hash);
44484470

44494471
info!("------------------------- Starting Tenure B -------------------------");
4472+
// Start a new tenure and ensure the miner can propose a new block N+1' that is accepted by all signers
44504473
let commits_submitted = signer_test.running_nodes.commits_submitted.clone();
44514474
let commits_before = commits_submitted.load(Ordering::SeqCst);
44524475
next_block_and(
@@ -4458,23 +4481,19 @@ fn reorg_locally_accepted_blocks_across_tenures_succeeds() {
44584481
},
44594482
)
44604483
.unwrap();
4484+
44614485
info!(
44624486
"------------------------- Mine Nakamoto Block N+1' in Tenure B -------------------------"
44634487
);
4464-
TEST_IGNORE_ALL_BLOCK_PROPOSALS
4465-
.lock()
4466-
.unwrap()
4467-
.replace(Vec::new());
44684488
let info_before = signer_test
44694489
.stacks_client
44704490
.get_peer_info()
44714491
.expect("Failed to get peer info");
4472-
// submit a tx so that the miner will mine a stacks block
4473-
let transfer_tx =
4474-
make_stacks_transfer(&sender_sk, sender_nonce, send_fee, &recipient, send_amt);
4475-
let tx = submit_tx(&http_origin, &transfer_tx);
4476-
info!("Submitted tx {tx} in to mine block N");
4477-
wait_for(short_timeout.as_secs(), || {
4492+
TEST_IGNORE_ALL_BLOCK_PROPOSALS
4493+
.lock()
4494+
.unwrap()
4495+
.replace(Vec::new());
4496+
wait_for(short_timeout, || {
44784497
let info_after = signer_test
44794498
.stacks_client
44804499
.get_peer_info()
@@ -4491,15 +4510,6 @@ fn reorg_locally_accepted_blocks_across_tenures_succeeds() {
44914510
info_before.stacks_tip_height + 1,
44924511
info_after.stacks_tip_height
44934512
);
4494-
let nmb_signatures = signer_test
4495-
.stacks_client
4496-
.get_tenure_tip(&info_after.stacks_tip_consensus_hash)
4497-
.expect("Failed to get tip")
4498-
.as_stacks_nakamoto()
4499-
.expect("Not a Nakamoto block")
4500-
.signer_signature
4501-
.len();
4502-
assert_eq!(nmb_signatures, num_signers);
45034513

45044514
// Ensure that the block was accepted globally so the stacks tip has advanced to N+1'
45054515
let nakamoto_blocks = test_observer::get_mined_nakamoto_blocks();
@@ -4509,6 +4519,30 @@ fn reorg_locally_accepted_blocks_across_tenures_succeeds() {
45094519
block_n_1_prime.block_hash
45104520
);
45114521
assert_ne!(block_n_1_prime, block_n);
4522+
4523+
// Make sure that ALL signers accepted the block proposal even though they signed a conflicting one in prior tenure
4524+
wait_for(short_timeout, || {
4525+
let signatures = test_observer::get_stackerdb_chunks()
4526+
.into_iter()
4527+
.flat_map(|chunk| chunk.modified_slots)
4528+
.filter_map(|chunk| {
4529+
let message = SignerMessage::consensus_deserialize(&mut chunk.data.as_slice())
4530+
.expect("Failed to deserialize SignerMessage");
4531+
match message {
4532+
SignerMessage::BlockResponse(BlockResponse::Accepted((hash, signature))) => {
4533+
if hash == block_n_1_prime.signer_signature_hash {
4534+
Some(signature)
4535+
} else {
4536+
None
4537+
}
4538+
}
4539+
_ => None,
4540+
}
4541+
})
4542+
.collect::<Vec<_>>();
4543+
Ok(signatures.len() == num_signers)
4544+
})
4545+
.expect("FAIL: Timed out waiting for block proposal acceptance by ALL signers");
45124546
}
45134547

45144548
#[test]

0 commit comments

Comments
 (0)