Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // src/wallet/api/pending_transaction.cpp
- /** Returns a vector of tuples with (txid, destination address, tx key) for each output of a specific transaction, disregarding change. */
- std::vector<std::tuple<std::string, std::string, std::string>> PendingTransactionImpl::txKeys(const std::string &tx_hash) const
- {
- std::vector<std::tuple<std::string, std::string, std::string>> keys;
- for (const auto &ptx : m_pending_tx)
- {
- const std::string current_tx_hash = epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(ptx.tx));
- if (current_tx_hash != tx_hash)
- {
- continue;
- }
- const std::string main_tx_key = epee::string_tools::pod_to_hex(unwrap(unwrap(ptx.tx_key)));
- if (ptx.tx.vout.size() != ptx.construction_data.splitted_dsts.size()) {
- throw std::runtime_error(
- "Number of outputs in transaction "
- + current_tx_hash
- + " (" + std::to_string(ptx.tx.vout.size()) + ")"
- + " does not match number of destinations ("
- + std::to_string(ptx.construction_data.splitted_dsts.size()) + ")");
- }
- for (size_t i = 0; i < ptx.tx.vout.size(); i++) {
- const cryptonote::tx_out tx_output = ptx.tx.vout[i];
- const cryptonote::tx_destination_entry dest_entry = ptx.construction_data.splitted_dsts[i];
- // skip change outputs
- if (dest_entry.addr.m_spend_public_key == ptx.construction_data.change_dts.addr.m_spend_public_key &&
- dest_entry.addr.m_view_public_key == ptx.construction_data.change_dts.addr.m_view_public_key) {
- continue;
- }
- crypto::public_key out_pk;
- if (!cryptonote::get_output_public_key(ptx.tx.vout[i], out_pk)) {
- throw std::runtime_error("Unable to get output public key from transaction out");
- }
- std::vector<crypto::secret_key> keys_to_try = ptx.additional_tx_keys;
- keys_to_try.push_back(ptx.tx_key);
- bool found_key = false;
- crypto::secret_key matched_key = crypto::null_skey;
- for (const auto &candidate_key: keys_to_try) {
- // compute derivation from recipient view pubkey and our tx secret key
- crypto::key_derivation derivation;
- if (!crypto::generate_key_derivation(dest_entry.addr.m_view_public_key, candidate_key, derivation)) {
- continue;
- }
- // derive expected output public key and compare
- crypto::public_key expected_out_pk;
- if (!crypto::derive_public_key(derivation, i, dest_entry.addr.m_spend_public_key, expected_out_pk)) {
- continue;
- }
- if (expected_out_pk == out_pk) {
- found_key = true;
- matched_key = candidate_key;
- break;
- }
- }
- if (!found_key) {
- throw std::runtime_error("No matching tx key found for output");
- }
- // push (txid, destination address (human-readable), hex(tx_secret_key))
- const std::string dest_addr_str = dest_entry.address(m_wallet.m_wallet->nettype(), crypto::null_hash);
- keys.emplace_back(
- current_tx_hash,
- dest_addr_str,
- epee::string_tools::pod_to_hex(unwrap(unwrap(matched_key)))
- );
- }
- }
- return keys;
- }
Advertisement
Add Comment
Please, Sign In to add comment