Skip to content
Permalink
Browse files

Wallet: Distingush amounts for a single subaddress

Adding a new `amounts` field ot the output of `get_transfers` RPC
method. This field specifies individual payments made to a single
subaddress in a single transaction, e.g., made by this command:

    transfer <addr1> <amount1> <addr1> <amount2>
  • Loading branch information
Tadeas Moravec authored and tmoravec committed Jan 9, 2020
1 parent 3c01bff commit 096a9dbdf958d23f74d132247143b8b8d3cb6dcd
@@ -1842,7 +1842,11 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
// (that is, the prunable stuff may or may not be included)
if (!miner_tx && !pool)
process_unconfirmed(txid, tx, height);
std::unordered_map<cryptonote::subaddress_index, uint64_t> tx_money_got_in_outs; // per receiving subaddress index

// per receiving subaddress index
std::unordered_map<cryptonote::subaddress_index, uint64_t> tx_money_got_in_outs;
std::unordered_map<cryptonote::subaddress_index, amounts_container> tx_amounts_individual_outs;

crypto::public_key tx_pub_key = null_pkey;
bool notify = false;

@@ -1971,6 +1975,10 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
{
hwdev.conceal_derivation(tx_scan_info[i].received->derivation, tx_pub_key, additional_tx_pub_keys.data, derivation, additional_derivations);
scan_output(tx, miner_tx, tx_pub_key, i, tx_scan_info[i], num_vouts_received, tx_money_got_in_outs, outs, pool);
if (!tx_scan_info[i].error)
{
tx_amounts_individual_outs[tx_scan_info[i].received->index].push_back(tx_scan_info[i].money_transfered);
}
}
}
}
@@ -1994,6 +2002,10 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
{
hwdev.conceal_derivation(tx_scan_info[i].received->derivation, tx_pub_key, additional_tx_pub_keys.data, derivation, additional_derivations);
scan_output(tx, miner_tx, tx_pub_key, i, tx_scan_info[i], num_vouts_received, tx_money_got_in_outs, outs, pool);
if (!tx_scan_info[i].error)
{
tx_amounts_individual_outs[tx_scan_info[i].received->index].push_back(tx_scan_info[i].money_transfered);
}
}
}
}
@@ -2010,6 +2022,10 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
hwdev.set_mode(hw::device::NONE);
hwdev.conceal_derivation(tx_scan_info[i].received->derivation, tx_pub_key, additional_tx_pub_keys.data, derivation, additional_derivations);
scan_output(tx, miner_tx, tx_pub_key, i, tx_scan_info[i], num_vouts_received, tx_money_got_in_outs, outs, pool);
if (!tx_scan_info[i].error)
{
tx_amounts_individual_outs[tx_scan_info[i].received->index].push_back(tx_scan_info[i].money_transfered);
}
}
}
}
@@ -2118,6 +2134,12 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
THROW_WALLET_EXCEPTION_IF(tx_money_got_in_outs[tx_scan_info[o].received->index] < tx_scan_info[o].amount,
error::wallet_internal_error, "Unexpected values of new and old outputs");
tx_money_got_in_outs[tx_scan_info[o].received->index] -= tx_scan_info[o].amount;

amounts_container& tx_amounts_this_out = tx_amounts_individual_outs[tx_scan_info[o].received->index]; // Only for readability on the following lines
auto amount_iterator = std::find(tx_amounts_this_out.begin(), tx_amounts_this_out.end(), tx_scan_info[o].amount);
THROW_WALLET_EXCEPTION_IF(amount_iterator == tx_amounts_this_out.end(),
error::wallet_internal_error, "Unexpected values of new and old outputs");
tx_amounts_this_out.erase(amount_iterator);
}
else
{
@@ -2183,6 +2205,8 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
}
}

THROW_WALLET_EXCEPTION_IF(tx_money_got_in_outs.size() != tx_amounts_individual_outs.size(), error::wallet_internal_error, "Inconsistent size of output arrays");

uint64_t tx_money_spent_in_ins = 0;
// The line below is equivalent to "boost::optional<uint32_t> subaddr_account;", but avoids the GCC warning: ‘*((void*)& subaddr_account +4)’ may be used uninitialized in this function
// It's a GCC bug with boost::optional, see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47679
@@ -2286,6 +2310,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
if (subaddr_account && i->first.major == *subaddr_account)
{
sub_change += i->second;
tx_amounts_individual_outs.erase(i->first);
i = tx_money_got_in_outs.erase(i);
}
else
@@ -2363,6 +2388,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
payment.m_tx_hash = txid;
payment.m_fee = fee;
payment.m_amount = i.second;
payment.m_amounts = tx_amounts_individual_outs[i.first];
payment.m_block_height = height;
payment.m_unlock_time = tx.unlock_time;
payment.m_timestamp = ts;
@@ -360,10 +360,12 @@ namespace tools
END_SERIALIZE()
};

typedef std::vector<uint64_t> amounts_container;
struct payment_details
{
crypto::hash m_tx_hash;
uint64_t m_amount;
amounts_container m_amounts;
uint64_t m_fee;
uint64_t m_block_height;
uint64_t m_unlock_time;
@@ -1628,7 +1630,7 @@ BOOST_CLASS_VERSION(tools::wallet2::transfer_details, 12)
BOOST_CLASS_VERSION(tools::wallet2::multisig_info, 1)
BOOST_CLASS_VERSION(tools::wallet2::multisig_info::LR, 0)
BOOST_CLASS_VERSION(tools::wallet2::multisig_tx_set, 1)
BOOST_CLASS_VERSION(tools::wallet2::payment_details, 4)
BOOST_CLASS_VERSION(tools::wallet2::payment_details, 5)
BOOST_CLASS_VERSION(tools::wallet2::pool_payment_details, 1)
BOOST_CLASS_VERSION(tools::wallet2::unconfirmed_transfer_details, 8)
BOOST_CLASS_VERSION(tools::wallet2::confirmed_transfer_details, 6)
@@ -1939,6 +1941,9 @@ namespace boost
return;
}
a & x.m_coinbase;
if (ver < 5)
return;
a & x.m_amounts;
}

template <class Archive>
@@ -326,6 +326,7 @@ namespace tools
entry.height = pd.m_block_height;
entry.timestamp = pd.m_timestamp;
entry.amount = pd.m_amount;
entry.amounts = pd.m_amounts;
entry.unlock_time = pd.m_unlock_time;
entry.locked = !m_wallet->is_transfer_unlocked(pd.m_unlock_time, pd.m_block_height);
entry.fee = pd.m_fee;
@@ -408,6 +409,7 @@ namespace tools
entry.height = 0;
entry.timestamp = pd.m_timestamp;
entry.amount = pd.m_amount;
entry.amounts = pd.m_amounts;
entry.unlock_time = pd.m_unlock_time;
entry.locked = true;
entry.fee = pd.m_fee;
@@ -1354,13 +1354,15 @@ namespace wallet_rpc
typedef epee::misc_utils::struct_init<response_t> response;
};

typedef std::vector<uint64_t> amounts_container;
struct transfer_entry
{
std::string txid;
std::string payment_id;
uint64_t height;
uint64_t timestamp;
uint64_t amount;
amounts_container amounts;
uint64_t fee;
std::string note;
std::list<transfer_destination> destinations;
@@ -1380,6 +1382,7 @@ namespace wallet_rpc
KV_SERIALIZE(height);
KV_SERIALIZE(timestamp);
KV_SERIALIZE(amount);
KV_SERIALIZE(amounts);
KV_SERIALIZE(fee);
KV_SERIALIZE(note);
KV_SERIALIZE(destinations);

0 comments on commit 096a9db

Please sign in to comment.
You can’t perform that action at this time.