@@ -3943,6 +3943,118 @@ fn tx_replay_failsafe() {
3943
3943
signer_test.shutdown();
3944
3944
}
3945
3945
3946
+ /// Simple/fast test scenario for transaction replay.
3947
+ ///
3948
+ /// We fork one tenure, which has a STX transfer. The test
3949
+ /// verifies that the replay set is updated correctly, and then
3950
+ /// exits.
3951
+ #[ignore]
3952
+ #[test]
3953
+ fn tx_replay_simple() {
3954
+ if env::var("BITCOIND_TEST") != Ok("1".into()) {
3955
+ return;
3956
+ }
3957
+
3958
+ let num_signers = 5;
3959
+ let sender_sk = Secp256k1PrivateKey::from_seed("sender_1".as_bytes());
3960
+ let sender_addr = tests::to_addr(&sender_sk);
3961
+ let send_amt = 100;
3962
+ let send_fee = 180;
3963
+ let signer_test: SignerTest<SpawnedSigner> =
3964
+ SignerTest::new_with_config_modifications_and_snapshot(
3965
+ num_signers,
3966
+ vec![(sender_addr, (send_amt + send_fee) * 10)],
3967
+ |c| {
3968
+ c.validate_with_replay_tx = true;
3969
+ },
3970
+ |node_config| {
3971
+ node_config.miner.block_commit_delay = Duration::from_secs(1);
3972
+ node_config.miner.replay_transactions = true;
3973
+ node_config.miner.activated_vrf_key_path =
3974
+ Some(format!("{}/vrf_key", node_config.node.working_dir));
3975
+ },
3976
+ None,
3977
+ None,
3978
+ Some(function_name!()),
3979
+ );
3980
+
3981
+ let conf = &signer_test.running_nodes.conf;
3982
+ let _http_origin = format!("http://{}", &conf.node.rpc_bind);
3983
+ let btc_controller = &signer_test.running_nodes.btc_regtest_controller;
3984
+
3985
+ let miner_pk = btc_controller
3986
+ .get_mining_pubkey()
3987
+ .as_deref()
3988
+ .map(Secp256k1PublicKey::from_hex)
3989
+ .unwrap()
3990
+ .unwrap();
3991
+
3992
+ if signer_test.bootstrap_snapshot() {
3993
+ signer_test.shutdown_and_snapshot();
3994
+ return;
3995
+ }
3996
+
3997
+ info!("------------------------- Beginning test -------------------------");
3998
+
3999
+ let tip = signer_test.get_peer_info();
4000
+
4001
+ info!("---- Tip ----";
4002
+ "tip.stacks_tip_height" => tip.stacks_tip_height,
4003
+ "tip.burn_block_height" => tip.burn_block_height,
4004
+ );
4005
+
4006
+ let pre_fork_tenures = 1;
4007
+ for i in 0..pre_fork_tenures {
4008
+ info!("Mining pre-fork tenure {} of {pre_fork_tenures}", i + 1);
4009
+ signer_test.mine_nakamoto_block(Duration::from_secs(30), true);
4010
+ }
4011
+
4012
+ info!("---- Submitting STX transfer ----");
4013
+
4014
+ // let tip = get_chain_info(&conf);
4015
+ // Make a transfer tx (this will get forked)
4016
+ let (txid, nonce) = signer_test
4017
+ .submit_transfer_tx(&sender_sk, send_fee, send_amt)
4018
+ .unwrap();
4019
+
4020
+ // Ensure we got a new block with this tx
4021
+ signer_test
4022
+ .wait_for_nonce_increase(&sender_addr, nonce)
4023
+ .expect("Timed out waiting for transfer tx to be mined");
4024
+
4025
+ let tip_before = get_chain_info(&conf);
4026
+
4027
+ info!("---- Triggering Bitcoin fork ----";
4028
+ "tip.stacks_tip_height" => tip_before.stacks_tip_height,
4029
+ "tip.burn_block_height" => tip_before.burn_block_height,
4030
+ "tip.consensus_hash" => %tip_before.pox_consensus,
4031
+ );
4032
+
4033
+ let burn_header_hash_to_fork = btc_controller.get_block_hash(tip_before.burn_block_height);
4034
+ btc_controller.invalidate_block(&burn_header_hash_to_fork);
4035
+ TEST_MINE_STALL.set(true);
4036
+ btc_controller.build_next_block(2);
4037
+
4038
+ wait_for(30, || {
4039
+ let tip = get_chain_info(&conf);
4040
+ Ok(tip.stacks_tip_height < tip_before.stacks_tip_height)
4041
+ })
4042
+ .expect("Timed out waiting for next block to be mined");
4043
+
4044
+ let tip = get_chain_info(&conf);
4045
+
4046
+ info!("---- Tip after fork ----";
4047
+ "tip.stacks_tip_height" => tip.stacks_tip_height,
4048
+ "tip.burn_block_height" => tip.burn_block_height,
4049
+ );
4050
+
4051
+ info!("---- Wait for tx replay set to be updated ----");
4052
+
4053
+ signer_test.wait_for_replay_set_eq(5, vec![txid.clone()]);
4054
+
4055
+ signer_test.shutdown();
4056
+ }
4057
+
3946
4058
/// Test scenario where two signers disagree on the tx replay set,
3947
4059
/// which means there is no consensus on the tx replay set.
3948
4060
#[test]
@@ -4488,6 +4600,7 @@ fn tx_replay_with_fork_after_empty_tenures_before_starting_replaying_txs() {
4488
4600
vec![(sender1_addr, (send_amt + send_fee) * num_txs)],
4489
4601
|c| {
4490
4602
c.validate_with_replay_tx = true;
4603
+ c.reset_replay_set_after_fork_blocks = 5;
4491
4604
},
4492
4605
|node_config| {
4493
4606
node_config.miner.block_commit_delay = Duration::from_secs(1);
@@ -4859,6 +4972,7 @@ fn tx_replay_with_fork_middle_replay_while_tenure_extending() {
4859
4972
|c| {
4860
4973
c.validate_with_replay_tx = true;
4861
4974
c.tenure_idle_timeout = Duration::from_secs(10);
4975
+ c.reset_replay_set_after_fork_blocks = 5;
4862
4976
},
4863
4977
|node_config| {
4864
4978
node_config.miner.block_commit_delay = Duration::from_secs(1);
0 commit comments