aboutsummaryrefslogtreecommitdiff
path: root/tests/core_tests/chaingen.h
diff options
context:
space:
mode:
Diffstat (limited to 'tests/core_tests/chaingen.h')
-rw-r--r--tests/core_tests/chaingen.h461
1 files changed, 426 insertions, 35 deletions
diff --git a/tests/core_tests/chaingen.h b/tests/core_tests/chaingen.h
index 907b32bcd..0e67a7e65 100644
--- a/tests/core_tests/chaingen.h
+++ b/tests/core_tests/chaingen.h
@@ -37,8 +37,12 @@
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/program_options.hpp>
+#include <boost/optional.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/variant.hpp>
+#include <boost/serialization/optional.hpp>
+#include <boost/serialization/unordered_map.hpp>
+#include <boost/functional/hash.hpp>
#include "include_base_utils.h"
#include "common/boost_serialization_helper.h"
@@ -129,13 +133,32 @@ private:
}
};
+typedef std::vector<std::pair<uint8_t, uint64_t>> v_hardforks_t;
+struct event_replay_settings
+{
+ boost::optional<v_hardforks_t> hard_forks;
+
+ event_replay_settings() = default;
+
+private:
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int /*version*/)
+ {
+ ar & hard_forks;
+ }
+};
+
+
VARIANT_TAG(binary_archive, callback_entry, 0xcb);
VARIANT_TAG(binary_archive, cryptonote::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_replay_settings, 0xda);
-typedef boost::variant<cryptonote::block, cryptonote::transaction, std::vector<cryptonote::transaction>, cryptonote::account_base, callback_entry, serialized_block, serialized_transaction, event_visitor_settings> test_event_entry;
+typedef boost::variant<cryptonote::block, cryptonote::transaction, std::vector<cryptonote::transaction>, cryptonote::account_base, callback_entry, serialized_block, serialized_transaction, event_visitor_settings, event_replay_settings> test_event_entry;
typedef std::unordered_map<crypto::hash, const cryptonote::transaction*> map_hash2tx_t;
class test_chain_unit_base
@@ -173,6 +196,17 @@ public:
crypto::hash prev_id;
uint64_t already_generated_coins;
size_t block_weight;
+
+ private:
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int /*version*/)
+ {
+ ar & prev_id;
+ ar & already_generated_coins;
+ ar & block_weight;
+ }
};
enum block_fields
@@ -189,6 +223,8 @@ public:
bf_hf_version= 1 << 8
};
+ test_generator() {}
+ test_generator(const test_generator &other): m_blocks_info(other.m_blocks_info) {}
void get_block_chain(std::vector<block_info>& blockchain, const crypto::hash& head, size_t n) const;
void get_last_n_block_weights(std::vector<size_t>& block_weights, const crypto::hash& head, size_t n) const;
uint64_t get_already_generated_coins(const crypto::hash& blk_id) const;
@@ -198,10 +234,12 @@ public:
uint8_t hf_version = 1);
bool construct_block(cryptonote::block& blk, uint64_t height, const crypto::hash& prev_id,
const cryptonote::account_base& miner_acc, uint64_t timestamp, uint64_t already_generated_coins,
- std::vector<size_t>& block_weights, const std::list<cryptonote::transaction>& tx_list);
+ std::vector<size_t>& block_weights, const std::list<cryptonote::transaction>& tx_list,
+ const boost::optional<uint8_t>& hf_ver = boost::none);
bool construct_block(cryptonote::block& blk, const cryptonote::account_base& miner_acc, uint64_t timestamp);
bool construct_block(cryptonote::block& blk, const cryptonote::block& blk_prev, const cryptonote::account_base& miner_acc,
- const std::list<cryptonote::transaction>& tx_list = std::list<cryptonote::transaction>());
+ const std::list<cryptonote::transaction>& tx_list = std::list<cryptonote::transaction>(),
+ const boost::optional<uint8_t>& hf_ver = boost::none);
bool construct_block_manually(cryptonote::block& blk, const cryptonote::block& prev_block,
const cryptonote::account_base& miner_acc, int actual_params = bf_none, uint8_t major_ver = 0,
@@ -214,30 +252,241 @@ public:
private:
std::unordered_map<crypto::hash, block_info> m_blocks_info;
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int /*version*/)
+ {
+ ar & m_blocks_info;
+ }
};
-inline cryptonote::difficulty_type get_test_difficulty() {return 1;}
+template<typename T>
+std::string dump_keys(T * buff32)
+{
+ std::ostringstream ss;
+ char buff[10];
+
+ ss << "[";
+ for(int i = 0; i < 32; i++)
+ {
+ snprintf(buff, 10, "0x%02x", ((uint8_t)buff32[i] & 0xff));
+ ss << buff;
+ if (i < 31)
+ ss << ",";
+ }
+ ss << "]";
+ return ss.str();
+}
+
+struct output_index {
+ const cryptonote::txout_target_v out;
+ uint64_t amount;
+ size_t blk_height; // block height
+ size_t tx_no; // index of transaction in block
+ size_t out_no; // index of out in transaction
+ size_t idx;
+ uint64_t unlock_time;
+ bool is_coin_base;
+ bool spent;
+ bool rct;
+ rct::key comm;
+ const cryptonote::block *p_blk;
+ const cryptonote::transaction *p_tx;
+
+ output_index(const cryptonote::txout_target_v &_out, uint64_t _a, size_t _h, size_t tno, size_t ono, const cryptonote::block *_pb, const cryptonote::transaction *_pt)
+ : out(_out), amount(_a), blk_height(_h), tx_no(tno), out_no(ono), idx(0), unlock_time(0),
+ is_coin_base(false), spent(false), rct(false), p_blk(_pb), p_tx(_pt)
+ {
+
+ }
+
+ output_index(const output_index &other)
+ : out(other.out), amount(other.amount), blk_height(other.blk_height), tx_no(other.tx_no), rct(other.rct),
+ out_no(other.out_no), idx(other.idx), unlock_time(other.unlock_time), is_coin_base(other.is_coin_base),
+ spent(other.spent), comm(other.comm), p_blk(other.p_blk), p_tx(other.p_tx) { }
+
+ void set_rct(bool arct) {
+ rct = arct;
+ if (rct && p_tx->rct_signatures.outPk.size() > out_no)
+ comm = p_tx->rct_signatures.outPk[out_no].mask;
+ else
+ comm = rct::commit(amount, rct::identity());
+ }
+
+ rct::key commitment() const {
+ return comm;
+ }
+
+ const std::string toString() const {
+ std::stringstream ss;
+
+ ss << "output_index{blk_height=" << blk_height
+ << " tx_no=" << tx_no
+ << " out_no=" << out_no
+ << " amount=" << amount
+ << " idx=" << idx
+ << " unlock_time=" << unlock_time
+ << " spent=" << spent
+ << " is_coin_base=" << is_coin_base
+ << " rct=" << rct
+ << " comm=" << dump_keys(comm.bytes)
+ << "}";
+
+ return ss.str();
+ }
+
+ output_index& operator=(const output_index& other)
+ {
+ new(this) output_index(other);
+ return *this;
+ }
+};
+
+typedef std::tuple<uint64_t, crypto::public_key, rct::key> get_outs_entry;
+typedef std::pair<crypto::hash, size_t> output_hasher;
+typedef boost::hash<output_hasher> output_hasher_hasher;
+typedef std::map<uint64_t, std::vector<size_t> > map_output_t;
+typedef std::map<uint64_t, std::vector<output_index> > map_output_idx_t;
+typedef std::unordered_map<crypto::hash, cryptonote::block> map_block_t;
+typedef std::unordered_map<output_hasher, output_index, output_hasher_hasher> map_txid_output_t;
+typedef std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddresses_t;
+typedef std::pair<uint64_t, size_t> outloc_t;
+
+typedef boost::variant<cryptonote::account_public_address, cryptonote::account_keys, cryptonote::account_base, cryptonote::tx_destination_entry> var_addr_t;
+typedef struct {
+ const var_addr_t addr;
+ bool is_subaddr;
+ uint64_t amount;
+} dest_wrapper_t;
+
+// Daemon functionality
+class block_tracker
+{
+public:
+ map_output_idx_t m_outs;
+ map_txid_output_t m_map_outs; // mapping (txid, out) -> output_index
+ map_block_t m_blocks;
+
+ block_tracker() = default;
+ block_tracker(const block_tracker &bt): m_outs(bt.m_outs), m_map_outs(bt.m_map_outs), m_blocks(bt.m_blocks) {};
+ map_txid_output_t::iterator find_out(const crypto::hash &txid, size_t out);
+ map_txid_output_t::iterator find_out(const output_hasher &id);
+ void process(const std::vector<cryptonote::block>& blockchain, const map_hash2tx_t& mtx);
+ void process(const std::vector<const cryptonote::block*>& blockchain, const map_hash2tx_t& mtx);
+ void process(const cryptonote::block* blk, const cryptonote::transaction * tx, size_t i);
+ void global_indices(const cryptonote::transaction *tx, std::vector<uint64_t> &indices);
+ void get_fake_outs(size_t num_outs, uint64_t amount, uint64_t global_index, uint64_t cur_height, std::vector<get_outs_entry> &outs);
+
+ std::string dump_data();
+ void dump_data(const std::string & fname);
+
+private:
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int /*version*/)
+ {
+ ar & m_outs;
+ ar & m_map_outs;
+ ar & m_blocks;
+ }
+};
+
+std::string dump_data(const cryptonote::transaction &tx);
+cryptonote::account_public_address get_address(const var_addr_t& inp);
+cryptonote::account_public_address get_address(const cryptonote::account_public_address& inp);
+cryptonote::account_public_address get_address(const cryptonote::account_keys& inp);
+cryptonote::account_public_address get_address(const cryptonote::account_base& inp);
+cryptonote::account_public_address get_address(const cryptonote::tx_destination_entry& inp);
+
+inline cryptonote::difficulty_type get_test_difficulty(const boost::optional<uint8_t>& hf_ver=boost::none) {return !hf_ver || hf_ver.get() <= 1 ? 1 : 2;}
+inline uint64_t current_difficulty_window(const boost::optional<uint8_t>& hf_ver=boost::none){ return !hf_ver || hf_ver.get() <= 1 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET_V2; }
void fill_nonce(cryptonote::block& blk, const cryptonote::difficulty_type& diffic, uint64_t height);
+cryptonote::tx_destination_entry build_dst(const var_addr_t& to, bool is_subaddr=false, uint64_t amount=0);
+std::vector<cryptonote::tx_destination_entry> build_dsts(const var_addr_t& to1, bool sub1=false, uint64_t am1=0);
+std::vector<cryptonote::tx_destination_entry> build_dsts(std::initializer_list<dest_wrapper_t> inps);
+uint64_t sum_amount(const std::vector<cryptonote::tx_destination_entry>& destinations);
+uint64_t sum_amount(const std::vector<cryptonote::tx_source_entry>& sources);
+
bool construct_miner_tx_manually(size_t height, uint64_t already_generated_coins,
const cryptonote::account_public_address& miner_address, cryptonote::transaction& tx,
- uint64_t fee, cryptonote::keypair* p_txkey = 0);
+ uint64_t fee, cryptonote::keypair* p_txkey = nullptr);
+
bool construct_tx_to_key(const std::vector<test_event_entry>& events, cryptonote::transaction& tx,
- const cryptonote::block& blk_head, const cryptonote::account_base& from, const cryptonote::account_base& to,
- uint64_t amount, uint64_t fee, size_t nmix);
+ const cryptonote::block& blk_head, const cryptonote::account_base& from, const var_addr_t& to, uint64_t amount,
+ uint64_t fee, size_t nmix, bool rct=false, rct::RangeProofType range_proof_type=rct::RangeProofBorromean, int bp_version = 0);
+
+bool construct_tx_to_key(const std::vector<test_event_entry>& events, cryptonote::transaction& tx, const cryptonote::block& blk_head,
+ const cryptonote::account_base& from, std::vector<cryptonote::tx_destination_entry> destinations,
+ uint64_t fee, size_t nmix, bool rct=false, rct::RangeProofType range_proof_type=rct::RangeProofBorromean, int bp_version = 0);
+
+bool construct_tx_to_key(cryptonote::transaction& tx, const cryptonote::account_base& from, const var_addr_t& to, uint64_t amount,
+ std::vector<cryptonote::tx_source_entry> &sources,
+ uint64_t fee, bool rct=false, rct::RangeProofType range_proof_type=rct::RangeProofBorromean, int bp_version = 0);
+
+bool construct_tx_to_key(cryptonote::transaction& tx, const cryptonote::account_base& from, const std::vector<cryptonote::tx_destination_entry>& destinations,
+ std::vector<cryptonote::tx_source_entry> &sources,
+ uint64_t fee, bool rct, rct::RangeProofType range_proof_type, int bp_version = 0);
+
cryptonote::transaction construct_tx_with_fee(std::vector<test_event_entry>& events, const cryptonote::block& blk_head,
- const cryptonote::account_base& acc_from, const cryptonote::account_base& acc_to,
+ const cryptonote::account_base& acc_from, const var_addr_t& to,
uint64_t amount, uint64_t fee);
+bool construct_tx_rct(const cryptonote::account_keys& sender_account_keys,
+ std::vector<cryptonote::tx_source_entry>& sources,
+ const std::vector<cryptonote::tx_destination_entry>& destinations,
+ const boost::optional<cryptonote::account_public_address>& change_addr,
+ std::vector<uint8_t> extra, cryptonote::transaction& tx, uint64_t unlock_time,
+ bool rct=false, rct::RangeProofType range_proof_type=rct::RangeProofBorromean, int bp_version = 0);
+
+
+uint64_t num_blocks(const std::vector<test_event_entry>& events);
+cryptonote::block get_head_block(const std::vector<test_event_entry>& events);
+
void get_confirmed_txs(const std::vector<cryptonote::block>& blockchain, const map_hash2tx_t& mtx, map_hash2tx_t& confirmed_txs);
+bool trim_block_chain(std::vector<cryptonote::block>& blockchain, const crypto::hash& tail);
+bool trim_block_chain(std::vector<const cryptonote::block*>& blockchain, const crypto::hash& tail);
bool find_block_chain(const std::vector<test_event_entry>& events, std::vector<cryptonote::block>& blockchain, map_hash2tx_t& mtx, const crypto::hash& head);
+bool find_block_chain(const std::vector<test_event_entry>& events, std::vector<const cryptonote::block*>& blockchain, map_hash2tx_t& mtx, const crypto::hash& head);
+
+void fill_tx_destinations(const var_addr_t& from, const cryptonote::account_public_address& to,
+ uint64_t amount, uint64_t fee,
+ const std::vector<cryptonote::tx_source_entry> &sources,
+ std::vector<cryptonote::tx_destination_entry>& destinations, bool always_change=false);
+
+void fill_tx_destinations(const var_addr_t& from, const std::vector<cryptonote::tx_destination_entry>& dests,
+ uint64_t fee,
+ const std::vector<cryptonote::tx_source_entry> &sources,
+ std::vector<cryptonote::tx_destination_entry>& destinations,
+ bool always_change);
+
+void fill_tx_destinations(const var_addr_t& from, const cryptonote::account_public_address& to,
+ uint64_t amount, uint64_t fee,
+ const std::vector<cryptonote::tx_source_entry> &sources,
+ std::vector<cryptonote::tx_destination_entry>& destinations,
+ std::vector<cryptonote::tx_destination_entry>& destinations_pure,
+ bool always_change=false);
+
+
+void fill_tx_sources_and_destinations(const std::vector<test_event_entry>& events, const cryptonote::block& blk_head,
+ const cryptonote::account_base& from, const cryptonote::account_public_address& to,
+ uint64_t amount, uint64_t fee, size_t nmix,
+ std::vector<cryptonote::tx_source_entry>& sources,
+ std::vector<cryptonote::tx_destination_entry>& destinations);
+
void fill_tx_sources_and_destinations(const std::vector<test_event_entry>& events, const cryptonote::block& blk_head,
const cryptonote::account_base& from, const cryptonote::account_base& to,
uint64_t amount, uint64_t fee, size_t nmix,
std::vector<cryptonote::tx_source_entry>& sources,
std::vector<cryptonote::tx_destination_entry>& destinations);
+
uint64_t get_balance(const cryptonote::account_base& addr, const std::vector<cryptonote::block>& blockchain, const map_hash2tx_t& mtx);
+bool extract_hard_forks(const std::vector<test_event_entry>& events, v_hardforks_t& hard_forks);
+
//--------------------------------------------------------------------------
template<class t_test_class>
auto do_check_tx_verification_context(const cryptonote::tx_verification_context& tvc, bool tx_added, size_t event_index, const cryptonote::transaction& tx, t_test_class& validator, int)
@@ -338,6 +587,12 @@ public:
m_ev_index = ev_index;
}
+ bool operator()(const event_replay_settings& settings)
+ {
+ log_event("event_replay_settings");
+ return true;
+ }
+
bool operator()(const event_visitor_settings& settings)
{
log_event("event_visitor_settings");
@@ -461,12 +716,20 @@ private:
template<class t_test_class>
inline bool replay_events_through_core(cryptonote::core& cr, const std::vector<test_event_entry>& events, t_test_class& validator)
{
+ return replay_events_through_core_plain(cr, events, validator, true);
+}
+//--------------------------------------------------------------------------
+template<class t_test_class>
+inline bool replay_events_through_core_plain(cryptonote::core& cr, const std::vector<test_event_entry>& events, t_test_class& validator, bool reinit=true)
+{
TRY_ENTRY();
//init core here
-
- CHECK_AND_ASSERT_MES(typeid(cryptonote::block) == events[0].type(), false, "First event must be genesis block creation");
- cr.set_genesis_block(boost::get<cryptonote::block>(events[0]));
+ if (reinit) {
+ CHECK_AND_ASSERT_MES(typeid(cryptonote::block) == events[0].type(), false,
+ "First event must be genesis block creation");
+ cr.set_genesis_block(boost::get<cryptonote::block>(events[0]));
+ }
bool r = true;
push_core_event_visitor<t_test_class> visitor(cr, events, validator);
@@ -489,10 +752,9 @@ struct get_test_options {
};
get_test_options():hard_forks{std::make_pair((uint8_t)1, (uint64_t)0), std::make_pair((uint8_t)0, (uint64_t)0)}{}
};
-
//--------------------------------------------------------------------------
template<class t_test_class>
-inline bool do_replay_events(std::vector<test_event_entry>& events)
+inline bool do_replay_events_get_core(std::vector<test_event_entry>& events, cryptonote::core **core)
{
boost::program_options::options_description desc("Allowed options");
cryptonote::core::init_options(desc);
@@ -506,12 +768,24 @@ inline bool do_replay_events(std::vector<test_event_entry>& events)
if (!r)
return false;
- cryptonote::cryptonote_protocol_stub pr; //TODO: stub only for this kind of test, make real validation of relayed objects
- cryptonote::core c(&pr);
+ *core = new cryptonote::core(nullptr);
+ auto & c = **core;
+
// FIXME: make sure that vm has arg_testnet_on set to true or false if
// this test needs for it to be so.
get_test_options<t_test_class> gto;
- if (!c.init(vm, &gto.test_options))
+
+ // Hardforks can be specified in events.
+ v_hardforks_t hardforks;
+ cryptonote::test_options test_options_tmp{};
+ const cryptonote::test_options * test_options_ = &gto.test_options;
+ if (extract_hard_forks(events, hardforks)){
+ hardforks.push_back(std::make_pair((uint8_t)0, (uint64_t)0)); // terminator
+ test_options_tmp.hard_forks = hardforks.data();
+ test_options_ = &test_options_tmp;
+ }
+
+ if (!c.init(vm, test_options_))
{
MERROR("Failed to init core");
return false;
@@ -529,7 +803,31 @@ inline bool do_replay_events(std::vector<test_event_entry>& events)
t_test_class validator;
bool ret = replay_events_through_core<t_test_class>(c, events, validator);
- c.deinit();
+// c.deinit();
+ return ret;
+}
+//--------------------------------------------------------------------------
+template<class t_test_class>
+inline bool replay_events_through_core_validate(std::vector<test_event_entry>& events, cryptonote::core & c)
+{
+ std::vector<crypto::hash> pool_txs;
+ if (!c.get_pool_transaction_hashes(pool_txs))
+ {
+ MERROR("Failed to flush txpool");
+ return false;
+ }
+ c.get_blockchain_storage().flush_txes_from_pool(pool_txs);
+
+ t_test_class validator;
+ return replay_events_through_core_plain<t_test_class>(c, events, validator, false);
+}
+//--------------------------------------------------------------------------
+template<class t_test_class>
+inline bool do_replay_events(std::vector<test_event_entry>& events)
+{
+ cryptonote::core * core;
+ bool ret = do_replay_events_get_core<t_test_class>(events, &core);
+ core->deinit();
return ret;
}
//--------------------------------------------------------------------------
@@ -546,6 +844,12 @@ inline bool do_replay_file(const std::string& filename)
}
//--------------------------------------------------------------------------
+#define DEFAULT_HARDFORKS(HARDFORKS) do { \
+ HARDFORKS.push_back(std::make_pair((uint8_t)1, (uint64_t)0)); \
+} while(0)
+
+#define ADD_HARDFORK(HARDFORKS, FORK, HEIGHT) HARDFORKS.push_back(std::make_pair((uint8_t)FORK, (uint64_t)HEIGHT))
+
#define GENERATE_ACCOUNT(account) \
cryptonote::account_base account; \
account.generate();
@@ -589,6 +893,11 @@ inline bool do_replay_file(const std::string& filename)
generator.construct_block(BLK_NAME, PREV_BLOCK, MINER_ACC); \
VEC_EVENTS.push_back(BLK_NAME);
+#define MAKE_NEXT_BLOCK_HF(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC, HF) \
+ cryptonote::block BLK_NAME; \
+ generator.construct_block(BLK_NAME, PREV_BLOCK, MINER_ACC, std::list<cryptonote::transaction>(), HF); \
+ VEC_EVENTS.push_back(BLK_NAME);
+
#define MAKE_NEXT_BLOCK_TX1(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC, TX1) \
cryptonote::block BLK_NAME; \
{ \
@@ -598,46 +907,91 @@ inline bool do_replay_file(const std::string& filename)
} \
VEC_EVENTS.push_back(BLK_NAME);
+#define MAKE_NEXT_BLOCK_TX1_HF(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC, TX1, HF) \
+ cryptonote::block BLK_NAME; \
+ { \
+ std::list<cryptonote::transaction> tx_list; \
+ tx_list.push_back(TX1); \
+ generator.construct_block(BLK_NAME, PREV_BLOCK, MINER_ACC, tx_list, HF); \
+ } \
+ VEC_EVENTS.push_back(BLK_NAME);
+
#define MAKE_NEXT_BLOCK_TX_LIST(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC, TXLIST) \
cryptonote::block BLK_NAME; \
generator.construct_block(BLK_NAME, PREV_BLOCK, MINER_ACC, TXLIST); \
VEC_EVENTS.push_back(BLK_NAME);
-#define REWIND_BLOCKS_N(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC, COUNT) \
+#define MAKE_NEXT_BLOCK_TX_LIST_HF(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC, TXLIST, HF) \
cryptonote::block BLK_NAME; \
+ generator.construct_block(BLK_NAME, PREV_BLOCK, MINER_ACC, TXLIST, HF); \
+ VEC_EVENTS.push_back(BLK_NAME);
+
+#define REWIND_BLOCKS_N_HF(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC, COUNT, HF) \
+ cryptonote::block BLK_NAME; \
{ \
- cryptonote::block blk_last = PREV_BLOCK; \
+ cryptonote::block blk_last = PREV_BLOCK; \
for (size_t i = 0; i < COUNT; ++i) \
{ \
- MAKE_NEXT_BLOCK(VEC_EVENTS, blk, blk_last, MINER_ACC); \
+ MAKE_NEXT_BLOCK_HF(VEC_EVENTS, blk, blk_last, MINER_ACC, HF); \
blk_last = blk; \
} \
BLK_NAME = blk_last; \
}
+#define REWIND_BLOCKS_N(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC, COUNT) REWIND_BLOCKS_N_HF(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC, COUNT, boost::none)
#define REWIND_BLOCKS(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC) REWIND_BLOCKS_N(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC, CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW)
+#define REWIND_BLOCKS_HF(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC, HF) REWIND_BLOCKS_N_HF(VEC_EVENTS, BLK_NAME, PREV_BLOCK, MINER_ACC, CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, HF)
#define MAKE_TX_MIX(VEC_EVENTS, TX_NAME, FROM, TO, AMOUNT, NMIX, HEAD) \
cryptonote::transaction TX_NAME; \
construct_tx_to_key(VEC_EVENTS, TX_NAME, HEAD, FROM, TO, AMOUNT, TESTS_DEFAULT_FEE, NMIX); \
VEC_EVENTS.push_back(TX_NAME);
+#define MAKE_TX_MIX_RCT(VEC_EVENTS, TX_NAME, FROM, TO, AMOUNT, NMIX, HEAD) \
+ cryptonote::transaction TX_NAME; \
+ construct_tx_to_key(VEC_EVENTS, TX_NAME, HEAD, FROM, TO, AMOUNT, TESTS_DEFAULT_FEE, NMIX, true, rct::RangeProofPaddedBulletproof); \
+ VEC_EVENTS.push_back(TX_NAME);
+
#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_MIX_LIST(VEC_EVENTS, SET_NAME, FROM, TO, AMOUNT, NMIX, HEAD) \
{ \
- cryptonote::transaction t; \
+ cryptonote::transaction t; \
construct_tx_to_key(VEC_EVENTS, t, HEAD, FROM, TO, AMOUNT, TESTS_DEFAULT_FEE, NMIX); \
SET_NAME.push_back(t); \
VEC_EVENTS.push_back(t); \
}
+#define MAKE_TX_MIX_LIST_RCT(VEC_EVENTS, SET_NAME, FROM, TO, AMOUNT, NMIX, HEAD) \
+ MAKE_TX_MIX_LIST_RCT_EX(VEC_EVENTS, SET_NAME, FROM, TO, AMOUNT, NMIX, HEAD, rct::RangeProofPaddedBulletproof, 1)
+#define MAKE_TX_MIX_LIST_RCT_EX(VEC_EVENTS, SET_NAME, FROM, TO, AMOUNT, NMIX, HEAD, RCT_TYPE, BP_VER) \
+ { \
+ cryptonote::transaction t; \
+ construct_tx_to_key(VEC_EVENTS, t, HEAD, FROM, TO, AMOUNT, TESTS_DEFAULT_FEE, NMIX, true, RCT_TYPE, BP_VER); \
+ SET_NAME.push_back(t); \
+ VEC_EVENTS.push_back(t); \
+ }
+
+#define MAKE_TX_MIX_DEST_LIST_RCT(VEC_EVENTS, SET_NAME, FROM, TO, NMIX, HEAD) \
+ MAKE_TX_MIX_DEST_LIST_RCT_EX(VEC_EVENTS, SET_NAME, FROM, TO, NMIX, HEAD, rct::RangeProofPaddedBulletproof, 1)
+#define MAKE_TX_MIX_DEST_LIST_RCT_EX(VEC_EVENTS, SET_NAME, FROM, TO, NMIX, HEAD, RCT_TYPE, BP_VER) \
+ { \
+ cryptonote::transaction t; \
+ construct_tx_to_key(VEC_EVENTS, t, HEAD, FROM, TO, TESTS_DEFAULT_FEE, NMIX, true, RCT_TYPE, BP_VER); \
+ SET_NAME.push_back(t); \
+ VEC_EVENTS.push_back(t); \
+ }
+
#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)
#define MAKE_TX_LIST_START(VEC_EVENTS, SET_NAME, FROM, TO, AMOUNT, HEAD) \
std::list<cryptonote::transaction> SET_NAME; \
MAKE_TX_LIST(VEC_EVENTS, SET_NAME, FROM, TO, AMOUNT, HEAD);
+#define MAKE_TX_LIST_START_RCT(VEC_EVENTS, SET_NAME, FROM, TO, AMOUNT, NMIX, HEAD) \
+ std::list<cryptonote::transaction> SET_NAME; \
+ MAKE_TX_MIX_LIST_RCT(VEC_EVENTS, SET_NAME, FROM, TO, AMOUNT, NMIX, HEAD);
+
#define MAKE_MINER_TX_AND_KEY_MANUALLY(TX, BLK, KEY) \
transaction TX; \
if (!construct_miner_tx_manually(get_block_height(BLK) + 1, generator.get_already_generated_coins(BLK), \
@@ -668,19 +1022,7 @@ inline bool do_replay_file(const std::string& filename)
return 1; \
}
-#define GENERATE_AND_PLAY(genclass) \
- if (list_tests) \
- std::cout << #genclass << std::endl; \
- else if (filter.empty() || boost::regex_match(std::string(#genclass), match, boost::regex(filter))) \
- { \
- std::vector<test_event_entry> events; \
- ++tests_count; \
- bool generated = false; \
- try \
- { \
- genclass g; \
- generated = g.generate(events);; \
- } \
+#define CATCH_REPLAY(genclass) \
catch (const std::exception& ex) \
{ \
MERROR(#genclass << " generation failed: what=" << ex.what()); \
@@ -688,7 +1030,9 @@ inline bool do_replay_file(const std::string& filename)
catch (...) \
{ \
MERROR(#genclass << " generation failed: generic exception"); \
- } \
+ }
+
+#define REPLAY_CORE(genclass) \
if (generated && do_replay_events< genclass >(events)) \
{ \
MGINFO_GREEN("#TEST# Succeeded " << #genclass); \
@@ -697,7 +1041,54 @@ inline bool do_replay_file(const std::string& filename)
{ \
MERROR("#TEST# Failed " << #genclass); \
failed_tests.push_back(#genclass); \
+ }
+
+#define REPLAY_WITH_CORE(genclass, CORE) \
+ if (generated && replay_events_through_core_validate< genclass >(events, CORE)) \
+ { \
+ MGINFO_GREEN("#TEST# Succeeded " << #genclass); \
+ } \
+ else \
+ { \
+ MERROR("#TEST# Failed " << #genclass); \
+ failed_tests.push_back(#genclass); \
+ }
+
+#define CATCH_GENERATE_REPLAY(genclass) \
+ CATCH_REPLAY(genclass); \
+ REPLAY_CORE(genclass);
+
+#define CATCH_GENERATE_REPLAY_CORE(genclass, CORE) \
+ CATCH_REPLAY(genclass); \
+ REPLAY_WITH_CORE(genclass, CORE);
+
+#define GENERATE_AND_PLAY(genclass) \
+ if (list_tests) \
+ std::cout << #genclass << std::endl; \
+ else if (filter.empty() || boost::regex_match(std::string(#genclass), match, boost::regex(filter))) \
+ { \
+ std::vector<test_event_entry> events; \
+ ++tests_count; \
+ bool generated = false; \
+ try \
+ { \
+ genclass g; \
+ generated = g.generate(events); \
+ } \
+ CATCH_GENERATE_REPLAY(genclass); \
+ }
+
+#define GENERATE_AND_PLAY_INSTANCE(genclass, ins, CORE) \
+ if (filter.empty() || boost::regex_match(std::string(#genclass), match, boost::regex(filter))) \
+ { \
+ std::vector<test_event_entry> events; \
+ ++tests_count; \
+ bool generated = false; \
+ try \
+ { \
+ generated = ins.generate(events); \
} \
+ CATCH_GENERATE_REPLAY_CORE(genclass, CORE); \
}
#define CALL_TEST(test_name, function) \