Skip to content

Commit

Permalink
core_tests: added service node tests
Browse files Browse the repository at this point in the history
  • Loading branch information
msgmaxim committed Aug 28, 2018
1 parent 7d89507 commit 3dfb7e3
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 28 deletions.
4 changes: 2 additions & 2 deletions src/cryptonote_core/cryptonote_tx_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -812,14 +812,14 @@ namespace cryptonote
return r;
}
//---------------------------------------------------------------
bool construct_tx(const account_keys& sender_account_keys, std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::tx_destination_entry>& change_addr, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time)
bool construct_tx(const account_keys& sender_account_keys, std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::tx_destination_entry>& change_addr, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time, bool is_staking, bool per_output_unlock)
{
std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddresses;
subaddresses[sender_account_keys.m_account_address.m_spend_public_key] = {0,0};
crypto::secret_key tx_key;
std::vector<crypto::secret_key> additional_tx_keys;
std::vector<tx_destination_entry> destinations_copy = destinations;
return construct_tx_and_get_tx_key(sender_account_keys, subaddresses, sources, destinations_copy, change_addr, extra, tx, unlock_time, tx_key, additional_tx_keys, true, false, NULL);
return construct_tx_and_get_tx_key(sender_account_keys, subaddresses, sources, destinations_copy, change_addr, extra, tx, unlock_time, tx_key, additional_tx_keys, true, false, NULL, is_staking, per_output_unlock);
}
//---------------------------------------------------------------
bool generate_genesis_block(
Expand Down
2 changes: 1 addition & 1 deletion src/cryptonote_core/cryptonote_tx_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ namespace cryptonote

//---------------------------------------------------------------
crypto::public_key get_destination_view_key_pub(const std::vector<tx_destination_entry> &destinations, const boost::optional<cryptonote::tx_destination_entry>& change_addr);
bool construct_tx(const account_keys& sender_account_keys, std::vector<tx_source_entry> &sources, const std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::tx_destination_entry>& change_addr, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time);
bool construct_tx(const account_keys& sender_account_keys, std::vector<tx_source_entry> &sources, const std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::tx_destination_entry>& change_addr, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time, bool is_staking = false, bool per_output_unlock = false);
bool construct_tx_with_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::tx_destination_entry>& change_addr, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, bool rct = false, bool bulletproof = false, rct::multisig_out *msout = NULL, bool per_output_unlock = false, bool shuffle_outs = true);
bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::tx_destination_entry>& change_addr, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys, bool rct = false, bool bulletproof = false, rct::multisig_out *msout = NULL, bool is_staking_tx = false, bool per_output_unlock = false);

Expand Down
63 changes: 49 additions & 14 deletions tests/core_tests/chaingen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "include_base_utils.h"

#include "console_handler.h"
#include "common/rules.h"

#include "p2p/net_node.h"
#include "cryptonote_basic/cryptonote_basic.h"
Expand Down Expand Up @@ -107,8 +108,9 @@ bool test_generator::construct_block(cryptonote::block& blk, uint64_t height, co
const cryptonote::account_base& miner_acc, uint64_t timestamp, uint64_t already_generated_coins,
std::vector<size_t>& block_sizes, const std::list<cryptonote::transaction>& tx_list)
{
blk.major_version = CURRENT_BLOCK_MAJOR_VERSION;
blk.minor_version = CURRENT_BLOCK_MINOR_VERSION;
/// a temporary workaround
blk.major_version = hf_version_;
blk.minor_version = hf_version_;
blk.timestamp = timestamp;
blk.prev_id = prev_id;

Expand Down Expand Up @@ -263,18 +265,19 @@ struct output_index {
uint64_t amount;
rct::key mask;
size_t blk_height; // block height
uint64_t unlock_time;
size_t tx_no; // index of transaction in block
size_t out_no; // index of out in transaction
size_t idx;
bool spent;
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), spent(false), p_blk(_pb), p_tx(_pt) { }
output_index(const cryptonote::txout_target_v &_out, uint64_t _a, size_t _h, uint64_t ut, size_t tno, size_t ono, const cryptonote::block *_pb, const cryptonote::transaction *_pt)
: out(_out), amount(_a), blk_height(_h), unlock_time(ut), tx_no(tno), out_no(ono), idx(0), spent(false), p_blk(_pb), p_tx(_pt) { }

output_index(const output_index &other)
: out(other.out), amount(other.amount), mask(other.mask), blk_height(other.blk_height), tx_no(other.tx_no), out_no(other.out_no), idx(other.idx), spent(other.spent), p_blk(other.p_blk), p_tx(other.p_tx) { }
: out(other.out), amount(other.amount), mask(other.mask), blk_height(other.blk_height), tx_no(other.tx_no), out_no(other.out_no), idx(other.idx), spent(other.spent), p_blk(other.p_blk), p_tx(other.p_tx), unlock_time(other.unlock_time) { }

const std::string toString() const {
std::stringstream ss;
Expand Down Expand Up @@ -394,7 +397,9 @@ bool init_output_indices(output_index_vec& outs, output_vec& outs_mine, const st

const auto height = boost::get<txin_gen>(*blk.miner_tx.vin.begin()).height; /// replace with front?

outs.push_back({out.target, out.amount, height, i, j, &blk, vtx[i]});
const auto unlock_time = (tx.version < 3) ? tx.unlock_time : tx.output_unlock_times[j];

outs.push_back({out.target, out.amount, height, unlock_time, i, j, &blk, vtx[i]});
size_t tx_global_idx = outs.size() - 1;
outs[tx_global_idx].idx = tx_global_idx;
outs[tx_global_idx].mask = rct::zeroCommit(out.amount);
Expand Down Expand Up @@ -568,7 +573,7 @@ bool fill_tx_destination(tx_destination_entry &de, const cryptonote::account_bas
void fill_tx_sources_and_destinations(const std::vector<test_event_entry>& events, const block& blk_head,
const cryptonote::account_base& from, const cryptonote::account_base& to,
uint64_t amount, uint64_t fee, size_t nmix, std::vector<tx_source_entry>& sources,
std::vector<tx_destination_entry>& destinations)
std::vector<tx_destination_entry>& destinations, uint64_t *change_amount)
{
sources.clear();
destinations.clear();
Expand All @@ -582,13 +587,15 @@ void fill_tx_sources_and_destinations(const std::vector<test_event_entry>& event
destinations.push_back(de);

tx_destination_entry de_change;
uint64_t cache_back = get_inputs_amount(sources) - (amount + fee);
if (0 < cache_back)
uint64_t cash_back = get_inputs_amount(sources) - (amount + fee);
if (0 < cash_back)
{
if (!fill_tx_destination(de_change, from, cache_back))
if (!fill_tx_destination(de_change, from, cash_back))
throw std::runtime_error("couldn't fill transaction cache back destination");
destinations.push_back(de_change);
}

if (change_amount) *change_amount = (cash_back > 0) ? cash_back : 0;
}

void fill_nonce(cryptonote::block& blk, const difficulty_type& diffic, uint64_t height)
Expand Down Expand Up @@ -650,14 +657,16 @@ bool construct_tx_to_key(const std::vector<test_event_entry>& events,

bool construct_tx_to_key(const std::vector<test_event_entry>& events, cryptonote::transaction& tx, const block& blk_head,
const cryptonote::account_base& from, const cryptonote::account_base& to, uint64_t amount,
uint64_t fee, size_t nmix, bool stake)
uint64_t fee, size_t nmix, bool stake, uint64_t unlock_time)
{
vector<tx_source_entry> sources;
vector<tx_destination_entry> destinations;
fill_tx_sources_and_destinations(events, blk_head, from, to, amount, fee, nmix, sources, destinations);
tx_destination_entry change_addr{ amount, from.get_keys().m_account_address, false /* is subaddr */ };

return cryptonote::construct_tx(from.get_keys(), sources, destinations, change_addr, {}, tx, 0);
uint64_t change_amount;
fill_tx_sources_and_destinations(events, blk_head, from, to, amount, fee, nmix, sources, destinations, &change_amount);
tx_destination_entry change_addr{change_amount, from.get_keys().m_account_address, false /* is subaddr */ };

return cryptonote::construct_tx(from.get_keys(), sources, destinations, change_addr, {}, tx, unlock_time, stake, true);
}

transaction construct_tx_with_fee(std::vector<test_event_entry>& events, const block& blk_head,
Expand Down Expand Up @@ -691,6 +700,32 @@ uint64_t get_balance(const cryptonote::account_base& addr, const std::vector<cry
return res;
}

uint64_t get_unlocked_balance(const cryptonote::account_base& addr, const std::vector<cryptonote::block>& blockchain, const map_hash2tx_t& mtx) {

if (blockchain.empty()) return 0;

uint64_t res = 0;
output_index_vec outs;
output_vec outs_mine;

map_hash2tx_t confirmed_txs;
get_confirmed_txs(blockchain, mtx, confirmed_txs);

if (!init_output_indices(outs, outs_mine, blockchain, confirmed_txs, addr))
return false;

if (!init_spent_output_indices(outs, outs_mine, blockchain, confirmed_txs, addr))
return false;

for (const size_t out_idx : outs_mine) {
const auto unlocked = rules::is_output_unlocked(outs[out_idx].unlock_time, get_block_height(blockchain.back()));
if (outs[out_idx].spent || !unlocked) continue;
res += outs[out_idx].amount;
}

return res;
}

void get_confirmed_txs(const std::vector<cryptonote::block>& blockchain, const map_hash2tx_t& mtx, map_hash2tx_t& confirmed_txs)
{
std::unordered_set<crypto::hash> confirmed_hashes;
Expand Down
23 changes: 18 additions & 5 deletions tests/core_tests/chaingen.h
Original file line number Diff line number Diff line change
Expand Up @@ -219,9 +219,13 @@ class test_generator
bool construct_block_manually_tx(cryptonote::block& blk, const cryptonote::block& prev_block,
const cryptonote::account_base& miner_acc, const std::vector<crypto::hash>& tx_hashes, size_t txs_size);

explicit test_generator(uint8_t hf_version = 7) : hf_version_(hf_version) {}

void set_hf_version(uint8_t ver) { hf_version_ = ver; }

private:
std::unordered_map<crypto::hash, block_info> m_blocks_info;
uint8_t hf_version_ = 7;
uint8_t hf_version_;
};

inline cryptonote::difficulty_type get_test_difficulty() {return 1;}
Expand All @@ -238,7 +242,7 @@ bool construct_tx_to_key(const std::vector<test_event_entry>& events,
uint64_t amount);
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, bool stake=false);
uint64_t amount, uint64_t fee, size_t nmix, bool stake=false, uint64_t unlock_time=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,
uint64_t amount, uint64_t fee);
Expand All @@ -249,11 +253,12 @@ void fill_tx_sources_and_destinations(const std::vector<test_event_entry>& event
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);
std::vector<cryptonote::tx_destination_entry>& destinations, uint64_t *change_amount = nullptr);

/// Get the amount transferred to `account` in `tx` as output `i`
uint64_t get_amount(const cryptonote::account_base& account, const cryptonote::transaction& tx, int i);
uint64_t get_balance(const cryptonote::account_base& addr, const std::vector<cryptonote::block>& blockchain, const map_hash2tx_t& mtx);
uint64_t get_unlocked_balance(const cryptonote::account_base& addr, const std::vector<cryptonote::block>& blockchain, const map_hash2tx_t& mtx);

//--------------------------------------------------------------------------
template<class t_test_class>
Expand Down Expand Up @@ -591,7 +596,14 @@ inline bool do_replay_file(const std::string& filename)
register_callback(#METHOD, boost::bind(&CLASS::METHOD, this, _1, _2, _3));

#define MAKE_GENESIS_BLOCK(VEC_EVENTS, BLK_NAME, MINER_ACC, TS) \
test_generator generator; \
test_generator generator; \
cryptonote::block BLK_NAME; \
generator.construct_block(BLK_NAME, MINER_ACC, TS); \
VEC_EVENTS.push_back(BLK_NAME);

/// TODO: use hf_ver from test options
#define MAKE_GENESIS_BLOCK_WITH_HF_VERSION(VEC_EVENTS, BLK_NAME, MINER_ACC, TS, HF_VER) \
test_generator generator(HF_VER); \
cryptonote::block BLK_NAME; \
generator.construct_block(BLK_NAME, MINER_ACC, TS); \
VEC_EVENTS.push_back(BLK_NAME);
Expand Down Expand Up @@ -644,7 +656,8 @@ inline cryptonote::transaction make_registration_tx(
uint64_t amount = service_nodes::portions_to_amount(portions[0], staking_requirement);

cryptonote::transaction tx;
construct_tx_to_key(events, tx, head, account, account, amount, TESTS_DEFAULT_FEE, 9, true /* staking */);
construct_tx_to_key(events, tx, head, account, account, amount, TESTS_DEFAULT_FEE, 9, true /* staking */, STAKING_REQUIREMENT_LOCK_BLOCKS_TESTNET);
events.push_back(tx);
return tx;
}

Expand Down
25 changes: 19 additions & 6 deletions tests/core_tests/service_nodes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,20 +49,31 @@ bool gen_service_nodes::generate(std::vector<test_event_entry> &events) const
uint64_t ts_start = 1338224400;

GENERATE_ACCOUNT(miner);
MAKE_GENESIS_BLOCK(events, blk_0, miner, ts_start); // 0
MAKE_ACCOUNT(events, alice); // 1

MAKE_NEXT_BLOCK(events, blk_0a, blk_0, miner);
REWIND_BLOCKS(events, blk_1, blk_0a, miner);
MAKE_GENESIS_BLOCK(events, blk_0, miner, ts_start);
MAKE_ACCOUNT(events, alice);

generator.set_hf_version(8);
MAKE_NEXT_BLOCK(events, blk_a, blk_0, miner);

generator.set_hf_version(9);
MAKE_NEXT_BLOCK(events, blk_b, blk_a, miner);


REWIND_BLOCKS_N(events, blk_c, blk_b, miner, 10);

REWIND_BLOCKS(events, blk_1, blk_c, miner);

MAKE_TX(events, tx_0, miner, alice, MK_COINS(101), blk_1);
MAKE_NEXT_BLOCK_TX1(events, blk_2, blk_1, miner, tx_0);

REWIND_BLOCKS_N(events, blk_3, blk_2, miner, 100);
REWIND_BLOCKS(events, blk_3, blk_2, miner);

cryptonote::transaction alice_registration =
make_registration_tx(events, alice, m_alice_service_node_keys, 0, { alice.get_keys().m_account_address }, { STAKING_PORTIONS }, blk_3);

MAKE_NEXT_BLOCK_TX1(events, blk_4, blk_3, miner, alice_registration);

DO_CALLBACK(events, "check_stuff");

return true;
Expand All @@ -83,7 +94,9 @@ bool gen_service_nodes::check_stuff(cryptonote::core& c, size_t ev_index, const
r = find_block_chain(events, chain, mtx, get_block_hash(blocks.back()));
CHECK_TEST_CONDITION(r);

CHECK_EQ(MK_COINS(100), get_balance(alice, blocks, mtx));
const uint64_t staking_requirement = MK_COINS(100);

CHECK_EQ(MK_COINS(101) - TESTS_DEFAULT_FEE - staking_requirement, get_unlocked_balance(alice, blocks, mtx));

return true;
}
9 changes: 9 additions & 0 deletions tests/core_tests/service_nodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,12 @@ class gen_service_nodes : public test_chain_unit_base
private:
cryptonote::keypair m_alice_service_node_keys;
};

template<>
struct get_test_options<gen_service_nodes> {
const std::pair<uint8_t, uint64_t> hard_forks[3] = {std::make_pair(7, 0), std::make_pair(8, 1), std::make_pair(9, 2)};
// const std::pair<uint8_t, uint64_t> hard_forks[1] = {std::make_pair(9, 0)};
const cryptonote::test_options test_options = {
hard_forks
};
};

0 comments on commit 3dfb7e3

Please sign in to comment.