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

core_tests: check service node registration and expiration #195

Merged
merged 3 commits into from
Sep 4, 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
2 changes: 0 additions & 2 deletions src/cryptonote_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,6 @@
#define CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE 10

#define STAKING_REQUIREMENT_LOCK_BLOCKS_EXCESS 20
#define STAKING_REQUIREMENT_LOCK_BLOCKS (30*24*30)
#define STAKING_REQUIREMENT_LOCK_BLOCKS_TESTNET (30*24*2)
#define STAKING_PORTIONS UINT64_C(0xfffffffffffffffc)
#define MAX_NUMBER_OF_CONTRIBUTORS 4
#define MIN_PORTIONS (STAKING_PORTIONS / MAX_NUMBER_OF_CONTRIBUTORS)
Expand Down
23 changes: 16 additions & 7 deletions src/cryptonote_core/service_node_list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ namespace service_nodes
if (tx.version >= cryptonote::transaction::version_3_per_output_unlock_times)
unlock_time = tx.output_unlock_times[i];

return unlock_time < CRYPTONOTE_MAX_BLOCK_NUMBER && unlock_time >= block_height + get_staking_requirement_lock_blocks();
return unlock_time < CRYPTONOTE_MAX_BLOCK_NUMBER && unlock_time >= block_height + get_staking_requirement_lock_blocks(m_blockchain.nettype());
}

bool service_node_list::reg_tx_extract_fields(const cryptonote::transaction& tx, std::vector<cryptonote::account_public_address>& addresses, uint64_t& portions_for_operator, std::vector<uint64_t>& portions, uint64_t& expiration_timestamp, crypto::public_key& service_node_key, crypto::signature& signature, crypto::public_key& tx_pub_key) const
Expand Down Expand Up @@ -582,7 +582,7 @@ namespace service_nodes
{
std::vector<crypto::public_key> expired_nodes;

const uint64_t lock_blocks = get_staking_requirement_lock_blocks();
const uint64_t lock_blocks = get_staking_requirement_lock_blocks(m_blockchain.nettype());

if (block_height < lock_blocks)
return expired_nodes;
Expand Down Expand Up @@ -802,11 +802,6 @@ namespace service_nodes
}
}

uint64_t service_node_list::get_staking_requirement_lock_blocks() const
{
return m_blockchain.nettype() == cryptonote::TESTNET || m_blockchain.nettype() == cryptonote::FAKECHAIN ? STAKING_REQUIREMENT_LOCK_BLOCKS_TESTNET : STAKING_REQUIREMENT_LOCK_BLOCKS;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

service_node_list::rollback_event::rollback_event(uint64_t block_height, rollback_type type) : m_block_height(block_height), type(type)
Expand Down Expand Up @@ -1156,6 +1151,20 @@ namespace service_nodes
cmd = stream.str();
return true;
}

uint64_t get_staking_requirement_lock_blocks(cryptonote::network_type nettype)
{
constexpr static uint32_t STAKING_REQUIREMENT_LOCK_BLOCKS = 30*24*30;
constexpr static uint32_t STAKING_REQUIREMENT_LOCK_BLOCKS_TESTNET = 30*24*2;
constexpr static uint32_t STAKING_REQUIREMENT_LOCK_BLOCKS_FAKENET = 30;

switch(nettype) {
case cryptonote::TESTNET: return STAKING_REQUIREMENT_LOCK_BLOCKS_TESTNET;
case cryptonote::FAKECHAIN: return STAKING_REQUIREMENT_LOCK_BLOCKS_FAKENET;
default: return STAKING_REQUIREMENT_LOCK_BLOCKS;
}
}

uint64_t get_staking_requirement(cryptonote::network_type m_nettype, uint64_t height)
{
if (m_nettype == cryptonote::TESTNET || m_nettype == cryptonote::FAKECHAIN)
Expand Down
4 changes: 2 additions & 2 deletions src/cryptonote_core/service_node_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,6 @@ namespace service_nodes

std::vector<crypto::public_key> get_service_nodes_pubkeys() const;

uint64_t get_staking_requirement_lock_blocks() const;

template<typename T>
void block_added_generic(const cryptonote::block& block, const T& txs);

Expand Down Expand Up @@ -284,6 +282,8 @@ namespace service_nodes
bool make_registration_cmd(cryptonote::network_type nettype, const std::vector<std::string> args, const crypto::public_key& service_node_pubkey,
const crypto::secret_key service_node_key, std::string &cmd, bool make_friendly);

uint64_t get_staking_requirement_lock_blocks(cryptonote::network_type m_nettype);

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

uint64_t portions_to_amount(uint64_t portions, uint64_t staking_requirement);
Expand Down
2 changes: 1 addition & 1 deletion src/daemon/rpc_command_executor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2037,7 +2037,7 @@ static void print_service_node_list_state(cryptonote::network_type nettype, uint
// Print Expiry Info
{
uint64_t expiry_height = entry.registration_height;
expiry_height += (nettype == cryptonote::TESTNET) ? STAKING_REQUIREMENT_LOCK_BLOCKS_TESTNET : STAKING_REQUIREMENT_LOCK_BLOCKS;
expiry_height += service_nodes::get_staking_requirement_lock_blocks(nettype);

if (curr_height)
{
Expand Down
4 changes: 2 additions & 2 deletions src/simplewallet/simplewallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4740,7 +4740,7 @@ bool simple_wallet::register_service_node_main(
return true;
}

uint64_t staking_requirement_lock_blocks = (m_wallet->nettype() == cryptonote::TESTNET ? STAKING_REQUIREMENT_LOCK_BLOCKS_TESTNET : STAKING_REQUIREMENT_LOCK_BLOCKS);
uint64_t staking_requirement_lock_blocks = service_nodes::get_staking_requirement_lock_blocks(m_wallet->nettype());
uint64_t locked_blocks = staking_requirement_lock_blocks + STAKING_REQUIREMENT_LOCK_BLOCKS_EXCESS;

std::string err, err2;
Expand Down Expand Up @@ -5089,7 +5089,7 @@ bool simple_wallet::stake_main(
uint64_t fetched_blocks;
m_wallet->refresh(0, fetched_blocks);

uint64_t staking_requirement_lock_blocks = (m_wallet->nettype() == cryptonote::TESTNET ? STAKING_REQUIREMENT_LOCK_BLOCKS_TESTNET : STAKING_REQUIREMENT_LOCK_BLOCKS);
uint64_t staking_requirement_lock_blocks = service_nodes::get_staking_requirement_lock_blocks(m_wallet->nettype());
uint64_t locked_blocks = staking_requirement_lock_blocks + STAKING_REQUIREMENT_LOCK_BLOCKS_EXCESS;

std::string err, err2;
Expand Down
77 changes: 61 additions & 16 deletions tests/core_tests/chaingen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,13 @@ void test_generator::add_block(const cryptonote::block& blk, size_t tsx_size, st
const size_t block_size = tsx_size + get_object_blobsize(blk.miner_tx);
uint64_t block_reward;
cryptonote::get_block_reward(misc_utils::median(block_sizes), block_size, already_generated_coins, block_reward, hf_version_, 0);
m_blocks_info[get_block_hash(blk)] = block_info(blk.prev_id, already_generated_coins + block_reward, block_size);
m_blocks_info.insert({get_block_hash(blk), block_info(blk.prev_id, already_generated_coins + block_reward, block_size)});
}

bool test_generator::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_sizes, const std::list<cryptonote::transaction>& tx_list)
std::vector<size_t>& block_sizes, const std::list<cryptonote::transaction>& tx_list,
const crypto::public_key& sn_pub_key /* = crypto::null_key */, const std::vector<sn_contributor_t>& sn_infos)
{
/// a temporary workaround
blk.major_version = hf_version_;
Expand Down Expand Up @@ -137,7 +138,8 @@ bool test_generator::construct_block(cryptonote::block& blk, uint64_t height, co
size_t target_block_size = txs_size + get_object_blobsize(blk.miner_tx);
while (true)
{
if (!construct_miner_tx(height, misc_utils::median(block_sizes), already_generated_coins, target_block_size, total_fee, miner_acc.get_keys().m_account_address, blk.miner_tx, blobdata(), hf_version_))

if (!construct_miner_tx(height, misc_utils::median(block_sizes), already_generated_coins, target_block_size, total_fee, miner_acc.get_keys().m_account_address, blk.miner_tx, blobdata(), hf_version_, cryptonote::MAINNET, sn_pub_key, sn_infos))
return false;

size_t actual_block_size = txs_size + get_object_blobsize(blk.miner_tx);
Expand Down Expand Up @@ -199,7 +201,8 @@ bool test_generator::construct_block(cryptonote::block& blk, const cryptonote::a

bool test_generator::construct_block(cryptonote::block& blk, const cryptonote::block& blk_prev,
const cryptonote::account_base& miner_acc,
const std::list<cryptonote::transaction>& tx_list/* = {}*/)
const std::list<cryptonote::transaction>& tx_list/* = {}*/,
const crypto::public_key& sn_pub_key /* = crypto::null_key */, const std::vector<sn_contributor_t>& sn_infos)
{
uint64_t height = boost::get<txin_gen>(blk_prev.miner_tx.vin.front()).height + 1;
crypto::hash prev_id = get_block_hash(blk_prev);
Expand All @@ -209,7 +212,7 @@ bool test_generator::construct_block(cryptonote::block& blk, const cryptonote::b
std::vector<size_t> block_sizes;
get_last_n_block_sizes(block_sizes, prev_id, CRYPTONOTE_REWARD_BLOCKS_WINDOW);

return construct_block(blk, height, prev_id, miner_acc, timestamp, already_generated_coins, block_sizes, tx_list);
return construct_block(blk, height, prev_id, miner_acc, timestamp, already_generated_coins, block_sizes, tx_list, sn_pub_key, sn_infos);
}

bool test_generator::construct_block_manually(block& blk, const block& prev_block, const account_base& miner_acc,
Expand Down Expand Up @@ -270,14 +273,14 @@ struct output_index {
size_t out_no; // index of out in transaction
size_t idx;
bool spent;
bool is_sn_reward = false;
const cryptonote::block *p_blk;
const cryptonote::transaction *p_tx;

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), unlock_time(other.unlock_time) { }
output_index(const output_index &other) = default;

const std::string toString() const {
std::stringstream ss;
Expand Down Expand Up @@ -404,13 +407,20 @@ bool init_output_indices(output_index_vec& outs, output_vec& outs_mine, const st
outs[tx_global_idx].idx = tx_global_idx;
outs[tx_global_idx].mask = rct::zeroCommit(out.amount);
// Is out to me?
if (is_out_to_acc(from.get_keys(), boost::get<txout_to_key>(out.target), get_tx_pub_key_from_extra(tx), get_additional_tx_pub_keys_from_extra(tx), j)) {
outs_mine.push_back(tx_global_idx);
auto& out = outs.back();
if (out.amount == 0) {
out.amount = get_amount(from, tx, j);
out.mask = tx.rct_signatures.outPk[j].mask;
const auto gov_key = cryptonote::get_deterministic_keypair_from_height(height);

const bool to_acc_regular = is_out_to_acc(from.get_keys(), boost::get<txout_to_key>(out.target), get_tx_pub_key_from_extra(tx), get_additional_tx_pub_keys_from_extra(tx), j);
const bool to_acc_sn_reward = to_acc_regular ? false : is_out_to_acc(from.get_keys(), boost::get<txout_to_key>(out.target), gov_key.pub, {}, j);

if (to_acc_regular || to_acc_sn_reward) {
outs_mine.push_back(tx_global_idx);
auto& oi = outs.back();
oi.is_sn_reward = to_acc_sn_reward;
if (oi.amount == 0) {
oi.amount = get_amount(from, tx, j);
oi.mask = tx.rct_signatures.outPk[j].mask;
}

}
}
}
Expand All @@ -436,10 +446,14 @@ bool init_spent_output_indices(output_index_vec& outs,
crypto::public_key out_key = boost::get<txout_to_key>(oi.out).key;
std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddresses;
subaddresses[from.get_keys().m_account_address.m_spend_public_key] = {0,0};

const auto tx_pk = oi.is_sn_reward ? get_deterministic_keypair_from_height(oi.blk_height).pub
: get_tx_pub_key_from_extra(*oi.p_tx);

generate_key_image_helper(from.get_keys(),
subaddresses,
out_key,
get_tx_pub_key_from_extra(*oi.p_tx),
tx_pk,
get_additional_tx_pub_keys_from_extra(*oi.p_tx),
oi.out_no,
in_ephemeral,
Expand Down Expand Up @@ -737,7 +751,7 @@ 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 unlock_time)
uint64_t fee, size_t nmix, bool stake, boost::optional<const register_info> reg_info, uint64_t unlock_time)
{
vector<tx_source_entry> sources;
vector<tx_destination_entry> destinations;
Expand All @@ -746,7 +760,38 @@ bool construct_tx_to_key(const std::vector<test_event_entry>& events, cryptonote
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);

std::vector<uint8_t> extra;

if (stake) {

if (!reg_info) {
LOG_ERROR("Stake tx has not registration info");
return false;
}

add_service_node_pubkey_to_tx_extra(extra, reg_info->service_node_keypair.pub);

const uint64_t exp_timestamp = time(nullptr) + STAKING_AUTHORIZATION_EXPIRATION_WINDOW;

crypto::hash hash;
bool hashed = cryptonote::get_registration_hash(reg_info->addresses, reg_info->operator_cut, reg_info->portions, exp_timestamp, hash);
if (!hashed)
{
MERROR("Could not make registration hash from addresses and portions");
return false;
}

crypto::signature signature;
crypto::generate_signature(hash, reg_info->service_node_keypair.pub, reg_info->service_node_keypair.sec, signature);

add_service_node_register_to_tx_extra(extra, reg_info->addresses, reg_info->operator_cut, reg_info->portions, exp_timestamp, signature);
add_service_node_contributor_to_tx_extra(extra, reg_info->addresses.at(0));

}


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

transaction construct_tx_with_fee(std::vector<test_event_entry>& events, const block& blk_head,
Expand Down
Loading