wallet: send 0 change to a random address where necessary with rct

If a rct transaction would cause no change to be generated, a zero
change output is added, and sent to a randomly generated address.
This ensures that no transaction will be sent with just one output,
which could cause the receiver to be able to determine which of the
inputs in the sent rings is the real one.
This is very rare, since it requires the sum of outputs to be equal
to the sum of outputs plus the fee, which is now a function of the
last few blocks.
This commit is contained in:
moneromooo-monero 2016-12-07 21:05:50 +00:00
parent 45bb393577
commit 6c44f5c6eb
No known key found for this signature in database
GPG key ID: 686F07454D6CEFC3

View file

@ -3770,12 +3770,22 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
// we still keep a copy, since we want to keep dsts free of change for user feedback purposes // we still keep a copy, since we want to keep dsts free of change for user feedback purposes
std::vector<cryptonote::tx_destination_entry> splitted_dsts = dsts; std::vector<cryptonote::tx_destination_entry> splitted_dsts = dsts;
cryptonote::tx_destination_entry change_dts = AUTO_VAL_INIT(change_dts); cryptonote::tx_destination_entry change_dts = AUTO_VAL_INIT(change_dts);
if (needed_money < found_money) change_dts.amount = found_money - needed_money;
if (change_dts.amount == 0)
{
// If the change is 0, send it to a random address, to avoid confusing
// the sender with a 0 amount output. We send a 0 amount in order to avoid
// letting the destination be able to work out which of the inputs is the
// real one in our rings
cryptonote::account_base dummy;
dummy.generate();
change_dts.addr = dummy.get_keys().m_account_address;
}
else
{ {
change_dts.addr = m_account.get_keys().m_account_address; change_dts.addr = m_account.get_keys().m_account_address;
change_dts.amount = found_money - needed_money;
splitted_dsts.push_back(change_dts);
} }
splitted_dsts.push_back(change_dts);
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, true); bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), sources, splitted_dsts, extra, tx, unlock_time, tx_key, true);