2022-10-31 18:17:34 +01:00
// Copyright (c) 2014-2022 Zano Project
2018-12-27 18:50:45 +03:00
// Copyright (c) 2014-2018 The Louisdor Project
// Copyright (c) 2012-2013 The Cryptonote developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
# pragma once
# include <string>
# include <iostream>
2019-09-11 14:32:45 +03:00
# define USE_INSECURE_RANDOM_RPNG_ROUTINES // turns on pseudorandom number generator manupulations for tests
2018-12-27 18:50:45 +03:00
# include "currency_core/currency_basic.h"
# include "currency_core/currency_core.h"
# include "wallet/wallet2.h"
# include "test_core_time.h"
# define TESTS_DEFAULT_FEE ((uint64_t)TX_DEFAULT_FEE)
2019-04-25 23:37:43 +02:00
# define MK_TEST_COINS(amount) (static_cast<uint64_t>(amount) * TX_DEFAULT_FEE)
2018-12-27 18:50:45 +03:00
# define TESTS_POS_CONFIG_MIN_COINSTAKE_AGE 4
# define TESTS_POS_CONFIG_POS_MINIMUM_HEIGH 4
namespace concolor
{
inline std : : basic_ostream < char , std : : char_traits < char > > & bright_white ( std : : basic_ostream < char , std : : char_traits < char > > & ostr )
{
epee : : log_space : : set_console_color ( epee : : log_space : : console_color_white , true ) ;
return ostr ;
}
inline std : : basic_ostream < char , std : : char_traits < char > > & red ( std : : basic_ostream < char , std : : char_traits < char > > & ostr )
{
epee : : log_space : : set_console_color ( epee : : log_space : : console_color_red , true ) ;
return ostr ;
}
inline std : : basic_ostream < char , std : : char_traits < char > > & green ( std : : basic_ostream < char , std : : char_traits < char > > & ostr )
{
epee : : log_space : : set_console_color ( epee : : log_space : : console_color_green , true ) ;
return ostr ;
}
inline std : : basic_ostream < char , std : : char_traits < char > > & magenta ( std : : basic_ostream < char , std : : char_traits < char > > & ostr )
{
epee : : log_space : : set_console_color ( epee : : log_space : : console_color_magenta , true ) ;
return ostr ;
}
inline std : : basic_ostream < char , std : : char_traits < char > > & yellow ( std : : basic_ostream < char , std : : char_traits < char > > & ostr )
{
epee : : log_space : : set_console_color ( epee : : log_space : : console_color_yellow , true ) ;
return ostr ;
}
inline std : : basic_ostream < char , std : : char_traits < char > > & normal ( std : : basic_ostream < char , std : : char_traits < char > > & ostr )
{
epee : : log_space : : reset_console_color ( ) ;
return ostr ;
}
}
struct callback_entry
{
callback_entry ( ) { }
callback_entry ( const std : : string & cb_name , const currency : : blobdata & cb_params ) : callback_name ( cb_name ) , callback_params ( cb_params ) { }
std : : string callback_name ;
currency : : blobdata callback_params ;
BEGIN_SERIALIZE_OBJECT ( )
FIELD ( callback_name )
FIELD ( callback_params )
END_SERIALIZE ( )
private :
friend class boost : : serialization : : access ;
template < class Archive >
void serialize ( Archive & ar , const unsigned int /*version*/ )
{
ar & callback_name ;
ar & callback_params ;
}
} ;
template < typename T >
struct serialized_object
{
serialized_object ( ) { }
serialized_object ( const currency : : blobdata & a_data )
: data ( a_data )
{
}
currency : : blobdata data ;
BEGIN_SERIALIZE_OBJECT ( )
FIELD ( data )
END_SERIALIZE ( )
private :
friend class boost : : serialization : : access ;
template < class Archive >
void serialize ( Archive & ar , const unsigned int /*version*/ )
{
ar & data ;
}
} ;
typedef serialized_object < currency : : block > serialized_block ;
typedef serialized_object < currency : : transaction > serialized_transaction ;
struct event_visitor_settings
{
int valid_mask ;
bool txs_kept_by_block ;
bool skip_txs_blobsize_check ;
enum settings
{
set_txs_kept_by_block = 1 < < 0 ,
set_skip_txs_blobsize_check = 1 < < 1 ,
} ;
event_visitor_settings ( int a_valid_mask = 0 , bool a_txs_kept_by_block = false , bool skip_txs_blobsize_check = false )
: valid_mask ( a_valid_mask )
, txs_kept_by_block ( a_txs_kept_by_block )
, skip_txs_blobsize_check ( skip_txs_blobsize_check )
{
}
private :
friend class boost : : serialization : : access ;
template < class Archive >
void serialize ( Archive & ar , const unsigned int /*version*/ )
{
ar & valid_mask ;
ar & txs_kept_by_block ;
ar & skip_txs_blobsize_check ;
}
} ;
struct event_special_block
{
currency : : block block ;
int special_flags ;
enum special_flags_t
{
flag_skip = 1 < < 0 // block won't be passed to the core to simulate delays and/or orphanness
} ;
event_special_block ( )
: special_flags ( 0 )
{
}
event_special_block ( const currency : : block & block , int special_flags = 0 )
: block ( block )
, special_flags ( special_flags )
{
}
private :
friend class boost : : serialization : : access ;
template < class Archive >
void serialize ( Archive & ar , const unsigned int /*version*/ )
{
ar & block ;
ar & special_flags ;
}
} ;
struct event_core_time
{
uint64_t time_shift ;
bool relative ;
event_core_time ( )
: time_shift ( 0 )
, relative ( true )
{ }
event_core_time ( uint64_t time_shift , bool relative = false )
: time_shift ( time_shift )
, relative ( relative )
{ }
private :
friend class boost : : serialization : : access ;
template < class Archive >
void serialize ( Archive & ar , const unsigned int /*version*/ )
{
ar & time_shift ;
ar & relative ;
}
} ;
2023-04-30 00:43:49 +02:00
struct core_hardforks_config
{
std : : array < uint64_t , currency : : hard_forks_descriptor : : m_total_count > hardforks ;
template < class Archive >
void serialize ( Archive & ar , const unsigned int /*version*/ )
{
ar & hardforks ;
}
} ;
2018-12-27 18:50:45 +03:00
VARIANT_TAG ( binary_archive , callback_entry , 0xcb ) ;
VARIANT_TAG ( binary_archive , currency : : account_base , 0xcc ) ;
VARIANT_TAG ( binary_archive , serialized_block , 0xcd ) ;
VARIANT_TAG ( binary_archive , serialized_transaction , 0xce ) ;
VARIANT_TAG ( binary_archive , event_visitor_settings , 0xcf ) ;
VARIANT_TAG ( binary_archive , event_special_block , 0xd0 ) ;
VARIANT_TAG ( binary_archive , event_core_time , 0xd1 ) ;
2023-04-30 00:43:49 +02:00
VARIANT_TAG ( binary_archive , core_hardforks_config , 0xd2 ) ;
2018-12-27 18:50:45 +03:00
2023-04-30 00:43:49 +02:00
typedef boost : : variant < currency : : block , currency : : transaction , currency : : account_base , callback_entry , serialized_block , serialized_transaction , event_visitor_settings , event_special_block , event_core_time , core_hardforks_config > test_event_entry ;
2018-12-27 18:50:45 +03:00
typedef std : : unordered_map < crypto : : hash , const currency : : transaction * > map_hash2tx_t ;
2023-06-06 22:37:32 +02:00
enum test_tx_split_strategy { tests_default_split_strategy /*height-based, TODO*/ , tests_void_split_strategy , tests_null_split_strategy , tests_digits_split_strategy , tests_random_split_strategy } ;
2018-12-27 18:50:45 +03:00
struct test_gentime_settings
{
2022-10-28 04:17:48 +02:00
test_tx_split_strategy split_strategy = tests_digits_split_strategy ;
size_t miner_tx_max_outs = CURRENCY_MINER_TX_MAX_OUTS ;
uint64_t tx_max_out_amount = WALLET_MAX_ALLOWED_OUTPUT_AMOUNT ;
uint64_t dust_threshold = DEFAULT_DUST_THRESHOLD ;
size_t rss_min_number_of_outputs = CURRENCY_TX_MIN_ALLOWED_OUTS ; // for random split strategy: min (target) number of tx outputs, one output will be split into this many parts
size_t rss_num_digits_to_keep = CURRENCY_TX_OUTS_RND_SPLIT_DIGITS_TO_KEEP ; // for random split strategy: number of digits to keep
2022-11-01 00:06:47 +01:00
bool ignore_invalid_blocks = true ; // gen-time blockchain building: don't take into account blocks marked as invalid ("mark_invalid_block")
bool ignore_invalid_txs = true ; // gen-time blockchain building: don't take into account txs marked as invalid ("mark_invalid_txs")
2018-12-27 18:50:45 +03:00
} ;
2022-10-25 23:59:25 +02:00
class test_generator ;
2018-12-27 18:50:45 +03:00
class test_chain_unit_base
{
public :
2023-04-26 23:59:33 +02:00
test_chain_unit_base ( ) ;
2018-12-27 18:50:45 +03:00
typedef boost : : function < bool ( currency : : core & c , size_t ev_index , const std : : vector < test_event_entry > & events ) > verify_callback ;
typedef std : : map < std : : string , verify_callback > callbacks_map ;
void register_callback ( const std : : string & cb_name , verify_callback cb ) ;
bool verify ( const std : : string & cb_name , currency : : core & c , size_t ev_index , const std : : vector < test_event_entry > & events ) ;
bool need_core_proxy ( ) const { return false ; } // tests can override this in order to obtain core proxy (e.g. for wallet)
void set_core_proxy ( std : : shared_ptr < tools : : i_core_proxy > ) { /* do nothing */ }
2022-05-11 23:52:33 +02:00
uint64_t get_tx_version_from_events ( const std : : vector < test_event_entry > & events ) const ;
2022-05-26 16:53:40 +02:00
2023-06-03 04:12:01 +02:00
virtual void on_test_constructed ( ) { } // called right after test class is constructed by the chaingen
2022-10-25 23:59:25 +02:00
void on_test_generator_created ( test_generator & generator ) const ; // tests can override this for special initialization
2023-05-01 00:03:24 +02:00
currency : : core_runtime_config get_runtime_info_for_core ( ) const ; // tests can override this for special initialization
2022-10-25 23:59:25 +02:00
2023-05-20 00:53:53 +02:00
void set_hardforks_for_old_tests ( ) ;
2023-06-03 04:12:01 +02:00
currency : : hard_forks_descriptor & get_hardforks ( ) { return m_hardforks ; }
const currency : : hard_forks_descriptor & get_hardforks ( ) const { return m_hardforks ; }
2023-05-20 00:53:53 +02:00
2018-12-27 18:50:45 +03:00
private :
callbacks_map m_callbacks ;
2022-05-26 16:53:40 +02:00
2022-05-11 23:52:33 +02:00
protected :
2023-04-30 00:43:49 +02:00
mutable currency : : hard_forks_descriptor m_hardforks ;
2018-12-27 18:50:45 +03:00
} ;
struct offers_count_param
{
offers_count_param ( size_t offers_count = 0 , size_t offers_count_raw = SIZE_MAX )
: offers_count ( offers_count ) , offers_count_raw ( offers_count_raw )
{ }
size_t offers_count ;
size_t offers_count_raw ;
} ;
2019-08-09 07:34:27 +03:00
class test_chain_unit_enchanced : virtual public test_chain_unit_base
2018-12-27 18:50:45 +03:00
{
public :
test_chain_unit_enchanced ( ) ;
bool check_tx_verification_context ( const currency : : tx_verification_context & tvc , bool tx_added , size_t event_idx , const currency : : transaction & /*tx*/ )
{
if ( m_invalid_tx_index = = event_idx )
2022-11-17 22:19:06 +01:00
{
CHECK_AND_ASSERT_MES ( tvc . m_verification_failed , false , ENDL < < " event # " < < event_idx < < " : the tx passed the verification, although it had been marked as invalid " < < ENDL ) ;
2018-12-27 18:50:45 +03:00
return tvc . m_verification_failed ;
2022-11-17 22:19:06 +01:00
}
2020-02-16 21:43:59 +03:00
if ( m_unverifiable_tx_index = = event_idx )
2022-11-17 22:19:06 +01:00
{
2022-11-17 23:01:37 +01:00
CHECK_AND_ASSERT_MES ( tvc . m_verification_impossible , false , ENDL < < " event # " < < event_idx < < " : the tx passed normally, although it had been marked as unverifiable " < < ENDL ) ;
2020-02-16 21:43:59 +03:00
return tvc . m_verification_impossible ;
2022-11-17 22:19:06 +01:00
}
CHECK_AND_ASSERT_MES ( tx_added , false , ENDL < < " event # " < < event_idx < < " : the tx has not been added for some reason " < < ENDL ) ;
2018-12-27 18:50:45 +03:00
return ! tvc . m_verification_failed & & tx_added ;
}
bool check_block_verification_context ( const currency : : block_verification_context & bvc , size_t event_idx , const currency : : block & /*block*/ )
{
if ( m_invalid_block_index = = event_idx )
2022-11-17 22:19:06 +01:00
{
CHECK_AND_ASSERT_MES ( bvc . m_verification_failed , false , ENDL < < " event # " < < event_idx < < " : the block passed the verification, although it had been marked as invalid " < < ENDL ) ;
2018-12-27 18:50:45 +03:00
return bvc . m_verification_failed ;
2022-11-17 22:19:06 +01:00
}
2018-12-27 18:50:45 +03:00
if ( m_orphan_block_index = = event_idx )
2022-11-17 22:19:06 +01:00
{
CHECK_AND_ASSERT_MES ( bvc . m_marked_as_orphaned , false , ENDL < < " event # " < < event_idx < < " : the block passed normally, although it had been marked as orphaned " < < ENDL ) ;
2018-12-27 18:50:45 +03:00
return bvc . m_marked_as_orphaned ;
2022-11-17 22:19:06 +01:00
}
2018-12-27 18:50:45 +03:00
return ! bvc . m_verification_failed ;
}
bool mark_invalid_block ( currency : : core & /*c*/ , size_t ev_index , const std : : vector < test_event_entry > & /*events*/ )
{
m_invalid_block_index = ev_index + 1 ;
return true ;
}
bool mark_orphan_block ( currency : : core & /*c*/ , size_t ev_index , const std : : vector < test_event_entry > & /*events*/ )
{
m_orphan_block_index = ev_index + 1 ;
return true ;
}
bool mark_invalid_tx ( currency : : core & /*c*/ , size_t ev_index , const std : : vector < test_event_entry > & /*events*/ )
{
m_invalid_tx_index = ev_index + 1 ;
return true ;
}
2020-02-16 21:43:59 +03:00
bool mark_unverifiable_tx ( currency : : core & /*c*/ , size_t ev_index , const std : : vector < test_event_entry > & /*events*/ )
{
m_unverifiable_tx_index = ev_index + 1 ;
return true ;
}
2021-03-11 19:43:39 +03:00
void set_hard_fork_heights_to_generator ( test_generator & generator ) const ;
2018-12-27 18:50:45 +03:00
bool configure_core ( currency : : core & c , size_t ev_index , const std : : vector < test_event_entry > & events ) ;
bool check_top_block ( currency : : core & c , size_t ev_index , const std : : vector < test_event_entry > & events ) ;
bool clear_tx_pool ( currency : : core & c , size_t ev_index , const std : : vector < test_event_entry > & events ) ;
bool check_tx_pool_empty ( currency : : core & c , size_t ev_index , const std : : vector < test_event_entry > & events ) ;
bool check_tx_pool_count ( currency : : core & c , size_t ev_index , const std : : vector < test_event_entry > & events ) ;
bool print_tx_pool ( currency : : core & c , size_t ev_index , const std : : vector < test_event_entry > & events ) ;
2019-10-16 16:32:58 +03:00
bool remove_stuck_txs ( currency : : core & c , size_t ev_index , const std : : vector < test_event_entry > & events ) ;
2018-12-27 18:50:45 +03:00
bool check_offers_count ( currency : : core & c , size_t ev_index , const std : : vector < test_event_entry > & events ) ;
2021-04-28 07:00:32 +03:00
bool check_hardfork_active ( currency : : core & c , size_t ev_index , const std : : vector < test_event_entry > & events ) ;
2022-11-09 16:55:54 +01:00
bool check_hardfork_inactive ( currency : : core & c , size_t ev_index , const std : : vector < test_event_entry > & events ) ;
2018-12-27 18:50:45 +03:00
2022-11-01 00:06:47 +01:00
static bool is_event_mark_invalid_block ( const test_event_entry & ev , bool use_global_gentime_settings = true ) ;
static bool is_event_mark_invalid_tx ( const test_event_entry & ev , bool use_global_gentime_settings = true ) ;
2022-05-11 23:52:33 +02:00
2018-12-27 18:50:45 +03:00
protected :
struct params_top_block
{
params_top_block ( const currency : : block & b ) : height ( currency : : get_block_height ( b ) ) , hash ( currency : : get_block_hash ( b ) ) { }
params_top_block ( uint64_t height = 0 , crypto : : hash hash = currency : : null_hash ) : height ( height ) , hash ( hash ) { }
uint64_t height ;
crypto : : hash hash ;
} ;
size_t m_invalid_block_index ;
size_t m_invalid_tx_index ;
2020-02-16 21:43:59 +03:00
size_t m_unverifiable_tx_index ;
2018-12-27 18:50:45 +03:00
size_t m_orphan_block_index ;
} ;
struct wallet_test_core_proxy ;
class test_generator
{
public :
struct block_info
{
block_info ( )
: b ( )
, already_generated_coins ( 0 )
, block_size ( 0 )
, cumul_difficulty ( 0 )
{
}
block_info ( const currency : : block & b_ ,
uint64_t an_already_generated_coins ,
size_t a_block_size ,
currency : : wide_difficulty_type diff ,
const std : : list < currency : : transaction > & tx_list ,
const crypto : : hash & k_hash )
: b ( b_ )
, already_generated_coins ( an_already_generated_coins )
, block_size ( a_block_size )
, cumul_difficulty ( diff ) ,
m_transactions ( tx_list . begin ( ) , tx_list . end ( ) ) ,
ks_hash ( k_hash )
{ }
currency : : block b ;
uint64_t already_generated_coins ;
size_t block_size ;
currency : : wide_difficulty_type cumul_difficulty ;
std : : vector < currency : : transaction > m_transactions ;
crypto : : hash ks_hash ;
2019-08-01 18:47:20 +02:00
} ;
2018-12-27 18:50:45 +03:00
2022-11-16 02:31:22 +01:00
struct out_index_info
{
size_t block_height ;
size_t in_block_tx_index ;
size_t in_tx_out_index ;
} ;
typedef std : : map < uint64_t , std : : vector < out_index_info > > outputs_index ; // amount -> [gindex -> out_index_info]
typedef std : : unordered_map < crypto : : hash , std : : vector < uint64_t > > tx_global_indexes ; // tx_hash -> vector of tx's outputs global indices
2018-12-27 18:50:45 +03:00
typedef std : : vector < const block_info * > blockchain_vector ;
2022-10-14 19:18:24 +02:00
struct gen_wallet_info
{
tools : : wallet2 : : mining_context mining_context ;
std : : shared_ptr < tools : : wallet2 > wallet ;
} ;
typedef std : : vector < gen_wallet_info > wallets_vector ;
2018-12-27 18:50:45 +03:00
enum block_fields
{
bf_none = 0 ,
bf_major_ver = 1 < < 0 ,
bf_minor_ver = 1 < < 1 ,
bf_timestamp = 1 < < 2 ,
bf_prev_id = 1 < < 3 ,
bf_miner_tx = 1 < < 4 ,
bf_tx_hashes = 1 < < 5 ,
bf_diffic = 1 < < 6
} ;
test_generator ( ) ;
//-----------
2022-09-23 18:45:22 +02:00
static currency : : wide_difficulty_type get_difficulty_for_next_block ( const std : : vector < const block_info * > & blocks , bool pow = true ) ;
2018-12-27 18:50:45 +03:00
currency : : wide_difficulty_type get_difficulty_for_next_block ( const crypto : : hash & head_id , bool pow = true ) const ;
2022-11-16 03:34:42 +01:00
bool get_params_for_next_pos_block ( const crypto : : hash & head_id , currency : : wide_difficulty_type & pos_difficulty , crypto : : hash & last_pow_block_hash , crypto : : hash & last_pos_block_kernel_hash ) const ;
2018-12-27 18:50:45 +03:00
currency : : wide_difficulty_type get_cumul_difficulty_for_next_block ( const crypto : : hash & head_id , bool pow = true ) const ;
void get_block_chain ( std : : vector < const block_info * > & blockchain , const crypto : : hash & head , size_t n ) const ;
void get_last_n_block_sizes ( std : : vector < size_t > & block_sizes , const crypto : : hash & head , size_t n ) const ;
uint64_t get_last_n_blocks_fee_median ( const crypto : : hash & head_block_hash , size_t n = ALIAS_COAST_PERIOD ) ;
template < typename cb_t >
bool construct_block_gentime_with_coinbase_cb ( const currency : : block & prev_block , const currency : : account_base & acc , cb_t cb , currency : : block & b ) ;
bool construct_pow_block_with_alias_info_in_coinbase ( const currency : : account_base & acc , const currency : : block & prev_block , const currency : : extra_alias_entry & ai , currency : : block & b ) ;
uint64_t get_base_reward_for_next_block ( const crypto : : hash & head_id , bool pow = true ) const ;
//POS
2022-09-23 18:45:22 +02:00
static bool build_stake_modifier ( currency : : stake_modifier_type & sm , const test_generator : : blockchain_vector & blck_chain ) ;
2018-12-27 18:50:45 +03:00
bool find_kernel ( const std : : list < currency : : account_base > & accs ,
const blockchain_vector & blck_chain ,
wallets_vector & wallets ,
currency : : pos_entry & pe ,
size_t & found_wallet_index ,
uint64_t & found_timestamp ,
crypto : : hash & found_kh ) ;
bool build_wallets ( const blockchain_vector & blocks ,
const std : : list < currency : : account_base > & accs ,
const tx_global_indexes & txs_outs ,
2022-11-16 03:15:31 +01:00
const outputs_index & oi ,
2018-12-27 18:50:45 +03:00
wallets_vector & wallets ,
const currency : : core_runtime_config & cc = currency : : get_default_core_runtime_config ( ) ) ;
bool build_wallets ( const crypto : : hash & blockchain_head ,
const std : : list < currency : : account_base > & accounts ,
wallets_vector & wallets ,
const currency : : core_runtime_config & cc = currency : : get_default_core_runtime_config ( ) ) ;
bool init_test_wallet ( const currency : : account_base & account , const crypto : : hash & genesis_hash , std : : shared_ptr < tools : : wallet2 > & result ) ;
bool refresh_test_wallet ( const std : : vector < test_event_entry > & events , tools : : wallet2 * w , const crypto : : hash & top_block_hash , size_t expected_blocks_to_be_fetched = std : : numeric_limits < size_t > : : max ( ) ) ;
2022-10-20 12:46:41 +02:00
bool sign_block ( const tools : : wallet2 : : mining_context & mining_context ,
const currency : : pos_entry & pe ,
2023-06-09 01:19:37 +02:00
uint64_t full_block_reward ,
2022-10-20 12:46:41 +02:00
const tools : : wallet2 & w ,
2023-04-12 20:13:54 +02:00
currency : : tx_generation_context & miner_tx_tgc ,
2022-10-20 12:46:41 +02:00
currency : : block & b ) ;
2018-12-27 18:50:45 +03:00
2022-10-26 20:50:21 +02:00
/*bool get_output_details_by_global_index(const test_generator::blockchain_vector& blck_chain,
2018-12-27 18:50:45 +03:00
const test_generator : : outputs_index & indexes ,
uint64_t amount ,
uint64_t global_index ,
uint64_t & h ,
const currency : : transaction * tx ,
uint64_t & tx_out_index ,
crypto : : public_key & tx_pub_key ,
2022-10-26 20:50:21 +02:00
crypto : : public_key & output_key ) ; */
2018-12-27 18:50:45 +03:00
uint64_t get_already_generated_coins ( const crypto : : hash & blk_id ) const ;
uint64_t get_already_generated_coins ( const currency : : block & blk ) const ;
currency : : wide_difficulty_type get_block_difficulty ( const crypto : : hash & blk_id ) const ;
currency : : wide_difficulty_type get_cumul_difficulty ( const crypto : : hash & head_id ) const ;
2022-09-23 18:45:22 +02:00
static uint64_t get_timestamps_median ( const blockchain_vector & blck_chain , size_t window_size = BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW ) ;
2018-12-27 18:50:45 +03:00
uint64_t get_timestamps_median ( const crypto : : hash & blockchain_head , size_t window_size = BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW ) ;
bool build_outputs_indext_for_chain ( const std : : vector < const block_info * > & blocks , outputs_index & index , tx_global_indexes & txs_outs ) const ;
size_t get_tx_out_gindex ( const crypto : : hash & blockchain_head , const crypto : : hash & tx_hash , const size_t output_index ) const ;
void add_block ( const currency : : block & blk ,
size_t tsx_size ,
std : : vector < size_t > & block_sizes ,
uint64_t already_generated_coins ,
currency : : wide_difficulty_type cum_diff ,
const std : : list < currency : : transaction > & tx_list ,
const crypto : : hash & ks_hash ) ;
void add_block_info ( const block_info & bi ) ;
bool add_block_info ( const currency : : block & b , const std : : list < currency : : transaction > & tx_list ) ;
2022-11-16 22:04:18 +01:00
bool remove_block_info ( const currency : : block & blk ) ;
bool remove_block_info ( const crypto : : hash & block_id ) ;
2018-12-27 18:50:45 +03:00
bool construct_block ( currency : : block & blk ,
uint64_t height ,
const crypto : : hash & prev_id ,
const currency : : account_base & miner_acc ,
uint64_t timestamp ,
uint64_t already_generated_coins ,
std : : vector < size_t > & block_sizes ,
const std : : list < currency : : transaction > & tx_list ,
const std : : list < currency : : account_base > & coin_stake_sources = std : : list < currency : : account_base > ( ) //in case of PoS block
) ;
bool construct_genesis_block ( currency : : block & blk ,
const currency : : account_base & miner_acc ,
uint64_t timestamp ) ;
2019-08-01 18:47:20 +02:00
2018-12-27 18:50:45 +03:00
bool construct_block ( const std : : vector < test_event_entry > & events ,
currency : : block & blk ,
const currency : : block & blk_prev ,
const currency : : account_base & miner_acc ,
const std : : list < currency : : transaction > & tx_list = std : : list < currency : : transaction > ( ) ,
const std : : list < currency : : account_base > & coin_stake_sources = std : : list < currency : : account_base > ( ) //in case of PoS block
) ;
2019-08-01 18:47:20 +02:00
bool construct_block ( int64_t manual_timestamp_adjustment ,
const std : : vector < test_event_entry > & events ,
currency : : block & blk ,
const currency : : block & blk_prev ,
const currency : : account_base & miner_acc ,
const std : : list < currency : : transaction > & tx_list = std : : list < currency : : transaction > ( ) ,
const std : : list < currency : : account_base > & coin_stake_sources = std : : list < currency : : account_base > ( ) //in case of PoS block
) ;
2018-12-27 18:50:45 +03:00
bool construct_block_manually ( currency : : block & blk , const currency : : block & prev_block ,
const currency : : account_base & miner_acc , int actual_params = bf_none , uint8_t major_ver = 0 ,
uint8_t minor_ver = 0 , uint64_t timestamp = 0 , const crypto : : hash & prev_id = crypto : : hash ( ) ,
const currency : : wide_difficulty_type & diffic = 1 , const currency : : transaction & miner_tx = currency : : transaction ( ) ,
const std : : vector < crypto : : hash > & tx_hashes = std : : vector < crypto : : hash > ( ) , size_t txs_sizes = 0 ) ;
bool construct_block_manually_tx ( currency : : block & blk , const currency : : block & prev_block ,
const currency : : account_base & miner_acc , const std : : vector < crypto : : hash > & tx_hashes , size_t txs_size ) ;
bool find_nounce ( currency : : block & blk , std : : vector < const block_info * > & blocks , currency : : wide_difficulty_type dif , uint64_t height ) const ;
//bool find_nounce(currency::block& blk, currency::wide_difficulty_type dif, uint64_t height);
crypto : : secret_key last_tx_generated_secret_key ;
std : : shared_ptr < wallet_test_core_proxy > m_wallet_test_core_proxy ;
/////////////////////////
// test gentime settings (all made static as test_generator not necessary for tx construction)
static const test_gentime_settings & get_test_gentime_settings ( ) { return m_test_gentime_settings ; }
static void set_test_gentime_settings ( const test_gentime_settings & s ) { m_test_gentime_settings = s ; }
static void set_test_gentime_settings_default ( ) { m_test_gentime_settings = m_test_gentime_settings_default ; }
2019-08-03 19:15:56 +02:00
void set_ignore_last_pow_in_wallets ( bool ignore_last_pow_in_wallets ) { m_ignore_last_pow_in_wallets = ignore_last_pow_in_wallets ; }
2020-04-23 15:41:40 +03:00
void set_hardfork_height ( size_t hardfork_id , uint64_t h ) ;
2022-05-10 23:49:20 +02:00
void set_hardforks ( const currency : : hard_forks_descriptor & hardforks ) ;
2022-05-26 16:53:40 +02:00
const currency : : hard_forks_descriptor & get_hardforks ( ) const { return m_hardforks ; }
2024-02-04 22:03:27 +01:00
void load_hardforks_from ( const test_chain_unit_base * pthis ) { m_hardforks = pthis - > get_hardforks ( ) ; }
template < typename t_type >
void load_hardforks_from ( const t_type * pthis ) { }
2018-12-27 18:50:45 +03:00
private :
2019-08-03 19:15:56 +02:00
bool m_ignore_last_pow_in_wallets ;
2019-08-01 18:47:20 +02:00
2023-04-30 00:43:49 +02:00
mutable currency : : hard_forks_descriptor m_hardforks ;
2019-08-01 18:47:20 +02:00
2018-12-27 18:50:45 +03:00
std : : unordered_map < crypto : : hash , block_info > m_blocks_info ;
static test_gentime_settings m_test_gentime_settings ;
2022-10-28 04:17:48 +02:00
static const test_gentime_settings m_test_gentime_settings_default ;
2022-05-26 16:53:40 +02:00
} ; // class class test_generator
2018-12-27 18:50:45 +03:00
2022-11-01 00:10:51 +01:00
struct test_gentime_settings_restorer
{
test_gentime_settings_restorer ( ) : m_settings ( test_generator : : get_test_gentime_settings ( ) ) { }
~ test_gentime_settings_restorer ( ) { test_generator : : set_test_gentime_settings ( m_settings ) ; }
test_gentime_settings m_settings ;
} ;
2018-12-27 18:50:45 +03:00
extern const crypto : : signature invalid_signature ; // invalid non-null signature for test purpose
static const std : : vector < currency : : extra_v > empty_extra ;
static const std : : vector < currency : : attachment_v > empty_attachment ;
inline currency : : wide_difficulty_type get_test_difficulty ( ) { return 1 ; }
void fill_nonce ( currency : : block & blk , const currency : : wide_difficulty_type & diffic , uint64_t height ) ;
bool construct_miner_tx_manually ( size_t height , uint64_t already_generated_coins ,
const currency : : account_public_address & miner_address , currency : : transaction & tx ,
uint64_t fee , currency : : keypair * p_txkey = 0 ) ;
2022-05-11 23:52:33 +02:00
bool construct_tx_to_key ( const currency : : hard_forks_descriptor & hf ,
const std : : vector < test_event_entry > & events ,
2018-12-27 18:50:45 +03:00
currency : : transaction & tx ,
const currency : : block & blk_head ,
const currency : : account_base & from ,
const currency : : account_base & to ,
uint64_t amount ,
uint64_t fee ,
size_t nmix ,
uint8_t mix_attr = CURRENCY_TO_KEY_OUT_RELAXED ,
const std : : vector < currency : : extra_v > & extr = std : : vector < currency : : extra_v > ( ) ,
const std : : vector < currency : : attachment_v > & att = std : : vector < currency : : attachment_v > ( ) ,
bool check_for_spends = true ,
bool check_for_unlocktime = true ) ;
2022-05-11 23:52:33 +02:00
bool construct_tx_to_key ( const currency : : hard_forks_descriptor & hf ,
const std : : vector < test_event_entry > & events ,
2018-12-27 18:50:45 +03:00
currency : : transaction & tx ,
const currency : : block & blk_head ,
const currency : : account_base & from ,
const currency : : account_base & to ,
uint64_t amount ,
uint64_t fee ,
size_t nmix ,
crypto : : secret_key & sk ,
uint8_t mix_attr = CURRENCY_TO_KEY_OUT_RELAXED ,
const std : : vector < currency : : extra_v > & extr = std : : vector < currency : : extra_v > ( ) ,
const std : : vector < currency : : attachment_v > & att = std : : vector < currency : : attachment_v > ( ) ,
bool check_for_spends = true ,
bool check_for_unlocktime = true ) ;
2022-05-11 23:52:33 +02:00
bool construct_tx_to_key ( const currency : : hard_forks_descriptor & hf ,
const std : : vector < test_event_entry > & events ,
2018-12-27 18:50:45 +03:00
currency : : transaction & tx ,
const currency : : block & blk_head ,
const currency : : account_base & from ,
const std : : vector < currency : : tx_destination_entry > & destinations ,
2019-04-25 23:37:43 +02:00
uint64_t fee = TESTS_DEFAULT_FEE ,
2018-12-27 18:50:45 +03:00
size_t nmix = 0 ,
uint8_t mix_attr = CURRENCY_TO_KEY_OUT_RELAXED ,
const std : : vector < currency : : extra_v > & extr = empty_extra ,
const std : : vector < currency : : attachment_v > & att = empty_attachment ,
bool check_for_spends = true ,
bool check_for_unlocktime = true ,
bool use_ref_by_id = false ) ;
2022-05-11 23:52:33 +02:00
currency : : transaction construct_tx_with_fee ( const currency : : hard_forks_descriptor & hf , std : : vector < test_event_entry > & events , const currency : : block & blk_head ,
2018-12-27 18:50:45 +03:00
const currency : : account_base & acc_from , const currency : : account_base & acc_to ,
uint64_t amount , uint64_t fee ) ;
2022-05-11 23:52:33 +02:00
bool construct_tx_with_many_outputs ( const currency : : hard_forks_descriptor & hf , std : : vector < test_event_entry > & events , const currency : : block & blk_head ,
2018-12-27 18:50:45 +03:00
const currency : : account_keys & keys_from , const currency : : account_public_address & addr_to ,
2021-01-08 23:52:46 +03:00
uint64_t total_amount , size_t outputs_count , uint64_t fee , currency : : transaction & tx , bool use_ref_by_id = false ) ;
2018-12-27 18:50:45 +03:00
void get_confirmed_txs ( const std : : vector < currency : : block > & blockchain , const map_hash2tx_t & mtx , map_hash2tx_t & confirmed_txs ) ;
bool find_block_chain ( const std : : vector < test_event_entry > & events , std : : vector < currency : : block > & blockchain , map_hash2tx_t & mtx , const crypto : : hash & head ) ;
bool fill_tx_sources ( std : : vector < currency : : tx_source_entry > & sources , const std : : vector < test_event_entry > & events ,
const currency : : block & blk_head , const currency : : account_keys & from , uint64_t amount , size_t nmix , bool check_for_spends = true , bool check_for_unlocktime = true , bool use_ref_by_id = false ) ;
bool fill_tx_sources ( std : : vector < currency : : tx_source_entry > & sources , const std : : vector < test_event_entry > & events ,
const currency : : block & blk_head , const currency : : account_keys & from , uint64_t amount , size_t nmix ,
const std : : vector < currency : : tx_source_entry > & sources_to_avoid , bool check_for_spends = true , bool check_for_unlocktime = true ,
bool use_ref_by_id = false , uint64_t * p_sources_amount_found = nullptr ) ;
bool fill_tx_sources_and_destinations ( const std : : vector < test_event_entry > & events , const currency : : block & blk_head ,
const currency : : account_keys & from , const std : : list < currency : : account_public_address > & to ,
uint64_t amount , uint64_t fee , size_t nmix , std : : vector < currency : : tx_source_entry > & sources ,
std : : vector < currency : : tx_destination_entry > & destinations ,
bool check_for_spends = true ,
bool check_for_unlocktime = true ,
size_t minimum_sigs = SIZE_MAX ,
bool use_ref_by_id = false ) ;
bool fill_tx_sources_and_destinations ( const std : : vector < test_event_entry > & events , const currency : : block & blk_head ,
const currency : : account_keys & from , const currency : : account_public_address & to ,
uint64_t amount , uint64_t fee , size_t nmix ,
std : : vector < currency : : tx_source_entry > & sources ,
std : : vector < currency : : tx_destination_entry > & destinations ,
bool check_for_spends = true ,
bool check_for_unlocktime = true ,
bool use_ref_by_id = false ) ;
bool fill_tx_sources_and_destinations ( const std : : vector < test_event_entry > & events , const currency : : block & blk_head ,
const currency : : account_base & from , const currency : : account_base & to ,
uint64_t amount , uint64_t fee , size_t nmix ,
std : : vector < currency : : tx_source_entry > & sources ,
std : : vector < currency : : tx_destination_entry > & destinations ,
bool check_for_spends = true ,
bool check_for_unlocktime = true ,
bool use_ref_by_id = false ) ;
uint64_t get_balance ( const currency : : account_keys & addr , const std : : vector < currency : : block > & blockchain , const map_hash2tx_t & mtx , bool dbg_log = false ) ;
uint64_t get_balance ( const currency : : account_base & addr , const std : : vector < currency : : block > & blockchain , const map_hash2tx_t & mtx , bool dbg_log = false ) ;
2023-10-18 21:08:16 +02:00
void balance_via_wallet ( const tools : : wallet2 & w , const crypto : : public_key & asset_id , uint64_t * p_total , uint64_t * p_unlocked = 0 , uint64_t * p_awaiting_in = 0 , uint64_t * p_awaiting_out = 0 , uint64_t * p_mined = 0 ) ;
2018-12-27 18:50:45 +03:00
# define INVALID_BALANCE_VAL std::numeric_limits<uint64_t>::max()
bool check_balance_via_wallet ( const tools : : wallet2 & w , const char * account_name ,
uint64_t expected_total ,
uint64_t expected_mined = INVALID_BALANCE_VAL ,
uint64_t expected_unlocked = INVALID_BALANCE_VAL ,
uint64_t expected_awaiting_in = INVALID_BALANCE_VAL ,
2023-10-18 21:08:16 +02:00
uint64_t expected_awaiting_out = INVALID_BALANCE_VAL ,
const crypto : : public_key & asset_id = currency : : native_coin_asset_id ) ;
2018-12-27 18:50:45 +03:00
bool calculate_amounts_many_outs_have_and_no_outs_have ( const uint64_t first_blocks_reward , uint64_t & amount_many_outs_have , uint64_t & amount_no_outs_have ) ;
bool find_global_index_for_output ( const std : : vector < test_event_entry > & events , const crypto : : hash & head_block_hash , const currency : : transaction & reference_tx , const size_t reference_tx_out_index , uint64_t & global_index ) ;
size_t get_tx_out_index_by_amount ( const currency : : transaction & tx , const uint64_t amount ) ;
bool sign_multisig_input_in_tx_custom ( currency : : transaction & tx , size_t ms_input_index , const currency : : account_keys & keys , const currency : : transaction & source_tx , bool * p_is_input_fully_signed = nullptr , bool compact_sigs = true ) ;
bool make_tx_multisig_to_key ( const currency : : transaction & source_tx ,
size_t source_tx_out_idx ,
const std : : list < currency : : account_keys > & participants ,
const currency : : account_public_address & target_address ,
currency : : transaction & tx ,
2019-04-25 23:37:43 +02:00
uint64_t fee = TESTS_DEFAULT_FEE ,
2018-12-27 18:50:45 +03:00
const std : : vector < currency : : attachment_v > & attachments = empty_attachment ,
const std : : vector < currency : : extra_v > & extra = empty_extra ) ;
2023-06-16 20:19:49 +02:00
bool estimate_wallet_balance_blocked_for_escrow ( const tools : : wallet2 & w , uint64_t & result , bool substruct_change_from_result = true ) ;
2018-12-27 18:50:45 +03:00
bool check_wallet_balance_blocked_for_escrow ( const tools : : wallet2 & w , const char * wallet_name , uint64_t expected_amount ) ;
bool refresh_wallet_and_check_balance ( const char * intro_log_message , const char * wallet_name , std : : shared_ptr < tools : : wallet2 > wallet , uint64_t expected_total ,
bool print_transfers = false ,
size_t block_to_be_fetched = SIZE_MAX ,
uint64_t expected_unlocked = UINT64_MAX ,
uint64_t expected_mined = UINT64_MAX ,
uint64_t expected_awaiting_in = UINT64_MAX ,
uint64_t expected_awaiting_out = UINT64_MAX ) ;
uint64_t get_last_block_of_type ( bool looking_for_pos , const test_generator : : blockchain_vector & blck_chain ) ;
bool generate_pos_block_with_given_coinstake ( test_generator & generator , const std : : vector < test_event_entry > & events , const currency : : account_base & miner , const currency : : block & prev_block , const currency : : transaction & stake_tx , size_t stake_output_idx , currency : : block & result , uint64_t stake_output_gidx = UINT64_MAX ) ;
bool check_ring_signature_at_gen_time ( const std : : vector < test_event_entry > & events , const crypto : : hash & last_block_id , const currency : : txin_to_key & in_t_k ,
const crypto : : hash & hash_for_sig , const std : : vector < crypto : : signature > & sig ) ;
2021-10-19 04:46:20 +03:00
bool check_mixin_value_for_each_input ( size_t mixin , const crypto : : hash & tx_id , currency : : core & c ) ;
2018-12-27 18:50:45 +03:00
2022-11-09 16:57:48 +01:00
bool shuffle_source_entry ( currency : : tx_source_entry & se ) ;
bool shuffle_source_entries ( std : : vector < currency : : tx_source_entry > & sources ) ;
2023-08-06 01:51:31 +02:00
// one output will be created for each destination entry and one additional output to add up to old coinbase total amount
bool replace_coinbase_in_genesis_block ( const std : : vector < currency : : tx_destination_entry > & destinations , test_generator & generator , std : : vector < test_event_entry > & events , currency : : block & genesis_block ) ;
2018-12-27 18:50:45 +03:00
//--------------------------------------------------------------------------
template < class t_test_class >
auto do_check_tx_verification_context ( const currency : : tx_verification_context & tvc , bool tx_added , size_t event_index , const currency : : transaction & tx , t_test_class & validator , int )
- > decltype ( validator . check_tx_verification_context ( tvc , tx_added , event_index , tx ) )
{
return validator . check_tx_verification_context ( tvc , tx_added , event_index , tx ) ;
}
//--------------------------------------------------------------------------
template < class t_test_class >
bool do_check_tx_verification_context ( const currency : : tx_verification_context & tvc , bool tx_added , size_t /*event_index*/ , const currency : : transaction & /*tx*/ , t_test_class & , long )
{
// Default block verification context check
if ( tvc . m_verification_failed )
throw std : : runtime_error ( " Transaction verification failed " ) ;
return true ;
}
//--------------------------------------------------------------------------
template < class t_test_class >
bool check_tx_verification_context ( const currency : : tx_verification_context & tvc , bool tx_added , size_t event_index , const currency : : transaction & tx , t_test_class & validator )
{
// SFINAE in action
return do_check_tx_verification_context ( tvc , tx_added , event_index , tx , validator , 0 ) ;
}
//--------------------------------------------------------------------------
template < class t_test_class >
auto do_check_block_verification_context ( const currency : : block_verification_context & bvc , size_t event_index , const currency : : block & blk , t_test_class & validator , int )
- > decltype ( validator . check_block_verification_context ( bvc , event_index , blk ) )
{
return validator . check_block_verification_context ( bvc , event_index , blk ) ;
}
//--------------------------------------------------------------------------
template < class t_test_class >
bool do_check_block_verification_context ( const currency : : block_verification_context & bvc , size_t /*event_index*/ , const currency : : block & /*blk*/ , t_test_class & , long )
{
// Default block verification context check
if ( bvc . m_verification_failed )
throw std : : runtime_error ( " Block verification failed " ) ;
return true ;
}
//--------------------------------------------------------------------------
template < class t_test_class >
bool check_block_verification_context ( const currency : : block_verification_context & bvc , size_t event_index , const currency : : block & blk , t_test_class & validator )
{
// SFINAE in action
return do_check_block_verification_context ( bvc , event_index , blk , validator , 0 ) ;
}
template < class attachment_cb >
bool construct_broken_tx ( const currency : : account_keys & sender_account_keys , const std : : vector < currency : : tx_source_entry > & sources ,
const std : : vector < currency : : tx_destination_entry > & destinations ,
const std : : vector < currency : : extra_v > & extra ,
const std : : vector < currency : : attachment_v > & attachments ,
currency : : transaction & tx ,
uint64_t unlock_time ,
uint8_t tx_outs_attr , attachment_cb acb )
{
tx . vin . clear ( ) ;
tx . vout . clear ( ) ;
2022-06-19 19:47:43 +02:00
tx . signatures . clear ( ) ;
2018-12-27 18:50:45 +03:00
tx . extra = extra ;
2022-05-13 23:35:56 +02:00
tx . version = TRANSACTION_VERSION_PRE_HF4 ;
2018-12-27 18:50:45 +03:00
set_tx_unlock_time ( tx , unlock_time ) ;
currency : : keypair txkey = currency : : keypair : : generate ( ) ;
add_tx_pub_key_to_extra ( tx , txkey . pub ) ;
struct input_generation_context_data
{
currency : : keypair in_ephemeral ;
2023-11-02 18:40:09 +01:00
std : : vector < currency : : tx_source_entry : : output_entry > sorted_outputs ;
2023-11-02 18:29:55 +01:00
size_t real_out_index = 0 ;
2018-12-27 18:50:45 +03:00
} ;
std : : vector < input_generation_context_data > in_contexts ;
uint64_t summary_inputs_money = 0 ;
2023-11-02 18:29:55 +01:00
// fill inputs
for ( const currency : : tx_source_entry & src_entr : sources )
2018-12-27 18:50:45 +03:00
{
2023-11-02 18:29:55 +01:00
CHECK_AND_ASSERT_MES ( src_entr . real_output < src_entr . outputs . size ( ) , false , " real_output index = " < < src_entr . real_output < < " is bigger than output_keys.size() = " < < src_entr . outputs . size ( ) ) ;
input_generation_context_data & igc = in_contexts . emplace_back ( ) ;
igc . sorted_outputs = prepare_outputs_entries_for_key_offsets ( src_entr . outputs , src_entr . real_output , igc . real_out_index ) ;
2018-12-27 18:50:45 +03:00
summary_inputs_money + = src_entr . amount ;
crypto : : key_image img ;
2023-11-02 18:29:55 +01:00
if ( ! currency : : generate_key_image_helper ( sender_account_keys , src_entr . real_out_tx_key , src_entr . real_output_in_tx_index , igc . in_ephemeral , img ) )
2018-12-27 18:50:45 +03:00
return false ;
//check that derivated key is equal with real output key
2023-11-02 18:29:55 +01:00
if ( ! ( igc . in_ephemeral . pub = = igc . sorted_outputs [ igc . real_out_index ] . stealth_address ) )
2018-12-27 18:50:45 +03:00
{
LOG_ERROR ( " derived public key missmatch with output public key! " < < ENDL < < " derived_key: "
2023-11-02 18:29:55 +01:00
< < epst : : pod_to_hex ( igc . in_ephemeral . pub ) < < ENDL < < " real output_public_key: "
< < epst : : pod_to_hex ( igc . sorted_outputs [ igc . real_out_index ] . stealth_address ) ) ;
2018-12-27 18:50:45 +03:00
return false ;
}
2023-11-02 18:29:55 +01:00
// fill tx input
2018-12-27 18:50:45 +03:00
currency : : txin_to_key input_to_key ;
input_to_key . amount = src_entr . amount ;
input_to_key . k_image = img ;
2023-11-02 18:29:55 +01:00
// fill ring references
for ( const currency : : tx_source_entry : : output_entry & out_entry : igc . sorted_outputs )
2022-07-13 17:17:04 +02:00
input_to_key . key_offsets . push_back ( out_entry . out_reference ) ;
2018-12-27 18:50:45 +03:00
tx . vin . push_back ( input_to_key ) ;
}
// "Shuffle" outs
std : : vector < currency : : tx_destination_entry > shuffled_dsts ( destinations ) ;
std : : sort ( shuffled_dsts . begin ( ) , shuffled_dsts . end ( ) , [ ] ( const currency : : tx_destination_entry & de1 , const currency : : tx_destination_entry & de2 ) { return de1 . amount < de2 . amount ; } ) ;
uint64_t summary_outs_money = 0 ;
//fill outputs
size_t output_index = 0 ;
std : : set < uint16_t > der_hints ;
BOOST_FOREACH ( const currency : : tx_destination_entry & dst_entr , shuffled_dsts )
{
CHECK_AND_ASSERT_MES ( dst_entr . amount > 0 , false , " Destination with wrong amount: " < < dst_entr . amount ) ;
2021-02-03 18:37:57 +01:00
bool r = construct_tx_out ( dst_entr , txkey . sec , output_index , tx , der_hints , sender_account_keys , tx_outs_attr ) ;
2018-12-27 18:50:45 +03:00
CHECK_AND_ASSERT_MES ( r , false , " Failed to construc tx out " ) ;
output_index + + ;
summary_outs_money + = dst_entr . amount ;
}
//check money
if ( summary_outs_money > summary_inputs_money )
{
LOG_ERROR ( " Transaction inputs money ( " < < summary_inputs_money < < " ) less than outputs money ( " < < summary_outs_money < < " ) " ) ;
return false ;
}
//include offers if need
tx . attachment = attachments ;
if ( ! acb ( tx ) )
return false ;
//generate ring signatures
crypto : : hash tx_prefix_hash ;
get_transaction_prefix_hash ( tx , tx_prefix_hash ) ;
std : : stringstream ss_ring_s ;
size_t i = 0 ;
2023-11-02 18:29:55 +01:00
for ( const currency : : tx_source_entry & src_entr : sources )
2018-12-27 18:50:45 +03:00
{
ss_ring_s < < " pub_keys: " < < ENDL ;
std : : vector < const crypto : : public_key * > keys_ptrs ;
2023-11-02 18:29:55 +01:00
for ( const currency : : tx_source_entry : : output_entry & o : in_contexts [ i ] . sorted_outputs )
2018-12-27 18:50:45 +03:00
{
2022-07-13 17:17:04 +02:00
keys_ptrs . push_back ( & o . stealth_address ) ;
ss_ring_s < < o . stealth_address < < ENDL ;
2018-12-27 18:50:45 +03:00
}
2022-06-25 00:06:26 +02:00
tx . signatures . push_back ( currency : : NLSAG_sig ( ) ) ;
2022-06-19 19:47:43 +02:00
std : : vector < crypto : : signature > & sigs = boost : : get < currency : : NLSAG_sig > ( tx . signatures . back ( ) ) . s ;
2018-12-27 18:50:45 +03:00
sigs . resize ( src_entr . outputs . size ( ) ) ;
2023-11-02 18:29:55 +01:00
crypto : : generate_ring_signature ( tx_prefix_hash , boost : : get < currency : : txin_to_key > ( tx . vin [ i ] ) . k_image , keys_ptrs , in_contexts [ i ] . in_ephemeral . sec , in_contexts [ i ] . real_out_index , sigs . data ( ) ) ;
2018-12-27 18:50:45 +03:00
ss_ring_s < < " signatures: " < < ENDL ;
std : : for_each ( sigs . begin ( ) , sigs . end ( ) , [ & ] ( const crypto : : signature & s ) { ss_ring_s < < s < < ENDL ; } ) ;
2023-11-02 18:29:55 +01:00
ss_ring_s < < " prefix_hash: " < < tx_prefix_hash < < ENDL < < " in_ephemeral_key: " < < in_contexts [ i ] . in_ephemeral . sec < < ENDL < < " real_output: " < < in_contexts [ i ] . real_out_index ;
2018-12-27 18:50:45 +03:00
i + + ;
}
LOG_PRINT2 ( " construct_tx.log " , " transaction_created: " < < get_transaction_hash ( tx ) < < ENDL < < obj_to_json_str ( tx ) < < ENDL < < ss_ring_s . str ( ) , LOG_LEVEL_3 ) ;
return true ;
}
template < typename callback_t >
bool construct_broken_tx ( std : : list < currency : : transaction > & txs_set ,
std : : vector < test_event_entry > & events ,
const currency : : account_base & sender_account_keys ,
const currency : : account_base & rcvr_account_keys ,
const currency : : block & blk_head ,
const std : : vector < currency : : attachment_v > & att ,
callback_t cb )
{
currency : : transaction t = AUTO_VAL_INIT ( t ) ;
std : : vector < currency : : tx_source_entry > sources ;
std : : vector < currency : : tx_destination_entry > destinations ;
fill_tx_sources_and_destinations ( events , blk_head , sender_account_keys , rcvr_account_keys , MK_TEST_COINS ( 1 ) , TESTS_DEFAULT_FEE , 0 , sources , destinations , true ) ;
bool r = construct_broken_tx ( sender_account_keys . get_keys ( ) , sources , destinations , std : : vector < currency : : extra_v > ( ) , att , t , 0 , CURRENCY_TO_KEY_OUT_RELAXED , cb ) ;
txs_set . push_back ( t ) ;
events . push_back ( t ) ;
return r ;
}
template < typename cb_t >
bool test_generator : : construct_block_gentime_with_coinbase_cb ( const currency : : block & prev_block , const currency : : account_base & acc , cb_t cb , currency : : block & b )
{
bool r = false ;
crypto : : hash prev_id = get_block_hash ( prev_block ) ;
uint64_t already_generated_coins = get_already_generated_coins ( prev_block ) ;
std : : vector < size_t > block_sizes ;
get_last_n_block_sizes ( block_sizes , prev_id , CURRENCY_REWARD_BLOCKS_WINDOW ) ;
currency : : transaction miner_tx = AUTO_VAL_INIT ( miner_tx ) ;
size_t height = get_block_height ( prev_block ) + 1 ;
//size_t current_block_size = get_object_blobsize(miner_tx);
2023-06-09 01:19:37 +02:00
uint64_t block_reward_without_fee = 0 ;
2024-02-07 18:48:18 +01:00
uint64_t block_reward = 0 ;
2023-06-09 01:19:37 +02:00
2023-08-06 03:17:26 +02:00
currency : : keypair tx_sec_key = currency : : keypair : : generate ( ) ;
2023-08-04 02:47:52 +02:00
r = construct_miner_tx ( height , epee : : misc_utils : : median ( block_sizes ) , already_generated_coins , 0 /* current_block_size !HACK! */ , 0 ,
2024-02-07 18:48:18 +01:00
acc . get_public_address ( ) , acc . get_public_address ( ) , miner_tx , block_reward_without_fee , block_reward , get_tx_version ( height , m_hardforks ) , currency : : blobdata ( ) , /* max outs: */ 1 ,
2023-08-04 02:47:52 +02:00
/* pos: */ false , currency : : pos_entry ( ) , /* ogc_ptr: */ nullptr , & tx_sec_key ) ;
2018-12-27 18:50:45 +03:00
CHECK_AND_ASSERT_MES ( r , false , " construct_miner_tx failed " ) ;
2023-08-04 02:47:52 +02:00
if ( ! cb ( miner_tx , tx_sec_key ) )
2018-12-27 18:50:45 +03:00
return false ;
currency : : wide_difficulty_type diff = get_difficulty_for_next_block ( prev_id , true ) ;
2023-04-30 00:43:49 +02:00
r = construct_block_manually ( b , prev_block , acc ,
test_generator : : block_fields : : bf_miner_tx | test_generator : : block_fields : : bf_major_ver | test_generator : : block_fields : : bf_minor_ver ,
m_hardforks . get_block_major_version_by_height ( height ) ,
m_hardforks . get_block_minor_version_by_height ( height ) ,
0 , prev_id , diff , miner_tx ) ;
2018-12-27 18:50:45 +03:00
CHECK_AND_ASSERT_MES ( r , false , " construct_block_manually failed " ) ;
return true ;
}
namespace crypto {
inline std : : ostream & operator < < ( std : : ostream & o , const currency : : account_base & acc )
{
return o < <
" account: " < < std : : endl < <
" addr: " < < get_account_address_as_str ( acc . get_public_address ( ) ) < < std : : endl < <
2020-04-23 14:56:03 +03:00
" spend secret key: " < < acc . get_keys ( ) . spend_secret_key < < std : : endl < <
" spend public key: " < < acc . get_public_address ( ) . spend_public_key < < std : : endl < <
" view secret key: " < < acc . get_keys ( ) . view_secret_key < < std : : endl < <
" view public key: " < < acc . get_public_address ( ) . view_public_key < < std : : endl < <
2018-12-27 18:50:45 +03:00
" timestamp: " < < acc . get_createtime ( ) ;
}
}
inline uint64_t get_sources_total_amount ( const std : : vector < currency : : tx_source_entry > & s )
{
uint64_t result = 0 ;
for ( auto & e : s )
result + = e . amount ;
return result ;
}
2021-01-08 02:22:29 +03:00
inline void count_ref_by_id_and_gindex_refs_for_tx_inputs ( const currency : : transaction & tx , size_t & refs_by_id , size_t & refs_by_gindex )
{
refs_by_id = 0 ;
refs_by_gindex = 0 ;
for ( auto & in : tx . vin )
{
if ( in . type ( ) ! = typeid ( currency : : txin_to_key ) )
continue ;
const currency : : txin_to_key & in2key = boost : : get < currency : : txin_to_key > ( in ) ;
for ( auto & ko : in2key . key_offsets )
{
if ( ko . type ( ) = = typeid ( currency : : ref_by_id ) )
+ + refs_by_id ;
else if ( ko . type ( ) = = typeid ( uint64_t ) )
+ + refs_by_gindex ;
}
}
}
2018-12-27 18:50:45 +03:00
template < typename U , typename V >
void append_vector_by_another_vector ( U & dst , const V & src )
{
dst . reserve ( dst . size ( ) + src . size ( ) ) ;
dst . insert ( dst . end ( ) , src . begin ( ) , src . end ( ) ) ;
}
//--------------------------------------------------------------------------
2022-05-26 17:01:28 +02:00
# define PRINT_EVENT_N(VEC_EVENTS) std::cout << concolor::yellow << ">EVENT # " << VEC_EVENTS.size() << ", line " << STR(__LINE__) << concolor::normal << std::endl
# define PRINT_EVENT_N_TEXT(VEC_EVENTS, text) std::cout << concolor::yellow << ">EVENT # " << VEC_EVENTS.size() << ", line " << STR(__LINE__) << " " << text << concolor::normal << std::endl
2018-12-27 18:50:45 +03:00
2022-05-26 17:01:28 +02:00
# define GENERATE_ACCOUNT(account) \
currency : : account_base account ; \
account . generate ( )
2018-12-27 18:50:45 +03:00
2022-05-26 17:01:28 +02:00
# define MAKE_ACCOUNT(VEC_EVENTS, account) \
PRINT_EVENT_N_TEXT ( VEC_EVENTS , " MAKE_ACCOUNT( " < < # account < < " ) " ) ; \
currency : : account_base account ; \
account . generate ( ) ; \
VEC_EVENTS . push_back ( account )
2018-12-27 18:50:45 +03:00
# define DO_CALLBACK(VEC_EVENTS, CB_NAME) \
2022-05-26 17:01:28 +02:00
{ \
PRINT_EVENT_N_TEXT ( VEC_EVENTS , " DO_CALLBACK( " < < # CB_NAME < < " ) " ) ; \
callback_entry CALLBACK_ENTRY ; \
CALLBACK_ENTRY . callback_name = CB_NAME ; \
VEC_EVENTS . push_back ( CALLBACK_ENTRY ) ; \
}
2018-12-27 18:50:45 +03:00
# define DO_CALLBACK_PARAMS(VEC_EVENTS, CB_NAME, PARAMS_POD_OBJ) \
{ \
2022-05-26 17:01:28 +02:00
PRINT_EVENT_N_TEXT ( VEC_EVENTS , " DO_CALLBACK_PARAMS( " < < # CB_NAME < < " ) " ) ; \
2018-12-27 18:50:45 +03:00
callback_entry ce = AUTO_VAL_INIT ( ce ) ; \
ce . callback_name = CB_NAME ; \
2022-05-11 21:02:06 +02:00
ce . callback_params = epst : : pod_to_hex ( PARAMS_POD_OBJ ) ; \
2018-12-27 18:50:45 +03:00
VEC_EVENTS . push_back ( ce ) ; \
}
# define DO_CALLBACK_PARAMS_STR(VEC_EVENTS, CB_NAME, STR_PARAMS) \
{ \
2022-05-26 17:01:28 +02:00
PRINT_EVENT_N_TEXT ( VEC_EVENTS , " DO_CALLBACK_PARAMS_STR( " < < # CB_NAME < < " ) " ) ; \
2018-12-27 18:50:45 +03:00
callback_entry ce = AUTO_VAL_INIT ( ce ) ; \
ce . callback_name = CB_NAME ; \
ce . callback_params = STR_PARAMS ; \
VEC_EVENTS . push_back ( ce ) ; \
}
# define REGISTER_CALLBACK(CB_NAME, CLBACK) \
2022-03-20 03:22:46 +03:00
register_callback ( CB_NAME , boost : : bind ( & CLBACK , this , boost : : placeholders : : _1 , boost : : placeholders : : _2 , boost : : placeholders : : _3 ) )
2018-12-27 18:50:45 +03:00
# define REGISTER_CALLBACK_METHOD(CLASS, METHOD) \
2022-03-20 03:22:46 +03:00
register_callback ( # METHOD , boost : : bind ( & CLASS : : METHOD , this , boost : : placeholders : : _1 , boost : : placeholders : : _2 , boost : : placeholders : : _3 ) )
2018-12-27 18:50:45 +03:00
# define MAKE_GENESIS_BLOCK(VEC_EVENTS, BLK_NAME, MINER_ACC, TS) \
2022-05-26 17:01:28 +02:00
PRINT_EVENT_N_TEXT ( VEC_EVENTS , " MAKE_GENESIS_BLOCK( " < < # BLK_NAME < < " ) " ) ; \
2018-12-27 18:50:45 +03:00
test_generator generator ; \
2022-10-26 17:58:58 +02:00
this - > on_test_generator_created ( generator ) ; \
2018-12-27 18:50:45 +03:00
currency : : block BLK_NAME = AUTO_VAL_INIT ( BLK_NAME ) ; \
generator . construct_genesis_block ( BLK_NAME , MINER_ACC , TS ) ; \
2022-05-26 17:01:28 +02:00
VEC_EVENTS . push_back ( BLK_NAME )
2018-12-27 18:50:45 +03:00
# define MAKE_NEXT_BLOCK(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC) \
2022-05-26 17:01:28 +02:00
PRINT_EVENT_N_TEXT ( VEC_EVENTS , " MAKE_NEXT_BLOCK( " < < # BLK_NAME < < " ) " ) ; \
2018-12-27 18:50:45 +03:00
currency : : block BLK_NAME = AUTO_VAL_INIT ( BLK_NAME ) ; \
generator . construct_block ( VEC_EVENTS , BLK_NAME , PREV_BLOCK , MINER_ACC ) ; \
2022-05-26 17:01:28 +02:00
VEC_EVENTS . push_back ( BLK_NAME )
2018-12-27 18:50:45 +03:00
2019-08-01 18:47:20 +02:00
2022-05-26 17:01:28 +02:00
# define MAKE_NEXT_BLOCK_TIMESTAMP_ADJUSTMENT(ADJ, VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC) \
2022-10-28 01:07:45 +02:00
PRINT_EVENT_N_TEXT ( VEC_EVENTS , " MAKE_NEXT_BLOCK_TIMESTAMP_ADJUSTMENT( " < < # BLK_NAME < < " ) " ) ; \
2019-08-01 18:47:20 +02:00
currency : : block BLK_NAME = AUTO_VAL_INIT ( BLK_NAME ) ; \
2022-05-26 17:01:28 +02:00
generator . construct_block ( ADJ , VEC_EVENTS , BLK_NAME , PREV_BLOCK , MINER_ACC ) ; \
VEC_EVENTS . push_back ( BLK_NAME )
2019-08-01 18:47:20 +02:00
2022-05-26 17:01:28 +02:00
# define MAKE_NEXT_POS_BLOCK(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC, MINERS_ACC_LIST) \
2022-10-28 01:07:45 +02:00
PRINT_EVENT_N_TEXT ( VEC_EVENTS , " MAKE_NEXT_POS_BLOCK( " < < # BLK_NAME < < " ) " ) ; \
2018-12-27 18:50:45 +03:00
currency : : block BLK_NAME = AUTO_VAL_INIT ( BLK_NAME ) ; \
2022-05-26 17:01:28 +02:00
generator . construct_block ( VEC_EVENTS , BLK_NAME , PREV_BLOCK , MINER_ACC , std : : list < currency : : transaction > ( ) , MINERS_ACC_LIST ) ; \
VEC_EVENTS . push_back ( BLK_NAME )
2018-12-27 18:50:45 +03:00
2019-08-03 19:15:56 +02:00
# define MAKE_NEXT_POS_BLOCK_TX1(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC, MINERS_ACC_LIST, TX_1) \
2022-10-28 01:07:45 +02:00
PRINT_EVENT_N_TEXT ( VEC_EVENTS , " MAKE_NEXT_POS_BLOCK_TX1( " < < # BLK_NAME < < " ) " ) ; \
2019-08-03 19:15:56 +02:00
currency : : block BLK_NAME = AUTO_VAL_INIT ( BLK_NAME ) ; \
{ \
2023-10-16 11:41:24 +02:00
std : : list < currency : : transaction > tx_list ; \
2019-08-03 19:15:56 +02:00
tx_list . push_back ( TX_1 ) ; \
2023-10-16 11:41:24 +02:00
if ( ! generator . construct_block ( VEC_EVENTS , BLK_NAME , PREV_BLOCK , MINER_ACC , tx_list , MINERS_ACC_LIST ) ) \
return false ; \
2019-08-03 19:15:56 +02:00
} \
2022-05-26 17:01:28 +02:00
VEC_EVENTS . push_back ( BLK_NAME )
2019-08-03 19:15:56 +02:00
2018-12-27 18:50:45 +03:00
# define MAKE_NEXT_BLOCK_NO_ADD(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC) \
2022-10-28 01:07:45 +02:00
PRINT_EVENT_N_TEXT ( VEC_EVENTS , " MAKE_NEXT_BLOCK_NO_ADD( " < < # BLK_NAME < < " ) " ) ; \
2018-12-27 18:50:45 +03:00
currency : : block BLK_NAME = AUTO_VAL_INIT ( BLK_NAME ) ; \
generator . construct_block ( VEC_EVENTS , BLK_NAME , PREV_BLOCK , MINER_ACC ) ; \
2022-05-26 17:01:28 +02:00
VEC_EVENTS . push_back ( event_special_block ( BLK_NAME , event_special_block : : flag_skip ) )
2018-12-27 18:50:45 +03:00
# define ADD_BLOCK(VEC_EVENTS, BLK_NAME) \
2022-05-26 17:01:28 +02:00
PRINT_EVENT_N_TEXT ( VEC_EVENTS , " ADD_BLOCK( " < < # BLK_NAME < < " ) " ) ; \
VEC_EVENTS . push_back ( BLK_NAME )
2018-12-27 18:50:45 +03:00
# define MAKE_NEXT_BLOCK_TX1(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC, TX1) \
2022-10-28 01:07:45 +02:00
PRINT_EVENT_N_TEXT ( VEC_EVENTS , " MAKE_NEXT_BLOCK_TX1( " < < # BLK_NAME < < " , " < < # TX1 < < " ) " ) ; \
2018-12-27 18:50:45 +03:00
currency : : block BLK_NAME = AUTO_VAL_INIT ( BLK_NAME ) ; \
2022-05-26 17:01:28 +02:00
{ \
std : : list < currency : : transaction > tx_list ; \
tx_list . push_back ( TX1 ) ; \
generator . construct_block ( VEC_EVENTS , BLK_NAME , PREV_BLOCK , MINER_ACC , tx_list ) ; \
} \
VEC_EVENTS . push_back ( BLK_NAME )
2018-12-27 18:50:45 +03:00
2019-08-03 19:15:56 +02:00
2018-12-27 18:50:45 +03:00
# define MAKE_NEXT_BLOCK_TX_LIST(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC, TXLIST) \
2022-10-28 01:07:45 +02:00
PRINT_EVENT_N_TEXT ( VEC_EVENTS , " MAKE_NEXT_BLOCK_TX_LIST( " < < # BLK_NAME < < " , " < < # TXLIST < < " ) " ) ; \
2018-12-27 18:50:45 +03:00
currency : : block BLK_NAME = AUTO_VAL_INIT ( BLK_NAME ) ; \
generator . construct_block ( VEC_EVENTS , BLK_NAME , PREV_BLOCK , MINER_ACC , TXLIST ) ; \
2022-05-26 17:01:28 +02:00
VEC_EVENTS . push_back ( BLK_NAME )
2018-12-27 18:50:45 +03:00
# define REWIND_BLOCKS_N(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC, COUNT) \
currency : : block BLK_NAME = AUTO_VAL_INIT ( BLK_NAME ) ; \
2022-05-26 17:01:28 +02:00
{ \
currency : : block blk_last = PREV_BLOCK ; \
for ( size_t i = 0 ; i < COUNT ; + + i ) \
2018-12-27 18:50:45 +03:00
{ \
2022-05-26 17:01:28 +02:00
MAKE_NEXT_BLOCK ( VEC_EVENTS , blk , blk_last , MINER_ACC ) ; \
blk_last = blk ; \
2018-12-27 18:50:45 +03:00
} \
2022-05-26 17:01:28 +02:00
BLK_NAME = blk_last ; \
}
2018-12-27 18:50:45 +03:00
# define REWIND_BLOCKS_N_WITH_TIME(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC, COUNT) \
currency : : block BLK_NAME = PREV_BLOCK ; \
for ( size_t i = 0 ; i < COUNT ; + + i ) \
{ \
2022-05-26 17:01:28 +02:00
PRINT_EVENT_N_TEXT ( VEC_EVENTS , " REWIND_BLOCKS_N_WITH_TIME( " < < # BLK_NAME < < " , " < < # PREV_BLOCK < < " , " < < # MINER_ACC < < " , " < < # COUNT < < " ) " ) ; \
2018-12-27 18:50:45 +03:00
currency : : block next_block = AUTO_VAL_INIT ( next_block ) ; \
generator . construct_block ( VEC_EVENTS , next_block , BLK_NAME , MINER_ACC ) ; \
VEC_EVENTS . push_back ( event_core_time ( next_block . timestamp - 10 ) ) ; \
VEC_EVENTS . push_back ( next_block ) ; \
BLK_NAME = next_block ; \
2022-09-23 18:45:22 +02:00
}
2018-12-27 18:50:45 +03:00
# define REWIND_BLOCKS(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC) REWIND_BLOCKS_N(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC, CURRENCY_MINED_MONEY_UNLOCK_WINDOW)
2022-05-26 17:01:28 +02:00
# define MAKE_TX_MIX_ATTR_EXTRA(VEC_EVENTS, TX_NAME, FROM, TO, AMOUNT, NMIX, HEAD, MIX_ATTR, EXTRA, CHECK_SPENDS) \
2022-10-28 01:07:45 +02:00
PRINT_EVENT_N_TEXT ( VEC_EVENTS , " transaction " < < # TX_NAME ) ; \
2022-05-26 17:01:28 +02:00
currency : : transaction TX_NAME ; \
{ \
bool txr = construct_tx_to_key ( generator . get_hardforks ( ) , VEC_EVENTS , TX_NAME , HEAD , FROM , TO , AMOUNT , TESTS_DEFAULT_FEE , NMIX , generator . last_tx_generated_secret_key , MIX_ATTR , EXTRA , std : : vector < currency : : attachment_v > ( ) , CHECK_SPENDS ) ; \
CHECK_AND_ASSERT_THROW_MES ( txr , " failed to construct transaction " ) ; \
} \
VEC_EVENTS . push_back ( TX_NAME )
2018-12-27 18:50:45 +03:00
# define MAKE_TX_FEE_MIX_ATTR_EXTRA(VEC_EVENTS, TX_NAME, FROM, TO, AMOUNT, FEE, NMIX, HEAD, MIX_ATTR, EXTRA, CHECK_SPENDS) \
2022-10-28 01:07:45 +02:00
PRINT_EVENT_N_TEXT ( VEC_EVENTS , " transaction " < < # TX_NAME ) ; \
2022-05-26 17:01:28 +02:00
currency : : transaction TX_NAME ; \
{ \
bool txr = construct_tx_to_key ( generator . get_hardforks ( ) , VEC_EVENTS , TX_NAME , HEAD , FROM , TO , AMOUNT , FEE , NMIX , generator . last_tx_generated_secret_key , MIX_ATTR , EXTRA , std : : vector < currency : : attachment_v > ( ) , CHECK_SPENDS ) ; \
CHECK_AND_ASSERT_THROW_MES ( txr , " failed to construct transaction " ) ; \
} \
VEC_EVENTS . push_back ( TX_NAME )
2018-12-27 18:50:45 +03:00
# define MAKE_TX_MIX_ATTR(VEC_EVENTS, TX_NAME, FROM, TO, AMOUNT, NMIX, HEAD, MIX_ATTR, CHECK_SPENDS) \
MAKE_TX_MIX_ATTR_EXTRA ( VEC_EVENTS , TX_NAME , FROM , TO , AMOUNT , NMIX , HEAD , MIX_ATTR , std : : vector < currency : : extra_v > ( ) , CHECK_SPENDS ) ;
# define MAKE_TX_FEE_MIX_ATTR(VEC_EVENTS, TX_NAME, FROM, TO, AMOUNT, FEE, NMIX, HEAD, MIX_ATTR, CHECK_SPENDS) \
MAKE_TX_FEE_MIX_ATTR_EXTRA ( VEC_EVENTS , TX_NAME , FROM , TO , AMOUNT , FEE , NMIX , HEAD , MIX_ATTR , std : : vector < currency : : extra_v > ( ) , CHECK_SPENDS ) ;
# define MAKE_TX_MIX(VEC_EVENTS, TX_NAME, FROM, TO, AMOUNT, NMIX, HEAD) MAKE_TX_MIX_ATTR(VEC_EVENTS, TX_NAME, FROM, TO, AMOUNT, NMIX, HEAD, CURRENCY_TO_KEY_OUT_RELAXED, true)
# define MAKE_TX_FEE_MIX(VEC_EVENTS, TX_NAME, FROM, TO, AMOUNT, FEE, NMIX, HEAD) MAKE_TX_FEE_MIX_ATTR(VEC_EVENTS, TX_NAME, FROM, TO, AMOUNT, FEE, NMIX, HEAD, CURRENCY_TO_KEY_OUT_RELAXED, true)
# define MAKE_TX(VEC_EVENTS, TX_NAME, FROM, TO, AMOUNT, HEAD) MAKE_TX_MIX(VEC_EVENTS, TX_NAME, FROM, TO, AMOUNT, 0, HEAD)
# define MAKE_TX_FEE(VEC_EVENTS, TX_NAME, FROM, TO, AMOUNT, FEE, HEAD) MAKE_TX_FEE_MIX(VEC_EVENTS, TX_NAME, FROM, TO, AMOUNT, FEE, 0, HEAD)
2022-05-26 17:01:28 +02:00
# define MAKE_TX_MIX_LIST_EXTRA_MIX_ATTR(VEC_EVENTS, SET_NAME, FROM, TO, AMOUNT, NMIX, HEAD, MIX_ATTR, EXTRA, ATTACH) \
2018-12-27 18:50:45 +03:00
{ \
2022-10-28 01:07:45 +02:00
PRINT_EVENT_N_TEXT ( VEC_EVENTS , " transaction list " < < # SET_NAME ) ; \
2018-12-27 18:50:45 +03:00
currency : : transaction t ; \
2022-05-26 17:01:28 +02:00
bool r = construct_tx_to_key ( generator . get_hardforks ( ) , VEC_EVENTS , t , HEAD , FROM , TO , AMOUNT , TESTS_DEFAULT_FEE , NMIX , generator . last_tx_generated_secret_key , MIX_ATTR , EXTRA , ATTACH ) ; \
2018-12-27 18:50:45 +03:00
if ( ! r ) { LOG_PRINT_YELLOW ( " ERROR in tx @ EVENT # " < < VEC_EVENTS . size ( ) , LOG_LEVEL_0 ) ; } \
CHECK_AND_ASSERT_THROW_MES ( r , " failed to construct transaction " ) ; \
SET_NAME . push_back ( t ) ; \
VEC_EVENTS . push_back ( t ) ; \
}
# define MAKE_TX_MIX_LIST_MIX_ATTR(VEC_EVENTS, SET_NAME, FROM, TO, AMOUNT, NMIX, HEAD, MIX_ATTR, ATTACH) \
MAKE_TX_MIX_LIST_EXTRA_MIX_ATTR ( VEC_EVENTS , SET_NAME , FROM , TO , AMOUNT , NMIX , HEAD , MIX_ATTR , std : : vector < currency : : extra_v > ( ) , ATTACH )
# define MAKE_TX_MIX_LIST(VEC_EVENTS, SET_NAME, FROM, TO, AMOUNT, NMIX, HEAD, ATTACH) MAKE_TX_MIX_LIST_MIX_ATTR(VEC_EVENTS, SET_NAME, FROM, TO, AMOUNT, NMIX, HEAD, CURRENCY_TO_KEY_OUT_RELAXED, ATTACH)
# define MAKE_TX_LIST(VEC_EVENTS, SET_NAME, FROM, TO, AMOUNT, HEAD) MAKE_TX_MIX_LIST(VEC_EVENTS, SET_NAME, FROM, TO, AMOUNT, 0, HEAD, std::vector<currency::attachment_v>())
# define MAKE_TX_LIST_ATTACH(VEC_EVENTS, SET_NAME, FROM, TO, AMOUNT, HEAD, ATTACH) MAKE_TX_MIX_LIST(VEC_EVENTS, SET_NAME, FROM, TO, AMOUNT, 0, HEAD, ATTACH)
# define MAKE_TX_LIST_MIX_ATTR(VEC_EVENTS, SET_NAME, FROM, TO, AMOUNT, HEAD, MIX_ATTR) MAKE_TX_MIX_LIST_MIX_ATTR(VEC_EVENTS, SET_NAME, FROM, TO, AMOUNT, 0, HEAD, MIX_ATTR, std::vector<currency::attachment_v>())
# define MAKE_TX_LIST_START_MIX_ATTR(VEC_EVENTS, SET_NAME, FROM, TO, AMOUNT, HEAD, MIX_ATTR, ATTACHS) \
std : : list < currency : : transaction > SET_NAME ; \
2022-05-26 17:01:28 +02:00
MAKE_TX_MIX_LIST_MIX_ATTR ( VEC_EVENTS , SET_NAME , FROM , TO , AMOUNT , 0 , HEAD , MIX_ATTR , ATTACHS )
2018-12-27 18:50:45 +03:00
# define MAKE_TX_LIST_START(VEC_EVENTS, SET_NAME, FROM, TO, AMOUNT, HEAD) MAKE_TX_LIST_START_MIX_ATTR(VEC_EVENTS, SET_NAME, FROM, TO, AMOUNT, HEAD, CURRENCY_TO_KEY_OUT_RELAXED, std::vector<currency::attachment_v>())
# define MAKE_TX_LIST_START_WITH_ATTACHS(VEC_EVENTS, SET_NAME, FROM, TO, AMOUNT, HEAD, ATTACHS) MAKE_TX_LIST_START_MIX_ATTR(VEC_EVENTS, SET_NAME, FROM, TO, AMOUNT, HEAD, CURRENCY_TO_KEY_OUT_RELAXED, ATTACHS)
2022-05-26 17:01:28 +02:00
# define MAKE_TX_ATTACH_FEE(EVENTS, TX_VAR, FROM, TO, AMOUNT, FEE, HEAD, ATTACH) \
PRINT_EVENT_N ( EVENTS ) ; \
currency : : transaction TX_VAR = AUTO_VAL_INIT ( TX_VAR ) ; \
CHECK_AND_ASSERT_MES ( construct_tx_to_key ( generator . get_hardforks ( ) , EVENTS , TX_VAR , HEAD , FROM , TO , AMOUNT , FEE , 0 , generator . last_tx_generated_secret_key , CURRENCY_TO_KEY_OUT_RELAXED , empty_extra , ATTACH ) , false , " construct_tx_to_key failed " ) ; \
2018-12-27 18:50:45 +03:00
EVENTS . push_back ( TX_VAR )
# define MAKE_TX_ATTACH(EVENTS, TX_VAR, FROM, TO, AMOUNT, HEAD, ATTACH) MAKE_TX_ATTACH_FEE(EVENTS, TX_VAR, FROM, TO, AMOUNT, TESTS_DEFAULT_FEE, HEAD, ATTACH)
2019-09-05 16:15:21 +03:00
# define MAKE_MINER_TX_AND_KEY_MANUALLY(TX, PREV_BLOCK, P_KEYPAIR) \
transaction TX ; \
if ( ! construct_miner_tx_manually ( get_block_height ( PREV_BLOCK ) + 1 , generator . get_already_generated_coins ( PREV_BLOCK ) , \
2020-04-23 14:56:03 +03:00
miner_account . get_keys ( ) . account_address , TX , 0 , P_KEYPAIR ) ) \
2018-12-27 18:50:45 +03:00
return false ;
2019-09-05 16:15:21 +03:00
# define MAKE_MINER_TX_MANUALLY(TX, PREV_BLOCK) MAKE_MINER_TX_AND_KEY_MANUALLY(TX, PREV_BLOCK, nullptr)
2018-12-27 18:50:45 +03:00
# define SET_EVENT_VISITOR_SETT(VEC_EVENTS, SETT, VAL) VEC_EVENTS.push_back(event_visitor_settings(SETT, VAL));
# define QUOTEME(x) #x
# define CHECK_TEST_CONDITION(cond) CHECK_AND_FORCE_ASSERT_MES(cond, false, "failed: \"" << QUOTEME(cond) << "\"")
# define CHECK_EQ(v1, v2) CHECK_AND_FORCE_ASSERT_MES(v1 == v2, false, "failed: \"" << QUOTEME(v1) << " == " << QUOTEME(v2) << "\", " << v1 << " != " << v2)
# define CHECK_NOT_EQ(v1, v2) CHECK_AND_FORCE_ASSERT_MES(!(v1 == v2), false, "failed: \"" << QUOTEME(v1) << " != " << QUOTEME(v2) << "\", " << v1 << " == " << v2)
# define CHECK_V_EQ_EXPECTED_AND_ASSERT(value, expected) CHECK_AND_ASSERT_MES((value) == (expected), false, QUOTEME(value) << " has wrong value: " << value << ", expected: " << expected)
// Adjust gentime and playtime "time" at once
2022-05-26 17:01:28 +02:00
# define ADJUST_TEST_CORE_TIME(desired_time) \
2022-10-28 01:07:45 +02:00
PRINT_EVENT_N_TEXT ( events , " ADJUST_TEST_CORE_TIME( " < < desired_time < < " ) " ) ; \
2022-05-26 17:01:28 +02:00
test_core_time : : adjust ( desired_time ) ; \
2018-12-27 18:50:45 +03:00
events . push_back ( event_core_time ( desired_time ) )
2022-10-27 23:58:52 +02:00
# define ADD_CUSTOM_EVENT_CODE(VEC_EVENTS, CODE) PRINT_EVENT_N_TEXT(VEC_EVENTS, #CODE); CODE
# define ADD_CUSTOM_EVENT(VEC_EVENTS, EVENT_OBJ) PRINT_EVENT_N_TEXT(VEC_EVENTS, #EVENT_OBJ); VEC_EVENTS.push_back(EVENT_OBJ)
2023-04-30 00:43:49 +02:00
# define SET_HARDFORKS_TO_OLD_TESTS() \
core_hardforks_config hardforks_update = AUTO_VAL_INIT ( hardforks_update ) ; \
hardforks_update . hardforks = get_default_core_runtime_config ( ) . hard_forks . m_height_the_hardfork_n_active_after ; \
hardforks_update . hardforks [ 1 ] = 1440 ; \
hardforks_update . hardforks [ 2 ] = 1800 ; \
hardforks_update . hardforks [ 3 ] = 1801 ; \
currency : : hard_forks_descriptor hardforks_desc = AUTO_VAL_INIT ( hardforks_desc ) ; \
hardforks_desc . m_height_the_hardfork_n_active_after = hardforks_update . hardforks ; \
generator . set_hardforks ( hardforks_desc ) ; \
m_hardforks . m_height_the_hardfork_n_active_after = hardforks_desc . m_height_the_hardfork_n_active_after ; \
events . push_back ( hardforks_update ) ;
2018-12-27 18:50:45 +03:00
// --- gentime wallet helpers -----------------------------------------------------------------------
# define CREATE_TEST_WALLET(WLT_VAR, ACCOUNT, GENESIS_BLOCK) \
std : : shared_ptr < tools : : wallet2 > WLT_VAR ; \
generator . init_test_wallet ( ACCOUNT , get_block_hash ( GENESIS_BLOCK ) , WLT_VAR )
# define REFRESH_TEST_WALLET_AT_GEN_TIME(EVENTS_VEC, WLT_WAR, TOP_BLOCK, EXPECTED_BLOCKS_TO_BE_FETCH) \
{ \
bool r = generator . refresh_test_wallet ( EVENTS_VEC , WLT_WAR . get ( ) , get_block_hash ( TOP_BLOCK ) , EXPECTED_BLOCKS_TO_BE_FETCH ) ; \
CHECK_AND_ASSERT_MES ( r , false , " refresh_test_wallet failed " ) ; \
}
2022-05-26 17:01:28 +02:00
# define MAKE_TEST_WALLET_TX(EVENTS_VEC, TX_VAR, WLT_WAR, MONEY, DEST_ACC) \
PRINT_EVENT_N ( EVENTS_VEC ) ; \
transaction TX_VAR = AUTO_VAL_INIT ( TX_VAR ) ; \
{ \
2018-12-27 18:50:45 +03:00
std : : vector < tx_destination_entry > destinations ( 1 , tx_destination_entry ( MONEY , DEST_ACC . get_public_address ( ) ) ) ; \
2019-04-25 23:37:43 +02:00
WLT_WAR - > transfer ( destinations , 0 , 0 , TESTS_DEFAULT_FEE , std : : vector < extra_v > ( ) , std : : vector < attachment_v > ( ) , TX_VAR ) ; \
2022-05-26 17:01:28 +02:00
} \
2018-12-27 18:50:45 +03:00
EVENTS_VEC . push_back ( TX_VAR )
# define MAKE_TEST_WALLET_TX_ATTACH(EVENTS_VEC, TX_VAR, WLT_WAR, MONEY, DEST_ACC, ATTACH) \
2022-05-26 17:01:28 +02:00
PRINT_EVENT_N ( EVENTS_VEC ) ; \
transaction TX_VAR = AUTO_VAL_INIT ( TX_VAR ) ; \
{ \
2018-12-27 18:50:45 +03:00
std : : vector < tx_destination_entry > destinations ( 1 , tx_destination_entry ( MONEY , DEST_ACC . get_public_address ( ) ) ) ; \
2019-04-25 23:37:43 +02:00
WLT_WAR - > transfer ( destinations , 0 , 0 , TESTS_DEFAULT_FEE , std : : vector < extra_v > ( ) , ATTACH , TX_VAR ) ; \
2022-05-26 17:01:28 +02:00
} \
2018-12-27 18:50:45 +03:00
EVENTS_VEC . push_back ( TX_VAR )
# define MAKE_TEST_WALLET_TX_EXTRA(EVENTS_VEC, TX_VAR, WLT_WAR, MONEY, DEST_ACC, EXTRA) \
2022-05-26 17:01:28 +02:00
PRINT_EVENT_N ( EVENTS_VEC ) ; \
transaction TX_VAR = AUTO_VAL_INIT ( TX_VAR ) ; \
{ \
2018-12-27 18:50:45 +03:00
std : : vector < tx_destination_entry > destinations ( 1 , tx_destination_entry ( MONEY , DEST_ACC . get_public_address ( ) ) ) ; \
2019-04-25 23:37:43 +02:00
WLT_WAR - > transfer ( destinations , 0 , 0 , TESTS_DEFAULT_FEE , EXTRA , std : : vector < attachment_v > ( ) , TX_VAR ) ; \
2022-05-26 17:01:28 +02:00
} \
2018-12-27 18:50:45 +03:00
EVENTS_VEC . push_back ( TX_VAR )
# define CHECK_TEST_WALLET_BALANCE_AT_GEN_TIME(WLT_WAR, TOTAL_BALANCE) \
if ( ! check_balance_via_wallet ( * WLT_WAR . get ( ) , # WLT_WAR , TOTAL_BALANCE ) ) \
return false
# define CHECK_TEST_WALLET_BALANCE_AT_GEN_TIME_FULL(WLT_WAR, TOTAL_BALANCE, MINED_BALANCE, UNLOCKED_BALANCE, AWAITING_IN_BALANCE, AWAITING_OUT_BALANCE) \
if ( ! check_balance_via_wallet ( * WLT_WAR . get ( ) , # WLT_WAR , TOTAL_BALANCE , MINED_BALANCE , UNLOCKED_BALANCE , AWAITING_IN_BALANCE , AWAITING_OUT_BALANCE ) ) \
return false
// --- end of gentime wallet helpers -----------------------------------------------------------------------
2020-05-18 17:20:23 +03:00
# include "chaingen_helpers.h"