diff options
38 files changed, 1682 insertions, 883 deletions
diff --git a/.gitignore b/.gitignore index a27982af1..1f88b6ad3 100644 --- a/.gitignore +++ b/.gitignore @@ -103,4 +103,4 @@ local.properties .texlipse .idea/ -/testnet
\ No newline at end of file + @@ -193,26 +193,26 @@ invokes cmake commands as needed. Tested on a Raspberry Pi 2 with a clean install of minimal Debian Jessie from https://www.raspberrypi.org/downloads/raspbian/ -* `apt-get update` and `apt-get upgrade` to install all of the latest software +* `apt-get update && apt-get upgrade` to install all of the latest software * Install the dependencies for Monero except libunwind and libboost-all-dev -* Increase the system swap size - - sudo /etc/init.d/dphys-swapfile stop - sudo nano /etc/dphys-swapfile - CONF_SWAPSIZE=1024 - sudo /etc/init.d/dphys-swapfile start - -* Install the latest version of boost (this may first require invoking `apt-get remove --purge libboost*` to remove a previous version if you're not using a clean install) - - cd - wget https://sourceforge.net/projects/boost/files/boost/1.62.0/boost_1_62_0.tar.bz2 - tar xvfo boost_1_62_0.tar.bz2 - cd boost_1_62_0 - ./bootstrap.sh - sudo ./b2 - +* Increase the system swap size: +``` + sudo /etc/init.d/dphys-swapfile stop + sudo nano /etc/dphys-swapfile + CONF_SWAPSIZE=1024 + sudo /etc/init.d/dphys-swapfile start +``` +* Install the latest version of boost (this may first require invoking `apt-get remove --purge libboost*` to remove a previous version if you're not using a clean install): +``` + cd + wget https://sourceforge.net/projects/boost/files/boost/1.62.0/boost_1_62_0.tar.bz2 + tar xvfo boost_1_62_0.tar.bz2 + cd boost_1_62_0 + ./bootstrap.sh + sudo ./b2 +``` * Wait ~8 hours sudo ./bjam install @@ -378,3 +378,20 @@ Note: rlwrap will save things like your seed and private keys, if you supply the If you want to help out, see CONTRIBUTING for a set of guidelines. +# Debugging + +This section contains general instructions for debugging failed installs or problems encountered with Monero. First ensure you are running the latest version built from the github repo. + +## LMDB + +Instructions for debugging suspected blockchain corruption as per @HYC + +There is an `mdb_stat` command in the LMDB source that can print statistics about the database but it's not routinely built. This can be built with the following command: + +`cd ~/monero/external/db_drivers/liblmdb && make` + +The output of `mdb_stat -ea <path to blockchain dir>` will indicate inconsistencies in the blocks, block_heights and block_info table. + +The output of `mdb_dump -s blocks <path to blockchain dir>` and `mdb_dump -s block_info <path to blockchain dir>` is useful for indicating whether blocks and block_info contain the same keys. + +These records are dumped as hex data, where the first line is the key and the second line is the data. diff --git a/contrib/epee/include/console_handler.h b/contrib/epee/include/console_handler.h index 95b986ff5..2ad92b3f2 100644 --- a/contrib/epee/include/console_handler.h +++ b/contrib/epee/include/console_handler.h @@ -155,6 +155,20 @@ namespace epee else if (0 < retval) return true; } +#else + while (m_run.load(std::memory_order_relaxed)) + { + int retval = ::WaitForSingleObject(::GetStdHandle(STD_INPUT_HANDLE), 100); + switch (retval) + { + case WAIT_FAILED: + return false; + case WAIT_OBJECT_0: + return true; + default: + break; + } + } #endif return true; diff --git a/contrib/epee/include/net/abstract_tcp_server2.inl b/contrib/epee/include/net/abstract_tcp_server2.inl index dbdfbc74d..3dca30006 100644 --- a/contrib/epee/include/net/abstract_tcp_server2.inl +++ b/contrib/epee/include/net/abstract_tcp_server2.inl @@ -727,7 +727,7 @@ PRAGMA_WARNING_DISABLE_VS(4355) m_address = address; // Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR). boost::asio::ip::tcp::resolver resolver(io_service_); - boost::asio::ip::tcp::resolver::query query(address, boost::lexical_cast<std::string>(port)); + boost::asio::ip::tcp::resolver::query query(address, boost::lexical_cast<std::string>(port), boost::asio::ip::tcp::resolver::query::canonical_name); boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query); acceptor_.open(endpoint.protocol()); acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); @@ -970,7 +970,7 @@ POP_WARNINGS ////////////////////////////////////////////////////////////////////////// boost::asio::ip::tcp::resolver resolver(io_service_); - boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), adr, port); + boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), adr, port, boost::asio::ip::tcp::resolver::query::canonical_name); boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query); boost::asio::ip::tcp::resolver::iterator end; if(iterator == end) @@ -1010,7 +1010,7 @@ POP_WARNINGS boost::unique_lock<boost::mutex> lock(local_shared_context->connect_mut); auto connect_callback = [](boost::system::error_code ec_, boost::shared_ptr<local_async_context> shared_context) { - shared_context->connect_mut.lock(); shared_context->ec = ec_; shared_context->connect_mut.unlock(); shared_context->cond.notify_one(); + shared_context->connect_mut.lock(); shared_context->ec = ec_; shared_context->cond.notify_one(); shared_context->connect_mut.unlock(); }; sock_.async_connect(remote_endpoint, boost::bind<void>(connect_callback, _1, local_shared_context)); @@ -1074,7 +1074,7 @@ POP_WARNINGS ////////////////////////////////////////////////////////////////////////// boost::asio::ip::tcp::resolver resolver(io_service_); - boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), adr, port); + boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), adr, port, boost::asio::ip::tcp::resolver::query::canonical_name); boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query); boost::asio::ip::tcp::resolver::iterator end; if(iterator == end) diff --git a/contrib/valgrind/monero.supp b/contrib/valgrind/monero.supp index 1c400076e..16e34e82f 100644 --- a/contrib/valgrind/monero.supp +++ b/contrib/valgrind/monero.supp @@ -8,3 +8,12 @@ fun:_ULx86_64_step ... } + +{ + boost unlocks before signalling cond var + Helgrind:Misc + ... + fun:pthread_cond_signal@* + fun:maybe_unlock_and_signal_one<boost::asio::detail::scoped_lock<boost::asio::detail::posix_mutex> > + ... +} diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index d5d22bca6..dd17f6d64 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -33,6 +33,7 @@ set(common_sources util.cpp i18n.cpp perf_timer.cpp + task_region.cpp thread_group.cpp) if (STACK_TRACE) @@ -57,6 +58,7 @@ set(common_private_headers i18n.h perf_timer.h stack_trace.h + task_region.h thread_group.h) monero_private_headers(common diff --git a/src/common/command_line.cpp b/src/common/command_line.cpp index b3f488447..28879e098 100644 --- a/src/common/command_line.cpp +++ b/src/common/command_line.cpp @@ -29,11 +29,22 @@ // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers #include "command_line.h" -#include "string_tools.h" +#include <boost/algorithm/string/compare.hpp> +#include <boost/algorithm/string/predicate.hpp> +#include "common/i18n.h" #include "cryptonote_config.h" +#include "string_tools.h" namespace command_line { + namespace + { + const char* tr(const char* str) + { + return i18n_translate(str, "command_line"); + } + } + std::string input_line(const std::string& prompt) { std::cout << prompt; @@ -45,6 +56,20 @@ namespace command_line } + bool is_yes(const std::string& str) + { + if (str == "y" || str == "Y") + return true; + + boost::algorithm::is_iequal ignore_case{}; + if (boost::algorithm::equals("yes", str, ignore_case)) + return true; + if (boost::algorithm::equals(command_line::tr("yes"), str, ignore_case)) + return true; + + return false; + } + const arg_descriptor<bool> arg_help = {"help", "Produce help message"}; const arg_descriptor<bool> arg_version = {"version", "Output version information"}; const arg_descriptor<std::string> arg_data_dir = {"data-dir", "Specify data directory"}; diff --git a/src/common/command_line.h b/src/common/command_line.h index 0ea749168..98c115bb7 100644 --- a/src/common/command_line.h +++ b/src/common/command_line.h @@ -43,6 +43,9 @@ namespace command_line std::string input_line(const std::string& prompt); + //! \return True if `str` is `is_iequal("y" || "yes" || `tr("yes"))`. + bool is_yes(const std::string& str); + template<typename T, bool required = false> struct arg_descriptor; diff --git a/src/common/task_region.cpp b/src/common/task_region.cpp new file mode 100644 index 000000000..b53a8376a --- /dev/null +++ b/src/common/task_region.cpp @@ -0,0 +1,94 @@ +// Copyright (c) 2014-2016, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#include "common/task_region.h" + +#include <boost/thread/locks.hpp> +#include <cassert> + +/* `mark_completed` and `wait` can throw in the lock call, but its difficult to +recover from either. An exception in `wait` means the post condition of joining +all threads cannot be achieved, and an exception in `mark_completed` means +certain deadlock. `noexcept` qualifier will force a call to `std::terminate` if +locking throws an exception, which should only happen if a recursive lock +attempt is made (which is not possible since no external function is called +while holding the lock). */ + +namespace tools +{ +void task_region_handle::state::mark_completed(id task_id) noexcept { + assert(task_id != 0 && (task_id & (task_id - 1)) == 0); // power of 2 check + if (pending.fetch_and(~task_id) == task_id) { + // synchronize with wait call, but do not need to hold + boost::unique_lock<boost::mutex>{sync_on_complete}; + all_complete.notify_all(); + } +} + +void task_region_handle::state::abort() noexcept { + state* current = this; + while (current) { + current->ready = 0; + current = current->next.get(); + } +} + +void task_region_handle::state::wait() noexcept { + state* current = this; + while (current) { + { + boost::unique_lock<boost::mutex> lock{current->sync_on_complete}; + current->all_complete.wait(lock, [current] { return current->pending == 0; }); + } + current = current->next.get(); + } +} + +void task_region_handle::state::wait(thread_group& threads) noexcept { + state* current = this; + while (current) { + while (current->pending != 0) { + if (!threads.try_run_one()) { + current->wait(); + return; + } + } + current = current->next.get(); + } +} + +void task_region_handle::create_state() { + st = std::make_shared<state>(std::move(st)); + next_id = 1; +} + +void task_region_handle::do_wait() noexcept { + assert(st); + const std::shared_ptr<state> temp = std::move(st); + temp->wait(threads); +} +} diff --git a/src/common/task_region.h b/src/common/task_region.h new file mode 100644 index 000000000..e4d210661 --- /dev/null +++ b/src/common/task_region.h @@ -0,0 +1,223 @@ +// Copyright (c) 2014-2016, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#pragma once + +#include <atomic> +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/mutex.hpp> +#include <memory> +#include <type_traits> +#include <utility> + +#include "common/thread_group.h" + +namespace tools +{ + +/*! A model of the fork-join concept. `run(...)` "forks" (i.e. spawns new +tasks), and `~task_region_handle()` or `wait()` "joins" the spawned tasks. +`wait` will block until all tasks have completed, while `~task_region_handle()` +blocks until all tasks have completed or aborted. + +Do _NOT_ give this object to separate thread of execution (which includes +`task_region_handle::run(...)`) because joining on a different thread is +undesireable (potential deadlock). + +This class cannot be constructed directly, use the function +`task_region(...)` instead. +*/ +class task_region_handle +{ + struct state + { + using id = unsigned; + + explicit state(std::shared_ptr<state> next_src) noexcept + : next(std::move(next_src)) + , ready(0) + , pending(0) + , sync_on_complete() + , all_complete() { + } + + state(const state&) = default; + state(state&&) = default; + ~state() = default; + state& operator=(const state&) = default; + state& operator=(state&&) = default; + + void track_id(id task_id) noexcept { + pending |= task_id; + ready |= task_id; + } + + //! \return True only once whether a given id can execute + bool can_run(id task_id) noexcept { + return (ready.fetch_and(~task_id) & task_id); + } + + //! Mark id as completed, and synchronize with waiting threads + void mark_completed(id task_id) noexcept; + + //! Tell all unstarted functions in region to return immediately + void abort() noexcept; + + //! Blocks until all functions in region have aborted or completed. + void wait() noexcept; + + //! Same as `wait()`, except `this_thread` runs tasks while waiting. + void wait(thread_group& threads) noexcept; + + private: + /* This implementation is a bit pessimistic, it ensures that all copies + of a wrapped task can only be executed once. `thread_group` should never + do this, but some variable needs to track whether an abort should be done + anyway... */ + std::shared_ptr<state> next; + std::atomic<id> ready; //!< Tracks whether a task has been invoked + std::atomic<id> pending; //!< Tracks when a task has completed or aborted + boost::mutex sync_on_complete; + boost::condition_variable all_complete; + }; + + template<typename F> + struct wrapper + { + wrapper(state::id id_src, std::shared_ptr<state> st_src, F f_src) + : task_id(id_src), st(std::move(st_src)), f(std::move(f_src)) { + } + + wrapper(const wrapper&) = default; + wrapper(wrapper&&) = default; + wrapper& operator=(const wrapper&) = default; + wrapper& operator=(wrapper&&) = default; + + void operator()() { + if (st) { + if (st->can_run(task_id)) { + f(); + } + st->mark_completed(task_id); + } + } + + private: + const state::id task_id; + std::shared_ptr<state> st; + F f; + }; + +public: + friend struct task_region_; + + task_region_handle() = delete; + task_region_handle(const task_region_handle&) = delete; + task_region_handle(task_region_handle&&) = delete; + + //! Cancels unstarted pending tasks, and waits for them to respond. + ~task_region_handle() noexcept { + if (st) { + st->abort(); + st->wait(threads); + } + } + + task_region_handle& operator=(const task_region_handle&) = delete; + task_region_handle& operator=(task_region_handle&&) = delete; + + /*! If the group has no threads, `f` is immediately run before returning. + Otherwise, `f` is dispatched to the thread_group associated with `this` + region. If `f` is dispatched to another thread, and it throws, the process + will immediately terminate. See std::packaged_task for getting exceptions on + functions executed on other threads. */ + template<typename F> + void run(F&& f) { + if (threads.count() == 0) { + f(); + } else { + if (!st || next_id == 0) { + create_state(); + } + const state::id this_id = next_id; + next_id <<= 1; + + st->track_id(this_id); + threads.dispatch(wrapper<F>{this_id, st, std::move(f)}); + } + } + + //! Wait until all functions provided to `run` have completed. + void wait() noexcept { + if (st) { + do_wait(); + } + } + +private: + explicit task_region_handle(thread_group& threads_src) + : st(nullptr), threads(threads_src), next_id(0) { + } + + void create_state(); + void do_wait() noexcept; + + std::shared_ptr<state> st; + thread_group& threads; + state::id next_id; +}; + +/*! Function for creating a `task_region_handle`, which automatically calls +`task_region_handle::wait()` before returning. If a `thread_group` is not +provided, one is created with an optimal number of threads. The callback `f` +must have the signature `void(task_region_handle&)`. */ +struct task_region_ { + template<typename F> + void operator()(thread_group& threads, F&& f) const { + static_assert( + std::is_same<void, typename std::result_of<F(task_region_handle&)>::type>::value, + "f cannot have a return value" + ); + task_region_handle region{threads}; + f(region); + region.wait(); + } + + template<typename F> + void operator()(thread_group&& threads, F&& f) const { + (*this)(threads, std::forward<F>(f)); + } + + template<typename F> + void operator()(F&& f) const { + thread_group threads; + (*this)(threads, std::forward<F>(f)); + } +}; + +constexpr const task_region_ task_region{}; +} diff --git a/src/common/thread_group.cpp b/src/common/thread_group.cpp index aa1b64f2e..4e1cc8964 100644 --- a/src/common/thread_group.cpp +++ b/src/common/thread_group.cpp @@ -27,6 +27,7 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "common/thread_group.h" +#include <boost/thread/locks.hpp> #include <cassert> #include <limits> #include <stdexcept> @@ -35,14 +36,20 @@ namespace tools { -thread_group::thread_group(std::size_t count) : internal() { +std::size_t thread_group::optimal() { static_assert( std::numeric_limits<unsigned>::max() <= std::numeric_limits<std::size_t>::max(), "unexpected truncation" ); - count = std::min<std::size_t>(count, get_max_concurrency()); - count = count ? count - 1 : 0; + const std::size_t hardware = get_max_concurrency(); + return hardware ? (hardware - 1) : 0; +} + +std::size_t thread_group::optimal_with_max(std::size_t count) { + return count ? std::min(count - 1, optimal()) : 0; +} +thread_group::thread_group(std::size_t count) : internal() { if (count) { internal.emplace(count); } @@ -52,24 +59,21 @@ thread_group::data::data(std::size_t count) : threads() , head{nullptr} , last(std::addressof(head)) - , pending(count) , mutex() , has_work() - , finished_work() , stop(false) { threads.reserve(count); while (count--) { - threads.push_back(std::thread(&thread_group::data::run, this)); + threads.push_back(boost::thread(&thread_group::data::run, this)); } } thread_group::data::~data() noexcept { { - const std::unique_lock<std::mutex> lock(mutex); + const boost::unique_lock<boost::mutex> lock(mutex); stop = true; } has_work.notify_all(); - finished_work.notify_all(); for (auto& worker : threads) { try { worker.join(); @@ -78,10 +82,20 @@ thread_group::data::~data() noexcept { } } +std::unique_ptr<thread_group::data::work> thread_group::data::get_next() noexcept { + std::unique_ptr<work> rc = std::move(head.ptr); + if (rc != nullptr) { + head.ptr = std::move(rc->next.ptr); + if (head.ptr == nullptr) { + last = std::addressof(head); + } + } + return rc; +} -void thread_group::data::sync() noexcept { +bool thread_group::data::try_run_one() noexcept { /* This function and `run()` can both throw when acquiring the lock, or in - the dispatched function. It is tough to recover from either, particularly the + dispatched function. It is tough to recover from either, particularly the lock case. These functions are marked as noexcept so that if either call throws, the entire process is terminated. Users of the `dispatch` call are expected to make their functions noexcept, or use std::packaged_task to copy @@ -89,50 +103,25 @@ void thread_group::data::sync() noexcept { cases (std::bad_alloc). This was the existing behavior; `asio::io_service::run` propogates errors from dispatched calls, and uncaught exceptions on threads result in process termination. */ - assert(!threads.empty()); - bool not_first = false; - while (true) { - std::unique_ptr<work> next = nullptr; - { - std::unique_lock<std::mutex> lock(mutex); - pending -= std::size_t(not_first); - not_first = true; - finished_work.notify_all(); - - if (stop) { - return; - } - - next = get_next(); - if (next == nullptr) { - finished_work.wait(lock, [this] { return pending == 0 || stop; }); - return; - } - } + std::unique_ptr<work> next = nullptr; + { + const boost::unique_lock<boost::mutex> lock(mutex); + next = get_next(); + } + if (next) { assert(next->f); next->f(); + return true; } -} - -std::unique_ptr<thread_group::data::work> thread_group::data::get_next() noexcept { - std::unique_ptr<work> rc = std::move(head.ptr); - if (rc != nullptr) { - head.ptr = std::move(rc->next.ptr); - if (head.ptr == nullptr) { - last = std::addressof(head); - } - } - return rc; + return false; } void thread_group::data::run() noexcept { - // see `sync()` source for additional information + // see `try_run_one()` source for additional information while (true) { std::unique_ptr<work> next = nullptr; { - std::unique_lock<std::mutex> lock(mutex); - --pending; - finished_work.notify_all(); + boost::unique_lock<boost::mutex> lock(mutex); has_work.wait(lock, [this] { return head.ptr != nullptr || stop; }); if (stop) { return; @@ -149,15 +138,12 @@ void thread_group::data::dispatch(std::function<void()> f) { std::unique_ptr<work> latest(new work{std::move(f), node{nullptr}}); node* const latest_node = std::addressof(latest->next); { - const std::unique_lock<std::mutex> lock(mutex); + const boost::unique_lock<boost::mutex> lock(mutex); assert(last != nullptr); assert(last->ptr == nullptr); - if (pending == std::numeric_limits<std::size_t>::max()) { - throw std::overflow_error("thread_group exceeded max queue depth"); - } + last->ptr = std::move(latest); last = latest_node; - ++pending; } has_work.notify_one(); } diff --git a/src/common/thread_group.h b/src/common/thread_group.h index d8461d49a..62e82d832 100644 --- a/src/common/thread_group.h +++ b/src/common/thread_group.h @@ -25,8 +25,12 @@ // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#pragma once + #include <boost/optional/optional.hpp> -#include <condition_variable> +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> #include <cstddef> #include <functional> #include <thread> @@ -35,11 +39,21 @@ namespace tools { -//! Manages zero or more threads for work dispatching +//! Manages zero or more threads for work dispatching. class thread_group { public: - //! Create `min(count, get_max_concurrency()) - 1` threads + + //! \return `get_max_concurrency() ? get_max_concurrency() - 1 : 0` + static std::size_t optimal(); + + //! \return `count ? min(count - 1, optimal()) : 0` + static std::size_t optimal_with_max(std::size_t count); + + //! Create an optimal number of threads. + explicit thread_group() : thread_group(optimal()) {} + + //! Create exactly `count` threads. explicit thread_group(std::size_t count); thread_group(thread_group const&) = delete; @@ -51,30 +65,26 @@ public: thread_group& operator=(thread_group const&) = delete; thread_group& operator=(thread_group&&) = delete; - /*! Blocks until all functions provided to `dispatch` complete. Does not - destroy threads. If a dispatched function calls `this->dispatch(...)`, - `this->sync()` will continue to block until that new function completes. */ - void sync() noexcept { + //! \return Number of threads owned by `this` group. + std::size_t count() const noexcept { if (internal) { - internal->sync(); + return internal->count(); } + return 0; } - /*! Example usage: - std::unique_ptr<thread_group, thread_group::lazy_sync> sync(std::addressof(group)); - which guarantees synchronization before the unique_ptr destructor returns. */ - struct lazy_sync { - void operator()(thread_group* group) const noexcept { - if (group != nullptr) { - group->sync(); - } + //! \return True iff a function was available and executed (on `this_thread`). + bool try_run_one() noexcept { + if (internal) { + return internal->try_run_one(); } - }; + return false; + } - /*! `f` is invoked immediately if the thread_group is empty, otherwise - execution of `f` is queued for next available thread. If `f` is queued, any - exception leaving that function will result in process termination. Use - std::packaged_task if exceptions need to be handled. */ + /*! `f` is invoked immediately if `count() == 0`, otherwise execution of `f` + is queued for next available thread. If `f` is queued, any exception leaving + that function will result in process termination. Use std::packaged_task if + exceptions need to be handled. */ template<typename F> void dispatch(F&& f) { if (internal) { @@ -91,8 +101,11 @@ private: data(std::size_t count); ~data() noexcept; - void sync() noexcept; + std::size_t count() const noexcept { + return threads.size(); + } + bool try_run_one() noexcept; void dispatch(std::function<void()> f); private: @@ -116,13 +129,11 @@ private: void run() noexcept; private: - std::vector<std::thread> threads; + std::vector<boost::thread> threads; node head; node* last; - std::size_t pending; - std::condition_variable has_work; - std::condition_variable finished_work; - std::mutex mutex; + boost::condition_variable has_work; + boost::mutex mutex; bool stop; }; @@ -130,4 +141,5 @@ private: // optionally construct elements, without separate heap allocation boost::optional<data> internal; }; + } diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index ffebcd592..bf2b4b71a 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -1758,7 +1758,7 @@ bool Blockchain::get_random_rct_outs(const COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS::r return true; } //------------------------------------------------------------------ -bool Blockchain::get_outs(const COMMAND_RPC_GET_OUTPUTS::request& req, COMMAND_RPC_GET_OUTPUTS::response& res) const +bool Blockchain::get_outs(const COMMAND_RPC_GET_OUTPUTS_BIN::request& req, COMMAND_RPC_GET_OUTPUTS_BIN::response& res) const { LOG_PRINT_L3("Blockchain::" << __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); @@ -2231,6 +2231,19 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context } } + // from v4, forbid invalid pubkeys + if (m_hardfork->get_current_version() >= 4) { + for (const auto &o: tx.vout) { + if (o.target.type() == typeid(txout_to_key)) { + const txout_to_key& out_to_key = boost::get<txout_to_key>(o.target); + if (!crypto::check_key(out_to_key.key)) { + tvc.m_invalid_output = true; + return false; + } + } + } + } + return true; } //------------------------------------------------------------------ diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h index eb7a050b2..f9ae9d8aa 100644 --- a/src/cryptonote_core/blockchain.h +++ b/src/cryptonote_core/blockchain.h @@ -452,7 +452,7 @@ namespace cryptonote * * @return true */ - bool get_outs(const COMMAND_RPC_GET_OUTPUTS::request& req, COMMAND_RPC_GET_OUTPUTS::response& res) const; + bool get_outs(const COMMAND_RPC_GET_OUTPUTS_BIN::request& req, COMMAND_RPC_GET_OUTPUTS_BIN::response& res) const; /** * @brief gets random ringct outputs to mix with diff --git a/src/cryptonote_core/cryptonote_basic_impl.cpp b/src/cryptonote_core/cryptonote_basic_impl.cpp index 74f44e2af..4f35b8298 100644 --- a/src/cryptonote_core/cryptonote_basic_impl.cpp +++ b/src/cryptonote_core/cryptonote_basic_impl.cpp @@ -199,7 +199,7 @@ namespace cryptonote { uint64_t prefix; if (!tools::base58::decode_addr(str, prefix, data)) { - LOG_PRINT_L1("Invalid address format"); + LOG_PRINT_L2("Invalid address format"); return false; } diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 9deb8863d..84a41cfbf 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -758,7 +758,7 @@ namespace cryptonote return m_blockchain_storage.get_random_outs_for_amounts(req, res); } //----------------------------------------------------------------------------------------------- - bool core::get_outs(const COMMAND_RPC_GET_OUTPUTS::request& req, COMMAND_RPC_GET_OUTPUTS::response& res) const + bool core::get_outs(const COMMAND_RPC_GET_OUTPUTS_BIN::request& req, COMMAND_RPC_GET_OUTPUTS_BIN::response& res) const { return m_blockchain_storage.get_outs(req, res); } diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h index 5ddab4ed4..21f84cdd4 100644 --- a/src/cryptonote_core/cryptonote_core.h +++ b/src/cryptonote_core/cryptonote_core.h @@ -471,7 +471,7 @@ namespace cryptonote * * @note see Blockchain::get_outs */ - bool get_outs(const COMMAND_RPC_GET_OUTPUTS::request& req, COMMAND_RPC_GET_OUTPUTS::response& res) const; + bool get_outs(const COMMAND_RPC_GET_OUTPUTS_BIN::request& req, COMMAND_RPC_GET_OUTPUTS_BIN::response& res) const; /** * diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index d8dadae1f..b5bfc2979 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -339,7 +339,7 @@ namespace nodetool io_service io_srv; ip::tcp::resolver resolver(io_srv); - ip::tcp::resolver::query query(host, port); + ip::tcp::resolver::query query(host, port, boost::asio::ip::tcp::resolver::query::canonical_name); boost::system::error_code ec; ip::tcp::resolver::iterator i = resolver.resolve(query, ec); CHECK_AND_ASSERT_MES_NO_RET(!ec, "Failed to resolve host name '" << host << "': " << ec.message() << ':' << ec.value()); diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp index df33c26b2..b773be1e5 100644 --- a/src/ringct/rctSigs.cpp +++ b/src/ringct/rctSigs.cpp @@ -30,6 +30,7 @@ #include "misc_log_ex.h" #include "common/perf_timer.h" +#include "common/task_region.h" #include "common/thread_group.h" #include "common/util.h" #include "rctSigs.h" @@ -39,22 +40,6 @@ using namespace crypto; using namespace std; namespace rct { - namespace { - struct verRangeWrapper_ { - void operator()(const key & C, const rangeSig & as, bool &result) const { - result = verRange(C, as); - } - }; - constexpr const verRangeWrapper_ verRangeWrapper{}; - - struct verRctMGSimpleWrapper_ { - void operator()(const key &message, const mgSig &mg, const ctkeyV & pubs, const key & C, bool &result) const { - result = verRctMGSimple(message, mg, pubs, C); - } - }; - constexpr const verRctMGSimpleWrapper_ verRctMGSimpleWrapper{}; - } - //Schnorr Non-linkable //Gen Gives a signature (L1, s1, s2) proving that the sender knows "x" such that xG = one of P1 or P2 //Ver Verifies that signer knows an "x" such that xG = one of P1 or P2 @@ -766,15 +751,17 @@ namespace rct { try { std::deque<bool> results(rv.outPk.size(), false); - tools::thread_group threadpool(rv.outPk.size()); // this must destruct before results + tools::thread_group threadpool(tools::thread_group::optimal_with_max(rv.outPk.size())); + + tools::task_region(threadpool, [&] (tools::task_region_handle& region) { + DP("range proofs verified?"); + for (size_t i = 0; i < rv.outPk.size(); i++) { + region.run([&, i] { + results[i] = verRange(rv.outPk[i].mask, rv.p.rangeSigs[i]); + }); + } + }); - DP("range proofs verified?"); - for (size_t i = 0; i < rv.outPk.size(); i++) { - threadpool.dispatch( - std::bind(verRangeWrapper, std::cref(rv.outPk[i].mask), std::cref(rv.p.rangeSigs[i]), std::ref(results[i])) - ); - } - threadpool.sync(); for (size_t i = 0; i < rv.outPk.size(); ++i) { if (!results[i]) { LOG_ERROR("Range proof verified failed for input " << i); @@ -804,7 +791,6 @@ namespace rct { //assumes only post-rct style inputs (at least for max anonymity) bool verRctSimple(const rctSig & rv) { PERF_TIMER(verRctSimple); - size_t i = 0; CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple, false, "verRctSimple called on non simple rctSig"); CHECK_AND_ASSERT_MES(rv.outPk.size() == rv.p.rangeSigs.size(), false, "Mismatched sizes of outPk and rv.p.rangeSigs"); @@ -813,28 +799,29 @@ namespace rct { CHECK_AND_ASSERT_MES(rv.pseudoOuts.size() == rv.mixRing.size(), false, "Mismatched sizes of rv.pseudoOuts and mixRing"); const size_t threads = std::max(rv.outPk.size(), rv.mixRing.size()); - tools::thread_group threadpool(threads); - { - std::deque<bool> results(rv.outPk.size(), false); - { - const std::unique_ptr<tools::thread_group, tools::thread_group::lazy_sync> - sync(std::addressof(threadpool)); - for (i = 0; i < rv.outPk.size(); i++) { - threadpool.dispatch( - std::bind(verRangeWrapper, std::cref(rv.outPk[i].mask), std::cref(rv.p.rangeSigs[i]), std::ref(results[i])) - ); - } - } // threadpool.sync(); - for (size_t i = 0; i < rv.outPk.size(); ++i) { - if (!results[i]) { - LOG_ERROR("Range proof verified failed for input " << i); - return false; - } + + std::deque<bool> results(threads); + tools::thread_group threadpool(tools::thread_group::optimal_with_max(threads)); + + results.clear(); + results.resize(rv.outPk.size()); + tools::task_region(threadpool, [&] (tools::task_region_handle& region) { + for (size_t i = 0; i < rv.outPk.size(); i++) { + region.run([&, i] { + results[i] = verRange(rv.outPk[i].mask, rv.p.rangeSigs[i]); + }); + } + }); + + for (size_t i = 0; i < results.size(); ++i) { + if (!results[i]) { + LOG_ERROR("Range proof verified failed for input " << i); + return false; } } key sumOutpks = identity(); - for (i = 0; i < rv.outPk.size(); i++) { + for (size_t i = 0; i < rv.outPk.size(); i++) { addKeys(sumOutpks, sumOutpks, rv.outPk[i].mask); } DP(sumOutpks); @@ -843,27 +830,25 @@ namespace rct { key message = get_pre_mlsag_hash(rv); - { - std::deque<bool> results(rv.mixRing.size(), false); - { - const std::unique_ptr<tools::thread_group, tools::thread_group::lazy_sync> - sync(std::addressof(threadpool)); - for (i = 0 ; i < rv.mixRing.size() ; i++) { - threadpool.dispatch( - std::bind(verRctMGSimpleWrapper, std::cref(message), std::cref(rv.p.MGs[i]), std::cref(rv.mixRing[i]), std::cref(rv.pseudoOuts[i]), std::ref(results[i])) - ); - } - } // threadpool.sync(); - for (size_t i = 0; i < results.size(); ++i) { - if (!results[i]) { - LOG_ERROR("verRctMGSimple failed for input " << i); - return false; - } + results.clear(); + results.resize(rv.mixRing.size()); + tools::task_region(threadpool, [&] (tools::task_region_handle& region) { + for (size_t i = 0 ; i < rv.mixRing.size() ; i++) { + region.run([&, i] { + results[i] = verRctMGSimple(message, rv.p.MGs[i], rv.mixRing[i], rv.pseudoOuts[i]); + }); + } + }); + + for (size_t i = 0; i < results.size(); ++i) { + if (!results[i]) { + LOG_ERROR("verRctMGSimple failed for input " << i); + return false; } } key sumPseudoOuts = identity(); - for (i = 0 ; i < rv.mixRing.size() ; i++) { + for (size_t i = 0 ; i < rv.mixRing.size() ; i++) { addKeys(sumPseudoOuts, sumPseudoOuts, rv.pseudoOuts[i]); } DP(sumPseudoOuts); diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index a02a2375b..5bf500733 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -246,7 +246,7 @@ namespace cryptonote return true; } //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_get_outs(const COMMAND_RPC_GET_OUTPUTS::request& req, COMMAND_RPC_GET_OUTPUTS::response& res) + bool core_rpc_server::on_get_outs_bin(const COMMAND_RPC_GET_OUTPUTS_BIN::request& req, COMMAND_RPC_GET_OUTPUTS_BIN::response& res) { CHECK_CORE_BUSY(); res.status = "Failed"; @@ -269,6 +269,42 @@ namespace cryptonote return true; } //------------------------------------------------------------------------------------------------------------------------------ + bool core_rpc_server::on_get_outs(const COMMAND_RPC_GET_OUTPUTS::request& req, COMMAND_RPC_GET_OUTPUTS::response& res) + { + CHECK_CORE_BUSY(); + res.status = "Failed"; + + if (m_restricted) + { + if (req.outputs.size() > MAX_RESTRICTED_GLOBAL_FAKE_OUTS_COUNT) + { + res.status = "Too many outs requested"; + return true; + } + } + + cryptonote::COMMAND_RPC_GET_OUTPUTS_BIN::request req_bin; + req_bin.outputs = req.outputs; + cryptonote::COMMAND_RPC_GET_OUTPUTS_BIN::response res_bin; + if(!m_core.get_outs(req_bin, res_bin)) + { + return true; + } + + // convert to text + for (const auto &i: res_bin.outs) + { + res.outs.push_back(cryptonote::COMMAND_RPC_GET_OUTPUTS::outkey()); + cryptonote::COMMAND_RPC_GET_OUTPUTS::outkey &outkey = res.outs.back(); + outkey.key = epee::string_tools::pod_to_hex(i.key); + outkey.mask = epee::string_tools::pod_to_hex(i.mask); + outkey.unlocked = i.unlocked; + } + + res.status = CORE_RPC_STATUS_OK; + return true; + } + //------------------------------------------------------------------------------------------------------------------------------ bool core_rpc_server::on_get_random_rct_outs(const COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS::request& req, COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS::response& res) { CHECK_CORE_BUSY(); @@ -388,6 +424,17 @@ namespace cryptonote res.txs_as_hex.push_back(e.as_hex); if (req.decode_as_json) res.txs_as_json.push_back(e.as_json); + + // output indices too if not in pool + if (pool_tx_hashes.find(tx_hash) == pool_tx_hashes.end()) + { + bool r = m_core.get_tx_outputs_gindexs(tx_hash, e.output_indices); + if (!r) + { + res.status = "Failed"; + return false; + } + } } BOOST_FOREACH(const auto& miss_tx, missed_txs) diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h index 2fdb790ab..b7f6cdd60 100644 --- a/src/rpc/core_rpc_server.h +++ b/src/rpc/core_rpc_server.h @@ -79,7 +79,7 @@ namespace cryptonote MAP_URI_AUTO_BIN2("/gethashes.bin", on_get_hashes, COMMAND_RPC_GET_HASHES_FAST) MAP_URI_AUTO_BIN2("/get_o_indexes.bin", on_get_indexes, COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES) MAP_URI_AUTO_BIN2("/getrandom_outs.bin", on_get_random_outs, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS) - MAP_URI_AUTO_BIN2("/get_outs.bin", on_get_outs, COMMAND_RPC_GET_OUTPUTS) + MAP_URI_AUTO_BIN2("/get_outs.bin", on_get_outs_bin, COMMAND_RPC_GET_OUTPUTS_BIN) MAP_URI_AUTO_BIN2("/getrandom_rctouts.bin", on_get_random_rct_outs, COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS) MAP_URI_AUTO_JON2("/gettransactions", on_get_transactions, COMMAND_RPC_GET_TRANSACTIONS) MAP_URI_AUTO_JON2("/is_key_image_spent", on_is_key_image_spent, COMMAND_RPC_IS_KEY_IMAGE_SPENT) @@ -97,6 +97,7 @@ namespace cryptonote MAP_URI_AUTO_JON2_IF("/out_peers", on_out_peers, COMMAND_RPC_OUT_PEERS, !m_restricted) MAP_URI_AUTO_JON2_IF("/start_save_graph", on_start_save_graph, COMMAND_RPC_START_SAVE_GRAPH, !m_restricted) MAP_URI_AUTO_JON2_IF("/stop_save_graph", on_stop_save_graph, COMMAND_RPC_STOP_SAVE_GRAPH, !m_restricted) + MAP_URI_AUTO_JON2("/get_outs", on_get_outs, COMMAND_RPC_GET_OUTPUTS) BEGIN_JSON_RPC_MAP("/json_rpc") MAP_JON_RPC("getblockcount", on_getblockcount, COMMAND_RPC_GETBLOCKCOUNT) MAP_JON_RPC_WE("on_getblockhash", on_getblockhash, COMMAND_RPC_GETBLOCKHASH) @@ -131,6 +132,7 @@ namespace cryptonote bool on_stop_mining(const COMMAND_RPC_STOP_MINING::request& req, COMMAND_RPC_STOP_MINING::response& res); bool on_mining_status(const COMMAND_RPC_MINING_STATUS::request& req, COMMAND_RPC_MINING_STATUS::response& res); bool on_get_random_outs(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res); + bool on_get_outs_bin(const COMMAND_RPC_GET_OUTPUTS_BIN::request& req, COMMAND_RPC_GET_OUTPUTS_BIN::response& res); bool on_get_outs(const COMMAND_RPC_GET_OUTPUTS::request& req, COMMAND_RPC_GET_OUTPUTS::response& res); bool on_get_random_rct_outs(const COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS::request& req, COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS::response& res); bool on_get_info(const COMMAND_RPC_GET_INFO::request& req, COMMAND_RPC_GET_INFO::response& res); diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 6d452f59d..23fcb0a92 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -41,7 +41,16 @@ namespace cryptonote #define CORE_RPC_STATUS_BUSY "BUSY" #define CORE_RPC_STATUS_NOT_MINING "NOT MINING" -#define CORE_RPC_VERSION 4 +// When making *any* change here, bump minor +// If the change is incompatible, then bump major and set minor to 0 +// This ensures CORE_RPC_VERSION always increases, that every change +// has its own version, and that clients can just test major to see +// whether they can talk to a given daemon without having to know in +// advance which version they will stop working with +// Don't go over 32767 for any of these +#define CORE_RPC_VERSION_MAJOR 1 +#define CORE_RPC_VERSION_MINOR 0 +#define CORE_RPC_VERSION (((CORE_RPC_VERSION_MAJOR)<<16)|(CORE_RPC_VERSION_MINOR)) struct COMMAND_RPC_GET_HEIGHT { @@ -162,6 +171,7 @@ namespace cryptonote std::string as_json; bool in_pool; uint64_t block_height; + std::vector<uint64_t> output_indices; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(tx_hash) @@ -169,6 +179,7 @@ namespace cryptonote KV_SERIALIZE(as_json) KV_SERIALIZE(in_pool) KV_SERIALIZE(block_height) + KV_SERIALIZE(output_indices) END_KV_SERIALIZE_MAP() }; @@ -291,22 +302,22 @@ namespace cryptonote }; }; //----------------------------------------------- - struct COMMAND_RPC_GET_OUTPUTS + struct get_outputs_out { - struct out - { - uint64_t amount; - uint64_t index; + uint64_t amount; + uint64_t index; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(amount) - KV_SERIALIZE(index) - END_KV_SERIALIZE_MAP() - }; + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(amount) + KV_SERIALIZE(index) + END_KV_SERIALIZE_MAP() + }; + struct COMMAND_RPC_GET_OUTPUTS_BIN + { struct request { - std::vector<out> outputs; + std::vector<get_outputs_out> outputs; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(outputs) @@ -337,6 +348,42 @@ namespace cryptonote END_KV_SERIALIZE_MAP() }; }; + //----------------------------------------------- + struct COMMAND_RPC_GET_OUTPUTS + { + struct request + { + std::vector<get_outputs_out> outputs; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(outputs) + END_KV_SERIALIZE_MAP() + }; + + struct outkey + { + std::string key; + std::string mask; + bool unlocked; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(key) + KV_SERIALIZE(mask) + KV_SERIALIZE(unlocked) + END_KV_SERIALIZE_MAP() + }; + + struct response + { + std::vector<outkey> outs; + std::string status; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(outs) + KV_SERIALIZE(status) + END_KV_SERIALIZE_MAP() + }; + }; struct COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS { diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 515fc5b22..faeed31ce 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -212,17 +212,17 @@ namespace return message_writer(epee::log_space::console_color_red, true, sw::tr("Error: "), LOG_LEVEL_0); } - bool is_it_true(std::string s) + bool is_it_true(const std::string& s) { - std::transform(s.begin(), s.end(), s.begin(), ::tolower); - if (s == "true") + if (s == "1" || command_line::is_yes(s)) return true; - if (s == "1") - return true; - if (s == "y" || s == "yes") + + boost::algorithm::is_iequal ignore_case{}; + if (boost::algorithm::equals("true", s, ignore_case)) return true; - if (s == sw::tr("yes")) + if (boost::algorithm::equals(simple_wallet::tr("true"), s, ignore_case)) return true; + return false; } @@ -263,6 +263,10 @@ namespace return "invalid"; } + std::string get_version_string(uint32_t version) + { + return boost::lexical_cast<std::string>(version >> 16) + "." + boost::lexical_cast<std::string>(version & 0xffff); + } } @@ -916,7 +920,7 @@ bool simple_wallet::ask_wallet_create_if_needed() LOG_ERROR("Unexpected std::cin.eof() - Exited simple_wallet::ask_wallet_create_if_needed()"); return false; } - if(is_it_true(confirm_creation)) + if(command_line::is_yes(confirm_creation)) { success_msg_writer() << tr("Generating new wallet..."); m_generate_new = wallet_path; @@ -1189,8 +1193,8 @@ bool simple_wallet::handle_command_line(const boost::program_options::variables_ //---------------------------------------------------------------------------------------------------- bool simple_wallet::try_connect_to_daemon(bool silent) { - bool same_version = false; - if (!m_wallet->check_connection(&same_version)) + uint32_t version = 0; + if (!m_wallet->check_connection(&version)) { if (!silent) fail_msg_writer() << tr("wallet failed to connect to daemon: ") << m_wallet->get_daemon_address() << ". " << @@ -1198,11 +1202,10 @@ bool simple_wallet::try_connect_to_daemon(bool silent) "Please make sure daemon is running or restart the wallet with the correct daemon address."); return false; } - if (!m_allow_mismatched_daemon_version && !same_version) + if (!m_allow_mismatched_daemon_version && ((version >> 16) != CORE_RPC_VERSION_MAJOR)) { if (!silent) - fail_msg_writer() << tr("Daemon uses a different RPC version that the wallet: ") << m_wallet->get_daemon_address() << ". " << - tr("Either update one of them, or use --allow-mismatched-daemon-version."); + fail_msg_writer() << boost::format(tr("Daemon uses a different RPC major version (%u) than the wallet (%u): %s. Either update one of them, or use --allow-mismatched-daemon-version.")) % (version>>16) % CORE_RPC_VERSION_MAJOR % m_wallet->get_daemon_address(); return false; } return true; @@ -1977,8 +1980,7 @@ bool simple_wallet::get_address_from_str(const std::string &str, cryptonote::acc { return false; } - if (confirm_dns_ok != "Y" && confirm_dns_ok != "y" && confirm_dns_ok != "Yes" && confirm_dns_ok != "yes" - && confirm_dns_ok != tr("yes") && confirm_dns_ok != tr("no")) + if (!command_line::is_yes(confirm_dns_ok)) { fail_msg_writer() << tr("you have cancelled the transfer request"); return false; @@ -2136,7 +2138,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri std::string accepted = command_line::input_line(tr("No payment id is included with this transaction. Is this okay? (Y/Yes/N/No)")); if (std::cin.eof()) return true; - if (accepted != "Y" && accepted != "y" && accepted != "Yes" && accepted != "yes") + if (!command_line::is_yes(accepted)) { fail_msg_writer() << tr("transaction cancelled."); @@ -2220,7 +2222,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri std::string accepted = command_line::input_line(prompt.str()); if (std::cin.eof()) return true; - if (accepted != "Y" && accepted != "y" && accepted != "Yes" && accepted != "yes") + if (!command_line::is_yes(accepted)) { fail_msg_writer() << tr("transaction cancelled."); @@ -2399,7 +2401,7 @@ bool simple_wallet::sweep_unmixable(const std::vector<std::string> &args_) std::string accepted = command_line::input_line(prompt_str); if (std::cin.eof()) return true; - if (accepted != "Y" && accepted != "y" && accepted != "Yes" && accepted != "yes") + if (!command_line::is_yes(accepted)) { fail_msg_writer() << tr("transaction cancelled."); @@ -2613,7 +2615,7 @@ bool simple_wallet::sweep_all(const std::vector<std::string> &args_) std::string accepted = command_line::input_line(tr("No payment id is included with this transaction. Is this okay? (Y/Yes/N/No)")); if (std::cin.eof()) return true; - if (accepted != "Y" && accepted != "y" && accepted != "Yes" && accepted != "yes") + if (!command_line::is_yes(accepted)) { fail_msg_writer() << tr("transaction cancelled."); @@ -2658,7 +2660,7 @@ bool simple_wallet::sweep_all(const std::vector<std::string> &args_) std::string accepted = command_line::input_line(prompt_str); if (std::cin.eof()) return true; - if (accepted != "Y" && accepted != "y" && accepted != "Yes" && accepted != "yes") + if (!command_line::is_yes(accepted)) { fail_msg_writer() << tr("transaction cancelled."); @@ -2853,8 +2855,7 @@ bool simple_wallet::accept_loaded_tx(const std::function<size_t()> get_num_txes, uint64_t fee = amount - amount_to_dests; std::string prompt_str = (boost::format(tr("Loaded %lu transactions, for %s, fee %s, %s, %s, with min mixin %lu. %sIs this okay? (Y/Yes/N/No)")) % (unsigned long)get_num_txes() % print_money(amount) % print_money(fee) % dest_string % change_string % (unsigned long)min_mixin % extra_message).str(); - std::string accepted = command_line::input_line(prompt_str); - return is_it_true(accepted); + return command_line::is_yes(command_line::input_line(prompt_str)); } //---------------------------------------------------------------------------------------------------- bool simple_wallet::accept_loaded_tx(const tools::wallet2::unsigned_tx_set &txs) @@ -2923,57 +2924,6 @@ bool simple_wallet::submit_transfer(const std::vector<std::string> &args_) return true; } - // if more than one tx necessary, prompt user to confirm - if (m_wallet->always_confirm_transfers()) - { - uint64_t total_sent = 0; - uint64_t total_fee = 0; - uint64_t dust_not_in_fee = 0; - uint64_t dust_in_fee = 0; - for (size_t n = 0; n < ptx_vector.size(); ++n) - { - total_fee += ptx_vector[n].fee; - for (auto i: ptx_vector[n].selected_transfers) - total_sent += m_wallet->get_transfer_details(i).amount(); - total_sent -= ptx_vector[n].change_dts.amount + ptx_vector[n].fee; - - if (ptx_vector[n].dust_added_to_fee) - dust_in_fee += ptx_vector[n].dust; - else - dust_not_in_fee += ptx_vector[n].dust; - } - - std::stringstream prompt; - prompt << boost::format(tr("Sending %s. ")) % print_money(total_sent); - if (ptx_vector.size() > 1) - { - prompt << boost::format(tr("Your transaction needs to be split into %llu transactions. " - "This will result in a transaction fee being applied to each transaction, for a total fee of %s")) % - ((unsigned long long)ptx_vector.size()) % print_money(total_fee); - } - else - { - prompt << boost::format(tr("The transaction fee is %s")) % - print_money(total_fee); - } - if (dust_in_fee != 0) prompt << boost::format(tr(", of which %s is dust from change")) % print_money(dust_in_fee); - if (dust_not_in_fee != 0) prompt << tr(".") << ENDL << boost::format(tr("A total of %s from dust change will be sent to dust address")) - % print_money(dust_not_in_fee); - prompt << tr(".") << ENDL << "Full transaction details are available in the log file" << ENDL << tr("Is this okay? (Y/Yes/N/No)"); - - std::string accepted = command_line::input_line(prompt.str()); - if (std::cin.eof()) - return true; - if (accepted != "Y" && accepted != "y" && accepted != "Yes" && accepted != "yes") - { - fail_msg_writer() << tr("transaction cancelled."); - - // would like to return false, because no tx made, but everything else returns true - // and I don't know what returning false might adversely affect. *sigh* - return true; - } - } - // actually commit the transactions while (!ptx_vector.empty()) { @@ -3615,7 +3565,8 @@ bool simple_wallet::get_tx_note(const std::vector<std::string> &args) bool simple_wallet::status(const std::vector<std::string> &args) { uint64_t local_height = m_wallet->get_blockchain_current_height(); - if (!try_connect_to_daemon()) + uint32_t version = 0; + if (!m_wallet->check_connection(&version)) { success_msg_writer() << "Refreshed " << local_height << "/?, no daemon connected"; return true; @@ -3626,7 +3577,8 @@ bool simple_wallet::status(const std::vector<std::string> &args) if (err.empty()) { bool synced = local_height == bc_height; - success_msg_writer() << "Refreshed " << local_height << "/" << bc_height << ", " << (synced ? "synced" : "syncing"); + success_msg_writer() << "Refreshed " << local_height << "/" << bc_height << ", " << (synced ? "synced" : "syncing") + << ", daemon RPC v" << get_version_string(version); } else { diff --git a/src/wallet/api/transaction_history.cpp b/src/wallet/api/transaction_history.cpp index 63c4ea3cc..603739598 100644 --- a/src/wallet/api/transaction_history.cpp +++ b/src/wallet/api/transaction_history.cpp @@ -55,7 +55,8 @@ TransactionHistoryImpl::TransactionHistoryImpl(WalletImpl *wallet) TransactionHistoryImpl::~TransactionHistoryImpl() { - + for (auto t : m_history) + delete t; } int TransactionHistoryImpl::count() const diff --git a/src/wallet/api/utils.cpp b/src/wallet/api/utils.cpp index 1bf35197c..7de9d1927 100644 --- a/src/wallet/api/utils.cpp +++ b/src/wallet/api/utils.cpp @@ -61,7 +61,7 @@ bool isAddressLocal(const std::string &address) // resolve to IP boost::asio::io_service io_service; boost::asio::ip::tcp::resolver resolver(io_service); - boost::asio::ip::tcp::resolver::query query(u_c.host, ""); + boost::asio::ip::tcp::resolver::query query(u_c.host, "", boost::asio::ip::tcp::resolver::query::canonical_name); boost::asio::ip::tcp::resolver::iterator i = resolver.resolve(query); while (i != boost::asio::ip::tcp::resolver::iterator()) { diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index d21d8b900..97aaf2785 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -399,6 +399,11 @@ std::string WalletImpl::integratedAddress(const std::string &payment_id) const return m_wallet->get_account().get_public_integrated_address_str(pid, m_wallet->testnet()); } +std::string WalletImpl::path() const +{ + return m_wallet->path(); +} + bool WalletImpl::store(const std::string &path) { clearStatus(); @@ -605,6 +610,17 @@ PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, const break; } } + else if (has_payment_id) { + std::string extra_nonce; + set_encrypted_payment_id_to_tx_extra_nonce(extra_nonce, payment_id_short); + bool r = add_extra_nonce_to_tx_extra(extra, extra_nonce); + if (!r) { + m_status = Status_Error; + m_errorString = tr("Failed to add short payment id: ") + epee::string_tools::pod_to_hex(payment_id_short); + break; + } + } + //std::vector<tools::wallet2::pending_tx> ptx_vector; @@ -895,11 +911,11 @@ bool WalletImpl::connectToDaemon() Wallet::ConnectionStatus WalletImpl::connected() const { - bool same_version = false; - bool is_connected = m_wallet->check_connection(&same_version); + uint32_t version = 0; + bool is_connected = m_wallet->check_connection(&version); if (!is_connected) return Wallet::ConnectionStatus_Disconnected; - if (!same_version) + if ((version >> 16) != CORE_RPC_VERSION_MAJOR) return Wallet::ConnectionStatus_WrongVersion; return Wallet::ConnectionStatus_Connected; } diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h index 02a46da8c..5e4a64ff8 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.h @@ -64,6 +64,7 @@ public: bool setPassword(const std::string &password); std::string address() const; std::string integratedAddress(const std::string &payment_id) const; + std::string path() const; bool store(const std::string &path); std::string filename() const; std::string keysFilename() const; diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 15a134257..a15233a87 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -191,7 +191,7 @@ boost::optional<tools::password_container> get_password(const boost::program_opt } // Remove line breaks the user might have inserted - password.erase(std::remove(password.begin() - 1, password.end(), '\n'), password.end()); + password.erase(std::remove(password.end() - 1, password.end(), '\n'), password.end()); password.erase(std::remove(password.end() - 1, password.end(), '\r'), password.end()); return {tools::password_container(std::move(password))}; } @@ -1574,12 +1574,35 @@ void wallet2::refresh(uint64_t start_height, uint64_t & blocks_fetched, bool& re std::list<cryptonote::block_complete_entry> blocks; std::vector<COMMAND_RPC_GET_BLOCKS_FAST::block_output_indices> o_indices; + std::string daemon_height_err = ""; + uint64_t daemon_bc_height = get_daemon_blockchain_height(daemon_height_err); + if(daemon_height_err.size() > 0) { + throw std::runtime_error(daemon_height_err); + } + // pull the first set of blocks get_short_chain_history(short_chain_history); m_run.store(true, std::memory_order_relaxed); if (start_height > m_blockchain.size() || m_refresh_from_block_height > m_blockchain.size()) { - if (!start_height) - start_height = m_refresh_from_block_height; + + // even target_height can be zero if the daemon just started and hasn't gotten some sync + // data back from peers .. hmmm, what to do ... O.o (you can see him thinking) + // i'm going with infiniti loop until i get something bigger than zero or err ... moneromoo don't kill me + std::string daemon_target_err = ""; + uint64_t daemon_target_height = 0; + + while(daemon_target_height == 0) + { + daemon_target_height = get_daemon_blockchain_target_height(daemon_target_err); + if(daemon_target_err.size() > 0) { + daemon_target_height = get_approximate_blockchain_height(); // - x? + } + } + + if (m_refresh_from_block_height > daemon_target_height) m_refresh_from_block_height = daemon_target_height - 1; + if (!start_height) start_height = m_refresh_from_block_height; + if (start_height >= daemon_bc_height) start_height = daemon_bc_height - 1; + // we can shortcut by only pulling hashes up to the start_height fast_refresh(start_height, blocks_start_height, short_chain_history); // regenerate the history now that we've got a full set of hashes @@ -1589,53 +1612,56 @@ void wallet2::refresh(uint64_t start_height, uint64_t & blocks_fetched, bool& re // and then fall through to regular refresh processing } - pull_blocks(start_height, blocks_start_height, short_chain_history, blocks, o_indices); - // always reset start_height to 0 to force short_chain_ history to be used on - // subsequent pulls in this refresh. - start_height = 0; - - while(m_run.load(std::memory_order_relaxed)) + if(!(m_refresh_from_block_height >= daemon_bc_height)) { - try - { - // pull the next set of blocks while we're processing the current one - uint64_t next_blocks_start_height; - std::list<cryptonote::block_complete_entry> next_blocks; - std::vector<cryptonote::COMMAND_RPC_GET_BLOCKS_FAST::block_output_indices> next_o_indices; - bool error = false; - pull_thread = boost::thread([&]{pull_next_blocks(start_height, next_blocks_start_height, short_chain_history, blocks, next_blocks, next_o_indices, error);}); - - process_blocks(blocks_start_height, blocks, o_indices, added_blocks); - blocks_fetched += added_blocks; - pull_thread.join(); - if(!added_blocks) - break; - - // switch to the new blocks from the daemon - blocks_start_height = next_blocks_start_height; - blocks = next_blocks; - o_indices = next_o_indices; + pull_blocks(start_height, blocks_start_height, short_chain_history, blocks, o_indices); + // always reset start_height to 0 to force short_chain_ history to be used on + // subsequent pulls in this refresh. + start_height = 0; - // handle error from async fetching thread - if (error) - { - throw std::runtime_error("proxy exception in refresh thread"); - } - } - catch (const std::exception&) + while(m_run.load(std::memory_order_relaxed)) { - blocks_fetched += added_blocks; - if (pull_thread.joinable()) - pull_thread.join(); - if(try_count < 3) + try { - LOG_PRINT_L1("Another try pull_blocks (try_count=" << try_count << ")..."); - ++try_count; + // pull the next set of blocks while we're processing the current one + uint64_t next_blocks_start_height; + std::list<cryptonote::block_complete_entry> next_blocks; + std::vector<cryptonote::COMMAND_RPC_GET_BLOCKS_FAST::block_output_indices> next_o_indices; + bool error = false; + pull_thread = boost::thread([&]{pull_next_blocks(start_height, next_blocks_start_height, short_chain_history, blocks, next_blocks, next_o_indices, error);}); + + process_blocks(blocks_start_height, blocks, o_indices, added_blocks); + blocks_fetched += added_blocks; + pull_thread.join(); + if(!added_blocks) + break; + + // switch to the new blocks from the daemon + blocks_start_height = next_blocks_start_height; + blocks = next_blocks; + o_indices = next_o_indices; + + // handle error from async fetching thread + if (error) + { + throw std::runtime_error("proxy exception in refresh thread"); + } } - else + catch (const std::exception&) { - LOG_ERROR("pull_blocks failed, try_count=" << try_count); - throw; + blocks_fetched += added_blocks; + if (pull_thread.joinable()) + pull_thread.join(); + if(try_count < 3) + { + LOG_PRINT_L1("Another try pull_blocks (try_count=" << try_count << ")..."); + ++try_count; + } + else + { + LOG_ERROR("pull_blocks failed, try_count=" << try_count); + throw; + } } } } @@ -2195,7 +2221,7 @@ bool wallet2::prepare_file_names(const std::string& file_path) return true; } //---------------------------------------------------------------------------------------------------- -bool wallet2::check_connection(bool *same_version) +bool wallet2::check_connection(uint32_t *version) { boost::lock_guard<boost::mutex> lock(m_daemon_rpc_mutex); @@ -2213,7 +2239,7 @@ bool wallet2::check_connection(bool *same_version) return false; } - if (same_version) + if (version) { epee::json_rpc::request<cryptonote::COMMAND_RPC_GET_VERSION::request> req_t = AUTO_VAL_INIT(req_t); epee::json_rpc::response<cryptonote::COMMAND_RPC_GET_VERSION::response, std::string> resp_t = AUTO_VAL_INIT(resp_t); @@ -2222,9 +2248,9 @@ bool wallet2::check_connection(bool *same_version) req_t.method = "get_version"; bool r = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/json_rpc", req_t, resp_t, m_http_client); if (!r || resp_t.result.status != CORE_RPC_STATUS_OK) - *same_version = false; + *version = 0; else - *same_version = resp_t.result.version == CORE_RPC_VERSION; + *version = resp_t.result.version; } return true; @@ -2327,6 +2353,11 @@ void wallet2::check_genesis(const crypto::hash& genesis_hash) const { THROW_WALLET_EXCEPTION_IF(genesis_hash != m_blockchain[0], error::wallet_internal_error, what); } //---------------------------------------------------------------------------------------------------- +std::string wallet2::path() const +{ + return m_wallet_file; +} +//---------------------------------------------------------------------------------------------------- void wallet2::store() { store_to("", ""); @@ -2730,7 +2761,7 @@ void wallet2::add_unconfirmed_tx(const cryptonote::transaction& tx, uint64_t amo utd.m_amount_out = 0; for (const auto &d: dests) utd.m_amount_out += d.amount; - utd.m_amount_out += change_amount; + utd.m_amount_out += change_amount; // dests does not contain change utd.m_change = change_amount; utd.m_sent_time = time(NULL); utd.m_tx = (const cryptonote::transaction_prefix&)tx; @@ -3057,7 +3088,7 @@ bool wallet2::sign_tx(const std::string &unsigned_filename, const std::string &s ptx.change_dts = sd.change_dts; ptx.selected_transfers = sd.selected_transfers; ptx.tx_key = rct::rct2sk(rct::identity()); // don't send it back to the untrusted view wallet - ptx.dests = sd.splitted_dsts; + ptx.dests = sd.dests; ptx.construction_data = sd; txs.push_back(ptx); @@ -3335,8 +3366,8 @@ void wallet2::get_outs(std::vector<std::vector<entry>> &outs, const std::list<si LOG_PRINT_L2("base_requested_outputs_count: " << base_requested_outputs_count); // generate output indices to request - COMMAND_RPC_GET_OUTPUTS::request req = AUTO_VAL_INIT(req); - COMMAND_RPC_GET_OUTPUTS::response daemon_resp = AUTO_VAL_INIT(daemon_resp); + COMMAND_RPC_GET_OUTPUTS_BIN::request req = AUTO_VAL_INIT(req); + COMMAND_RPC_GET_OUTPUTS_BIN::response daemon_resp = AUTO_VAL_INIT(daemon_resp); size_t num_selected_transfers = 0; for(size_t idx: selected_transfers) @@ -3442,7 +3473,7 @@ void wallet2::get_outs(std::vector<std::vector<entry>> &outs, const std::list<si // sort the subsection, to ensure the daemon doesn't know wich output is ours std::sort(req.outputs.begin() + start, req.outputs.end(), - [](const COMMAND_RPC_GET_OUTPUTS::out &a, const COMMAND_RPC_GET_OUTPUTS::out &b) { return a.index < b.index; }); + [](const get_outputs_out &a, const get_outputs_out &b) { return a.index < b.index; }); } for (auto i: req.outputs) @@ -3656,6 +3687,7 @@ void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_ent ptx.construction_data.extra = tx.extra; ptx.construction_data.unlock_time = unlock_time; ptx.construction_data.use_rct = false; + ptx.construction_data.dests = dsts; } void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry> dsts, const std::list<size_t> selected_transfers, size_t fake_outputs_count, @@ -3776,6 +3808,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry ptx.construction_data.extra = tx.extra; ptx.construction_data.unlock_time = unlock_time; ptx.construction_data.use_rct = true; + ptx.construction_data.dests = dsts; } static size_t estimate_rct_tx_size(int n_inputs, int mixin, int n_outputs) @@ -4688,6 +4721,53 @@ bool wallet2::verify(const std::string &data, const cryptonote::account_public_a return crypto::check_signature(hash, address.m_spend_public_key, s); } //---------------------------------------------------------------------------------------------------- +crypto::public_key wallet2::get_tx_pub_key_from_received_outs(const tools::wallet2::transfer_details &td) const +{ + std::vector<tx_extra_field> tx_extra_fields; + if(!parse_tx_extra(td.m_tx.extra, tx_extra_fields)) + { + // Extra may only be partially parsed, it's OK if tx_extra_fields contains public key + } + + // Due to a previous bug, there might be more than one tx pubkey in extra, one being + // the result of a previously discarded signature. + // For speed, since scanning for outputs is a slow process, we check whether extra + // contains more than one pubkey. If not, the first one is returned. If yes, they're + // checked for whether they yield at least one output + tx_extra_pub_key pub_key_field; + THROW_WALLET_EXCEPTION_IF(!find_tx_extra_field_by_type(tx_extra_fields, pub_key_field, 0), error::wallet_internal_error, + "Public key wasn't found in the transaction extra"); + const crypto::public_key tx_pub_key = pub_key_field.pub_key; + bool two_found = find_tx_extra_field_by_type(tx_extra_fields, pub_key_field, 1); + if (!two_found) { + // easy case, just one found + return tx_pub_key; + } + + // more than one, loop and search + const cryptonote::account_keys& keys = m_account.get_keys(); + size_t pk_index = 0; + while (find_tx_extra_field_by_type(tx_extra_fields, pub_key_field, pk_index++)) { + const crypto::public_key tx_pub_key = pub_key_field.pub_key; + crypto::key_derivation derivation; + generate_key_derivation(tx_pub_key, keys.m_view_secret_key, derivation); + + for (size_t i = 0; i < td.m_tx.vout.size(); ++i) + { + uint64_t money_transfered = 0; + bool error = false, received = false; + check_acc_out_precomp(keys.m_account_address.m_spend_public_key, td.m_tx.vout[i], derivation, i, received, money_transfered, error); + if (!error && received) + return tx_pub_key; + } + } + + // we found no key yielding an output + THROW_WALLET_EXCEPTION_IF(true, error::wallet_internal_error, + "Public key yielding at least one output wasn't found in the transaction extra"); + return cryptonote::null_pkey; +} +//---------------------------------------------------------------------------------------------------- std::vector<std::pair<crypto::key_image, crypto::signature>> wallet2::export_key_images() const { std::vector<std::pair<crypto::key_image, crypto::signature>> ski; @@ -4713,10 +4793,8 @@ std::vector<std::pair<crypto::key_image, crypto::signature>> wallet2::export_key { // Extra may only be partially parsed, it's OK if tx_extra_fields contains public key } - tx_extra_pub_key pub_key_field; - THROW_WALLET_EXCEPTION_IF(!find_tx_extra_field_by_type(tx_extra_fields, pub_key_field), error::wallet_internal_error, - "Public key wasn't found in the transaction extra"); - crypto::public_key tx_pub_key = pub_key_field.pub_key; + + crypto::public_key tx_pub_key = get_tx_pub_key_from_received_outs(td); // generate ephemeral secret key crypto::key_image ki; @@ -4845,10 +4923,9 @@ size_t wallet2::import_outputs(const std::vector<tools::wallet2::transfer_detail THROW_WALLET_EXCEPTION_IF(td.m_tx.vout.empty(), error::wallet_internal_error, "tx with no outputs at index " + boost::lexical_cast<std::string>(i)); THROW_WALLET_EXCEPTION_IF(!parse_tx_extra(td.m_tx.extra, tx_extra_fields), error::wallet_internal_error, "Transaction extra has unsupported format at index " + boost::lexical_cast<std::string>(i)); - THROW_WALLET_EXCEPTION_IF(!find_tx_extra_field_by_type(tx_extra_fields, pub_key_field), error::wallet_internal_error, - "Public key wasn't found in the transaction extra at index " + boost::lexical_cast<std::string>(i)); + crypto::public_key tx_pub_key = get_tx_pub_key_from_received_outs(td); - cryptonote::generate_key_image_helper(m_account.get_keys(), pub_key_field.pub_key, td.m_internal_output_index, in_ephemeral, td.m_key_image); + cryptonote::generate_key_image_helper(m_account.get_keys(), tx_pub_key, td.m_internal_output_index, in_ephemeral, td.m_key_image); td.m_key_image_known = true; THROW_WALLET_EXCEPTION_IF(in_ephemeral.pub != boost::get<cryptonote::txout_to_key>(td.m_tx.vout[td.m_internal_output_index].target).key, error::wallet_internal_error, "key_image generated ephemeral public key not matched with output_key at index " + boost::lexical_cast<std::string>(i)); @@ -4889,14 +4966,15 @@ std::string wallet2::encrypt_with_view_secret_key(const std::string &plaintext, //---------------------------------------------------------------------------------------------------- std::string wallet2::decrypt(const std::string &ciphertext, const crypto::secret_key &skey, bool authenticated) const { - THROW_WALLET_EXCEPTION_IF(ciphertext.size() < sizeof(chacha8_iv), - error::wallet_internal_error, "key_image generated ephemeral public key not matched with output_key"); + const size_t prefix_size = sizeof(chacha8_iv) + (authenticated ? sizeof(crypto::signature) : 0); + THROW_WALLET_EXCEPTION_IF(ciphertext.size() < prefix_size, + error::wallet_internal_error, "Unexpected ciphertext size"); crypto::chacha8_key key; crypto::generate_chacha8_key(&skey, sizeof(skey), key); const crypto::chacha8_iv &iv = *(const crypto::chacha8_iv*)&ciphertext[0]; std::string plaintext; - plaintext.resize(ciphertext.size() - sizeof(iv) - (authenticated ? sizeof(crypto::signature) : 0)); + plaintext.resize(ciphertext.size() - prefix_size); if (authenticated) { crypto::hash hash; @@ -4907,7 +4985,7 @@ std::string wallet2::decrypt(const std::string &ciphertext, const crypto::secret THROW_WALLET_EXCEPTION_IF(!crypto::check_signature(hash, pkey, signature), error::wallet_internal_error, "Failed to authenticate criphertext"); } - crypto::chacha8(ciphertext.data() + sizeof(iv), ciphertext.size() - sizeof(iv), key, iv, &plaintext[0]); + crypto::chacha8(ciphertext.data() + sizeof(iv), ciphertext.size() - prefix_size, key, iv, &plaintext[0]); return std::move(plaintext); } //---------------------------------------------------------------------------------------------------- diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 6168873d5..f62a0f15b 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -191,11 +191,12 @@ namespace tools { std::vector<cryptonote::tx_source_entry> sources; cryptonote::tx_destination_entry change_dts; - std::vector<cryptonote::tx_destination_entry> splitted_dsts; + std::vector<cryptonote::tx_destination_entry> splitted_dsts; // split, includes change std::list<size_t> selected_transfers; std::vector<uint8_t> extra; uint64_t unlock_time; bool use_rct; + std::vector<cryptonote::tx_destination_entry> dests; // original setup, does not include change BEGIN_SERIALIZE_OBJECT() FIELD(sources) @@ -205,12 +206,16 @@ namespace tools FIELD(extra) VARINT_FIELD(unlock_time) FIELD(use_rct) + FIELD(dests) END_SERIALIZE() }; typedef std::vector<transfer_details> transfer_container; typedef std::unordered_multimap<crypto::hash, payment_details> payment_container; + // The convention for destinations is: + // dests does not include change + // splitted_dsts (in construction_data) does struct pending_tx { cryptonote::transaction tx; @@ -327,6 +332,8 @@ namespace tools */ void store_to(const std::string &path, const std::string &password); + std::string path() const; + /*! * \brief verifies given password is correct for default wallet keys file */ @@ -403,7 +410,7 @@ namespace tools std::vector<wallet2::pending_tx> create_transactions_all(const cryptonote::account_public_address &address, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t> extra, bool trusted_daemon); std::vector<wallet2::pending_tx> create_transactions_from(const cryptonote::account_public_address &address, std::vector<size_t> unused_transfers_indices, std::vector<size_t> unused_dust_indices, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t> extra, bool trusted_daemon); std::vector<pending_tx> create_unmixable_sweep_transactions(bool trusted_daemon); - bool check_connection(bool *same_version = NULL); + bool check_connection(uint32_t *version = NULL); void get_transfers(wallet2::transfer_container& incoming_transfers) const; void get_payments(const crypto::hash& payment_id, std::list<wallet2::payment_details>& payments, uint64_t min_height = 0) const; void get_payments(std::list<std::pair<crypto::hash,wallet2::payment_details>>& payments, uint64_t min_height, uint64_t max_height = (uint64_t)-1) const; @@ -591,6 +598,7 @@ namespace tools template<typename entry> void get_outs(std::vector<std::vector<entry>> &outs, const std::list<size_t> &selected_transfers, size_t fake_outputs_count); bool wallet_generate_key_image_helper(const cryptonote::account_keys& ack, const crypto::public_key& tx_public_key, size_t real_output_index, cryptonote::keypair& in_ephemeral, crypto::key_image& ki); + crypto::public_key get_tx_pub_key_from_received_outs(const tools::wallet2::transfer_details &td) const; cryptonote::account_base m_account; std::string m_daemon_address; @@ -1047,6 +1055,7 @@ namespace tools ptx.construction_data.extra = tx.extra; ptx.construction_data.unlock_time = unlock_time; ptx.construction_data.use_rct = false; + ptx.construction_data.dests = dsts; } diff --git a/src/wallet/wallet2_api.h b/src/wallet/wallet2_api.h index 185d1c009..60907b436 100644 --- a/src/wallet/wallet2_api.h +++ b/src/wallet/wallet2_api.h @@ -195,6 +195,7 @@ struct Wallet virtual std::string errorString() const = 0; virtual bool setPassword(const std::string &password) = 0; virtual std::string address() const = 0; + virtual std::string path() const = 0; /*! * \brief integratedAddress - returns integrated address for current wallet address and given payment_id. diff --git a/tests/unit_tests/CMakeLists.txt b/tests/unit_tests/CMakeLists.txt index f3658b9ff..78dd74529 100644 --- a/tests/unit_tests/CMakeLists.txt +++ b/tests/unit_tests/CMakeLists.txt @@ -35,6 +35,7 @@ set(unit_tests_sources canonical_amounts.cpp chacha8.cpp checkpoints.cpp + command_line.cpp decompose_amount_into_digits.cpp dns_resolver.cpp epee_boosted_tcp_server.cpp @@ -50,6 +51,7 @@ set(unit_tests_sources test_format_utils.cpp test_peerlist.cpp test_protocol_pack.cpp + thread_group.cpp hardfork.cpp unbound.cpp varint.cpp diff --git a/tests/unit_tests/command_line.cpp b/tests/unit_tests/command_line.cpp new file mode 100644 index 000000000..4e1c9bff4 --- /dev/null +++ b/tests/unit_tests/command_line.cpp @@ -0,0 +1,50 @@ +// Copyright (c) 2014-2016, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#include "gtest/gtest.h" +#include "common/command_line.h" + +TEST(CommandLine, IsYes) +{ + EXPECT_TRUE(command_line::is_yes("Y")); + EXPECT_TRUE(command_line::is_yes("y")); + EXPECT_TRUE(command_line::is_yes("YES")); + EXPECT_TRUE(command_line::is_yes("YEs")); + EXPECT_TRUE(command_line::is_yes("YeS")); + EXPECT_TRUE(command_line::is_yes("yES")); + EXPECT_TRUE(command_line::is_yes("Yes")); + EXPECT_TRUE(command_line::is_yes("yeS")); + EXPECT_TRUE(command_line::is_yes("yEs")); + EXPECT_TRUE(command_line::is_yes("yes")); + + EXPECT_FALSE(command_line::is_yes("")); + EXPECT_FALSE(command_line::is_yes("yes-")); + EXPECT_FALSE(command_line::is_yes("NO")); + EXPECT_FALSE(command_line::is_yes("No")); + EXPECT_FALSE(command_line::is_yes("nO")); + EXPECT_FALSE(command_line::is_yes("no")); +} diff --git a/tests/unit_tests/epee_levin_protocol_handler_async.cpp b/tests/unit_tests/epee_levin_protocol_handler_async.cpp index ca110eb59..2dd3ffe29 100644 --- a/tests/unit_tests/epee_levin_protocol_handler_async.cpp +++ b/tests/unit_tests/epee_levin_protocol_handler_async.cpp @@ -242,6 +242,7 @@ namespace m_req_head.m_cb = m_in_data.size(); m_req_head.m_have_to_return_data = true; m_req_head.m_command = expected_command; + m_req_head.m_return_code = LEVIN_OK; m_req_head.m_flags = LEVIN_PACKET_REQUEST; m_req_head.m_protocol_version = LEVIN_PROTOCOL_VER_1; diff --git a/tests/unit_tests/hardfork.cpp b/tests/unit_tests/hardfork.cpp index 7b4874811..be2885f45 100644 --- a/tests/unit_tests/hardfork.cpp +++ b/tests/unit_tests/hardfork.cpp @@ -117,7 +117,7 @@ public: blocks.push_back(blk); } virtual block get_block_from_height(const uint64_t& height) const { - return blocks[height]; + return blocks.at(height); } virtual void set_hard_fork_version(uint64_t height, uint8_t version) { if (versions.size() <= height) @@ -125,7 +125,7 @@ public: versions[height] = version; } virtual uint8_t get_hard_fork_version(uint64_t height) const { - return versions[height]; + return versions.at(height); } virtual void check_hard_fork_info() {} diff --git a/tests/unit_tests/serialization.cpp b/tests/unit_tests/serialization.cpp index dc7f7cb06..b592f456b 100644 --- a/tests/unit_tests/serialization.cpp +++ b/tests/unit_tests/serialization.cpp @@ -395,7 +395,10 @@ TEST(Serialization, serializes_transacion_signatures_correctly) // Not enough signature vectors for all inputs txin_to_key txin_to_key1; - txin_to_key1.key_offsets.resize(2); + txin_to_key1.amount = 1; + memset(&txin_to_key1.k_image, 0x42, sizeof(crypto::key_image)); + txin_to_key1.key_offsets.push_back(12); + txin_to_key1.key_offsets.push_back(3453); tx.vin.clear(); tx.vin.push_back(txin_to_key1); tx.vin.push_back(txin_to_key1); diff --git a/tests/unit_tests/thread_group.cpp b/tests/unit_tests/thread_group.cpp new file mode 100644 index 000000000..2e7a78353 --- /dev/null +++ b/tests/unit_tests/thread_group.cpp @@ -0,0 +1,177 @@ +// Copyright (c) 2014-2016, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "gtest/gtest.h" + +#include <atomic> +#include "common/task_region.h" +#include "common/thread_group.h" + +TEST(ThreadGroup, NoThreads) +{ + tools::task_region(tools::thread_group(0), [] (tools::task_region_handle& region) { + std::atomic<bool> completed{false}; + region.run([&] { completed = true; }); + EXPECT_TRUE(completed); + }); + { + tools::thread_group group(0); + std::atomic<bool> completed{false}; + group.dispatch([&] { completed = true; }); + EXPECT_TRUE(completed); + } +} + +TEST(ThreadGroup, OneThread) +{ + tools::thread_group group(1); + + for (unsigned i = 0; i < 3; ++i) { + std::atomic<bool> completed{false}; + tools::task_region(group, [&] (tools::task_region_handle& region) { + region.run([&] { completed = true; }); + }); + EXPECT_TRUE(completed); + } +} + + +TEST(ThreadGroup, UseActiveThreadOnSync) +{ + tools::thread_group group(1); + + for (unsigned i = 0; i < 3; ++i) { + std::atomic<bool> completed{false}; + tools::task_region(group, [&] (tools::task_region_handle& region) { + region.run([&] { while (!completed); }); + region.run([&] { completed = true; }); + }); + EXPECT_TRUE(completed); + } +} + +TEST(ThreadGroup, InOrder) +{ + tools::thread_group group(1); + + for (unsigned i = 0; i < 3; ++i) { + std::atomic<unsigned> count{0}; + std::atomic<bool> completed{false}; + tools::task_region(group, [&] (tools::task_region_handle& region) { + region.run([&] { while (!completed); }); + region.run([&] { if (count == 0) completed = true; }); + region.run([&] { ++count; }); + }); + EXPECT_TRUE(completed); + EXPECT_EQ(1u, count); + } +} + +TEST(ThreadGroup, TwoThreads) +{ + tools::thread_group group(2); + + for (unsigned i = 0; i < 3; ++i) { + std::atomic<bool> completed{false}; + tools::task_region(group, [&] (tools::task_region_handle& region) { + region.run([&] { while (!completed); }); + region.run([&] { while (!completed); }); + region.run([&] { completed = true; }); + }); + EXPECT_TRUE(completed); + } +} + +TEST(ThreadGroup, Nested) { + struct fib { + unsigned operator()(tools::thread_group& group, unsigned value) const { + if (value == 0 || value == 1) { + return value; + } + unsigned left = 0; + unsigned right = 0; + tools::task_region(group, [&, value] (tools::task_region_handle& region) { + region.run([&, value] { left = fib{}(group, value - 1); }); + region.run([&, value] { right = fib{}(group, value - 2); } ); + }); + return left + right; + } + + unsigned operator()(tools::thread_group&& group, unsigned value) const { + return (*this)(group, value); + } + }; + // be careful of depth on asynchronous version + EXPECT_EQ(6765, fib{}(tools::thread_group(0), 20)); + EXPECT_EQ(377, fib{}(tools::thread_group(1), 14)); +} + +TEST(ThreadGroup, Many) +{ + tools::thread_group group(1); + + for (unsigned i = 0; i < 3; ++i) { + std::atomic<unsigned> count{0}; + tools::task_region(group, [&] (tools::task_region_handle& region) { + for (unsigned tasks = 0; tasks < 1000; ++tasks) { + region.run([&] { ++count; }); + } + }); + EXPECT_EQ(1000u, count); + } +} + +TEST(ThreadGroup, ThrowInTaskRegion) +{ + class test_exception final : std::exception { + public: + explicit test_exception() : std::exception() {} + + virtual const char* what() const noexcept override { + return "test_exception"; + } + }; + + tools::thread_group group(1); + + for (unsigned i = 0; i < 3; ++i) { + std::atomic<unsigned> count{0}; + EXPECT_THROW( + [&] { + tools::task_region(group, [&] (tools::task_region_handle& region) { + for (unsigned tasks = 0; tasks < 1000; ++tasks) { + region.run([&] { ++count; }); + } + throw test_exception(); + }); + }(), + test_exception + ); + EXPECT_GE(1000u, count); + } +} diff --git a/translations/monero.ts b/translations/monero.ts index 5f154944b..0dcb09d06 100644 --- a/translations/monero.ts +++ b/translations/monero.ts @@ -32,109 +32,109 @@ <context> <name>Bitmonero::WalletImpl</name> <message> - <location filename="../src/wallet/api/wallet.cpp" line="593"/> + <location filename="../src/wallet/api/wallet.cpp" line="604"/> <source>payment id has invalid format, expected 16 or 64 character hex string: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/api/wallet.cpp" line="609"/> - <location filename="../src/wallet/api/wallet.cpp" line="703"/> + <location filename="../src/wallet/api/wallet.cpp" line="629"/> + <location filename="../src/wallet/api/wallet.cpp" line="723"/> <source>daemon is busy. Please try again later.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/api/wallet.cpp" line="612"/> - <location filename="../src/wallet/api/wallet.cpp" line="706"/> + <location filename="../src/wallet/api/wallet.cpp" line="632"/> + <location filename="../src/wallet/api/wallet.cpp" line="726"/> <source>no connection to daemon. Please make sure daemon is running.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/api/wallet.cpp" line="615"/> - <location filename="../src/wallet/api/wallet.cpp" line="709"/> + <location filename="../src/wallet/api/wallet.cpp" line="635"/> + <location filename="../src/wallet/api/wallet.cpp" line="729"/> <source>RPC error: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/api/wallet.cpp" line="618"/> - <location filename="../src/wallet/api/wallet.cpp" line="712"/> + <location filename="../src/wallet/api/wallet.cpp" line="638"/> + <location filename="../src/wallet/api/wallet.cpp" line="732"/> <source>failed to get random outputs to mix</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/api/wallet.cpp" line="625"/> - <location filename="../src/wallet/api/wallet.cpp" line="719"/> + <location filename="../src/wallet/api/wallet.cpp" line="645"/> + <location filename="../src/wallet/api/wallet.cpp" line="739"/> <source>not enough money to transfer, available only %s, sent amount %s</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/api/wallet.cpp" line="634"/> - <location filename="../src/wallet/api/wallet.cpp" line="728"/> + <location filename="../src/wallet/api/wallet.cpp" line="654"/> + <location filename="../src/wallet/api/wallet.cpp" line="748"/> <source>not enough money to transfer, available only %s, transaction amount %s = %s + %s (fee)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/api/wallet.cpp" line="643"/> - <location filename="../src/wallet/api/wallet.cpp" line="737"/> + <location filename="../src/wallet/api/wallet.cpp" line="663"/> + <location filename="../src/wallet/api/wallet.cpp" line="757"/> <source>not enough outputs for specified mixin_count</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/api/wallet.cpp" line="645"/> - <location filename="../src/wallet/api/wallet.cpp" line="739"/> + <location filename="../src/wallet/api/wallet.cpp" line="665"/> + <location filename="../src/wallet/api/wallet.cpp" line="759"/> <source>output amount</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/api/wallet.cpp" line="645"/> - <location filename="../src/wallet/api/wallet.cpp" line="739"/> + <location filename="../src/wallet/api/wallet.cpp" line="665"/> + <location filename="../src/wallet/api/wallet.cpp" line="759"/> <source>found outputs to mix</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/api/wallet.cpp" line="650"/> - <location filename="../src/wallet/api/wallet.cpp" line="744"/> + <location filename="../src/wallet/api/wallet.cpp" line="670"/> + <location filename="../src/wallet/api/wallet.cpp" line="764"/> <source>transaction was not constructed</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/api/wallet.cpp" line="654"/> - <location filename="../src/wallet/api/wallet.cpp" line="748"/> + <location filename="../src/wallet/api/wallet.cpp" line="674"/> + <location filename="../src/wallet/api/wallet.cpp" line="768"/> <source>transaction %s was rejected by daemon with status: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/api/wallet.cpp" line="661"/> - <location filename="../src/wallet/api/wallet.cpp" line="755"/> + <location filename="../src/wallet/api/wallet.cpp" line="681"/> + <location filename="../src/wallet/api/wallet.cpp" line="775"/> <source>one of destinations is zero</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/api/wallet.cpp" line="664"/> - <location filename="../src/wallet/api/wallet.cpp" line="758"/> + <location filename="../src/wallet/api/wallet.cpp" line="684"/> + <location filename="../src/wallet/api/wallet.cpp" line="778"/> <source>failed to find a suitable way to split transactions</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/api/wallet.cpp" line="667"/> - <location filename="../src/wallet/api/wallet.cpp" line="761"/> + <location filename="../src/wallet/api/wallet.cpp" line="687"/> + <location filename="../src/wallet/api/wallet.cpp" line="781"/> <source>unknown transfer error: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/api/wallet.cpp" line="670"/> - <location filename="../src/wallet/api/wallet.cpp" line="764"/> + <location filename="../src/wallet/api/wallet.cpp" line="690"/> + <location filename="../src/wallet/api/wallet.cpp" line="784"/> <source>internal error: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/api/wallet.cpp" line="673"/> - <location filename="../src/wallet/api/wallet.cpp" line="767"/> + <location filename="../src/wallet/api/wallet.cpp" line="693"/> + <location filename="../src/wallet/api/wallet.cpp" line="787"/> <source>unexpected error: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/api/wallet.cpp" line="676"/> - <location filename="../src/wallet/api/wallet.cpp" line="770"/> + <location filename="../src/wallet/api/wallet.cpp" line="696"/> + <location filename="../src/wallet/api/wallet.cpp" line="790"/> <source>unknown error</source> <translation type="unfinished"></translation> </message> @@ -204,1041 +204,1055 @@ </message> </context> <context> + <name>command_line</name> + <message> + <location filename="../src/common/command_line.cpp" line="67"/> + <source>yes</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> <name>cryptonote::simple_wallet</name> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="276"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="272"/> <source>Commands: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="352"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="379"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="409"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="455"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="517"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="553"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="590"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="620"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="1491"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="1498"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="350"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="377"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="407"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="453"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="515"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="551"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="588"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="618"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1492"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1499"/> <source>failed to read wallet password</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="360"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="387"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="417"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="463"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="525"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="561"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="598"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="628"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="358"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="385"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="415"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="461"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="523"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="559"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="596"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="626"/> <source>invalid password</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="651"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="649"/> <source>start_mining [<number_of_threads>] - Start mining in daemon</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="652"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="650"/> <source>Stop mining in daemon</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="653"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="651"/> <source>Save current blockchain data</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="655"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="653"/> <source>Show current wallet balance</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="658"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="656"/> <source>Show blockchain height</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="667"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="665"/> <source>Show current wallet public address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="689"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="687"/> <source>Show this help</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="712"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="710"/> <source>set seed: needs an argument. available options: language</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="727"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="725"/> <source>set always-confirm-transfers: needs an argument (0 or 1)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="830"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="828"/> <source>set: unrecognized argument(s)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="845"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="843"/> <source>wrong number format, use: set_log <log_level_number_0-4></source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="850"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="848"/> <source>wrong number range, use: set_log <log_level_number_0-4></source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1374"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1375"/> <source>wallet file path not valid: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="892"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="890"/> <source>Attempting to generate or restore wallet, but specified file(s) exist. Exiting to not risk overwriting.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="941"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="939"/> <source>PLEASE NOTE: the following 25 words can be used to recover access to your wallet. Please write them down and store them somewhere safe and secure. Please do not store them in your email or on file storage services outside of your immediate control. </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="986"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="982"/> <source>specify a recovery parameter with the --electrum-seed="words list here"</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1195"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1196"/> <source>wallet failed to connect to daemon: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1223"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1224"/> <source>List of available languages for your wallet's seed:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1232"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1233"/> <source>Enter the number corresponding to the language of your choice: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1276"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1277"/> <source>You had been using a deprecated version of the wallet. Please use the new seed that we provide. </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1300"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="1357"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1301"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1358"/> <source>Generated new wallet: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1306"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="1362"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1307"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1363"/> <source>failed to generate new wallet: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1389"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1390"/> <source>Opened watch-only wallet</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1389"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1390"/> <source>Opened wallet</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1398"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1399"/> <source>You had been using a deprecated version of the wallet. Please proceed to upgrade your wallet. </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1413"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1414"/> <source>You had been using a deprecated version of the wallet. Your wallet file format is being upgraded now. </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1421"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1422"/> <source>failed to load wallet: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1429"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1430"/> <source>Use "help" command to see the list of available commands. </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1473"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1474"/> <source>Wallet data saved</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1488"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1489"/> <source>Password for the new watch-only wallet</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1495"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1496"/> <source>Enter new password again</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1503"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1504"/> <source>passwords do not match</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1547"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1548"/> <source>invalid arguments. Please use start_mining [<number_of_threads>], <number_of_threads> should be from 1 to </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1556"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1557"/> <source>Mining started in daemon</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1558"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1559"/> <source>mining has NOT been started: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1573"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1574"/> <source>Mining stopped in daemon</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1575"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1576"/> <source>mining has NOT been stopped: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1590"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1591"/> <source>Blockchain saved</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1605"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="1617"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="1629"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1606"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1618"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1630"/> <source>Height </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1606"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="1618"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="1630"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1607"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1619"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1631"/> <source>transaction </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1607"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1608"/> <source>received </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1619"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1620"/> <source>spent </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1631"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1632"/> <source>unsupported transaction format</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1648"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1649"/> <source>Starting refresh...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1661"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1662"/> <source>Refresh done, blocks received: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1970"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1982"/> <source>you have cancelled the transfer request</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1976"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1988"/> <source>failed to get a Monero address from: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1982"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1994"/> <source>not yet supported: Multiple Monero addresses found for given URL: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1987"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1999"/> <source>wrong address: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2055"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2555"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2067"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2572"/> <source>payment id has invalid format, expected 16 or 64 character hex string: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2070"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2082"/> <source>bad locked_blocks parameter:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2075"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2087"/> <source>Locked blocks too high, max 1000000 (˜4 yrs)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2094"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2577"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2106"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2594"/> <source>a single transaction cannot use more than one payment id: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2103"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2586"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2115"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2603"/> <source>failed to set up payment id, though it was decoded correctly</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2123"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2595"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2135"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2612"/> <source>No payment id is included with this transaction. Is this okay? (Y/Yes/N/No)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2128"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2207"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2386"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2600"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2645"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2918"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2140"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2224"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2403"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2617"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2662"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2967"/> <source>transaction cancelled.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2183"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2899"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2197"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2945"/> + <source>Sending %s. </source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/simplewallet/simplewallet.cpp" line="2200"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2948"/> <source>Your transaction needs to be split into %llu transactions. This will result in a transaction fee being applied to each transaction, for a total fee of %s</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2189"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2905"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2206"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2954"/> <source>The transaction fee is %s</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2192"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2908"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2209"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2957"/> <source>, of which %s is dust from change</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2193"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2200"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2909"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2911"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2210"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2217"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2958"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2960"/> <source>.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2193"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2909"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2210"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2958"/> <source>A total of %s from dust change will be sent to dust address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2198"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2215"/> <source>. This transaction will unlock on block %llu, in approximately %s days (assuming 2 minutes per block)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2200"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2911"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2217"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2960"/> <source>Is this okay? (Y/Yes/N/No)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2221"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2399"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2658"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2238"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2416"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2675"/> <source>Failed to write transaction(s) to file</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2225"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2403"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2662"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2242"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2420"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2679"/> <source>Unsigned transaction(s) successfully written to file: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2260"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2438"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2697"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2959"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2277"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2455"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2714"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3008"/> <source>Not enough money in unlocked balance</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2269"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2447"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2706"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2968"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2286"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2464"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2723"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3017"/> <source>Failed to find a way to create transactions. This is usually due to dust which is so small it cannot pay for itself in fees, or trying to send more money than the unlocked balance, or not leaving enough for fees</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2289"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2467"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2726"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2306"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2484"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2743"/> <source>Reason: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2301"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2479"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2738"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2318"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2496"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2755"/> <source>failed to find a suitable way to split transactions</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2356"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2373"/> <source>No unmixable outputs found</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2563"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2580"/> <source>No address given</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2615"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2632"/> <source>No outputs found</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2797"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2814"/> <source>Claimed change does not go to a paid address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2802"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2819"/> <source>Claimed change is larger than payment to the change address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2814"/> - <source>sending %s to %s</source> + <location filename="../src/simplewallet/simplewallet.cpp" line="2824"/> + <source>Change does to more than one address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2820"/> - <source>with no destinations</source> + <location filename="../src/simplewallet/simplewallet.cpp" line="2836"/> + <source>sending %s to %s</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2823"/> - <source>Loaded %lu transactions, for %s, fee %s, change %s, %s, with min mixin %lu. Is this okay? (Y/Yes/N/No)</source> + <location filename="../src/simplewallet/simplewallet.cpp" line="2842"/> + <source>with no destinations</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2851"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2888"/> <source>Failed to sign transaction</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2857"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2894"/> <source>Failed to sign transaction: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2861"/> - <source>Transaction successfully signed to file: </source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2876"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2920"/> <source>Failed to load transaction from file</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2939"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2988"/> <source>daemon is busy. Please try later</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1675"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="1909"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2249"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2427"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2686"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2948"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1676"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1922"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2266"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2444"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2703"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2997"/> <source>RPC error: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1685"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2311"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2489"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2748"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="3007"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1686"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2328"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2506"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2765"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3056"/> <source>internal error: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1690"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="1914"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2316"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2494"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2753"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="3012"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1691"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1927"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2333"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2511"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2770"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3061"/> <source>unexpected error: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1695"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="1919"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2321"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2499"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2758"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="3017"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1696"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1932"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2338"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2516"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2775"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3066"/> <source>unknown error</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1700"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1701"/> <source>refresh failed: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1700"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1701"/> <source>Blocks received: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1725"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1726"/> <source>unlocked balance: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1766"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="1810"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1775"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1823"/> <source>amount</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1766"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1775"/> <source>spent</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1766"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1775"/> <source>global index</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1766"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1775"/> <source>tx id</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1784"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1797"/> <source>No incoming transfers</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1788"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1801"/> <source>No incoming available transfers</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1792"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1805"/> <source>No incoming unavailable transfers</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1803"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1816"/> <source>expected at least one payment_id</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1810"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1823"/> <source>payment</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1810"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1823"/> <source>transaction</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1810"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1823"/> <source>height</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1810"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1823"/> <source>unlock time</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1822"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1835"/> <source>No payments with id </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1874"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2148"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1887"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2160"/> <source>failed to get blockchain height: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2021"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2033"/> <source>wrong number of arguments</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2842"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2878"/> <source>This is a watch only wallet</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1947"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1960"/> <source>DNSSEC validation passed</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="256"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="223"/> + <source>true</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/simplewallet/simplewallet.cpp" line="252"/> <source>failed to parse refresh type</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="307"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="339"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="305"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="337"/> <source>wallet is watch-only and has no seed</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="329"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="344"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="327"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="342"/> <source>wallet is non-deterministic and has no seed</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="401"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="431"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="489"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="613"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="399"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="429"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="487"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="611"/> <source>wallet is watch-only and cannot transfer</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="438"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="444"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="473"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="436"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="442"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="471"/> <source>mixin must be an integer >= 2</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="478"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="476"/> <source>could not change default mixin</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="496"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="494"/> <source>priority must be 0, 1, 2, or 3 </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="508"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="506"/> <source>priority must be 0, 1, 2, or 3</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="535"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="533"/> <source>priority must be 0, 1, 2 or 3</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="540"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="538"/> <source>could not change default priority</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="654"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="652"/> <source>Synchronize transactions and balance</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="656"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="654"/> <source>incoming_transfers [available|unavailable] - Show incoming transfers, all or filtered by availability</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="657"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="655"/> <source>payments <PID_1> [<PID_2> ... <PID_N>] - Show payments for given payment ID[s]</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="659"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="657"/> <source>transfer [<mixin_count>] <addr_1> <amount_1> [<addr_2> <amount_2> ... <addr_N> <amount_N>] [payment_id] - Transfer <amount_1>,... <amount_N> to <address_1>,... <address_N>, respectively. <mixin_count> is the number of extra inputs to include for untraceability (from 2 to maximum available)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="660"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="658"/> <source>Same as transfer_original, but using a new transaction building algorithm</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="661"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="659"/> <source>locked_transfer [<mixin_count>] <addr> <amount> <lockblocks>(Number of blocks to lock the transaction for, max 1000000) [<payment_id>]</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="662"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="660"/> <source>Send all unmixable outputs to yourself with mixin 0</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="663"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="661"/> <source>sweep_all [mixin] address [payment_id] - Send all unlocked balance an address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="664"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="662"/> <source>Sign a transaction from a file</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="665"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="663"/> <source>Submit a signed transaction from a file</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="666"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="664"/> <source>set_log <level> - Change current log detail level, <0-4></source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="668"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="666"/> <source>integrated_address [PID] - Encode a payment ID into an integrated address for the current wallet public address (no argument uses a random payment ID), or decode an integrated address to standard address and payment ID</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="669"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="667"/> <source>Save wallet data</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="670"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="668"/> <source>Save a watch-only keys file</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="671"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="669"/> <source>Display private view key</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="672"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="670"/> <source>Display private spend key</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="673"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="671"/> <source>Display Electrum-style mnemonic seed</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="674"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="672"/> <source>Available options: seed language - set wallet seed language; always-confirm-transfers <1|0> - whether to confirm unsplit txes; store-tx-info <1|0> - whether to store outgoing tx info (destination address, payment ID, tx secret key) for future reference; default-mixin <n> - set default mixin (default is 4); auto-refresh <1|0> - whether to automatically sync new blocks from the daemon; refresh-type <full|optimize-coinbase|no-coinbase|default> - set wallet refresh behaviour; priority [1|2|3] - normal/elevated/priority fee; confirm-missing-payment-id <1|0></source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="675"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="673"/> <source>Rescan blockchain for spent outputs</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="676"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="674"/> <source>Get transaction key (r) for a given <txid></source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="677"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="675"/> <source>Check amount going to <address> in <txid></source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="678"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="676"/> <source>show_transfers [in|out] [<min_height> [<max_height>]] - Show incoming/outgoing transfers within an optional height range</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="679"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="677"/> <source>Rescan blockchain from scratch</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="680"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="678"/> <source>Set an arbitrary string note for a txid</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="681"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="679"/> <source>Get a string note for a txid</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="682"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="680"/> <source>Show wallet status information</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="683"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="681"/> <source>Sign the contents of a file</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="684"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="682"/> <source>Verify a signature on the contents of a file</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="685"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="683"/> <source>Export a signed set of key images</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="686"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="684"/> <source>Import signed key images list and verify their spent status</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="687"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="685"/> <source>Export a set of outputs owned by this wallet</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="688"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="686"/> <source>Import set of outputs owned by this wallet</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="742"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="740"/> <source>set store-tx-info: needs an argument (0 or 1)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="757"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="755"/> <source>set default-mixin: needs an argument (integer >= 2)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="772"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="770"/> <source>set auto-refresh: needs an argument (0 or 1)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="787"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="785"/> <source>set refresh-type: needs an argument:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="788"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="786"/> <source>full (slowest, no assumptions); optimize-coinbase (fast, assumes the whole coinbase is paid to a single address); no-coinbase (fastest, assumes we receive no coinbase transaction), default (same as optimize-coinbase)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="803"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="801"/> <source>set priority: needs an argument: 0, 1, 2, or 3</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="818"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="816"/> <source>set confirm-missing-payment-id: needs an argument (0 or 1)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="839"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="837"/> <source>usage: set_log <log_level_number_0-4></source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="870"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="868"/> <source>Specify wallet file name (e.g., MyWallet). If the wallet doesn't exist, it will be created. Wallet file name (or Ctrl-C to quit): </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="880"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="878"/> <source>Wallet name not valid. Please try again or use Ctrl-C to quit.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="897"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="895"/> <source>Wallet and key files found, loading...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="903"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="901"/> <source>Key file found but not wallet file. Regenerating...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="909"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="907"/> <source>Key file not found. Failed to open wallet: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="914"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="912"/> <source>No wallet/key file found with that name. Confirm creation of new wallet named: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="915"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="913"/> <source>(y)es/(n)o: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="923"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="921"/> <source>Generating new wallet...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="957"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="955"/> <source>can't specify more than one of --generate-new-wallet="wallet_name", --wallet-file="wallet_name", --generate-from-view-key="wallet_name", --generate-from-json="jsonfilename" and --generate-from-keys="wallet_name"</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="975"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="971"/> <source>can't specify both --restore-deterministic-wallet and --non-deterministic</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="993"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="989"/> <source>Electrum-style word list failed verification</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1008"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1004"/> <source>bad m_restore_height parameter:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1020"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="1037"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="1071"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="1088"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="1104"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1017"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1034"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1069"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1086"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1102"/> <source>No data supplied, cancelled</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1028"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="1079"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="3098"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="3636"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1025"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1077"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3147"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3685"/> <source>failed to parse address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1043"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="1110"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1040"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1108"/> <source>failed to parse view key secret key</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1053"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="1128"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1050"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1126"/> <source>failed to verify view key secret key</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1057"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="1132"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1054"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1130"/> <source>view key does not match standard address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1062"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="1136"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="1146"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1059"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1134"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1147"/> <source>account creation failed</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1094"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1092"/> <source>failed to parse spend key secret key</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1120"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1118"/> <source>failed to verify spend key secret key</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1124"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1122"/> <source>spend key does not match standard address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1153"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1154"/> <source>failed to open account</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1196"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1197"/> <source>Daemon either is not started or wrong port was passed. Please make sure daemon is running or restart the wallet with the correct daemon address.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1203"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1204"/> <source>Daemon uses a different RPC version that the wallet: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1204"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1205"/> <source>Either update one of them, or use --allow-mismatched-daemon-version.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1241"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="1246"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1242"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1247"/> <source>invalid language choice passed. Please try again. </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1302"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1303"/> <source>View key: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1317"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1318"/> <source>Your wallet has been generated! To start synchronizing with the daemon, use "refresh" command. Use "help" command to see the list of available commands. @@ -1249,489 +1263,509 @@ your wallet again (your wallet keys are NOT at risk in any case). <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1424"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1425"/> <source>You may want to remove the file "%s" and try again</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1450"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1451"/> <source>failed to deinitialize wallet</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1516"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="1882"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1517"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1895"/> <source>this command requires a trusted daemon. Enable with --trusted-daemon</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1592"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1593"/> <source>blockchain can't be saved: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1666"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="1896"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2240"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2418"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2677"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1667"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1909"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2257"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2435"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2694"/> <source>daemon is busy. Please try again later.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1670"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="1900"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2244"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2422"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2681"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1671"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1913"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2261"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2439"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2698"/> <source>no connection to daemon. Please make sure daemon is running.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1680"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1681"/> <source>refresh error: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1724"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1725"/> <source>Balance: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1766"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="1773"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1774"/> + <source>pubkey</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/simplewallet/simplewallet.cpp" line="1774"/> + <source>key image</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/simplewallet/simplewallet.cpp" line="1775"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1785"/> <source>unlocked</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1766"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1775"/> <source>ringct</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1772"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1784"/> <source>T</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1772"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1784"/> <source>F</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1773"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1785"/> <source>locked</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1774"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1786"/> <source>RingCT</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1774"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1786"/> <source>-</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1843"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1856"/> <source>payment ID has invalid format, expected 16 or 64 character hex string: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1904"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1917"/> <source>failed to get spent status</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1951"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1964"/> <source>WARNING: DNSSEC validation was unsuccessful, this address may not be correct!</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1954"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1967"/> <source>For URL: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1956"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1969"/> <source> Monero Address = </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1958"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="1971"/> <source>Is this OK? (Y/n) </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1968"/> - <source>yes</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="1968"/> - <source>no</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3474"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3523"/> <source>usage: integrated_address [payment ID]</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3497"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3546"/> <source>Integrated address: account %s, payment ID %s</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3502"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3551"/> <source>Standard address: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3507"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3556"/> <source>failed to parse payment ID or address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3515"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3564"/> <source>usage: set_tx_note [txid] free text note</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3543"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3592"/> <source>usage: get_tx_note [txid]</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3591"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3640"/> <source>usage: sign <filename></source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3596"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3645"/> <source>wallet is watch-only and cannot sign</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3604"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="3627"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="3714"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="3837"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3653"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3676"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3763"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3886"/> <source>failed to read file </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3616"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3665"/> <source>usage: verify <filename> <address> <signature></source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3643"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3692"/> <source>Bad signature from </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3647"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3696"/> <source>Good signature from </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3656"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3705"/> <source>usage: export_key_images <filename></source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3661"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3710"/> <source>wallet is watch-only and cannot export key images</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3686"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="3809"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3735"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3858"/> <source>failed to save file </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3697"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3746"/> <source>Signed key images exported to </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3705"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3754"/> <source>usage: import_key_images <filename></source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3787"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3836"/> <source>usage: export_outputs <filename></source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3820"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3869"/> <source>Outputs exported to </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3828"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3877"/> <source>usage: import_outputs <filename></source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2112"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2124"/> <source>amount is wrong: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2113"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2125"/> <source>expected number from 0 to </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2232"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2249"/> <source>Money successfully sent, transaction </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2943"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2992"/> <source>no connection to daemon. Please, make sure daemon is running.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2253"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2431"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2690"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2952"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2270"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2448"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2707"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3001"/> <source>failed to get random outputs to mix</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2274"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2452"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2711"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2973"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2291"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2469"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2728"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3022"/> <source>not enough outputs for specified mixin_count</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2277"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2455"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2714"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2976"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2294"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2472"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2731"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3025"/> <source>output amount</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2277"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2455"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2714"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2976"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2294"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2472"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2731"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3025"/> <source>found outputs to mix</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2282"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2460"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2719"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2981"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2299"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2477"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2736"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3030"/> <source>transaction was not constructed</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2286"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2464"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2723"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2985"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2303"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2481"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2740"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3034"/> <source>transaction %s was rejected by daemon with status: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2297"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2475"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2734"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2993"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2314"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2492"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2751"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3042"/> <source>one of destinations is zero</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2997"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3046"/> <source>Failed to find a suitable way to split transactions</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2306"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2484"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2743"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="3002"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2323"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2501"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2760"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3051"/> <source>unknown transfer error: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2369"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2386"/> <source>Sweeping </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2371"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2630"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2388"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2647"/> <source>Sweeping %s in %llu transactions for a total fee of %s. Is this okay? (Y/Yes/N/No)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2377"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2636"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2394"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2653"/> <source>Sweeping %s for a total fee of %s. Is this okay? (Y/Yes/N/No)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="2410"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2669"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="2931"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2427"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2686"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2980"/> <source>Money successfully sent, transaction: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3028"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="2848"/> + <source>%s change to %s</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/simplewallet/simplewallet.cpp" line="2851"/> + <source>no change</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/simplewallet/simplewallet.cpp" line="2854"/> + <source>Loaded %lu transactions, for %s, fee %s, %s, %s, with min mixin %lu. %sIs this okay? (Y/Yes/N/No)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/simplewallet/simplewallet.cpp" line="2905"/> + <source>Transaction successfully signed to file </source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/simplewallet/simplewallet.cpp" line="3077"/> <source>usage: get_tx_key <txid></source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3035"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="3072"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="3522"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="3550"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3084"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3121"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3571"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3599"/> <source>failed to parse txid</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3046"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3095"/> <source>Tx key: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3051"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3100"/> <source>no tx keys found for this txid</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3061"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3110"/> <source>usage: check_tx_key <txid> <txkey> <address></source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3081"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="3088"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3130"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3137"/> <source>failed to parse tx key</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3108"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3157"/> <source>failed to get transaction from daemon</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3119"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3168"/> <source>failed to parse transaction from daemon</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3126"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3175"/> <source>failed to validate transaction from daemon</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3131"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3180"/> <source>failed to get the right transaction from daemon</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3138"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3187"/> <source>failed to generate key derivation from supplied parameters</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3194"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3243"/> <source>error: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3200"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3249"/> <source>received</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3200"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3249"/> <source>in txid</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3204"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3253"/> <source>received nothing in txid</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3208"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3257"/> <source>WARNING: this transaction is not yet included in the blockchain!</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3217"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3266"/> <source>This transaction has %u confirmations</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3221"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3270"/> <source>WARNING: failed to determine number of confirmations!</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3261"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3310"/> <source>usage: show_transfers [in|out|all|pending|failed] [<min_height> [<max_height>]]</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3300"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3349"/> <source>bad min_height parameter:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3312"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3361"/> <source>bad max_height parameter:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3358"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3407"/> <source>in</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3358"/> - <location filename="../src/simplewallet/simplewallet.cpp" line="3396"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3407"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3445"/> <source>out</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3396"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3445"/> <source>failed</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3396"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3445"/> <source>pending</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3449"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3498"/> <source>wallet</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3480"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3529"/> <source>Random payment ID: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3481"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3530"/> <source>Matching integrated address: </source> <translation type="unfinished"></translation> </message> @@ -1739,72 +1773,67 @@ your wallet again (your wallet keys are NOT at risk in any case). <context> <name>sw</name> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="106"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="102"/> <source>Generate new wallet and save it to <arg></source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="107"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="103"/> <source>Generate incoming-only wallet from view key</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="108"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="104"/> <source>Generate wallet from private keys</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="110"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="106"/> <source>Specify Electrum seed for wallet recovery/creation</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="111"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="107"/> <source>Recover wallet using Electrum-style mnemonic seed</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="112"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="108"/> <source>Create non-deterministic view and spend keys</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="113"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="109"/> <source>Enable commands which rely on a trusted daemon</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="114"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="110"/> <source>Allow communicating with a daemon that uses a different RPC version</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="115"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="111"/> <source>Restore from specific blockchain height</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="126"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="122"/> <source>daemon is busy. Please try again later.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="135"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="131"/> <source>possibly lost connection to daemon</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="216"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="212"/> <source>Error: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="228"/> - <source>yes</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3945"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3994"/> <source>Failed to initialize wallet</source> <translation type="unfinished"></translation> </message> @@ -1867,81 +1896,81 @@ your wallet again (your wallet keys are NOT at risk in any case). <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/wallet2.cpp" line="215"/> + <location filename="../src/wallet/wallet2.cpp" line="220"/> <source>Failed to load file </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/wallet2.cpp" line="221"/> + <location filename="../src/wallet/wallet2.cpp" line="226"/> <source>Failed to parse JSON</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/wallet2.cpp" line="228"/> + <location filename="../src/wallet/wallet2.cpp" line="233"/> <source>Version %u too new, we can only grok up to %u</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/wallet2.cpp" line="246"/> + <location filename="../src/wallet/wallet2.cpp" line="251"/> <source>failed to parse view key secret key</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/wallet2.cpp" line="252"/> - <location filename="../src/wallet/wallet2.cpp" line="319"/> - <location filename="../src/wallet/wallet2.cpp" line="361"/> + <location filename="../src/wallet/wallet2.cpp" line="257"/> + <location filename="../src/wallet/wallet2.cpp" line="324"/> + <location filename="../src/wallet/wallet2.cpp" line="366"/> <source>failed to verify view key secret key</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/wallet2.cpp" line="264"/> + <location filename="../src/wallet/wallet2.cpp" line="269"/> <source>failed to parse spend key secret key</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/wallet2.cpp" line="270"/> - <location filename="../src/wallet/wallet2.cpp" line="331"/> - <location filename="../src/wallet/wallet2.cpp" line="382"/> + <location filename="../src/wallet/wallet2.cpp" line="275"/> + <location filename="../src/wallet/wallet2.cpp" line="336"/> + <location filename="../src/wallet/wallet2.cpp" line="387"/> <source>failed to verify spend key secret key</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/wallet2.cpp" line="283"/> + <location filename="../src/wallet/wallet2.cpp" line="288"/> <source>Electrum-style word list failed verification</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/wallet2.cpp" line="294"/> + <location filename="../src/wallet/wallet2.cpp" line="299"/> <source>At least one of Electrum-style word list and private view key must be specified</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/wallet2.cpp" line="299"/> + <location filename="../src/wallet/wallet2.cpp" line="304"/> <source>Both Electrum-style word list and private key(s) specified</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/wallet2.cpp" line="312"/> + <location filename="../src/wallet/wallet2.cpp" line="317"/> <source>invalid address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/wallet2.cpp" line="323"/> + <location filename="../src/wallet/wallet2.cpp" line="328"/> <source>view key does not match standard address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/wallet2.cpp" line="335"/> + <location filename="../src/wallet/wallet2.cpp" line="340"/> <source>spend key does not match standard address</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/wallet2.cpp" line="344"/> + <location filename="../src/wallet/wallet2.cpp" line="349"/> <source>Cannot create deprecated wallets from JSON</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/wallet2.cpp" line="391"/> + <location filename="../src/wallet/wallet2.cpp" line="396"/> <source>failed to generate new wallet: </source> <translation type="unfinished"></translation> </message> @@ -1949,59 +1978,59 @@ your wallet again (your wallet keys are NOT at risk in any case). <context> <name>tools::wallet_rpc_server</name> <message> - <location filename="../src/wallet/wallet_rpc_server.cpp" line="1111"/> + <location filename="../src/wallet/wallet_rpc_server.cpp" line="1115"/> <source>Can't specify more than one of --wallet-file and --generate-from-json</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/wallet_rpc_server.cpp" line="1117"/> + <location filename="../src/wallet/wallet_rpc_server.cpp" line="1121"/> <source>Must specify --wallet-file or --generate-from-json</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/wallet_rpc_server.cpp" line="1121"/> + <location filename="../src/wallet/wallet_rpc_server.cpp" line="1125"/> <source>Loading wallet...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/wallet_rpc_server.cpp" line="1146"/> - <location filename="../src/wallet/wallet_rpc_server.cpp" line="1169"/> + <location filename="../src/wallet/wallet_rpc_server.cpp" line="1150"/> + <location filename="../src/wallet/wallet_rpc_server.cpp" line="1173"/> <source>Storing wallet...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/wallet_rpc_server.cpp" line="1148"/> - <location filename="../src/wallet/wallet_rpc_server.cpp" line="1171"/> + <location filename="../src/wallet/wallet_rpc_server.cpp" line="1152"/> + <location filename="../src/wallet/wallet_rpc_server.cpp" line="1175"/> <source>Stored ok</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/wallet_rpc_server.cpp" line="1151"/> + <location filename="../src/wallet/wallet_rpc_server.cpp" line="1155"/> <source>Loaded ok</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/wallet_rpc_server.cpp" line="1155"/> + <location filename="../src/wallet/wallet_rpc_server.cpp" line="1159"/> <source>Wallet initialization failed: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/wallet_rpc_server.cpp" line="1160"/> + <location filename="../src/wallet/wallet_rpc_server.cpp" line="1164"/> <source>Failed to initialize wallet rpc server</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/wallet_rpc_server.cpp" line="1164"/> + <location filename="../src/wallet/wallet_rpc_server.cpp" line="1168"/> <source>Starting wallet rpc server</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/wallet_rpc_server.cpp" line="1166"/> + <location filename="../src/wallet/wallet_rpc_server.cpp" line="1170"/> <source>Stopped wallet rpc server</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/wallet_rpc_server.cpp" line="1175"/> + <location filename="../src/wallet/wallet_rpc_server.cpp" line="1179"/> <source>Failed to store wallet: </source> <translation type="unfinished"></translation> </message> @@ -2009,53 +2038,53 @@ your wallet again (your wallet keys are NOT at risk in any case). <context> <name>wallet_args</name> <message> - <location filename="../src/simplewallet/simplewallet.cpp" line="3912"/> - <location filename="../src/wallet/wallet_rpc_server.cpp" line="1082"/> + <location filename="../src/simplewallet/simplewallet.cpp" line="3961"/> + <location filename="../src/wallet/wallet_rpc_server.cpp" line="1086"/> <source>Wallet options</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/wallet_args.cpp" line="25"/> + <location filename="../src/wallet/wallet_args.cpp" line="56"/> <source>Generate wallet from JSON format file</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/wallet_args.cpp" line="29"/> + <location filename="../src/wallet/wallet_args.cpp" line="60"/> <source>Use wallet <arg></source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/wallet_args.cpp" line="51"/> + <location filename="../src/wallet/wallet_args.cpp" line="82"/> <source>Max number of threads to use for a parallel job</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/wallet_args.cpp" line="52"/> + <location filename="../src/wallet/wallet_args.cpp" line="83"/> <source>Specify log file</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/wallet_args.cpp" line="61"/> + <location filename="../src/wallet/wallet_args.cpp" line="92"/> <source>General options</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/wallet_args.cpp" line="75"/> + <location filename="../src/wallet/wallet_args.cpp" line="106"/> <source>unexpected empty log file name in presence of non-empty file path</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/wallet_args.cpp" line="100"/> + <location filename="../src/wallet/wallet_args.cpp" line="131"/> <source>Usage:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/wallet_args.cpp" line="147"/> + <location filename="../src/wallet/wallet_args.cpp" line="178"/> <source>default_log: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/wallet/wallet_args.cpp" line="148"/> + <location filename="../src/wallet/wallet_args.cpp" line="179"/> <source>Logging at log level %d to %s</source> <translation type="unfinished"></translation> </message> diff --git a/utils/gpg_keys/jaquee.asc b/utils/gpg_keys/jaquee.asc index 1fa043b35..f1199dd25 100644 --- a/utils/gpg_keys/jaquee.asc +++ b/utils/gpg_keys/jaquee.asc @@ -1,30 +1,30 @@ -----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v2 -mQENBFfxeegBCACggflhOp8t5kXdNc9rusZB96cNJkCCNKj2El7Q/5FCN8LmIetq -IzWd9b4hpfxZRn6g6NaOv8bO6EJPZHpk1nO1ZVIM+jWl1oY3BCgR0Loalntyk6aF -HAAEo5YUlEN6pyZ9PHL6legR/pu90YV9cp2NoDmO85o1h5o8O549XPLBPwrxQ8tH -4ZPjVKOfL6EHkkNZPid7On30S2r6mnsLjlfME4xGJkZn9+giBtYLMNjDe9DNzwsO -lrVPVfUWO9zwdOLVQQ1dgA5mlAZCuzXm54Onp/sgHH4RVjhVMrPvnaiGcLW+jybR -5t2FOdZD0oa9V4lLCFT9GNgErhU6cmkAyPoRABEBAAG0IUphY29iIEJyeWRvbGYg -PGphY29iQGJyeWRvbGYubmV0PokBOQQTAQgAIwUCV/F56AIbAwcLCQgHAwIBBhUI -AgkKCwQWAgMBAh4BAheAAAoJEN5GJGVQ0vPFi+wH/iw4Y7hPbulYgyaNQfAZTXo2 -DKHQP6iKk6zafMlgMsISTWqm1qTF/7MFa6yYjrVTRvORFrphpvEwYDGN6i/3Q4zn -5C/xdZSgw6PQaLc4xB7lS7b/tlk06QN7esLFbwDXorx7w1WAB6GTdmWxLzCsKUaZ -9M8r5JtwndtVMqlMrjqBFPBiOJlgTsDc7L7cNpZXK/PqRA6Xd8Q93NJ9Y0w7I/sl -X0AL509dVCHyo5tTQP3/paDDjenYHhqy/IOKLWKLm65L76vqw9eA9vdldjb0am2g -djBenHZKcnVLir+r/C3FD7BxqWL1/ZR7A3JaAACfSIawOUs0NAVhZE7c+JGHgwG5 -AQ0EV/F56AEIANNgpM+Y3DL+TTjcs9GN4ZcaBitxpSOtei0b8hmQx82KWSMJxb4+ -pH+HTCsFmSX744+B7nvvyaYLfVWnh3n2khjPaae/e9BoCmCIVQGnxAbhPUvHALPr -FN+s2wpLYx2eXuVvZaaafrXinRx8uhdwZNw40K1BcfbOxFhnJy/URWGpQ5vFltMY -i/YDbcLgRQm1aRaF6uYldwImHqIBwZeETTKL5YdAZxpnKvJkpEb6LXCQd00H7jo9 -s4U7WHl6RofirnlsWiYqSoAcIzUxAuqaijd000PkgDHGVbQUTLsyws5UBuoe1Zb8 -+/DfS7eOba7fXvLG63AkEkVTydLHrtG7wO0AEQEAAYkBHwQYAQgACQUCV/F56AIb -DAAKCRDeRiRlUNLzxZlbB/4npqwsObodmOBW0b78xcDR8kmSvVyjThVoqsjkaqi1 -hP29/o+bmA6OhyET7EjTkCBlCd2zXcqAoUwvEvcSt/qnMrv02zTCvUkYHy2DtxDl -BmMPdbtX2EaKfHtQ+7/LEiQzckVwYsJrX2U23oGaRvwVwlF7ARTE8whVYfngvcgF -2zgStg9YfH9Gs7V0A14gr7tnaZsCj+BnF4BiDuClBiCn38cBVM0SKzb2QqEX68Wt -qRIfOexu99/Gt3Px+JvpKOf0uCOTRezpCuL9Nm7cxRzR69bMFO0rWfPZUMPHzHx3 -NJW9mHeFMvJVD3tEXMB6MaGHNVtc16lVUcgeqUKcDlqH -=B9zn ------END PGP PUBLIC KEY BLOCK----- +mQENBFg14koBCACxrLtcmKK1X9haFa90Vr04PfHK9hXDeUrwUS8xIhCojj2WccdR +6hJLUCR27G03gb36xadQhQVCYk2tAwOKLjZVlsUtJ5rLASjPv9mcmgZnL5nU66Qi +9lHFKBD/Mrf7X6Bg89nWT2dUshIUuvkmbAAh9o9i8CoA/P62/9TG4uWc+vbNGEzV +jb6UtPQc6DHgZ8HeagC9WLE4bTx8tIxNmimwyLc5fow0G0LE0eb3V8jPMUZkdG1h +byHOLeqbSkFJd8GVYz96o/XNzFPPv/60bihn5wDMZqL9J64odoCqzligP1OprhhF +wEsbt0QQ60R9AlCjCgz7pgH8QIJSeX1a121HABEBAAG0IEphcXVlZSA8amFxdWVl +Lm1vbmVyb0BnbWFpbC5jb20+iQE5BBMBCAAjBQJYNeJKAhsDBwsJCAcDAgEGFQgC +CQoLBBYCAwECHgECF4AACgkQOE5SsJ9F3DmyqggArNrQzE4jopaDzxNy+VKTKf7z +chMk9zzY6TSKQ9YfQe0zHKcL7GyfQ/plVmoPMZQglVvC54Vw0aLA8PGt1a/ZU0mD +KWLTGbdIHasGatkY7J3B/vjDsPxfWMKai4Bpesk+gI4/nb2V8/CVsSuVlX5PrQD4 +buXhv7S7Mn6ezzzRZD/oYN5WaokgAxu8rnTlJN8yQP3uat71ply+JN3u3TwFxMeX +WcrDTwq/XqJD7OUWrBm378v7M1Dd8kWQTwyWMPCDZhaYgiSlSwKfbDsq4e7d55jv +2ucKL1AOGnpn6hJ7ip0sn9rLr53qD7eqHl7yzsrrRZkYH6AYiXvk45Srx76DSbkB +DQRYNeJKAQgAvMTf6cGiBTJzj9DfATqQlLEPWJHbqfoFTIbRlHmYdCBbLH2M/GCr +HK4YdhF+9i+Wnq5E9fxnxJzhm22dfSWgw9GuyX8LxBanVhhQiE+9eH/H0ULHjokN +PVQOg90XdAQWahvl5YCOmqt7H7z6+HxHIhCHzo688+lPC4zol0PYNEWcHYBrVsax +cEQ2LObD9J7bBY1BqLXppzHATTwxuO/bp9Bd9LmCaFBinLyF34oDYttEVOq2RNko +vNeWbHWpmdzoagHxLGMU1ae+yCMuGHSdfLnLWTUdVLepVLmzblXxgTd7SS4Bm3Y0 +1jBgBni8msSTR1ICvyMcQuRZnK/yAgM+TQARAQABiQEfBBgBCAAJBQJYNeJKAhsM +AAoJEDhOUrCfRdw5hmsH/0Moh1Z4kPXbvfincDarDDDe5wUImey/7WwOrSsiPwTI +8AkRts496o3XHcsSWLXZ5Ab+cGKnys5TRfX+RqMrG4p+TXMt2vWDnF5gjeRcwpcz +UI/TCFkCg+x3QAEvlNFNLK4APd2fwR/KQJjmn4a4/0boqrrn09vLSx7/+bdsfYbZ +eKSuF58aYVROY9FUNhFsvgjGI/sYNQFj0DoexLe28f4/cFFVpZvb/kJYqm4QauyK +5SMyvTTu8PD+pZpLM9MFoQ+Jk+EmDzSUlarwnt75O6kMLNLPFJ8hCOiN2RNK2PKk +iTpY5CQtKsGQDRA7sT6ZaiWO7kkQGO0HSBfmWnZq2G0= +=Ky09 +-----END PGP PUBLIC KEY BLOCK-----
\ No newline at end of file |