@@ -18147,6 +18147,118 @@ fn bitcoin_reorg_extended_tenure() {
18147
18147
miners.shutdown();
18148
18148
}
18149
18149
18150
+ /// Tests that the active signer protocol version is set to the lowest common denominator
18151
+ #[test]
18152
+ #[ignore]
18153
+ fn multiversioned_signer_protocol_version_calculation() {
18154
+ if env::var("BITCOIND_TEST") != Ok("1".into()) {
18155
+ return;
18156
+ }
18157
+
18158
+ let num_signers = 5;
18159
+ let sender_sk = Secp256k1PrivateKey::random();
18160
+ let sender_addr = tests::to_addr(&sender_sk);
18161
+ let send_amt = 100;
18162
+ let send_fee = 180;
18163
+ let deploy_fee = 1000000;
18164
+ let call_fee = 1000;
18165
+ let signer_test: SignerTest<SpawnedSigner> = SignerTest::new_with_config_modifications(
18166
+ num_signers,
18167
+ vec![(
18168
+ sender_addr,
18169
+ (send_amt + send_fee) * 10 + deploy_fee + call_fee,
18170
+ )],
18171
+ |signer_config| {
18172
+ // We don't want the miner of the "inactive" sortition before the flash block
18173
+ // to get timed out.
18174
+ signer_config.block_proposal_timeout = Duration::from_secs(600);
18175
+
18176
+ let signer_version = match signer_config.endpoint.port() % num_signers as u16 {
18177
+ 0 | 1 => 0, // first two -> version 0
18178
+ 2 | 3 => 1, // next two -> version 1
18179
+ _ => 2, // last ones -> version 2
18180
+ };
18181
+ signer_config.supported_signer_protocol_version = signer_version;
18182
+ },
18183
+ |node_config| {
18184
+ node_config.miner.block_commit_delay = Duration::from_secs(1);
18185
+ node_config.miner.replay_transactions = true;
18186
+ },
18187
+ None,
18188
+ None,
18189
+ );
18190
+
18191
+ signer_test.boot_to_epoch_3();
18192
+ // Pause the miner to enforce exactly one proposal and to ensure it isn't just rejected with no consensus
18193
+ info!("------------------------- Pausing Mining -------------------------");
18194
+ TEST_MINE_SKIP.set(true);
18195
+ test_observer::clear();
18196
+ info!("------------------------- Reached Epoch 3.0 -------------------------");
18197
+
18198
+ // In the next block, the miner should win the tenure and mine a stacks block
18199
+ let peer_info_before = signer_test.get_peer_info();
18200
+
18201
+ info!("------------------------- Mining Burn Block for Tenure A -------------------------");
18202
+ next_block_and(
18203
+ &signer_test.running_nodes.btc_regtest_controller,
18204
+ 60,
18205
+ || {
18206
+ let peer_info = signer_test.get_peer_info();
18207
+ Ok(peer_info.burn_block_height > peer_info_before.burn_block_height)
18208
+ },
18209
+ )
18210
+ .unwrap();
18211
+ let peer_info_after = signer_test.get_peer_info();
18212
+ // All signers will view the active version as 0
18213
+ let signer_addresses: Vec<_> = signer_test
18214
+ .signer_addresses_versions()
18215
+ .into_iter()
18216
+ .map(|(address, _version)| (address, 0u64))
18217
+ .collect();
18218
+
18219
+ info!("------------------------- Waiting for Signer Updates with Version 0-------------------------");
18220
+ // Make sure all signers are on the same page before proposing a block so its accepted
18221
+ wait_for_state_machine_update(
18222
+ 30,
18223
+ &peer_info_after.pox_consensus,
18224
+ peer_info_after.burn_block_height,
18225
+ None,
18226
+ &signer_addresses,
18227
+ )
18228
+ .unwrap();
18229
+
18230
+ info!("------------------------- Resuming Mining of Tenure Start Block for Tenure A -------------------------");
18231
+ TEST_MINE_SKIP.set(false);
18232
+ wait_for(30, || {
18233
+ Ok(signer_test.get_peer_info().stacks_tip_height > peer_info_before.stacks_tip_height)
18234
+ })
18235
+ .unwrap();
18236
+
18237
+ info!("------------------------- Verifying Signers ONLY Sends Acceptances -------------------------");
18238
+ wait_for(30, || {
18239
+ let mut nmb_accept = 0;
18240
+ let stackerdb_events = test_observer::get_stackerdb_chunks();
18241
+ for chunk in stackerdb_events
18242
+ .into_iter()
18243
+ .flat_map(|chunk| chunk.modified_slots)
18244
+ {
18245
+ let message = SignerMessage::consensus_deserialize(&mut chunk.data.as_slice())
18246
+ .expect("Failed to deserialize SignerMessage");
18247
+ let SignerMessage::BlockResponse(response) = message else {
18248
+ continue;
18249
+ };
18250
+ assert!(
18251
+ matches!(response, BlockResponse::Accepted(_)),
18252
+ "Should have only received acceptances"
18253
+ );
18254
+ nmb_accept += 1;
18255
+ }
18256
+ Ok(nmb_accept == num_signers)
18257
+ })
18258
+ .unwrap();
18259
+ signer_test.shutdown();
18260
+ }
18261
+
18150
18262
// Basic test to ensure that signers will not issue a signature over a block proposal unless
18151
18263
// a threshold number of signers have pre-committed to sign.
18152
18264
#[test]
0 commit comments