Merge recent changes from upstream into branch
This commit is contained in:
commit
d23d46356a
|
@ -15,6 +15,10 @@
|
|||
void IGDstartelt(void * d, const char * name, int l)
|
||||
{
|
||||
struct IGDdatas * datas = (struct IGDdatas *)d;
|
||||
if (l >= MINIUPNPC_URL_MAXSIZE) {
|
||||
printf("Attempt to exploit miniupnpc buffer overflow\n");
|
||||
l = MINIUPNPC_URL_MAXSIZE - 1;
|
||||
}
|
||||
memcpy( datas->cureltname, name, l);
|
||||
datas->cureltname[l] = '\0';
|
||||
datas->level++;
|
||||
|
|
|
@ -118,6 +118,7 @@ namespace config
|
|||
uint64_t const DEFAULT_FEE_ATOMIC_XMR_PER_KB = 500; // Just a placeholder! Change me!
|
||||
uint8_t const FEE_CALCULATION_MAX_RETRIES = 10;
|
||||
uint64_t const DEFAULT_DUST_THRESHOLD = ((uint64_t)10000000000); // pow(10, 10)
|
||||
uint64_t const BASE_REWARD_CLAMP_THRESHOLD = ((uint64_t)100000000); // pow(10, 8)
|
||||
std::string const P2P_REMOTE_DEBUG_TRUSTED_PUB_KEY = "0000000000000000000000000000000000000000000000000000000000000000";
|
||||
|
||||
uint64_t const CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX = 18;
|
||||
|
|
|
@ -890,6 +890,14 @@ bool Blockchain::validate_miner_transaction(const block& b, size_t cumulative_bl
|
|||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// from hard fork 2, since a miner can claim less than the full block reward, we update the base_reward
|
||||
// to show the amount of coins that were actually generated, the remainder will be pushed back for later
|
||||
// emission. This modifies the emission curve very slightly.
|
||||
CHECK_AND_ASSERT_MES(money_in_use - fee <= base_reward, false, "base reward calculation bug");
|
||||
base_reward = money_in_use - fee;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
|
@ -1010,7 +1018,7 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m
|
|||
* size is known, the miner transaction is updated to reflect the correct
|
||||
* amount (fees + block reward).
|
||||
*/
|
||||
bool r = construct_miner_tx(height, median_size, already_generated_coins, txs_size, fee, miner_address, b.miner_tx, ex_nonce, 11);
|
||||
bool r = construct_miner_tx(height, median_size, already_generated_coins, txs_size, fee, miner_address, b.miner_tx, ex_nonce, 11, m_hardfork->get_current_version());
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to construc miner tx, first chance");
|
||||
size_t cumulative_size = txs_size + get_object_blobsize(b.miner_tx);
|
||||
#if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
|
||||
|
@ -1019,7 +1027,7 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m
|
|||
#endif
|
||||
for (size_t try_count = 0; try_count != 10; ++try_count)
|
||||
{
|
||||
r = construct_miner_tx(height, median_size, already_generated_coins, cumulative_size, fee, miner_address, b.miner_tx, ex_nonce, 11);
|
||||
r = construct_miner_tx(height, median_size, already_generated_coins, cumulative_size, fee, miner_address, b.miner_tx, ex_nonce, 11, m_hardfork->get_current_version());
|
||||
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to construc miner tx, second chance");
|
||||
size_t coinbase_blob_size = get_object_blobsize(b.miner_tx);
|
||||
|
@ -1911,6 +1919,23 @@ bool Blockchain::check_tx_inputs(const transaction& tx, uint64_t& max_used_block
|
|||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool Blockchain::check_tx_outputs(const transaction& tx)
|
||||
{
|
||||
LOG_PRINT_L3("Blockchain::" << __func__);
|
||||
CRITICAL_REGION_LOCAL(m_blockchain_lock);
|
||||
|
||||
// from hard fork 2, we forbid dust and compound outputs
|
||||
if (m_hardfork->get_current_version() >= 2) {
|
||||
BOOST_FOREACH(auto &o, tx.vout) {
|
||||
if (!is_valid_decomposed_amount(o.amount)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool Blockchain::have_tx_keyimges_as_spent(const transaction &tx) const
|
||||
{
|
||||
LOG_PRINT_L3("Blockchain::" << __func__);
|
||||
|
|
|
@ -475,6 +475,8 @@ namespace cryptonote
|
|||
*/
|
||||
bool check_tx_inputs(const transaction& tx, uint64_t& pmax_used_block_height, crypto::hash& max_used_block_id, bool kept_by_block = false);
|
||||
|
||||
bool check_tx_outputs(const transaction& tx);
|
||||
|
||||
/**
|
||||
* @brief gets the blocksize limit based on recent blocks
|
||||
*
|
||||
|
|
|
@ -40,6 +40,29 @@ using namespace epee;
|
|||
|
||||
#define ENCRYPTED_PAYMENT_ID_TAIL 0x8d
|
||||
|
||||
static const uint64_t valid_decomposed_outputs[] = {
|
||||
(uint64_t)1, (uint64_t)2, (uint64_t)3, (uint64_t)4, (uint64_t)5, (uint64_t)6, (uint64_t)7, (uint64_t)8, (uint64_t)9, // 1 piconero
|
||||
(uint64_t)10, (uint64_t)20, (uint64_t)30, (uint64_t)40, (uint64_t)50, (uint64_t)60, (uint64_t)70, (uint64_t)80, (uint64_t)90,
|
||||
(uint64_t)100, (uint64_t)200, (uint64_t)300, (uint64_t)400, (uint64_t)500, (uint64_t)600, (uint64_t)700, (uint64_t)800, (uint64_t)900,
|
||||
(uint64_t)1000, (uint64_t)2000, (uint64_t)3000, (uint64_t)4000, (uint64_t)5000, (uint64_t)6000, (uint64_t)7000, (uint64_t)8000, (uint64_t)9000,
|
||||
(uint64_t)10000, (uint64_t)20000, (uint64_t)30000, (uint64_t)40000, (uint64_t)50000, (uint64_t)60000, (uint64_t)70000, (uint64_t)80000, (uint64_t)90000,
|
||||
(uint64_t)100000, (uint64_t)200000, (uint64_t)300000, (uint64_t)400000, (uint64_t)500000, (uint64_t)600000, (uint64_t)700000, (uint64_t)800000, (uint64_t)900000,
|
||||
(uint64_t)1000000, (uint64_t)2000000, (uint64_t)3000000, (uint64_t)4000000, (uint64_t)5000000, (uint64_t)6000000, (uint64_t)7000000, (uint64_t)8000000, (uint64_t)9000000, // 1 micronero
|
||||
(uint64_t)10000000, (uint64_t)20000000, (uint64_t)30000000, (uint64_t)40000000, (uint64_t)50000000, (uint64_t)60000000, (uint64_t)70000000, (uint64_t)80000000, (uint64_t)90000000,
|
||||
(uint64_t)100000000, (uint64_t)200000000, (uint64_t)300000000, (uint64_t)400000000, (uint64_t)500000000, (uint64_t)600000000, (uint64_t)700000000, (uint64_t)800000000, (uint64_t)900000000,
|
||||
(uint64_t)1000000000, (uint64_t)2000000000, (uint64_t)3000000000, (uint64_t)4000000000, (uint64_t)5000000000, (uint64_t)6000000000, (uint64_t)7000000000, (uint64_t)8000000000, (uint64_t)9000000000,
|
||||
(uint64_t)10000000000, (uint64_t)20000000000, (uint64_t)30000000000, (uint64_t)40000000000, (uint64_t)50000000000, (uint64_t)60000000000, (uint64_t)70000000000, (uint64_t)80000000000, (uint64_t)90000000000,
|
||||
(uint64_t)100000000000, (uint64_t)200000000000, (uint64_t)300000000000, (uint64_t)400000000000, (uint64_t)500000000000, (uint64_t)600000000000, (uint64_t)700000000000, (uint64_t)800000000000, (uint64_t)900000000000,
|
||||
(uint64_t)1000000000000, (uint64_t)2000000000000, (uint64_t)3000000000000, (uint64_t)4000000000000, (uint64_t)5000000000000, (uint64_t)6000000000000, (uint64_t)7000000000000, (uint64_t)8000000000000, (uint64_t)9000000000000, // 1 monero
|
||||
(uint64_t)10000000000000, (uint64_t)20000000000000, (uint64_t)30000000000000, (uint64_t)40000000000000, (uint64_t)50000000000000, (uint64_t)60000000000000, (uint64_t)70000000000000, (uint64_t)80000000000000, (uint64_t)90000000000000,
|
||||
(uint64_t)100000000000000, (uint64_t)200000000000000, (uint64_t)300000000000000, (uint64_t)400000000000000, (uint64_t)500000000000000, (uint64_t)600000000000000, (uint64_t)700000000000000, (uint64_t)800000000000000, (uint64_t)900000000000000,
|
||||
(uint64_t)1000000000000000, (uint64_t)2000000000000000, (uint64_t)3000000000000000, (uint64_t)4000000000000000, (uint64_t)5000000000000000, (uint64_t)6000000000000000, (uint64_t)7000000000000000, (uint64_t)8000000000000000, (uint64_t)9000000000000000,
|
||||
(uint64_t)10000000000000000, (uint64_t)20000000000000000, (uint64_t)30000000000000000, (uint64_t)40000000000000000, (uint64_t)50000000000000000, (uint64_t)60000000000000000, (uint64_t)70000000000000000, (uint64_t)80000000000000000, (uint64_t)90000000000000000,
|
||||
(uint64_t)100000000000000000, (uint64_t)200000000000000000, (uint64_t)300000000000000000, (uint64_t)400000000000000000, (uint64_t)500000000000000000, (uint64_t)600000000000000000, (uint64_t)700000000000000000, (uint64_t)800000000000000000, (uint64_t)900000000000000000,
|
||||
(uint64_t)1000000000000000000, (uint64_t)2000000000000000000, (uint64_t)3000000000000000000, (uint64_t)4000000000000000000, (uint64_t)5000000000000000000, (uint64_t)6000000000000000000, (uint64_t)7000000000000000000, (uint64_t)8000000000000000000, (uint64_t)9000000000000000000, // 1 meganero
|
||||
(uint64_t)10000000000000000000ull
|
||||
};
|
||||
|
||||
namespace cryptonote
|
||||
{
|
||||
//---------------------------------------------------------------
|
||||
|
@ -82,7 +105,7 @@ namespace cryptonote
|
|||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool construct_miner_tx(size_t height, size_t median_size, uint64_t already_generated_coins, size_t current_block_size, uint64_t fee, const account_public_address &miner_address, transaction& tx, const blobdata& extra_nonce, size_t max_outs) {
|
||||
bool construct_miner_tx(size_t height, size_t median_size, uint64_t already_generated_coins, size_t current_block_size, uint64_t fee, const account_public_address &miner_address, transaction& tx, const blobdata& extra_nonce, size_t max_outs, uint8_t hard_fork_version) {
|
||||
tx.vin.clear();
|
||||
tx.vout.clear();
|
||||
tx.extra.clear();
|
||||
|
@ -102,6 +125,15 @@ namespace cryptonote
|
|||
LOG_PRINT_L0("Block is too big");
|
||||
return false;
|
||||
}
|
||||
|
||||
// from hard fork 2, we cut out the low significant digits. This makes the tx smaller, and
|
||||
// keeps the paid amount almost the same. The unpaid remainder gets pushed back to the
|
||||
// emission schedule
|
||||
if (hard_fork_version >= 2)
|
||||
{
|
||||
block_reward = block_reward - block_reward % ::config::BASE_REWARD_CLAMP_THRESHOLD;
|
||||
}
|
||||
|
||||
#if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
|
||||
LOG_PRINT_L1("Creating block template: reward " << block_reward <<
|
||||
", fee " << fee)
|
||||
|
@ -109,7 +141,7 @@ namespace cryptonote
|
|||
block_reward += fee;
|
||||
|
||||
std::vector<uint64_t> out_amounts;
|
||||
decompose_amount_into_digits(block_reward, ::config::DEFAULT_DUST_THRESHOLD,
|
||||
decompose_amount_into_digits(block_reward, hard_fork_version >= 2 ? 0 : ::config::DEFAULT_DUST_THRESHOLD,
|
||||
[&out_amounts](uint64_t a_chunk) { out_amounts.push_back(a_chunk); },
|
||||
[&out_amounts](uint64_t a_dust) { out_amounts.push_back(a_dust); });
|
||||
|
||||
|
@ -923,4 +955,11 @@ namespace cryptonote
|
|||
return get_tx_tree_hash(txs_ids);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool is_valid_decomposed_amount(uint64_t amount)
|
||||
{
|
||||
const uint64_t *begin = valid_decomposed_outputs;
|
||||
const uint64_t *end = valid_decomposed_outputs + sizeof(valid_decomposed_outputs) / sizeof(valid_decomposed_outputs[0]);
|
||||
return std::binary_search(begin, end, amount);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace cryptonote
|
|||
crypto::hash get_transaction_prefix_hash(const transaction_prefix& tx);
|
||||
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash);
|
||||
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx);
|
||||
bool construct_miner_tx(size_t height, size_t median_size, uint64_t already_generated_coins, size_t current_block_size, uint64_t fee, const account_public_address &miner_address, transaction& tx, const blobdata& extra_nonce = blobdata(), size_t max_outs = 1);
|
||||
bool construct_miner_tx(size_t height, size_t median_size, uint64_t already_generated_coins, size_t current_block_size, uint64_t fee, const account_public_address &miner_address, transaction& tx, const blobdata& extra_nonce = blobdata(), size_t max_outs = 1, uint8_t hard_fork_version = 1);
|
||||
bool encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key);
|
||||
bool decrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key);
|
||||
|
||||
|
@ -231,6 +231,7 @@ namespace cryptonote
|
|||
void get_tx_tree_hash(const std::vector<crypto::hash>& tx_hashes, crypto::hash& h);
|
||||
crypto::hash get_tx_tree_hash(const std::vector<crypto::hash>& tx_hashes);
|
||||
crypto::hash get_tx_tree_hash(const block& b);
|
||||
bool is_valid_decomposed_amount(uint64_t amount);
|
||||
|
||||
#define CHECKED_GET_SPECIFIC_VARIANT(variant_var, specific_type, variable_name, fail_return_val) \
|
||||
CHECK_AND_ASSERT_MES(variant_var.type() == typeid(specific_type), fail_return_val, "wrong variant type: " << variant_var.type().name() << ", expected " << typeid(specific_type).name()); \
|
||||
|
|
|
@ -125,6 +125,12 @@ namespace cryptonote
|
|||
}
|
||||
}
|
||||
|
||||
if (!m_blockchain.check_tx_outputs(tx))
|
||||
{
|
||||
LOG_PRINT_L1("Transaction with id= "<< id << " has at least one invalid outout");
|
||||
tvc.m_verifivation_failed = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
crypto::hash max_used_block_id = null_hash;
|
||||
uint64_t max_used_block_height = 0;
|
||||
|
|
|
@ -76,7 +76,7 @@ typedef cryptonote::simple_wallet sw;
|
|||
|
||||
unsigned int epee::g_test_dbg_lock_sleep = 0;
|
||||
|
||||
#define DEFAULT_MIX 3
|
||||
#define DEFAULT_MIX 4
|
||||
|
||||
namespace
|
||||
{
|
||||
|
@ -94,6 +94,7 @@ namespace
|
|||
const command_line::arg_descriptor<std::string> arg_log_file = {"log-file", sw::tr("Specify log file"), ""};
|
||||
const command_line::arg_descriptor<bool> arg_testnet = {"testnet", sw::tr("Used to deploy test nets. The daemon must be launched with --testnet flag"), false};
|
||||
const command_line::arg_descriptor<bool> arg_restricted = {"restricted-rpc", sw::tr("Restricts RPC to view only commands"), false};
|
||||
const command_line::arg_descriptor<bool> arg_trusted_daemon = {"trusted-daemon", sw::tr("Enable commands which rely on a trusted daemon"), false};
|
||||
|
||||
const command_line::arg_descriptor< std::vector<std::string> > arg_command = {"command", ""};
|
||||
|
||||
|
@ -709,6 +710,7 @@ void simple_wallet::handle_command_line(const boost::program_options::variables_
|
|||
m_electrum_seed = command_line::get_arg(vm, arg_electrum_seed);
|
||||
m_restore_deterministic_wallet = command_line::get_arg(vm, arg_restore_deterministic_wallet);
|
||||
m_non_deterministic = command_line::get_arg(vm, arg_non_deterministic);
|
||||
m_trusted_daemon = command_line::get_arg(vm, arg_trusted_daemon);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::try_connect_to_daemon()
|
||||
|
@ -1324,6 +1326,12 @@ bool simple_wallet::show_blockchain_height(const std::vector<std::string>& args)
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::rescan_spent(const std::vector<std::string> &args)
|
||||
{
|
||||
if (!m_trusted_daemon)
|
||||
{
|
||||
fail_msg_writer() << tr("This command assume a trusted daemon. Enable with --trusted-daemon");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!try_connect_to_daemon())
|
||||
return true;
|
||||
|
||||
|
@ -1937,6 +1945,7 @@ int main(int argc, char* argv[])
|
|||
command_line::add_arg(desc_params, arg_electrum_seed );
|
||||
command_line::add_arg(desc_params, arg_testnet);
|
||||
command_line::add_arg(desc_params, arg_restricted);
|
||||
command_line::add_arg(desc_params, arg_trusted_daemon);
|
||||
|
||||
RPC::Wallet::init_options(desc_params);
|
||||
|
||||
|
|
|
@ -213,6 +213,7 @@ namespace cryptonote
|
|||
crypto::secret_key m_recovery_key; // recovery key (used as random for wallet gen)
|
||||
bool m_restore_deterministic_wallet; // recover flag
|
||||
bool m_non_deterministic; // old 2-random generation
|
||||
bool m_trusted_daemon;
|
||||
|
||||
std::string m_daemon_address;
|
||||
std::string m_daemon_host;
|
||||
|
|
|
@ -1188,7 +1188,7 @@ uint64_t wallet2::select_transfers(uint64_t needed_money, bool add_dust, uint64_
|
|||
const transfer_details& td = m_transfers[i];
|
||||
if (!td.m_spent && is_transfer_unlocked(td))
|
||||
{
|
||||
if (dust < td.amount())
|
||||
if (dust < td.amount() && is_valid_decomposed_amount(td.amount()))
|
||||
unused_transfers_indices.push_back(i);
|
||||
else
|
||||
unused_dust_indices.push_back(i);
|
||||
|
@ -1643,14 +1643,17 @@ void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_ent
|
|||
change_dts.amount = found_money - needed_money;
|
||||
}
|
||||
|
||||
std::vector<cryptonote::tx_destination_entry> splitted_dsts, dust_dsts;
|
||||
uint64_t dust = 0;
|
||||
std::vector<cryptonote::tx_destination_entry> splitted_dsts;
|
||||
destination_split_strategy(dsts, change_dts, dust_policy.dust_threshold, splitted_dsts, dust);
|
||||
THROW_WALLET_EXCEPTION_IF(dust_policy.dust_threshold < dust, error::wallet_internal_error, "invalid dust value: dust = " +
|
||||
std::to_string(dust) + ", dust_threshold = " + std::to_string(dust_policy.dust_threshold));
|
||||
if (0 != dust && !dust_policy.add_to_fee)
|
||||
{
|
||||
splitted_dsts.push_back(cryptonote::tx_destination_entry(dust, dust_policy.addr_for_dust));
|
||||
destination_split_strategy(dsts, change_dts, dust_policy.dust_threshold, splitted_dsts, dust_dsts);
|
||||
BOOST_FOREACH(auto& d, dust_dsts) {
|
||||
THROW_WALLET_EXCEPTION_IF(dust_policy.dust_threshold < d.amount, error::wallet_internal_error, "invalid dust value: dust = " +
|
||||
std::to_string(d.amount) + ", dust_threshold = " + std::to_string(dust_policy.dust_threshold));
|
||||
}
|
||||
BOOST_FOREACH(auto& d, dust_dsts) {
|
||||
if (!dust_policy.add_to_fee)
|
||||
splitted_dsts.push_back(cryptonote::tx_destination_entry(d.amount, dust_policy.addr_for_dust));
|
||||
dust += d.amount;
|
||||
}
|
||||
|
||||
crypto::secret_key tx_key;
|
||||
|
@ -1740,7 +1743,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|||
const transfer_details& td = m_transfers[i];
|
||||
if (!td.m_spent && is_transfer_unlocked(td))
|
||||
{
|
||||
if (::config::DEFAULT_DUST_THRESHOLD <= td.amount())
|
||||
if (is_valid_decomposed_amount(td.amount()))
|
||||
unused_transfers_indices.push_back(i);
|
||||
else
|
||||
unused_dust_indices.push_back(i);
|
||||
|
@ -1994,11 +1997,12 @@ void wallet2::transfer_dust(size_t num_outputs, uint64_t unlock_time, uint64_t n
|
|||
if (dust_policy.dust_threshold > 0)
|
||||
money_back = money_back - money_back % dust_policy.dust_threshold;
|
||||
dsts.push_back(cryptonote::tx_destination_entry(money_back, m_account_public_address));
|
||||
uint64_t dust = 0;
|
||||
std::vector<cryptonote::tx_destination_entry> splitted_dsts;
|
||||
std::vector<cryptonote::tx_destination_entry> splitted_dsts, dust;
|
||||
destination_split_strategy(dsts, change_dts, dust_policy.dust_threshold, splitted_dsts, dust);
|
||||
THROW_WALLET_EXCEPTION_IF(dust_policy.dust_threshold < dust, error::wallet_internal_error, "invalid dust value: dust = " +
|
||||
std::to_string(dust) + ", dust_threshold = " + std::to_string(dust_policy.dust_threshold));
|
||||
BOOST_FOREACH(auto& d, dust) {
|
||||
THROW_WALLET_EXCEPTION_IF(dust_policy.dust_threshold < d.amount, error::wallet_internal_error, "invalid dust value: dust = " +
|
||||
std::to_string(d.amount) + ", dust_threshold = " + std::to_string(dust_policy.dust_threshold));
|
||||
}
|
||||
|
||||
crypto::secret_key tx_key;
|
||||
bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), sources, splitted_dsts, extra, tx, unlock_time, tx_key);
|
||||
|
@ -2016,7 +2020,7 @@ void wallet2::transfer_dust(size_t num_outputs, uint64_t unlock_time, uint64_t n
|
|||
|
||||
ptx.key_images = key_images;
|
||||
ptx.fee = money - money_back;
|
||||
ptx.dust = dust;
|
||||
ptx.dust = 0;
|
||||
ptx.tx = tx;
|
||||
ptx.change_dts = change_dts;
|
||||
ptx.selected_transfers = selected_transfers;
|
||||
|
@ -2032,7 +2036,7 @@ std::vector<wallet2::pending_tx> wallet2::create_dust_sweep_transactions()
|
|||
for (transfer_container::const_iterator i = m_transfers.begin(); i != m_transfers.end(); ++i)
|
||||
{
|
||||
const transfer_details& td = *i;
|
||||
if (!td.m_spent && td.amount() < dust_policy.dust_threshold && is_transfer_unlocked(td))
|
||||
if (!td.m_spent && (td.amount() < dust_policy.dust_threshold || !is_valid_decomposed_amount(td.amount())) && is_transfer_unlocked(td))
|
||||
{
|
||||
num_dust_outputs++;
|
||||
}
|
||||
|
|
|
@ -423,48 +423,36 @@ namespace tools
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
inline void digit_split_strategy(const std::vector<cryptonote::tx_destination_entry>& dsts,
|
||||
const cryptonote::tx_destination_entry& change_dst, uint64_t dust_threshold,
|
||||
std::vector<cryptonote::tx_destination_entry>& splitted_dsts, uint64_t& dust)
|
||||
std::vector<cryptonote::tx_destination_entry>& splitted_dsts, std::vector<cryptonote::tx_destination_entry> &dust_dsts)
|
||||
{
|
||||
splitted_dsts.clear();
|
||||
dust = 0;
|
||||
dust_dsts.clear();
|
||||
|
||||
BOOST_FOREACH(auto& de, dsts)
|
||||
{
|
||||
cryptonote::decompose_amount_into_digits(de.amount, dust_threshold,
|
||||
cryptonote::decompose_amount_into_digits(de.amount, 0,
|
||||
[&](uint64_t chunk) { splitted_dsts.push_back(cryptonote::tx_destination_entry(chunk, de.addr)); },
|
||||
[&](uint64_t a_dust) { splitted_dsts.push_back(cryptonote::tx_destination_entry(a_dust, de.addr)); } );
|
||||
}
|
||||
|
||||
cryptonote::decompose_amount_into_digits(change_dst.amount, dust_threshold,
|
||||
[&](uint64_t chunk) { splitted_dsts.push_back(cryptonote::tx_destination_entry(chunk, change_dst.addr)); },
|
||||
[&](uint64_t a_dust) { dust = a_dust; } );
|
||||
cryptonote::decompose_amount_into_digits(change_dst.amount, 0,
|
||||
[&](uint64_t chunk) {
|
||||
if (chunk <= dust_threshold)
|
||||
dust_dsts.push_back(cryptonote::tx_destination_entry(chunk, change_dst.addr));
|
||||
else
|
||||
splitted_dsts.push_back(cryptonote::tx_destination_entry(chunk, change_dst.addr));
|
||||
},
|
||||
[&](uint64_t a_dust) { dust_dsts.push_back(cryptonote::tx_destination_entry(a_dust, change_dst.addr)); } );
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
inline void null_split_strategy(const std::vector<cryptonote::tx_destination_entry>& dsts,
|
||||
const cryptonote::tx_destination_entry& change_dst, uint64_t dust_threshold,
|
||||
std::vector<cryptonote::tx_destination_entry>& splitted_dsts, uint64_t& dust)
|
||||
std::vector<cryptonote::tx_destination_entry>& splitted_dsts, std::vector<cryptonote::tx_destination_entry> &dust_dsts)
|
||||
{
|
||||
splitted_dsts = dsts;
|
||||
|
||||
dust = 0;
|
||||
dust_dsts.clear();
|
||||
uint64_t change = change_dst.amount;
|
||||
if (0 < dust_threshold)
|
||||
{
|
||||
for (uint64_t order = 10; order <= 10 * dust_threshold; order *= 10)
|
||||
{
|
||||
uint64_t dust_candidate = change_dst.amount % order;
|
||||
uint64_t change_candidate = (change_dst.amount / order) * order;
|
||||
if (dust_candidate <= dust_threshold)
|
||||
{
|
||||
dust = dust_candidate;
|
||||
change = change_candidate;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (0 != change)
|
||||
{
|
||||
|
@ -622,14 +610,17 @@ namespace tools
|
|||
change_dts.amount = found_money - needed_money;
|
||||
}
|
||||
|
||||
std::vector<cryptonote::tx_destination_entry> splitted_dsts, dust_dsts;
|
||||
uint64_t dust = 0;
|
||||
std::vector<cryptonote::tx_destination_entry> splitted_dsts;
|
||||
destination_split_strategy(dsts, change_dts, dust_policy.dust_threshold, splitted_dsts, dust);
|
||||
THROW_WALLET_EXCEPTION_IF(dust_policy.dust_threshold < dust, error::wallet_internal_error, "invalid dust value: dust = " +
|
||||
std::to_string(dust) + ", dust_threshold = " + std::to_string(dust_policy.dust_threshold));
|
||||
if (0 != dust && !dust_policy.add_to_fee)
|
||||
{
|
||||
splitted_dsts.push_back(cryptonote::tx_destination_entry(dust, dust_policy.addr_for_dust));
|
||||
destination_split_strategy(dsts, change_dts, dust_policy.dust_threshold, splitted_dsts, dust_dsts);
|
||||
BOOST_FOREACH(auto& d, dust_dsts) {
|
||||
THROW_WALLET_EXCEPTION_IF(dust_policy.dust_threshold < d.amount, error::wallet_internal_error, "invalid dust value: dust = " +
|
||||
std::to_string(d.amount) + ", dust_threshold = " + std::to_string(dust_policy.dust_threshold));
|
||||
}
|
||||
BOOST_FOREACH(auto& d, dust_dsts) {
|
||||
if (!dust_policy.add_to_fee)
|
||||
splitted_dsts.push_back(cryptonote::tx_destination_entry(d.amount, dust_policy.addr_for_dust));
|
||||
dust += d.amount;
|
||||
}
|
||||
|
||||
crypto::secret_key tx_key;
|
||||
|
|
Loading…
Reference in New Issue