@@ -1740,6 +1740,226 @@ fn simple_neon_integration() {
1740
1740
run_loop_thread. join ( ) . unwrap ( ) ;
1741
1741
}
1742
1742
1743
+ #[ test]
1744
+ #[ ignore]
1745
+ /// Test a scenario in which a miner is restarted right before a tenure
1746
+ /// which they won. The miner, on restart, should begin mining the new tenure.
1747
+ fn restarting_miner ( ) {
1748
+ if env:: var ( "BITCOIND_TEST" ) != Ok ( "1" . into ( ) ) {
1749
+ return ;
1750
+ }
1751
+
1752
+ let ( mut naka_conf, _miner_account) = naka_neon_integration_conf ( None ) ;
1753
+ let prom_bind = "127.0.0.1:6000" . to_string ( ) ;
1754
+ naka_conf. node . prometheus_bind = Some ( prom_bind. clone ( ) ) ;
1755
+ naka_conf. miner . activated_vrf_key_path =
1756
+ Some ( format ! ( "{}/vrf_key" , naka_conf. node. working_dir) ) ;
1757
+ naka_conf. miner . wait_on_interim_blocks = Duration :: from_secs ( 5 ) ;
1758
+ let sender_sk = Secp256k1PrivateKey :: new ( ) ;
1759
+ // setup sender + recipient for a test stx transfer
1760
+ let sender_addr = tests:: to_addr ( & sender_sk) ;
1761
+ let send_amt = 1000 ;
1762
+ let send_fee = 100 ;
1763
+ naka_conf. add_initial_balance (
1764
+ PrincipalData :: from ( sender_addr) . to_string ( ) ,
1765
+ send_amt * 2 + send_fee,
1766
+ ) ;
1767
+ let sender_signer_sk = Secp256k1PrivateKey :: new ( ) ;
1768
+ let sender_signer_addr = tests:: to_addr ( & sender_signer_sk) ;
1769
+ let mut signers = TestSigners :: new ( vec ! [ sender_signer_sk] ) ;
1770
+ naka_conf. add_initial_balance ( PrincipalData :: from ( sender_signer_addr) . to_string ( ) , 100000 ) ;
1771
+ let stacker_sk = setup_stacker ( & mut naka_conf) ;
1772
+
1773
+ test_observer:: spawn ( ) ;
1774
+ test_observer:: register_any ( & mut naka_conf) ;
1775
+
1776
+ let mut btcd_controller = BitcoinCoreController :: new ( naka_conf. clone ( ) ) ;
1777
+ btcd_controller
1778
+ . start_bitcoind ( )
1779
+ . expect ( "Failed starting bitcoind" ) ;
1780
+ let mut btc_regtest_controller = BitcoinRegtestController :: new ( naka_conf. clone ( ) , None ) ;
1781
+ btc_regtest_controller. bootstrap_chain ( 201 ) ;
1782
+
1783
+ let mut run_loop = boot_nakamoto:: BootRunLoop :: new ( naka_conf. clone ( ) ) . unwrap ( ) ;
1784
+ let run_loop_stopper = run_loop. get_termination_switch ( ) ;
1785
+ let Counters {
1786
+ blocks_processed,
1787
+ naka_submitted_commits : commits_submitted,
1788
+ naka_proposed_blocks : proposals_submitted,
1789
+ ..
1790
+ } = run_loop. counters ( ) ;
1791
+ let coord_channel = run_loop. coordinator_channels ( ) ;
1792
+
1793
+ let mut run_loop_2 = boot_nakamoto:: BootRunLoop :: new ( naka_conf. clone ( ) ) . unwrap ( ) ;
1794
+ let _run_loop_2_stopper = run_loop. get_termination_switch ( ) ;
1795
+ let Counters {
1796
+ blocks_processed : blocks_processed_2,
1797
+ naka_submitted_commits : commits_submitted_2,
1798
+ naka_proposed_blocks : proposals_submitted_2,
1799
+ ..
1800
+ } = run_loop_2. counters ( ) ;
1801
+ let coord_channel_2 = run_loop_2. coordinator_channels ( ) ;
1802
+
1803
+ let run_loop_thread = thread:: spawn ( move || run_loop. start ( None , 0 ) ) ;
1804
+ wait_for_runloop ( & blocks_processed) ;
1805
+ boot_to_epoch_3 (
1806
+ & naka_conf,
1807
+ & blocks_processed,
1808
+ & [ stacker_sk] ,
1809
+ & [ sender_signer_sk] ,
1810
+ & mut Some ( & mut signers) ,
1811
+ & mut btc_regtest_controller,
1812
+ ) ;
1813
+
1814
+ info ! ( "Bootstrapped to Epoch-3.0 boundary, starting nakamoto miner" ) ;
1815
+
1816
+ let burnchain = naka_conf. get_burnchain ( ) ;
1817
+ let sortdb = burnchain. open_sortition_db ( true ) . unwrap ( ) ;
1818
+ let ( chainstate, _) = StacksChainState :: open (
1819
+ naka_conf. is_mainnet ( ) ,
1820
+ naka_conf. burnchain . chain_id ,
1821
+ & naka_conf. get_chainstate_path_str ( ) ,
1822
+ None ,
1823
+ )
1824
+ . unwrap ( ) ;
1825
+
1826
+ let block_height_pre_3_0 =
1827
+ NakamotoChainState :: get_canonical_block_header ( chainstate. db ( ) , & sortdb)
1828
+ . unwrap ( )
1829
+ . unwrap ( )
1830
+ . stacks_block_height ;
1831
+
1832
+ info ! ( "Nakamoto miner started..." ) ;
1833
+ blind_signer_multinode (
1834
+ & signers,
1835
+ & [ & naka_conf, & naka_conf] ,
1836
+ vec ! [ proposals_submitted, proposals_submitted_2] ,
1837
+ ) ;
1838
+
1839
+ wait_for_first_naka_block_commit ( 60 , & commits_submitted) ;
1840
+
1841
+ // Mine 2 nakamoto tenures
1842
+ for _i in 0 ..2 {
1843
+ next_block_and_mine_commit (
1844
+ & mut btc_regtest_controller,
1845
+ 60 ,
1846
+ & coord_channel,
1847
+ & commits_submitted,
1848
+ )
1849
+ . unwrap ( ) ;
1850
+ }
1851
+
1852
+ let last_tip = NakamotoChainState :: get_canonical_block_header ( chainstate. db ( ) , & sortdb)
1853
+ . unwrap ( )
1854
+ . unwrap ( ) ;
1855
+ info ! (
1856
+ "Latest tip" ;
1857
+ "height" => last_tip. stacks_block_height,
1858
+ "is_nakamoto" => last_tip. anchored_header. as_stacks_nakamoto( ) . is_some( ) ,
1859
+ ) ;
1860
+
1861
+ // close the current miner
1862
+ coord_channel
1863
+ . lock ( )
1864
+ . expect ( "Mutex poisoned" )
1865
+ . stop_chains_coordinator ( ) ;
1866
+ run_loop_stopper. store ( false , Ordering :: SeqCst ) ;
1867
+ run_loop_thread. join ( ) . unwrap ( ) ;
1868
+
1869
+ // mine a bitcoin block -- this should include a winning commit from
1870
+ // the miner
1871
+ btc_regtest_controller. build_next_block ( 1 ) ;
1872
+
1873
+ // start it back up
1874
+
1875
+ let _run_loop_thread = thread:: spawn ( move || run_loop_2. start ( None , 0 ) ) ;
1876
+ wait_for_runloop ( & blocks_processed_2) ;
1877
+
1878
+ info ! ( " ================= RESTARTED THE MINER =================" ) ;
1879
+
1880
+ let tip = NakamotoChainState :: get_canonical_block_header ( chainstate. db ( ) , & sortdb)
1881
+ . unwrap ( )
1882
+ . unwrap ( ) ;
1883
+ info ! (
1884
+ "Latest tip" ;
1885
+ "height" => tip. stacks_block_height,
1886
+ "is_nakamoto" => tip. anchored_header. as_stacks_nakamoto( ) . is_some( ) ,
1887
+ ) ;
1888
+
1889
+ wait_for ( 60 , || {
1890
+ let tip = NakamotoChainState :: get_canonical_block_header ( chainstate. db ( ) , & sortdb)
1891
+ . unwrap ( )
1892
+ . unwrap ( ) ;
1893
+ Ok ( tip. stacks_block_height > last_tip. stacks_block_height )
1894
+ } )
1895
+ . unwrap_or_else ( |e| {
1896
+ let tip = NakamotoChainState :: get_canonical_block_header ( chainstate. db ( ) , & sortdb)
1897
+ . unwrap ( )
1898
+ . unwrap ( ) ;
1899
+
1900
+ error ! (
1901
+ "Failed to get a new block after restart" ;
1902
+ "last_tip_height" => last_tip. stacks_block_height,
1903
+ "latest_tip" => tip. stacks_block_height,
1904
+ "error" => & e,
1905
+ ) ;
1906
+
1907
+ panic ! ( "{e}" )
1908
+ } ) ;
1909
+
1910
+ // Mine 2 more nakamoto tenures
1911
+ for _i in 0 ..2 {
1912
+ next_block_and_mine_commit (
1913
+ & mut btc_regtest_controller,
1914
+ 60 ,
1915
+ & coord_channel_2,
1916
+ & commits_submitted_2,
1917
+ )
1918
+ . unwrap ( ) ;
1919
+ }
1920
+
1921
+ // load the chain tip, and assert that it is a nakamoto block and at least 30 blocks have advanced in epoch 3
1922
+ let tip = NakamotoChainState :: get_canonical_block_header ( chainstate. db ( ) , & sortdb)
1923
+ . unwrap ( )
1924
+ . unwrap ( ) ;
1925
+ info ! (
1926
+ "=== Last tip ===" ;
1927
+ "height" => tip. stacks_block_height,
1928
+ "is_nakamoto" => tip. anchored_header. as_stacks_nakamoto( ) . is_some( ) ,
1929
+ ) ;
1930
+
1931
+ assert ! ( tip. anchored_header. as_stacks_nakamoto( ) . is_some( ) ) ;
1932
+
1933
+ // Check that we aren't missing burn blocks
1934
+ let bhh = u64:: from ( tip. burn_header_height ) ;
1935
+ // make sure every burn block after the nakamoto transition has a mined
1936
+ // nakamoto block in it.
1937
+ let missing = test_observer:: get_missing_burn_blocks ( 220 ..=bhh) . unwrap ( ) ;
1938
+
1939
+ // This test was flakey because it was sometimes missing burn block 230, which is right at the Nakamoto transition
1940
+ // So it was possible to miss a burn block during the transition
1941
+ // But I don't it matters at this point since the Nakamoto transition has already happened on mainnet
1942
+ // So just print a warning instead, don't count it as an error
1943
+ let missing_is_error: Vec < _ > = missing
1944
+ . into_iter ( )
1945
+ . filter ( |i| match i {
1946
+ 230 => {
1947
+ warn ! ( "Missing burn block {i}" ) ;
1948
+ false
1949
+ }
1950
+ _ => true ,
1951
+ } )
1952
+ . collect ( ) ;
1953
+
1954
+ if !missing_is_error. is_empty ( ) {
1955
+ panic ! ( "Missing the following burn blocks: {missing_is_error:?}" ) ;
1956
+ }
1957
+
1958
+ check_nakamoto_empty_block_heuristics ( ) ;
1959
+
1960
+ assert ! ( tip. stacks_block_height >= block_height_pre_3_0 + 4 ) ;
1961
+ }
1962
+
1743
1963
#[ test]
1744
1964
#[ ignore]
1745
1965
/// This test spins up a nakamoto-neon node.
0 commit comments