Merge pull request #5008

c6d38718 core: include a dummy encrypted payment id when no payment is used (moneromooo-monero)
b7441c4a core, wallet: remember original text version of destination address (moneromooo-monero)
a9b1c04a crptonote_core: do not error out sending unparsable extra field (moneromooo-monero)
This commit is contained in:
Riccardo Spagni 2019-01-18 19:12:58 +02:00
commit 4e72384318
No known key found for this signature in database
GPG key ID: 55432DF31CCD4FCD
6 changed files with 93 additions and 26 deletions

View file

@ -226,13 +226,15 @@ namespace cryptonote
std::vector<tx_extra_field> tx_extra_fields; std::vector<tx_extra_field> tx_extra_fields;
if (parse_tx_extra(tx.extra, tx_extra_fields)) if (parse_tx_extra(tx.extra, tx_extra_fields))
{ {
bool add_dummy_payment_id = true;
tx_extra_nonce extra_nonce; tx_extra_nonce extra_nonce;
if (find_tx_extra_field_by_type(tx_extra_fields, extra_nonce)) if (find_tx_extra_field_by_type(tx_extra_fields, extra_nonce))
{ {
crypto::hash8 payment_id = null_hash8; crypto::hash payment_id = null_hash;
if (get_encrypted_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id)) crypto::hash8 payment_id8 = null_hash8;
if (get_encrypted_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id8))
{ {
LOG_PRINT_L2("Encrypting payment id " << payment_id); LOG_PRINT_L2("Encrypting payment id " << payment_id8);
crypto::public_key view_key_pub = get_destination_view_key_pub(destinations, change_addr); crypto::public_key view_key_pub = get_destination_view_key_pub(destinations, change_addr);
if (view_key_pub == null_pkey) if (view_key_pub == null_pkey)
{ {
@ -240,28 +242,60 @@ namespace cryptonote
return false; return false;
} }
if (!hwdev.encrypt_payment_id(payment_id, view_key_pub, tx_key)) if (!hwdev.encrypt_payment_id(payment_id8, view_key_pub, tx_key))
{ {
LOG_ERROR("Failed to encrypt payment id"); LOG_ERROR("Failed to encrypt payment id");
return false; return false;
} }
std::string extra_nonce; std::string extra_nonce;
set_encrypted_payment_id_to_tx_extra_nonce(extra_nonce, payment_id); set_encrypted_payment_id_to_tx_extra_nonce(extra_nonce, payment_id8);
remove_field_from_tx_extra(tx.extra, typeid(tx_extra_nonce)); remove_field_from_tx_extra(tx.extra, typeid(tx_extra_nonce));
if (!add_extra_nonce_to_tx_extra(tx.extra, extra_nonce)) if (!add_extra_nonce_to_tx_extra(tx.extra, extra_nonce))
{ {
LOG_ERROR("Failed to add encrypted payment id to tx extra"); LOG_ERROR("Failed to add encrypted payment id to tx extra");
return false; return false;
} }
LOG_PRINT_L1("Encrypted payment ID: " << payment_id); LOG_PRINT_L1("Encrypted payment ID: " << payment_id8);
add_dummy_payment_id = false;
}
else if (get_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id))
{
add_dummy_payment_id = false;
}
}
// we don't add one if we've got more than the usual 1 destination plus change
if (destinations.size() > 2)
add_dummy_payment_id = false;
if (add_dummy_payment_id)
{
// if we have neither long nor short payment id, add a dummy short one,
// this should end up being the vast majority of txes as time goes on
std::string extra_nonce;
crypto::hash8 payment_id8 = null_hash8;
crypto::public_key view_key_pub = get_destination_view_key_pub(destinations, change_addr);
if (view_key_pub == null_pkey)
{
LOG_ERROR("Failed to get key to encrypt dummy payment id with");
}
else
{
hwdev.encrypt_payment_id(payment_id8, view_key_pub, tx_key);
set_encrypted_payment_id_to_tx_extra_nonce(extra_nonce, payment_id8);
if (!add_extra_nonce_to_tx_extra(tx.extra, extra_nonce))
{
LOG_ERROR("Failed to add dummy encrypted payment id to tx extra");
// continue anyway
}
} }
} }
} }
else else
{ {
LOG_ERROR("Failed to parse tx extra"); MWARNING("Failed to parse tx extra");
return false; tx_extra_fields.clear();
} }
struct input_generation_context_data struct input_generation_context_data

View file

@ -73,17 +73,22 @@ namespace cryptonote
struct tx_destination_entry struct tx_destination_entry
{ {
std::string original;
uint64_t amount; //money uint64_t amount; //money
account_public_address addr; //destination address account_public_address addr; //destination address
bool is_subaddress; bool is_subaddress;
bool is_integrated;
tx_destination_entry() : amount(0), addr(AUTO_VAL_INIT(addr)), is_subaddress(false) { } tx_destination_entry() : amount(0), addr(AUTO_VAL_INIT(addr)), is_subaddress(false), is_integrated(false) { }
tx_destination_entry(uint64_t a, const account_public_address &ad, bool is_subaddress) : amount(a), addr(ad), is_subaddress(is_subaddress) { } tx_destination_entry(uint64_t a, const account_public_address &ad, bool is_subaddress) : amount(a), addr(ad), is_subaddress(is_subaddress), is_integrated(false) { }
tx_destination_entry(const std::string &o, uint64_t a, const account_public_address &ad, bool is_subaddress) : original(o), amount(a), addr(ad), is_subaddress(is_subaddress), is_integrated(false) { }
BEGIN_SERIALIZE_OBJECT() BEGIN_SERIALIZE_OBJECT()
FIELD(original)
VARINT_FIELD(amount) VARINT_FIELD(amount)
FIELD(addr) FIELD(addr)
FIELD(is_subaddress) FIELD(is_subaddress)
FIELD(is_integrated)
END_SERIALIZE() END_SERIALIZE()
}; };
@ -102,7 +107,7 @@ namespace cryptonote
} }
BOOST_CLASS_VERSION(cryptonote::tx_source_entry, 1) BOOST_CLASS_VERSION(cryptonote::tx_source_entry, 1)
BOOST_CLASS_VERSION(cryptonote::tx_destination_entry, 1) BOOST_CLASS_VERSION(cryptonote::tx_destination_entry, 2)
namespace boost namespace boost
{ {
@ -132,6 +137,13 @@ namespace boost
if (ver < 1) if (ver < 1)
return; return;
a & x.is_subaddress; a & x.is_subaddress;
if (ver < 2)
{
x.is_integrated = false;
return;
}
a & x.original;
a & x.is_integrated;
} }
} }
} }

View file

@ -4624,12 +4624,8 @@ void simple_wallet::on_money_received(uint64_t height, const crypto::hash &txid,
tx_extra_nonce extra_nonce; tx_extra_nonce extra_nonce;
if (find_tx_extra_field_by_type(tx_extra_fields, extra_nonce)) if (find_tx_extra_field_by_type(tx_extra_fields, extra_nonce))
{ {
crypto::hash8 payment_id8 = crypto::null_hash8;
crypto::hash payment_id = crypto::null_hash; crypto::hash payment_id = crypto::null_hash;
if (get_encrypted_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id8)) if (get_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id))
message_writer() <<
tr("NOTE: this transaction uses an encrypted payment ID: consider using subaddresses instead");
else if (get_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id))
message_writer(console_color_red, false) << message_writer(console_color_red, false) <<
(m_long_payment_id_support ? tr("WARNING: this transaction uses an unencrypted payment ID: consider using subaddresses instead.") : tr("WARNING: this transaction uses an unencrypted payment ID: these are obsolete. Support will be withdrawn in the future. Use subaddresses instead.")); (m_long_payment_id_support ? tr("WARNING: this transaction uses an unencrypted payment ID: consider using subaddresses instead.") : tr("WARNING: this transaction uses an unencrypted payment ID: these are obsolete. Support will be withdrawn in the future. Use subaddresses instead."));
} }
@ -5394,6 +5390,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
info.has_payment_id = true; info.has_payment_id = true;
} }
de.amount = amount; de.amount = amount;
de.original = local_args[i];
++i; ++i;
} }
else if (i + 1 < local_args.size()) else if (i + 1 < local_args.size())
@ -5406,6 +5403,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
", " << tr("expected number from 0 to ") << print_money(std::numeric_limits<uint64_t>::max()); ", " << tr("expected number from 0 to ") << print_money(std::numeric_limits<uint64_t>::max());
return false; return false;
} }
de.original = local_args[i];
i += 2; i += 2;
} }
else else
@ -5424,6 +5422,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
} }
de.addr = info.address; de.addr = info.address;
de.is_subaddress = info.is_subaddress; de.is_subaddress = info.is_subaddress;
de.is_integrated = info.has_payment_id;
num_subaddresses += info.is_subaddress; num_subaddresses += info.is_subaddress;
if (info.has_payment_id || !payment_id_uri.empty()) if (info.has_payment_id || !payment_id_uri.empty())
@ -6510,14 +6509,28 @@ bool simple_wallet::accept_loaded_tx(const std::function<size_t()> get_num_txes,
{ {
if (!payment_id_string.empty()) if (!payment_id_string.empty())
payment_id_string += ", "; payment_id_string += ", ";
payment_id_string = std::string("encrypted payment ID ") + epee::string_tools::pod_to_hex(payment_id8);
has_encrypted_payment_id = true; // if none of the addresses are integrated addresses, it's a dummy one
bool is_dummy = true;
for (const auto &e: cd.dests)
if (e.is_integrated)
is_dummy = false;
if (is_dummy)
{
payment_id_string += std::string("dummy encrypted payment ID");
}
else
{
payment_id_string += std::string("encrypted payment ID ") + epee::string_tools::pod_to_hex(payment_id8);
has_encrypted_payment_id = true;
}
} }
else if (get_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id)) else if (get_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id))
{ {
if (!payment_id_string.empty()) if (!payment_id_string.empty())
payment_id_string += ", "; payment_id_string += ", ";
payment_id_string = std::string("unencrypted payment ID ") + epee::string_tools::pod_to_hex(payment_id); payment_id_string += std::string("unencrypted payment ID ") + epee::string_tools::pod_to_hex(payment_id);
payment_id_string += " (OBSOLETE)"; payment_id_string += " (OBSOLETE)";
} }
} }

View file

@ -1407,9 +1407,11 @@ PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, const
if (amount) { if (amount) {
vector<cryptonote::tx_destination_entry> dsts; vector<cryptonote::tx_destination_entry> dsts;
cryptonote::tx_destination_entry de; cryptonote::tx_destination_entry de;
de.original = dst_addr;
de.addr = info.address; de.addr = info.address;
de.amount = *amount; de.amount = *amount;
de.is_subaddress = info.is_subaddress; de.is_subaddress = info.is_subaddress;
de.is_integrated = info.has_payment_id;
dsts.push_back(de); dsts.push_back(de);
transaction->m_pending_tx = m_wallet->create_transactions_2(dsts, fake_outs_count, 0 /* unlock_time */, transaction->m_pending_tx = m_wallet->create_transactions_2(dsts, fake_outs_count, 0 /* unlock_time */,
adjusted_priority, adjusted_priority,

View file

@ -8732,15 +8732,16 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
TX() : weight(0), needed_fee(0) {} TX() : weight(0), needed_fee(0) {}
void add(const account_public_address &addr, bool is_subaddress, uint64_t amount, unsigned int original_output_index, bool merge_destinations) { void add(const cryptonote::tx_destination_entry &de, uint64_t amount, unsigned int original_output_index, bool merge_destinations) {
if (merge_destinations) if (merge_destinations)
{ {
std::vector<cryptonote::tx_destination_entry>::iterator i; std::vector<cryptonote::tx_destination_entry>::iterator i;
i = std::find_if(dsts.begin(), dsts.end(), [&](const cryptonote::tx_destination_entry &d) { return !memcmp (&d.addr, &addr, sizeof(addr)); }); i = std::find_if(dsts.begin(), dsts.end(), [&](const cryptonote::tx_destination_entry &d) { return !memcmp (&d.addr, &de.addr, sizeof(de.addr)); });
if (i == dsts.end()) if (i == dsts.end())
{ {
dsts.push_back(tx_destination_entry(0,addr,is_subaddress)); dsts.push_back(de);
i = dsts.end() - 1; i = dsts.end() - 1;
i->amount = 0;
} }
i->amount += amount; i->amount += amount;
} }
@ -8749,8 +8750,11 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
THROW_WALLET_EXCEPTION_IF(original_output_index > dsts.size(), error::wallet_internal_error, THROW_WALLET_EXCEPTION_IF(original_output_index > dsts.size(), error::wallet_internal_error,
std::string("original_output_index too large: ") + std::to_string(original_output_index) + " > " + std::to_string(dsts.size())); std::string("original_output_index too large: ") + std::to_string(original_output_index) + " > " + std::to_string(dsts.size()));
if (original_output_index == dsts.size()) if (original_output_index == dsts.size())
dsts.push_back(tx_destination_entry(0,addr,is_subaddress)); {
THROW_WALLET_EXCEPTION_IF(memcmp(&dsts[original_output_index].addr, &addr, sizeof(addr)), error::wallet_internal_error, "Mismatched destination address"); dsts.push_back(de);
dsts.back().amount = 0;
}
THROW_WALLET_EXCEPTION_IF(memcmp(&dsts[original_output_index].addr, &de.addr, sizeof(de.addr)), error::wallet_internal_error, "Mismatched destination address");
dsts[original_output_index].amount += amount; dsts[original_output_index].amount += amount;
} }
} }
@ -9018,7 +9022,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
// we can fully pay that destination // we can fully pay that destination
LOG_PRINT_L2("We can fully pay " << get_account_address_as_str(m_nettype, dsts[0].is_subaddress, dsts[0].addr) << LOG_PRINT_L2("We can fully pay " << get_account_address_as_str(m_nettype, dsts[0].is_subaddress, dsts[0].addr) <<
" for " << print_money(dsts[0].amount)); " for " << print_money(dsts[0].amount));
tx.add(dsts[0].addr, dsts[0].is_subaddress, dsts[0].amount, original_output_index, m_merge_destinations); tx.add(dsts[0], dsts[0].amount, original_output_index, m_merge_destinations);
available_amount -= dsts[0].amount; available_amount -= dsts[0].amount;
dsts[0].amount = 0; dsts[0].amount = 0;
pop_index(dsts, 0); pop_index(dsts, 0);
@ -9029,7 +9033,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
// we can partially fill that destination // we can partially fill that destination
LOG_PRINT_L2("We can partially pay " << get_account_address_as_str(m_nettype, dsts[0].is_subaddress, dsts[0].addr) << LOG_PRINT_L2("We can partially pay " << get_account_address_as_str(m_nettype, dsts[0].is_subaddress, dsts[0].addr) <<
" for " << print_money(available_amount) << "/" << print_money(dsts[0].amount)); " for " << print_money(available_amount) << "/" << print_money(dsts[0].amount));
tx.add(dsts[0].addr, dsts[0].is_subaddress, available_amount, original_output_index, m_merge_destinations); tx.add(dsts[0], available_amount, original_output_index, m_merge_destinations);
dsts[0].amount -= available_amount; dsts[0].amount -= available_amount;
available_amount = 0; available_amount = 0;
} }

View file

@ -644,9 +644,11 @@ namespace tools
return false; return false;
} }
de.original = it->address;
de.addr = info.address; de.addr = info.address;
de.is_subaddress = info.is_subaddress; de.is_subaddress = info.is_subaddress;
de.amount = it->amount; de.amount = it->amount;
de.is_integrated = info.has_payment_id;
dsts.push_back(de); dsts.push_back(de);
if (info.has_payment_id) if (info.has_payment_id)