mirror of
https://github.com/monero-project/monero.git
synced 2024-11-17 16:27:39 +00:00
Fix describe_transfer for multiple txes in a txset
This ensures each list of recipients is only the recipients for one transaction. It also adds a new field "summary" that describes the txset as a whole. Fixes #7344
This commit is contained in:
parent
14a1b89122
commit
5fa1c90102
2 changed files with 54 additions and 10 deletions
|
@ -1292,13 +1292,20 @@ namespace tools
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// gather info to ask the user
|
// gather info to ask the user
|
||||||
std::unordered_map<cryptonote::account_public_address, std::pair<std::string, uint64_t>> dests;
|
std::unordered_map<cryptonote::account_public_address, std::pair<std::string, uint64_t>> tx_dests;
|
||||||
|
std::unordered_map<cryptonote::account_public_address, std::pair<std::string, uint64_t>> all_dests;
|
||||||
int first_known_non_zero_change_index = -1;
|
int first_known_non_zero_change_index = -1;
|
||||||
|
res.summary.amount_in = 0;
|
||||||
|
res.summary.amount_out = 0;
|
||||||
|
res.summary.change_amount = 0;
|
||||||
|
res.summary.fee = 0;
|
||||||
for (size_t n = 0; n < tx_constructions.size(); ++n)
|
for (size_t n = 0; n < tx_constructions.size(); ++n)
|
||||||
{
|
{
|
||||||
const tools::wallet2::tx_construction_data &cd = tx_constructions[n];
|
const tools::wallet2::tx_construction_data &cd = tx_constructions[n];
|
||||||
res.desc.push_back({0, 0, std::numeric_limits<uint32_t>::max(), 0, {}, "", 0, "", 0, 0, ""});
|
res.desc.push_back({0, 0, std::numeric_limits<uint32_t>::max(), 0, {}, "", 0, "", 0, 0, ""});
|
||||||
wallet_rpc::COMMAND_RPC_DESCRIBE_TRANSFER::transfer_description &desc = res.desc.back();
|
wallet_rpc::COMMAND_RPC_DESCRIBE_TRANSFER::transfer_description &desc = res.desc.back();
|
||||||
|
// Clear the recipients collection ready for this loop iteration
|
||||||
|
tx_dests.clear();
|
||||||
|
|
||||||
std::vector<cryptonote::tx_extra_field> tx_extra_fields;
|
std::vector<cryptonote::tx_extra_field> tx_extra_fields;
|
||||||
bool has_encrypted_payment_id = false;
|
bool has_encrypted_payment_id = false;
|
||||||
|
@ -1337,17 +1344,17 @@ namespace tools
|
||||||
std::string address = cryptonote::get_account_address_as_str(m_wallet->nettype(), entry.is_subaddress, entry.addr);
|
std::string address = cryptonote::get_account_address_as_str(m_wallet->nettype(), entry.is_subaddress, entry.addr);
|
||||||
if (has_encrypted_payment_id && !entry.is_subaddress && address != entry.original)
|
if (has_encrypted_payment_id && !entry.is_subaddress && address != entry.original)
|
||||||
address = cryptonote::get_account_integrated_address_as_str(m_wallet->nettype(), entry.addr, payment_id8);
|
address = cryptonote::get_account_integrated_address_as_str(m_wallet->nettype(), entry.addr, payment_id8);
|
||||||
auto i = dests.find(entry.addr);
|
auto i = tx_dests.find(entry.addr);
|
||||||
if (i == dests.end())
|
if (i == tx_dests.end())
|
||||||
dests.insert(std::make_pair(entry.addr, std::make_pair(address, entry.amount)));
|
tx_dests.insert(std::make_pair(entry.addr, std::make_pair(address, entry.amount)));
|
||||||
else
|
else
|
||||||
i->second.second += entry.amount;
|
i->second.second += entry.amount;
|
||||||
desc.amount_out += entry.amount;
|
desc.amount_out += entry.amount;
|
||||||
}
|
}
|
||||||
if (cd.change_dts.amount > 0)
|
if (cd.change_dts.amount > 0)
|
||||||
{
|
{
|
||||||
auto it = dests.find(cd.change_dts.addr);
|
auto it = tx_dests.find(cd.change_dts.addr);
|
||||||
if (it == dests.end())
|
if (it == tx_dests.end())
|
||||||
{
|
{
|
||||||
er.code = WALLET_RPC_ERROR_CODE_BAD_UNSIGNED_TX_DATA;
|
er.code = WALLET_RPC_ERROR_CODE_BAD_UNSIGNED_TX_DATA;
|
||||||
er.message = "Claimed change does not go to a paid address";
|
er.message = "Claimed change does not go to a paid address";
|
||||||
|
@ -1374,29 +1381,45 @@ namespace tools
|
||||||
desc.change_amount += cd.change_dts.amount;
|
desc.change_amount += cd.change_dts.amount;
|
||||||
it->second.second -= cd.change_dts.amount;
|
it->second.second -= cd.change_dts.amount;
|
||||||
if (it->second.second == 0)
|
if (it->second.second == 0)
|
||||||
dests.erase(cd.change_dts.addr);
|
tx_dests.erase(cd.change_dts.addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto i = dests.begin(); i != dests.end(); )
|
for (auto i = tx_dests.begin(); i != tx_dests.end(); ++i)
|
||||||
{
|
{
|
||||||
if (i->second.second > 0)
|
if (i->second.second > 0)
|
||||||
{
|
{
|
||||||
desc.recipients.push_back({i->second.first, i->second.second});
|
desc.recipients.push_back({i->second.first, i->second.second});
|
||||||
|
auto it_in_all = all_dests.find(i->first);
|
||||||
|
if (it_in_all == all_dests.end())
|
||||||
|
all_dests.insert(std::make_pair(i->first, i->second));
|
||||||
|
else
|
||||||
|
it_in_all->second.second += i->second.second;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
++desc.dummy_outputs;
|
++desc.dummy_outputs;
|
||||||
++i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (desc.change_amount > 0)
|
if (desc.change_amount > 0)
|
||||||
{
|
{
|
||||||
const tools::wallet2::tx_construction_data &cd0 = tx_constructions[0];
|
const tools::wallet2::tx_construction_data &cd0 = tx_constructions[0];
|
||||||
desc.change_address = get_account_address_as_str(m_wallet->nettype(), cd0.subaddr_account > 0, cd0.change_dts.addr);
|
desc.change_address = get_account_address_as_str(m_wallet->nettype(), cd0.subaddr_account > 0, cd0.change_dts.addr);
|
||||||
|
res.summary.change_address = desc.change_address;
|
||||||
}
|
}
|
||||||
|
|
||||||
desc.fee = desc.amount_in - desc.amount_out;
|
desc.fee = desc.amount_in - desc.amount_out;
|
||||||
desc.unlock_time = cd.unlock_time;
|
desc.unlock_time = cd.unlock_time;
|
||||||
desc.extra = epee::to_hex::string({cd.extra.data(), cd.extra.size()});
|
desc.extra = epee::to_hex::string({cd.extra.data(), cd.extra.size()});
|
||||||
|
|
||||||
|
// Update summary items
|
||||||
|
res.summary.amount_in += desc.amount_in;
|
||||||
|
res.summary.amount_out += desc.amount_out;
|
||||||
|
res.summary.change_amount += desc.change_amount;
|
||||||
|
res.summary.fee += desc.fee;
|
||||||
|
}
|
||||||
|
// Populate the summary recipients list
|
||||||
|
for (auto i = all_dests.begin(); i != all_dests.end(); ++i)
|
||||||
|
{
|
||||||
|
res.summary.recipients.push_back({i->second.first, i->second.second});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (const std::exception &e)
|
catch (const std::exception &e)
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
// advance which version they will stop working with
|
// advance which version they will stop working with
|
||||||
// Don't go over 32767 for any of these
|
// Don't go over 32767 for any of these
|
||||||
#define WALLET_RPC_VERSION_MAJOR 1
|
#define WALLET_RPC_VERSION_MAJOR 1
|
||||||
#define WALLET_RPC_VERSION_MINOR 22
|
#define WALLET_RPC_VERSION_MINOR 23
|
||||||
#define MAKE_WALLET_RPC_VERSION(major,minor) (((major)<<16)|(minor))
|
#define MAKE_WALLET_RPC_VERSION(major,minor) (((major)<<16)|(minor))
|
||||||
#define WALLET_RPC_VERSION MAKE_WALLET_RPC_VERSION(WALLET_RPC_VERSION_MAJOR, WALLET_RPC_VERSION_MINOR)
|
#define WALLET_RPC_VERSION MAKE_WALLET_RPC_VERSION(WALLET_RPC_VERSION_MAJOR, WALLET_RPC_VERSION_MINOR)
|
||||||
namespace tools
|
namespace tools
|
||||||
|
@ -701,6 +701,25 @@ namespace wallet_rpc
|
||||||
END_KV_SERIALIZE_MAP()
|
END_KV_SERIALIZE_MAP()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct txset_summary
|
||||||
|
{
|
||||||
|
uint64_t amount_in;
|
||||||
|
uint64_t amount_out;
|
||||||
|
std::list<recipient> recipients;
|
||||||
|
uint64_t change_amount;
|
||||||
|
std::string change_address;
|
||||||
|
uint64_t fee;
|
||||||
|
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
KV_SERIALIZE(amount_in)
|
||||||
|
KV_SERIALIZE(amount_out)
|
||||||
|
KV_SERIALIZE(recipients)
|
||||||
|
KV_SERIALIZE(change_amount)
|
||||||
|
KV_SERIALIZE(change_address)
|
||||||
|
KV_SERIALIZE(fee)
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
|
||||||
struct request_t
|
struct request_t
|
||||||
{
|
{
|
||||||
std::string unsigned_txset;
|
std::string unsigned_txset;
|
||||||
|
@ -716,8 +735,10 @@ namespace wallet_rpc
|
||||||
struct response_t
|
struct response_t
|
||||||
{
|
{
|
||||||
std::list<transfer_description> desc;
|
std::list<transfer_description> desc;
|
||||||
|
struct txset_summary summary;
|
||||||
|
|
||||||
BEGIN_KV_SERIALIZE_MAP()
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
KV_SERIALIZE(summary)
|
||||||
KV_SERIALIZE(desc)
|
KV_SERIALIZE(desc)
|
||||||
END_KV_SERIALIZE_MAP()
|
END_KV_SERIALIZE_MAP()
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue