simplewallet: add option for exporting tx keys

This commit adds an option to export transaction
keys when performing export_transfers all. By passing
option=with_keys a new column 'tx key' will be
populated with respective keys.
This commit is contained in:
reemuru 2022-02-13 00:06:25 -05:00
parent 9aab19f349
commit 3f88fddbfa
No known key found for this signature in database
GPG key ID: 5EDBFEFFA9E9A7AB

View file

@ -3544,7 +3544,7 @@ simple_wallet::simple_wallet()
"** Set of address indices used as inputs in this transfer.")); "** Set of address indices used as inputs in this transfer."));
m_cmd_binder.set_handler("export_transfers", m_cmd_binder.set_handler("export_transfers",
boost::bind(&simple_wallet::on_command, this, &simple_wallet::export_transfers, _1), boost::bind(&simple_wallet::on_command, this, &simple_wallet::export_transfers, _1),
tr("export_transfers [in|out|all|pending|failed|pool|coinbase] [index=<N1>[,<N2>,...]] [<min_height> [<max_height>]] [output=<filepath>]"), tr("export_transfers [in|out|all|pending|failed|pool|coinbase] [index=<N1>[,<N2>,...]] [<min_height> [<max_height>]] [output=<filepath>] [option=<with_keys>]"),
tr("Export to CSV the incoming/outgoing transfers within an optional height range.")); tr("Export to CSV the incoming/outgoing transfers within an optional height range."));
m_cmd_binder.set_handler("unspent_outputs", m_cmd_binder.set_handler("unspent_outputs",
boost::bind(&simple_wallet::on_command, this, &simple_wallet::unspent_outputs, _1), boost::bind(&simple_wallet::on_command, this, &simple_wallet::unspent_outputs, _1),
@ -8051,6 +8051,15 @@ bool simple_wallet::submit_transfer(const std::vector<std::string> &args_)
return true; return true;
} }
//---------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------
std::string get_tx_key_stream(crypto::secret_key tx_key, std::vector<crypto::secret_key> additional_tx_keys)
{
ostringstream oss;
oss << epee::string_tools::pod_to_hex(tx_key);
for (size_t i = 0; i < additional_tx_keys.size(); ++i)
oss << epee::string_tools::pod_to_hex(additional_tx_keys[i]);
return oss.str();
}
bool simple_wallet::get_tx_key(const std::vector<std::string> &args_) bool simple_wallet::get_tx_key(const std::vector<std::string> &args_)
{ {
std::vector<std::string> local_args = args_; std::vector<std::string> local_args = args_;
@ -8080,11 +8089,8 @@ bool simple_wallet::get_tx_key(const std::vector<std::string> &args_)
bool found_tx_key = m_wallet->get_tx_key(txid, tx_key, additional_tx_keys); bool found_tx_key = m_wallet->get_tx_key(txid, tx_key, additional_tx_keys);
if (found_tx_key) if (found_tx_key)
{ {
ostringstream oss; std::string stream = get_tx_key_stream(tx_key, additional_tx_keys);
oss << epee::string_tools::pod_to_hex(tx_key); success_msg_writer() << tr("Tx key: ") << stream;
for (size_t i = 0; i < additional_tx_keys.size(); ++i)
oss << epee::string_tools::pod_to_hex(additional_tx_keys[i]);
success_msg_writer() << tr("Tx key: ") << oss.str();
return true; return true;
} }
else else
@ -8895,13 +8901,11 @@ bool simple_wallet::export_transfers(const std::vector<std::string>& args_)
{ {
std::vector<std::string> local_args = args_; std::vector<std::string> local_args = args_;
if(local_args.size() > 5) { if(local_args.size() > 6) {
fail_msg_writer() << tr("usage: export_transfers [in|out|all|pending|failed|pool|coinbase] [index=<N1>[,<N2>,...]] [<min_height> [<max_height>]] [output=<path>]"); fail_msg_writer() << tr("usage: export_transfers [in|out|all|pending|failed|pool|coinbase] [index=<N1>[,<N2>,...]] [<min_height> [<max_height>]] [output=<path>] [option=<with_keys>]");
return true; return true;
} }
LOCK_IDLE_SCOPE();
std::vector<transfer_view> all_transfers; std::vector<transfer_view> all_transfers;
// might consumes arguments in local_args // might consumes arguments in local_args
@ -8915,17 +8919,36 @@ bool simple_wallet::export_transfers(const std::vector<std::string>& args_)
filename = local_args[0].substr(7, -1); filename = local_args[0].substr(7, -1);
local_args.erase(local_args.begin()); local_args.erase(local_args.begin());
} }
// check for export with tx keys
bool export_keys = false;
if (local_args.size() > 0 && local_args[0].substr(0, 7) == "option=")
{
export_keys = local_args[0].substr(7, -1) == "with_keys";
local_args.erase(local_args.begin());
}
if (export_keys)
{
if (m_wallet->key_on_device() && m_wallet->get_account().get_device().get_type() != hw::device::TREZOR)
{
fail_msg_writer() << tr("command not supported by HW wallet");
return true;
}
SCOPED_WALLET_UNLOCK();
} else
{
LOCK_IDLE_SCOPE();
}
std::ofstream file(filename); std::ofstream file(filename);
// header // header
file << file <<
boost::format("%8.8s,%9.9s,%8.8s,%25.25s,%20.20s,%20.20s,%64.64s,%16.16s,%14.14s,%106.106s,%20.20s,%s,%s") % boost::format("%8.8s,%9.9s,%8.8s,%25.25s,%20.20s,%20.20s,%64.64s,%16.16s,%14.14s,%106.106s,%20.20s,%s,%s,%s") %
tr("block") % tr("direction") % tr("unlocked") % tr("timestamp") % tr("amount") % tr("running balance") % tr("hash") % tr("payment ID") % tr("fee") % tr("destination") % tr("amount") % tr("index") % tr("note") tr("block") % tr("direction") % tr("unlocked") % tr("timestamp") % tr("amount") % tr("running balance") % tr("hash") % tr("payment ID") % tr("fee") % tr("destination") % tr("amount") % tr("index") % tr("note") % tr("tx key")
<< std::endl; << std::endl;
uint64_t running_balance = 0; uint64_t running_balance = 0;
auto formatter = boost::format("%8.8llu,%9.9s,%8.8s,%25.25s,%20.20s,%20.20s,%64.64s,%16.16s,%14.14s,%106.106s,%20.20s,\"%s\",%s"); auto formatter = boost::format("%8.8llu,%9.9s,%8.8s,%25.25s,%20.20s,%20.20s,%64.64s,%16.16s,%14.14s,%106.106s,%20.20s,\"%s\",%s,%s");
for (const auto& transfer : all_transfers) for (const auto& transfer : all_transfers)
{ {
@ -8938,6 +8961,15 @@ bool simple_wallet::export_transfers(const std::vector<std::string>& args_)
running_balance -= transfer.amount + transfer.fee; running_balance -= transfer.amount + transfer.fee;
} }
crypto::secret_key tx_key;
std::vector<crypto::secret_key> additional_tx_keys;
bool found_tx_key = m_wallet->get_tx_key(transfer.hash, tx_key, additional_tx_keys);
std::string key_string;
if (export_keys && found_tx_key)
{
key_string = get_tx_key_stream(tx_key, additional_tx_keys);
}
file << formatter file << formatter
% transfer.block % transfer.block
% transfer.direction % transfer.direction
@ -8952,6 +8984,7 @@ bool simple_wallet::export_transfers(const std::vector<std::string>& args_)
% (transfer.outputs.size() ? print_money(transfer.outputs[0].second) : "") % (transfer.outputs.size() ? print_money(transfer.outputs[0].second) : "")
% boost::algorithm::join(transfer.index | boost::adaptors::transformed([](uint32_t i) { return std::to_string(i); }), ", ") % boost::algorithm::join(transfer.index | boost::adaptors::transformed([](uint32_t i) { return std::to_string(i); }), ", ")
% transfer.note % transfer.note
% key_string
<< std::endl; << std::endl;
for (size_t i = 1; i < transfer.outputs.size(); ++i) for (size_t i = 1; i < transfer.outputs.size(); ++i)
@ -8970,6 +9003,7 @@ bool simple_wallet::export_transfers(const std::vector<std::string>& args_)
% print_money(transfer.outputs[i].second) % print_money(transfer.outputs[i].second)
% "" % ""
% "" % ""
% ""
<< std::endl; << std::endl;
} }
} }