Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First service node test #190

Merged
merged 2 commits into from
Aug 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/cryptonote_core/cryptonote_core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1757,6 +1757,7 @@ namespace cryptonote

return result;
}
//-----------------------------------------------------------------------------------------------
bool core::get_service_node_keys(crypto::public_key &pub_key, crypto::secret_key &sec_key) const
{
if (m_service_node)
Expand Down
2 changes: 1 addition & 1 deletion src/cryptonote_core/cryptonote_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -817,7 +817,7 @@ namespace cryptonote
bool add_deregister_vote(const loki::service_node_deregister::vote& vote, vote_verification_context &vvc);

/**
* @brief Return the account associated to this service node.
* @brief Get the keypair for this service node.

* @param pub_key The public key for the service node, unmodified if not a service node

Expand Down
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
8 changes: 8 additions & 0 deletions src/cryptonote_core/service_node_list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1163,5 +1163,13 @@ namespace service_nodes
uint64_t flat = 15000 * COIN;
return std::max(base + variable, height < 3628800 ? linear_up : flat);
}

uint64_t portions_to_amount(uint64_t portions, uint64_t staking_requirement)
{
uint64_t hi, lo, resulthi, resultlo;
lo = mul128(staking_requirement, portions, &hi);
div128_64(hi, lo, STAKING_PORTIONS, &resulthi, &resultlo);
return resultlo;
}
}

2 changes: 2 additions & 0 deletions src/cryptonote_core/service_node_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,8 @@ namespace service_nodes

uint64_t get_staking_requirement(cryptonote::network_type nettype, uint64_t height);

uint64_t portions_to_amount(uint64_t portions, uint64_t staking_requirement);

const static cryptonote::account_public_address null_address{ crypto::null_pkey, crypto::null_pkey };
}

Expand Down
2 changes: 2 additions & 0 deletions tests/core_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ set(core_tests_sources
integer_overflow.cpp
multisig.cpp
ring_signature_1.cpp
service_nodes.cpp
transaction_tests.cpp
tx_validation.cpp
v2_tests.cpp
Expand All @@ -55,6 +56,7 @@ set(core_tests_headers
integer_overflow.h
multisig.h
ring_signature_1.h
service_nodes.h
transaction_tests.h
tx_validation.h
v2_tests.h
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;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

boost::optional is less bug prone than null pointers @msgmaxim I actually was reminded about this when reading the rust book. I see what you mean now about compile-time reference checks, very cool

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! :)

}

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)
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
55 changes: 48 additions & 7 deletions tests/core_tests/chaingen.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "tests.core"


#define TESTS_DEFAULT_FEE ((uint64_t)200000000) // 2 * pow(10, 8)

struct callback_entry
{
Expand Down Expand Up @@ -106,10 +106,12 @@ struct event_visitor_settings
{
int valid_mask;
bool txs_keeped_by_block;
crypto::secret_key service_node_key;

enum settings
{
set_txs_keeped_by_block = 1 << 0
set_txs_keeped_by_block = 1 << 0,
set_service_node_key = 1 << 1
};

event_visitor_settings(int a_valid_mask = 0, bool a_txs_keeped_by_block = false)
Expand All @@ -118,6 +120,13 @@ struct event_visitor_settings
{
}

static event_visitor_settings make_set_service_node_key(const crypto::secret_key& a_service_node_key)
{
event_visitor_settings settings(set_service_node_key);
settings.service_node_key = a_service_node_key;
return settings;
}

private:
friend class boost::serialization::access;

Expand All @@ -126,6 +135,7 @@ struct event_visitor_settings
{
ar & valid_mask;
ar & txs_keeped_by_block;
ar & service_node_key;
}
};

Expand Down Expand Up @@ -209,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 @@ -228,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);
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 @@ -239,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 @@ -581,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 @@ -619,6 +641,26 @@ inline bool do_replay_file(const std::string& filename)

#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)

inline cryptonote::transaction make_registration_tx(
std::vector<test_event_entry>& events,
const cryptonote::account_base& account,
const cryptonote::keypair& service_node_keys,
uint64_t operator_cut,
const std::vector<cryptonote::account_public_address>& addresses,
const std::vector<uint64_t>& portions,
const cryptonote::block& head)
{
uint64_t staking_requirement =
service_nodes::get_staking_requirement(cryptonote::FAKECHAIN, cryptonote::get_block_height(head) + 1);

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 */, STAKING_REQUIREMENT_LOCK_BLOCKS_TESTNET);
events.push_back(tx);
return tx;
}

#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); \
Expand Down Expand Up @@ -719,4 +761,3 @@ inline bool do_replay_file(const std::string& filename)
#define CHECK_EQ(v1, v2) CHECK_AND_ASSERT_MES(v1 == v2, false, "[" << perr_context << "] failed: \"" << QUOTEME(v1) << " == " << QUOTEME(v2) << "\", " << v1 << " != " << v2)
#define CHECK_NOT_EQ(v1, v2) CHECK_AND_ASSERT_MES(!(v1 == v2), false, "[" << perr_context << "] failed: \"" << QUOTEME(v1) << " != " << QUOTEME(v2) << "\", " << v1 << " == " << v2)
#define MK_COINS(amount) (UINT64_C(amount) * COIN)
#define TESTS_DEFAULT_FEE ((uint64_t)20000000000) // 2 * pow(10, 10)
1 change: 1 addition & 0 deletions tests/core_tests/chaingen_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ int main(int argc, char* argv[])
}
else if (command_line::get_arg(vm, arg_generate_and_play_test_data))
{
GENERATE_AND_PLAY(gen_service_nodes);
GENERATE_AND_PLAY(gen_simple_chain_001);
GENERATE_AND_PLAY(gen_simple_chain_split_1);
GENERATE_AND_PLAY(one_block);
Expand Down
1 change: 1 addition & 0 deletions tests/core_tests/chaingen_tests_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "double_spend.h"
#include "integer_overflow.h"
#include "ring_signature_1.h"
#include "service_nodes.h"
#include "tx_validation.h"
#include "v2_tests.h"
#include "rct.h"
Expand Down
Loading