@@ -18083,3 +18083,115 @@ fn bitcoin_reorg_extended_tenure() {
18083
18083
18084
18084
miners.shutdown();
18085
18085
}
18086
+
18087
+ /// Tests that the active signer protocol version is set to the lowest common denominator
18088
+ #[test]
18089
+ #[ignore]
18090
+ fn multiversioned_signer_protocol_version_calculation() {
18091
+ if env::var("BITCOIND_TEST") != Ok("1".into()) {
18092
+ return;
18093
+ }
18094
+
18095
+ let num_signers = 5;
18096
+ let sender_sk = Secp256k1PrivateKey::random();
18097
+ let sender_addr = tests::to_addr(&sender_sk);
18098
+ let send_amt = 100;
18099
+ let send_fee = 180;
18100
+ let deploy_fee = 1000000;
18101
+ let call_fee = 1000;
18102
+ let signer_test: SignerTest<SpawnedSigner> = SignerTest::new_with_config_modifications(
18103
+ num_signers,
18104
+ vec![(
18105
+ sender_addr,
18106
+ (send_amt + send_fee) * 10 + deploy_fee + call_fee,
18107
+ )],
18108
+ |signer_config| {
18109
+ // We don't want the miner of the "inactive" sortition before the flash block
18110
+ // to get timed out.
18111
+ signer_config.block_proposal_timeout = Duration::from_secs(600);
18112
+
18113
+ let signer_version = match signer_config.endpoint.port() % num_signers as u16 {
18114
+ 0 | 1 => 0, // first two -> version 0
18115
+ 2 | 3 => 1, // next two -> version 1
18116
+ _ => 2, // last ones -> version 2
18117
+ };
18118
+ signer_config.supported_signer_protocol_version = signer_version;
18119
+ },
18120
+ |node_config| {
18121
+ node_config.miner.block_commit_delay = Duration::from_secs(1);
18122
+ node_config.miner.replay_transactions = true;
18123
+ },
18124
+ None,
18125
+ None,
18126
+ );
18127
+
18128
+ signer_test.boot_to_epoch_3();
18129
+ // Pause the miner to enforce exactly one proposal and to ensure it isn't just rejected with no consensus
18130
+ info!("------------------------- Pausing Mining -------------------------");
18131
+ TEST_MINE_SKIP.set(true);
18132
+ test_observer::clear();
18133
+ info!("------------------------- Reached Epoch 3.0 -------------------------");
18134
+
18135
+ // In the next block, the miner should win the tenure and mine a stacks block
18136
+ let peer_info_before = signer_test.get_peer_info();
18137
+
18138
+ info!("------------------------- Mining Burn Block for Tenure A -------------------------");
18139
+ next_block_and(
18140
+ &signer_test.running_nodes.btc_regtest_controller,
18141
+ 60,
18142
+ || {
18143
+ let peer_info = signer_test.get_peer_info();
18144
+ Ok(peer_info.burn_block_height > peer_info_before.burn_block_height)
18145
+ },
18146
+ )
18147
+ .unwrap();
18148
+ let peer_info_after = signer_test.get_peer_info();
18149
+ // All signers will view the active version as 0
18150
+ let signer_addresses: Vec<_> = signer_test
18151
+ .signer_addresses_versions()
18152
+ .into_iter()
18153
+ .map(|(address, _version)| (address, 0u64))
18154
+ .collect();
18155
+
18156
+ info!("------------------------- Waiting for Signer Updates with Version 0-------------------------");
18157
+ // Make sure all signers are on the same page before proposing a block so its accepted
18158
+ wait_for_state_machine_update(
18159
+ 30,
18160
+ &peer_info_after.pox_consensus,
18161
+ peer_info_after.burn_block_height,
18162
+ None,
18163
+ &signer_addresses,
18164
+ )
18165
+ .unwrap();
18166
+
18167
+ info!("------------------------- Resuming Mining of Tenure Start Block for Tenure A -------------------------");
18168
+ TEST_MINE_SKIP.set(false);
18169
+ wait_for(30, || {
18170
+ Ok(signer_test.get_peer_info().stacks_tip_height > peer_info_before.stacks_tip_height)
18171
+ })
18172
+ .unwrap();
18173
+
18174
+ info!("------------------------- Verifying Signers ONLY Sends Acceptances -------------------------");
18175
+ wait_for(30, || {
18176
+ let mut nmb_accept = 0;
18177
+ let stackerdb_events = test_observer::get_stackerdb_chunks();
18178
+ for chunk in stackerdb_events
18179
+ .into_iter()
18180
+ .flat_map(|chunk| chunk.modified_slots)
18181
+ {
18182
+ let message = SignerMessage::consensus_deserialize(&mut chunk.data.as_slice())
18183
+ .expect("Failed to deserialize SignerMessage");
18184
+ let SignerMessage::BlockResponse(response) = message else {
18185
+ continue;
18186
+ };
18187
+ assert!(
18188
+ matches!(response, BlockResponse::Accepted(_)),
18189
+ "Should have only received acceptances"
18190
+ );
18191
+ nmb_accept += 1;
18192
+ }
18193
+ Ok(nmb_accept == num_signers)
18194
+ })
18195
+ .unwrap();
18196
+ signer_test.shutdown();
18197
+ }
0 commit comments