aboutsummaryrefslogtreecommitdiff
path: root/src/simplewallet/simplewallet.cpp
diff options
context:
space:
mode:
authormoneromooo-monero <moneromooo-monero@users.noreply.github.com>2016-07-15 12:11:55 +0100
committermoneromooo-monero <moneromooo-monero@users.noreply.github.com>2016-07-24 09:23:30 +0100
commitebf97d76f0020eb027175818ebbdafd6d578aa77 (patch)
tree5efd79bff6431a845b88f007bf4db783118ce272 /src/simplewallet/simplewallet.cpp
parentMerge pull request #923 (diff)
downloadmonero-ebf97d76f0020eb027175818ebbdafd6d578aa77.tar.xz
wallet: new {ex,im}port_key_images commands and RPC calls
They are used to export a signed set of key images from a wallet with a private spend key, so an auditor with the matching view key may see which of those are spent, and which are not.
Diffstat (limited to 'src/simplewallet/simplewallet.cpp')
-rw-r--r--src/simplewallet/simplewallet.cpp107
1 files changed, 107 insertions, 0 deletions
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index eb763b0cd..a3a4685b5 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -662,6 +662,8 @@ simple_wallet::simple_wallet()
m_cmd_binder.set_handler("status", boost::bind(&simple_wallet::status, this, _1), tr("Show wallet status information"));
m_cmd_binder.set_handler("sign", boost::bind(&simple_wallet::sign, this, _1), tr("Sign the contents of a file"));
m_cmd_binder.set_handler("verify", boost::bind(&simple_wallet::verify, this, _1), tr("Verify a signature on the contents of a file"));
+ m_cmd_binder.set_handler("export_key_images", boost::bind(&simple_wallet::export_key_images, this, _1), tr("Export a signed set of key images"));
+ m_cmd_binder.set_handler("import_key_images", boost::bind(&simple_wallet::import_key_images, this, _1), tr("Import signed key images list and verify their spent status"));
m_cmd_binder.set_handler("help", boost::bind(&simple_wallet::help, this, _1), tr("Show this help"));
}
//----------------------------------------------------------------------------------------------------
@@ -3480,6 +3482,111 @@ bool simple_wallet::verify(const std::vector<std::string> &args)
return true;
}
//----------------------------------------------------------------------------------------------------
+bool simple_wallet::export_key_images(const std::vector<std::string> &args)
+{
+ if (args.size() != 1)
+ {
+ fail_msg_writer() << tr("usage: export_key_images <filename>");
+ return true;
+ }
+ if (m_wallet->watch_only())
+ {
+ fail_msg_writer() << tr("wallet is watch-only and cannot export key images");
+ return true;
+ }
+ std::string filename = args[0];
+
+ try
+ {
+ std::vector<std::pair<crypto::key_image, crypto::signature>> ski = m_wallet->export_key_images();
+ std::string data;
+ for (const auto &i: ski)
+ {
+ data += epee::string_tools::pod_to_hex(i.first);
+ data += epee::string_tools::pod_to_hex(i.second);
+ }
+ bool r = epee::file_io_utils::save_string_to_file(filename, data);
+ if (!r)
+ {
+ fail_msg_writer() << tr("failed to save file ") << filename;
+ return true;
+ }
+ }
+ catch (std::exception &e)
+ {
+ LOG_ERROR("Error exporting key images: " << e.what());
+ fail_msg_writer() << "Error exporting key images: " << e.what();
+ return true;
+ }
+
+ success_msg_writer() << tr("Signed key images exported to ") << filename;
+ return true;
+}
+//----------------------------------------------------------------------------------------------------
+bool simple_wallet::import_key_images(const std::vector<std::string> &args)
+{
+ if (args.size() != 1)
+ {
+ fail_msg_writer() << tr("usage: import_key_images <filename>");
+ return true;
+ }
+ std::string filename = args[0];
+
+ std::string data;
+ bool r = epee::file_io_utils::load_file_to_string(filename, data);
+ if (!r)
+ {
+ fail_msg_writer() << tr("failed to read file ") << filename;
+ return true;
+ }
+
+ const size_t record_size = sizeof(crypto::key_image)*2 + sizeof(crypto::signature)*2;
+ if (data.size() % record_size)
+ {
+ fail_msg_writer() << "Bad data size from file " << filename;
+ return true;
+ }
+ size_t nki = data.size() / record_size;
+
+ std::vector<std::pair<crypto::key_image, crypto::signature>> ski;
+ ski.reserve(nki);
+ for (size_t n = 0; n < nki; ++n)
+ {
+ cryptonote::blobdata bd;
+
+ if(!epee::string_tools::parse_hexstr_to_binbuff(std::string(&data[n * record_size], sizeof(crypto::key_image)*2), bd))
+ {
+ fail_msg_writer() << tr("failed to parse key image");
+ return false;
+ }
+ crypto::key_image key_image = *reinterpret_cast<const crypto::key_image*>(bd.data());
+
+ if(!epee::string_tools::parse_hexstr_to_binbuff(std::string(&data[n * record_size + sizeof(crypto::key_image)*2], sizeof(crypto::signature)*2), bd))
+ {
+ fail_msg_writer() << tr("failed to parse signature");
+ return false;
+ }
+ crypto::signature signature = *reinterpret_cast<const crypto::signature*>(bd.data());
+
+ ski.push_back(std::make_pair(key_image, signature));
+ }
+
+ try
+ {
+ uint64_t spent = 0, unspent = 0;
+ uint64_t height = m_wallet->import_key_images(ski, spent, unspent);
+ success_msg_writer() << "Signed key images imported to height " << height << ", "
+ << print_money(spent) << " spent, " << print_money(unspent) << " unspent";
+ }
+ catch (const std::exception &e)
+ {
+ fail_msg_writer() << "Failed to import key images: " << e.what();
+ return true;
+ }
+
+ return true;
+}
+//----------------------------------------------------------------------------------------------------
bool simple_wallet::process_command(const std::vector<std::string> &args)
{
return m_cmd_binder.process_command_vec(args);