aboutsummaryrefslogtreecommitdiff
path: root/src/simplewallet/simplewallet.cpp
diff options
context:
space:
mode:
authorRiccardo Spagni <ric@spagni.net>2018-03-16 18:07:33 +0200
committerRiccardo Spagni <ric@spagni.net>2018-03-16 18:07:33 +0200
commit7d928be240ecaade41bbe823497086ce04372eeb (patch)
tree0ab820cc329d2cf61fbe257df9ee62a254e85d9d /src/simplewallet/simplewallet.cpp
parentMerge pull request #3410 (diff)
parentwallet: more user friendly print_ring (diff)
downloadmonero-7d928be240ecaade41bbe823497086ce04372eeb.tar.xz
Merge pull request #3322
eac3a11e wallet: more user friendly print_ring (moneromooo-monero) 79853514 wallet2_api: add key reuse mitigations API (moneromooo-monero) b057a21d wallet2_api: add ring api (moneromooo-monero) d32ef7b0 ringdb: factor ring addition code (moneromooo-monero) a7da8208 wallet2_api: add blackball api (moneromooo-monero) 2ab66ff1 liblmdb: install lmdb library for wallet2_api usage (stoffu) 504428ab ringdb: use the genesis block as a db name (moneromooo-monero) b09e5181 wallet: add a set_ring command (moneromooo-monero) 0590f62a new blockchain_usage tool, reports on output usage (moneromooo-monero) db10dd6d wallet: make ringdb an object with database state (moneromooo-monero) df6fad4c blockchain_utilities: new blockchain_blackball tool (moneromooo-monero) d29ea045 wallet: add an output blackball list to avoid using those in rings (moneromooo-monero) 18eaf194 wallet: key reuse mitigation options (moneromooo-monero) 5f146873 wallet: add shared ring database (moneromooo-monero) 41f727ce add RPC to get a histogram of outputs of a given amount (moneromooo-monero)
Diffstat (limited to 'src/simplewallet/simplewallet.cpp')
-rw-r--r--src/simplewallet/simplewallet.cpp329
1 files changed, 328 insertions, 1 deletions
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index 8bae1e2c9..3c257979e 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -1294,6 +1294,275 @@ bool simple_wallet::export_raw_multisig(const std::vector<std::string> &args)
return true;
}
+bool simple_wallet::print_ring(const std::vector<std::string> &args)
+{
+ crypto::key_image key_image;
+ crypto::hash txid;
+ if (args.size() != 1)
+ {
+ fail_msg_writer() << tr("usage: print_ring <key_image|txid>");
+ return true;
+ }
+
+ if (!epee::string_tools::hex_to_pod(args[0], key_image))
+ {
+ fail_msg_writer() << tr("Invalid key image");
+ return true;
+ }
+ // this one will always work, they're all 32 byte hex
+ if (!epee::string_tools::hex_to_pod(args[0], txid))
+ {
+ fail_msg_writer() << tr("Invalid txid");
+ return true;
+ }
+
+ std::vector<uint64_t> ring;
+ std::vector<std::pair<crypto::key_image, std::vector<uint64_t>>> rings;
+ try
+ {
+ if (m_wallet->get_ring(key_image, ring))
+ rings.push_back({key_image, ring});
+ else if (!m_wallet->get_rings(txid, rings))
+ {
+ fail_msg_writer() << tr("Key image either not spent, or spent with mixin 0");
+ return true;
+ }
+
+ for (const auto &ring: rings)
+ {
+ std::stringstream str;
+ for (const auto &x: ring.second)
+ str << x<< " ";
+ // do NOT translate this "absolute" below, the lin can be used as input to set_ring
+ success_msg_writer() << epee::string_tools::pod_to_hex(ring.first) << " absolute " << str.str();
+ }
+ }
+ catch (const std::exception &e)
+ {
+ fail_msg_writer() << tr("Failed to get key image ring: ") << e.what();
+ }
+
+ return true;
+}
+
+bool simple_wallet::set_ring(const std::vector<std::string> &args)
+{
+ crypto::key_image key_image;
+ if (args.size() < 3)
+ {
+ fail_msg_writer() << tr("usage: set_ring <key_image> absolute|relative <index> [<index>...]");
+ return true;
+ }
+
+ if (!epee::string_tools::hex_to_pod(args[0], key_image))
+ {
+ fail_msg_writer() << tr("Invalid key image");
+ return true;
+ }
+
+ bool relative;
+ if (args[1] == "absolute")
+ {
+ relative = false;
+ }
+ else if (args[1] == "relative")
+ {
+ relative = true;
+ }
+ else
+ {
+ fail_msg_writer() << tr("Missing absolute or relative keyword");
+ return true;
+ }
+
+ std::vector<uint64_t> ring;
+ for (size_t n = 2; n < args.size(); ++n)
+ {
+ ring.resize(ring.size() + 1);
+ if (!string_tools::get_xtype_from_string(ring.back(), args[n]))
+ {
+ fail_msg_writer() << tr("invalid index: must be a strictly positive unsigned integer");
+ return true;
+ }
+ if (relative)
+ {
+ if (ring.size() > 1 && !ring.back())
+ {
+ fail_msg_writer() << tr("invalid index: must be a strictly positive unsigned integer");
+ return true;
+ }
+ uint64_t sum = 0;
+ for (uint64_t out: ring)
+ {
+ if (out > std::numeric_limits<uint64_t>::max() - sum)
+ {
+ fail_msg_writer() << tr("invalid index: indices wrap");
+ return true;
+ }
+ sum += out;
+ }
+ }
+ else
+ {
+ if (ring.size() > 1 && ring[ring.size() - 2] >= ring[ring.size() - 1])
+ {
+ fail_msg_writer() << tr("invalid index: indices should be in strictly ascending order");
+ return true;
+ }
+ }
+ }
+ if (!m_wallet->set_ring(key_image, ring, relative))
+ {
+ fail_msg_writer() << tr("failed to set ring");
+ return true;
+ }
+
+ return true;
+}
+
+bool simple_wallet::blackball(const std::vector<std::string> &args)
+{
+ crypto::public_key output;
+ if (args.size() == 0)
+ {
+ fail_msg_writer() << tr("usage: blackball <output_public_key> | <filename> [add]");
+ return true;
+ }
+
+ try
+ {
+ if (epee::string_tools::hex_to_pod(args[0], output))
+ {
+ m_wallet->blackball_output(output);
+ }
+ else if (epee::file_io_utils::is_file_exist(args[0]))
+ {
+ std::vector<crypto::public_key> outputs;
+ char str[65];
+
+ std::unique_ptr<FILE, tools::close_file> f(fopen(args[0].c_str(), "r"));
+ if (f)
+ {
+ while (!feof(f.get()))
+ {
+ if (!fgets(str, sizeof(str), f.get()))
+ break;
+ const size_t len = strlen(str);
+ if (len > 0 && str[len - 1] == '\n')
+ str[len - 1] = 0;
+ if (!str[0])
+ continue;
+ outputs.push_back(crypto::public_key());
+ if (!epee::string_tools::hex_to_pod(str, outputs.back()))
+ {
+ fail_msg_writer() << tr("Invalid public key: ") << str;
+ return true;
+ }
+ }
+ f.reset();
+ bool add = false;
+ if (args.size() > 1)
+ {
+ if (args[1] != "add")
+ {
+ fail_msg_writer() << tr("Bad argument: ") + args[1] + ": " + tr("should be \"add\"");
+ return true;
+ }
+ add = true;
+ }
+ m_wallet->set_blackballed_outputs(outputs, add);
+ }
+ else
+ {
+ fail_msg_writer() << tr("Failed to open file");
+ return true;
+ }
+ }
+ else
+ {
+ fail_msg_writer() << tr("Invalid public key, and file doesn't exist");
+ return true;
+ }
+ }
+ catch (const std::exception &e)
+ {
+ fail_msg_writer() << tr("Failed to blackball output: ") << e.what();
+ }
+
+ return true;
+}
+
+bool simple_wallet::unblackball(const std::vector<std::string> &args)
+{
+ crypto::public_key output;
+ if (args.size() != 1)
+ {
+ fail_msg_writer() << tr("usage: unblackball <output_public_key>");
+ return true;
+ }
+
+ if (!epee::string_tools::hex_to_pod(args[0], output))
+ {
+ fail_msg_writer() << tr("Invalid public key");
+ return true;
+ }
+
+ try
+ {
+ m_wallet->unblackball_output(output);
+ }
+ catch (const std::exception &e)
+ {
+ fail_msg_writer() << tr("Failed to unblackball output: ") << e.what();
+ }
+
+ return true;
+}
+
+bool simple_wallet::blackballed(const std::vector<std::string> &args)
+{
+ crypto::public_key output;
+ if (args.size() != 1)
+ {
+ fail_msg_writer() << tr("usage: blackballed <output_public_key>");
+ return true;
+ }
+
+ if (!epee::string_tools::hex_to_pod(args[0], output))
+ {
+ fail_msg_writer() << tr("Invalid public key");
+ return true;
+ }
+
+ try
+ {
+ if (m_wallet->is_output_blackballed(output))
+ message_writer() << tr("Blackballed: ") << output;
+ else
+ message_writer() << tr("not blackballed: ") << output;
+ }
+ catch (const std::exception &e)
+ {
+ fail_msg_writer() << tr("Failed to unblackball output: ") << e.what();
+ }
+
+ return true;
+}
+
+bool simple_wallet::save_known_rings(const std::vector<std::string> &args)
+{
+ try
+ {
+ LOCK_IDLE_SCOPE();
+ m_wallet->find_and_save_rings();
+ }
+ catch (const std::exception &e)
+ {
+ fail_msg_writer() << tr("Failed to save known rings: ") << e.what();
+ }
+ return true;
+}
+
bool simple_wallet::set_always_confirm_transfers(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
{
const auto pwd_container = get_and_verify_password();
@@ -1638,6 +1907,32 @@ bool simple_wallet::set_auto_low_priority(const std::vector<std::string> &args/*
return true;
}
+bool simple_wallet::set_segregate_pre_fork_outputs(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
+{
+ const auto pwd_container = get_and_verify_password();
+ if (pwd_container)
+ {
+ parse_bool_and_use(args[1], [&](bool r) {
+ m_wallet->segregate_pre_fork_outputs(r);
+ m_wallet->rewrite(m_wallet_file, pwd_container->password());
+ });
+ }
+ return true;
+}
+
+bool simple_wallet::set_key_reuse_mitigation2(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
+{
+ const auto pwd_container = get_and_verify_password();
+ if (pwd_container)
+ {
+ parse_bool_and_use(args[1], [&](bool r) {
+ m_wallet->key_reuse_mitigation2(r);
+ m_wallet->rewrite(m_wallet_file, pwd_container->password());
+ });
+ }
+ return true;
+}
+
bool simple_wallet::help(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
{
if(args.empty())
@@ -1812,7 +2107,11 @@ simple_wallet::simple_wallet()
"refresh-from-block-height [n]\n "
" Set the height before which to ignore blocks.\n "
"auto-low-priority <1|0>\n "
- " Whether to automatically use the low priority fee level when it's safe to do so."));
+ " Whether to automatically use the low priority fee level when it's safe to do so.\n "
+ "segregate-pre-fork-outputs <1|0>\n "
+ " Set this if you intend to spend outputs on both Monero AND a key reusing fork.\n "
+ "key-reuse-mitigation2 <1|0>\n "
+ " Set this if you are not sure whether you will spend on a key reusing Monero fork later."));
m_cmd_binder.set_handler("encrypted_seed",
boost::bind(&simple_wallet::encrypted_seed, this, _1),
tr("Display the encrypted Electrum-style mnemonic seed."));
@@ -1951,6 +2250,30 @@ simple_wallet::simple_wallet()
boost::bind(&simple_wallet::export_raw_multisig, this, _1),
tr("export_raw_multisig_tx <filename>"),
tr("Export a signed multisig transaction to a file"));
+ m_cmd_binder.set_handler("print_ring",
+ boost::bind(&simple_wallet::print_ring, this, _1),
+ tr("print_ring <key_image> | <txid>"),
+ tr("Print the ring(s) used to spend a given key image or transaction (if the ring size is > 1)"));
+ m_cmd_binder.set_handler("set_ring",
+ boost::bind(&simple_wallet::set_ring, this, _1),
+ tr("set_ring <key_image> absolute|relative <index> [<index>...]"),
+ tr("Set the ring used for a given key image, so it can be reused in a fork"));
+ m_cmd_binder.set_handler("save_known_rings",
+ boost::bind(&simple_wallet::save_known_rings, this, _1),
+ tr("save_known_rings"),
+ tr("Save known rings to the shared rings database"));
+ m_cmd_binder.set_handler("blackball",
+ boost::bind(&simple_wallet::blackball, this, _1),
+ tr("blackball <output public key> | <filename> [add]"),
+ tr("Blackball output(s) so they never get selected as fake outputs in a ring"));
+ m_cmd_binder.set_handler("unblackball",
+ boost::bind(&simple_wallet::unblackball, this, _1),
+ tr("unblackball <output public key>"),
+ tr("Unblackballs an output so it may get selected as a fake output in a ring"));
+ m_cmd_binder.set_handler("blackballed",
+ boost::bind(&simple_wallet::blackballed, this, _1),
+ tr("blackballed <output public key>"),
+ tr("Checks whether an output is blackballed"));
m_cmd_binder.set_handler("help",
boost::bind(&simple_wallet::help, this, _1),
tr("help [<command>]"),
@@ -1980,6 +2303,8 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args)
success_msg_writer() << "confirm-export-overwrite = " << m_wallet->confirm_export_overwrite();
success_msg_writer() << "refresh-from-block-height = " << m_wallet->get_refresh_from_block_height();
success_msg_writer() << "auto-low-priority = " << m_wallet->auto_low_priority();
+ success_msg_writer() << "segregate-pre-fork-outputs = " << m_wallet->segregate_pre_fork_outputs();
+ success_msg_writer() << "key-reuse-mitigation2 = " << m_wallet->key_reuse_mitigation2();
return true;
}
else
@@ -2030,6 +2355,8 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args)
CHECK_SIMPLE_VARIABLE("confirm-export-overwrite", set_confirm_export_overwrite, tr("0 or 1"));
CHECK_SIMPLE_VARIABLE("refresh-from-block-height", set_refresh_from_block_height, tr("block height"));
CHECK_SIMPLE_VARIABLE("auto-low-priority", set_auto_low_priority, tr("0 or 1"));
+ CHECK_SIMPLE_VARIABLE("segregate-pre-fork-outputs", set_segregate_pre_fork_outputs, tr("0 or 1"));
+ CHECK_SIMPLE_VARIABLE("key-reuse-mitigation2", set_key_reuse_mitigation2, tr("0 or 1"));
}
fail_msg_writer() << tr("set: unrecognized argument(s)");
return true;