mirror of https://github.com/oxen-io/oxen-core.git
service nodes: changed portions to 64 bits
also miner fixes to simplewallet behaviour and interactive registration prompt
This commit is contained in:
parent
1977b01cb3
commit
78b7fccfbf
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue