@@ -578,6 +578,15 @@ impl Burnchain {
578
578
. nakamoto_first_block_of_cycle ( self . first_block_height , reward_cycle)
579
579
}
580
580
581
+ #[ cfg( any( test, feature = "testing" ) ) ]
582
+ /// the last burn block that must be *signed* by the signer set of `reward_cycle`.
583
+ /// this is the modulo -1 block
584
+ pub fn nakamoto_last_block_of_cycle ( & self , reward_cycle : u64 ) -> u64 {
585
+ self . nakamoto_first_block_of_cycle ( reward_cycle)
586
+ + self . pox_constants . reward_cycle_length as u64
587
+ - 1
588
+ }
589
+
581
590
/// What is the reward cycle for this block height?
582
591
/// This considers the modulo 0 block to be in reward cycle `n`, even though
583
592
/// rewards for cycle `n` do not begin until modulo 1.
@@ -1765,3 +1774,173 @@ impl Burnchain {
1765
1774
Ok ( block_header)
1766
1775
}
1767
1776
}
1777
+
1778
+ #[ cfg( test) ]
1779
+ mod tests {
1780
+ use regex:: Regex ;
1781
+
1782
+ use super :: * ;
1783
+ use crate :: burnchains:: * ;
1784
+
1785
+ #[ test]
1786
+ fn test_creation_by_new_for_bitcoin_mainnet ( ) {
1787
+ let burn_chain = Burnchain :: new ( "workdir/path" , "bitcoin" , "mainnet" ) ;
1788
+ assert ! ( burn_chain. is_ok( ) ) ;
1789
+
1790
+ let burn_chain = burn_chain. unwrap ( ) ;
1791
+ let first_block_hash =
1792
+ BurnchainHeaderHash :: from_hex ( BITCOIN_MAINNET_FIRST_BLOCK_HASH ) . unwrap ( ) ;
1793
+ assert_eq ! ( PEER_VERSION_MAINNET , burn_chain. peer_version) ;
1794
+ assert_eq ! ( BITCOIN_NETWORK_ID_MAINNET , burn_chain. network_id) ;
1795
+ assert_eq ! ( BITCOIN_MAINNET_NAME , burn_chain. network_name) ;
1796
+ assert_eq ! ( "workdir/path" , burn_chain. working_dir) ;
1797
+ assert_eq ! ( 24 , burn_chain. consensus_hash_lifetime) ;
1798
+ assert_eq ! ( 7 , burn_chain. stable_confirmations) ;
1799
+ assert_eq ! (
1800
+ BITCOIN_MAINNET_FIRST_BLOCK_HEIGHT ,
1801
+ burn_chain. first_block_height
1802
+ ) ;
1803
+ assert_eq ! ( first_block_hash, burn_chain. first_block_hash) ;
1804
+ assert_eq ! (
1805
+ BITCOIN_MAINNET_FIRST_BLOCK_TIMESTAMP ,
1806
+ burn_chain. first_block_timestamp
1807
+ ) ;
1808
+ assert_eq ! ( PoxConstants :: mainnet_default( ) , burn_chain. pox_constants) ;
1809
+ assert_eq ! (
1810
+ BITCOIN_MAINNET_INITIAL_REWARD_START_BLOCK ,
1811
+ burn_chain. initial_reward_start_block
1812
+ ) ;
1813
+ }
1814
+
1815
+ #[ test]
1816
+ fn test_creation_by_new_for_bitcoin_testnet ( ) {
1817
+ let burn_chain = Burnchain :: new ( "workdir/path" , "bitcoin" , "testnet" ) ;
1818
+ assert ! ( burn_chain. is_ok( ) ) ;
1819
+
1820
+ let burn_chain = burn_chain. unwrap ( ) ;
1821
+ let first_block_hash =
1822
+ BurnchainHeaderHash :: from_hex ( BITCOIN_TESTNET_FIRST_BLOCK_HASH ) . unwrap ( ) ;
1823
+ assert_eq ! ( PEER_VERSION_TESTNET , burn_chain. peer_version) ;
1824
+ assert_eq ! ( BITCOIN_NETWORK_ID_TESTNET , burn_chain. network_id) ;
1825
+ assert_eq ! ( BITCOIN_TESTNET_NAME , burn_chain. network_name) ;
1826
+ assert_eq ! ( "workdir/path" , burn_chain. working_dir) ;
1827
+ assert_eq ! ( 24 , burn_chain. consensus_hash_lifetime) ;
1828
+ assert_eq ! ( 7 , burn_chain. stable_confirmations) ;
1829
+ assert_eq ! (
1830
+ BITCOIN_TESTNET_FIRST_BLOCK_HEIGHT ,
1831
+ burn_chain. first_block_height
1832
+ ) ;
1833
+ assert_eq ! ( first_block_hash, burn_chain. first_block_hash) ;
1834
+ assert_eq ! (
1835
+ BITCOIN_TESTNET_FIRST_BLOCK_TIMESTAMP ,
1836
+ burn_chain. first_block_timestamp
1837
+ ) ;
1838
+ assert_eq ! ( PoxConstants :: testnet_default( ) , burn_chain. pox_constants) ;
1839
+ assert_eq ! ( 1_990_000 , burn_chain. initial_reward_start_block) ;
1840
+ }
1841
+
1842
+ #[ test]
1843
+ fn test_creation_by_new_for_bitcoin_regtest ( ) {
1844
+ let burn_chain = Burnchain :: new ( "workdir/path" , "bitcoin" , "regtest" ) ;
1845
+ assert ! ( burn_chain. is_ok( ) ) ;
1846
+
1847
+ let burn_chain = burn_chain. unwrap ( ) ;
1848
+ let first_block_hash =
1849
+ BurnchainHeaderHash :: from_hex ( BITCOIN_REGTEST_FIRST_BLOCK_HASH ) . unwrap ( ) ;
1850
+ assert_eq ! ( PEER_VERSION_TESTNET , burn_chain. peer_version) ;
1851
+ assert_eq ! ( BITCOIN_NETWORK_ID_REGTEST , burn_chain. network_id) ;
1852
+ assert_eq ! ( BITCOIN_REGTEST_NAME , burn_chain. network_name) ;
1853
+ assert_eq ! ( "workdir/path" , burn_chain. working_dir) ;
1854
+ assert_eq ! ( 24 , burn_chain. consensus_hash_lifetime) ;
1855
+ assert_eq ! ( 1 , burn_chain. stable_confirmations) ;
1856
+ assert_eq ! (
1857
+ BITCOIN_REGTEST_FIRST_BLOCK_HEIGHT ,
1858
+ burn_chain. first_block_height
1859
+ ) ;
1860
+ assert_eq ! ( first_block_hash, burn_chain. first_block_hash) ;
1861
+ assert_eq ! (
1862
+ BITCOIN_REGTEST_FIRST_BLOCK_TIMESTAMP ,
1863
+ burn_chain. first_block_timestamp
1864
+ ) ;
1865
+ assert_eq ! ( PoxConstants :: regtest_default( ) , burn_chain. pox_constants) ;
1866
+ assert_eq ! (
1867
+ BITCOIN_REGTEST_FIRST_BLOCK_HEIGHT ,
1868
+ burn_chain. initial_reward_start_block
1869
+ ) ;
1870
+ }
1871
+
1872
+ #[ test]
1873
+ fn test_creation_by_new_failure ( ) {
1874
+ //case: wrong chain name
1875
+ let burn_chain = Burnchain :: new ( "workdir/path" , "wrong_chain_name" , "regtest" ) ;
1876
+ assert ! ( burn_chain. is_err( ) ) ;
1877
+ assert ! ( matches!(
1878
+ burn_chain. unwrap_err( ) ,
1879
+ burnchain_error:: UnsupportedBurnchain
1880
+ ) ) ;
1881
+
1882
+ //case: wrong network name
1883
+ let burn_chain = Burnchain :: new ( "workdir/path" , "bitcoin" , "wrong_net_name" ) ;
1884
+ assert ! ( burn_chain. is_err( ) ) ;
1885
+ assert ! ( matches!(
1886
+ burn_chain. unwrap_err( ) ,
1887
+ burnchain_error:: UnsupportedBurnchain
1888
+ ) ) ;
1889
+
1890
+ //case: wrong chain name + wrong network name
1891
+ let burn_chain = Burnchain :: new ( "workdir/path" , "wrong_chain_name" , "wrong_net_name" ) ;
1892
+ assert ! ( burn_chain. is_err( ) ) ;
1893
+ assert ! ( matches!(
1894
+ burn_chain. unwrap_err( ) ,
1895
+ burnchain_error:: UnsupportedBurnchain
1896
+ ) ) ;
1897
+ }
1898
+
1899
+ #[ test]
1900
+ fn test_creation_by_default_unittest ( ) {
1901
+ let first_block_height = 0 ;
1902
+ let first_block_hash = BurnchainHeaderHash ( [ 0u8 ; 32 ] ) ;
1903
+ let burn_chain = Burnchain :: default_unittest ( first_block_height, & first_block_hash) ;
1904
+
1905
+ let workdir_re = Regex :: new ( r"^/tmp/stacks-node-tests/unit-tests-[0-9a-f]{32}$" ) . unwrap ( ) ;
1906
+
1907
+ assert_eq ! ( PEER_VERSION_MAINNET , burn_chain. peer_version) ;
1908
+ assert_eq ! ( BITCOIN_NETWORK_ID_MAINNET , burn_chain. network_id) ;
1909
+ assert_eq ! ( BITCOIN_MAINNET_NAME , burn_chain. network_name) ;
1910
+ assert ! ( workdir_re. is_match( & burn_chain. working_dir) ) ;
1911
+ assert_eq ! ( 24 , burn_chain. consensus_hash_lifetime) ;
1912
+ assert_eq ! ( 7 , burn_chain. stable_confirmations) ;
1913
+ assert_eq ! ( first_block_height, burn_chain. first_block_height) ;
1914
+ assert_eq ! ( first_block_hash, burn_chain. first_block_hash) ;
1915
+ assert_eq ! (
1916
+ BITCOIN_MAINNET_FIRST_BLOCK_TIMESTAMP ,
1917
+ burn_chain. first_block_timestamp
1918
+ ) ;
1919
+ assert_eq ! ( PoxConstants :: mainnet_default( ) , burn_chain. pox_constants) ;
1920
+ assert_eq ! ( first_block_height, burn_chain. initial_reward_start_block) ;
1921
+ }
1922
+
1923
+ #[ test]
1924
+ fn test_nakamoto_reward_cycle_boundaries ( ) {
1925
+ let first_block_height = 0 ;
1926
+ let first_block_hash = BurnchainHeaderHash ( [ 0u8 ; 32 ] ) ;
1927
+ let burn_chain = Burnchain :: default_unittest ( first_block_height, & first_block_hash) ;
1928
+
1929
+ //making obvious the reward cycle length used
1930
+ assert_eq ! ( 2100 , burn_chain. pox_constants. reward_cycle_length) ;
1931
+
1932
+ //Reward Cycle: 0
1933
+ let rc = 0 ;
1934
+ let rc_first_block = burn_chain. nakamoto_first_block_of_cycle ( rc) ;
1935
+ let rc_last_block = burn_chain. nakamoto_last_block_of_cycle ( rc) ;
1936
+ assert_eq ! ( 0 , rc_first_block) ;
1937
+ assert_eq ! ( 2099 , rc_last_block) ;
1938
+
1939
+ //Reward Cycle: 1
1940
+ let rc = 1 ;
1941
+ let rc_first_block = burn_chain. nakamoto_first_block_of_cycle ( rc) ;
1942
+ let rc_last_block = burn_chain. nakamoto_last_block_of_cycle ( rc) ;
1943
+ assert_eq ! ( 2100 , rc_first_block) ;
1944
+ assert_eq ! ( 4199 , rc_last_block) ;
1945
+ }
1946
+ }
0 commit comments