service nodes: changed portions to 64 bits

also miner fixes to simplewallet behaviour and interactive registration
prompt
This commit is contained in:
jcktm 2018-08-18 14:36:16 +10:00
parent 1977b01cb3
commit 78b7fccfbf
13 changed files with 97 additions and 79 deletions

View File

@ -552,8 +552,8 @@ namespace cryptonote
bool add_service_node_register_to_tx_extra(
std::vector<uint8_t>& tx_extra,
const std::vector<cryptonote::account_public_address>& addresses,
uint32_t portions_for_operator,
const std::vector<uint32_t>& portions,
uint64_t portions_for_operator,
const std::vector<uint64_t>& portions,
uint64_t expiration_timestamp,
const crypto::signature& service_node_signature)
{
@ -1041,22 +1041,24 @@ namespace cryptonote
return true;
}
//---------------------------------------------------------------
bool get_registration_hash(const std::vector<cryptonote::account_public_address>& addresses, uint32_t operator_portions, const std::vector<uint32_t>& portions, uint64_t expiration_timestamp, crypto::hash& hash)
bool get_registration_hash(const std::vector<cryptonote::account_public_address>& addresses, uint64_t operator_portions, const std::vector<uint64_t>& portions, uint64_t expiration_timestamp, crypto::hash& hash)
{
if (addresses.size() != portions.size())
{
LOG_ERROR("get_registration_hash addresses.size() != portions.size()");
return false;
}
uint64_t total_portions = 0;
for (uint32_t portion : portions)
total_portions += portion;
if (total_portions > STAKING_PORTIONS)
uint64_t portions_left = STAKING_PORTIONS;
for (uint64_t portion : portions)
{
LOG_ERROR(tr("Your registration has more than ") << STAKING_PORTIONS << tr(" portions, this registration is invalid!"));
return false;
if (portion > portions_left)
{
LOG_ERROR(tr("Your registration has more than ") << STAKING_PORTIONS << tr(" portions, this registration is invalid!"));
return false;
}
portions_left -= portion;
}
size_t size = addresses.size() * (sizeof(cryptonote::account_public_address) + sizeof(uint32_t)) + sizeof(uint32_t) + sizeof(uint64_t);
size_t size = addresses.size() * (sizeof(cryptonote::account_public_address) + sizeof(uint64_t)) + sizeof(uint64_t) + sizeof(uint64_t);
char* buffer = new char[size];
char* buffer_iter = buffer;
memcpy(buffer_iter, &operator_portions, sizeof(operator_portions));
@ -1065,8 +1067,8 @@ namespace cryptonote
{
memcpy(buffer_iter, &addresses[i], sizeof(cryptonote::account_public_address));
buffer_iter += sizeof(cryptonote::account_public_address);
memcpy(buffer_iter, &portions[i], sizeof(uint32_t));
buffer_iter += sizeof(uint32_t);
memcpy(buffer_iter, &portions[i], sizeof(uint64_t));
buffer_iter += sizeof(uint64_t);
}
memcpy(buffer_iter, &expiration_timestamp, sizeof(expiration_timestamp));
buffer_iter += sizeof(expiration_timestamp);

View File

@ -75,7 +75,7 @@ namespace cryptonote
bool get_service_node_deregister_from_tx_extra(const std::vector<uint8_t>& tx_extra, tx_extra_service_node_deregister& deregistration);
bool get_service_node_pubkey_from_tx_extra(const std::vector<uint8_t>& tx_extra, crypto::public_key& pubkey);
bool get_service_node_contributor_from_tx_extra(const std::vector<uint8_t>& tx_extra, cryptonote::account_public_address& address);
bool add_service_node_register_to_tx_extra(std::vector<uint8_t>& tx_extra, const std::vector<cryptonote::account_public_address>& addresses, uint32_t portions_for_operator, const std::vector<uint32_t>& portions, uint64_t expiration_timestamp, const crypto::signature& signature);
bool add_service_node_register_to_tx_extra(std::vector<uint8_t>& tx_extra, const std::vector<cryptonote::account_public_address>& addresses, uint64_t portions_for_operator, const std::vector<uint64_t>& portions, uint64_t expiration_timestamp, const crypto::signature& signature);
bool get_tx_secret_key_from_tx_extra(const std::vector<uint8_t>& tx_extra, crypto::secret_key& key);
void add_tx_secret_key_to_tx_extra(std::vector<uint8_t>& tx_extra, const crypto::secret_key& key);
void add_service_node_winner_to_tx_extra(std::vector<uint8_t>& tx_extra, const crypto::public_key& winner);
@ -110,7 +110,7 @@ namespace cryptonote
crypto::hash get_blob_hash(const blobdata& blob);
std::string short_hash_str(const crypto::hash& h);
bool get_registration_hash(const std::vector<cryptonote::account_public_address>& addresses, uint32_t operator_portions, const std::vector<uint32_t>& portions, uint64_t expiration_timestamp, crypto::hash& hash);
bool get_registration_hash(const std::vector<cryptonote::account_public_address>& addresses, uint64_t operator_portions, const std::vector<uint64_t>& portions, uint64_t expiration_timestamp, crypto::hash& hash);
crypto::hash get_transaction_hash(const transaction& t);
bool get_transaction_hash(const transaction& t, crypto::hash& res);

View File

@ -207,8 +207,8 @@ namespace cryptonote
{
std::vector<crypto::public_key> m_public_spend_keys;
std::vector<crypto::public_key> m_public_view_keys;
uint32_t m_portions_for_operator;
std::vector<uint32_t> m_portions;
uint64_t m_portions_for_operator;
std::vector<uint64_t> m_portions;
uint64_t m_expiration_timestamp;
crypto::signature m_service_node_signature;

View File

@ -52,7 +52,7 @@
#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 0xfffffffc
#define STAKING_PORTIONS UINT64_C(0xfffffffffffffffc)
#define MAX_NUMBER_OF_CONTRIBUTORS 4
#define MIN_PORTIONS (STAKING_PORTIONS / MAX_NUMBER_OF_CONTRIBUTORS)

View File

@ -1329,7 +1329,7 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m
uint8_t hf_version = m_hardfork->get_current_version();
crypto::public_key winner = m_service_node_list.select_winner(b.prev_id);
std::vector<std::pair<account_public_address, uint32_t>> service_node_addresses = m_service_node_list.get_winner_addresses_and_portions(b.prev_id);
std::vector<std::pair<account_public_address, uint64_t>> service_node_addresses = m_service_node_list.get_winner_addresses_and_portions(b.prev_id);
bool r = construct_miner_tx(height, median_size, already_generated_coins, txs_size, fee, miner_address, b.miner_tx, ex_nonce, hf_version, m_nettype, winner, service_node_addresses);
CHECK_AND_ASSERT_MES(r, false, "Failed to construct miner tx, first chance");

View File

@ -111,15 +111,15 @@ namespace cryptonote
return hard_fork_version >= 9 ? base_reward / 2 : 0;
}
uint64_t get_portion_of_reward(uint32_t portions, uint64_t total_service_node_reward)
uint64_t get_portion_of_reward(uint64_t portions, uint64_t total_service_node_reward)
{
uint64_t hi, lo, rewardhi, rewardlo;
lo = mul128(total_service_node_reward, portions, &hi);
div128_32(hi, lo, STAKING_PORTIONS, &rewardhi, &rewardlo);
div128_64(hi, lo, STAKING_PORTIONS, &rewardhi, &rewardlo);
return rewardlo;
}
static uint64_t calculate_sum_of_portions(const std::vector<std::pair<cryptonote::account_public_address, uint32_t>>& portions, uint64_t total_service_node_reward)
static uint64_t calculate_sum_of_portions(const std::vector<std::pair<cryptonote::account_public_address, uint64_t>>& portions, uint64_t total_service_node_reward)
{
uint64_t reward = 0;
for (size_t i = 0; i < portions.size(); i++)
@ -184,7 +184,7 @@ namespace cryptonote
uint8_t hard_fork_version,
network_type nettype,
const crypto::public_key& service_node_key,
const std::vector<std::pair<account_public_address, uint32_t>>& service_node_info)
const std::vector<std::pair<account_public_address, uint64_t>>& service_node_info)
{
tx.vin.clear();
tx.vout.clear();

View File

@ -49,12 +49,12 @@ namespace cryptonote
uint8_t hard_fork_version = 1,
network_type nettype = MAINNET,
const crypto::public_key& service_node_key = crypto::null_pkey,
const std::vector<std::pair<account_public_address, uint32_t>>& service_node_info={ std::pair<account_public_address, uint32_t>({ crypto::null_pkey, crypto::null_pkey }, STAKING_PORTIONS) }
const std::vector<std::pair<account_public_address, uint64_t>>& service_node_info={ std::pair<account_public_address, uint64_t>({ crypto::null_pkey, crypto::null_pkey }, STAKING_PORTIONS) }
);
keypair get_deterministic_keypair_from_height(uint64_t height);
uint64_t get_portion_of_reward(uint32_t portions, uint64_t total_service_node_reward);
uint64_t get_portion_of_reward(uint64_t portions, uint64_t total_service_node_reward);
uint64_t get_governance_reward(uint64_t height, uint64_t base_reward);
uint64_t get_service_node_reward(uint64_t height, uint64_t base_reward, int hard_fork_version);

View File

@ -190,7 +190,7 @@ namespace service_nodes
return unlock_time < CRYPTONOTE_MAX_BLOCK_NUMBER && unlock_time >= block_height + get_staking_requirement_lock_blocks();
}
bool service_node_list::reg_tx_extract_fields(const cryptonote::transaction& tx, std::vector<cryptonote::account_public_address>& addresses, uint32_t& portions_for_operator, std::vector<uint32_t>& portions, uint64_t& expiration_timestamp, crypto::public_key& service_node_key, crypto::signature& signature, crypto::public_key& tx_pub_key) const
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
{
cryptonote::tx_extra_service_node_register registration;
if (!get_service_node_register_from_tx_extra(tx.extra, registration))
@ -293,8 +293,8 @@ namespace service_nodes
{
crypto::public_key tx_pub_key, service_node_key;
std::vector<cryptonote::account_public_address> service_node_addresses;
std::vector<uint32_t> service_node_portions;
uint32_t portions_for_operator;
std::vector<uint64_t> service_node_portions;
uint64_t portions_for_operator;
uint64_t expiration_timestamp;
crypto::signature signature;
@ -309,7 +309,7 @@ namespace service_nodes
uint64_t portions_left = STAKING_PORTIONS;
for (size_t i = 0; i < service_node_portions.size(); i++)
{
uint64_t min_portions = std::min(portions_left, (uint64_t)MIN_PORTIONS);
uint64_t min_portions = std::min(portions_left, MIN_PORTIONS);
if (service_node_portions[i] < min_portions || service_node_portions[i] > portions_left)
return false;
portions_left -= service_node_portions[i];
@ -365,7 +365,7 @@ namespace service_nodes
return false;
uint64_t hi, lo, resulthi, resultlo;
lo = mul128(info.staking_requirement, service_node_portions[i], &hi);
div128_32(hi, lo, STAKING_PORTIONS, &resulthi, &resultlo);
div128_64(hi, lo, STAKING_PORTIONS, &resulthi, &resultlo);
info.contributors.push_back(service_node_info::contribution(resultlo, service_node_addresses[i]));
if (m_blockchain.nettype() == cryptonote::TESTNET && block_height < 5500)
@ -622,13 +622,13 @@ namespace service_nodes
return expired_nodes;
}
std::vector<std::pair<cryptonote::account_public_address, uint32_t>> service_node_list::get_winner_addresses_and_portions(const crypto::hash& prev_id) const
std::vector<std::pair<cryptonote::account_public_address, uint64_t>> service_node_list::get_winner_addresses_and_portions(const crypto::hash& prev_id) const
{
crypto::public_key key = select_winner(prev_id);
if (key == crypto::null_pkey)
return { std::make_pair(null_address, STAKING_PORTIONS) };
std::vector<std::pair<cryptonote::account_public_address, uint32_t>> winners;
std::vector<std::pair<cryptonote::account_public_address, uint64_t>> winners;
const service_node_info& info = m_service_nodes_infos.at(key);
@ -681,7 +681,7 @@ namespace service_nodes
if (check_winner_pubkey != winner)
return false;
const std::vector<std::pair<cryptonote::account_public_address, uint32_t>> addresses_and_portions = get_winner_addresses_and_portions(prev_id);
const std::vector<std::pair<cryptonote::account_public_address, uint64_t>> addresses_and_portions = get_winner_addresses_and_portions(prev_id);
if (miner_tx.vout.size() - 1 < addresses_and_portions.size())
return false;
@ -1013,7 +1013,7 @@ namespace service_nodes
m_height = 0;
}
bool convert_registration_args(cryptonote::network_type nettype, std::vector<std::string> args, std::vector<cryptonote::account_public_address>& addresses, std::vector<uint32_t>& portions, uint32_t& portions_for_operator, bool& autostake)
bool convert_registration_args(cryptonote::network_type nettype, std::vector<std::string> args, std::vector<cryptonote::account_public_address>& addresses, std::vector<uint64_t>& portions, uint64_t& portions_for_operator, bool& autostake)
{
autostake = false;
if (!args.empty() && args[0] == "auto")
@ -1074,8 +1074,8 @@ namespace service_nodes
try
{
uint32_t num_portions = boost::lexical_cast<uint64_t>(args[i+1]);
uint64_t min_portions = std::min(portions_left, (uint64_t)MIN_PORTIONS);
uint64_t num_portions = boost::lexical_cast<uint64_t>(args[i+1]);
uint64_t min_portions = std::min(portions_left, MIN_PORTIONS);
if (num_portions < min_portions || num_portions > portions_left)
{
MERROR(tr("Invalid portion amount: ") << args[i+1] << tr(". ") << tr("The contributors must each have at least 25%, except for the last contributor which may have the remaining amount"));
@ -1098,8 +1098,8 @@ namespace service_nodes
{
std::vector<cryptonote::account_public_address> addresses;
std::vector<uint32_t> portions;
uint32_t operator_portions;
std::vector<uint64_t> portions;
uint64_t operator_portions;
bool autostake;
if (!convert_registration_args(nettype, args, addresses, portions, operator_portions, autostake))
{

View File

@ -85,7 +85,7 @@ namespace service_nodes
uint64_t total_contributed;
uint64_t total_reserved;
uint64_t staking_requirement;
uint32_t portions_for_operator;
uint64_t portions_for_operator;
cryptonote::account_public_address operator_address;
bool is_fully_funded() const { return total_contributed >= staking_requirement; }
@ -130,7 +130,7 @@ namespace service_nodes
std::vector<crypto::public_key> get_expired_nodes(uint64_t block_height) const;
std::vector<std::pair<cryptonote::account_public_address, uint32_t>> get_winner_addresses_and_portions(const crypto::hash& prev_id) const;
std::vector<std::pair<cryptonote::account_public_address, uint64_t>> get_winner_addresses_and_portions(const crypto::hash& prev_id) const;
crypto::public_key select_winner(const crypto::hash& prev_id) const;
bool is_service_node(const crypto::public_key& pubkey) const;
@ -155,7 +155,7 @@ namespace service_nodes
void block_added_generic(const cryptonote::block& block, const T& txs);
bool contribution_tx_output_has_correct_unlock_time(const cryptonote::transaction& tx, size_t i, uint64_t block_height) const;
bool reg_tx_extract_fields(const cryptonote::transaction& tx, std::vector<cryptonote::account_public_address>& addresses, uint32_t& portions_for_operator, std::vector<uint32_t>& portions, uint64_t& expiration_timestamp, crypto::public_key& service_node_key, crypto::signature& signature, crypto::public_key& tx_pub_key) const;
bool 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;
uint64_t get_reg_tx_staking_output_contribution(const cryptonote::transaction& tx, int i, crypto::key_derivation derivation, hw::device& hwdev) const;
crypto::public_key find_service_node_from_miner_tx(const cryptonote::transaction& miner_tx, uint64_t block_height) const;
@ -282,7 +282,7 @@ namespace service_nodes
std::map<block_height, std::shared_ptr<quorum_state>> m_quorum_states;
};
bool convert_registration_args(cryptonote::network_type nettype, std::vector<std::string> args, std::vector<cryptonote::account_public_address>& addresses, std::vector<uint32_t>& portions, uint32_t& portions_for_operator, bool& autostake);
bool convert_registration_args(cryptonote::network_type nettype, std::vector<std::string> args, std::vector<cryptonote::account_public_address>& addresses, std::vector<uint64_t>& portions, uint64_t& portions_for_operator, bool& autostake);
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);

View File

@ -2156,21 +2156,32 @@ bool t_rpc_command_executor::print_sn_key()
}
// Returns lowest x such that (STAKING_PORTIONS * x/amount) >= portions
static uint64_t get_amount_to_make_portions(uint64_t amount, uint32_t portions)
static uint64_t get_amount_to_make_portions(uint64_t amount, uint64_t portions)
{
uint64_t lo, hi, resulthi, resultlo;
lo = mul128(amount, portions, &hi);
if (lo > UINT64_MAX - (STAKING_PORTIONS - 1))
hi++;
lo += STAKING_PORTIONS-1;
div128_32(hi, lo, STAKING_PORTIONS, &resulthi, &resultlo);
div128_64(hi, lo, STAKING_PORTIONS, &resulthi, &resultlo);
return resultlo;
}
static uint64_t get_actual_amount(uint64_t amount, uint32_t portions)
// Returns lowest x such that (staking_requirement * x/STAKING_PORTIONS) >= amount
static uint64_t get_portions_to_make_amount(uint64_t staking_requirement, uint64_t amount)
{
uint64_t lo, hi, resulthi, resultlo;
lo = mul128(amount, STAKING_PORTIONS, &hi);
if (lo > UINT64_MAX - (staking_requirement - 1))
hi++;
lo += staking_requirement-1;
div128_64(hi, lo, staking_requirement, &resulthi, &resultlo);
return resultlo;
}
static uint64_t get_actual_amount(uint64_t amount, uint64_t portions)
{
uint64_t lo, hi, resulthi, resultlo;
lo = mul128(amount, portions, &hi);
div128_32(hi, lo, STAKING_PORTIONS, &resulthi, &resultlo);
div128_64(hi, lo, STAKING_PORTIONS, &resulthi, &resultlo);
return resultlo;
}
@ -2211,22 +2222,22 @@ bool t_rpc_command_executor::prepare_registration()
#endif
size_t number_participants = 1;
uint32_t operating_cost_portions = STAKING_PORTIONS;
uint64_t operating_cost_portions = STAKING_PORTIONS;
bool is_solo_stake = false;
const auto nettype = m_rpc_server->nettype();
std::vector<std::string> addresses;
std::vector<uint32_t> contributions;
std::vector<uint64_t> contributions;
const uint64_t block_height = std::max(res.height, res.target_height);
const uint64_t staking_requirement =
std::max(service_nodes::get_staking_requirement(nettype, block_height),
service_nodes::get_staking_requirement(nettype, block_height + 30 * 24)); // allow 1 day
uint32_t portions_remaining = STAKING_PORTIONS;
uint64_t portions_remaining = STAKING_PORTIONS;
uint64_t total_reserved_contributions = 0;
// anything less than DUST will be added to operator stake
const uint64_t DUST = (staking_requirement / STAKING_PORTIONS + 1) * (MAX_NUMBER_OF_CONTRIBUTORS - 1);
const uint64_t DUST = MAX_NUMBER_OF_CONTRIBUTORS;
std::cout << "Current staking requirement: " << cryptonote::print_money(staking_requirement) << " " << cryptonote::get_unit() << std::endl;
@ -2287,7 +2298,7 @@ bool t_rpc_command_executor::prepare_registration()
operating_cost_portions = (operating_cost_percent / 100.0) * STAKING_PORTIONS;
const uint32_t min_contribution_portions = std::min(portions_remaining, MIN_PORTIONS);
const uint64_t min_contribution_portions = std::min(portions_remaining, MIN_PORTIONS);
const uint64_t min_contribution = get_amount_to_make_portions(staking_requirement, min_contribution_portions);
@ -2303,10 +2314,7 @@ bool t_rpc_command_executor::prepare_registration()
mlog_set_categories(categories.c_str());
return true;
}
uint64_t lo, hi, resultlo, resulthi;
lo = mul128(operator_cut, STAKING_PORTIONS, &hi);
div128_64(hi, lo, staking_requirement, &resulthi, &resultlo);
uint32_t portions = resultlo;
uint64_t portions = get_portions_to_make_amount(staking_requirement, operator_cut);
if(portions < min_contribution_portions)
{
std::cout << "The operator needs to contribute at least 25% of the stake requirement (" << cryptonote::print_money(min_contribution) << " " << cryptonote::get_unit() << "). Aborted." << std::endl;
@ -2364,10 +2372,7 @@ bool t_rpc_command_executor::prepare_registration()
mlog_set_categories(categories.c_str());
return true;
}
uint64_t lo, hi, resultlo, resulthi;
lo = mul128(contribution_amount, STAKING_PORTIONS, &hi);
div128_64(hi, lo, staking_requirement, &resulthi, &resultlo);
uint32_t portions = resultlo;
uint64_t portions = get_portions_to_make_amount(staking_requirement, contribution_amount);
if (portions < min_contribution_portions)
{
std::cout << "Invalid amount. Aborted." << std::endl;
@ -2456,11 +2461,18 @@ bool t_rpc_command_executor::prepare_registration()
uint64_t amount = get_actual_amount(staking_requirement, contributions[i]);
if (amount_left <= DUST && i == 0)
amount += amount_left; // add dust to the operator.
printf("%-16s%-9s%-19s%-.2f\n", participant_name.c_str(), addresses[i].substr(0,6).c_str(), cryptonote::print_money(amount).c_str(), (double)contributions[i] * 100 / STAKING_PORTIONS);
printf("%-16s%-9s%-19s%-.9f\n", participant_name.c_str(), addresses[i].substr(0,6).c_str(), cryptonote::print_money(amount).c_str(), (double)contributions[i] * 100 / STAKING_PORTIONS);
}
if (amount_left > DUST)
{
printf("%-16s%-9s%-19s%-.2f\n", "(open)", "", cryptonote::print_money(amount_left).c_str(), amount_left * 100.0 / staking_requirement);
}
else if (amount_left > 0)
{
std::cout << "\nActual amounts may differ slightly from specification. This is due to\n" << std::endl;
std::cout << "limitations on the way fractions are represented internally.\n" << std::endl;
}
std::cout << "\nBecause the actual requirement will depend on the time that you register, the\n";
std::cout << "amounts shown here are used as a guide only, and the percentages will remain\n";

View File

@ -2383,7 +2383,7 @@ namespace cryptonote
uint64_t total_contributed;
uint64_t total_reserved;
uint64_t staking_requirement;
uint32_t portions_for_operator;
uint64_t portions_for_operator;
std::string operator_address;
BEGIN_KV_SERIALIZE_MAP()

View File

@ -4712,7 +4712,7 @@ bool simple_wallet::register_service_node_main(
uint64_t expiration_timestamp,
const cryptonote::account_public_address& address,
uint32_t priority,
const std::vector<uint32_t>& portions,
const std::vector<uint64_t>& portions,
const std::vector<uint8_t>& extra,
std::set<uint32_t>& subaddr_indices,
bool autostake)
@ -4723,11 +4723,11 @@ bool simple_wallet::register_service_node_main(
{
if (!try_connect_to_daemon(true))
return true;
uint64_t fetched_blocks;
m_wallet->refresh(0, fetched_blocks);
}
uint64_t fetched_blocks;
m_wallet->refresh(0, fetched_blocks);
if (expiration_timestamp <= (uint64_t)time(nullptr) + 600 /* 10 minutes */)
{
fail_msg_writer() << tr("This registration has expired.");
@ -4798,7 +4798,7 @@ bool simple_wallet::register_service_node_main(
service_nodes::get_staking_requirement(m_wallet->nettype(), bc_height+STAKING_REQUIREMENT_LOCK_BLOCKS_EXCESS)
);
const uint64_t DUST = (expected_staking_requirement / STAKING_PORTIONS + 1) * (MAX_NUMBER_OF_CONTRIBUTORS - 1);
const uint64_t DUST = MAX_NUMBER_OF_CONTRIBUTORS;
uint64_t amount_left = expected_staking_requirement;
uint64_t amount_payable_by_operator = 0;
@ -4806,7 +4806,7 @@ bool simple_wallet::register_service_node_main(
{
uint64_t hi, lo, resulthi, resultlo;
lo = mul128(expected_staking_requirement, portions[i], &hi);
div128_32(hi, lo, STAKING_PORTIONS, &resulthi, &resultlo);
div128_64(hi, lo, STAKING_PORTIONS, &resulthi, &resultlo);
if (i == 0)
amount_payable_by_operator += resultlo;
amount_left -= resultlo;
@ -4979,8 +4979,8 @@ bool simple_wallet::register_service_node(const std::vector<std::string> &args_)
std::vector<std::string> address_portions_args(local_args.begin(), local_args.begin() + local_args.size() - 3);
std::vector<cryptonote::account_public_address> addresses;
std::vector<uint32_t> portions;
uint32_t portions_for_operator;
std::vector<uint64_t> portions;
uint64_t portions_for_operator;
bool autostake;
if (!service_nodes::convert_registration_args(m_wallet->nettype(), address_portions_args, addresses, portions, portions_for_operator, autostake))
{
@ -5090,11 +5090,11 @@ bool simple_wallet::stake_main(
{
if (!try_connect_to_daemon(true))
return true;
uint64_t fetched_blocks;
m_wallet->refresh(0, fetched_blocks);
}
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 locked_blocks = staking_requirement_lock_blocks + STAKING_REQUIREMENT_LOCK_BLOCKS_EXCESS;
@ -5151,7 +5151,7 @@ bool simple_wallet::stake_main(
const auto& snode_info = response.service_node_states.front();
bool full = false;
const uint64_t DUST = (snode_info.staking_requirement / STAKING_PORTIONS + 1) * (MAX_NUMBER_OF_CONTRIBUTORS - 1);
const uint64_t DUST = MAX_NUMBER_OF_CONTRIBUTORS;
if (amount == 0)
amount = snode_info.staking_requirement * amount_fraction;
@ -5196,18 +5196,22 @@ bool simple_wallet::stake_main(
if (amount < must_contrib_total)
{
success_msg_writer() << tr("Warning: You must contribute ") << print_money(must_contrib_total) << tr(" loki to meet your registration requirements for this service node");
success_msg_writer() << tr("You have only specified ") << print_money(amount);
if (must_contrib_total - amount <= DUST)
if (amount == 0)
{
success_msg_writer() << tr("Seeing as this is only a little bit, amount was increased automatically");
amount = must_contrib_total;
}
else if (autostake)
else
{
if (amount == 0)
success_msg_writer() << tr("You have only specified ") << print_money(amount);
if (must_contrib_total - amount <= DUST)
{
success_msg_writer() << tr("Seeing as this is only a little bit, amount was increased automatically");
amount = must_contrib_total;
else
}
else if (autostake)
{
return true;
}
}
}
}

View File

@ -225,7 +225,7 @@ namespace cryptonote
bool blackballed(const std::vector<std::string>& args);
bool version(const std::vector<std::string>& args);
bool register_service_node_main(const std::vector<std::string>& service_node_key_as_str, uint64_t expiration_timestamp, const cryptonote::account_public_address& address, uint32_t priority, const std::vector<uint32_t>& portions, const std::vector<uint8_t>& extra, std::set<uint32_t>& subaddr_indices, bool autostake);
bool register_service_node_main(const std::vector<std::string>& service_node_key_as_str, uint64_t expiration_timestamp, const cryptonote::account_public_address& address, uint32_t priority, const std::vector<uint64_t>& portions, const std::vector<uint8_t>& extra, std::set<uint32_t>& subaddr_indices, bool autostake);
bool stake_main(const crypto::public_key& service_node_key, const cryptonote::account_public_address& address, uint32_t priority, std::set<uint32_t>& subaddr_indices, uint64_t amount, double amount_fraction, bool autostake);
uint64_t get_daemon_blockchain_height(std::string& err);