@ -39,6 +39,97 @@ using namespace cryptonote;
# define BLOCKS_PER_YEAR 525960
# define SECONDS_PER_YEAR 31557600
class TestDB : public BlockchainDB {
public :
virtual void open ( const std : : string & filename , const int db_flags = 0 ) {
for ( size_t n = 0 ; n < 256 ; + + n )
starting_height [ n ] = std : : numeric_limits < uint64_t > : : max ( ) ;
}
virtual void close ( ) { }
virtual void sync ( ) { }
virtual void reset ( ) { }
virtual std : : vector < std : : string > get_filenames ( ) const { return std : : vector < std : : string > ( ) ; }
virtual std : : string get_db_name ( ) const { return std : : string ( ) ; }
virtual bool lock ( ) { return true ; }
virtual void unlock ( ) { }
virtual void batch_start ( uint64_t batch_num_blocks = 0 ) { }
virtual void batch_stop ( ) { }
virtual void set_batch_transactions ( bool ) { }
virtual bool block_exists ( const crypto : : hash & h ) const { return false ; }
virtual block get_block ( const crypto : : hash & h ) const { return block ( ) ; }
virtual uint64_t get_block_height ( const crypto : : hash & h ) const { return 0 ; }
virtual block_header get_block_header ( const crypto : : hash & h ) const { return block_header ( ) ; }
virtual uint64_t get_block_timestamp ( const uint64_t & height ) const { return 0 ; }
virtual uint64_t get_top_block_timestamp ( ) const { return 0 ; }
virtual size_t get_block_size ( const uint64_t & height ) const { return 128 ; }
virtual difficulty_type get_block_cumulative_difficulty ( const uint64_t & height ) const { return 10 ; }
virtual difficulty_type get_block_difficulty ( const uint64_t & height ) const { return 0 ; }
virtual uint64_t get_block_already_generated_coins ( const uint64_t & height ) const { return 10000000000 ; }
virtual crypto : : hash get_block_hash_from_height ( const uint64_t & height ) const { return crypto : : hash ( ) ; }
virtual std : : vector < block > get_blocks_range ( const uint64_t & h1 , const uint64_t & h2 ) const { return std : : vector < block > ( ) ; }
virtual std : : vector < crypto : : hash > get_hashes_range ( const uint64_t & h1 , const uint64_t & h2 ) const { return std : : vector < crypto : : hash > ( ) ; }
virtual crypto : : hash top_block_hash ( ) const { return crypto : : hash ( ) ; }
virtual block get_top_block ( ) const { return block ( ) ; }
virtual uint64_t height ( ) const { return blocks . size ( ) ; }
virtual bool tx_exists ( const crypto : : hash & h ) const { return false ; }
virtual uint64_t get_tx_unlock_time ( const crypto : : hash & h ) const { return 0 ; }
virtual transaction get_tx ( const crypto : : hash & h ) const { return transaction ( ) ; }
virtual uint64_t get_tx_count ( ) const { return 0 ; }
virtual std : : vector < transaction > get_tx_list ( const std : : vector < crypto : : hash > & hlist ) const { return std : : vector < transaction > ( ) ; }
virtual uint64_t get_tx_block_height ( const crypto : : hash & h ) const { return 0 ; }
virtual uint64_t get_num_outputs ( const uint64_t & amount ) const { return 1 ; }
virtual output_data_t get_output_key ( const uint64_t & amount , const uint64_t & index ) { return output_data_t ( ) ; }
virtual output_data_t get_output_key ( const uint64_t & global_index ) const { return output_data_t ( ) ; }
virtual tx_out get_output ( const crypto : : hash & h , const uint64_t & index ) const { return tx_out ( ) ; }
virtual tx_out_index get_output_tx_and_index_from_global ( const uint64_t & index ) const { return tx_out_index ( ) ; }
virtual tx_out_index get_output_tx_and_index ( const uint64_t & amount , const uint64_t & index ) { return tx_out_index ( ) ; }
virtual void get_output_tx_and_index ( const uint64_t & amount , const std : : vector < uint64_t > & offsets , std : : vector < tx_out_index > & indices ) { }
virtual void get_output_key ( const uint64_t & amount , const std : : vector < uint64_t > & offsets , std : : vector < output_data_t > & outputs ) { }
virtual bool can_thread_bulk_indices ( ) const { return false ; }
virtual std : : vector < uint64_t > get_tx_output_indices ( const crypto : : hash & h ) const { return std : : vector < uint64_t > ( ) ; }
virtual std : : vector < uint64_t > get_tx_amount_output_indices ( const crypto : : hash & h ) const { return std : : vector < uint64_t > ( ) ; }
virtual bool has_key_image ( const crypto : : key_image & img ) const { return false ; }
virtual void remove_block ( ) { blocks . pop_back ( ) ; }
virtual void add_transaction_data ( const crypto : : hash & blk_hash , const transaction & tx , const crypto : : hash & tx_hash ) { }
virtual void remove_transaction_data ( const crypto : : hash & tx_hash , const transaction & tx ) { }
virtual void add_output ( const crypto : : hash & tx_hash , const tx_out & tx_output , const uint64_t & local_index , const uint64_t unlock_time ) { }
virtual void remove_output ( const tx_out & tx_output ) { }
virtual void add_spent_key ( const crypto : : key_image & k_image ) { }
virtual void remove_spent_key ( const crypto : : key_image & k_image ) { }
virtual void add_block ( const block & blk
, const size_t & block_size
, const difficulty_type & cumulative_difficulty
, const uint64_t & coins_generated
, const crypto : : hash & blk_hash
) {
blocks . push_back ( blk ) ;
}
virtual block get_block_from_height ( const uint64_t & height ) const {
return blocks [ height ] ;
}
virtual void set_hard_fork_starting_height ( uint8_t version , uint64_t height ) {
starting_height [ version ] = height ;
}
virtual uint64_t get_hard_fork_starting_height ( uint8_t version ) const {
return starting_height [ version ] ;
}
virtual void set_hard_fork_version ( uint64_t height , uint8_t version ) {
printf ( " set_hard_fork_version(%lu, %u) \n " , ( unsigned long ) height , version ) ;
if ( versions . size ( ) < = height ) versions . resize ( height + 1 ) ; versions [ height ] = version ;
}
virtual uint8_t get_hard_fork_version ( uint64_t height ) const {
printf ( " get_hard_fork_version(%lu) \n " , ( unsigned long ) height ) ;
return versions [ height ] ;
}
private :
std : : vector < block > blocks ;
uint64_t starting_height [ 256 ] ;
std : : deque < uint8_t > versions ;
} ;
static cryptonote : : block mkblock ( uint8_t version )
{
cryptonote : : block b ;
@ -48,19 +139,27 @@ static cryptonote::block mkblock(uint8_t version)
TEST ( empty_hardforks , Success )
{
HardFork hf ;
TestDB db ;
HardFork hf ( db ) ;
ASSERT_TRUE ( hf . add ( 1 , 0 , 0 ) ) ;
hf . init ( ) ;
ASSERT_TRUE ( hf . get_state ( time ( NULL ) ) = = HardFork : : Ready ) ;
ASSERT_TRUE ( hf . get_state ( time ( NULL ) + 3600 * 24 * 400 ) = = HardFork : : Ready ) ;
for ( uint64_t h = 0 ; h < = 10 ; + + h ) {
db . add_block ( mkblock ( 1 ) , 0 , 0 , 0 , crypto : : hash ( ) ) ;
ASSERT_TRUE ( hf . add ( db . get_block_from_height ( h ) , h ) ) ;
}
ASSERT_EQ ( hf . get ( 0 ) , 1 ) ;
ASSERT_EQ ( hf . get ( 1 ) , 1 ) ;
ASSERT_EQ ( hf . get ( 100000000 ) , 1 ) ;
ASSERT_EQ ( hf . get ( 10 ) , 1 ) ;
}
TEST ( ordering , Success )
{
HardFork hf ;
TestDB db ;
HardFork hf ( db ) ;
ASSERT_TRUE ( hf . add ( 2 , 2 , 1 ) ) ;
ASSERT_FALSE ( hf . add ( 3 , 3 , 1 ) ) ;
@ -73,8 +172,10 @@ TEST(ordering, Success)
TEST ( states , Success )
{
HardFork hf ;
TestDB db ;
HardFork hf ( db ) ;
ASSERT_TRUE ( hf . add ( 1 , 0 , 0 ) ) ;
ASSERT_TRUE ( hf . add ( 2 , BLOCKS_PER_YEAR , SECONDS_PER_YEAR ) ) ;
ASSERT_TRUE ( hf . get_state ( 0 ) = = HardFork : : Ready ) ;
@ -94,15 +195,20 @@ TEST(states, Success)
TEST ( steps_asap , Success )
{
HardFork hf ( 1 , 1 , 1 , 1 ) ;
TestDB db ;
HardFork hf ( db , 1 , 1 , 1 , 1 ) ;
// v h t
ASSERT_TRUE ( hf . add ( 1 , 0 , 0 ) ) ;
ASSERT_TRUE ( hf . add ( 4 , 2 , 1 ) ) ;
ASSERT_TRUE ( hf . add ( 7 , 4 , 2 ) ) ;
ASSERT_TRUE ( hf . add ( 9 , 6 , 3 ) ) ;
hf . init ( ) ;
for ( uint64_t h = 0 ; h < 10 ; + + h )
hf . add ( mkblock ( 10 ) , h ) ;
for ( uint64_t h = 0 ; h < 10 ; + + h ) {
db . add_block ( mkblock ( 10 ) , 0 , 0 , 0 , crypto : : hash ( ) ) ;
ASSERT_TRUE ( hf . add ( db . get_block_from_height ( h ) , h ) ) ;
}
ASSERT_EQ ( hf . get ( 0 ) , 1 ) ;
ASSERT_EQ ( hf . get ( 1 ) , 1 ) ;
@ -114,195 +220,142 @@ TEST(steps_asap, Success)
ASSERT_EQ ( hf . get ( 7 ) , 9 ) ;
ASSERT_EQ ( hf . get ( 8 ) , 9 ) ;
ASSERT_EQ ( hf . get ( 9 ) , 9 ) ;
ASSERT_EQ ( hf . get ( 100000 ) , 9 ) ;
}
TEST ( steps_1 , Success )
{
HardFork hf ( 1 , 1 , 1 , 1 ) ;
TestDB db ;
HardFork hf ( db , 1 , 1 , 1 , 1 ) ;
// v h t
ASSERT_TRUE ( hf . add ( 1 , 0 , 0 ) ) ;
for ( int n = 1 ; n < 10 ; + + n )
ASSERT_TRUE ( hf . add ( n + 1 , n , n ) ) ;
hf . init ( ) ;
for ( uint64_t h = 0 ; h < 10 ; + + h ) {
db . add_block ( mkblock ( h + 1 ) , 0 , 0 , 0 , crypto : : hash ( ) ) ;
ASSERT_TRUE ( hf . add ( db . get_block_from_height ( h ) , h ) ) ;
}
for ( uint64_t h = 0 ; h < 10 ; + + h ) {
hf . add ( mkblock ( h + 1 ) , h ) ;
ASSERT_EQ ( hf . get ( h ) , h + 1 ) ;
}
}
class TestDB : public BlockchainDB {
public :
virtual void open ( const std : : string & filename , const int db_flags = 0 ) { }
virtual void close ( ) { }
virtual void sync ( ) { }
virtual void reset ( ) { }
virtual std : : vector < std : : string > get_filenames ( ) const { return std : : vector < std : : string > ( ) ; }
virtual std : : string get_db_name ( ) const { return std : : string ( ) ; }
virtual bool lock ( ) { return true ; }
virtual void unlock ( ) { }
virtual void batch_start ( uint64_t batch_num_blocks = 0 ) { }
virtual void batch_stop ( ) { }
virtual void set_batch_transactions ( bool ) { }
virtual bool block_exists ( const crypto : : hash & h ) const { return false ; }
virtual block get_block ( const crypto : : hash & h ) const { return block ( ) ; }
virtual uint64_t get_block_height ( const crypto : : hash & h ) const { return 0 ; }
virtual block_header get_block_header ( const crypto : : hash & h ) const { return block_header ( ) ; }
virtual uint64_t get_block_timestamp ( const uint64_t & height ) const { return 0 ; }
virtual uint64_t get_top_block_timestamp ( ) const { return 0 ; }
virtual size_t get_block_size ( const uint64_t & height ) const { return 128 ; }
virtual difficulty_type get_block_cumulative_difficulty ( const uint64_t & height ) const { return 10 ; }
virtual difficulty_type get_block_difficulty ( const uint64_t & height ) const { return 0 ; }
virtual uint64_t get_block_already_generated_coins ( const uint64_t & height ) const { return 10000000000 ; }
virtual crypto : : hash get_block_hash_from_height ( const uint64_t & height ) const { return crypto : : hash ( ) ; }
virtual std : : vector < block > get_blocks_range ( const uint64_t & h1 , const uint64_t & h2 ) const { return std : : vector < block > ( ) ; }
virtual std : : vector < crypto : : hash > get_hashes_range ( const uint64_t & h1 , const uint64_t & h2 ) const { return std : : vector < crypto : : hash > ( ) ; }
virtual crypto : : hash top_block_hash ( ) const { return crypto : : hash ( ) ; }
virtual block get_top_block ( ) const { return block ( ) ; }
virtual uint64_t height ( ) const { return blocks . size ( ) ; }
virtual bool tx_exists ( const crypto : : hash & h ) const { return false ; }
virtual uint64_t get_tx_unlock_time ( const crypto : : hash & h ) const { return 0 ; }
virtual transaction get_tx ( const crypto : : hash & h ) const { return transaction ( ) ; }
virtual uint64_t get_tx_count ( ) const { return 0 ; }
virtual std : : vector < transaction > get_tx_list ( const std : : vector < crypto : : hash > & hlist ) const { return std : : vector < transaction > ( ) ; }
virtual uint64_t get_tx_block_height ( const crypto : : hash & h ) const { return 0 ; }
virtual uint64_t get_num_outputs ( const uint64_t & amount ) const { return 1 ; }
virtual output_data_t get_output_key ( const uint64_t & amount , const uint64_t & index ) { return output_data_t ( ) ; }
virtual output_data_t get_output_key ( const uint64_t & global_index ) const { return output_data_t ( ) ; }
virtual tx_out get_output ( const crypto : : hash & h , const uint64_t & index ) const { return tx_out ( ) ; }
virtual tx_out_index get_output_tx_and_index_from_global ( const uint64_t & index ) const { return tx_out_index ( ) ; }
virtual tx_out_index get_output_tx_and_index ( const uint64_t & amount , const uint64_t & index ) { return tx_out_index ( ) ; }
virtual void get_output_tx_and_index ( const uint64_t & amount , const std : : vector < uint64_t > & offsets , std : : vector < tx_out_index > & indices ) { }
virtual void get_output_key ( const uint64_t & amount , const std : : vector < uint64_t > & offsets , std : : vector < output_data_t > & outputs ) { }
virtual bool can_thread_bulk_indices ( ) const { return false ; }
virtual std : : vector < uint64_t > get_tx_output_indices ( const crypto : : hash & h ) const { return std : : vector < uint64_t > ( ) ; }
virtual std : : vector < uint64_t > get_tx_amount_output_indices ( const crypto : : hash & h ) const { return std : : vector < uint64_t > ( ) ; }
virtual bool has_key_image ( const crypto : : key_image & img ) const { return false ; }
virtual void remove_block ( ) { blocks . pop_back ( ) ; }
virtual void add_transaction_data ( const crypto : : hash & blk_hash , const transaction & tx , const crypto : : hash & tx_hash ) { }
virtual void remove_transaction_data ( const crypto : : hash & tx_hash , const transaction & tx ) { }
virtual void add_output ( const crypto : : hash & tx_hash , const tx_out & tx_output , const uint64_t & local_index , const uint64_t unlock_time ) { }
virtual void remove_output ( const tx_out & tx_output ) { }
virtual void add_spent_key ( const crypto : : key_image & k_image ) { }
virtual void remove_spent_key ( const crypto : : key_image & k_image ) { }
virtual void add_block ( const block & blk
, const size_t & block_size
, const difficulty_type & cumulative_difficulty
, const uint64_t & coins_generated
, const crypto : : hash & blk_hash
) {
blocks . push_back ( blk ) ;
}
virtual block get_block_from_height ( const uint64_t & height ) const {
return blocks [ height ] ;
}
private :
std : : vector < block > blocks ;
} ;
TEST ( reorganize , Same )
{
for ( int history = 1 ; history < = 12 ; + + history ) {
for ( uint64_t checkpoint_period = 1 ; checkpoint_period < = 16 ; checkpoint_period + + ) {
HardFork hf ( 1 , 1 , 1 , history , 100 , checkpoint_period ) ;
TestDB db ;
// v h t
ASSERT_TRUE ( hf . add ( 4 , 2 , 1 ) ) ;
ASSERT_TRUE ( hf . add ( 7 , 4 , 2 ) ) ;
ASSERT_TRUE ( hf . add ( 9 , 6 , 3 ) ) ;
// index 0 1 2 3 4 5 6 7 8 9
static const uint8_t block_versions [ ] = { 1 , 1 , 4 , 4 , 7 , 7 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 } ;
for ( uint64_t h = 0 ; h < 20 ; + + h ) {
db . add_block ( mkblock ( block_versions [ h ] ) , 0 , 0 , 0 , crypto : : hash ( ) ) ;
hf . add ( db . get_block_from_height ( h ) , h ) ;
}
for ( uint64_t rh = 0 ; rh < 20 ; + + rh ) {
hf . reorganize_from_block_height ( & db , rh ) ;
for ( int hh = 0 ; hh < 20 ; + + hh ) {
uint8_t version = hh > = ( history - 1 ) ? block_versions [ hh - ( history - 1 ) ] : 1 ;
ASSERT_EQ ( hf . get ( hh ) , version ) ;
}
ASSERT_EQ ( hf . get ( 100000 ) , 9 ) ;
}
}
}
}
TEST ( reorganize , Changed )
{
int history = 4 ;
for ( uint64_t checkpoint_period = 1 ; checkpoint_period < = 16 ; checkpoint_period + + ) {
HardFork hf ( 1 , 1 , 1 , 4 , 100 , checkpoint_period ) ;
TestDB db ;
HardFork hf ( db , 1 , 1 , 1 , history , 100 ) ;
// v h t
ASSERT_TRUE ( hf . add ( 1 , 0 , 0 ) ) ;
ASSERT_TRUE ( hf . add ( 4 , 2 , 1 ) ) ;
ASSERT_TRUE ( hf . add ( 7 , 4 , 2 ) ) ;
ASSERT_TRUE ( hf . add ( 9 , 6 , 3 ) ) ;
hf . init ( ) ;
// index 0 1 2 3 4 5 6 7 8 9
static const uint8_t block_versions [ ] = { 1 , 1 , 4 , 4 , 7 , 7 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 } ;
for ( uint64_t h = 0 ; h < 20 ; + + h ) {
db . add_block ( mkblock ( block_versions [ h ] ) , 0 , 0 , 0 , crypto : : hash ( ) ) ;
hf. add ( db . get_block_from_height ( h ) , h ) ;
ASSERT_TRUE ( hf . add ( db . get_block_from_height ( h ) , h ) ) ;
}
for ( uint64_t rh = 0 ; rh < 20 ; + + rh ) {
hf . reorganize_from_block_height ( & db , rh ) ;
hf . reorganize_from_block_height ( rh ) ;
for ( int hh = 0 ; hh < 20 ; + + hh ) {
uint8_t version = hh > = ( history - 1 ) ? block_versions [ hh - ( history - 1 ) ] : 1 ;
ASSERT_EQ ( hf . get ( hh ) , version ) ;
}
ASSERT_EQ ( hf . get ( 100000 ) , 9 ) ;
}
}
}
// delay a bit for 9, and go back to 1 to check it stays at 9
static const uint8_t block_versions_new [ ] = { 1 , 1 , 4 , 4 , 7 , 7 , 4 , 7 , 7 , 7 , 9 , 9 , 9 , 9 , 9 , 1 , 1 , 1 , 1 , 1 } ;
static const uint8_t expected_versions_new [ ] = { 1 , 1 , 1 , 1 , 1 , 4 , 4 , 4 , 4 , 4 , 7 , 7 , 7 , 9 , 9 , 9 , 9 , 9 , 9 , 9 } ;
for ( uint64_t h = 3 ; h < 20 ; + + h ) {
db . remove_block ( ) ;
}
ASSERT_EQ ( db . height ( ) , 3 ) ;
hf . reorganize_from_block_height ( & db , 2 ) ;
for ( uint64_t h = 3 ; h < 20 ; + + h ) {
db . add_block ( mkblock ( block_versions_new [ h ] ) , 0 , 0 , 0 , crypto : : hash ( ) ) ;
hf . add ( db . get_block_from_height ( h ) , h ) ;
}
for ( int hh = 0 ; hh < 20 ; + + hh ) {
ASSERT_EQ ( hf . get ( hh ) , expected_versions_new [ hh ] ) ;
TEST ( reorganize , Changed )
{
int history = 4 ;
TestDB db ;
HardFork hf ( db , 1 , 1 , 1 , 4 , 100 ) ;
// v h t
ASSERT_TRUE ( hf . add ( 1 , 0 , 0 ) ) ;
ASSERT_TRUE ( hf . add ( 4 , 2 , 1 ) ) ;
ASSERT_TRUE ( hf . add ( 7 , 4 , 2 ) ) ;
ASSERT_TRUE ( hf . add ( 9 , 6 , 3 ) ) ;
hf . init ( ) ;
// index 0 1 2 3 4 5 6 7 8 9
static const uint8_t block_versions [ ] = { 1 , 1 , 4 , 4 , 7 , 7 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 } ;
for ( uint64_t h = 0 ; h < 16 ; + + h ) {
db . add_block ( mkblock ( block_versions [ h ] ) , 0 , 0 , 0 , crypto : : hash ( ) ) ;
ASSERT_TRUE ( hf . add ( db . get_block_from_height ( h ) , h ) ) ;
}
for ( uint64_t rh = 0 ; rh < 16 ; + + rh ) {
hf . reorganize_from_block_height ( rh ) ;
for ( int hh = 0 ; hh < 16 ; + + hh ) {
uint8_t version = hh > = ( history - 1 ) ? block_versions [ hh - ( history - 1 ) ] : 1 ;
ASSERT_EQ ( hf . get ( hh ) , version ) ;
}
ASSERT_EQ ( hf . get ( 100000 ) , 9 ) ;
}
// delay a bit for 9, and go back to 1 to check it stays at 9
static const uint8_t block_versions_new [ ] = { 1 , 1 , 4 , 4 , 7 , 7 , 4 , 7 , 7 , 7 , 9 , 9 , 9 , 9 , 9 , 1 } ;
static const uint8_t expected_versions_new [ ] = { 1 , 1 , 1 , 1 , 1 , 4 , 4 , 4 , 4 , 4 , 7 , 7 , 7 , 9 , 9 , 9 } ;
for ( uint64_t h = 3 ; h < 16 ; + + h ) {
db . remove_block ( ) ;
}
ASSERT_EQ ( db . height ( ) , 3 ) ;
hf . reorganize_from_block_height ( 2 ) ;
for ( uint64_t h = 3 ; h < 16 ; + + h ) {
db . add_block ( mkblock ( block_versions_new [ h ] ) , 0 , 0 , 0 , crypto : : hash ( ) ) ;
bool ret = hf . add ( db . get_block_from_height ( h ) , h ) ;
ASSERT_EQ ( ret , h < 15 ) ;
}
db . remove_block ( ) ; // last block added to the blockchain, but not hf
ASSERT_EQ ( db . height ( ) , 15 ) ;
for ( int hh = 0 ; hh < 15 ; + + hh ) {
ASSERT_EQ ( hf . get ( hh ) , expected_versions_new [ hh ] ) ;
}
}
TEST ( voting , threshold )
{
for ( int threshold = 87 ; threshold < = 88 ; + + threshold ) {
HardFork hf ( 1 , 1 , 1 , 8 , threshold , 10 ) ;
TestDB db ;
HardFork hf ( db , 1 , 1 , 1 , 8 , threshold ) ;
// v h t
ASSERT_TRUE ( hf . add ( 1 , 0 , 0 ) ) ;
ASSERT_TRUE ( hf . add ( 2 , 2 , 1 ) ) ;
hf . init ( ) ;
for ( uint64_t h = 0 ; h < 10 ; + + h ) {
for ( uint64_t h = 0 ; h < = 8 ; + + h ) {
uint8_t v = 1 + ! ! ( h % 8 ) ;
hf . add ( mkblock ( v ) , h ) ;
uint8_t expected = threshold = = 88 ? 1 : h < 7 ? 1 : 2 ;
ASSERT_EQ ( hf . get ( h ) , expected ) ;
db . add_block ( mkblock ( v ) , 0 , 0 , 0 , crypto : : hash ( ) ) ;
bool ret = hf . add ( db . get_block_from_height ( h ) , h ) ;
if ( h > = 8 & & threshold = = 87 ) {
ASSERT_FALSE ( ret ) ;
}
else {
ASSERT_TRUE ( ret ) ;
uint8_t expected = threshold = = 88 ? 1 : h < 7 ? 1 : 2 ;
ASSERT_EQ ( hf . get ( h ) , expected ) ;
}
}
}
}
TEST ( new_blocks , denied )
{
HardFork hf ( 1 , 1 , 1 , 4 , 50 , 10 ) ;
TestDB db ;
HardFork hf ( db , 1 , 1 , 1 , 4 , 50 ) ;
// v h t
ASSERT_TRUE ( hf . add ( 1 , 0 , 0 ) ) ;
ASSERT_TRUE ( hf . add ( 2 , 2 , 1 ) ) ;
hf . init ( ) ;
ASSERT_FALSE ( hf . add ( mkblock ( 0 ) , 0 ) ) ;
ASSERT_TRUE ( hf . add ( mkblock ( 1 ) , 0 ) ) ;
@ -322,10 +375,13 @@ TEST(new_blocks, denied)
TEST ( new_version , early )
{
HardFork hf ( 1 , 1 , 1 , 4 , 50 , 10 ) ;
TestDB db ;
HardFork hf ( db , 1 , 1 , 1 , 4 , 50 ) ;
// v h t
ASSERT_TRUE ( hf . add ( 1 , 0 , 0 ) ) ;
ASSERT_TRUE ( hf . add ( 2 , 4 , 1 ) ) ;
hf . init ( ) ;
ASSERT_FALSE ( hf . add ( mkblock ( 0 ) , 0 ) ) ;
ASSERT_TRUE ( hf . add ( mkblock ( 2 ) , 0 ) ) ;
@ -342,12 +398,14 @@ TEST(new_version, early)
TEST ( reorganize , changed )
{
HardFork hf ( 1 , 1 , 1 , 4 , 50 , 10 ) ;
TestDB db ;
HardFork hf ( db , 1 , 1 , 1 , 4 , 50 ) ;
// v h t
ASSERT_TRUE ( hf . add ( 1 , 0 , 0 ) ) ;
ASSERT_TRUE ( hf . add ( 2 , 2 , 1 ) ) ;
ASSERT_TRUE ( hf . add ( 3 , 5 , 2 ) ) ;
hf . init ( ) ;
# define ADD(v, h, a) \
do { \
@ -376,10 +434,10 @@ TEST(reorganize, changed)
// pop a few blocks and check current version goes back down
db . remove_block ( ) ;
hf . reorganize_from_block_height ( & db , 8 ) ;
hf . reorganize_from_block_height ( 8 ) ;
ASSERT_EQ ( hf . get_current_version ( ) , 3 ) ;
db . remove_block ( ) ;
hf . reorganize_from_block_height ( & db , 7 ) ;
hf . reorganize_from_block_height ( 7 ) ;
ASSERT_EQ ( hf . get_current_version ( ) , 2 ) ;
db . remove_block ( ) ;
ASSERT_EQ ( hf . get_current_version ( ) , 2 ) ;