from hard fork 2, all outputs must be decomposed
The wallet decomposes fully as of now too.
This commit is contained in:
parent
90ccad1236
commit
ac90d488e7
6 changed files with 67 additions and 48 deletions
|
@ -1972,6 +1972,23 @@ bool Blockchain::check_tx_inputs(const transaction& tx, uint64_t& max_used_block
|
||||||
return true;
|
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
|
bool Blockchain::have_tx_keyimges_as_spent(const transaction &tx) const
|
||||||
{
|
{
|
||||||
LOG_PRINT_L3("Blockchain::" << __func__);
|
LOG_PRINT_L3("Blockchain::" << __func__);
|
||||||
|
|
|
@ -134,6 +134,7 @@ namespace cryptonote
|
||||||
bool store_blockchain();
|
bool store_blockchain();
|
||||||
|
|
||||||
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_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);
|
||||||
uint64_t get_current_cumulative_blocksize_limit() const;
|
uint64_t get_current_cumulative_blocksize_limit() const;
|
||||||
bool is_storing_blockchain()const{return m_is_blockchain_storing;}
|
bool is_storing_blockchain()const{return m_is_blockchain_storing;}
|
||||||
uint64_t block_difficulty(uint64_t i) const;
|
uint64_t block_difficulty(uint64_t i) const;
|
||||||
|
|
|
@ -141,7 +141,7 @@ namespace cryptonote
|
||||||
block_reward += fee;
|
block_reward += fee;
|
||||||
|
|
||||||
std::vector<uint64_t> out_amounts;
|
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_chunk) { out_amounts.push_back(a_chunk); },
|
||||||
[&out_amounts](uint64_t a_dust) { out_amounts.push_back(a_dust); });
|
[&out_amounts](uint64_t a_dust) { out_amounts.push_back(a_dust); });
|
||||||
|
|
||||||
|
|
|
@ -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;
|
crypto::hash max_used_block_id = null_hash;
|
||||||
uint64_t max_used_block_height = 0;
|
uint64_t max_used_block_height = 0;
|
||||||
|
|
|
@ -1143,7 +1143,7 @@ uint64_t wallet2::select_transfers(uint64_t needed_money, bool add_dust, uint64_
|
||||||
const transfer_details& td = m_transfers[i];
|
const transfer_details& td = m_transfers[i];
|
||||||
if (!td.m_spent && is_transfer_unlocked(td))
|
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);
|
unused_transfers_indices.push_back(i);
|
||||||
else
|
else
|
||||||
unused_dust_indices.push_back(i);
|
unused_dust_indices.push_back(i);
|
||||||
|
@ -1572,14 +1572,17 @@ void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_ent
|
||||||
change_dts.amount = found_money - needed_money;
|
change_dts.amount = found_money - needed_money;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<cryptonote::tx_destination_entry> splitted_dsts, dust_dsts;
|
||||||
uint64_t dust = 0;
|
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_dsts);
|
||||||
destination_split_strategy(dsts, change_dts, dust_policy.dust_threshold, splitted_dsts, dust);
|
BOOST_FOREACH(auto& d, dust_dsts) {
|
||||||
THROW_WALLET_EXCEPTION_IF(dust_policy.dust_threshold < dust, error::wallet_internal_error, "invalid dust value: dust = " +
|
THROW_WALLET_EXCEPTION_IF(dust_policy.dust_threshold < d.amount, error::wallet_internal_error, "invalid dust value: dust = " +
|
||||||
std::to_string(dust) + ", dust_threshold = " + std::to_string(dust_policy.dust_threshold));
|
std::to_string(d.amount) + ", dust_threshold = " + std::to_string(dust_policy.dust_threshold));
|
||||||
if (0 != dust && !dust_policy.add_to_fee)
|
}
|
||||||
{
|
BOOST_FOREACH(auto& d, dust_dsts) {
|
||||||
splitted_dsts.push_back(cryptonote::tx_destination_entry(dust, dust_policy.addr_for_dust));
|
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;
|
crypto::secret_key tx_key;
|
||||||
|
@ -1669,7 +1672,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
||||||
const transfer_details& td = m_transfers[i];
|
const transfer_details& td = m_transfers[i];
|
||||||
if (!td.m_spent && is_transfer_unlocked(td))
|
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);
|
unused_transfers_indices.push_back(i);
|
||||||
else
|
else
|
||||||
unused_dust_indices.push_back(i);
|
unused_dust_indices.push_back(i);
|
||||||
|
@ -1923,11 +1926,12 @@ void wallet2::transfer_dust(size_t num_outputs, uint64_t unlock_time, uint64_t n
|
||||||
if (dust_policy.dust_threshold > 0)
|
if (dust_policy.dust_threshold > 0)
|
||||||
money_back = money_back - money_back % dust_policy.dust_threshold;
|
money_back = money_back - money_back % dust_policy.dust_threshold;
|
||||||
dsts.push_back(cryptonote::tx_destination_entry(money_back, m_account_public_address));
|
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, dust;
|
||||||
std::vector<cryptonote::tx_destination_entry> splitted_dsts;
|
|
||||||
destination_split_strategy(dsts, change_dts, dust_policy.dust_threshold, 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 = " +
|
BOOST_FOREACH(auto& d, dust) {
|
||||||
std::to_string(dust) + ", dust_threshold = " + std::to_string(dust_policy.dust_threshold));
|
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;
|
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);
|
bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), sources, splitted_dsts, extra, tx, unlock_time, tx_key);
|
||||||
|
@ -1945,7 +1949,7 @@ void wallet2::transfer_dust(size_t num_outputs, uint64_t unlock_time, uint64_t n
|
||||||
|
|
||||||
ptx.key_images = key_images;
|
ptx.key_images = key_images;
|
||||||
ptx.fee = money - money_back;
|
ptx.fee = money - money_back;
|
||||||
ptx.dust = dust;
|
ptx.dust = 0;
|
||||||
ptx.tx = tx;
|
ptx.tx = tx;
|
||||||
ptx.change_dts = change_dts;
|
ptx.change_dts = change_dts;
|
||||||
ptx.selected_transfers = selected_transfers;
|
ptx.selected_transfers = selected_transfers;
|
||||||
|
@ -1961,7 +1965,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)
|
for (transfer_container::const_iterator i = m_transfers.begin(); i != m_transfers.end(); ++i)
|
||||||
{
|
{
|
||||||
const transfer_details& td = *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++;
|
num_dust_outputs++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -400,48 +400,36 @@ namespace tools
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
inline void digit_split_strategy(const std::vector<cryptonote::tx_destination_entry>& dsts,
|
inline void digit_split_strategy(const std::vector<cryptonote::tx_destination_entry>& dsts,
|
||||||
const cryptonote::tx_destination_entry& change_dst, uint64_t dust_threshold,
|
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();
|
splitted_dsts.clear();
|
||||||
dust = 0;
|
dust_dsts.clear();
|
||||||
|
|
||||||
BOOST_FOREACH(auto& de, dsts)
|
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 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)); } );
|
[&](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,
|
cryptonote::decompose_amount_into_digits(change_dst.amount, 0,
|
||||||
[&](uint64_t chunk) { splitted_dsts.push_back(cryptonote::tx_destination_entry(chunk, change_dst.addr)); },
|
[&](uint64_t chunk) {
|
||||||
[&](uint64_t a_dust) { dust = a_dust; } );
|
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,
|
inline void null_split_strategy(const std::vector<cryptonote::tx_destination_entry>& dsts,
|
||||||
const cryptonote::tx_destination_entry& change_dst, uint64_t dust_threshold,
|
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;
|
splitted_dsts = dsts;
|
||||||
|
|
||||||
dust = 0;
|
dust_dsts.clear();
|
||||||
uint64_t change = change_dst.amount;
|
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)
|
if (0 != change)
|
||||||
{
|
{
|
||||||
|
@ -577,14 +565,17 @@ namespace tools
|
||||||
change_dts.amount = found_money - needed_money;
|
change_dts.amount = found_money - needed_money;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<cryptonote::tx_destination_entry> splitted_dsts, dust_dsts;
|
||||||
uint64_t dust = 0;
|
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_dsts);
|
||||||
destination_split_strategy(dsts, change_dts, dust_policy.dust_threshold, splitted_dsts, dust);
|
BOOST_FOREACH(auto& d, dust_dsts) {
|
||||||
THROW_WALLET_EXCEPTION_IF(dust_policy.dust_threshold < dust, error::wallet_internal_error, "invalid dust value: dust = " +
|
THROW_WALLET_EXCEPTION_IF(dust_policy.dust_threshold < d.amount, error::wallet_internal_error, "invalid dust value: dust = " +
|
||||||
std::to_string(dust) + ", dust_threshold = " + std::to_string(dust_policy.dust_threshold));
|
std::to_string(d.amount) + ", dust_threshold = " + std::to_string(dust_policy.dust_threshold));
|
||||||
if (0 != dust && !dust_policy.add_to_fee)
|
}
|
||||||
{
|
BOOST_FOREACH(auto& d, dust_dsts) {
|
||||||
splitted_dsts.push_back(cryptonote::tx_destination_entry(dust, dust_policy.addr_for_dust));
|
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;
|
crypto::secret_key tx_key;
|
||||||
|
|
Loading…
Reference in a new issue