diff options
96 files changed, 1566 insertions, 904 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index d60eecbc1..aac15b5b6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -298,7 +298,7 @@ if(SANITIZE) endif() # Set default blockchain storage location: -# memory was the default in Cryptonote before Monero implimented LMDB, it still works but is unneccessary. +# memory was the default in Cryptonote before Monero implemented LMDB, it still works but is unnecessary. # set(DATABASE memory) set(DATABASE lmdb) @@ -783,7 +783,7 @@ if(STATIC) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_STATIC_RUNTIME ON) endif() -find_package(Boost 1.58 QUIET REQUIRED COMPONENTS system filesystem thread date_time chrono regex serialization program_options) +find_package(Boost 1.58 QUIET REQUIRED COMPONENTS system filesystem thread date_time chrono regex serialization program_options locale) set(CMAKE_FIND_LIBRARY_SUFFIXES ${OLD_LIB_SUFFIXES}) if(NOT Boost_FOUND) @@ -800,6 +800,7 @@ endif() include_directories(SYSTEM ${Boost_INCLUDE_DIRS}) if(MINGW) set(EXTRA_LIBRARIES mswsock;ws2_32;iphlpapi) + set(ICU_LIBRARIES ${Boost_LOCALE_LIBRARY} sicuio sicuin sicuuc sicudt sicutu iconv) elseif(APPLE OR OPENBSD OR ANDROID) set(EXTRA_LIBRARIES "") elseif(FREEBSD) diff --git a/Dockerfile b/Dockerfile index f5d670633..44a1015e9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -24,7 +24,7 @@ WORKDIR /usr/local ARG BOOST_VERSION=1_66_0 ARG BOOST_VERSION_DOT=1.66.0 ARG BOOST_HASH=5721818253e6a0989583192f96782c4a98eb6204965316df9f5ad75819225ca9 -RUN curl -s -L -o boost_${BOOST_VERSION}.tar.bz2 https://sourceforge.net/projects/boost/files/boost/${BOOST_VERSION_DOT}/boost_${BOOST_VERSION}.tar.bz2/download \ +RUN curl -s -L -o boost_${BOOST_VERSION}.tar.bz2 https://dl.bintray.com/boostorg/release/${BOOST_VERSION_DOT}/source/boost_${BOOST_VERSION}.tar.bz2 \ && echo "${BOOST_HASH} boost_${BOOST_VERSION}.tar.bz2" | sha256sum -c \ && tar -xvf boost_${BOOST_VERSION}.tar.bz2 \ && cd boost_${BOOST_VERSION} \ diff --git a/contrib/epee/include/file_io_utils.h b/contrib/epee/include/file_io_utils.h index 989d16fba..196610674 100644 --- a/contrib/epee/include/file_io_utils.h +++ b/contrib/epee/include/file_io_utils.h @@ -31,6 +31,31 @@ #include <iostream> #include <boost/filesystem/path.hpp> #include <boost/filesystem/operations.hpp> +#ifdef WIN32 +#include <windows.h> +#endif + +// On Windows there is a problem with non-ASCII characters in path and file names +// as far as support by the standard components used is concerned: + +// The various file stream classes, e.g. std::ifstream and std::ofstream, are +// part of the GNU C++ Library / libstdc++. On the most basic level they use the +// fopen() call as defined / made accessible to programs compiled within MSYS2 +// by the stdio.h header file maintained by the MinGW project. + +// The critical point: The implementation of fopen() is part of MSVCRT, the +// Microsoft Visual C/C++ Runtime Library, and this method does NOT offer any +// Unicode support. + +// Monero code that would want to continue to use the normal file stream classes +// but WITH Unicode support could therefore not solve this problem on its own, +// but 2 different projects from 2 different maintaining groups would need changes +// in this particular direction - something probably difficult to achieve and +// with a long time to wait until all new versions / releases arrive. + +// Implemented solution approach: Circumvent the problem by stopping to use std +// file stream classes on Windows and directly use Unicode-capable WIN32 API +// calls. Most of the code doing so is concentrated in this header file here. namespace epee { @@ -46,7 +71,22 @@ namespace file_io_utils inline bool save_string_to_file(const std::string& path_to_file, const std::string& str) { - +#ifdef WIN32 + WCHAR wide_path[1000]; + int chars = MultiByteToWideChar(CP_UTF8, 0, path_to_file.c_str(), path_to_file.size() + 1, wide_path, 1000); + if (chars == 0) + return false; + HANDLE file_handle = CreateFileW(wide_path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (file_handle == INVALID_HANDLE_VALUE) + return false; + DWORD bytes_written; + DWORD bytes_to_write = (DWORD)str.size(); + BOOL result = WriteFile(file_handle, str.data(), bytes_to_write, &bytes_written, NULL); + CloseHandle(file_handle); + if (bytes_written != bytes_to_write) + result = FALSE; + return result; +#else try { std::ofstream fstream; @@ -61,6 +101,7 @@ namespace file_io_utils { return false; } +#endif } inline @@ -89,6 +130,27 @@ namespace file_io_utils inline bool load_file_to_string(const std::string& path_to_file, std::string& target_str) { +#ifdef WIN32 + WCHAR wide_path[1000]; + int chars = MultiByteToWideChar(CP_UTF8, 0, path_to_file.c_str(), path_to_file.size() + 1, wide_path, 1000); + if (chars == 0) + return false; + HANDLE file_handle = CreateFileW(wide_path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (file_handle == INVALID_HANDLE_VALUE) + return false; + DWORD file_size = GetFileSize(file_handle, NULL); + if ((file_size == INVALID_FILE_SIZE) || (file_size > 1000000000)) { + CloseHandle(file_handle); + return false; + } + target_str.resize(file_size); + DWORD bytes_read; + BOOL result = ReadFile(file_handle, &target_str[0], file_size, &bytes_read, NULL); + CloseHandle(file_handle); + if (bytes_read != file_size) + result = FALSE; + return result; +#else try { std::ifstream fstream; @@ -113,11 +175,13 @@ namespace file_io_utils { return false; } +#endif } inline bool append_string_to_file(const std::string& path_to_file, const std::string& str) { + // No special Windows implementation because so far not used in Monero code try { std::ofstream fstream; @@ -137,6 +201,22 @@ namespace file_io_utils inline bool get_file_size(const std::string& path_to_file, uint64_t &size) { +#ifdef WIN32 + WCHAR wide_path[1000]; + int chars = MultiByteToWideChar(CP_UTF8, 0, path_to_file.c_str(), path_to_file.size() + 1, wide_path, 1000); + if (chars == 0) + return false; + HANDLE file_handle = CreateFileW(wide_path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (file_handle == INVALID_HANDLE_VALUE) + return false; + LARGE_INTEGER file_size; + BOOL result = GetFileSizeEx(file_handle, &file_size); + CloseHandle(file_handle); + if (result) { + size = file_size.QuadPart; + } + return size; +#else try { std::ifstream fstream; @@ -151,6 +231,7 @@ namespace file_io_utils { return false; } +#endif } } diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index bdec846d1..f9c829013 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -451,7 +451,8 @@ void BlockchainLMDB::do_resize(uint64_t increase_size) boost::filesystem::space_info si = boost::filesystem::space(path); if(si.available < add_size) { - MERROR("!! WARNING: Insufficient free space to extend database !!: " << si.available / 1LL << 20L); + MERROR("!! WARNING: Insufficient free space to extend database !!: " << + (si.available >> 20L) << " MB available, " << (add_size >> 20L) << " MB needed"); return; } } @@ -472,7 +473,7 @@ void BlockchainLMDB::do_resize(uint64_t increase_size) // add 1Gb per resize, instead of doing a percentage increase uint64_t new_mapsize = (double) mei.me_mapsize + add_size; - // If given, use increase_size intead of above way of resizing. + // If given, use increase_size instead of above way of resizing. // This is currently used for increasing by an estimated size at start of new // batch txn. if (increase_size > 0) diff --git a/src/blockchain_utilities/blockchain_export.cpp b/src/blockchain_utilities/blockchain_export.cpp index b3e11605d..5a49f3478 100644 --- a/src/blockchain_utilities/blockchain_export.cpp +++ b/src/blockchain_utilities/blockchain_export.cpp @@ -58,7 +58,6 @@ int main(int argc, char* argv[]) tools::on_startup(); - boost::filesystem::path default_data_path {tools::get_default_data_dir()}; boost::filesystem::path output_file_path; po::options_description desc_cmd_only("Command line options"); @@ -75,6 +74,7 @@ int main(int argc, char* argv[]) command_line::add_arg(desc_cmd_sett, cryptonote::arg_data_dir); command_line::add_arg(desc_cmd_sett, arg_output_file); command_line::add_arg(desc_cmd_sett, cryptonote::arg_testnet_on); + command_line::add_arg(desc_cmd_sett, cryptonote::arg_stagenet_on); command_line::add_arg(desc_cmd_sett, arg_log_level); command_line::add_arg(desc_cmd_sett, arg_database); command_line::add_arg(desc_cmd_sett, arg_block_stop); @@ -112,6 +112,12 @@ int main(int argc, char* argv[]) LOG_PRINT_L0("Starting..."); bool opt_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on); + bool opt_stagenet = command_line::get_arg(vm, cryptonote::arg_stagenet_on); + if (opt_testnet && opt_stagenet) + { + std::cerr << "Can't specify more than one of --testnet and --stagenet" << std::endl; + return 1; + } bool opt_blocks_dat = command_line::get_arg(vm, arg_blocks_dat); std::string m_config_folder; @@ -169,7 +175,7 @@ int main(int argc, char* argv[]) LOG_PRINT_L0("Error opening database: " << e.what()); return 1; } - r = core_storage->init(db, opt_testnet); + r = core_storage->init(db, opt_testnet ? cryptonote::TESTNET : opt_stagenet ? cryptonote::STAGENET : cryptonote::MAINNET); CHECK_AND_ASSERT_MES(r, 1, "Failed to initialize source blockchain storage"); LOG_PRINT_L0("Source blockchain storage initialized OK"); diff --git a/src/blockchain_utilities/blockchain_import.cpp b/src/blockchain_utilities/blockchain_import.cpp index 6195e47e7..caa549c13 100644 --- a/src/blockchain_utilities/blockchain_import.cpp +++ b/src/blockchain_utilities/blockchain_import.cpp @@ -53,6 +53,7 @@ bool opt_batch = true; bool opt_verify = true; // use add_new_block, which does verification before calling add_block bool opt_resume = true; bool opt_testnet = true; +bool opt_stagenet = true; // number of blocks per batch transaction // adjustable through command-line argument according to available RAM @@ -574,8 +575,6 @@ int main(int argc, char* argv[]) tools::on_startup(); - boost::filesystem::path default_data_path {tools::get_default_data_dir()}; - boost::filesystem::path default_testnet_data_path {default_data_path / "testnet"}; std::string import_file_path; po::options_description desc_cmd_only("Command line options"); @@ -671,6 +670,12 @@ int main(int argc, char* argv[]) } opt_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on); + opt_stagenet = command_line::get_arg(vm, cryptonote::arg_stagenet_on); + if (opt_testnet && opt_stagenet) + { + std::cerr << "Error: Can't specify more than one of --testnet and --stagenet" << ENDL; + return 1; + } m_config_folder = command_line::get_arg(vm, cryptonote::arg_data_dir); db_arg_str = command_line::get_arg(vm, arg_database); @@ -728,7 +733,7 @@ int main(int argc, char* argv[]) MINFO("batch: " << std::boolalpha << opt_batch << std::noboolalpha); } MINFO("resume: " << std::boolalpha << opt_resume << std::noboolalpha); - MINFO("testnet: " << std::boolalpha << opt_testnet << std::noboolalpha); + MINFO("nettype: " << (opt_testnet ? "testnet" : opt_stagenet ? "stagenet" : "mainnet")); MINFO("bootstrap file path: " << import_file_path); MINFO("database path: " << m_config_folder); diff --git a/src/blocks/CMakeLists.txt b/src/blocks/CMakeLists.txt index 079c59fb5..cf3f0b354 100644 --- a/src/blocks/CMakeLists.txt +++ b/src/blocks/CMakeLists.txt @@ -32,7 +32,8 @@ if(APPLE) else() add_custom_command(OUTPUT blocks.o MAIN_DEPENDENCY blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocks.o blocks.dat) add_custom_command(OUTPUT testnet_blocks.o MAIN_DEPENDENCY testnet_blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/testnet_blocks.o testnet_blocks.dat) - add_library(blocks STATIC blocks.o testnet_blocks.o blockexports.c) + add_custom_command(OUTPUT stagenet_blocks.o MAIN_DEPENDENCY stagenet_blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/stagenet_blocks.o stagenet_blocks.dat) + add_library(blocks STATIC blocks.o testnet_blocks.o stagenet_blocks.o blockexports.c) set_target_properties(blocks PROPERTIES LINKER_LANGUAGE C) endif() diff --git a/src/blocks/blockexports.c b/src/blocks/blockexports.c index 477167a12..0154b0413 100644 --- a/src/blocks/blockexports.c +++ b/src/blocks/blockexports.c @@ -16,20 +16,24 @@ extern const struct mach_header_64 _mh_execute_header; #endif #endif -const unsigned char *get_blocks_dat_start(int testnet) +const unsigned char *get_blocks_dat_start(int testnet, int stagenet) { size_t size; if (testnet) return getsectiondata(&_mh_execute_header, "__DATA", "__testnet_blocks_dat", &size); + else if (stagenet) + return getsectiondata(&_mh_execute_header, "__DATA", "__stagenet_blocks_dat", &size); else return getsectiondata(&_mh_execute_header, "__DATA", "__blocks_dat", &size); } -size_t get_blocks_dat_size(int testnet) +size_t get_blocks_dat_size(int testnet, int stagenet) { size_t size; if (testnet) getsectiondata(&_mh_execute_header, "__DATA", "__testnet_blocks_dat", &size); + else if (stagenet) + getsectiondata(&_mh_execute_header, "__DATA", "__stagenet_blocks_dat", &size); else getsectiondata(&_mh_execute_header, "__DATA", "__blocks_dat", &size); return size; @@ -42,30 +46,40 @@ size_t get_blocks_dat_size(int testnet) #define _binary_blocks_end binary_blocks_dat_end #define _binary_testnet_blocks_start binary_testnet_blocks_dat_start #define _binary_testnet_blocks_end binary_testnet_blocks_dat_end +#define _binary_stagenet_blocks_start binary_stagenet_blocks_dat_start +#define _binary_stagenet_blocks_end binary_stagenet_blocks_dat_end #else #define _binary_blocks_start _binary_blocks_dat_start #define _binary_blocks_end _binary_blocks_dat_end #define _binary_testnet_blocks_start _binary_testnet_blocks_dat_start #define _binary_testnet_blocks_end _binary_testnet_blocks_dat_end +#define _binary_stagenet_blocks_start _binary_stagenet_blocks_dat_start +#define _binary_stagenet_blocks_end _binary_stagenet_blocks_dat_end #endif extern const unsigned char _binary_blocks_start[]; extern const unsigned char _binary_blocks_end[]; extern const unsigned char _binary_testnet_blocks_start[]; extern const unsigned char _binary_testnet_blocks_end[]; +extern const unsigned char _binary_stagenet_blocks_start[]; +extern const unsigned char _binary_stagenet_blocks_end[]; -const unsigned char *get_blocks_dat_start(int testnet) +const unsigned char *get_blocks_dat_start(int testnet, int stagenet) { if (testnet) return _binary_testnet_blocks_start; + else if (stagenet) + return _binary_stagenet_blocks_start; else return _binary_blocks_start; } -size_t get_blocks_dat_size(int testnet) +size_t get_blocks_dat_size(int testnet, int stagenet) { if (testnet) return (size_t) (_binary_testnet_blocks_end - _binary_testnet_blocks_start); + else if (stagenet) + return (size_t) (_binary_stagenet_blocks_end - _binary_stagenet_blocks_start); else return (size_t) (_binary_blocks_end - _binary_blocks_start); } diff --git a/src/blocks/blocks.h b/src/blocks/blocks.h index b842009a4..ec683f47e 100644 --- a/src/blocks/blocks.h +++ b/src/blocks/blocks.h @@ -5,8 +5,8 @@ extern "C" { #endif -const unsigned char *get_blocks_dat_start(int testnet); -size_t get_blocks_dat_size(int testnet); +const unsigned char *get_blocks_dat_start(int testnet, int stagenet); +size_t get_blocks_dat_size(int testnet, int stagenet); #ifdef __cplusplus } diff --git a/src/blocks/stagenet_blocks.dat b/src/blocks/stagenet_blocks.dat new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/src/blocks/stagenet_blocks.dat diff --git a/src/checkpoints/checkpoints.cpp b/src/checkpoints/checkpoints.cpp index eadfb4df7..f709465c8 100644 --- a/src/checkpoints/checkpoints.cpp +++ b/src/checkpoints/checkpoints.cpp @@ -159,14 +159,20 @@ namespace cryptonote return true; } - bool checkpoints::init_default_checkpoints(bool testnet) + bool checkpoints::init_default_checkpoints(network_type nettype) { - if (testnet) + if (nettype == TESTNET) { ADD_CHECKPOINT(0, "48ca7cd3c8de5b6a4d53d2861fbdaedca141553559f9be9520068053cda8430b"); ADD_CHECKPOINT(1000000, "46b690b710a07ea051bc4a6b6842ac37be691089c0f7758cfeec4d5fc0b4a258"); return true; } + if (nettype == STAGENET) + { + ADD_CHECKPOINT(0, "76ee3cc98646292206cd3e86f74d88b4dcc1d937088645e9b0cbca84b7ce74eb"); + ADD_CHECKPOINT(10000, "1f8b0ce313f8b9ba9a46108bfd285c45ad7c2176871fd41c3a690d4830ce2fd5"); + return true; + } ADD_CHECKPOINT(1, "771fbcd656ec1464d3a02ead5e18644030007a0fc664c0a964d30922821a8148"); ADD_CHECKPOINT(10, "c0e3b387e47042f72d8ccdca88071ff96bff1ac7cde09ae113dbb7ad3fe92381"); ADD_CHECKPOINT(100, "ac3e11ca545e57c49fca2b4e8c48c03c23be047c43e471e1394528b1f9f80b2d"); @@ -240,7 +246,7 @@ namespace cryptonote return true; } - bool checkpoints::load_checkpoints_from_dns(bool testnet) + bool checkpoints::load_checkpoints_from_dns(network_type nettype) { std::vector<std::string> records; @@ -257,7 +263,13 @@ namespace cryptonote , "testpoints.moneropulse.co" }; - if (!tools::dns_utils::load_txt_records_from_dns(records, testnet ? testnet_dns_urls : dns_urls)) + static const std::vector<std::string> stagenet_dns_urls = { "stagenetpoints.moneropulse.se" + , "stagenetpoints.moneropulse.org" + , "stagenetpoints.moneropulse.net" + , "stagenetpoints.moneropulse.co" + }; + + if (!tools::dns_utils::load_txt_records_from_dns(records, nettype == TESTNET ? testnet_dns_urls : nettype == STAGENET ? stagenet_dns_urls : dns_urls)) return true; // why true ? for (const auto& record : records) @@ -290,14 +302,14 @@ namespace cryptonote return true; } - bool checkpoints::load_new_checkpoints(const std::string &json_hashfile_fullpath, bool testnet, bool dns) + bool checkpoints::load_new_checkpoints(const std::string &json_hashfile_fullpath, network_type nettype, bool dns) { bool result; result = load_checkpoints_from_json(json_hashfile_fullpath); if (dns) { - result &= load_checkpoints_from_dns(testnet); + result &= load_checkpoints_from_dns(nettype); } return result; diff --git a/src/checkpoints/checkpoints.h b/src/checkpoints/checkpoints.h index e71861c44..61be2c27a 100644 --- a/src/checkpoints/checkpoints.h +++ b/src/checkpoints/checkpoints.h @@ -33,6 +33,7 @@ #include <vector> #include "misc_log_ex.h" #include "crypto/hash.h" +#include "cryptonote_config.h" #define ADD_CHECKPOINT(h, hash) CHECK_AND_ASSERT(add_checkpoint(h, hash), false); #define JSON_HASH_FILE_NAME "checkpoints.json" @@ -147,11 +148,11 @@ namespace cryptonote /** * @brief loads the default main chain checkpoints - * @param testnet whether to load testnet checkpoints or mainnet + * @param nettype network type * * @return true unless adding a checkpoint fails */ - bool init_default_checkpoints(bool testnet); + bool init_default_checkpoints(network_type nettype); /** * @brief load new checkpoints @@ -160,12 +161,12 @@ namespace cryptonote * (optionally) from DNS. * * @param json_hashfile_fullpath path to the json checkpoints file - * @param testnet whether to load testnet checkpoints or mainnet + * @param nettype network type * @param dns whether or not to load DNS checkpoints * * @return true if loading successful and no conflicts */ - bool load_new_checkpoints(const std::string &json_hashfile_fullpath, bool testnet=false, bool dns=true); + bool load_new_checkpoints(const std::string &json_hashfile_fullpath, network_type nettype=MAINNET, bool dns=true); /** * @brief load new checkpoints from json @@ -179,11 +180,11 @@ namespace cryptonote /** * @brief load new checkpoints from DNS * - * @param testnet whether to load testnet checkpoints or mainnet + * @param nettype network type * * @return true if loading successful and no conflicts */ - bool load_checkpoints_from_dns(bool testnet = false); + bool load_checkpoints_from_dns(network_type nettype = MAINNET); private: std::map<uint64_t, crypto::hash> m_points; //!< the checkpoints container diff --git a/src/common/command_line.h b/src/common/command_line.h index f67efcf86..3a869bb26 100644 --- a/src/common/command_line.h +++ b/src/common/command_line.h @@ -33,6 +33,7 @@ #include <functional> #include <iostream> #include <sstream> +#include <array> #include <type_traits> #include <boost/program_options/parsers.hpp> @@ -48,7 +49,7 @@ namespace command_line //! \return True if `str` is `is_iequal("n" || "no" || `tr("no"))`. bool is_no(const std::string& str); - template<typename T, bool required = false, bool dependent = false> + template<typename T, bool required = false, bool dependent = false, int NUM_DEPS = 1> struct arg_descriptor; template<typename T> @@ -98,6 +99,22 @@ namespace command_line bool not_use_default; }; + template<typename T, int NUM_DEPS> + struct arg_descriptor<T, false, true, NUM_DEPS> + { + typedef T value_type; + + const char* name; + const char* description; + + T default_value; + + std::array<const arg_descriptor<bool, false> *, NUM_DEPS> ref; + std::function<T(std::array<bool, NUM_DEPS>, bool, T)> depf; + + bool not_use_default; + }; + template<typename T> boost::program_options::typed_value<T, char>* make_semantic(const arg_descriptor<T, true>& /*arg*/) { @@ -127,6 +144,28 @@ namespace command_line return semantic; } + template<typename T, int NUM_DEPS> + boost::program_options::typed_value<T, char>* make_semantic(const arg_descriptor<T, false, true, NUM_DEPS>& arg) + { + auto semantic = boost::program_options::value<T>(); + if (!arg.not_use_default) { + std::array<bool, NUM_DEPS> depval; + depval.fill(false); + std::ostringstream format; + format << arg.depf(depval, true, arg.default_value); + for (size_t i = 0; i < depval.size(); ++i) + { + depval.fill(false); + depval[i] = true; + format << ", " << arg.depf(depval, true, arg.default_value) << " if '" << arg.ref[i]->name << "'"; + } + for (size_t i = 0; i < depval.size(); ++i) + depval[i] = arg.ref[i]->default_value; + semantic->default_value(arg.depf(depval, true, arg.default_value), format.str()); + } + return semantic; + } + template<typename T> boost::program_options::typed_value<T, char>* make_semantic(const arg_descriptor<T, false>& arg, const T& def) { @@ -144,8 +183,8 @@ namespace command_line return semantic; } - template<typename T, bool required, bool dependent> - void add_arg(boost::program_options::options_description& description, const arg_descriptor<T, required, dependent>& arg, bool unique = true) + template<typename T, bool required, bool dependent, int NUM_DEPS> + void add_arg(boost::program_options::options_description& description, const arg_descriptor<T, required, dependent, NUM_DEPS>& arg, bool unique = true) { if (0 != description.find_nothrow(arg.name, false)) { @@ -214,35 +253,44 @@ namespace command_line } } - template<typename T, bool required> - bool has_arg(const boost::program_options::variables_map& vm, const arg_descriptor<T, required>& arg) + template<typename T, bool required, bool dependent, int NUM_DEPS> + typename std::enable_if<!std::is_same<T, bool>::value, bool>::type has_arg(const boost::program_options::variables_map& vm, const arg_descriptor<T, required, dependent, NUM_DEPS>& arg) { auto value = vm[arg.name]; return !value.empty(); } - template<typename T, bool required, bool dependent> - bool is_arg_defaulted(const boost::program_options::variables_map& vm, const arg_descriptor<T, required, dependent>& arg) + template<typename T, bool required, bool dependent, int NUM_DEPS> + bool is_arg_defaulted(const boost::program_options::variables_map& vm, const arg_descriptor<T, required, dependent, NUM_DEPS>& arg) { return vm[arg.name].defaulted(); } - template<typename T, bool required> - T get_arg(const boost::program_options::variables_map& vm, const arg_descriptor<T, required, true>& arg) + template<typename T> + T get_arg(const boost::program_options::variables_map& vm, const arg_descriptor<T, false, true>& arg) { return arg.depf(get_arg(vm, arg.ref), is_arg_defaulted(vm, arg), vm[arg.name].template as<T>()); } + template<typename T, int NUM_DEPS> + T get_arg(const boost::program_options::variables_map& vm, const arg_descriptor<T, false, true, NUM_DEPS>& arg) + { + std::array<bool, NUM_DEPS> depval; + for (size_t i = 0; i < depval.size(); ++i) + depval[i] = get_arg(vm, *arg.ref[i]); + return arg.depf(depval, is_arg_defaulted(vm, arg), vm[arg.name].template as<T>()); + } + template<typename T, bool required> T get_arg(const boost::program_options::variables_map& vm, const arg_descriptor<T, required>& arg) { return vm[arg.name].template as<T>(); } - template<> - inline bool has_arg<bool, false>(const boost::program_options::variables_map& vm, const arg_descriptor<bool, false>& arg) + template<bool dependent, int NUM_DEPS> + inline bool has_arg(const boost::program_options::variables_map& vm, const arg_descriptor<bool, false, dependent, NUM_DEPS>& arg) { - return get_arg<bool, false>(vm, arg); + return get_arg(vm, arg); } diff --git a/src/common/util.cpp b/src/common/util.cpp index e0f3cd655..d01da0fb7 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -435,15 +435,17 @@ std::string get_nix_version_display_string() #ifdef WIN32 std::string get_special_folder_path(int nfolder, bool iscreate) { - namespace fs = boost::filesystem; - char psz_path[MAX_PATH] = ""; + WCHAR psz_path[MAX_PATH] = L""; - if(SHGetSpecialFolderPathA(NULL, psz_path, nfolder, iscreate)) + if (SHGetSpecialFolderPathW(NULL, psz_path, nfolder, iscreate)) { - return psz_path; + int size_needed = WideCharToMultiByte(CP_UTF8, 0, psz_path, wcslen(psz_path), NULL, 0, NULL, NULL); + std::string folder_name(size_needed, 0); + WideCharToMultiByte(CP_UTF8, 0, psz_path, wcslen(psz_path), &folder_name[0], size_needed, NULL, NULL); + return folder_name; } - LOG_ERROR("SHGetSpecialFolderPathA() failed, could not obtain requested path."); + LOG_ERROR("SHGetSpecialFolderPathW() failed, could not obtain requested path."); return ""; } #endif @@ -501,13 +503,18 @@ std::string get_nix_version_display_string() int code; #if defined(WIN32) // Maximizing chances for success - DWORD attributes = ::GetFileAttributes(replaced_name.c_str()); + WCHAR wide_replacement_name[1000]; + MultiByteToWideChar(CP_UTF8, 0, replacement_name.c_str(), replacement_name.size() + 1, wide_replacement_name, 1000); + WCHAR wide_replaced_name[1000]; + MultiByteToWideChar(CP_UTF8, 0, replaced_name.c_str(), replaced_name.size() + 1, wide_replaced_name, 1000); + + DWORD attributes = ::GetFileAttributesW(wide_replaced_name); if (INVALID_FILE_ATTRIBUTES != attributes) { - ::SetFileAttributes(replaced_name.c_str(), attributes & (~FILE_ATTRIBUTE_READONLY)); + ::SetFileAttributesW(wide_replaced_name, attributes & (~FILE_ATTRIBUTE_READONLY)); } - bool ok = 0 != ::MoveFileEx(replacement_name.c_str(), replaced_name.c_str(), MOVEFILE_REPLACE_EXISTING); + bool ok = 0 != ::MoveFileExW(wide_replacement_name, wide_replaced_name, MOVEFILE_REPLACE_EXISTING); code = ok ? 0 : static_cast<int>(::GetLastError()); #else bool ok = 0 == std::rename(replacement_name.c_str(), replaced_name.c_str()); diff --git a/src/common/varint.h b/src/common/varint.h index 262bd1360..151d13dbf 100644 --- a/src/common/varint.h +++ b/src/common/varint.h @@ -45,7 +45,7 @@ * is as follows: Strip the msb of each byte, then from left to right, * read in what remains, placing it in reverse, into the buffer. Thus, * the following bit stream: 0xff02 would return 0x027f. 0xff turns - * into 0x7f, is placed on the beggining of the buffer, then 0x02 is + * into 0x7f, is placed on the beginning of the buffer, then 0x02 is * unchanged, since its msb is not set, and placed at the end of the * buffer. */ @@ -108,7 +108,7 @@ namespace tools { return EVARINT_REPRESENT; } - write |= static_cast<T>(byte & 0x7f) << shift; /* Does the actualy placing into write, stripping the first bit */ + write |= static_cast<T>(byte & 0x7f) << shift; /* Does the actually placing into write, stripping the first bit */ /* If there is no next */ if ((byte & 0x80) == 0) { diff --git a/src/crypto/chacha.h b/src/crypto/chacha.h index b45c3d7c7..22da53bd0 100644 --- a/src/crypto/chacha.h +++ b/src/crypto/chacha.h @@ -69,10 +69,10 @@ namespace crypto { chacha20(data, length, key.data(), reinterpret_cast<const uint8_t*>(&iv), cipher); } - inline void generate_chacha_key(const void *data, size_t size, chacha_key& key, bool prehashed=false) { + inline void generate_chacha_key(const void *data, size_t size, chacha_key& key, int cn_variant = 0, bool prehashed=false) { static_assert(sizeof(chacha_key) <= sizeof(hash), "Size of hash must be at least that of chacha_key"); tools::scrubbed_arr<char, HASH_SIZE> pwd_hash; - crypto::cn_slow_hash_pre(data, size, pwd_hash.data(), prehashed); + crypto::cn_slow_hash_pre(data, size, pwd_hash.data(), cn_variant, prehashed); memcpy(&key, pwd_hash.data(), sizeof(key)); } diff --git a/src/crypto/crypto.cpp b/src/crypto/crypto.cpp index afac105e4..0c70b9eeb 100644 --- a/src/crypto/crypto.cpp +++ b/src/crypto/crypto.cpp @@ -107,7 +107,7 @@ namespace crypto { /* * generate public and secret keys from a random 256-bit integer - * TODO: allow specifiying random value (for wallet recovery) + * TODO: allow specifying random value (for wallet recovery) * */ secret_key crypto_ops::generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key, bool recover) { diff --git a/src/crypto/hash-ops.h b/src/crypto/hash-ops.h index 130bf02db..934d464de 100644 --- a/src/crypto/hash-ops.h +++ b/src/crypto/hash-ops.h @@ -79,8 +79,8 @@ enum { }; void cn_fast_hash(const void *data, size_t length, char *hash); -void cn_slow_hash(const void *data, size_t length, char *hash); -void cn_slow_hash_pre(const void *data, size_t length, char *hash, bool pre); +void cn_slow_hash(const void *data, size_t length, char *hash, int variant); +void cn_slow_hash_pre(const void *data, size_t length, char *hash, int variant, bool pre); void hash_extra_blake(const void *data, size_t length, char *hash); void hash_extra_groestl(const void *data, size_t length, char *hash); diff --git a/src/crypto/hash.h b/src/crypto/hash.h index 14104699b..bf4f4c096 100644 --- a/src/crypto/hash.h +++ b/src/crypto/hash.h @@ -71,8 +71,8 @@ namespace crypto { return h; } - inline void cn_slow_hash(const void *data, std::size_t length, hash &hash) { - cn_slow_hash(data, length, reinterpret_cast<char *>(&hash)); + inline void cn_slow_hash(const void *data, std::size_t length, hash &hash, int variant = 0) { + cn_slow_hash(data, length, reinterpret_cast<char *>(&hash), variant); } inline void tree_hash(const hash *hashes, std::size_t count, hash &root_hash) { diff --git a/src/crypto/slow-hash.c b/src/crypto/slow-hash.c index 36bfba9fd..c733d7b39 100644 --- a/src/crypto/slow-hash.c +++ b/src/crypto/slow-hash.c @@ -32,6 +32,8 @@ #include <stddef.h> #include <stdint.h> #include <string.h> +#include <stdio.h> +#include <unistd.h> #include "common/int-util.h" #include "hash-ops.h" @@ -47,6 +49,46 @@ extern int aesb_single_round(const uint8_t *in, uint8_t*out, const uint8_t *expandedKey); extern int aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *expandedKey); +#define VARIANT1_1(p) \ + do if (variant > 0) \ + { \ + const uint8_t tmp = ((const uint8_t*)(p))[11]; \ + static const uint32_t table = 0x75310; \ + const uint8_t index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; \ + ((uint8_t*)(p))[11] = tmp ^ ((table >> index) & 0x30); \ + } while(0) + +#define VARIANT1_2(p) \ + do if (variant > 0) \ + { \ + xor64(p, tweak1_2); \ + } while(0) + +#define VARIANT1_CHECK() \ + do if (length < 43) \ + { \ + fprintf(stderr, "Cryptonight variants need at least 43 bytes of data"); \ + _exit(1); \ + } while(0) + +#define NONCE_POINTER (((const uint8_t*)data)+35) + +#define VARIANT1_PORTABLE_INIT() \ + uint8_t tweak1_2[8]; \ + do if (variant > 0) \ + { \ + VARIANT1_CHECK(); \ + memcpy(&tweak1_2, &state.hs.b[192], sizeof(tweak1_2)); \ + xor64(tweak1_2, NONCE_POINTER); \ + } while(0) + +#define VARIANT1_INIT64() \ + if (variant > 0) \ + { \ + VARIANT1_CHECK(); \ + } \ + const uint64_t tweak1_2 = variant > 0 ? (state.hs.w[24] ^ (*((const uint64_t*)NONCE_POINTER))) : 0 + #if !defined NO_AES && (defined(__x86_64__) || (defined(_MSC_VER) && defined(_WIN64))) // Optimised code below, uses x86-specific intrinsics, SSE2, AES-NI // Fall back to more portable code is down at the bottom @@ -125,6 +167,7 @@ extern int aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *exp _mm_store_si128(R128(c), _c); \ _b = _mm_xor_si128(_b, _c); \ _mm_store_si128(R128(&hp_state[j]), _b); \ + VARIANT1_1(&hp_state[j]); \ j = state_index(c); \ p = U64(&hp_state[j]); \ b[0] = p[0]; b[1] = p[1]; \ @@ -133,6 +176,7 @@ extern int aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *exp p = U64(&hp_state[j]); \ p[0] = a[0]; p[1] = a[1]; \ a[0] ^= b[0]; a[1] ^= b[1]; \ + VARIANT1_2(p + 1); \ _b = _c; \ #if defined(_MSC_VER) @@ -183,6 +227,11 @@ STATIC INLINE void xor_blocks(uint8_t *a, const uint8_t *b) U64(a)[1] ^= U64(b)[1]; } +STATIC INLINE void xor64(uint64_t *a, const uint64_t b) +{ + *a ^= b; +} + /** * @brief uses cpuid to determine if the CPU supports the AES instructions * @return true if the CPU supports AES, false otherwise @@ -515,11 +564,11 @@ void slow_hash_free_state(void) * @param length the length in bytes of the data * @param hash a pointer to a buffer in which the final 256 bit hash will be stored */ -void cn_slow_hash(const void *data, size_t length, char *hash) { - cn_slow_hash_pre(data,length,hash,false); +void cn_slow_hash(const void *data, size_t length, char *hash, int variant) { + cn_slow_hash_pre(data,length,hash,variant,false); } -void cn_slow_hash_pre(const void *data, size_t length, char *hash, bool prehashed) +void cn_slow_hash_pre(const void *data, size_t length, char *hash, int variant, bool prehashed) { RDATA_ALIGN16 uint8_t expandedKey[240]; /* These buffers are aligned to use later with SSE functions */ @@ -553,6 +602,8 @@ void cn_slow_hash_pre(const void *data, size_t length, char *hash, bool prehashe } memcpy(text, state.init, INIT_SIZE_BYTE); + VARIANT1_INIT64(); + /* CryptoNight Step 2: Iteratively encrypt the results from Keccak to fill * the 2MB large random access buffer. */ @@ -676,6 +727,11 @@ void slow_hash_free_state(void) #define U64(x) ((uint64_t *) (x)) +STATIC INLINE void xor64(uint64 *a, const uint64 b) +{ + *a ^= b; +} + #pragma pack(push, 1) union cn_slow_hash_state { @@ -712,6 +768,7 @@ union cn_slow_hash_state vst1q_u8((uint8_t *)c, _c); \ _b = veorq_u8(_b, _c); \ vst1q_u8(&hp_state[j], _b); \ + VARIANT1_1(&hp_state[j]); \ j = state_index(c); \ p = U64(&hp_state[j]); \ b[0] = p[0]; b[1] = p[1]; \ @@ -720,6 +777,7 @@ union cn_slow_hash_state p = U64(&hp_state[j]); \ p[0] = a[0]; p[1] = a[1]; \ a[0] ^= b[0]; a[1] ^= b[1]; \ + VARIANT1_2(p + 1); \ _b = _c; \ @@ -851,7 +909,7 @@ STATIC INLINE void aes_pseudo_round_xor(const uint8_t *in, uint8_t *out, const u } } -void cn_slow_hash(const void *data, size_t length, char *hash) +void cn_slow_hash(const void *data, size_t length, char *hash, int variant) { RDATA_ALIGN16 uint8_t expandedKey[240]; RDATA_ALIGN16 uint8_t hp_state[MEMORY]; @@ -877,6 +935,8 @@ void cn_slow_hash(const void *data, size_t length, char *hash) hash_process(&state.hs, data, length); memcpy(text, state.init, INIT_SIZE_BYTE); + VARIANT1_INIT64(); + /* CryptoNight Step 2: Iteratively encrypt the results from Keccak to fill * the 2MB large random access buffer. */ @@ -1045,7 +1105,7 @@ STATIC INLINE void xor_blocks(uint8_t* a, const uint8_t* b) U64(a)[1] ^= U64(b)[1]; } -void cn_slow_hash(const void *data, size_t length, char *hash) +void cn_slow_hash(const void *data, size_t length, char *hash, int variant) { uint8_t text[INIT_SIZE_BYTE]; uint8_t a[AES_BLOCK_SIZE]; @@ -1074,6 +1134,8 @@ void cn_slow_hash(const void *data, size_t length, char *hash) hash_process(&state.hs, data, length); memcpy(text, state.init, INIT_SIZE_BYTE); + VARIANT1_INIT64(); + aes_ctx = (oaes_ctx *) oaes_alloc(); oaes_key_import_data(aes_ctx, state.hs.b, AES_KEY_SIZE); @@ -1103,6 +1165,7 @@ void cn_slow_hash(const void *data, size_t length, char *hash) xor_blocks(b, p); swap_blocks(b, p); swap_blocks(a, b); + VARIANT1_1(p); // Iteration 2 p = &long_state[state_index(a)]; @@ -1112,6 +1175,7 @@ void cn_slow_hash(const void *data, size_t length, char *hash) swap_blocks(b, p); xor_blocks(b, p); swap_blocks(a, b); + VARIANT1_2(U64(p) + 1); } memcpy(text, state.init, INIT_SIZE_BYTE); @@ -1206,6 +1270,15 @@ static void xor_blocks(uint8_t* a, const uint8_t* b) { } } +static void xor64(uint8_t* left, const uint8_t* right) +{ + size_t i; + for (i = 0; i < 8; ++i) + { + left[i] ^= right[i]; + } +} + #pragma pack(push, 1) union cn_slow_hash_state { union hash_state hs; @@ -1216,7 +1289,7 @@ union cn_slow_hash_state { }; #pragma pack(pop) -void cn_slow_hash(const void *data, size_t length, char *hash) { +void cn_slow_hash(const void *data, size_t length, char *hash, int variant) { uint8_t long_state[MEMORY]; union cn_slow_hash_state state; uint8_t text[INIT_SIZE_BYTE]; @@ -1233,6 +1306,8 @@ void cn_slow_hash(const void *data, size_t length, char *hash) { memcpy(aes_key, state.hs.b, AES_KEY_SIZE); aes_ctx = (oaes_ctx *) oaes_alloc(); + VARIANT1_PORTABLE_INIT(); + oaes_key_import_data(aes_ctx, aes_key, AES_KEY_SIZE); for (i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) { for (j = 0; j < INIT_SIZE_BLK; j++) { @@ -1260,6 +1335,7 @@ void cn_slow_hash(const void *data, size_t length, char *hash) { copy_block(&long_state[j * AES_BLOCK_SIZE], c); assert(j == e2i(a, MEMORY / AES_BLOCK_SIZE)); swap_blocks(a, b); + VARIANT1_1(&long_state[j * AES_BLOCK_SIZE]); /* Iteration 2 */ j = e2i(a, MEMORY / AES_BLOCK_SIZE); copy_block(c, &long_state[j * AES_BLOCK_SIZE]); @@ -1267,6 +1343,7 @@ void cn_slow_hash(const void *data, size_t length, char *hash) { sum_half_blocks(b, d); swap_blocks(b, c); xor_blocks(b, c); + VARIANT1_2(c + 8); copy_block(&long_state[j * AES_BLOCK_SIZE], c); assert(j == e2i(a, MEMORY / AES_BLOCK_SIZE)); swap_blocks(a, b); diff --git a/src/cryptonote_basic/account.cpp b/src/cryptonote_basic/account.cpp index 26c823c2a..375b17389 100644 --- a/src/cryptonote_basic/account.cpp +++ b/src/cryptonote_basic/account.cpp @@ -183,16 +183,16 @@ DISABLE_VS_WARNINGS(4244 4345) return m_keys; } //----------------------------------------------------------------- - std::string account_base::get_public_address_str(bool testnet) const + std::string account_base::get_public_address_str(network_type nettype) const { //TODO: change this code into base 58 - return get_account_address_as_str(testnet, false, m_keys.m_account_address); + return get_account_address_as_str(nettype, false, m_keys.m_account_address); } //----------------------------------------------------------------- - std::string account_base::get_public_integrated_address_str(const crypto::hash8 &payment_id, bool testnet) const + std::string account_base::get_public_integrated_address_str(const crypto::hash8 &payment_id, network_type nettype) const { //TODO: change this code into base 58 - return get_account_integrated_address_as_str(testnet, m_keys.m_account_address, payment_id); + return get_account_integrated_address_as_str(nettype, m_keys.m_account_address, payment_id); } //----------------------------------------------------------------- } diff --git a/src/cryptonote_basic/account.h b/src/cryptonote_basic/account.h index d734599a3..b5d6ed85d 100644 --- a/src/cryptonote_basic/account.h +++ b/src/cryptonote_basic/account.h @@ -73,8 +73,8 @@ namespace cryptonote bool make_multisig(const crypto::secret_key &view_secret_key, const crypto::secret_key &spend_secret_key, const crypto::public_key &spend_public_key, const std::vector<crypto::secret_key> &multisig_keys); void finalize_multisig(const crypto::public_key &spend_public_key); const account_keys& get_keys() const; - std::string get_public_address_str(bool testnet) const; - std::string get_public_integrated_address_str(const crypto::hash8 &payment_id, bool testnet) const; + std::string get_public_address_str(network_type nettype) const; + std::string get_public_integrated_address_str(const crypto::hash8 &payment_id, network_type nettype) const; hw::device& get_device() const {return m_keys.get_device();} void set_device( hw::device &hwdev) {m_keys.set_device(hwdev);} diff --git a/src/cryptonote_basic/cryptonote_basic_impl.cpp b/src/cryptonote_basic/cryptonote_basic_impl.cpp index dbf4d4045..08a95d2e9 100644 --- a/src/cryptonote_basic/cryptonote_basic_impl.cpp +++ b/src/cryptonote_basic/cryptonote_basic_impl.cpp @@ -157,25 +157,26 @@ namespace cryptonote { } //----------------------------------------------------------------------- std::string get_account_address_as_str( - bool testnet + network_type nettype , bool subaddress , account_public_address const & adr ) { - uint64_t address_prefix = testnet ? - (subaddress ? config::testnet::CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX : config::testnet::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX) : + uint64_t address_prefix = nettype == TESTNET ? + (subaddress ? config::testnet::CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX : config::testnet::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX) : nettype == STAGENET ? + (subaddress ? config::stagenet::CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX : config::stagenet::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX) : (subaddress ? config::CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX : config::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX); return tools::base58::encode_addr(address_prefix, t_serializable_object_to_blob(adr)); } //----------------------------------------------------------------------- std::string get_account_integrated_address_as_str( - bool testnet + network_type nettype , account_public_address const & adr , crypto::hash8 const & payment_id ) { - uint64_t integrated_address_prefix = testnet ? config::testnet::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX : config::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX; + uint64_t integrated_address_prefix = nettype == TESTNET ? config::testnet::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX : nettype == STAGENET ? config::stagenet::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX : config::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX; integrated_address iadr = { adr, payment_id @@ -196,16 +197,19 @@ namespace cryptonote { //----------------------------------------------------------------------- bool get_account_address_from_str( address_parse_info& info - , bool testnet + , network_type nettype , std::string const & str ) { - uint64_t address_prefix = testnet ? - config::testnet::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX : config::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX; - uint64_t integrated_address_prefix = testnet ? - config::testnet::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX : config::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX; - uint64_t subaddress_prefix = testnet ? - config::testnet::CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX : config::CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX; + uint64_t address_prefix = nettype == TESTNET ? + config::testnet::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX : nettype == STAGENET ? + config::stagenet::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX : config::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX; + uint64_t integrated_address_prefix = nettype == TESTNET ? + config::testnet::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX : nettype == STAGENET ? + config::stagenet::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX : config::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX; + uint64_t subaddress_prefix = nettype == TESTNET ? + config::testnet::CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX : nettype == STAGENET ? + config::stagenet::CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX : config::CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX; if (2 * sizeof(public_address_outer_blob) != str.size()) { @@ -304,17 +308,17 @@ namespace cryptonote { //-------------------------------------------------------------------------------- bool get_account_address_from_str_or_url( address_parse_info& info - , bool testnet + , network_type nettype , const std::string& str_or_url , std::function<std::string(const std::string&, const std::vector<std::string>&, bool)> dns_confirm ) { - if (get_account_address_from_str(info, testnet, str_or_url)) + if (get_account_address_from_str(info, nettype, str_or_url)) return true; bool dnssec_valid; std::string address_str = tools::dns_utils::get_account_address_as_str_from_url(str_or_url, dnssec_valid, dns_confirm); return !address_str.empty() && - get_account_address_from_str(info, testnet, address_str); + get_account_address_from_str(info, nettype, address_str); } //-------------------------------------------------------------------------------- bool operator ==(const cryptonote::transaction& a, const cryptonote::transaction& b) { diff --git a/src/cryptonote_basic/cryptonote_basic_impl.h b/src/cryptonote_basic/cryptonote_basic_impl.h index 8943d93ea..f59785021 100644 --- a/src/cryptonote_basic/cryptonote_basic_impl.h +++ b/src/cryptonote_basic/cryptonote_basic_impl.h @@ -94,26 +94,26 @@ namespace cryptonote { uint8_t get_account_integrated_address_checksum(const public_integrated_address_outer_blob& bl); std::string get_account_address_as_str( - bool testnet + network_type nettype , bool subaddress , const account_public_address& adr ); std::string get_account_integrated_address_as_str( - bool testnet + network_type nettype , const account_public_address& adr , const crypto::hash8& payment_id ); bool get_account_address_from_str( address_parse_info& info - , bool testnet + , network_type nettype , const std::string& str ); bool get_account_address_from_str_or_url( address_parse_info& info - , bool testnet + , network_type nettype , const std::string& str_or_url , std::function<std::string(const std::string&, const std::vector<std::string>&, bool)> dns_confirm = return_first_address ); diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp index f462d1ca9..a10772424 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.cpp +++ b/src/cryptonote_basic/cryptonote_format_utils.cpp @@ -1022,7 +1022,8 @@ namespace cryptonote return true; } blobdata bd = get_block_hashing_blob(b); - crypto::cn_slow_hash(bd.data(), bd.size(), res); + const int cn_variant = b.major_version >= 7 ? b.major_version - 6 : 0; + crypto::cn_slow_hash(bd.data(), bd.size(), res, cn_variant); return true; } //--------------------------------------------------------------- diff --git a/src/cryptonote_basic/miner.cpp b/src/cryptonote_basic/miner.cpp index 919872709..f949bbd2b 100644 --- a/src/cryptonote_basic/miner.cpp +++ b/src/cryptonote_basic/miner.cpp @@ -218,7 +218,7 @@ namespace cryptonote command_line::add_arg(desc, arg_bg_mining_miner_target_percentage); } //----------------------------------------------------------------------------------------------------- - bool miner::init(const boost::program_options::variables_map& vm, bool testnet) + bool miner::init(const boost::program_options::variables_map& vm, network_type nettype) { if(command_line::has_arg(vm, arg_extra_messages)) { @@ -246,7 +246,7 @@ namespace cryptonote if(command_line::has_arg(vm, arg_start_mining)) { address_parse_info info; - if(!cryptonote::get_account_address_from_str(info, testnet, command_line::get_arg(vm, arg_start_mining)) || info.is_subaddress) + if(!cryptonote::get_account_address_from_str(info, nettype, command_line::get_arg(vm, arg_start_mining)) || info.is_subaddress) { LOG_ERROR("Target account address " << command_line::get_arg(vm, arg_start_mining) << " has wrong format, starting daemon canceled"); return false; @@ -602,7 +602,7 @@ namespace cryptonote // this should take care of the case where mining is started with bg-enabled, // and then the user decides to un-check background mining, and just do // regular full-speed mining. I might just be over-doing it and thinking up - // non-existant use-cases, so if the concensus is to simplify, we can remove all this fluff. + // non-existant use-cases, so if the consensus is to simplify, we can remove all this fluff. /* while( !m_is_background_mining_enabled ) { diff --git a/src/cryptonote_basic/miner.h b/src/cryptonote_basic/miner.h index 7bf5dc372..2bff784c7 100644 --- a/src/cryptonote_basic/miner.h +++ b/src/cryptonote_basic/miner.h @@ -64,7 +64,7 @@ namespace cryptonote public: miner(i_miner_handler* phandler); ~miner(); - bool init(const boost::program_options::variables_map& vm, bool testnet); + bool init(const boost::program_options::variables_map& vm, network_type nettype); static void init_options(boost::program_options::options_description& desc); bool set_block_template(const block& bl, const difficulty_type& diffic, uint64_t height); bool on_block_chain_update(); diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h index f9460e7db..171fc194a 100644 --- a/src/cryptonote_config.h +++ b/src/cryptonote_config.h @@ -172,7 +172,33 @@ namespace config boost::uuids::uuid const NETWORK_ID = { { 0x12 ,0x30, 0xF1, 0x71 , 0x61, 0x04 , 0x41, 0x61, 0x17, 0x31, 0x00, 0x82, 0x16, 0xA1, 0xA1, 0x11 } }; // Bender's daydream - std::string const GENESIS_TX = "013c01ff0001ffffffffffff0f029b2e4c0281c0b02e7c53291a94d1d0cbff8883f8024f5142ee494ffbbd0880712101168d0c4ca86fb55a4cf6a36d31431be1c53a3bd7411bb24e8832410289fa6f3b"; + std::string const GENESIS_TX = "013c01ff0001ffffffffffff03029b2e4c0281c0b02e7c53291a94d1d0cbff8883f8024f5142ee494ffbbd08807121017767aafcde9be00dcfd098715ebcf7f410daebc582fda69d24a28e9d0bc890d1"; uint32_t const GENESIS_NONCE = 10001; } + + namespace stagenet + { + uint64_t const CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX = 24; + uint64_t const CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX = 25; + uint64_t const CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX = 36; + uint16_t const P2P_DEFAULT_PORT = 38080; + uint16_t const RPC_DEFAULT_PORT = 38081; + uint16_t const ZMQ_RPC_DEFAULT_PORT = 38082; + boost::uuids::uuid const NETWORK_ID = { { + 0x12 ,0x30, 0xF1, 0x71 , 0x61, 0x04 , 0x41, 0x61, 0x17, 0x31, 0x00, 0x82, 0x16, 0xA1, 0xA1, 0x12 + } }; // Bender's daydream + std::string const GENESIS_TX = "013c01ff0001ffffffffffff0302df5d56da0c7d643ddd1ce61901c7bdc5fb1738bfe39fbe69c28a3a7032729c0f2101168d0c4ca86fb55a4cf6a36d31431be1c53a3bd7411bb24e8832410289fa6f3b"; + uint32_t const GENESIS_NONCE = 10002; + } +} + +namespace cryptonote +{ + enum network_type : uint8_t + { + MAINNET = 0, + TESTNET, + STAGENET, + FAKECHAIN + }; } diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index fe4004caa..d88cc1bf9 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -132,6 +132,16 @@ static const struct { }; static const uint64_t testnet_hard_fork_version_1_till = 624633; +static const struct { + uint8_t version; + uint64_t height; + uint8_t threshold; + time_t time; +} stagenet_hard_forks[] = { + // version 1 from the start of the blockchain + { 1, 1, 0, 1341378000 }, +}; + //------------------------------------------------------------------ Blockchain::Blockchain(tx_memory_pool& tx_pool) : m_db(), m_tx_pool(tx_pool), m_hardfork(NULL), m_timestamps_and_difficulties_height(0), m_current_block_cumul_sz_limit(0), m_current_block_cumul_sz_median(0), @@ -306,14 +316,12 @@ uint64_t Blockchain::get_current_blockchain_height() const //------------------------------------------------------------------ //FIXME: possibly move this into the constructor, to avoid accidentally // dereferencing a null BlockchainDB pointer -bool Blockchain::init(BlockchainDB* db, const bool testnet, bool offline, const cryptonote::test_options *test_options) +bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline, const cryptonote::test_options *test_options) { LOG_PRINT_L3("Blockchain::" << __func__); CRITICAL_REGION_LOCAL(m_tx_pool); CRITICAL_REGION_LOCAL1(m_blockchain_lock); - bool fakechain = test_options != NULL; - if (db == nullptr) { LOG_ERROR("Attempted to init Blockchain with null DB"); @@ -328,27 +336,32 @@ bool Blockchain::init(BlockchainDB* db, const bool testnet, bool offline, const m_db = db; - m_testnet = testnet; + m_nettype = test_options != NULL ? FAKECHAIN : nettype; m_offline = offline; if (m_hardfork == nullptr) { - if (fakechain) + if (m_nettype == FAKECHAIN || m_nettype == STAGENET) m_hardfork = new HardFork(*db, 1, 0); - else if (m_testnet) + else if (m_nettype == TESTNET) m_hardfork = new HardFork(*db, 1, testnet_hard_fork_version_1_till); else m_hardfork = new HardFork(*db, 1, mainnet_hard_fork_version_1_till); } - if (fakechain) + if (m_nettype == FAKECHAIN) { for (size_t n = 0; test_options->hard_forks[n].first; ++n) m_hardfork->add_fork(test_options->hard_forks[n].first, test_options->hard_forks[n].second, 0, n + 1); } - else if (m_testnet) + else if (m_nettype == TESTNET) { for (size_t n = 0; n < sizeof(testnet_hard_forks) / sizeof(testnet_hard_forks[0]); ++n) m_hardfork->add_fork(testnet_hard_forks[n].version, testnet_hard_forks[n].height, testnet_hard_forks[n].threshold, testnet_hard_forks[n].time); } + else if (m_nettype == STAGENET) + { + for (size_t n = 0; n < sizeof(stagenet_hard_forks) / sizeof(stagenet_hard_forks[0]); ++n) + m_hardfork->add_fork(stagenet_hard_forks[n].version, stagenet_hard_forks[n].height, stagenet_hard_forks[n].threshold, stagenet_hard_forks[n].time); + } else { for (size_t n = 0; n < sizeof(mainnet_hard_forks) / sizeof(mainnet_hard_forks[0]); ++n) @@ -367,10 +380,14 @@ bool Blockchain::init(BlockchainDB* db, const bool testnet, bool offline, const MINFO("Blockchain not loaded, generating genesis block."); block bl = boost::value_initialized<block>(); block_verification_context bvc = boost::value_initialized<block_verification_context>(); - if (m_testnet) + if (m_nettype == TESTNET) { generate_genesis_block(bl, config::testnet::GENESIS_TX, config::testnet::GENESIS_NONCE); } + else if (m_nettype == STAGENET) + { + generate_genesis_block(bl, config::stagenet::GENESIS_TX, config::stagenet::GENESIS_NONCE); + } else { generate_genesis_block(bl, config::GENESIS_TX, config::GENESIS_NONCE); @@ -384,7 +401,7 @@ bool Blockchain::init(BlockchainDB* db, const bool testnet, bool offline, const { } - if (!fakechain) + if (m_nettype != FAKECHAIN) { // ensure we fixup anything we found and fix in the future m_db->fixup(); @@ -406,7 +423,7 @@ bool Blockchain::init(BlockchainDB* db, const bool testnet, bool offline, const m_async_pool.create_thread(boost::bind(&boost::asio::io_service::run, &m_async_service)); #if defined(PER_BLOCK_CHECKPOINT) - if (!fakechain) + if (m_nettype != FAKECHAIN) load_compiled_in_block_hashes(); #endif @@ -417,11 +434,11 @@ bool Blockchain::init(BlockchainDB* db, const bool testnet, bool offline, const return true; } //------------------------------------------------------------------ -bool Blockchain::init(BlockchainDB* db, HardFork*& hf, const bool testnet, bool offline) +bool Blockchain::init(BlockchainDB* db, HardFork*& hf, const network_type nettype, bool offline) { if (hf != nullptr) m_hardfork = hf; - bool res = init(db, testnet, offline, NULL); + bool res = init(db, nettype, offline, NULL); if (hf == nullptr) hf = m_hardfork; return res; @@ -2739,7 +2756,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc, case rct::RCTTypeSimple: case rct::RCTTypeSimpleBulletproof: { - // check all this, either recontructed (so should really pass), or not + // check all this, either reconstructed (so should really pass), or not { if (pubkeys.size() != rv.mixRing.size()) { @@ -2797,7 +2814,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc, case rct::RCTTypeFull: case rct::RCTTypeFullBulletproof: { - // check all this, either recontructed (so should really pass), or not + // check all this, either reconstructed (so should really pass), or not { bool size_matches = true; for (size_t i = 0; i < pubkeys.size(); ++i) @@ -3547,6 +3564,7 @@ bool Blockchain::add_new_block(const block& bl_, block_verification_context& bvc LOG_PRINT_L3("block with id = " << id << " already exists"); bvc.m_already_exists = true; m_db->block_txn_stop(); + m_blocks_txs_check.clear(); return false; } @@ -3556,7 +3574,9 @@ bool Blockchain::add_new_block(const block& bl_, block_verification_context& bvc //chain switching or wrong block bvc.m_added_to_main_chain = false; m_db->block_txn_stop(); - return handle_alternative_block(bl, id, bvc); + bool r = handle_alternative_block(bl, id, bvc); + m_blocks_txs_check.clear(); + return r; //never relay alternative blocks } @@ -4316,15 +4336,17 @@ void Blockchain::cancel() static const char expected_block_hashes_hash[] = "4b553162ee4e7af3c53666506591489c68560b9175e6e941dc96c89f96f0e35c"; void Blockchain::load_compiled_in_block_hashes() { - if (m_fast_sync && get_blocks_dat_start(m_testnet) != nullptr && get_blocks_dat_size(m_testnet) > 0) + const bool testnet = m_nettype == TESTNET; + const bool stagenet = m_nettype == STAGENET; + if (m_fast_sync && get_blocks_dat_start(testnet, stagenet) != nullptr && get_blocks_dat_size(testnet, stagenet) > 0) { - MINFO("Loading precomputed blocks (" << get_blocks_dat_size(m_testnet) << " bytes)"); + MINFO("Loading precomputed blocks (" << get_blocks_dat_size(testnet, stagenet) << " bytes)"); - if (!m_testnet) + if (m_nettype == MAINNET) { // first check hash crypto::hash hash; - if (!tools::sha256sum(get_blocks_dat_start(m_testnet), get_blocks_dat_size(m_testnet), hash)) + if (!tools::sha256sum(get_blocks_dat_start(testnet, stagenet), get_blocks_dat_size(testnet, stagenet), hash)) { MERROR("Failed to hash precomputed blocks data"); return; @@ -4344,9 +4366,9 @@ void Blockchain::load_compiled_in_block_hashes() } } - if (get_blocks_dat_size(m_testnet) > 4) + if (get_blocks_dat_size(testnet, stagenet) > 4) { - const unsigned char *p = get_blocks_dat_start(m_testnet); + const unsigned char *p = get_blocks_dat_start(testnet, stagenet); const uint32_t nblocks = *p | ((*(p+1))<<8) | ((*(p+2))<<16) | ((*(p+3))<<24); if (nblocks > (std::numeric_limits<uint32_t>::max() - 4) / sizeof(hash)) { @@ -4354,7 +4376,7 @@ void Blockchain::load_compiled_in_block_hashes() return; } const size_t size_needed = 4 + nblocks * sizeof(crypto::hash); - if(nblocks > 0 && nblocks > (m_db->height() + HASH_OF_HASHES_STEP - 1) / HASH_OF_HASHES_STEP && get_blocks_dat_size(m_testnet) >= size_needed) + if(nblocks > 0 && nblocks > (m_db->height() + HASH_OF_HASHES_STEP - 1) / HASH_OF_HASHES_STEP && get_blocks_dat_size(testnet, stagenet) >= size_needed) { p += sizeof(uint32_t); m_blocks_hash_of_hashes.reserve(nblocks); diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h index b2bbff488..dd490cdd5 100644 --- a/src/cryptonote_core/blockchain.h +++ b/src/cryptonote_core/blockchain.h @@ -111,25 +111,25 @@ namespace cryptonote * @brief Initialize the Blockchain state * * @param db a pointer to the backing store to use for the blockchain - * @param testnet true if on testnet, else false + * @param nettype network type * @param offline true if running offline, else false * @param test_options test parameters * * @return true on success, false if any initialization steps fail */ - bool init(BlockchainDB* db, const bool testnet = false, bool offline = false, const cryptonote::test_options *test_options = NULL); + bool init(BlockchainDB* db, const network_type nettype = MAINNET, bool offline = false, const cryptonote::test_options *test_options = NULL); /** * @brief Initialize the Blockchain state * * @param db a pointer to the backing store to use for the blockchain * @param hf a structure containing hardfork information - * @param testnet true if on testnet, else false + * @param nettype network type * @param offline true if running offline, else false * * @return true on success, false if any initialization steps fail */ - bool init(BlockchainDB* db, HardFork*& hf, const bool testnet = false, bool offline = false); + bool init(BlockchainDB* db, HardFork*& hf, const network_type nettype = MAINNET, bool offline = false); /** * @brief Uninitializes the blockchain state @@ -1010,7 +1010,7 @@ namespace cryptonote HardFork *m_hardfork; - bool m_testnet; + network_type m_nettype; bool m_offline; std::atomic<bool> m_cancel; diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 8b837f2e4..8c0118803 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -71,14 +71,21 @@ namespace cryptonote , "Run on testnet. The wallet must be launched with --testnet flag." , false }; - const command_line::arg_descriptor<std::string, false, true> arg_data_dir = { + const command_line::arg_descriptor<bool, false> arg_stagenet_on = { + "stagenet" + , "Run on stagenet. The wallet must be launched with --stagenet flag." + , false + }; + const command_line::arg_descriptor<std::string, false, true, 2> arg_data_dir = { "data-dir" , "Specify data directory" , tools::get_default_data_dir() - , arg_testnet_on - , [](bool testnet, bool defaulted, std::string val) { - if (testnet) + , {{ &arg_testnet_on, &arg_stagenet_on }} + , [](std::array<bool, 2> testnet_stagenet, bool defaulted, std::string val) { + if (testnet_stagenet[0]) return (boost::filesystem::path(val) / "testnet").string(); + else if (testnet_stagenet[1]) + return (boost::filesystem::path(val) / "stagenet").string(); return val; } }; @@ -194,7 +201,7 @@ namespace cryptonote //----------------------------------------------------------------------------------------------- bool core::update_checkpoints() { - if (m_testnet || m_fakechain || m_disable_dns_checkpoints) return true; + if (m_nettype != MAINNET || m_disable_dns_checkpoints) return true; if (m_checkpoints_updating.test_and_set()) return true; @@ -243,6 +250,7 @@ namespace cryptonote command_line::add_arg(desc, arg_test_drop_download_height); command_line::add_arg(desc, arg_testnet_on); + command_line::add_arg(desc, arg_stagenet_on); command_line::add_arg(desc, arg_dns_checkpoints); command_line::add_arg(desc, arg_prep_blocks_threads); command_line::add_arg(desc, arg_fast_block_sync); @@ -262,16 +270,21 @@ namespace cryptonote //----------------------------------------------------------------------------------------------- bool core::handle_command_line(const boost::program_options::variables_map& vm) { - m_testnet = command_line::get_arg(vm, arg_testnet_on); + if (m_nettype != FAKECHAIN) + { + const bool testnet = command_line::get_arg(vm, arg_testnet_on); + const bool stagenet = command_line::get_arg(vm, arg_stagenet_on); + m_nettype = testnet ? TESTNET : stagenet ? STAGENET : MAINNET; + } m_config_folder = command_line::get_arg(vm, arg_data_dir); auto data_dir = boost::filesystem::path(m_config_folder); - if (!m_testnet && !m_fakechain) + if (m_nettype == MAINNET) { cryptonote::checkpoints checkpoints; - if (!checkpoints.init_default_checkpoints(m_testnet)) + if (!checkpoints.init_default_checkpoints(m_nettype)) { throw std::runtime_error("Failed to initialize checkpoints"); } @@ -360,9 +373,11 @@ namespace cryptonote { start_time = std::time(nullptr); - m_fakechain = test_options != NULL; + if (test_options != NULL) + { + m_nettype = FAKECHAIN; + } bool r = handle_command_line(vm); - bool testnet = command_line::get_arg(vm, arg_testnet_on); std::string m_config_folder_mempool = m_config_folder; if (config_subdir) @@ -377,7 +392,7 @@ namespace cryptonote size_t max_txpool_size = command_line::get_arg(vm, arg_max_txpool_size); boost::filesystem::path folder(m_config_folder); - if (m_fakechain) + if (m_nettype == FAKECHAIN) folder /= "fake"; // make sure the data directory exists, and try to lock it @@ -491,7 +506,7 @@ namespace cryptonote m_blockchain_storage.set_user_options(blocks_threads, blocks_per_sync, sync_mode, fast_sync); - r = m_blockchain_storage.init(db.release(), m_testnet, m_offline, test_options); + r = m_blockchain_storage.init(db.release(), m_nettype, m_offline, test_options); r = m_mempool.init(max_txpool_size); CHECK_AND_ASSERT_MES(r, false, "Failed to initialize memory pool"); @@ -526,7 +541,7 @@ namespace cryptonote return false; } - r = m_miner.init(vm, m_testnet); + r = m_miner.init(vm, m_nettype); CHECK_AND_ASSERT_MES(r, false, "Failed to initialize miner instance"); return load_state_data(); @@ -909,7 +924,7 @@ namespace cryptonote //----------------------------------------------------------------------------------------------- size_t core::get_block_sync_size(uint64_t height) const { - static const uint64_t quick_height = m_testnet ? 801219 : 1220516; + static const uint64_t quick_height = m_nettype == TESTNET ? 801219 : m_nettype == MAINNET ? 1220516 : 0; if (block_sync_size > 0) return block_sync_size; if (height >= quick_height) diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h index ce39aaddf..e1e430516 100644 --- a/src/cryptonote_core/cryptonote_core.h +++ b/src/cryptonote_core/cryptonote_core.h @@ -58,8 +58,9 @@ namespace cryptonote const std::pair<uint8_t, uint64_t> *hard_forks; }; - extern const command_line::arg_descriptor<std::string, false, true> arg_data_dir; + extern const command_line::arg_descriptor<std::string, false, true, 2> arg_data_dir; extern const command_line::arg_descriptor<bool, false> arg_testnet_on; + extern const command_line::arg_descriptor<bool, false> arg_stagenet_on; extern const command_line::arg_descriptor<bool> arg_offline; /************************************************************************/ @@ -725,11 +726,11 @@ namespace cryptonote std::pair<uint64_t, uint64_t> get_coinbase_tx_sum(const uint64_t start_offset, const size_t count); /** - * @brief get whether we're on testnet or not + * @brief get the network type we're on * - * @return are we on testnet? + * @return which network are we on? */ - bool get_testnet() const { return m_testnet; }; + network_type get_nettype() const { return m_nettype; }; /** * @brief get whether fluffy blocks are enabled @@ -954,9 +955,7 @@ namespace cryptonote uint64_t m_target_blockchain_height; //!< blockchain height target - bool m_testnet; //!< are we on testnet? - - bool m_fakechain; //!< are we using a fake chain (for testing purposes)? + network_type m_nettype; //!< which network are we on? std::string m_checkpoints_path; //!< path to json checkpoints file time_t m_last_dns_checkpoints_update; //!< time when dns checkpoints were last updated diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp index d641caf80..d0a958e1e 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.cpp +++ b/src/cryptonote_core/cryptonote_tx_utils.cpp @@ -190,6 +190,8 @@ namespace cryptonote addr = i.addr; ++count; } + if (count == 0 && change_addr) + return change_addr->m_view_public_key; return addr.m_view_public_key; } //--------------------------------------------------------------- @@ -639,17 +641,8 @@ namespace cryptonote //genesis block bl = boost::value_initialized<block>(); - - account_public_address ac = boost::value_initialized<account_public_address>(); - std::vector<size_t> sz; - construct_miner_tx(0, 0, 0, 0, 0, ac, bl.miner_tx); // zero fee in genesis - blobdata txb = tx_to_blob(bl.miner_tx); - std::string hex_tx_represent = string_tools::buff_to_hex_nodelimer(txb); - - std::string genesis_coinbase_tx_hex = config::GENESIS_TX; - blobdata tx_bl; - bool r = string_tools::parse_hexstr_to_binbuff(genesis_coinbase_tx_hex, tx_bl); + bool r = string_tools::parse_hexstr_to_binbuff(genesis_tx, tx_bl); CHECK_AND_ASSERT_MES(r, false, "failed to parse coinbase tx from hard coded blob"); r = parse_and_validate_tx_from_blob(tx_bl, bl.miner_tx); CHECK_AND_ASSERT_MES(r, false, "failed to parse coinbase tx from hard coded blob"); diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.h b/src/cryptonote_protocol/cryptonote_protocol_handler.h index e24c964a5..d7b74c06d 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.h +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.h @@ -1,6 +1,6 @@ /// @file /// @author rfree (current maintainer/user in monero.cc project - most of code is from CryptoNote) -/// @brief This is the orginal cryptonote protocol network-events handler, modified by us +/// @brief This is the original cryptonote protocol network-events handler, modified by us // Copyright (c) 2014-2018, The Monero Project // diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl index ff187e8ae..7c4f16c77 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl @@ -1,6 +1,6 @@ /// @file /// @author rfree (current maintainer/user in monero.cc project - most of code is from CryptoNote) -/// @brief This is the orginal cryptonote protocol network-events handler, modified by us +/// @brief This is the original cryptonote protocol network-events handler, modified by us // Copyright (c) 2014-2018, The Monero Project // @@ -302,7 +302,7 @@ namespace cryptonote int64_t diff = static_cast<int64_t>(hshd.current_height) - static_cast<int64_t>(m_core.get_current_blockchain_height()); uint64_t abs_diff = std::abs(diff); uint64_t max_block_height = std::max(hshd.current_height,m_core.get_current_blockchain_height()); - uint64_t last_block_v1 = m_core.get_testnet() ? 624633 : 1009826; + uint64_t last_block_v1 = m_core.get_nettype() == TESTNET ? 624633 : m_core.get_nettype() == MAINNET ? 1009826 : (uint64_t)-1; uint64_t diff_v2 = max_block_height > last_block_v1 ? std::min(abs_diff, max_block_height - last_block_v1) : 0; MCLOG(is_inital ? el::Level::Info : el::Level::Debug, "global", context << "Sync data returned a new top block candidate: " << m_core.get_current_blockchain_height() << " -> " << hshd.current_height << " [Your node is " << abs_diff << " blocks (" << ((abs_diff - diff_v2) / (24 * 60 * 60 / DIFFICULTY_TARGET_V1)) + (diff_v2 / (24 * 60 * 60 / DIFFICULTY_TARGET_V2)) << " days) " diff --git a/src/daemon/command_line_args.h b/src/daemon/command_line_args.h index efbae488c..add752029 100644 --- a/src/daemon/command_line_args.h +++ b/src/daemon/command_line_args.h @@ -37,27 +37,33 @@ namespace daemon_args { std::string const WINDOWS_SERVICE_NAME = "Monero Daemon"; - const command_line::arg_descriptor<std::string, false, true> arg_config_file = { + const command_line::arg_descriptor<std::string, false, true, 2> arg_config_file = { "config-file" , "Specify configuration file" , (daemonizer::get_default_data_dir() / std::string(CRYPTONOTE_NAME ".conf")).string() - , cryptonote::arg_testnet_on - , [](bool testnet, bool defaulted, std::string val) { - if (testnet && defaulted) + , {{ &cryptonote::arg_testnet_on, &cryptonote::arg_stagenet_on }} + , [](std::array<bool, 2> testnet_stagenet, bool defaulted, std::string val) { + if (testnet_stagenet[0] && defaulted) return (daemonizer::get_default_data_dir() / "testnet" / std::string(CRYPTONOTE_NAME ".conf")).string(); + else if (testnet_stagenet[1] && defaulted) + return (daemonizer::get_default_data_dir() / "stagenet" / + std::string(CRYPTONOTE_NAME ".conf")).string(); return val; } }; - const command_line::arg_descriptor<std::string, false, true> arg_log_file = { + const command_line::arg_descriptor<std::string, false, true, 2> arg_log_file = { "log-file" , "Specify log file" , (daemonizer::get_default_data_dir() / std::string(CRYPTONOTE_NAME ".log")).string() - , cryptonote::arg_testnet_on - , [](bool testnet, bool defaulted, std::string val) { - if (testnet && defaulted) + , {{ &cryptonote::arg_testnet_on, &cryptonote::arg_stagenet_on }} + , [](std::array<bool, 2> testnet_stagenet, bool defaulted, std::string val) { + if (testnet_stagenet[0] && defaulted) return (daemonizer::get_default_data_dir() / "testnet" / std::string(CRYPTONOTE_NAME ".log")).string(); + else if (testnet_stagenet[1] && defaulted) + return (daemonizer::get_default_data_dir() / "stagenet" / + std::string(CRYPTONOTE_NAME ".log")).string(); return val; } }; @@ -91,14 +97,16 @@ namespace daemon_args , "127.0.0.1" }; - const command_line::arg_descriptor<std::string, false, true> arg_zmq_rpc_bind_port = { + const command_line::arg_descriptor<std::string, false, true, 2> arg_zmq_rpc_bind_port = { "zmq-rpc-bind-port" , "Port for ZMQ RPC server to listen on" , std::to_string(config::ZMQ_RPC_DEFAULT_PORT) - , cryptonote::arg_testnet_on - , [](bool testnet, bool defaulted, std::string val) { - if (testnet && defaulted) + , {{ &cryptonote::arg_testnet_on, &cryptonote::arg_stagenet_on }} + , [](std::array<bool, 2> testnet_stagenet, bool defaulted, std::string val) { + if (testnet_stagenet[0] && defaulted) return std::to_string(config::testnet::ZMQ_RPC_DEFAULT_PORT); + if (testnet_stagenet[1] && defaulted) + return std::to_string(config::stagenet::ZMQ_RPC_DEFAULT_PORT); return val; } }; diff --git a/src/daemon/command_parser_executor.cpp b/src/daemon/command_parser_executor.cpp index 09e425dd1..7a89ebc0c 100644 --- a/src/daemon/command_parser_executor.cpp +++ b/src/daemon/command_parser_executor.cpp @@ -268,30 +268,44 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg } cryptonote::address_parse_info info; - bool testnet = false; - if(!cryptonote::get_account_address_from_str(info, false, args.front())) + cryptonote::network_type nettype = cryptonote::MAINNET; + if(!cryptonote::get_account_address_from_str(info, cryptonote::MAINNET, args.front())) { - if(!cryptonote::get_account_address_from_str(info, true, args.front())) + if(!cryptonote::get_account_address_from_str(info, cryptonote::TESTNET, args.front())) { - bool dnssec_valid; - std::string address_str = tools::dns_utils::get_account_address_as_str_from_url(args.front(), dnssec_valid, - [](const std::string &url, const std::vector<std::string> &addresses, bool dnssec_valid){return addresses[0];}); - if(!cryptonote::get_account_address_from_str(info, false, address_str)) + if(!cryptonote::get_account_address_from_str(info, cryptonote::STAGENET, args.front())) { - if(!cryptonote::get_account_address_from_str(info, true, address_str)) + bool dnssec_valid; + std::string address_str = tools::dns_utils::get_account_address_as_str_from_url(args.front(), dnssec_valid, + [](const std::string &url, const std::vector<std::string> &addresses, bool dnssec_valid){return addresses[0];}); + if(!cryptonote::get_account_address_from_str(info, cryptonote::MAINNET, address_str)) { - std::cout << "target account address has wrong format" << std::endl; - return true; - } - else - { - testnet = true; + if(!cryptonote::get_account_address_from_str(info, cryptonote::TESTNET, address_str)) + { + if(!cryptonote::get_account_address_from_str(info, cryptonote::STAGENET, address_str)) + { + std::cout << "target account address has wrong format" << std::endl; + return true; + } + else + { + nettype = cryptonote::STAGENET; + } + } + else + { + nettype = cryptonote::TESTNET; + } } } + else + { + nettype = cryptonote::STAGENET; + } } else { - testnet = true; + nettype = cryptonote::TESTNET; } } if (info.is_subaddress) @@ -299,8 +313,8 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg tools::fail_msg_writer() << "subaddress for mining reward is not yet supported!" << std::endl; return true; } - if(testnet) - std::cout << "Mining to a testnet address, make sure this is intentional!" << std::endl; + if(nettype != cryptonote::MAINNET) + std::cout << "Mining to a " << (nettype == cryptonote::TESTNET ? "testnet" : "stagenet") << "address, make sure this is intentional!" << std::endl; uint64_t threads_count = 1; bool do_background_mining = false; bool ignore_battery = false; @@ -325,7 +339,7 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg threads_count = (ok && 0 < threads_count) ? threads_count : 1; } - m_executor.start_mining(info.address, threads_count, testnet, do_background_mining, ignore_battery); + m_executor.start_mining(info.address, threads_count, nettype, do_background_mining, ignore_battery); return true; } diff --git a/src/daemon/core.h b/src/daemon/core.h index 1ff696bef..475f418d6 100644 --- a/src/daemon/core.h +++ b/src/daemon/core.h @@ -69,9 +69,12 @@ public: std::string get_config_subdir() const { bool testnet = command_line::get_arg(m_vm_HACK, cryptonote::arg_testnet_on); + bool stagenet = command_line::get_arg(m_vm_HACK, cryptonote::arg_stagenet_on); + bool mainnet = !testnet && !stagenet; std::string port = command_line::get_arg(m_vm_HACK, nodetool::arg_p2p_bind_port); - if ((!testnet && port != std::to_string(::config::P2P_DEFAULT_PORT)) - || (testnet && port != std::to_string(::config::testnet::P2P_DEFAULT_PORT))) { + if ((mainnet && port != std::to_string(::config::P2P_DEFAULT_PORT)) + || (testnet && port != std::to_string(::config::testnet::P2P_DEFAULT_PORT)) + || (stagenet && port != std::to_string(::config::stagenet::P2P_DEFAULT_PORT))) { return port; } return std::string(); diff --git a/src/daemon/daemon.cpp b/src/daemon/daemon.cpp index 8053932fe..48671f190 100644 --- a/src/daemon/daemon.cpp +++ b/src/daemon/daemon.cpp @@ -76,15 +76,16 @@ public: core.set_protocol(protocol.get()); const auto testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on); + const auto stagenet = command_line::get_arg(vm, cryptonote::arg_stagenet_on); const auto restricted = command_line::get_arg(vm, cryptonote::core_rpc_server::arg_restricted_rpc); const auto main_rpc_port = command_line::get_arg(vm, cryptonote::core_rpc_server::arg_rpc_bind_port); - rpcs.emplace_back(new t_rpc{vm, core, p2p, restricted, testnet, main_rpc_port, "core"}); + rpcs.emplace_back(new t_rpc{vm, core, p2p, restricted, testnet ? cryptonote::TESTNET : stagenet ? cryptonote::STAGENET : cryptonote::MAINNET, main_rpc_port, "core"}); auto restricted_rpc_port_arg = cryptonote::core_rpc_server::arg_rpc_restricted_bind_port; if(!command_line::is_arg_defaulted(vm, restricted_rpc_port_arg)) { auto restricted_rpc_port = command_line::get_arg(vm, restricted_rpc_port_arg); - rpcs.emplace_back(new t_rpc{vm, core, p2p, true, testnet, restricted_rpc_port, "restricted"}); + rpcs.emplace_back(new t_rpc{vm, core, p2p, true, testnet ? cryptonote::TESTNET : stagenet ? cryptonote::STAGENET : cryptonote::MAINNET, restricted_rpc_port, "restricted"}); } } }; diff --git a/src/daemon/main.cpp b/src/daemon/main.cpp index 752a92ba4..50384b2a6 100644 --- a/src/daemon/main.cpp +++ b/src/daemon/main.cpp @@ -138,6 +138,14 @@ int main(int argc, char const * argv[]) return 0; } + const bool testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on); + const bool stagenet = command_line::get_arg(vm, cryptonote::arg_stagenet_on); + if (testnet && stagenet) + { + std::cerr << "Can't specify more than one of --tesnet and --stagenet" << ENDL; + return 1; + } + std::string db_type = command_line::get_arg(vm, cryptonote::arg_db_type); // verify that blockchaindb type is valid diff --git a/src/daemon/rpc.h b/src/daemon/rpc.h index 17f6c7f67..9621b0d01 100644 --- a/src/daemon/rpc.h +++ b/src/daemon/rpc.h @@ -54,7 +54,7 @@ public: , t_core & core , t_p2p & p2p , const bool restricted - , const bool testnet + , const cryptonote::network_type nettype , const std::string & port , const std::string & description ) @@ -62,7 +62,7 @@ public: { MGINFO("Initializing " << m_description << " RPC server..."); - if (!m_server.init(vm, restricted, testnet, port)) + if (!m_server.init(vm, restricted, nettype, port)) { throw std::runtime_error("Failed to initialize " + m_description + " RPC server."); } diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp index 5ef799d40..73b8d1a18 100644 --- a/src/daemon/rpc_command_executor.cpp +++ b/src/daemon/rpc_command_executor.cpp @@ -442,7 +442,7 @@ bool t_rpc_command_executor::show_status() { % (unsigned long long)ires.height % (unsigned long long)net_height % get_sync_percentage(ires) - % (ires.testnet ? "testnet" : "mainnet") + % (ires.testnet ? "testnet" : ires.stagenet ? "stagenet" : "mainnet") % bootstrap_msg % (!has_mining_info ? "mining info unavailable" : mining_busy ? "syncing" : mres.active ? ( ( mres.is_background_mining_enabled ? "smart " : "" ) + std::string("mining at ") + get_mining_speed(mres.speed) ) : "not mining") % get_mining_speed(ires.difficulty / ires.target) @@ -1036,10 +1036,10 @@ bool t_rpc_command_executor::print_transaction_pool_stats() { return true; } -bool t_rpc_command_executor::start_mining(cryptonote::account_public_address address, uint64_t num_threads, bool testnet, bool do_background_mining, bool ignore_battery) { +bool t_rpc_command_executor::start_mining(cryptonote::account_public_address address, uint64_t num_threads, cryptonote::network_type nettype, bool do_background_mining, bool ignore_battery) { cryptonote::COMMAND_RPC_START_MINING::request req; cryptonote::COMMAND_RPC_START_MINING::response res; - req.miner_address = cryptonote::get_account_address_as_str(testnet, false, address); + req.miner_address = cryptonote::get_account_address_as_str(nettype, false, address); req.threads_count = num_threads; req.do_background_mining = do_background_mining; req.ignore_battery = ignore_battery; diff --git a/src/daemon/rpc_command_executor.h b/src/daemon/rpc_command_executor.h index fa83d8988..46168c93b 100644 --- a/src/daemon/rpc_command_executor.h +++ b/src/daemon/rpc_command_executor.h @@ -105,7 +105,7 @@ public: bool print_transaction_pool_stats(); - bool start_mining(cryptonote::account_public_address address, uint64_t num_threads, bool testnet, bool do_background_mining = false, bool ignore_battery = false); + bool start_mining(cryptonote::account_public_address address, uint64_t num_threads, cryptonote::network_type nettype, bool do_background_mining = false, bool ignore_battery = false); bool stop_mining(); diff --git a/src/daemonizer/CMakeLists.txt b/src/daemonizer/CMakeLists.txt index 2c0583c49..2753d0003 100644 --- a/src/daemonizer/CMakeLists.txt +++ b/src/daemonizer/CMakeLists.txt @@ -54,6 +54,10 @@ else() ) endif() +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + add_definitions(-DDEBUG_TMPDIR_LOG=1) +endif() + monero_private_headers(daemonizer ${daemonizer_private_headers}) monero_add_library(daemonizer diff --git a/src/daemonizer/posix_fork.cpp b/src/daemonizer/posix_fork.cpp index 4dff04f3f..3cbee9c51 100644 --- a/src/daemonizer/posix_fork.cpp +++ b/src/daemonizer/posix_fork.cpp @@ -115,6 +115,7 @@ void fork(const std::string & pidfile) quit("Unable to open /dev/null"); } +#ifdef DEBUG_TMPDIR_LOG // Send standard output to a log file. const char *tmpdir = getenv("TMPDIR"); if (!tmpdir) @@ -133,6 +134,7 @@ void fork(const std::string & pidfile) { quit("Unable to dup output descriptor"); } +#endif } } // namespace posix diff --git a/src/device/device_default.cpp b/src/device/device_default.cpp index a38d96c15..c3ba42000 100644 --- a/src/device/device_default.cpp +++ b/src/device/device_default.cpp @@ -254,10 +254,10 @@ namespace hw { default_core_device->set_name("default_core_device"); } - registry.insert(std::make_pair("default",default_core_device)); + registry.insert(std::make_pair("default", std::unique_ptr<device>(default_core_device))); } } -}
\ No newline at end of file +} diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp index e8eb7cc8b..571d42724 100644 --- a/src/device/device_ledger.cpp +++ b/src/device/device_ledger.cpp @@ -511,7 +511,7 @@ namespace hw { char prekey[200]; memmove(prekey, &this->buffer_recv[0], 200); - crypto::generate_chacha_key(&prekey[0], sizeof(prekey), key, true); + crypto::generate_chacha_key(&prekey[0], sizeof(prekey), key, 0, true); #ifdef DEBUG_HWDEVICE hw::ledger::check32("generate_chacha_key", "key", (char*)key_x.data(), (char*)key.data()); @@ -2054,7 +2054,7 @@ namespace hw { legder_device = new device_ledger(); legder_device->set_name("Ledger"); } - registry.insert(std::make_pair("Ledger", legder_device)); + registry.insert(std::make_pair("Ledger", std::unique_ptr<device>(legder_device))); } #else //WITH_DEVICE_LEDGER diff --git a/src/gen_multisig/gen_multisig.cpp b/src/gen_multisig/gen_multisig.cpp index 64204d8b9..9bcf4495c 100644 --- a/src/gen_multisig/gen_multisig.cpp +++ b/src/gen_multisig/gen_multisig.cpp @@ -72,11 +72,12 @@ namespace const command_line::arg_descriptor<uint32_t> arg_participants = {"participants", genms::tr("How many participants wil share parts of the multisig wallet"), 0}; const command_line::arg_descriptor<uint32_t> arg_threshold = {"threshold", genms::tr("How many signers are required to sign a valid transaction"), 0}; const command_line::arg_descriptor<bool, false> arg_testnet = {"testnet", genms::tr("Create testnet multisig wallets"), false}; + const command_line::arg_descriptor<bool, false> arg_stagenet = {"stagenet", genms::tr("Create stagenet multisig wallets"), false}; const command_line::arg_descriptor< std::vector<std::string> > arg_command = {"command", ""}; } -static bool generate_multisig(uint32_t threshold, uint32_t total, const std::string &basename, bool testnet) +static bool generate_multisig(uint32_t threshold, uint32_t total, const std::string &basename, network_type nettype) { tools::msg_writer() << (boost::format(genms::tr("Generating %u %u/%u multisig wallets")) % total % threshold % total).str(); @@ -89,7 +90,7 @@ static bool generate_multisig(uint32_t threshold, uint32_t total, const std::str for (size_t n = 0; n < total; ++n) { std::string name = basename + "-" + std::to_string(n + 1); - wallets[n].reset(new tools::wallet2(testnet)); + wallets[n].reset(new tools::wallet2(nettype)); wallets[n]->init(""); wallets[n]->generate(name, pwd_container->password(), rct::rct2sk(rct::skGen()), false, false); } @@ -149,7 +150,7 @@ static bool generate_multisig(uint32_t threshold, uint32_t total, const std::str } } - std::string address = wallets[0]->get_account().get_public_address_str(wallets[0]->testnet()); + std::string address = wallets[0]->get_account().get_public_address_str(wallets[0]->nettype()); tools::success_msg_writer() << genms::tr("Generated multisig wallets for address ") << address << std::endl << ss.str(); } catch (const std::exception &e) @@ -169,10 +170,11 @@ int main(int argc, char* argv[]) command_line::add_arg(desc_params, arg_threshold); command_line::add_arg(desc_params, arg_participants); command_line::add_arg(desc_params, arg_testnet); + command_line::add_arg(desc_params, arg_stagenet); const auto vm = wallet_args::main( argc, argv, - "monero-gen-multisig [--testnet] [--filename-base=<filename>] [--scheme=M/N] [--threshold=M] [--participants=N]", + "monero-gen-multisig [(--testnet|--stagenet)] [--filename-base=<filename>] [--scheme=M/N] [--threshold=M] [--participants=N]", genms::tr("This program generates a set of multisig wallets - use this simpler scheme only if all the participants trust each other"), desc_params, boost::program_options::positional_options_description(), @@ -182,11 +184,17 @@ int main(int argc, char* argv[]) if (!vm) return 1; - bool testnet; + bool testnet, stagenet; uint32_t threshold = 0, total = 0; std::string basename; testnet = command_line::get_arg(*vm, arg_testnet); + stagenet = command_line::get_arg(*vm, arg_stagenet); + if (testnet && stagenet) + { + tools::fail_msg_writer() << genms::tr("Error: Can't specify more than one of --testnet and --stagenet"); + return 1; + } if (command_line::has_arg(*vm, arg_scheme)) { if (sscanf(command_line::get_arg(*vm, arg_scheme).c_str(), "%u/%u", &threshold, &total) != 2) @@ -233,7 +241,7 @@ int main(int argc, char* argv[]) tools::fail_msg_writer() << genms::tr("Error: unsupported scheme: only N/N and N-1/N are supported"); return 1; } - if (!generate_multisig(threshold, total, basename, testnet)) + if (!generate_multisig(threshold, total, basename, testnet ? TESTNET : stagenet ? STAGENET : MAINNET)) return 1; return 0; diff --git a/src/p2p/net_node.cpp b/src/p2p/net_node.cpp index 170b79984..bde6fc88e 100644 --- a/src/p2p/net_node.cpp +++ b/src/p2p/net_node.cpp @@ -34,14 +34,16 @@ namespace nodetool { const command_line::arg_descriptor<std::string> arg_p2p_bind_ip = {"p2p-bind-ip", "Interface for p2p network protocol", "0.0.0.0"}; - const command_line::arg_descriptor<std::string, false, true> arg_p2p_bind_port = { + const command_line::arg_descriptor<std::string, false, true, 2> arg_p2p_bind_port = { "p2p-bind-port" , "Port for p2p network protocol" , std::to_string(config::P2P_DEFAULT_PORT) - , cryptonote::arg_testnet_on - , [](bool testnet, bool defaulted, std::string val) { - if (testnet && defaulted) + , {{ &cryptonote::arg_testnet_on, &cryptonote::arg_stagenet_on }} + , [](std::array<bool, 2> testnet_stagenet, bool defaulted, std::string val) { + if (testnet_stagenet[0] && defaulted) return std::to_string(config::testnet::P2P_DEFAULT_PORT); + else if (testnet_stagenet[1] && defaulted) + return std::to_string(config::stagenet::P2P_DEFAULT_PORT); return val; } }; diff --git a/src/p2p/net_node.h b/src/p2p/net_node.h index 54c474665..3010b43ad 100644 --- a/src/p2p/net_node.h +++ b/src/p2p/net_node.h @@ -223,7 +223,7 @@ namespace nodetool void cache_connect_fail_info(const epee::net_utils::network_address& addr); bool is_addr_recently_failed(const epee::net_utils::network_address& addr); bool is_priority_node(const epee::net_utils::network_address& na); - std::set<std::string> get_seed_nodes(bool testnet) const; + std::set<std::string> get_seed_nodes(cryptonote::network_type nettype) const; bool connect_to_seed(); template <class Container> @@ -331,13 +331,13 @@ namespace nodetool epee::critical_section m_host_fails_score_lock; std::map<std::string, uint64_t> m_host_fails_score; - bool m_testnet; + cryptonote::network_type m_nettype; }; const int64_t default_limit_up = 2048; const int64_t default_limit_down = 8192; extern const command_line::arg_descriptor<std::string> arg_p2p_bind_ip; - extern const command_line::arg_descriptor<std::string, false, true> arg_p2p_bind_port; + extern const command_line::arg_descriptor<std::string, false, true, 2> arg_p2p_bind_port; extern const command_line::arg_descriptor<uint32_t> arg_p2p_external_port; extern const command_line::arg_descriptor<bool> arg_p2p_allow_local_ip; extern const command_line::arg_descriptor<std::vector<std::string> > arg_p2p_add_peer; diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 59b417d90..8ef240326 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -262,7 +262,10 @@ namespace nodetool const boost::program_options::variables_map& vm ) { - m_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on); + bool testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on); + bool stagenet = command_line::get_arg(vm, cryptonote::arg_stagenet_on); + m_nettype = testnet ? cryptonote::TESTNET : stagenet ? cryptonote::STAGENET : cryptonote::MAINNET; + m_bind_ip = command_line::get_arg(vm, arg_p2p_bind_ip); m_port = command_line::get_arg(vm, arg_p2p_bind_port); m_external_port = command_line::get_arg(vm, arg_p2p_external_port); @@ -277,7 +280,7 @@ namespace nodetool { nodetool::peerlist_entry pe = AUTO_VAL_INIT(pe); pe.id = crypto::rand<uint64_t>(); - const uint16_t default_port = m_testnet ? ::config::testnet::P2P_DEFAULT_PORT : ::config::P2P_DEFAULT_PORT; + const uint16_t default_port = testnet ? ::config::testnet::P2P_DEFAULT_PORT : stagenet ? ::config::stagenet::P2P_DEFAULT_PORT : ::config::P2P_DEFAULT_PORT; bool r = parse_peer_from_string(pe.adr, pr_str, default_port); CHECK_AND_ASSERT_MES(r, false, "Failed to parse address from string: " << pr_str); m_command_line_peers.push_back(pe); @@ -370,10 +373,10 @@ namespace nodetool //----------------------------------------------------------------------------------- template<class t_payload_net_handler> - std::set<std::string> node_server<t_payload_net_handler>::get_seed_nodes(bool testnet) const + std::set<std::string> node_server<t_payload_net_handler>::get_seed_nodes(cryptonote::network_type nettype) const { std::set<std::string> full_addrs; - if (testnet) + if (nettype == cryptonote::TESTNET) { full_addrs.insert("212.83.175.67:28080"); full_addrs.insert("5.9.100.248:28080"); @@ -381,6 +384,11 @@ namespace nodetool full_addrs.insert("195.154.123.123:28080"); full_addrs.insert("212.83.172.165:28080"); } + else if (nettype == cryptonote::STAGENET) + { + full_addrs.insert("162.210.173.150:38080"); + full_addrs.insert("162.210.173.151:38080"); + } else { full_addrs.insert("107.152.130.98:18080"); @@ -404,10 +412,15 @@ namespace nodetool bool res = handle_command_line(vm); CHECK_AND_ASSERT_MES(res, false, "Failed to handle command line"); - if (m_testnet) + if (m_nettype == cryptonote::TESTNET) { memcpy(&m_network_id, &::config::testnet::NETWORK_ID, 16); - full_addrs = get_seed_nodes(true); + full_addrs = get_seed_nodes(cryptonote::TESTNET); + } + else if (m_nettype == cryptonote::STAGENET) + { + memcpy(&m_network_id, &::config::stagenet::NETWORK_ID, 16); + full_addrs = get_seed_nodes(cryptonote::STAGENET); } else if (m_exclusive_peers.empty()) { @@ -488,7 +501,7 @@ namespace nodetool else MINFO("Not enough DNS seed nodes found, using fallback defaults too"); - for (const auto &peer: get_seed_nodes(false)) + for (const auto &peer: get_seed_nodes(cryptonote::MAINNET)) full_addrs.insert(peer); } } @@ -502,8 +515,9 @@ namespace nodetool m_config_folder = command_line::get_arg(vm, cryptonote::arg_data_dir); - if ((!m_testnet && m_port != std::to_string(::config::P2P_DEFAULT_PORT)) - || (m_testnet && m_port != std::to_string(::config::testnet::P2P_DEFAULT_PORT))) { + if ((m_nettype == cryptonote::MAINNET && m_port != std::to_string(::config::P2P_DEFAULT_PORT)) + || (m_nettype == cryptonote::TESTNET && m_port != std::to_string(::config::testnet::P2P_DEFAULT_PORT)) + || (m_nettype == cryptonote::STAGENET && m_port != std::to_string(::config::stagenet::P2P_DEFAULT_PORT))) { m_config_folder = m_config_folder + "/" + m_port; } @@ -1137,7 +1151,7 @@ namespace nodetool if (!fallback_nodes_added) { MWARNING("Failed to connect to any of seed peers, trying fallback seeds"); - for (const auto &peer: get_seed_nodes(m_testnet)) + for (const auto &peer: get_seed_nodes(m_nettype)) { MDEBUG("Fallback seed node: " << peer); append_net_address(m_seed_nodes, peer); @@ -1797,7 +1811,7 @@ namespace nodetool for(const std::string& pr_str: perrs) { epee::net_utils::network_address na = AUTO_VAL_INIT(na); - const uint16_t default_port = m_testnet ? ::config::testnet::P2P_DEFAULT_PORT : ::config::P2P_DEFAULT_PORT; + const uint16_t default_port = m_nettype == cryptonote::TESTNET ? ::config::testnet::P2P_DEFAULT_PORT : m_nettype == cryptonote::STAGENET ? ::config::stagenet::P2P_DEFAULT_PORT : ::config::P2P_DEFAULT_PORT; bool r = parse_peer_from_string(na, pr_str, default_port); CHECK_AND_ASSERT_MES(r, false, "Failed to parse address from string: " << pr_str); container.push_back(na); diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp index d3437eb36..ae0ee21c8 100644 --- a/src/ringct/rctSigs.cpp +++ b/src/ringct/rctSigs.cpp @@ -130,29 +130,12 @@ namespace rct { return equalKeys(eeComputed, bb.ee); } - //Multilayered Spontaneous Anonymous Group Signatures (MLSAG signatures) - //These are aka MG signatutes in earlier drafts of the ring ct paper - // c.f. http://eprint.iacr.org/2015/1098 section 2. - // keyImageV just does I[i] = xx[i] * Hash(xx[i] * G) for each i - // Gen creates a signature which proves that for some column in the keymatrix "pk" - // the signer knows a secret key for each row in that column - // Ver verifies that the MG sig was created correctly - keyV keyImageV(const keyV &xx) { - keyV II(xx.size()); - size_t i = 0; - for (i = 0; i < xx.size(); i++) { - II[i] = scalarmultKey(hashToPoint(scalarmultBase(xx[i])), xx[i]); - } - return II; - } - //Multilayered Spontaneous Anonymous Group Signatures (MLSAG signatures) //This is a just slghtly more efficient version than the ones described below //(will be explained in more detail in Ring Multisig paper //These are aka MG signatutes in earlier drafts of the ring ct paper // c.f. http://eprint.iacr.org/2015/1098 section 2. - // keyImageV just does I[i] = xx[i] * Hash(xx[i] * G) for each i // Gen creates a signature which proves that for some column in the keymatrix "pk" // the signer knows a secret key for each row in that column // Ver verifies that the MG sig was created correctly @@ -250,7 +233,6 @@ namespace rct { //(will be explained in more detail in Ring Multisig paper //These are aka MG signatutes in earlier drafts of the ring ct paper // c.f. http://eprint.iacr.org/2015/1098 section 2. - // keyImageV just does I[i] = xx[i] * Hash(xx[i] * G) for each i // Gen creates a signature which proves that for some column in the keymatrix "pk" // the signer knows a secret key for each row in that column // Ver verifies that the MG sig was created correctly @@ -506,11 +488,12 @@ namespace rct { keyV sk(rows + 1); size_t i; keyM M(cols, tmp); + + sk[0] = copy(inSk.dest); + sc_sub(sk[1].bytes, inSk.mask.bytes, a.bytes); for (i = 0; i < cols; i++) { M[i][0] = pubs[i].dest; subKeys(M[i][1], pubs[i].mask, Cout); - sk[0] = copy(inSk.dest); - sc_sub(sk[1].bytes, inSk.mask.bytes, a.bytes); } return MLSAG_Gen(message, M, sk, kLRki, mscout, index, rows, hwdev); } diff --git a/src/ringct/rctSigs.h b/src/ringct/rctSigs.h index 17047fc0f..7485938ee 100644 --- a/src/ringct/rctSigs.h +++ b/src/ringct/rctSigs.h @@ -70,11 +70,9 @@ namespace rct { //Multilayered Spontaneous Anonymous Group Signatures (MLSAG signatures) //These are aka MG signatutes in earlier drafts of the ring ct paper // c.f. http://eprint.iacr.org/2015/1098 section 2. - // keyImageV just does I[i] = xx[i] * HashToPoint(xx[i] * G) for each i // Gen creates a signature which proves that for some column in the keymatrix "pk" // the signer knows a secret key for each row in that column // Ver verifies that the MG sig was created correctly - keyV keyImageV(const keyV &xx); mgSig MLSAG_Gen(const key &message, const keyM & pk, const keyV & xx, const multisig_kLRki *kLRki, key *mscout, const unsigned int index, size_t dsRows, hw::device &hwdev); bool MLSAG_Ver(const key &message, const keyM &pk, const mgSig &sig, size_t dsRows); //mgSig MLSAG_Gen_Old(const keyM & pk, const keyV & xx, const int index); diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index a8d801ac7..0e3e6757b 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -90,12 +90,12 @@ namespace cryptonote bool core_rpc_server::init( const boost::program_options::variables_map& vm , const bool restricted - , const bool testnet + , const network_type nettype , const std::string& port ) { m_restricted = restricted; - m_testnet = testnet; + m_nettype = nettype; m_net_server.set_threads_prefix("RPC"); auto rpc_config = cryptonote::rpc_args::process(vm); @@ -190,7 +190,9 @@ namespace cryptonote res.rpc_connections_count = get_connections_count(); res.white_peerlist_size = m_p2p.get_peerlist_manager().get_white_peers_count(); res.grey_peerlist_size = m_p2p.get_peerlist_manager().get_gray_peers_count(); - res.testnet = m_testnet; + res.mainnet = m_nettype == MAINNET; + res.testnet = m_nettype == TESTNET; + res.stagenet = m_nettype == STAGENET; res.cumulative_difficulty = m_core.get_blockchain_storage().get_db().get_block_cumulative_difficulty(res.height - 1); res.block_size_limit = m_core.get_blockchain_storage().get_current_cumulative_blocksize_limit(); res.block_size_median = m_core.get_blockchain_storage().get_current_cumulative_blocksize_median(); @@ -823,7 +825,7 @@ namespace cryptonote PERF_TIMER(on_start_mining); CHECK_CORE_READY(); cryptonote::address_parse_info info; - if(!get_account_address_from_str(info, m_testnet, req.miner_address)) + if(!get_account_address_from_str(info, m_nettype, req.miner_address)) { res.status = "Failed, wrong address"; LOG_PRINT_L0(res.status); @@ -891,7 +893,7 @@ namespace cryptonote res.speed = lMiner.get_speed(); res.threads_count = lMiner.get_threads_count(); const account_public_address& lMiningAdr = lMiner.get_mining_address(); - res.address = get_account_address_as_str(m_testnet, false, lMiningAdr); + res.address = get_account_address_as_str(m_nettype, false, lMiningAdr); } res.status = CORE_RPC_STATUS_OK; @@ -1106,7 +1108,7 @@ namespace cryptonote cryptonote::address_parse_info info; - if(!req.wallet_address.size() || !cryptonote::get_account_address_from_str(info, m_testnet, req.wallet_address)) + if(!req.wallet_address.size() || !cryptonote::get_account_address_from_str(info, m_nettype, req.wallet_address)) { error_resp.code = CORE_RPC_ERROR_CODE_WRONG_WALLET_ADDRESS; error_resp.message = "Failed to parse wallet address"; @@ -1568,7 +1570,9 @@ namespace cryptonote res.rpc_connections_count = get_connections_count(); res.white_peerlist_size = m_p2p.get_peerlist_manager().get_white_peers_count(); res.grey_peerlist_size = m_p2p.get_peerlist_manager().get_gray_peers_count(); - res.testnet = m_testnet; + res.mainnet = m_nettype == MAINNET; + res.testnet = m_nettype == TESTNET; + res.stagenet = m_nettype == STAGENET; res.cumulative_difficulty = m_core.get_blockchain_storage().get_db().get_block_cumulative_difficulty(res.height - 1); res.block_size_limit = m_core.get_blockchain_storage().get_current_cumulative_blocksize_limit(); res.block_size_median = m_core.get_blockchain_storage().get_current_cumulative_blocksize_median(); @@ -2073,14 +2077,16 @@ namespace cryptonote } //------------------------------------------------------------------------------------------------------------------------------ - const command_line::arg_descriptor<std::string, false, true> core_rpc_server::arg_rpc_bind_port = { + const command_line::arg_descriptor<std::string, false, true, 2> core_rpc_server::arg_rpc_bind_port = { "rpc-bind-port" , "Port for RPC server" , std::to_string(config::RPC_DEFAULT_PORT) - , cryptonote::arg_testnet_on - , [](bool testnet, bool defaulted, std::string val) { - if (testnet && defaulted) + , {{ &cryptonote::arg_testnet_on, &cryptonote::arg_stagenet_on }} + , [](std::array<bool, 2> testnet_stagenet, bool defaulted, std::string val) { + if (testnet_stagenet[0] && defaulted) return std::to_string(config::testnet::RPC_DEFAULT_PORT); + else if (testnet_stagenet[1] && defaulted) + return std::to_string(config::stagenet::RPC_DEFAULT_PORT); return val; } }; diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h index 3c57a6016..4754a5d5f 100644 --- a/src/rpc/core_rpc_server.h +++ b/src/rpc/core_rpc_server.h @@ -53,7 +53,7 @@ namespace cryptonote { public: - static const command_line::arg_descriptor<std::string, false, true> arg_rpc_bind_port; + static const command_line::arg_descriptor<std::string, false, true, 2> arg_rpc_bind_port; static const command_line::arg_descriptor<std::string> arg_rpc_restricted_bind_port; static const command_line::arg_descriptor<bool> arg_restricted_rpc; static const command_line::arg_descriptor<std::string> arg_bootstrap_daemon_address; @@ -70,10 +70,10 @@ namespace cryptonote bool init( const boost::program_options::variables_map& vm, const bool restricted, - const bool testnet, + const network_type nettype, const std::string& port ); - bool is_testnet() const { return m_testnet; } + network_type nettype() const { return m_nettype; } CHAIN_HTTP_TO_MAP2(connection_context); //forward http requests to uri map @@ -235,7 +235,7 @@ private: bool m_should_use_bootstrap_daemon; std::chrono::system_clock::time_point m_bootstrap_height_check_time; bool m_was_bootstrap_ever_used; - bool m_testnet; + network_type m_nettype; bool m_restricted; }; } diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 64a97f8a3..a2c780376 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -948,7 +948,9 @@ namespace cryptonote uint64_t rpc_connections_count; uint64_t white_peerlist_size; uint64_t grey_peerlist_size; + bool mainnet; bool testnet; + bool stagenet; std::string top_block_hash; uint64_t cumulative_difficulty; uint64_t block_size_limit; @@ -975,7 +977,9 @@ namespace cryptonote KV_SERIALIZE(rpc_connections_count) KV_SERIALIZE(white_peerlist_size) KV_SERIALIZE(grey_peerlist_size) + KV_SERIALIZE(mainnet) KV_SERIALIZE(testnet) + KV_SERIALIZE(stagenet) KV_SERIALIZE(top_block_hash) KV_SERIALIZE(cumulative_difficulty) KV_SERIALIZE(block_size_limit) diff --git a/src/rpc/daemon_handler.cpp b/src/rpc/daemon_handler.cpp index 2f3f336a4..29020aa57 100644 --- a/src/rpc/daemon_handler.cpp +++ b/src/rpc/daemon_handler.cpp @@ -413,7 +413,7 @@ namespace rpc void DaemonHandler::handle(const StartMining::Request& req, StartMining::Response& res) { cryptonote::address_parse_info info; - if(!get_account_address_from_str(info, m_core.get_testnet(), req.miner_address)) + if(!get_account_address_from_str(info, m_core.get_nettype(), req.miner_address)) { res.error_details = "Failed, wrong address"; LOG_PRINT_L0(res.error_details); @@ -492,7 +492,9 @@ namespace rpc res.info.grey_peerlist_size = m_p2p.get_peerlist_manager().get_gray_peers_count(); - res.info.testnet = m_core.get_testnet(); + res.info.mainnet = m_core.get_nettype() == MAINNET; + res.info.testnet = m_core.get_nettype() == TESTNET; + res.info.stagenet = m_core.get_nettype() == STAGENET; res.info.cumulative_difficulty = m_core.get_blockchain_storage().get_db().get_block_cumulative_difficulty(res.info.height - 1); res.info.block_size_limit = m_core.get_blockchain_storage().get_current_cumulative_blocksize_limit(); res.info.start_time = (uint64_t)m_core.get_start_time(); @@ -525,7 +527,7 @@ namespace rpc res.speed = lMiner.get_speed(); res.threads_count = lMiner.get_threads_count(); const account_public_address& lMiningAdr = lMiner.get_mining_address(); - res.address = get_account_address_as_str(m_core.get_testnet(), false, lMiningAdr); + res.address = get_account_address_as_str(m_core.get_nettype(), false, lMiningAdr); } res.status = Message::STATUS_OK; diff --git a/src/rpc/message_data_structs.h b/src/rpc/message_data_structs.h index 9ba311976..17ae9629f 100644 --- a/src/rpc/message_data_structs.h +++ b/src/rpc/message_data_structs.h @@ -178,7 +178,9 @@ namespace rpc uint64_t incoming_connections_count; uint64_t white_peerlist_size; uint64_t grey_peerlist_size; + bool mainnet; bool testnet; + bool stagenet; crypto::hash top_block_hash; uint64_t cumulative_difficulty; uint64_t block_size_limit; diff --git a/src/serialization/binary_archive.h b/src/serialization/binary_archive.h index 79c6c753c..f47a4494d 100644 --- a/src/serialization/binary_archive.h +++ b/src/serialization/binary_archive.h @@ -82,7 +82,7 @@ protected: /* \struct binary_archive * - * \brief the actualy binary archive type + * \brief the actually binary archive type * * \detailed The boolean template argument /a W is the is_saving * parameter for binary_archive_base. diff --git a/src/serialization/variant.h b/src/serialization/variant.h index 31d903d55..1d00ab461 100644 --- a/src/serialization/variant.h +++ b/src/serialization/variant.h @@ -87,7 +87,7 @@ struct variant_reader }; // This one just fails when you call it.... okay -// So the TEnd parameter must be specified/differnt from TBegin +// So the TEnd parameter must be specified/different from TBegin template <class Archive, class Variant, class TBegin> struct variant_reader<Archive, Variant, TBegin, TBegin> { diff --git a/src/simplewallet/CMakeLists.txt b/src/simplewallet/CMakeLists.txt index 4230e32c0..8bb295931 100644 --- a/src/simplewallet/CMakeLists.txt +++ b/src/simplewallet/CMakeLists.txt @@ -54,6 +54,7 @@ target_link_libraries(simplewallet ${Boost_CHRONO_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_FILESYSTEM_LIBRARY} + ${ICU_LIBRARIES} ${Boost_THREAD_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${GNU_READLINE_LIBRARY} diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 02deee0c7..c618869f2 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -65,6 +65,11 @@ #include "device/device.hpp" #include <stdexcept> +#ifdef WIN32 +#include <boost/locale.hpp> +#include <boost/filesystem.hpp> +#endif + #ifdef HAVE_READLINE #include "readline_buffer.h" #endif @@ -132,6 +137,28 @@ namespace const command_line::arg_descriptor< std::vector<std::string> > arg_command = {"command", ""}; +#ifdef WIN32 + // Translate from CP850 to UTF-8; + // std::getline for a Windows console returns a string in CP437 or CP850; as simplewallet, + // like all of Monero, is assumed to work internally with UTF-8 throughout, even on Windows + // (although only implemented partially), a translation to UTF-8 is needed for input. + // + // Note that if a program is started inside the MSYS2 shell somebody already translates + // console input to UTF-8, but it's not clear how one could detect that in order to avoid + // double-translation; this code here thus breaks UTF-8 input within a MSYS2 shell, + // unfortunately. + // + // Note also that input for passwords is NOT translated, to remain compatible with any + // passwords containing special characters that predate this switch to UTF-8 support. + static std::string cp850_to_utf8(const std::string &cp850_str) + { + boost::locale::generator gen; + gen.locale_cache_enabled(true); + std::locale loc = gen("en_US.CP850"); + return boost::locale::conv::to_utf<char>(cp850_str, loc); + } +#endif + std::string input_line(const std::string& prompt) { #ifdef HAVE_READLINE @@ -141,6 +168,9 @@ namespace std::string buf; std::getline(std::cin, buf); +#ifdef WIN32 + buf = cp850_to_utf8(buf); +#endif return epee::string_tools::trim(buf); } @@ -576,10 +606,7 @@ bool simple_wallet::print_seed(bool encrypted) epee::wipeable_string seed_pass; if (encrypted) { -#ifdef HAVE_READLINE - rdln::suspend_readline pause_readline; -#endif - auto pwd_container = tools::password_container::prompt(true, tr("Enter optional seed encryption passphrase, empty to see raw seed")); + auto pwd_container = password_prompter(tr("Enter optional seed encryption passphrase, empty to see raw seed"), true); if (std::cin.eof() || !pwd_container) return true; seed_pass = pwd_container->password(); @@ -855,7 +882,7 @@ bool simple_wallet::make_multisig(const std::vector<std::string> &args) return true; } success_msg_writer() << std::to_string(threshold) << "/" << total << tr(" multisig address: ") - << m_wallet->get_account().get_public_address_str(m_wallet->testnet()); + << m_wallet->get_account().get_public_address_str(m_wallet->nettype()); return true; } @@ -2120,6 +2147,15 @@ static bool might_be_partial_seed(std::string words) //---------------------------------------------------------------------------------------------------- bool simple_wallet::init(const boost::program_options::variables_map& vm) { + const bool testnet = tools::wallet2::has_testnet_option(vm); + const bool stagenet = tools::wallet2::has_stagenet_option(vm); + if (testnet && stagenet) + { + fail_msg_writer() << tr("Can't specify more than one of --testnet and --stagenet"); + return false; + } + const network_type nettype = testnet ? TESTNET : stagenet ? STAGENET : MAINNET; + std::string multisig_keys; if (!handle_command_line(vm)) @@ -2205,10 +2241,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm) } } -#ifdef HAVE_READLINE - rdln::suspend_readline pause_readline; -#endif - auto pwd_container = tools::password_container::prompt(false, tr("Enter seed encryption passphrase, empty if none")); + auto pwd_container = password_prompter(tr("Enter seed encryption passphrase, empty if none"), false); if (std::cin.eof() || !pwd_container) return false; epee::wipeable_string seed_pass = pwd_container->password(); @@ -2237,7 +2270,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm) return false; } cryptonote::address_parse_info info; - if(!get_account_address_from_str(info, tools::wallet2::has_testnet_option(vm), address_string)) + if(!get_account_address_from_str(info, nettype, address_string)) { fail_msg_writer() << tr("failed to parse address"); return false; @@ -2311,7 +2344,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm) return false; } cryptonote::address_parse_info info; - if(!get_account_address_from_str(info, tools::wallet2::has_testnet_option(vm), address_string)) + if(!get_account_address_from_str(info, nettype, address_string)) { fail_msg_writer() << tr("failed to parse address"); return false; @@ -2420,7 +2453,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm) return false; } cryptonote::address_parse_info info; - if(!get_account_address_from_str(info, tools::wallet2::has_testnet_option(vm), address_string)) + if(!get_account_address_from_str(info, nettype, address_string)) { fail_msg_writer() << tr("failed to parse address"); return false; @@ -2589,7 +2622,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm) try { year = boost::lexical_cast<uint16_t>(heightstr.substr(0,4)); - // lexical_cast<uint8_t> won't work becasue uint8_t is treated as character type + // lexical_cast<uint8_t> won't work because uint8_t is treated as character type month = boost::lexical_cast<uint16_t>(heightstr.substr(5,2)); day = boost::lexical_cast<uint16_t>(heightstr.substr(8,2)); m_restore_height = m_wallet->get_blockchain_height_by_date(year, month, day); @@ -2800,7 +2833,7 @@ bool simple_wallet::new_wallet(const boost::program_options::variables_map& vm, // a seed language is not already specified AND // (it is not a wallet restore OR if it was a deprecated wallet // that was earlier used before this restore) - if ((!two_random) && (mnemonic_language.empty()) && (!m_restore_deterministic_wallet || was_deprecated_wallet)) + if ((!two_random) && (mnemonic_language.empty() || mnemonic_language == crypto::ElectrumWords::old_language_name) && (!m_restore_deterministic_wallet || was_deprecated_wallet)) { if (was_deprecated_wallet) { @@ -2820,7 +2853,7 @@ bool simple_wallet::new_wallet(const boost::program_options::variables_map& vm, { recovery_val = m_wallet->generate(m_wallet_file, std::move(rc.second).password(), recovery_key, recover, two_random); message_writer(console_color_white, true) << tr("Generated new wallet: ") - << m_wallet->get_account().get_public_address_str(m_wallet->testnet()); + << m_wallet->get_account().get_public_address_str(m_wallet->nettype()); std::cout << tr("View key: ") << string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_view_secret_key) << ENDL; } catch (const std::exception& e) @@ -2878,7 +2911,7 @@ bool simple_wallet::new_wallet(const boost::program_options::variables_map& vm, m_wallet->generate(m_wallet_file, std::move(rc.second).password(), address, viewkey); } message_writer(console_color_white, true) << tr("Generated new wallet: ") - << m_wallet->get_account().get_public_address_str(m_wallet->testnet()); + << m_wallet->get_account().get_public_address_str(m_wallet->nettype()); } catch (const std::exception& e) { @@ -2906,7 +2939,7 @@ bool simple_wallet::new_wallet(const boost::program_options::variables_map& vm, { m_wallet->restore(m_wallet_file, std::move(rc.second).password(), device_name); message_writer(console_color_white, true) << tr("Generated new on device wallet: ") - << m_wallet->get_account().get_public_address_str(m_wallet->testnet()); + << m_wallet->get_account().get_public_address_str(m_wallet->nettype()); } catch (const std::exception& e) { @@ -2949,7 +2982,7 @@ bool simple_wallet::new_wallet(const boost::program_options::variables_map& vm, return false; } message_writer(console_color_white, true) << boost::format(tr("Generated new %u/%u multisig wallet: ")) % threshold % total - << m_wallet->get_account().get_public_address_str(m_wallet->testnet()); + << m_wallet->get_account().get_public_address_str(m_wallet->nettype()); } catch (const std::exception& e) { @@ -2988,7 +3021,7 @@ bool simple_wallet::open_wallet(const boost::program_options::variables_map& vm) else prefix = tr("Opened wallet"); message_writer(console_color_white, true) << - prefix << ": " << m_wallet->get_account().get_public_address_str(m_wallet->testnet()); + prefix << ": " << m_wallet->get_account().get_public_address_str(m_wallet->nettype()); if (m_wallet->get_account().get_device()) { message_writer(console_color_white, true) << "Wallet is on device: " << m_wallet->get_account().get_device().get_name(); } @@ -3102,7 +3135,7 @@ bool simple_wallet::save_watch_only(const std::vector<std::string> &args/* = std return true; } - const auto pwd_container = tools::password_container::prompt(true, tr("Password for new watch-only wallet")); + const auto pwd_container = password_prompter(tr("Password for new watch-only wallet"), true); if (!pwd_container) { @@ -3132,7 +3165,7 @@ bool simple_wallet::start_mining(const std::vector<std::string>& args) return true; } COMMAND_RPC_START_MINING::request req = AUTO_VAL_INIT(req); - req.miner_address = m_wallet->get_account().get_public_address_str(m_wallet->testnet()); + req.miner_address = m_wallet->get_account().get_public_address_str(m_wallet->nettype()); bool ok = true; size_t max_mining_threads_count = (std::max)(tools::get_max_concurrency(), static_cast<unsigned>(2)); @@ -3221,7 +3254,7 @@ bool simple_wallet::set_daemon(const std::vector<std::string>& args) // If no port has been provided, use the default from config if (!match[3].length()) { - int daemon_port = m_wallet->testnet() ? config::testnet::RPC_DEFAULT_PORT : config::RPC_DEFAULT_PORT; + int daemon_port = m_wallet->nettype() == cryptonote::TESTNET ? config::testnet::RPC_DEFAULT_PORT : m_wallet->nettype() == cryptonote::STAGENET ? config::stagenet::RPC_DEFAULT_PORT : config::RPC_DEFAULT_PORT; daemon_url = match[1] + match[2] + std::string(":") + std::to_string(daemon_port); } else { daemon_url = args[0]; @@ -3683,14 +3716,25 @@ bool simple_wallet::print_ring_members(const std::vector<tools::wallet2::pending const tools::wallet2::tx_construction_data& construction_data = ptx_vector[n].construction_data; ostr << boost::format(tr("\nTransaction %llu/%llu: txid=%s")) % (n + 1) % ptx_vector.size() % cryptonote::get_transaction_hash(tx); // for each input - std::vector<int> spent_key_height(tx.vin.size()); + std::vector<uint64_t> spent_key_height(tx.vin.size()); std::vector<crypto::hash> spent_key_txid (tx.vin.size()); for (size_t i = 0; i < tx.vin.size(); ++i) { if (tx.vin[i].type() != typeid(cryptonote::txin_to_key)) continue; const cryptonote::txin_to_key& in_key = boost::get<cryptonote::txin_to_key>(tx.vin[i]); - const cryptonote::tx_source_entry& source = construction_data.sources[i]; + const tools::wallet2::transfer_details &td = m_wallet->get_transfer_details(construction_data.selected_transfers[i]); + const cryptonote::tx_source_entry *sptr = NULL; + for (const auto &src: construction_data.sources) + if (src.outputs[src.real_output].second.dest == td.get_public_key()) + sptr = &src; + if (!sptr) + { + fail_msg_writer() << tr("failed to find construction data for tx input"); + return false; + } + const cryptonote::tx_source_entry& source = *sptr; + ostr << boost::format(tr("\nInput %llu/%llu: amount=%s")) % (i + 1) % tx.vin.size() % print_money(source.amount); // convert relative offsets of ring member keys into absolute offsets (indices) associated with the amount std::vector<uint64_t> absolute_offsets = cryptonote::relative_output_offsets_to_absolute(in_key.key_offsets); @@ -3744,7 +3788,7 @@ bool simple_wallet::print_ring_members(const std::vector<tools::wallet2::pending { if (spent_key_txid[i] == spent_key_txid[j]) are_keys_from_same_tx = true; - if (std::abs(spent_key_height[i] - spent_key_height[j]) < 5) + if (std::abs((int64_t)(spent_key_height[i] - spent_key_height[j])) < (int64_t)5) are_keys_from_close_height = true; } } @@ -3880,7 +3924,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri { cryptonote::address_parse_info info; cryptonote::tx_destination_entry de; - if (!cryptonote::get_account_address_from_str_or_url(info, m_wallet->testnet(), local_args[i], oa_prompter)) + if (!cryptonote::get_account_address_from_str_or_url(info, m_wallet->nettype(), local_args[i], oa_prompter)) { fail_msg_writer() << tr("failed to parse address"); return true; @@ -4329,7 +4373,7 @@ bool simple_wallet::sweep_main(uint64_t below, const std::vector<std::string> &a } cryptonote::address_parse_info info; - if (!cryptonote::get_account_address_from_str_or_url(info, m_wallet->testnet(), local_args[0], oa_prompter)) + if (!cryptonote::get_account_address_from_str_or_url(info, m_wallet->nettype(), local_args[0], oa_prompter)) { fail_msg_writer() << tr("failed to parse address"); return true; @@ -4543,7 +4587,7 @@ bool simple_wallet::sweep_single(const std::vector<std::string> &args_) } cryptonote::address_parse_info info; - if (!cryptonote::get_account_address_from_str_or_url(info, m_wallet->testnet(), local_args[1], oa_prompter)) + if (!cryptonote::get_account_address_from_str_or_url(info, m_wallet->nettype(), local_args[1], oa_prompter)) { fail_msg_writer() << tr("failed to parse address"); return true; @@ -4690,9 +4734,9 @@ bool simple_wallet::sweep_below(const std::vector<std::string> &args_) //---------------------------------------------------------------------------------------------------- bool simple_wallet::donate(const std::vector<std::string> &args_) { - if(m_wallet->testnet()) + if(m_wallet->nettype() != cryptonote::MAINNET) { - fail_msg_writer() << tr("donations are not enabled on the testnet"); + fail_msg_writer() << tr("donations are not enabled on the testnet or on the stagenet"); return true; } @@ -4773,10 +4817,10 @@ bool simple_wallet::accept_loaded_tx(const std::function<size_t()> get_num_txes, for (size_t d = 0; d < cd.splitted_dsts.size(); ++d) { const tx_destination_entry &entry = cd.splitted_dsts[d]; - std::string address, standard_address = get_account_address_as_str(m_wallet->testnet(), entry.is_subaddress, entry.addr); + std::string address, standard_address = get_account_address_as_str(m_wallet->nettype(), entry.is_subaddress, entry.addr); if (has_encrypted_payment_id && !entry.is_subaddress) { - address = get_account_integrated_address_as_str(m_wallet->testnet(), entry.addr, payment_id8); + address = get_account_integrated_address_as_str(m_wallet->nettype(), entry.addr, payment_id8); address += std::string(" (" + standard_address + " with encrypted payment id " + epee::string_tools::pod_to_hex(payment_id8) + ")"); } else @@ -4847,7 +4891,7 @@ bool simple_wallet::accept_loaded_tx(const std::function<size_t()> get_num_txes, std::string change_string; if (change > 0) { - std::string address = get_account_address_as_str(m_wallet->testnet(), get_tx(0).subaddr_account > 0, get_tx(0).change_dts.addr); + std::string address = get_account_address_as_str(m_wallet->nettype(), get_tx(0).subaddr_account > 0, get_tx(0).change_dts.addr); change_string += (boost::format(tr("%s change to %s")) % print_money(change) % address).str(); } else @@ -5035,7 +5079,7 @@ bool simple_wallet::get_tx_proof(const std::vector<std::string> &args) } cryptonote::address_parse_info info; - if(!cryptonote::get_account_address_from_str_or_url(info, m_wallet->testnet(), args[1], oa_prompter)) + if(!cryptonote::get_account_address_from_str_or_url(info, m_wallet->nettype(), args[1], oa_prompter)) { fail_msg_writer() << tr("failed to parse address"); return true; @@ -5103,7 +5147,7 @@ bool simple_wallet::check_tx_key(const std::vector<std::string> &args_) } cryptonote::address_parse_info info; - if(!cryptonote::get_account_address_from_str_or_url(info, m_wallet->testnet(), local_args[2], oa_prompter)) + if(!cryptonote::get_account_address_from_str_or_url(info, m_wallet->nettype(), local_args[2], oa_prompter)) { fail_msg_writer() << tr("failed to parse address"); return true; @@ -5118,7 +5162,7 @@ bool simple_wallet::check_tx_key(const std::vector<std::string> &args_) if (received > 0) { - success_msg_writer() << get_account_address_as_str(m_wallet->testnet(), info.is_subaddress, info.address) << " " << tr("received") << " " << print_money(received) << " " << tr("in txid") << " " << txid; + success_msg_writer() << get_account_address_as_str(m_wallet->nettype(), info.is_subaddress, info.address) << " " << tr("received") << " " << print_money(received) << " " << tr("in txid") << " " << txid; if (in_pool) { success_msg_writer() << tr("WARNING: this transaction is not yet included in the blockchain!"); @@ -5137,7 +5181,7 @@ bool simple_wallet::check_tx_key(const std::vector<std::string> &args_) } else { - fail_msg_writer() << get_account_address_as_str(m_wallet->testnet(), info.is_subaddress, info.address) << " " << tr("received nothing in txid") << " " << txid; + fail_msg_writer() << get_account_address_as_str(m_wallet->nettype(), info.is_subaddress, info.address) << " " << tr("received nothing in txid") << " " << txid; } } catch (const std::exception &e) @@ -5167,7 +5211,7 @@ bool simple_wallet::check_tx_proof(const std::vector<std::string> &args) // parse address cryptonote::address_parse_info info; - if(!cryptonote::get_account_address_from_str_or_url(info, m_wallet->testnet(), args[1], oa_prompter)) + if(!cryptonote::get_account_address_from_str_or_url(info, m_wallet->nettype(), args[1], oa_prompter)) { fail_msg_writer() << tr("failed to parse address"); return true; @@ -5191,7 +5235,7 @@ bool simple_wallet::check_tx_proof(const std::vector<std::string> &args) success_msg_writer() << tr("Good signature"); if (received > 0) { - success_msg_writer() << get_account_address_as_str(m_wallet->testnet(), info.is_subaddress, info.address) << " " << tr("received") << " " << print_money(received) << " " << tr("in txid") << " " << txid; + success_msg_writer() << get_account_address_as_str(m_wallet->nettype(), info.is_subaddress, info.address) << " " << tr("received") << " " << print_money(received) << " " << tr("in txid") << " " << txid; if (in_pool) { success_msg_writer() << tr("WARNING: this transaction is not yet included in the blockchain!"); @@ -5210,7 +5254,7 @@ bool simple_wallet::check_tx_proof(const std::vector<std::string> &args) } else { - fail_msg_writer() << get_account_address_as_str(m_wallet->testnet(), info.is_subaddress, info.address) << " " << tr("received nothing in txid") << " " << txid; + fail_msg_writer() << get_account_address_as_str(m_wallet->nettype(), info.is_subaddress, info.address) << " " << tr("received nothing in txid") << " " << txid; } } else @@ -5385,7 +5429,7 @@ bool simple_wallet::check_reserve_proof(const std::vector<std::string> &args) } cryptonote::address_parse_info info; - if(!cryptonote::get_account_address_from_str_or_url(info, m_wallet->testnet(), args[0], oa_prompter)) + if(!cryptonote::get_account_address_from_str_or_url(info, m_wallet->nettype(), args[0], oa_prompter)) { fail_msg_writer() << tr("failed to parse address"); return true; @@ -5580,7 +5624,7 @@ bool simple_wallet::show_transfers(const std::vector<std::string> &args_) for (const auto &d: pd.m_dests) { if (!dests.empty()) dests += ", "; - dests += get_account_address_as_str(m_wallet->testnet(), d.is_subaddress, d.addr) + ": " + print_money(d.amount); + dests += get_account_address_as_str(m_wallet->nettype(), d.is_subaddress, d.addr) + ": " + print_money(d.amount); } std::string payment_id = string_tools::pod_to_hex(i->second.m_payment_id); if (payment_id.substr(16).find_first_not_of('0') == std::string::npos) @@ -6179,7 +6223,7 @@ bool simple_wallet::print_integrated_address(const std::vector<std::string> &arg } payment_id = crypto::rand<crypto::hash8>(); success_msg_writer() << tr("Random payment ID: ") << payment_id; - success_msg_writer() << tr("Matching integrated address: ") << m_wallet->get_account().get_public_integrated_address_str(payment_id, m_wallet->testnet()); + success_msg_writer() << tr("Matching integrated address: ") << m_wallet->get_account().get_public_integrated_address_str(payment_id, m_wallet->nettype()); return true; } if(tools::wallet2::parse_short_payment_id(args.back(), payment_id)) @@ -6189,21 +6233,21 @@ bool simple_wallet::print_integrated_address(const std::vector<std::string> &arg fail_msg_writer() << tr("Integrated addresses can only be created for account 0"); return true; } - success_msg_writer() << m_wallet->get_account().get_public_integrated_address_str(payment_id, m_wallet->testnet()); + success_msg_writer() << m_wallet->get_account().get_public_integrated_address_str(payment_id, m_wallet->nettype()); return true; } else { address_parse_info info; - if(get_account_address_from_str(info, m_wallet->testnet(), args.back())) + if(get_account_address_from_str(info, m_wallet->nettype(), args.back())) { if (info.has_payment_id) { success_msg_writer() << boost::format(tr("Integrated address: %s, payment ID: %s")) % - get_account_address_as_str(m_wallet->testnet(), false, info.address) % epee::string_tools::pod_to_hex(info.payment_id); + get_account_address_as_str(m_wallet->nettype(), false, info.address) % epee::string_tools::pod_to_hex(info.payment_id); } else { - success_msg_writer() << (info.is_subaddress ? tr("Subaddress: ") : tr("Standard address: ")) << get_account_address_as_str(m_wallet->testnet(), info.is_subaddress, info.address); + success_msg_writer() << (info.is_subaddress ? tr("Subaddress: ") : tr("Standard address: ")) << get_account_address_as_str(m_wallet->nettype(), info.is_subaddress, info.address); } return true; } @@ -6225,7 +6269,7 @@ bool simple_wallet::address_book(const std::vector<std::string> &args/* = std::v else if (args[0] == "add") { cryptonote::address_parse_info info; - if(!cryptonote::get_account_address_from_str_or_url(info, m_wallet->testnet(), args[1], oa_prompter)) + if(!cryptonote::get_account_address_from_str_or_url(info, m_wallet->nettype(), args[1], oa_prompter)) { fail_msg_writer() << tr("failed to parse address"); return true; @@ -6282,7 +6326,7 @@ bool simple_wallet::address_book(const std::vector<std::string> &args/* = std::v for (size_t i = 0; i < address_book.size(); ++i) { auto& row = address_book[i]; success_msg_writer() << tr("Index: ") << i; - success_msg_writer() << tr("Address: ") << get_account_address_as_str(m_wallet->testnet(), row.m_is_subaddress, row.m_address); + success_msg_writer() << tr("Address: ") << get_account_address_as_str(m_wallet->nettype(), row.m_is_subaddress, row.m_address); success_msg_writer() << tr("Payment ID: ") << row.m_payment_id; success_msg_writer() << tr("Description: ") << row.m_description << "\n"; } @@ -6408,7 +6452,7 @@ bool simple_wallet::wallet_info(const std::vector<std::string> &args) message_writer() << tr("Filename: ") << m_wallet->get_wallet_file(); message_writer() << tr("Description: ") << m_wallet->get_description(); - message_writer() << tr("Address: ") << m_wallet->get_account().get_public_address_str(m_wallet->testnet()); + message_writer() << tr("Address: ") << m_wallet->get_account().get_public_address_str(m_wallet->nettype()); std::string type; if (m_wallet->watch_only()) type = tr("Watch only"); @@ -6417,7 +6461,9 @@ bool simple_wallet::wallet_info(const std::vector<std::string> &args) else type = tr("Normal"); message_writer() << tr("Type: ") << type; - message_writer() << tr("Testnet: ") << (m_wallet->testnet() ? tr("Yes") : tr("No")); + message_writer() << tr("Network type: ") << ( + m_wallet->nettype() == cryptonote::TESTNET ? tr("Testnet") : + m_wallet->nettype() == cryptonote::STAGENET ? tr("Stagenet") : tr("Mainnet")); return true; } //---------------------------------------------------------------------------------------------------- @@ -6477,7 +6523,7 @@ bool simple_wallet::verify(const std::vector<std::string> &args) } cryptonote::address_parse_info info; - if(!cryptonote::get_account_address_from_str_or_url(info, m_wallet->testnet(), address_string, oa_prompter)) + if(!cryptonote::get_account_address_from_str_or_url(info, m_wallet->nettype(), address_string, oa_prompter)) { fail_msg_writer() << tr("failed to parse address"); return true; @@ -6780,7 +6826,7 @@ bool simple_wallet::show_transfer(const std::vector<std::string> &args) for (const auto &d: pd.m_dests) { if (!dests.empty()) dests += ", "; - dests += get_account_address_as_str(m_wallet->testnet(), d.is_subaddress, d.addr) + ": " + print_money(d.amount); + dests += get_account_address_as_str(m_wallet->nettype(), d.is_subaddress, d.addr) + ": " + print_money(d.amount); } std::string payment_id = string_tools::pod_to_hex(i->second.m_payment_id); if (payment_id.substr(16).find_first_not_of('0') == std::string::npos) @@ -6906,6 +6952,12 @@ void simple_wallet::commit_or_save(std::vector<tools::wallet2::pending_tx>& ptx_ //---------------------------------------------------------------------------------------------------- int main(int argc, char* argv[]) { +#ifdef WIN32 + // Activate UTF-8 support for Boost filesystem classes on Windows + std::locale::global(boost::locale::generator().generate("")); + boost::filesystem::path::imbue(std::locale()); +#endif + po::options_description desc_params(wallet_args::tr("Wallet options")); tools::wallet2::init_options(desc_params); command_line::add_arg(desc_params, arg_wallet_file); diff --git a/src/wallet/api/address_book.cpp b/src/wallet/api/address_book.cpp index 38c34a912..7ef011e06 100644 --- a/src/wallet/api/address_book.cpp +++ b/src/wallet/api/address_book.cpp @@ -49,7 +49,7 @@ bool AddressBookImpl::addRow(const std::string &dst_addr , const std::string &pa clearStatus(); cryptonote::address_parse_info info; - if(!cryptonote::get_account_address_from_str(info, m_wallet->m_wallet->testnet(), dst_addr)) { + if(!cryptonote::get_account_address_from_str(info, m_wallet->m_wallet->nettype(), dst_addr)) { m_errorString = tr("Invalid destination address"); m_errorCode = Invalid_Address; return false; @@ -105,13 +105,13 @@ void AddressBookImpl::refresh() tools::wallet2::address_book_row * row = &rows.at(i); std::string payment_id = (row->m_payment_id == crypto::null_hash)? "" : epee::string_tools::pod_to_hex(row->m_payment_id); - std::string address = cryptonote::get_account_address_as_str(m_wallet->m_wallet->testnet(), row->m_is_subaddress, row->m_address); + std::string address = cryptonote::get_account_address_as_str(m_wallet->m_wallet->nettype(), row->m_is_subaddress, row->m_address); // convert the zero padded short payment id to integrated address if (!row->m_is_subaddress && payment_id.length() > 16 && payment_id.substr(16).find_first_not_of('0') == std::string::npos) { payment_id = payment_id.substr(0,16); crypto::hash8 payment_id_short; if(tools::wallet2::parse_short_payment_id(payment_id, payment_id_short)) { - address = cryptonote::get_account_integrated_address_as_str(m_wallet->m_wallet->testnet(), row->m_address, payment_id_short); + address = cryptonote::get_account_integrated_address_as_str(m_wallet->m_wallet->nettype(), row->m_address, payment_id_short); // Don't show payment id when integrated address is used payment_id = ""; } diff --git a/src/wallet/api/transaction_history.cpp b/src/wallet/api/transaction_history.cpp index 95a055f8f..ba46a6904 100644 --- a/src/wallet/api/transaction_history.cpp +++ b/src/wallet/api/transaction_history.cpp @@ -181,7 +181,7 @@ void TransactionHistoryImpl::refresh() // single output transaction might contain multiple transfers for (const auto &d: pd.m_dests) { - ti->m_transfers.push_back({d.amount, get_account_address_as_str(m_wallet->m_wallet->testnet(), d.is_subaddress, d.addr)}); + ti->m_transfers.push_back({d.amount, get_account_address_as_str(m_wallet->m_wallet->nettype(), d.is_subaddress, d.addr)}); } m_history.push_back(ti); } diff --git a/src/wallet/api/unsigned_transaction.cpp b/src/wallet/api/unsigned_transaction.cpp index c6ebcb009..29910a3b6 100644 --- a/src/wallet/api/unsigned_transaction.cpp +++ b/src/wallet/api/unsigned_transaction.cpp @@ -144,10 +144,10 @@ bool UnsignedTransactionImpl::checkLoadedTx(const std::function<size_t()> get_nu for (size_t d = 0; d < cd.splitted_dsts.size(); ++d) { const cryptonote::tx_destination_entry &entry = cd.splitted_dsts[d]; - std::string address, standard_address = get_account_address_as_str(m_wallet.testnet(), entry.is_subaddress, entry.addr); + std::string address, standard_address = get_account_address_as_str(m_wallet.m_wallet->nettype(), entry.is_subaddress, entry.addr); if (has_encrypted_payment_id && !entry.is_subaddress) { - address = get_account_integrated_address_as_str(m_wallet.testnet(), entry.addr, payment_id8); + address = get_account_integrated_address_as_str(m_wallet.m_wallet->nettype(), entry.addr, payment_id8); address += std::string(" (" + standard_address + " with encrypted payment id " + epee::string_tools::pod_to_hex(payment_id8) + ")"); } else @@ -205,7 +205,7 @@ bool UnsignedTransactionImpl::checkLoadedTx(const std::function<size_t()> get_nu std::string change_string; if (change > 0) { - std::string address = get_account_address_as_str(m_wallet.m_wallet->testnet(), get_tx(0).subaddr_account > 0, get_tx(0).change_dts.addr); + std::string address = get_account_address_as_str(m_wallet.m_wallet->nettype(), get_tx(0).subaddr_account > 0, get_tx(0).change_dts.addr); change_string += (boost::format(tr("%s change to %s")) % cryptonote::print_money(change) % address).str(); } else @@ -297,7 +297,7 @@ std::vector<std::string> UnsignedTransactionImpl::recipientAddress() const MERROR("empty destinations, skipped"); continue; } - result.push_back(cryptonote::get_account_address_as_str(m_wallet.m_wallet->testnet(), utx.dests[0].is_subaddress, utx.dests[0].addr)); + result.push_back(cryptonote::get_account_address_as_str(m_wallet.m_wallet->nettype(), utx.dests[0].is_subaddress, utx.dests[0].addr)); } return result; } diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index 5ce8ede8d..ff0d2fdbd 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -40,10 +40,16 @@ #include "common/util.h" #include "mnemonics/electrum-words.h" +#include "mnemonics/english.h" #include <boost/format.hpp> #include <sstream> #include <unordered_map> +#ifdef WIN32 +#include <boost/locale.hpp> +#include <boost/filesystem.hpp> +#endif + using namespace std; using namespace cryptonote; @@ -233,16 +239,16 @@ bool Wallet::paymentIdValid(const string &paiment_id) return false; } -bool Wallet::addressValid(const std::string &str, bool testnet) +bool Wallet::addressValid(const std::string &str, NetworkType nettype) { cryptonote::address_parse_info info; - return get_account_address_from_str(info, testnet, str); + return get_account_address_from_str(info, static_cast<cryptonote::network_type>(nettype), str); } -bool Wallet::keyValid(const std::string &secret_key_string, const std::string &address_string, bool isViewKey, bool testnet, std::string &error) +bool Wallet::keyValid(const std::string &secret_key_string, const std::string &address_string, bool isViewKey, NetworkType nettype, std::string &error) { cryptonote::address_parse_info info; - if(!get_account_address_from_str(info, testnet, address_string)) { + if(!get_account_address_from_str(info, static_cast<cryptonote::network_type>(nettype), address_string)) { error = tr("Failed to parse address"); return false; } @@ -275,10 +281,10 @@ bool Wallet::keyValid(const std::string &secret_key_string, const std::string &a return true; } -std::string Wallet::paymentIdFromAddress(const std::string &str, bool testnet) +std::string Wallet::paymentIdFromAddress(const std::string &str, NetworkType nettype) { cryptonote::address_parse_info info; - if (!get_account_address_from_str(info, testnet, str)) + if (!get_account_address_from_str(info, static_cast<cryptonote::network_type>(nettype), str)) return ""; if (!info.has_payment_id) return ""; @@ -291,6 +297,11 @@ uint64_t Wallet::maximumAllowedAmount() } void Wallet::init(const char *argv0, const char *default_log_base_name) { +#ifdef WIN32 + // Activate UTF-8 support for Boost filesystem classes on Windows + std::locale::global(boost::locale::generator().generate("")); + boost::filesystem::path::imbue(std::locale()); +#endif epee::string_tools::set_module_name_and_folder(argv0); mlog_configure(mlog_get_default_log_path(default_log_base_name), true); } @@ -300,7 +311,7 @@ void Wallet::debug(const std::string &str) { } ///////////////////////// WalletImpl implementation //////////////////////// -WalletImpl::WalletImpl(bool testnet) +WalletImpl::WalletImpl(NetworkType nettype) :m_wallet(nullptr) , m_status(Wallet::Status_Ok) , m_trustedDaemon(false) @@ -310,7 +321,7 @@ WalletImpl::WalletImpl(bool testnet) , m_rebuildWalletCache(false) , m_is_connected(false) { - m_wallet = new tools::wallet2(testnet); + m_wallet = new tools::wallet2(static_cast<cryptonote::network_type>(nettype)); m_history = new TransactionHistoryImpl(this); m_wallet2Callback = new Wallet2CallbackImpl(this); m_wallet->callback(m_wallet2Callback); @@ -388,7 +399,7 @@ bool WalletImpl::create(const std::string &path, const std::string &password, co bool WalletImpl::createWatchOnly(const std::string &path, const std::string &password, const std::string &language) const { clearStatus(); - std::unique_ptr<tools::wallet2> view_wallet(new tools::wallet2(m_wallet->testnet())); + std::unique_ptr<tools::wallet2> view_wallet(new tools::wallet2(m_wallet->nettype())); // Store same refresh height as original wallet view_wallet->set_refresh_from_block_height(m_wallet->get_refresh_from_block_height()); @@ -469,7 +480,7 @@ bool WalletImpl::recoverFromKeysWithPassword(const std::string &path, const std::string &spendkey_string) { cryptonote::address_parse_info info; - if(!get_account_address_from_str(info, m_wallet->testnet(), address_string)) + if(!get_account_address_from_str(info, m_wallet->nettype(), address_string)) { m_errorString = tr("failed to parse address"); m_status = Status_Error; @@ -603,6 +614,9 @@ bool WalletImpl::recover(const std::string &path, const std::string &password, c return false; } + if (old_language == crypto::ElectrumWords::old_language_name) + old_language = Language::English().get_language_name(); + try { m_wallet->set_seed_language(old_language); m_wallet->generate(path, password, recovery_key, true, false); @@ -1079,7 +1093,7 @@ PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, const PendingTransactionImpl * transaction = new PendingTransactionImpl(*this); do { - if(!cryptonote::get_account_address_from_str(info, m_wallet->testnet(), dst_addr)) { + if(!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), dst_addr)) { // TODO: copy-paste 'if treating as an address fails, try as url' from simplewallet.cpp:1982 m_status = Status_Error; m_errorString = "Invalid destination address"; @@ -1464,7 +1478,7 @@ bool WalletImpl::checkTxKey(const std::string &txid_str, std::string tx_key_str, } cryptonote::address_parse_info info; - if (!cryptonote::get_account_address_from_str(info, m_wallet->testnet(), address_str)) + if (!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), address_str)) { m_status = Status_Error; m_errorString = tr("Failed to parse address"); @@ -1496,7 +1510,7 @@ std::string WalletImpl::getTxProof(const std::string &txid_str, const std::strin } cryptonote::address_parse_info info; - if (!cryptonote::get_account_address_from_str(info, m_wallet->testnet(), address_str)) + if (!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), address_str)) { m_status = Status_Error; m_errorString = tr("Failed to parse address"); @@ -1527,7 +1541,7 @@ bool WalletImpl::checkTxProof(const std::string &txid_str, const std::string &ad } cryptonote::address_parse_info info; - if (!cryptonote::get_account_address_from_str(info, m_wallet->testnet(), address_str)) + if (!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), address_str)) { m_status = Status_Error; m_errorString = tr("Failed to parse address"); @@ -1615,7 +1629,7 @@ std::string WalletImpl::getReserveProof(bool all, uint32_t account_index, uint64 bool WalletImpl::checkReserveProof(const std::string &address, const std::string &message, const std::string &signature, bool &good, uint64_t &total, uint64_t &spent) const { cryptonote::address_parse_info info; - if (!cryptonote::get_account_address_from_str(info, m_wallet->testnet(), address)) + if (!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), address)) { m_status = Status_Error; m_errorString = tr("Failed to parse address"); @@ -1652,7 +1666,7 @@ bool WalletImpl::verifySignedMessage(const std::string &message, const std::stri { cryptonote::address_parse_info info; - if (!cryptonote::get_account_address_from_str(info, m_wallet->testnet(), address)) + if (!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), address)) return false; return m_wallet->verify(message, info.address, signature); @@ -1746,7 +1760,7 @@ void WalletImpl::doRefresh() m_synchronized = true; } // assuming if we have empty history, it wasn't initialized yet - // for futher history changes client need to update history in + // for further history changes client need to update history in // "on_money_received" and "on_money_sent" callbacks if (m_history->count() == 0) { m_history->refresh(); diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h index fcd53c3f8..9b4a0cc12 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.h @@ -52,7 +52,7 @@ struct Wallet2CallbackImpl; class WalletImpl : public Wallet { public: - WalletImpl(bool testnet = false); + WalletImpl(NetworkType nettype = MAINNET); ~WalletImpl(); bool create(const std::string &path, const std::string &password, const std::string &language); @@ -115,7 +115,7 @@ public: void setRecoveringFromSeed(bool recoveringFromSeed); bool watchOnly() const; bool rescanSpent(); - bool testnet() const {return m_wallet->testnet();} + NetworkType nettype() const {return static_cast<NetworkType>(m_wallet->nettype());} void hardForkInfo(uint8_t &version, uint64_t &earliest_height) const; bool useForkRules(uint8_t version, int64_t early_blocks) const; diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h index a22788399..a6320545e 100644 --- a/src/wallet/api/wallet2_api.h +++ b/src/wallet/api/wallet2_api.h @@ -40,6 +40,12 @@ // Public interface for libwallet library namespace Monero { +enum NetworkType : uint8_t { + MAINNET = 0, + TESTNET, + STAGENET +}; + namespace Utils { bool isAddressLocal(const std::string &hostaddr); void onStartup(); @@ -358,7 +364,10 @@ struct Wallet virtual std::string address(uint32_t accountIndex = 0, uint32_t addressIndex = 0) const = 0; std::string mainAddress() const { return address(0, 0); } virtual std::string path() const = 0; - virtual bool testnet() const = 0; + virtual NetworkType nettype() const = 0; + bool mainnet() const { return nettype() == MAINNET; } + bool testnet() const { return nettype() == TESTNET; } + bool stagenet() const { return nettype() == STAGENET; } //! returns current hard fork info virtual void hardForkInfo(uint8_t &version, uint64_t &earliest_height) const = 0; //! check if hard fork rules should be used @@ -529,9 +538,21 @@ struct Wallet static uint64_t amountFromDouble(double amount); static std::string genPaymentId(); static bool paymentIdValid(const std::string &paiment_id); - static bool addressValid(const std::string &str, bool testnet); - static bool keyValid(const std::string &secret_key_string, const std::string &address_string, bool isViewKey, bool testnet, std::string &error); - static std::string paymentIdFromAddress(const std::string &str, bool testnet); + static bool addressValid(const std::string &str, NetworkType nettype); + static bool addressValid(const std::string &str, bool testnet) // deprecated + { + return addressValid(str, testnet ? MAINNET : TESTNET); + } + static bool keyValid(const std::string &secret_key_string, const std::string &address_string, bool isViewKey, NetworkType nettype, std::string &error); + static bool keyValid(const std::string &secret_key_string, const std::string &address_string, bool isViewKey, bool testnet, std::string &error) // deprecated + { + return keyValid(secret_key_string, address_string, isViewKey, testnet ? TESTNET : MAINNET, error); + } + static std::string paymentIdFromAddress(const std::string &str, NetworkType nettype); + static std::string paymentIdFromAddress(const std::string &str, bool testnet) // deprecated + { + return paymentIdFromAddress(str, testnet ? TESTNET : MAINNET); + } static uint64_t maximumAllowedAmount(); // Easylogger wrapper static void init(const char *argv0, const char *default_log_base_name); @@ -685,7 +706,7 @@ struct Wallet * \brief setUserNote - attach an arbitrary string note to a txid * \param txid - the transaction id to attach the note to * \param note - the note - * \return true if succesful, false otherwise + * \return true if successful, false otherwise */ virtual bool setUserNote(const std::string &txid, const std::string ¬e) = 0; /*! @@ -750,47 +771,66 @@ struct WalletManager * \param path Name of wallet file * \param password Password of wallet file * \param language Language to be used to generate electrum seed mnemonic + * \param nettype Network type * \return Wallet instance (Wallet::status() needs to be called to check if created successfully) */ - virtual Wallet * createWallet(const std::string &path, const std::string &password, const std::string &language, bool testnet = false) = 0; + virtual Wallet * createWallet(const std::string &path, const std::string &password, const std::string &language, NetworkType nettype = MAINNET) = 0; + Wallet * createWallet(const std::string &path, const std::string &password, const std::string &language, bool testnet = false) // deprecated + { + return createWallet(path, password, language, testnet ? TESTNET : MAINNET); + } /*! * \brief Opens existing wallet * \param path Name of wallet file * \param password Password of wallet file + * \param nettype Network type * \return Wallet instance (Wallet::status() needs to be called to check if opened successfully) */ - virtual Wallet * openWallet(const std::string &path, const std::string &password, bool testnet = false) = 0; + virtual Wallet * openWallet(const std::string &path, const std::string &password, NetworkType nettype = MAINNET) = 0; + Wallet * openWallet(const std::string &path, const std::string &password, bool testnet = false) // deprecated + { + return openWallet(path, password, testnet ? TESTNET : MAINNET); + } /*! * \brief recovers existing wallet using mnemonic (electrum seed) * \param path Name of wallet file to be created * \param password Password of wallet file * \param mnemonic mnemonic (25 words electrum seed) - * \param testnet testnet + * \param nettype Network type * \param restoreHeight restore from start height * \return Wallet instance (Wallet::status() needs to be called to check if recovered successfully) */ virtual Wallet * recoveryWallet(const std::string &path, const std::string &password, const std::string &mnemonic, - bool testnet = false, uint64_t restoreHeight = 0) = 0; + NetworkType nettype = MAINNET, uint64_t restoreHeight = 0) = 0; + Wallet * recoveryWallet(const std::string &path, const std::string &password, const std::string &mnemonic, + bool testnet = false, uint64_t restoreHeight = 0) // deprecated + { + return recoveryWallet(path, password, mnemonic, testnet ? TESTNET : MAINNET, restoreHeight); + } /*! * \deprecated this method creates a wallet WITHOUT a passphrase, use the alternate recoverWallet() method * \brief recovers existing wallet using mnemonic (electrum seed) * \param path Name of wallet file to be created * \param mnemonic mnemonic (25 words electrum seed) - * \param testnet testnet + * \param nettype Network type * \param restoreHeight restore from start height * \return Wallet instance (Wallet::status() needs to be called to check if recovered successfully) */ - virtual Wallet * recoveryWallet(const std::string &path, const std::string &mnemonic, bool testnet = false, uint64_t restoreHeight = 0) = 0; + virtual Wallet * recoveryWallet(const std::string &path, const std::string &mnemonic, NetworkType nettype = MAINNET, uint64_t restoreHeight = 0) = 0; + Wallet * recoveryWallet(const std::string &path, const std::string &mnemonic, bool testnet = false, uint64_t restoreHeight = 0) // deprecated + { + return recoveryWallet(path, mnemonic, testnet ? TESTNET : MAINNET, restoreHeight); + } /*! * \brief recovers existing wallet using keys. Creates a view only wallet if spend key is omitted * \param path Name of wallet file to be created * \param password Password of wallet file * \param language language - * \param testnet testnet + * \param nettype Network type * \param restoreHeight restore from start height * \param addressString public address * \param viewKeyString view key @@ -800,18 +840,29 @@ struct WalletManager virtual Wallet * createWalletFromKeys(const std::string &path, const std::string &password, const std::string &language, - bool testnet, + NetworkType nettype, uint64_t restoreHeight, const std::string &addressString, const std::string &viewKeyString, const std::string &spendKeyString = "") = 0; + Wallet * createWalletFromKeys(const std::string &path, + const std::string &password, + const std::string &language, + bool testnet, + uint64_t restoreHeight, + const std::string &addressString, + const std::string &viewKeyString, + const std::string &spendKeyString = "") // deprecated + { + return createWalletFromKeys(path, password, language, testnet ? TESTNET : MAINNET, restoreHeight, addressString, viewKeyString, spendKeyString); + } /*! * \deprecated this method creates a wallet WITHOUT a passphrase, use createWalletFromKeys(..., password, ...) instead * \brief recovers existing wallet using keys. Creates a view only wallet if spend key is omitted * \param path Name of wallet file to be created * \param language language - * \param testnet testnet + * \param nettype Network type * \param restoreHeight restore from start height * \param addressString public address * \param viewKeyString view key @@ -820,14 +871,24 @@ struct WalletManager */ virtual Wallet * createWalletFromKeys(const std::string &path, const std::string &language, - bool testnet, + NetworkType nettype, uint64_t restoreHeight, const std::string &addressString, const std::string &viewKeyString, const std::string &spendKeyString = "") = 0; + Wallet * createWalletFromKeys(const std::string &path, + const std::string &language, + bool testnet, + uint64_t restoreHeight, + const std::string &addressString, + const std::string &viewKeyString, + const std::string &spendKeyString = "") // deprecated + { + return createWalletFromKeys(path, language, testnet ? TESTNET : MAINNET, restoreHeight, addressString, viewKeyString, spendKeyString); + } /*! - * \brief Closes wallet. In case operation succeded, wallet object deleted. in case operation failed, wallet object not deleted + * \brief Closes wallet. In case operation succeeded, wallet object deleted. in case operation failed, wallet object not deleted * \param wallet previously opened / created wallet instance * \return None */ diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp index b3d3150d4..b03332f40 100644 --- a/src/wallet/api/wallet_manager.cpp +++ b/src/wallet/api/wallet_manager.cpp @@ -60,46 +60,46 @@ namespace { namespace Monero { Wallet *WalletManagerImpl::createWallet(const std::string &path, const std::string &password, - const std::string &language, bool testnet) + const std::string &language, NetworkType nettype) { - WalletImpl * wallet = new WalletImpl(testnet); + WalletImpl * wallet = new WalletImpl(nettype); wallet->create(path, password, language); return wallet; } -Wallet *WalletManagerImpl::openWallet(const std::string &path, const std::string &password, bool testnet) +Wallet *WalletManagerImpl::openWallet(const std::string &path, const std::string &password, NetworkType nettype) { - WalletImpl * wallet = new WalletImpl(testnet); + WalletImpl * wallet = new WalletImpl(nettype); wallet->open(path, password); //Refresh addressBook wallet->addressBook()->refresh(); return wallet; } -Wallet *WalletManagerImpl::recoveryWallet(const std::string &path, const std::string &mnemonic, bool testnet, uint64_t restoreHeight) +Wallet *WalletManagerImpl::recoveryWallet(const std::string &path, const std::string &mnemonic, NetworkType nettype, uint64_t restoreHeight) { - return recoveryWallet(path, "", mnemonic, testnet, restoreHeight); + return recoveryWallet(path, "", mnemonic, nettype, restoreHeight); } Wallet *WalletManagerImpl::createWalletFromKeys(const std::string &path, const std::string &language, - bool testnet, + NetworkType nettype, uint64_t restoreHeight, const std::string &addressString, const std::string &viewKeyString, const std::string &spendKeyString) { - return createWalletFromKeys(path, "", language, testnet, restoreHeight, + return createWalletFromKeys(path, "", language, nettype, restoreHeight, addressString, viewKeyString, spendKeyString); } Wallet *WalletManagerImpl::recoveryWallet(const std::string &path, const std::string &password, const std::string &mnemonic, - bool testnet, + NetworkType nettype, uint64_t restoreHeight) { - WalletImpl * wallet = new WalletImpl(testnet); + WalletImpl * wallet = new WalletImpl(nettype); if(restoreHeight > 0){ wallet->setRefreshFromBlockHeight(restoreHeight); } @@ -110,13 +110,13 @@ Wallet *WalletManagerImpl::recoveryWallet(const std::string &path, Wallet *WalletManagerImpl::createWalletFromKeys(const std::string &path, const std::string &password, const std::string &language, - bool testnet, + NetworkType nettype, uint64_t restoreHeight, const std::string &addressString, const std::string &viewKeyString, const std::string &spendKeyString) { - WalletImpl * wallet = new WalletImpl(testnet); + WalletImpl * wallet = new WalletImpl(nettype); if(restoreHeight > 0){ wallet->setRefreshFromBlockHeight(restoreHeight); } diff --git a/src/wallet/api/wallet_manager.h b/src/wallet/api/wallet_manager.h index 6a4d9de2e..409a6d499 100644 --- a/src/wallet/api/wallet_manager.h +++ b/src/wallet/api/wallet_manager.h @@ -38,27 +38,27 @@ class WalletManagerImpl : public WalletManager { public: Wallet * createWallet(const std::string &path, const std::string &password, - const std::string &language, bool testnet); - Wallet * openWallet(const std::string &path, const std::string &password, bool testnet); + const std::string &language, NetworkType nettype); + Wallet * openWallet(const std::string &path, const std::string &password, NetworkType nettype); virtual Wallet * recoveryWallet(const std::string &path, const std::string &password, const std::string &mnemonic, - bool testnet, + NetworkType nettype, uint64_t restoreHeight); virtual Wallet * createWalletFromKeys(const std::string &path, const std::string &password, const std::string &language, - bool testnet, + NetworkType nettype, uint64_t restoreHeight, const std::string &addressString, const std::string &viewKeyString, const std::string &spendKeyString = ""); // next two methods are deprecated - use the above version which allow setting of a password - virtual Wallet * recoveryWallet(const std::string &path, const std::string &mnemonic, bool testnet, uint64_t restoreHeight); + virtual Wallet * recoveryWallet(const std::string &path, const std::string &mnemonic, NetworkType nettype, uint64_t restoreHeight); // deprecated: use createWalletFromKeys(..., password, ...) instead virtual Wallet * createWalletFromKeys(const std::string &path, const std::string &language, - bool testnet, + NetworkType nettype, uint64_t restoreHeight, const std::string &addressString, const std::string &viewKeyString, diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index d8837eccf..4a6c6fad2 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -118,6 +118,7 @@ struct options { const command_line::arg_descriptor<int> daemon_port = {"daemon-port", tools::wallet2::tr("Use daemon instance at port <arg> instead of 18081"), 0}; const command_line::arg_descriptor<std::string> daemon_login = {"daemon-login", tools::wallet2::tr("Specify username[:password] for daemon RPC client"), "", true}; const command_line::arg_descriptor<bool> testnet = {"testnet", tools::wallet2::tr("For testnet. Daemon must also be launched with --testnet flag"), false}; + const command_line::arg_descriptor<bool> stagenet = {"stagenet", tools::wallet2::tr("For stagenet. Daemon must also be launched with --stagenet flag"), false}; const command_line::arg_descriptor<bool> restricted = {"restricted-rpc", tools::wallet2::tr("Restricts to view-only commands"), false}; }; @@ -159,6 +160,7 @@ std::string get_size_string(const cryptonote::blobdata &tx) std::unique_ptr<tools::wallet2> make_basic(const boost::program_options::variables_map& vm, const options& opts, const std::function<boost::optional<tools::password_container>(const char *, bool)> &password_prompter) { const bool testnet = command_line::get_arg(vm, opts.testnet); + const bool stagenet = command_line::get_arg(vm, opts.stagenet); const bool restricted = command_line::get_arg(vm, opts.restricted); auto daemon_address = command_line::get_arg(vm, opts.daemon_address); @@ -187,13 +189,13 @@ std::unique_ptr<tools::wallet2> make_basic(const boost::program_options::variabl if (!daemon_port) { - daemon_port = testnet ? config::testnet::RPC_DEFAULT_PORT : config::RPC_DEFAULT_PORT; + daemon_port = testnet ? config::testnet::RPC_DEFAULT_PORT : stagenet ? config::stagenet::RPC_DEFAULT_PORT : config::RPC_DEFAULT_PORT; } if (daemon_address.empty()) daemon_address = std::string("http://") + daemon_host + ":" + std::to_string(daemon_port); - std::unique_ptr<tools::wallet2> wallet(new tools::wallet2(testnet, restricted)); + std::unique_ptr<tools::wallet2> wallet(new tools::wallet2(testnet ? TESTNET : stagenet ? STAGENET : MAINNET, restricted)); wallet->init(std::move(daemon_address), std::move(login)); return wallet; } @@ -230,6 +232,8 @@ boost::optional<tools::password_container> get_password(const boost::program_opt std::unique_ptr<tools::wallet2> generate_from_json(const std::string& json_file, const boost::program_options::variables_map& vm, const options& opts, const std::function<boost::optional<tools::password_container>(const char *, bool)> &password_prompter) { const bool testnet = command_line::get_arg(vm, opts.testnet); + const bool stagenet = command_line::get_arg(vm, opts.stagenet); + const network_type nettype = testnet ? TESTNET : stagenet ? STAGENET : MAINNET; /* GET_FIELD_FROM_JSON_RETURN_ON_ERROR Is a generic macro that can return false. Gcc will coerce this into unique_ptr(nullptr), but clang correctly @@ -329,7 +333,7 @@ std::unique_ptr<tools::wallet2> generate_from_json(const std::string& json_file, if (field_address_found) { cryptonote::address_parse_info info; - if(!get_account_address_from_str(info, testnet, field_address)) + if(!get_account_address_from_str(info, nettype, field_address)) { THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("invalid address")); } @@ -383,12 +387,12 @@ std::unique_ptr<tools::wallet2> generate_from_json(const std::string& json_file, if (field_spendkey.empty()) { - // if we have an addres but no spend key, we can deduce the spend public key + // if we have an address but no spend key, we can deduce the spend public key // from the address if (field_address_found) { cryptonote::address_parse_info info; - if(!get_account_address_from_str(info, testnet, field_address)) + if(!get_account_address_from_str(info, nettype, field_address)) { THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, std::string(tools::wallet2::tr("failed to parse address: ")) + field_address); } @@ -589,12 +593,12 @@ const size_t MAX_SPLIT_ATTEMPTS = 30; constexpr const std::chrono::seconds wallet2::rpc_timeout; const char* wallet2::tr(const char* str) { return i18n_translate(str, "tools::wallet2"); } -wallet2::wallet2(bool testnet, bool restricted): +wallet2::wallet2(network_type nettype, bool restricted): m_multisig_rescan_info(NULL), m_multisig_rescan_k(NULL), m_run(true), m_callback(0), - m_testnet(testnet), + m_nettype(nettype), m_always_confirm_transfers(true), m_print_ring_members(false), m_store_tx_info(true), @@ -634,6 +638,11 @@ bool wallet2::has_testnet_option(const boost::program_options::variables_map& vm return command_line::get_arg(vm, options().testnet); } +bool wallet2::has_stagenet_option(const boost::program_options::variables_map& vm) +{ + return command_line::get_arg(vm, options().stagenet); +} + void wallet2::init_options(boost::program_options::options_description& desc_params) { const options opts{}; @@ -644,6 +653,7 @@ void wallet2::init_options(boost::program_options::options_description& desc_par command_line::add_arg(desc_params, opts.daemon_port); command_line::add_arg(desc_params, opts.daemon_login); command_line::add_arg(desc_params, opts.testnet); + command_line::add_arg(desc_params, opts.stagenet); command_line::add_arg(desc_params, opts.restricted); } @@ -690,7 +700,7 @@ std::unique_ptr<wallet2> wallet2::make_dummy(const boost::program_options::varia //---------------------------------------------------------------------------------------------------- bool wallet2::init(std::string daemon_address, boost::optional<epee::net_utils::http::login> daemon_login, uint64_t upper_transaction_size_limit, bool ssl) { - m_checkpoints.init_default_checkpoints(m_testnet); + m_checkpoints.init_default_checkpoints(m_nettype); if(m_http_client.is_connected()) m_http_client.disconnect(); m_is_initialized = true; @@ -836,12 +846,12 @@ crypto::public_key wallet2::get_subaddress_spend_public_key(const cryptonote::su std::string wallet2::get_subaddress_as_str(const cryptonote::subaddress_index& index) const { cryptonote::account_public_address address = get_subaddress(index); - return cryptonote::get_account_address_as_str(m_testnet, !index.is_zero(), address); + return cryptonote::get_account_address_as_str(m_nettype, !index.is_zero(), address); } //---------------------------------------------------------------------------------------------------- std::string wallet2::get_integrated_address_as_str(const crypto::hash8& payment_id) const { - return cryptonote::get_account_integrated_address_as_str(m_testnet, get_address(), payment_id); + return cryptonote::get_account_integrated_address_as_str(m_nettype, get_address(), payment_id); } //---------------------------------------------------------------------------------------------------- void wallet2::add_subaddress_account(const std::string& label) @@ -2441,8 +2451,8 @@ bool wallet2::store_keys(const std::string& keys_file_name, const epee::wipeable value2.SetInt(m_auto_low_priority ? 1 : 0); json.AddMember("auto_low_priority", value2, json.GetAllocator()); - value2.SetInt(m_testnet ? 1 :0); - json.AddMember("testnet", value2, json.GetAllocator()); + value2.SetUint(m_nettype); + json.AddMember("nettype", value2, json.GetAllocator()); // Serialize the JSON object rapidjson::StringBuffer buffer; @@ -2624,11 +2634,12 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_ m_confirm_export_overwrite = field_confirm_export_overwrite; GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, auto_low_priority, int, Int, false, true); m_auto_low_priority = field_auto_low_priority; - GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, testnet, int, Int, false, m_testnet); - // Wallet is being opened with testnet flag, but is saved as a mainnet wallet - THROW_WALLET_EXCEPTION_IF(m_testnet && !field_testnet, error::wallet_internal_error, "Mainnet wallet can not be opened as testnet wallet"); - // Wallet is being opened without testnet flag but is saved as a testnet wallet. - THROW_WALLET_EXCEPTION_IF(!m_testnet && field_testnet, error::wallet_internal_error, "Testnet wallet can not be opened as mainnet wallet"); + GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, nettype, uint8_t, Uint, false, static_cast<uint8_t>(m_nettype)); + // The network type given in the program argument is inconsistent with the network type saved in the wallet + THROW_WALLET_EXCEPTION_IF(static_cast<uint8_t>(m_nettype) != field_nettype, error::wallet_internal_error, + (boost::format("%s wallet can not be opened as %s wallet") + % (field_nettype == 0 ? "Mainnet" : field_nettype == 1 ? "Testnet" : "Stagenet") + % (m_nettype == MAINNET ? "mainnet" : m_nettype == TESTNET ? "testnet" : "stagenet")).str()); } else { @@ -2801,7 +2812,7 @@ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string& bool r = store_keys(m_keys_file, password, false); THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file); - r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_testnet)); + r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype)); if(!r) MERROR("String with address text not saved"); } @@ -2845,16 +2856,9 @@ crypto::secret_key wallet2::generate(const std::string& wallet_, const epee::wip m_multisig_signers.clear(); m_key_on_device = false; - // -1 month for fluctuations in block time and machine date/time setup. - // avg seconds per block - const int seconds_per_block = DIFFICULTY_TARGET_V2; - // ~num blocks per month - const uint64_t blocks_per_month = 60*60*24*30/seconds_per_block; - - // try asking the daemon first + // calculate a starting refresh height if(m_refresh_from_block_height == 0 && !recover){ - uint64_t height = estimate_blockchain_height(); - m_refresh_from_block_height = height >= blocks_per_month ? height - blocks_per_month : 0; + m_refresh_from_block_height = estimate_blockchain_height(); } if (!wallet_.empty()) @@ -2862,7 +2866,7 @@ crypto::secret_key wallet2::generate(const std::string& wallet_, const epee::wip bool r = store_keys(m_keys_file, password, false); THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file); - r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_testnet)); + r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype)); if(!r) MERROR("String with address text not saved"); } @@ -2889,20 +2893,30 @@ crypto::secret_key wallet2::generate(const std::string& wallet_, const epee::wip std::string err; uint64_t height = 0; - // we get the max of approximated height and known height + // we get the max of approximated height and local height. // approximated height is the least of daemon target height // (the max of what the other daemons are claiming is their // height) and the theoretical height based on the local // clock. This will be wrong only if both the local clock // is bad *and* a peer daemon claims a highest height than // the real chain. - // known height is the height the local daemon is currently + // local height is the height the local daemon is currently // synced to, it will be lower than the real chain height if // the daemon is currently syncing. + // If we use the approximate height we subtract one month as + // a safety margin. height = get_approximate_blockchain_height(); uint64_t target_height = get_daemon_blockchain_target_height(err); - if (err.empty() && target_height < height) - height = target_height; + if (err.empty()) { + if (target_height < height) + height = target_height; + } else { + // if we couldn't talk to the daemon, check safety margin. + if (height > blocks_per_month) + height -= blocks_per_month; + else + height = 0; + } uint64_t local_height = get_daemon_blockchain_height(err); if (err.empty() && local_height > height) height = local_height; @@ -2942,7 +2956,7 @@ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string& bool r = store_keys(m_keys_file, password, true); THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file); - r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_testnet)); + r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype)); if(!r) MERROR("String with address text not saved"); } @@ -2989,7 +3003,7 @@ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string& bool r = store_keys(m_keys_file, password, false); THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file); - r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_testnet)); + r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype)); if(!r) MERROR("String with address text not saved"); } @@ -3030,7 +3044,7 @@ void wallet2::restore(const std::string& wallet_, const epee::wipeable_string& p bool r = store_keys(m_keys_file, password, false); THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file); - r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_testnet)); + r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype)); if(!r) MERROR("String with address text not saved"); } cryptonote::block b; @@ -3122,7 +3136,7 @@ std::string wallet2::make_multisig(const epee::wipeable_string &password, bool r = store_keys(m_keys_file, password, false); THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file); - r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_testnet)); + r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype)); if(!r) MERROR("String with address text not saved"); } @@ -3222,7 +3236,7 @@ bool wallet2::finalize_multisig(const epee::wipeable_string &password, std::unor bool r = store_keys(m_keys_file, password, false); THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file); - r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_testnet)); + r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype)); if(!r) MERROR("String with address text not saved"); } @@ -3532,7 +3546,7 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass { THROW_WALLET_EXCEPTION_IF(true, error::file_read_error, m_keys_file); } - LOG_PRINT_L0("Loaded wallet keys file, with public address: " << m_account.get_public_address_str(m_testnet)); + LOG_PRINT_L0("Loaded wallet keys file, with public address: " << m_account.get_public_address_str(m_nettype)); //keys loaded ok! //try to load wallet file. but even if we failed, it is not big problem @@ -3671,7 +3685,7 @@ void wallet2::trim_hashchain() } //---------------------------------------------------------------------------------------------------- void wallet2::check_genesis(const crypto::hash& genesis_hash) const { - std::string what("Genesis block mismatch. You probably use wallet without testnet flag with blockchain from test network or vice versa"); + std::string what("Genesis block mismatch. You probably use wallet without testnet (or stagenet) flag with blockchain from test (or stage) network or vice versa"); THROW_WALLET_EXCEPTION_IF(genesis_hash != m_blockchain.genesis(), error::wallet_internal_error, what); } @@ -3748,7 +3762,7 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file); // save address to the new file const std::string address_file = m_wallet_file + ".address.txt"; - r = file_io_utils::save_string_to_file(address_file, m_account.get_public_address_str(m_testnet)); + r = file_io_utils::save_string_to_file(address_file, m_account.get_public_address_str(m_nettype)); THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_wallet_file); // remove old wallet file r = boost::filesystem::remove(old_file); @@ -3767,12 +3781,24 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas } } else { // save to new file +#ifdef WIN32 + // On Windows avoid using std::ofstream which does not work with UTF-8 filenames + // The price to pay is temporary higher memory consumption for string stream + binary archive + std::ostringstream oss; + binary_archive<true> oar(oss); + bool success = ::serialization::serialize(oar, cache_file_data); + if (success) { + success = epee::file_io_utils::save_string_to_file(new_file, oss.str()); + } + THROW_WALLET_EXCEPTION_IF(!success, error::file_save_error, new_file); +#else std::ofstream ostr; ostr.open(new_file, std::ios_base::binary | std::ios_base::out | std::ios_base::trunc); binary_archive<true> oar(ostr); bool success = ::serialization::serialize(oar, cache_file_data); ostr.close(); THROW_WALLET_EXCEPTION_IF(!success || !ostr.good(), error::file_save_error, new_file); +#endif // here we have "*.new" file, we need to rename it to be without ".new" std::error_code e = tools::replace_file(new_file, m_wallet_file); @@ -4025,7 +4051,7 @@ bool wallet2::is_tx_spendtime_unlocked(uint64_t unlock_time, uint64_t block_heig uint64_t current_time = static_cast<uint64_t>(time(NULL)); // XXX: this needs to be fast, so we'd need to get the starting heights // from the daemon to be correct once voting kicks in - uint64_t v2height = m_testnet ? 624634 : 1009827; + uint64_t v2height = m_nettype == TESTNET ? 624634 : m_nettype == STAGENET ? (uint64_t)-1/*TODO*/ : 1009827; uint64_t leeway = block_height < v2height ? CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS_V1 : CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS_V2; if(current_time + leeway >= unlock_time) return true; @@ -4313,7 +4339,7 @@ void wallet2::commit_tx(pending_tx& ptx) { cryptonote::COMMAND_RPC_SUBMIT_RAW_TX::request oreq; cryptonote::COMMAND_RPC_SUBMIT_RAW_TX::response ores; - oreq.address = get_account().get_public_address_str(m_testnet); + oreq.address = get_account().get_public_address_str(m_nettype); oreq.view_key = string_tools::pod_to_hex(get_account().get_keys().m_view_secret_key); oreq.tx = epee::string_tools::buff_to_hex_nodelimer(tx_to_blob(ptx.tx)); m_daemon_rpc_mutex.lock(); @@ -4523,7 +4549,7 @@ bool wallet2::sign_tx(unsigned_tx_set &exported_txs, const std::string &signed_f std::vector<crypto::secret_key> additional_tx_keys; rct::multisig_out msout; bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), m_subaddresses, sd.sources, sd.splitted_dsts, sd.change_dts.addr, sd.extra, ptx.tx, sd.unlock_time, tx_key, additional_tx_keys, sd.use_rct, bulletproof, m_multisig ? &msout : NULL); - THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sd.sources, sd.splitted_dsts, sd.unlock_time, m_testnet); + THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sd.sources, sd.splitted_dsts, sd.unlock_time, m_nettype); // we don't test tx size, because we don't know the current limit, due to not having a blockchain, // and it's a bit pointless to fail there anyway, since it'd be a (good) guess only. We sign anyway, // and if we really go over limit, the daemon will reject when it gets submitted. Chances are it's @@ -4896,7 +4922,7 @@ bool wallet2::sign_multisig_tx(multisig_tx_set &exported_txs, std::vector<crypto auto sources = sd.sources; const bool bulletproof = sd.use_rct && (ptx.tx.rct_signatures.type == rct::RCTTypeFullBulletproof || ptx.tx.rct_signatures.type == rct::RCTTypeSimpleBulletproof); bool r = cryptonote::construct_tx_with_tx_key(m_account.get_keys(), m_subaddresses, sources, sd.splitted_dsts, ptx.change_dts.addr, sd.extra, tx, sd.unlock_time, ptx.tx_key, ptx.additional_tx_keys, sd.use_rct, bulletproof, &msout); - THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sd.sources, sd.splitted_dsts, sd.unlock_time, m_testnet); + THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sd.sources, sd.splitted_dsts, sd.unlock_time, m_nettype); THROW_WALLET_EXCEPTION_IF(get_transaction_prefix_hash (tx) != get_transaction_prefix_hash(ptx.tx), error::wallet_internal_error, "Transaction prefix does not match data"); @@ -5305,7 +5331,7 @@ void wallet2::light_wallet_get_outs(std::vector<std::vector<tools::wallet2::get_ bool r = epee::net_utils::invoke_http_json("/get_random_outs", oreq, ores, m_http_client, rpc_timeout, "POST"); m_daemon_rpc_mutex.unlock(); THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "get_random_outs"); - THROW_WALLET_EXCEPTION_IF(ores.amount_outs.empty() , error::wallet_internal_error, "No outputs recieved from light wallet node. Error: " + ores.Error); + THROW_WALLET_EXCEPTION_IF(ores.amount_outs.empty() , error::wallet_internal_error, "No outputs received from light wallet node. Error: " + ores.Error); // Check if we got enough outputs for each amount for(auto& out: ores.amount_outs) { @@ -5529,7 +5555,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>> } } - // sort the subsection, to ensure the daemon doesn't know wich output is ours + // sort the subsection, to ensure the daemon doesn't know which output is ours std::sort(req.outputs.begin() + start, req.outputs.end(), [](const get_outputs_out &a, const get_outputs_out &b) { return a.index < b.index; }); } @@ -5642,7 +5668,7 @@ void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_ent THROW_WALLET_EXCEPTION_IF(0 == dt.amount, error::zero_destination); needed_money += dt.amount; LOG_PRINT_L2("transfer: adding " << print_money(dt.amount) << ", for a total of " << print_money (needed_money)); - THROW_WALLET_EXCEPTION_IF(needed_money < dt.amount, error::tx_sum_overflow, dsts, fee, m_testnet); + THROW_WALLET_EXCEPTION_IF(needed_money < dt.amount, error::tx_sum_overflow, dsts, fee, m_nettype); } uint64_t found_money = 0; @@ -5735,7 +5761,7 @@ void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_ent LOG_PRINT_L2("constructing tx"); bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), m_subaddresses, sources, splitted_dsts, change_dts.addr, extra, tx, unlock_time, tx_key, additional_tx_keys, false, false, m_multisig ? &msout : NULL); LOG_PRINT_L2("constructed tx, r="<<r); - THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_testnet); + THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_nettype); THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit); std::string key_images; @@ -5799,7 +5825,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry THROW_WALLET_EXCEPTION_IF(0 == dt.amount, error::zero_destination); needed_money += dt.amount; LOG_PRINT_L2("transfer: adding " << print_money(dt.amount) << ", for a total of " << print_money (needed_money)); - THROW_WALLET_EXCEPTION_IF(needed_money < dt.amount, error::tx_sum_overflow, dsts, fee, m_testnet); + THROW_WALLET_EXCEPTION_IF(needed_money < dt.amount, error::tx_sum_overflow, dsts, fee, m_nettype); } // if this is a multisig wallet, create a list of multisig signers we can use @@ -5939,7 +5965,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry auto sources_copy = sources; bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), m_subaddresses, sources, splitted_dsts, change_dts.addr, extra, tx, unlock_time, tx_key, additional_tx_keys, true, bulletproof, m_multisig ? &msout : NULL); LOG_PRINT_L2("constructed tx, r="<<r); - THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, dsts, unlock_time, m_testnet); + THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, dsts, unlock_time, m_nettype); THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit); // work out the permutation done on sources @@ -5984,7 +6010,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry auto sources_copy_copy = sources_copy; bool r = cryptonote::construct_tx_with_tx_key(m_account.get_keys(), m_subaddresses, sources_copy_copy, splitted_dsts, change_dts.addr, extra, ms_tx, unlock_time,tx_key, additional_tx_keys, true, bulletproof, &msout); LOG_PRINT_L2("constructed tx, r="<<r); - THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_testnet); + THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_nettype); THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit); THROW_WALLET_EXCEPTION_IF(cryptonote::get_transaction_prefix_hash(ms_tx) != prefix_hash, error::wallet_internal_error, "Multisig txes do not share prefix"); multisig_sigs.push_back({ms_tx.rct_signatures, multisig_signers[signer_index], new_used_L, std::unordered_set<crypto::public_key>(), msout}); @@ -6154,9 +6180,9 @@ bool wallet2::light_wallet_login(bool &new_address) m_light_wallet_connected = false; cryptonote::COMMAND_RPC_LOGIN::request request; cryptonote::COMMAND_RPC_LOGIN::response response; - request.address = get_account().get_public_address_str(m_testnet); + request.address = get_account().get_public_address_str(m_nettype); request.view_key = string_tools::pod_to_hex(get_account().get_keys().m_view_secret_key); - // Always create account if it doesnt exist. + // Always create account if it doesn't exist. request.create_account = true; m_daemon_rpc_mutex.lock(); bool connected = epee::net_utils::invoke_http_json("/login", request, response, m_http_client, rpc_timeout, "POST"); @@ -6169,7 +6195,7 @@ bool wallet2::light_wallet_login(bool &new_address) MDEBUG("New wallet: " << response.new_address); if(m_light_wallet_connected) { - // Clear old data on successfull login. + // Clear old data on successful login. // m_transfers.clear(); // m_payments.clear(); // m_unconfirmed_payments.clear(); @@ -6181,7 +6207,7 @@ bool wallet2::light_wallet_import_wallet_request(cryptonote::COMMAND_RPC_IMPORT_ { MDEBUG("Light wallet import wallet request"); cryptonote::COMMAND_RPC_IMPORT_WALLET_REQUEST::request oreq; - oreq.address = get_account().get_public_address_str(m_testnet); + oreq.address = get_account().get_public_address_str(m_nettype); oreq.view_key = string_tools::pod_to_hex(get_account().get_keys().m_view_secret_key); m_daemon_rpc_mutex.lock(); bool r = epee::net_utils::invoke_http_json("/import_wallet_request", oreq, response, m_http_client, rpc_timeout, "POST"); @@ -6200,7 +6226,7 @@ void wallet2::light_wallet_get_unspent_outs() cryptonote::COMMAND_RPC_GET_UNSPENT_OUTS::response ores; oreq.amount = "0"; - oreq.address = get_account().get_public_address_str(m_testnet); + oreq.address = get_account().get_public_address_str(m_nettype); oreq.view_key = string_tools::pod_to_hex(get_account().get_keys().m_view_secret_key); // openMonero specific oreq.dust_threshold = boost::lexical_cast<std::string>(::config::DEFAULT_DUST_THRESHOLD); @@ -6350,7 +6376,7 @@ bool wallet2::light_wallet_get_address_info(cryptonote::COMMAND_RPC_GET_ADDRESS_ cryptonote::COMMAND_RPC_GET_ADDRESS_INFO::request request; - request.address = get_account().get_public_address_str(m_testnet); + request.address = get_account().get_public_address_str(m_nettype); request.view_key = string_tools::pod_to_hex(get_account().get_keys().m_view_secret_key); m_daemon_rpc_mutex.lock(); bool r = epee::net_utils::invoke_http_json("/get_address_info", request, response, m_http_client, rpc_timeout, "POST"); @@ -6367,7 +6393,7 @@ void wallet2::light_wallet_get_address_txs() cryptonote::COMMAND_RPC_GET_ADDRESS_TXS::request ireq; cryptonote::COMMAND_RPC_GET_ADDRESS_TXS::response ires; - ireq.address = get_account().get_public_address_str(m_testnet); + ireq.address = get_account().get_public_address_str(m_nettype); ireq.view_key = string_tools::pod_to_hex(get_account().get_keys().m_view_secret_key); m_daemon_rpc_mutex.lock(); bool r = epee::net_utils::invoke_http_json("/get_address_txs", ireq, ires, m_http_client, rpc_timeout, "POST"); @@ -6541,7 +6567,7 @@ void wallet2::light_wallet_get_address_txs() // Calculate wallet balance m_light_wallet_balance = ires.total_received-wallet_total_sent; - // MyMonero doesnt send unlocked balance + // MyMonero doesn't send unlocked balance if(ires.total_received_unlocked > 0) m_light_wallet_unlocked_balance = ires.total_received_unlocked-wallet_total_sent; else @@ -6692,7 +6718,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp THROW_WALLET_EXCEPTION_IF(0 == dt.amount, error::zero_destination); needed_money += dt.amount; LOG_PRINT_L2("transfer: adding " << print_money(dt.amount) << ", for a total of " << print_money (needed_money)); - THROW_WALLET_EXCEPTION_IF(needed_money < dt.amount, error::tx_sum_overflow, dsts, 0, m_testnet); + THROW_WALLET_EXCEPTION_IF(needed_money < dt.amount, error::tx_sum_overflow, dsts, 0, m_nettype); } // throw if attempting a transaction with no money @@ -6818,7 +6844,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp { string s; for (auto i: preferred_inputs) s += boost::lexical_cast<std::string>(i) + " (" + print_money(m_transfers[i].amount()) + ") "; - LOG_PRINT_L1("Found prefered rct inputs for rct tx: " << s); + LOG_PRINT_L1("Found preferred rct inputs for rct tx: " << s); // bring the list of available outputs stored by the same subaddress index to the front of the list uint32_t index_minor = m_transfers[preferred_inputs[0]].m_subaddr_index.minor; @@ -6920,7 +6946,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp while (!dsts.empty() && dsts[0].amount <= available_amount && estimate_tx_size(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size(), extra.size(), bulletproof) < TX_SIZE_TARGET(upper_transaction_size_limit)) { // we can fully pay that destination - LOG_PRINT_L2("We can fully pay " << get_account_address_as_str(m_testnet, dsts[0].is_subaddress, dsts[0].addr) << + LOG_PRINT_L2("We can fully pay " << get_account_address_as_str(m_nettype, dsts[0].is_subaddress, dsts[0].addr) << " for " << print_money(dsts[0].amount)); tx.add(dsts[0].addr, dsts[0].is_subaddress, dsts[0].amount, original_output_index, m_merge_destinations); available_amount -= dsts[0].amount; @@ -6931,7 +6957,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp if (available_amount > 0 && !dsts.empty() && estimate_tx_size(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size(), extra.size(), bulletproof) < TX_SIZE_TARGET(upper_transaction_size_limit)) { // we can partially fill that destination - LOG_PRINT_L2("We can partially pay " << get_account_address_as_str(m_testnet, dsts[0].is_subaddress, dsts[0].addr) << + LOG_PRINT_L2("We can partially pay " << get_account_address_as_str(m_nettype, dsts[0].is_subaddress, dsts[0].addr) << " for " << print_money(available_amount) << "/" << print_money(dsts[0].amount)); tx.add(dsts[0].addr, dsts[0].is_subaddress, available_amount, original_output_index, m_merge_destinations); dsts[0].amount -= available_amount; @@ -7001,7 +7027,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp if (i->amount > needed_fee) { uint64_t new_paid_amount = i->amount /*+ test_ptx.fee*/ - needed_fee; - LOG_PRINT_L2("Adjusting amount paid to " << get_account_address_as_str(m_testnet, i->is_subaddress, i->addr) << " from " << + LOG_PRINT_L2("Adjusting amount paid to " << get_account_address_as_str(m_nettype, i->is_subaddress, i->addr) << " from " << print_money(i->amount) << " to " << print_money(new_paid_amount) << " to accommodate " << print_money(needed_fee) << " fee"); dsts[0].amount += i->amount - new_paid_amount; @@ -8428,16 +8454,16 @@ uint64_t wallet2::get_daemon_blockchain_target_height(string &err) uint64_t wallet2::get_approximate_blockchain_height() const { // time of v2 fork - const time_t fork_time = m_testnet ? 1448285909 : 1458748658; + const time_t fork_time = m_nettype == TESTNET ? 1448285909 : m_nettype == STAGENET ? (time_t)-1/*TODO*/ : 1458748658; // v2 fork block - const uint64_t fork_block = m_testnet ? 624634 : 1009827; + const uint64_t fork_block = m_nettype == TESTNET ? 624634 : m_nettype == STAGENET ? (uint64_t)-1/*TODO*/ : 1009827; // avg seconds per block const int seconds_per_block = DIFFICULTY_TARGET_V2; // Calculated blockchain height uint64_t approx_blockchain_height = fork_block + (time(NULL) - fork_time)/seconds_per_block; // testnet got some huge rollbacks, so the estimation is way off static const uint64_t approximate_testnet_rolled_back_blocks = 148540; - if (m_testnet && approx_blockchain_height > approximate_testnet_rolled_back_blocks) + if (m_nettype == TESTNET && approx_blockchain_height > approximate_testnet_rolled_back_blocks) approx_blockchain_height -= approximate_testnet_rolled_back_blocks; LOG_PRINT_L2("Calculated blockchain height: " << approx_blockchain_height); return approx_blockchain_height; @@ -9418,7 +9444,7 @@ std::string wallet2::decrypt_with_view_secret_key(const std::string &ciphertext, std::string wallet2::make_uri(const std::string &address, const std::string &payment_id, uint64_t amount, const std::string &tx_description, const std::string &recipient_name, std::string &error) const { cryptonote::address_parse_info info; - if(!get_account_address_from_str(info, testnet(), address)) + if(!get_account_address_from_str(info, nettype(), address)) { error = std::string("wrong address: ") + address; return std::string(); @@ -9482,7 +9508,7 @@ bool wallet2::parse_uri(const std::string &uri, std::string &address, std::strin address = ptr ? remainder.substr(0, ptr-remainder.c_str()) : remainder; cryptonote::address_parse_info info; - if(!get_account_address_from_str(info, testnet(), address)) + if(!get_account_address_from_str(info, nettype(), address)) { error = std::string("URI has wrong address: ") + address; return false; @@ -9731,10 +9757,14 @@ std::vector<std::pair<uint64_t, uint64_t>> wallet2::estimate_backlog(uint64_t mi } //---------------------------------------------------------------------------------------------------- void wallet2::generate_genesis(cryptonote::block& b) const { - if (m_testnet) + if (m_nettype == TESTNET) { cryptonote::generate_genesis_block(b, config::testnet::GENESIS_TX, config::testnet::GENESIS_NONCE); } + else if (m_nettype == STAGENET) + { + cryptonote::generate_genesis_block(b, config::stagenet::GENESIS_TX, config::stagenet::GENESIS_NONCE); + } else { cryptonote::generate_genesis_block(b, config::GENESIS_TX, config::GENESIS_NONCE); diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 127e70a26..57a61cb9d 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -147,6 +147,7 @@ namespace tools static const char* tr(const char* str); static bool has_testnet_option(const boost::program_options::variables_map& vm); + static bool has_stagenet_option(const boost::program_options::variables_map& vm); static void init_options(boost::program_options::options_description& desc_params); //! Uses stdin and stdout. Returns a wallet2 if no errors. @@ -164,7 +165,7 @@ namespace tools static bool verify_password(const std::string& keys_file_name, const epee::wipeable_string& password, bool no_spend_key, hw::device &hwdev); - wallet2(bool testnet = false, bool restricted = false); + wallet2(cryptonote::network_type nettype = cryptonote::MAINNET, bool restricted = false); struct multisig_info { @@ -637,7 +638,7 @@ namespace tools void set_refresh_type(RefreshType refresh_type) { m_refresh_type = refresh_type; } RefreshType get_refresh_type() const { return m_refresh_type; } - bool testnet() const { return m_testnet; } + cryptonote::network_type nettype() const { return m_nettype; } bool restricted() const { return m_restricted; } bool watch_only() const { return m_watch_only; } bool multisig(bool *ready = NULL, uint32_t *threshold = NULL, uint32_t *total = NULL) const; @@ -1115,7 +1116,7 @@ namespace tools i_wallet2_callback* m_callback; bool m_key_on_device; - bool m_testnet; + cryptonote::network_type m_nettype; bool m_restricted; std::string seed_language; /*!< Language of the mnemonics (seed). */ bool is_old_file_format; /*!< Whether the wallet file is of an old file format */ @@ -1646,7 +1647,7 @@ namespace tools { THROW_WALLET_EXCEPTION_IF(0 == dt.amount, error::zero_destination); needed_money += dt.amount; - THROW_WALLET_EXCEPTION_IF(needed_money < dt.amount, error::tx_sum_overflow, dsts, fee, m_testnet); + THROW_WALLET_EXCEPTION_IF(needed_money < dt.amount, error::tx_sum_overflow, dsts, fee, m_nettype); } // randomly select inputs for transaction @@ -1768,7 +1769,7 @@ namespace tools std::vector<crypto::secret_key> additional_tx_keys; rct::multisig_out msout; bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), m_subaddresses, sources, splitted_dsts, change_dts.addr, extra, tx, unlock_time, tx_key, additional_tx_keys, false, false, m_multisig ? &msout : NULL); - THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_testnet); + THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_nettype); THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit); std::string key_images; diff --git a/src/wallet/wallet_errors.h b/src/wallet/wallet_errors.h index 5c1c49d5d..32a0231b1 100644 --- a/src/wallet/wallet_errors.h +++ b/src/wallet/wallet_errors.h @@ -529,13 +529,13 @@ namespace tools , sources_t const & sources , destinations_t const & destinations , uint64_t unlock_time - , bool testnet + , cryptonote::network_type nettype ) : transfer_error(std::move(loc), "transaction was not constructed") , m_sources(sources) , m_destinations(destinations) , m_unlock_time(unlock_time) - , m_testnet(testnet) + , m_nettype(nettype) { } @@ -569,7 +569,7 @@ namespace tools for (size_t i = 0; i < m_destinations.size(); ++i) { const cryptonote::tx_destination_entry& dst = m_destinations[i]; - ss << "\n " << i << ": " << cryptonote::get_account_address_as_str(m_testnet, dst.is_subaddress, dst.addr) << " " << + ss << "\n " << i << ": " << cryptonote::get_account_address_as_str(m_nettype, dst.is_subaddress, dst.addr) << " " << cryptonote::print_money(dst.amount); } @@ -582,7 +582,7 @@ namespace tools sources_t m_sources; destinations_t m_destinations; uint64_t m_unlock_time; - bool m_testnet; + cryptonote::network_type m_nettype; }; //---------------------------------------------------------------------------------------------------- struct tx_rejected : public transfer_error @@ -624,12 +624,12 @@ namespace tools std::string && loc , const std::vector<cryptonote::tx_destination_entry>& destinations , uint64_t fee - , bool testnet + , cryptonote::network_type nettype ) : transfer_error(std::move(loc), "transaction sum + fee exceeds " + cryptonote::print_money(std::numeric_limits<uint64_t>::max())) , m_destinations(destinations) , m_fee(fee) - , m_testnet(testnet) + , m_nettype(nettype) { } @@ -644,7 +644,7 @@ namespace tools ", destinations:"; for (const auto& dst : m_destinations) { - ss << '\n' << cryptonote::print_money(dst.amount) << " -> " << cryptonote::get_account_address_as_str(m_testnet, dst.is_subaddress, dst.addr); + ss << '\n' << cryptonote::print_money(dst.amount) << " -> " << cryptonote::get_account_address_as_str(m_nettype, dst.is_subaddress, dst.addr); } return ss.str(); } @@ -652,7 +652,7 @@ namespace tools private: std::vector<cryptonote::tx_destination_entry> m_destinations; uint64_t m_fee; - bool m_testnet; + cryptonote::network_type m_nettype; }; //---------------------------------------------------------------------------------------------------- struct tx_too_big : public transfer_error diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index 6d5419521..220dbbc58 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -280,7 +280,7 @@ namespace tools entry.destinations.push_back(wallet_rpc::transfer_destination()); wallet_rpc::transfer_destination &td = entry.destinations.back(); td.amount = d.amount; - td.address = get_account_address_as_str(m_wallet->testnet(), d.is_subaddress, d.addr); + td.address = get_account_address_as_str(m_wallet->nettype(), d.is_subaddress, d.addr); } entry.type = "out"; @@ -584,7 +584,7 @@ namespace tools cryptonote::address_parse_info info; cryptonote::tx_destination_entry de; er.message = ""; - if(!get_account_address_from_str_or_url(info, m_wallet->testnet(), it->address, + if(!get_account_address_from_str_or_url(info, m_wallet->nettype(), it->address, [&er](const std::string &url, const std::vector<std::string> &addresses, bool dnssec_valid)->std::string { if (!dnssec_valid) { @@ -786,7 +786,15 @@ namespace tools try { - uint64_t mixin = m_wallet->adjust_mixin(req.mixin); + uint64_t mixin; + if(req.ring_size != 0) + { + mixin = m_wallet->adjust_mixin(req.ring_size - 1); + } + else + { + mixin = m_wallet->adjust_mixin(req.mixin); + } uint32_t priority = m_wallet->adjust_priority(req.priority); std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_2(dsts, mixin, req.unlock_time, priority, extra, req.account_index, req.subaddr_indices, m_trusted_daemon); @@ -838,7 +846,15 @@ namespace tools try { - uint64_t mixin = m_wallet->adjust_mixin(req.mixin); + uint64_t mixin; + if(req.ring_size != 0) + { + mixin = m_wallet->adjust_mixin(req.ring_size - 1); + } + else + { + mixin = m_wallet->adjust_mixin(req.mixin); + } uint32_t priority = m_wallet->adjust_priority(req.priority); LOG_PRINT_L2("on_transfer_split calling create_transactions_2"); std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_2(dsts, mixin, req.unlock_time, priority, extra, req.account_index, req.subaddr_indices, m_trusted_daemon); @@ -905,7 +921,15 @@ namespace tools try { - uint64_t mixin = m_wallet->adjust_mixin(req.mixin); + uint64_t mixin; + if(req.ring_size != 0) + { + mixin = m_wallet->adjust_mixin(req.ring_size - 1); + } + else + { + mixin = m_wallet->adjust_mixin(req.mixin); + } uint32_t priority = m_wallet->adjust_priority(req.priority); std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_all(req.below_amount, dsts[0].addr, dsts[0].is_subaddress, mixin, req.unlock_time, priority, extra, req.account_index, req.subaddr_indices, m_trusted_daemon); @@ -953,7 +977,15 @@ namespace tools try { - uint64_t mixin = m_wallet->adjust_mixin(req.mixin); + uint64_t mixin; + if(req.ring_size != 0) + { + mixin = m_wallet->adjust_mixin(req.ring_size - 1); + } + else + { + mixin = m_wallet->adjust_mixin(req.mixin); + } uint32_t priority = m_wallet->adjust_priority(req.priority); std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_single(ki, dsts[0].addr, dsts[0].is_subaddress, mixin, req.unlock_time, priority, extra, m_trusted_daemon); @@ -1075,7 +1107,7 @@ namespace tools { cryptonote::address_parse_info info; - if(!get_account_address_from_str(info, m_wallet->testnet(), req.integrated_address)) + if(!get_account_address_from_str(info, m_wallet->nettype(), req.integrated_address)) { er.code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS; er.message = "Invalid address"; @@ -1087,7 +1119,7 @@ namespace tools er.message = "Address is not an integrated address"; return false; } - res.standard_address = get_account_address_as_str(m_wallet->testnet(), info.is_subaddress, info.address); + res.standard_address = get_account_address_as_str(m_wallet->nettype(), info.is_subaddress, info.address); res.payment_id = epee::string_tools::pod_to_hex(info.payment_id); return true; } @@ -1385,7 +1417,7 @@ namespace tools cryptonote::address_parse_info info; er.message = ""; - if(!get_account_address_from_str_or_url(info, m_wallet->testnet(), req.address, + if(!get_account_address_from_str_or_url(info, m_wallet->nettype(), req.address, [&er](const std::string &url, const std::vector<std::string> &addresses, bool dnssec_valid)->std::string { if (!dnssec_valid) { @@ -1595,7 +1627,7 @@ namespace tools } cryptonote::address_parse_info info; - if(!get_account_address_from_str(info, m_wallet->testnet(), req.address)) + if(!get_account_address_from_str(info, m_wallet->nettype(), req.address)) { er.code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS; er.message = "Invalid address"; @@ -1628,7 +1660,7 @@ namespace tools } cryptonote::address_parse_info info; - if(!get_account_address_from_str(info, m_wallet->testnet(), req.address)) + if(!get_account_address_from_str(info, m_wallet->nettype(), req.address)) { er.code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS; er.message = "Invalid address"; @@ -1661,7 +1693,7 @@ namespace tools } cryptonote::address_parse_info info; - if(!get_account_address_from_str(info, m_wallet->testnet(), req.address)) + if(!get_account_address_from_str(info, m_wallet->nettype(), req.address)) { er.code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS; er.message = "Invalid address"; @@ -1768,7 +1800,7 @@ namespace tools if (!m_wallet) return not_open(er); cryptonote::address_parse_info info; - if (!get_account_address_from_str(info, m_wallet->testnet(), req.address)) + if (!get_account_address_from_str(info, m_wallet->nettype(), req.address)) { er.code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS; er.message = "Invalid address"; @@ -2058,7 +2090,7 @@ namespace tools { uint64_t idx = 0; for (const auto &entry: ab) - res.entries.push_back(wallet_rpc::COMMAND_RPC_GET_ADDRESS_BOOK_ENTRY::entry{idx++, get_account_address_as_str(m_wallet->testnet(), entry.m_is_subaddress, entry.m_address), epee::string_tools::pod_to_hex(entry.m_payment_id), entry.m_description}); + res.entries.push_back(wallet_rpc::COMMAND_RPC_GET_ADDRESS_BOOK_ENTRY::entry{idx++, get_account_address_as_str(m_wallet->nettype(), entry.m_is_subaddress, entry.m_address), epee::string_tools::pod_to_hex(entry.m_payment_id), entry.m_description}); } else { @@ -2071,7 +2103,7 @@ namespace tools return false; } const auto &entry = ab[idx]; - res.entries.push_back(wallet_rpc::COMMAND_RPC_GET_ADDRESS_BOOK_ENTRY::entry{idx, get_account_address_as_str(m_wallet->testnet(), entry.m_is_subaddress, entry.m_address), epee::string_tools::pod_to_hex(entry.m_payment_id), entry.m_description}); + res.entries.push_back(wallet_rpc::COMMAND_RPC_GET_ADDRESS_BOOK_ENTRY::entry{idx, get_account_address_as_str(m_wallet->nettype(), entry.m_is_subaddress, entry.m_address), epee::string_tools::pod_to_hex(entry.m_payment_id), entry.m_description}); } } return true; @@ -2090,7 +2122,7 @@ namespace tools cryptonote::address_parse_info info; crypto::hash payment_id = crypto::null_hash; er.message = ""; - if(!get_account_address_from_str_or_url(info, m_wallet->testnet(), req.address, + if(!get_account_address_from_str_or_url(info, m_wallet->nettype(), req.address, [&er](const std::string &url, const std::vector<std::string> &addresses, bool dnssec_valid)->std::string { if (!dnssec_valid) { @@ -2219,7 +2251,7 @@ namespace tools } cryptonote::COMMAND_RPC_START_MINING::request daemon_req = AUTO_VAL_INIT(daemon_req); - daemon_req.miner_address = m_wallet->get_account().get_public_address_str(m_wallet->testnet()); + daemon_req.miner_address = m_wallet->get_account().get_public_address_str(m_wallet->nettype()); daemon_req.threads_count = req.threads_count; daemon_req.do_background_mining = req.do_background_mining; daemon_req.ignore_battery = req.ignore_battery; @@ -2535,7 +2567,7 @@ namespace tools try { res.multisig_info = m_wallet->make_multisig(req.password, req.multisig_info, req.threshold); - res.address = m_wallet->get_account().get_public_address_str(m_wallet->testnet()); + res.address = m_wallet->get_account().get_public_address_str(m_wallet->nettype()); } catch (const std::exception &e) { @@ -2706,7 +2738,7 @@ namespace tools er.message = std::string("Error calling finalize_multisig: ") + e.what(); return false; } - res.address = m_wallet->get_account().get_public_address_str(m_wallet->testnet()); + res.address = m_wallet->get_account().get_public_address_str(m_wallet->nettype()); return true; } @@ -2883,6 +2915,14 @@ int main(int argc, char** argv) { std::unique_ptr<tools::wallet2> wal; try { + const bool testnet = tools::wallet2::has_testnet_option(*vm); + const bool stagenet = tools::wallet2::has_stagenet_option(*vm); + if (testnet && stagenet) + { + MERROR(tools::wallet_rpc_server::tr("Can't specify more than one of --testnet and --stagenet")); + return 1; + } + const auto wallet_file = command_line::get_arg(*vm, arg_wallet_file); const auto from_json = command_line::get_arg(*vm, arg_from_json); const auto wallet_dir = command_line::get_arg(*vm, arg_wallet_dir); diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h index e38cba5a5..370fea858 100644 --- a/src/wallet/wallet_rpc_server_commands_defs.h +++ b/src/wallet/wallet_rpc_server_commands_defs.h @@ -385,6 +385,7 @@ namespace wallet_rpc std::set<uint32_t> subaddr_indices; uint32_t priority; uint64_t mixin; + uint64_t ring_size; uint64_t unlock_time; std::string payment_id; bool get_tx_key; @@ -398,6 +399,7 @@ namespace wallet_rpc KV_SERIALIZE(subaddr_indices) KV_SERIALIZE(priority) KV_SERIALIZE(mixin) + KV_SERIALIZE_OPT(ring_size, (uint64_t)0) KV_SERIALIZE(unlock_time) KV_SERIALIZE(payment_id) KV_SERIALIZE(get_tx_key) @@ -440,6 +442,7 @@ namespace wallet_rpc std::set<uint32_t> subaddr_indices; uint32_t priority; uint64_t mixin; + uint64_t ring_size; uint64_t unlock_time; std::string payment_id; bool get_tx_keys; @@ -453,6 +456,7 @@ namespace wallet_rpc KV_SERIALIZE(subaddr_indices) KV_SERIALIZE(priority) KV_SERIALIZE(mixin) + KV_SERIALIZE_OPT(ring_size, (uint64_t)0) KV_SERIALIZE(unlock_time) KV_SERIALIZE(payment_id) KV_SERIALIZE(get_tx_keys) @@ -550,6 +554,7 @@ namespace wallet_rpc std::set<uint32_t> subaddr_indices; uint32_t priority; uint64_t mixin; + uint64_t ring_size; uint64_t unlock_time; std::string payment_id; bool get_tx_keys; @@ -564,6 +569,7 @@ namespace wallet_rpc KV_SERIALIZE(subaddr_indices) KV_SERIALIZE(priority) KV_SERIALIZE(mixin) + KV_SERIALIZE_OPT(ring_size, (uint64_t)0) KV_SERIALIZE(unlock_time) KV_SERIALIZE(payment_id) KV_SERIALIZE(get_tx_keys) @@ -612,6 +618,7 @@ namespace wallet_rpc std::string address; uint32_t priority; uint64_t mixin; + uint64_t ring_size; uint64_t unlock_time; std::string payment_id; bool get_tx_key; @@ -624,6 +631,7 @@ namespace wallet_rpc KV_SERIALIZE(address) KV_SERIALIZE(priority) KV_SERIALIZE(mixin) + KV_SERIALIZE_OPT(ring_size, (uint64_t)0) KV_SERIALIZE(unlock_time) KV_SERIALIZE(payment_id) KV_SERIALIZE(get_tx_key) diff --git a/tests/core_proxy/core_proxy.h b/tests/core_proxy/core_proxy.h index b7c3dc022..59f8d5239 100644 --- a/tests/core_proxy/core_proxy.h +++ b/tests/core_proxy/core_proxy.h @@ -91,7 +91,7 @@ namespace tests uint64_t get_target_blockchain_height() const { return 1; } size_t get_block_sync_size(uint64_t height) const { return BLOCKS_SYNCHRONIZING_DEFAULT_COUNT; } virtual void on_transaction_relayed(const cryptonote::blobdata& tx) {} - bool get_testnet() const { return false; } + cryptonote::network_type get_nettype() const { return cryptonote::MAINNET; } bool get_pool_transaction(const crypto::hash& id, cryptonote::blobdata& tx_blob) const { return false; } bool pool_has_tx(const crypto::hash &txid) const { return false; } bool get_blocks(uint64_t start_offset, size_t count, std::list<std::pair<cryptonote::blobdata, cryptonote::block>>& blocks, std::list<cryptonote::blobdata>& txs) const { return false; } diff --git a/tests/core_tests/transaction_tests.cpp b/tests/core_tests/transaction_tests.cpp index 9157c2db4..3c6954bc6 100644 --- a/tests/core_tests/transaction_tests.cpp +++ b/tests/core_tests/transaction_tests.cpp @@ -54,7 +54,7 @@ bool test_transaction_generation_and_ring_signature() account_base miner_acc6; miner_acc6.generate(); - std::string add_str = miner_acc3.get_public_address_str(false); + std::string add_str = miner_acc3.get_public_address_str(MAINNET); account_base rv_acc; @@ -140,7 +140,7 @@ bool test_block_creation() uint64_t vszs[] = {80,476,476,475,475,474,475,474,474,475,472,476,476,475,475,474,475,474,474,475,472,476,476,475,475,474,475,474,474,475,9391,476,476,475,475,474,475,8819,8301,475,472,4302,5316,14347,16620,19583,19403,19728,19442,19852,19015,19000,19016,19795,19749,18087,19787,19704,19750,19267,19006,19050,19445,19407,19522,19546,19788,19369,19486,19329,19370,18853,19600,19110,19320,19746,19474,19474,19743,19494,19755,19715,19769,19620,19368,19839,19532,23424,28287,30707}; std::vector<uint64_t> szs(&vszs[0], &vszs[90]); address_parse_info info; - bool r = get_account_address_from_str(info, false, "0099be99c70ef10fd534c43c88e9d13d1c8853213df7e362afbec0e4ee6fec4948d0c190b58f4b356cd7feaf8d9d0a76e7c7e5a9a0a497a6b1faf7a765882dd08ac2"); + bool r = get_account_address_from_str(info, MAINNET, "0099be99c70ef10fd534c43c88e9d13d1c8853213df7e362afbec0e4ee6fec4948d0c190b58f4b356cd7feaf8d9d0a76e7c7e5a9a0a497a6b1faf7a765882dd08ac2"); CHECK_AND_ASSERT_MES(r, false, "failed to import"); block b; r = construct_miner_tx(90, epee::misc_utils::median(szs), 3553616528562147, 33094, 10000000, info.address, b.miner_tx, blobdata(), 11); diff --git a/tests/functional_tests/transactions_flow_test.cpp b/tests/functional_tests/transactions_flow_test.cpp index 98368c26b..55c18283e 100644 --- a/tests/functional_tests/transactions_flow_test.cpp +++ b/tests/functional_tests/transactions_flow_test.cpp @@ -152,8 +152,8 @@ bool transactions_flow_test(std::string& working_folder, w2.init(daemon_addr_b); MGINFO_GREEN("Using wallets: " << ENDL - << "Source: " << w1.get_account().get_public_address_str(false) << ENDL << "Path: " << working_folder + "/" + path_source_wallet << ENDL - << "Target: " << w2.get_account().get_public_address_str(false) << ENDL << "Path: " << working_folder + "/" + path_target_wallet); + << "Source: " << w1.get_account().get_public_address_str(MAINNET) << ENDL << "Path: " << working_folder + "/" + path_source_wallet << ENDL + << "Target: " << w2.get_account().get_public_address_str(MAINNET) << ENDL << "Path: " << working_folder + "/" + path_target_wallet); //lets do some money epee::net_utils::http::http_simple_client http_client; @@ -164,7 +164,7 @@ bool transactions_flow_test(std::string& working_folder, COMMAND_RPC_START_MINING::request daemon_req = AUTO_VAL_INIT(daemon_req); COMMAND_RPC_START_MINING::response daemon_rsp = AUTO_VAL_INIT(daemon_rsp); - daemon_req.miner_address = w1.get_account().get_public_address_str(false); + daemon_req.miner_address = w1.get_account().get_public_address_str(MAINNET); daemon_req.threads_count = 9; r = net_utils::invoke_http_json("/start_mining", daemon_req, daemon_rsp, http_client, std::chrono::seconds(10)); CHECK_AND_ASSERT_MES(r, false, "failed to get getrandom_outs"); diff --git a/tests/fuzz/cold-outputs.cpp b/tests/fuzz/cold-outputs.cpp index e6f92db27..9aa9460d5 100644 --- a/tests/fuzz/cold-outputs.cpp +++ b/tests/fuzz/cold-outputs.cpp @@ -37,7 +37,7 @@ class ColdOutputsFuzzer: public Fuzzer { public: - ColdOutputsFuzzer(): wallet(true) {} + ColdOutputsFuzzer(): wallet(cryptonote::TESTNET) {} virtual int init(); virtual int run(const std::string &filename); diff --git a/tests/fuzz/cold-transaction.cpp b/tests/fuzz/cold-transaction.cpp index 5879d6253..d81092c82 100644 --- a/tests/fuzz/cold-transaction.cpp +++ b/tests/fuzz/cold-transaction.cpp @@ -37,7 +37,7 @@ class ColdTransactionFuzzer: public Fuzzer { public: - ColdTransactionFuzzer(): wallet(true) {} + ColdTransactionFuzzer(): wallet(cryptonote::TESTNET) {} virtual int init(); virtual int run(const std::string &filename); diff --git a/tests/fuzz/signature.cpp b/tests/fuzz/signature.cpp index 69fae84fa..2b8ffe465 100644 --- a/tests/fuzz/signature.cpp +++ b/tests/fuzz/signature.cpp @@ -37,7 +37,7 @@ class SignatureFuzzer: public Fuzzer { public: - SignatureFuzzer(): Fuzzer(), wallet(true) {} + SignatureFuzzer(): Fuzzer(), wallet(cryptonote::TESTNET) {} virtual int init(); virtual int run(const std::string &filename); @@ -58,7 +58,7 @@ int SignatureFuzzer::init() wallet.generate("", "", spendkey, true, false); cryptonote::address_parse_info info; - if (!cryptonote::get_account_address_from_str_or_url(info, true, "9uVsvEryzpN8WH2t1WWhFFCG5tS8cBNdmJYNRuckLENFimfauV5pZKeS1P2CbxGkSDTUPHXWwiYE5ZGSXDAGbaZgDxobqDN")) + if (!cryptonote::get_account_address_from_str_or_url(info, cryptonote::TESTNET, "9uVsvEryzpN8WH2t1WWhFFCG5tS8cBNdmJYNRuckLENFimfauV5pZKeS1P2CbxGkSDTUPHXWwiYE5ZGSXDAGbaZgDxobqDN")) { std::cerr << "failed to parse address" << std::endl; return 1; diff --git a/tests/gtest/include/gtest/internal/gtest-filepath.h b/tests/gtest/include/gtest/internal/gtest-filepath.h index 7a13b4b0d..184450686 100644 --- a/tests/gtest/include/gtest/internal/gtest-filepath.h +++ b/tests/gtest/include/gtest/internal/gtest-filepath.h @@ -192,7 +192,7 @@ class GTEST_API_ FilePath { void Normalize(); - // Returns a pointer to the last occurence of a valid path separator in + // Returns a pointer to the last occurrence of a valid path separator in // the FilePath. On Windows, for example, both '/' and '\' are valid path // separators. Returns NULL if no path separator was found. const char* FindLastPathSeparator() const; diff --git a/tests/gtest/src/gtest-filepath.cc b/tests/gtest/src/gtest-filepath.cc index 0292dc119..3bb275488 100644 --- a/tests/gtest/src/gtest-filepath.cc +++ b/tests/gtest/src/gtest-filepath.cc @@ -130,7 +130,7 @@ FilePath FilePath::RemoveExtension(const char* extension) const { return *this; } -// Returns a pointer to the last occurence of a valid path separator in +// Returns a pointer to the last occurrence of a valid path separator in // the FilePath. On Windows, for example, both '/' and '\' are valid path // separators. Returns NULL if no path separator was found. const char* FilePath::FindLastPathSeparator() const { diff --git a/tests/hash/CMakeLists.txt b/tests/hash/CMakeLists.txt index e2aca8517..92abeca20 100644 --- a/tests/hash/CMakeLists.txt +++ b/tests/hash/CMakeLists.txt @@ -43,7 +43,7 @@ set_property(TARGET hash-tests PROPERTY FOLDER "tests") -foreach (hash IN ITEMS fast slow tree extra-blake extra-groestl extra-jh extra-skein) +foreach (hash IN ITEMS fast slow slow-1 tree extra-blake extra-groestl extra-jh extra-skein) add_test( NAME "hash-${hash}" COMMAND hash-tests "${hash}" "${CMAKE_CURRENT_SOURCE_DIR}/tests-${hash}.txt") diff --git a/tests/hash/main.cpp b/tests/hash/main.cpp index aa928856a..5a16284df 100644 --- a/tests/hash/main.cpp +++ b/tests/hash/main.cpp @@ -51,6 +51,12 @@ extern "C" { } tree_hash((const char (*)[32]) data, length >> 5, hash); } + static void cn_slow_hash_0(const void *data, size_t length, char *hash) { + return cn_slow_hash(data, length, hash, 0); + } + static void cn_slow_hash_1(const void *data, size_t length, char *hash) { + return cn_slow_hash(data, length, hash, 1); + } } POP_WARNINGS @@ -58,9 +64,10 @@ extern "C" typedef void hash_f(const void *, size_t, char *); struct hash_func { const string name; hash_f &f; -} hashes[] = {{"fast", cn_fast_hash}, {"slow", cn_slow_hash}, {"tree", hash_tree}, +} hashes[] = {{"fast", cn_fast_hash}, {"slow", cn_slow_hash_0}, {"tree", hash_tree}, {"extra-blake", hash_extra_blake}, {"extra-groestl", hash_extra_groestl}, - {"extra-jh", hash_extra_jh}, {"extra-skein", hash_extra_skein}}; + {"extra-jh", hash_extra_jh}, {"extra-skein", hash_extra_skein}, + {"slow-1", cn_slow_hash_1}}; int main(int argc, char *argv[]) { hash_f *f; diff --git a/tests/hash/tests-slow-1.txt b/tests/hash/tests-slow-1.txt new file mode 100644 index 000000000..ed8eccc22 --- /dev/null +++ b/tests/hash/tests-slow-1.txt @@ -0,0 +1,5 @@ +b5a7f63abb94d07d1a6445c36c07c7e8327fe61b1647e391b4c7edae5de57a3d 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +80563c40ed46575a9e44820d93ee095e2851aa22483fd67837118c6cd951ba61 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +5bb40c5880cef2f739bdb6aaaf16161eaae55530e7b10d7ea996b751a299e949 8519e039172b0d70e5ca7b3383d6b3167315a422747b73f019cf9528f0fde341fd0f2a63030ba6450525cf6de31837669af6f1df8131faf50aaab8d3a7405589 +613e638505ba1fd05f428d5c9f8e08f8165614342dac419adc6a47dce257eb3e 37a636d7dafdf259b7287eddca2f58099e98619d2f99bdb8969d7b14498102cc065201c8be90bd777323f449848b215d2977c92c4c1c2da36ab46b2e389689ed97c18fec08cd3b03235c5e4c62a37ad88c7b67932495a71090e85dd4020a9300 +ed082e49dbd5bbe34a3726a0d1dad981146062b39d36d62c71eb1ed8ab49459b 38274c97c45a172cfc97679870422e3a1ab0784960c60514d816271415c306ee3a3ed1a77e31f6a885c3cb diff --git a/tests/libwallet_api_tests/main.cpp b/tests/libwallet_api_tests/main.cpp index 96e327ef1..1e63a12f3 100644 --- a/tests/libwallet_api_tests/main.cpp +++ b/tests/libwallet_api_tests/main.cpp @@ -841,7 +841,7 @@ struct MyWalletListener : public Monero::WalletListener { std::cout << "wallet: " << wallet->mainAddress() << "**** just received unconfirmed money (" << txId << ", " << wallet->displayAmount(amount) << ")" << std::endl; - // Don't trigger recieve until tx is mined + // Don't trigger receive until tx is mined // total_rx += amount; // receive_triggered = true; // cv_receive.notify_one(); diff --git a/tests/libwallet_api_tests/scripts/README.md b/tests/libwallet_api_tests/scripts/README.md index 2705cc04b..3818a27d8 100644 --- a/tests/libwallet_api_tests/scripts/README.md +++ b/tests/libwallet_api_tests/scripts/README.md @@ -3,7 +3,7 @@ ## Environment for the tests * Running monero node, linked to private/public testnet. By default, tests expect daemon running at ```localhost:38081```, - can we overriden with enviroment variable ```TESTNET_DAEMON_ADDRESS=<your_daemon_address>``` + can we overriden with environment variable ```TESTNET_DAEMON_ADDRESS=<your_daemon_address>``` [Manual](https://github.com/moneroexamples/private-testnet) explaining how to run private testnet. * Directory with pre-generated wallets diff --git a/tests/unit_tests/ban.cpp b/tests/unit_tests/ban.cpp index 4a3ab0bc3..688656cbc 100644 --- a/tests/unit_tests/ban.cpp +++ b/tests/unit_tests/ban.cpp @@ -70,7 +70,7 @@ public: uint64_t get_target_blockchain_height() const { return 1; } size_t get_block_sync_size(uint64_t height) const { return BLOCKS_SYNCHRONIZING_DEFAULT_COUNT; } virtual void on_transaction_relayed(const cryptonote::blobdata& tx) {} - bool get_testnet() const { return false; } + cryptonote::network_type get_nettype() const { return cryptonote::MAINNET; } bool get_pool_transaction(const crypto::hash& id, cryptonote::blobdata& tx_blob) const { return false; } bool pool_has_tx(const crypto::hash &txid) const { return false; } bool get_blocks(uint64_t start_offset, size_t count, std::list<std::pair<cryptonote::blobdata, cryptonote::block>>& blocks, std::list<cryptonote::blobdata>& txs) const { return false; } diff --git a/tests/unit_tests/base58.cpp b/tests/unit_tests/base58.cpp index e90fa416d..7edb28e62 100644 --- a/tests/unit_tests/base58.cpp +++ b/tests/unit_tests/base58.cpp @@ -474,14 +474,14 @@ TEST(get_account_address_as_str, works_correctly) { cryptonote::account_public_address addr; ASSERT_TRUE(serialization::parse_binary(test_serialized_keys, addr)); - std::string addr_str = cryptonote::get_account_address_as_str(false, false, addr); + std::string addr_str = cryptonote::get_account_address_as_str(cryptonote::MAINNET, false, addr); ASSERT_EQ(addr_str, test_keys_addr_str); } TEST(get_account_address_from_str, handles_valid_address) { cryptonote::address_parse_info info; - ASSERT_TRUE(cryptonote::get_account_address_from_str(info, false, test_keys_addr_str)); + ASSERT_TRUE(cryptonote::get_account_address_from_str(info, cryptonote::MAINNET, test_keys_addr_str)); std::string blob; ASSERT_TRUE(serialization::dump_binary(info.address, blob)); @@ -494,7 +494,7 @@ TEST(get_account_address_from_str, fails_on_invalid_address_format) std::string addr_str = test_keys_addr_str; addr_str[0] = '0'; - ASSERT_FALSE(cryptonote::get_account_address_from_str(info, false, addr_str)); + ASSERT_FALSE(cryptonote::get_account_address_from_str(info, cryptonote::MAINNET, addr_str)); } TEST(get_account_address_from_str, fails_on_invalid_address_prefix) @@ -502,7 +502,7 @@ TEST(get_account_address_from_str, fails_on_invalid_address_prefix) std::string addr_str = base58::encode_addr(0, test_serialized_keys); cryptonote::address_parse_info info; - ASSERT_FALSE(cryptonote::get_account_address_from_str(info, false, addr_str)); + ASSERT_FALSE(cryptonote::get_account_address_from_str(info, cryptonote::MAINNET, addr_str)); } TEST(get_account_address_from_str, fails_on_invalid_address_content) @@ -510,7 +510,7 @@ TEST(get_account_address_from_str, fails_on_invalid_address_content) std::string addr_str = base58::encode_addr(config::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX, test_serialized_keys.substr(1)); cryptonote::address_parse_info info; - ASSERT_FALSE(cryptonote::get_account_address_from_str(info, false, addr_str)); + ASSERT_FALSE(cryptonote::get_account_address_from_str(info, cryptonote::MAINNET, addr_str)); } TEST(get_account_address_from_str, fails_on_invalid_address_spend_key) @@ -520,7 +520,7 @@ TEST(get_account_address_from_str, fails_on_invalid_address_spend_key) std::string addr_str = base58::encode_addr(config::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX, serialized_keys_copy); cryptonote::address_parse_info info; - ASSERT_FALSE(cryptonote::get_account_address_from_str(info, false, addr_str)); + ASSERT_FALSE(cryptonote::get_account_address_from_str(info, cryptonote::MAINNET, addr_str)); } TEST(get_account_address_from_str, fails_on_invalid_address_view_key) @@ -530,11 +530,11 @@ TEST(get_account_address_from_str, fails_on_invalid_address_view_key) std::string addr_str = base58::encode_addr(config::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX, serialized_keys_copy); cryptonote::address_parse_info info; - ASSERT_FALSE(cryptonote::get_account_address_from_str(info, false, addr_str)); + ASSERT_FALSE(cryptonote::get_account_address_from_str(info, cryptonote::MAINNET, addr_str)); } TEST(get_account_address_from_str, parses_old_address_format) { cryptonote::address_parse_info info; - ASSERT_TRUE(cryptonote::get_account_address_from_str(info, false, "002391bbbb24dea6fd95232e97594a27769d0153d053d2102b789c498f57a2b00b69cd6f2f5c529c1660f2f4a2b50178d6640c20ce71fe26373041af97c5b10236fc")); + ASSERT_TRUE(cryptonote::get_account_address_from_str(info, cryptonote::MAINNET, "002391bbbb24dea6fd95232e97594a27769d0153d053d2102b789c498f57a2b00b69cd6f2f5c529c1660f2f4a2b50178d6640c20ce71fe26373041af97c5b10236fc")); } diff --git a/tests/unit_tests/multisig.cpp b/tests/unit_tests/multisig.cpp index f70bb91a3..922299333 100644 --- a/tests/unit_tests/multisig.cpp +++ b/tests/unit_tests/multisig.cpp @@ -64,7 +64,7 @@ static void make_wallet(unsigned int idx, tools::wallet2 &wallet) wallet.init(""); wallet.set_subaddress_lookahead(1, 1); wallet.generate("", "", spendkey, true, false); - ASSERT_TRUE(test_addresses[idx].address == wallet.get_account().get_public_address_str(true)); + ASSERT_TRUE(test_addresses[idx].address == wallet.get_account().get_public_address_str(cryptonote::TESTNET)); } catch (const std::exception &e) { @@ -93,7 +93,7 @@ static void make_M_2_wallet(tools::wallet2 &wallet0, tools::wallet2 &wallet1, un wallet0.make_multisig("", sk0, pk0, M); wallet1.make_multisig("", sk1, pk1, M); - ASSERT_TRUE(wallet0.get_account().get_public_address_str(true) == wallet1.get_account().get_public_address_str(true)); + ASSERT_TRUE(wallet0.get_account().get_public_address_str(cryptonote::TESTNET) == wallet1.get_account().get_public_address_str(cryptonote::TESTNET)); bool ready; uint32_t threshold, total; @@ -150,8 +150,8 @@ static void make_M_3_wallet(tools::wallet2 &wallet0, tools::wallet2 &wallet1, to ASSERT_TRUE(wallet2.finalize_multisig("", pkeys, signers)); } - ASSERT_TRUE(wallet0.get_account().get_public_address_str(true) == wallet1.get_account().get_public_address_str(true)); - ASSERT_TRUE(wallet0.get_account().get_public_address_str(true) == wallet2.get_account().get_public_address_str(true)); + ASSERT_TRUE(wallet0.get_account().get_public_address_str(cryptonote::TESTNET) == wallet1.get_account().get_public_address_str(cryptonote::TESTNET)); + ASSERT_TRUE(wallet0.get_account().get_public_address_str(cryptonote::TESTNET) == wallet2.get_account().get_public_address_str(cryptonote::TESTNET)); bool ready; uint32_t threshold, total; diff --git a/tests/unit_tests/ringct.cpp b/tests/unit_tests/ringct.cpp index 95b20f563..b7fcbbcab 100644 --- a/tests/unit_tests/ringct.cpp +++ b/tests/unit_tests/ringct.cpp @@ -132,7 +132,7 @@ TEST(ringct, MG_sigs) } sk[j] = xx[ind][j]; } - sk[2] = skGen();//asume we don't know one of the private keys.. + sk[2] = skGen();//assume we don't know one of the private keys.. IIccss = MLSAG_Gen(message, P, sk, NULL, NULL, ind, R, hw::get_device("default")); ASSERT_FALSE(MLSAG_Ver(message, P, IIccss, R)); } diff --git a/tests/unit_tests/serialization.cpp b/tests/unit_tests/serialization.cpp index 00bb9e49c..5a2114027 100644 --- a/tests/unit_tests/serialization.cpp +++ b/tests/unit_tests/serialization.cpp @@ -670,9 +670,9 @@ TEST(Serialization, serializes_ringct_types) TEST(Serialization, portability_wallet) { - const bool testnet = true; + const cryptonote::network_type nettype = cryptonote::TESTNET; const bool restricted = false; - tools::wallet2 w(testnet, restricted); + tools::wallet2 w(nettype, restricted); const boost::filesystem::path wallet_file = unit_test::data_dir / "wallet_9svHk1"; string password = "test"; bool r = false; @@ -914,7 +914,7 @@ TEST(Serialization, portability_unsigned_tx) { const boost::filesystem::path filename = unit_test::data_dir / "unsigned_monero_tx"; std::string s; - const bool testnet = true; + const cryptonote::network_type nettype = cryptonote::TESTNET; bool r = epee::file_io_utils::load_file_to_string(filename.string(), s); ASSERT_TRUE(r); const size_t magiclen = strlen(UNSIGNED_TX_PREFIX); @@ -992,15 +992,15 @@ TEST(Serialization, portability_unsigned_tx) ASSERT_TRUE(epee::string_tools::pod_to_hex(tse.mask) == "789bafff169ef206aa21219342c69ca52ce1d78d776c10b21d14bdd960fc7703"); // tcd.change_dts ASSERT_TRUE(tcd.change_dts.amount == 9631208773403); - ASSERT_TRUE(cryptonote::get_account_address_as_str(testnet, false, tcd.change_dts.addr) == "9svHk1wHPo3ULf2AZykghzcye6sitaRE4MaDjPC6uanTHCynHjJHZaiAb922PojE1GexhhRt1LVf5DC43feyrRZMLXQr3mk"); + ASSERT_TRUE(cryptonote::get_account_address_as_str(nettype, false, tcd.change_dts.addr) == "9svHk1wHPo3ULf2AZykghzcye6sitaRE4MaDjPC6uanTHCynHjJHZaiAb922PojE1GexhhRt1LVf5DC43feyrRZMLXQr3mk"); // tcd.splitted_dsts ASSERT_TRUE(tcd.splitted_dsts.size() == 2); auto& splitted_dst0 = tcd.splitted_dsts[0]; auto& splitted_dst1 = tcd.splitted_dsts[1]; ASSERT_TRUE(splitted_dst0.amount == 1400000000000); ASSERT_TRUE(splitted_dst1.amount == 9631208773403); - ASSERT_TRUE(cryptonote::get_account_address_as_str(testnet, false, splitted_dst0.addr) == "9xnhrMczQkPeoGi6dyu6BgKAYX4tZsDs6KHCkyTStDBKL4M4pM1gfCR3utmTAcSaKHGa1R5o266FbdnubErmij3oMdLyYgA"); - ASSERT_TRUE(cryptonote::get_account_address_as_str(testnet, false, splitted_dst1.addr) == "9svHk1wHPo3ULf2AZykghzcye6sitaRE4MaDjPC6uanTHCynHjJHZaiAb922PojE1GexhhRt1LVf5DC43feyrRZMLXQr3mk"); + ASSERT_TRUE(cryptonote::get_account_address_as_str(nettype, false, splitted_dst0.addr) == "9xnhrMczQkPeoGi6dyu6BgKAYX4tZsDs6KHCkyTStDBKL4M4pM1gfCR3utmTAcSaKHGa1R5o266FbdnubErmij3oMdLyYgA"); + ASSERT_TRUE(cryptonote::get_account_address_as_str(nettype, false, splitted_dst1.addr) == "9svHk1wHPo3ULf2AZykghzcye6sitaRE4MaDjPC6uanTHCynHjJHZaiAb922PojE1GexhhRt1LVf5DC43feyrRZMLXQr3mk"); // tcd.selected_transfers ASSERT_TRUE(tcd.selected_transfers.size() == 1); ASSERT_TRUE(tcd.selected_transfers.front() == 2); @@ -1013,7 +1013,7 @@ TEST(Serialization, portability_unsigned_tx) ASSERT_TRUE(tcd.dests.size() == 1); auto& dest = tcd.dests[0]; ASSERT_TRUE(dest.amount == 1400000000000); - ASSERT_TRUE(cryptonote::get_account_address_as_str(testnet, false, dest.addr) == "9xnhrMczQkPeoGi6dyu6BgKAYX4tZsDs6KHCkyTStDBKL4M4pM1gfCR3utmTAcSaKHGa1R5o266FbdnubErmij3oMdLyYgA"); + ASSERT_TRUE(cryptonote::get_account_address_as_str(nettype, false, dest.addr) == "9xnhrMczQkPeoGi6dyu6BgKAYX4tZsDs6KHCkyTStDBKL4M4pM1gfCR3utmTAcSaKHGa1R5o266FbdnubErmij3oMdLyYgA"); // transfers ASSERT_TRUE(exported_txs.transfers.size() == 3); auto& td0 = exported_txs.transfers[0]; @@ -1061,7 +1061,7 @@ TEST(Serialization, portability_unsigned_tx) TEST(Serialization, portability_signed_tx) { const boost::filesystem::path filename = unit_test::data_dir / "signed_monero_tx"; - const bool testnet = true; + const cryptonote::network_type nettype = cryptonote::TESTNET; std::string s; bool r = epee::file_io_utils::load_file_to_string(filename.string(), s); ASSERT_TRUE(r); @@ -1106,7 +1106,7 @@ TEST(Serialization, portability_signed_tx) ASSERT_FALSE(ptx.dust_added_to_fee); // ptx.change.{amount, addr} ASSERT_TRUE(ptx.change_dts.amount == 9631208773403); - ASSERT_TRUE(cryptonote::get_account_address_as_str(testnet, false, ptx.change_dts.addr) == "9svHk1wHPo3ULf2AZykghzcye6sitaRE4MaDjPC6uanTHCynHjJHZaiAb922PojE1GexhhRt1LVf5DC43feyrRZMLXQr3mk"); + ASSERT_TRUE(cryptonote::get_account_address_as_str(nettype, false, ptx.change_dts.addr) == "9svHk1wHPo3ULf2AZykghzcye6sitaRE4MaDjPC6uanTHCynHjJHZaiAb922PojE1GexhhRt1LVf5DC43feyrRZMLXQr3mk"); // ptx.selected_transfers ASSERT_TRUE(ptx.selected_transfers.size() == 1); ASSERT_TRUE(ptx.selected_transfers.front() == 2); @@ -1116,7 +1116,7 @@ TEST(Serialization, portability_signed_tx) // ptx.dests ASSERT_TRUE(ptx.dests.size() == 1); ASSERT_TRUE(ptx.dests[0].amount == 1400000000000); - ASSERT_TRUE(cryptonote::get_account_address_as_str(testnet, false, ptx.dests[0].addr) == "9xnhrMczQkPeoGi6dyu6BgKAYX4tZsDs6KHCkyTStDBKL4M4pM1gfCR3utmTAcSaKHGa1R5o266FbdnubErmij3oMdLyYgA"); + ASSERT_TRUE(cryptonote::get_account_address_as_str(nettype, false, ptx.dests[0].addr) == "9xnhrMczQkPeoGi6dyu6BgKAYX4tZsDs6KHCkyTStDBKL4M4pM1gfCR3utmTAcSaKHGa1R5o266FbdnubErmij3oMdLyYgA"); // ptx.construction_data auto& tcd = ptx.construction_data; ASSERT_TRUE(tcd.sources.size() == 1); @@ -1147,15 +1147,15 @@ TEST(Serialization, portability_signed_tx) ASSERT_TRUE(epee::string_tools::pod_to_hex(tse.mask) == "789bafff169ef206aa21219342c69ca52ce1d78d776c10b21d14bdd960fc7703"); // ptx.construction_data.change_dts ASSERT_TRUE(tcd.change_dts.amount == 9631208773403); - ASSERT_TRUE(cryptonote::get_account_address_as_str(testnet, false, tcd.change_dts.addr) == "9svHk1wHPo3ULf2AZykghzcye6sitaRE4MaDjPC6uanTHCynHjJHZaiAb922PojE1GexhhRt1LVf5DC43feyrRZMLXQr3mk"); + ASSERT_TRUE(cryptonote::get_account_address_as_str(nettype, false, tcd.change_dts.addr) == "9svHk1wHPo3ULf2AZykghzcye6sitaRE4MaDjPC6uanTHCynHjJHZaiAb922PojE1GexhhRt1LVf5DC43feyrRZMLXQr3mk"); // ptx.construction_data.splitted_dsts ASSERT_TRUE(tcd.splitted_dsts.size() == 2); auto& splitted_dst0 = tcd.splitted_dsts[0]; auto& splitted_dst1 = tcd.splitted_dsts[1]; ASSERT_TRUE(splitted_dst0.amount == 1400000000000); ASSERT_TRUE(splitted_dst1.amount == 9631208773403); - ASSERT_TRUE(cryptonote::get_account_address_as_str(testnet, false, splitted_dst0.addr) == "9xnhrMczQkPeoGi6dyu6BgKAYX4tZsDs6KHCkyTStDBKL4M4pM1gfCR3utmTAcSaKHGa1R5o266FbdnubErmij3oMdLyYgA"); - ASSERT_TRUE(cryptonote::get_account_address_as_str(testnet, false, splitted_dst1.addr) == "9svHk1wHPo3ULf2AZykghzcye6sitaRE4MaDjPC6uanTHCynHjJHZaiAb922PojE1GexhhRt1LVf5DC43feyrRZMLXQr3mk"); + ASSERT_TRUE(cryptonote::get_account_address_as_str(nettype, false, splitted_dst0.addr) == "9xnhrMczQkPeoGi6dyu6BgKAYX4tZsDs6KHCkyTStDBKL4M4pM1gfCR3utmTAcSaKHGa1R5o266FbdnubErmij3oMdLyYgA"); + ASSERT_TRUE(cryptonote::get_account_address_as_str(nettype, false, splitted_dst1.addr) == "9svHk1wHPo3ULf2AZykghzcye6sitaRE4MaDjPC6uanTHCynHjJHZaiAb922PojE1GexhhRt1LVf5DC43feyrRZMLXQr3mk"); // ptx.construction_data.selected_transfers ASSERT_TRUE(tcd.selected_transfers.size() == 1); ASSERT_TRUE(tcd.selected_transfers.front() == 2); @@ -1168,7 +1168,7 @@ TEST(Serialization, portability_signed_tx) ASSERT_TRUE(tcd.dests.size() == 1); auto& dest = tcd.dests[0]; ASSERT_TRUE(dest.amount == 1400000000000); - ASSERT_TRUE(cryptonote::get_account_address_as_str(testnet, false, dest.addr) == "9xnhrMczQkPeoGi6dyu6BgKAYX4tZsDs6KHCkyTStDBKL4M4pM1gfCR3utmTAcSaKHGa1R5o266FbdnubErmij3oMdLyYgA"); + ASSERT_TRUE(cryptonote::get_account_address_as_str(nettype, false, dest.addr) == "9xnhrMczQkPeoGi6dyu6BgKAYX4tZsDs6KHCkyTStDBKL4M4pM1gfCR3utmTAcSaKHGa1R5o266FbdnubErmij3oMdLyYgA"); // key_images ASSERT_TRUE(exported_txs.key_images.size() == 3); auto& ki0 = exported_txs.key_images[0]; diff --git a/tests/unit_tests/uri.cpp b/tests/unit_tests/uri.cpp index 1026cc85b..999c117c2 100644 --- a/tests/unit_tests/uri.cpp +++ b/tests/unit_tests/uri.cpp @@ -37,7 +37,7 @@ std::string address, payment_id, recipient_name, description, error; \ uint64_t amount; \ std::vector<std::string> unknown_parameters; \ - tools::wallet2 w(true); \ + tools::wallet2 w(cryptonote::TESTNET); \ bool ret = w.parse_uri(uri, address, payment_id, amount, description, recipient_name, unknown_parameters, error); \ ASSERT_EQ(ret, expected); diff --git a/translations/monero_fr.ts b/translations/monero_fr.ts index 37d7d5928..a52d1a11f 100644 --- a/translations/monero_fr.ts +++ b/translations/monero_fr.ts @@ -21,7 +21,7 @@ <message> <location filename="../src/wallet/api/address_book.cpp" line="77"/> <source>Integrated address and long payment ID can't be used at the same time</source> - <translation type="unfinished"></translation> + <translation>Adresse intégrée et ID de paiement long ne peuvent pas être utilisés en même temps</translation> </message> </context> <context> @@ -118,7 +118,7 @@ <message> <location filename="../src/wallet/api/unsigned_transaction.cpp" line="214"/> <source>Loaded %lu transactions, for %s, fee %s, %s, %s, with min ring size %lu. %s</source> - <translation type="unfinished"></translation> + <translation>%lu transactions chargées, pour %s, frais %s, %s, %s, taille de cercle minimum %lu, %s</translation> </message> </context> <context> @@ -155,18 +155,18 @@ <location filename="../src/wallet/api/wallet.cpp" line="1197"/> <location filename="../src/wallet/api/wallet.cpp" line="1301"/> <source>not enough outputs for specified ring size</source> - <translation type="unfinished"></translation> + <translation>pas assez de sorties pour la taille de cercle spécifiée</translation> </message> <message> <location filename="../src/wallet/api/wallet.cpp" line="1199"/> <location filename="../src/wallet/api/wallet.cpp" line="1303"/> <source>found outputs to use</source> - <translation type="unfinished"></translation> + <translation>sorties à utiliser trouvées</translation> </message> <message> <location filename="../src/wallet/api/wallet.cpp" line="1201"/> <source>Please sweep unmixable outputs.</source> - <translation type="unfinished"></translation> + <translation>Veuillez balayer les sorties non mélangeables.</translation> </message> <message> <location filename="../src/wallet/api/wallet.cpp" line="1267"/> @@ -227,7 +227,7 @@ <message> <location filename="../src/wallet/api/wallet.cpp" line="773"/> <source>Failed to send import wallet request</source> - <translation type="unfinished"></translation> + <translation>Échec de l'envoi de la requête d'importation de portefeuille</translation> </message> <message> <location filename="../src/wallet/api/wallet.cpp" line="919"/> @@ -252,7 +252,7 @@ <message> <location filename="../src/wallet/api/wallet.cpp" line="986"/> <source>Key images can only be imported with a trusted daemon</source> - <translation type="unfinished"></translation> + <translation>Les images de clé ne peuvent être importées qu'avec un démon de confiance</translation> </message> <message> <location filename="../src/wallet/api/wallet.cpp" line="999"/> @@ -262,12 +262,12 @@ <message> <location filename="../src/wallet/api/wallet.cpp" line="1032"/> <source>Failed to get subaddress label: </source> - <translation type="unfinished"></translation> + <translation>Échec de la récupération de l'étiquette de sous-adresse : </translation> </message> <message> <location filename="../src/wallet/api/wallet.cpp" line="1046"/> <source>Failed to set subaddress label: </source> - <translation type="unfinished"></translation> + <translation>Échec de l'affectation de l'étiquette de sous-adresse : </translation> </message> <message> <location filename="../src/wallet/api/wallet.cpp" line="1163"/> @@ -278,7 +278,7 @@ <location filename="../src/wallet/api/wallet.cpp" line="1179"/> <location filename="../src/wallet/api/wallet.cpp" line="1283"/> <source>not enough money to transfer, overall balance only %s, sent amount %s</source> - <translation type="unfinished"></translation> + <translation>pas assez de fonds pour le transfer, solde global disponible %s, montant envoyé %s</translation> </message> <message> <location filename="../src/wallet/api/wallet.cpp" line="1188"/> @@ -348,18 +348,18 @@ <location filename="../src/wallet/api/wallet.cpp" line="1556"/> <location filename="../src/wallet/api/wallet.cpp" line="1579"/> <source>Failed to parse txid</source> - <translation type="unfinished"></translation> + <translation>Échec de l'analyse de l'ID de transaction</translation> </message> <message> <location filename="../src/wallet/api/wallet.cpp" line="1430"/> <source>no tx keys found for this txid</source> - <translation type="unfinished">aucune clé de transaction trouvée pour cet ID de transaction</translation> + <translation>aucune clé de transaction trouvée pour cet ID de transaction</translation> </message> <message> <location filename="../src/wallet/api/wallet.cpp" line="1450"/> <location filename="../src/wallet/api/wallet.cpp" line="1460"/> <source>Failed to parse tx key</source> - <translation type="unfinished"></translation> + <translation>Échec de l'analyse de la clé de transaction</translation> </message> <message> <location filename="../src/wallet/api/wallet.cpp" line="1470"/> @@ -367,12 +367,12 @@ <location filename="../src/wallet/api/wallet.cpp" line="1533"/> <location filename="../src/wallet/api/wallet.cpp" line="1621"/> <source>Failed to parse address</source> - <translation type="unfinished">Échec de l'analyse de l'adresse</translation> + <translation>Échec de l'analyse de l'adresse</translation> </message> <message> <location filename="../src/wallet/api/wallet.cpp" line="1627"/> <source>Address must not be a subaddress</source> - <translation type="unfinished"></translation> + <translation>L'adresse ne doit pas être une sous-adresse</translation> </message> <message> <location filename="../src/wallet/api/wallet.cpp" line="1849"/> @@ -413,7 +413,7 @@ <message> <location filename="../src/common/command_line.cpp" line="71"/> <source>no</source> - <translation type="unfinished"></translation> + <translation>non</translation> </message> </context> <context> @@ -436,7 +436,7 @@ <message> <location filename="../src/rpc/rpc_args.cpp" line="43"/> <source>Specify a comma separated list of origins to allow cross origin resource sharing</source> - <translation type="unfinished"></translation> + <translation>Spécifier une liste d'origines séparées par des virgules pour autoriser le partage de ressource de différentes origines (CORS)</translation> </message> <message> <location filename="../src/rpc/rpc_args.cpp" line="70"/> @@ -462,7 +462,7 @@ <message> <location filename="../src/rpc/rpc_args.cpp" line="105"/> <source> requires RFC server password --</source> - <translation type="unfinished"></translation> + <translation> nécessite le mot de passe du serveur RPC --</translation> </message> </context> <context> @@ -541,7 +541,7 @@ <location filename="../src/simplewallet/simplewallet.cpp" line="2041"/> <source>NOTE: the following 25 words can be used to recover access to your wallet. 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>VEUILLEZ NOTER : les 25 mots suivants peuvent être utilisés pour restaurer votre portefeuille. Veuillez les écrire sur papier et les garder dans un endroit sûr. Ne les gardez pas dans un courriel ou dans un service de stockage de fichiers hors de votre contrôle. + <translation>VEUILLEZ NOTER : les 25 mots suivants peuvent être utilisés pour restaurer votre portefeuille. Veuillez les écrire sur papier et les garder dans un endroit sûr. Ne les gardez pas dans un courriel ou dans un service de stockage de fichiers hors de votre contrôle. </translation> </message> <message> @@ -572,7 +572,7 @@ <message> <location filename="../src/simplewallet/simplewallet.cpp" line="2662"/> <source>List of available languages for your wallet's seed:</source> - <translation>Liste des langues disponibles pour la graine de votre portefeuille :</translation> + <translation>Liste des langues disponibles pour la phrase mnémonique de votre portefeuille :</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="2671"/> @@ -583,7 +583,7 @@ <location filename="../src/simplewallet/simplewallet.cpp" line="2737"/> <source>You had been using a deprecated version of the wallet. Please use the new seed that we provide. </source> - <translation>Vous avez utilisé une version obsolète du portefeuille. Veuillez dorénavant utiliser la nouvelle graine que nous fournissons. + <translation>Vous avez utilisé une version obsolète du portefeuille. Veuillez dorénavant utiliser la nouvelle phrase mnémonique que nous fournissons. </translation> </message> <message> @@ -643,22 +643,22 @@ <message> <location filename="../src/simplewallet/simplewallet.cpp" line="3072"/> <source>Mining started in daemon</source> - <translation>L'extraction minière dans le démon a démarré</translation> + <translation>La mine a démarré dans le démon</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="3074"/> <source>mining has NOT been started: </source> - <translation>l'extraction minière n'a PAS démarré : </translation> + <translation>la mine n'a PAS démarré : </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="3093"/> <source>Mining stopped in daemon</source> - <translation>L'extraction minière dans le démon a été stoppée</translation> + <translation>La mine a été stoppée dans le démon</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="3095"/> <source>mining has NOT been stopped: </source> - <translation>l'extraction minière n'a PAS été stoppée : </translation> + <translation>la mine n'a PAS été stoppée : </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="3150"/> @@ -739,43 +739,46 @@ <location filename="../src/simplewallet/simplewallet.cpp" line="3895"/> <location filename="../src/simplewallet/simplewallet.cpp" line="3905"/> <source>Is this okay anyway? (Y/Yes/N/No): </source> - <translation type="unfinished"></translation> + <translation>Est-ce correct quand même ? (Y/Yes/Oui/N/No/Non) : </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="3900"/> <source>There is currently a %u block backlog at that fee level. Is this okay? (Y/Yes/N/No): </source> - <translation type="unfinished"></translation> + <translation>Il y a actuellement un arriéré de %u blocs à ce niveau de frais. Est-ce correct quand même ? (Y/Yes/Oui/N/No/Non) : </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="3905"/> <source>Failed to check for backlog: </source> - <translation type="unfinished"></translation> + <translation>Échec de la vérification du backlog : </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="3946"/> <location filename="../src/simplewallet/simplewallet.cpp" line="4302"/> <source> Transaction </source> - <translation type="unfinished"></translation> + <translation> +Transaction </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="3951"/> <location filename="../src/simplewallet/simplewallet.cpp" line="4307"/> <source>Spending from address index %d </source> - <translation type="unfinished"></translation> + <translation>Dépense depuis l'adresse d'index %d +</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="3953"/> <location filename="../src/simplewallet/simplewallet.cpp" line="4309"/> <source>WARNING: Outputs of multiple addresses are being used together, which might potentially compromise your privacy. </source> - <translation type="unfinished"></translation> + <translation>ATTENTION : Des sorties de multiples adresses sont utilisées ensemble, ce qui pourrait potentiellement compromettre votre confidentialité. +</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="3955"/> <source>Sending %s. </source> - <translation>Envoi de %s. </translation> + <translation>Envoi de %s. </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="3958"/> @@ -846,32 +849,32 @@ Cette transaction sera déverrouillée au bloc %llu, dans approximativement %s j <message> <location filename="../src/simplewallet/simplewallet.cpp" line="4424"/> <source>failed to parse Payment ID</source> - <translation type="unfinished"></translation> + <translation>échec de l'analyse de l'ID de paiement</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="4440"/> <source>usage: sweep_single [<priority>] [<ring_size>] <key_image> <address> [<payment_id>]</source> - <translation type="unfinished"></translation> + <translation>usage : sweep_single [<priorité>] [<taille_cercle>] <image_clé> <adresse> [<ID_paiement>]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="4447"/> <source>failed to parse key image</source> - <translation type="unfinished"></translation> + <translation>échec de l'analyse de l'image de clé</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="4499"/> <source>No outputs found</source> - <translation type="unfinished"></translation> + <translation>Pas de sorties trouvées</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="4504"/> <source>Multiple transactions are created, which is not supposed to happen</source> - <translation type="unfinished"></translation> + <translation>De multiples transactions sont crées, ce qui n'est pas supposé arriver</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="4509"/> <source>The transaction uses multiple or no inputs, which is not supposed to happen</source> - <translation type="unfinished"></translation> + <translation>La transaction utilise aucune ou de multiples entrées, ce qui n'est pas supposé arriver</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="4586"/> @@ -886,12 +889,12 @@ Cette transaction sera déverrouillée au bloc %llu, dans approximativement %s j <message> <location filename="../src/simplewallet/simplewallet.cpp" line="4601"/> <source>donations are not enabled on the testnet</source> - <translation type="unfinished"></translation> + <translation>les dons ne sont pas activés sur le réseau testnet</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="4608"/> <source>usage: donate [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <amount> [<payment_id>]</source> - <translation type="unfinished"></translation> + <translation>usage : donate [index=<N1>[,<N2>,...]] [<priorité>] [<taille_cercle>] <montant> [<ID_paiement>]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="4702"/> @@ -911,7 +914,7 @@ Cette transaction sera déverrouillée au bloc %llu, dans approximativement %s j <message> <location filename="../src/simplewallet/simplewallet.cpp" line="4748"/> <source> dummy output(s)</source> - <translation type="unfinished"></translation> + <translation> sortie(s) factice(s)</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="4751"/> @@ -921,17 +924,17 @@ Cette transaction sera déverrouillée au bloc %llu, dans approximativement %s j <message> <location filename="../src/simplewallet/simplewallet.cpp" line="4763"/> <source>Loaded %lu transactions, for %s, fee %s, %s, %s, with min ring size %lu, %s. %sIs this okay? (Y/Yes/N/No): </source> - <translation type="unfinished"></translation> + <translation>%lu transactions chargées, pour %s, frais %s, %s, %s, taille de cercle minimum %lu, %s. %sEst-ce correct ? (Y/Yes/Oui/N/No/Non) : </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="4787"/> <source>This is a multisig wallet, it can only sign with sign_multisig</source> - <translation type="unfinished"></translation> + <translation>Ceci est un portefeuille multisig, il ne peut signer qu'avec sign_multisig</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="4797"/> <source>usage: sign_transfer [export]</source> - <translation type="unfinished"></translation> + <translation>usage : sign_transfer [export]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="4809"/> @@ -946,7 +949,7 @@ Cette transaction sera déverrouillée au bloc %llu, dans approximativement %s j <message> <location filename="../src/simplewallet/simplewallet.cpp" line="4836"/> <source>Transaction raw hex data exported to </source> - <translation type="unfinished"></translation> + <translation>Données brutes hex de la transaction exportées vers </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="4852"/> @@ -1100,177 +1103,177 @@ Cette transaction sera déverrouillée au bloc %llu, dans approximativement %s j <message> <location filename="../src/simplewallet/simplewallet.cpp" line="219"/> <source>false</source> - <translation type="unfinished"></translation> + <translation>faux</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="493"/> <source>Unknown command: </source> - <translation type="unfinished"></translation> + <translation>Commande inconnue : </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="500"/> <source>Command usage: </source> - <translation type="unfinished"></translation> + <translation>Usage de la commande : </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="503"/> <source>Command description: </source> - <translation type="unfinished"></translation> + <translation>Description de la commande : </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="551"/> <source>wallet is multisig but not yet finalized</source> - <translation type="unfinished"></translation> + <translation>le portefeuille est multisig mais pas encore finalisé</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="567"/> <source>Enter optional seed encryption passphrase, empty to see raw seed</source> - <translation type="unfinished"></translation> + <translation>Entrer une phrase de passe facultative pour le chiffrement de la phrase mnémonique, effacer pour voir la phrase mnémonique brute</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="584"/> <source>Failed to retrieve seed</source> - <translation type="unfinished"></translation> + <translation>Échec de la récupération de la phrase mnémonique</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="603"/> <source>wallet is multisig and has no seed</source> - <translation type="unfinished"></translation> + <translation>le portefeuille est multisig et n'a pas de phrase mnémonique</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="674"/> <source>Cannot connect to daemon</source> - <translation type="unfinished"></translation> + <translation>Impossible de se connecter au démon</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="679"/> <source>Current fee is %s monero per kB</source> - <translation type="unfinished"></translation> + <translation>Les frais sont actuellement de %s monero par kO</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="695"/> <source>Error: failed to estimate backlog array size: </source> - <translation type="unfinished"></translation> + <translation>Erreur : échec de l'estimation de la taille du tableau d'arriéré : </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="700"/> <source>Error: bad estimated backlog array size</source> - <translation type="unfinished"></translation> + <translation>Erreur : mauvaise estimation de la taille du tableau d'arriéré</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="712"/> <source> (current)</source> - <translation type="unfinished"></translation> + <translation> (actuel)</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="715"/> <source>%u block (%u minutes) backlog at priority %u%s</source> - <translation type="unfinished"></translation> + <translation>arriéré de %u bloc(s) (%u minutes) à la priorité %u%s</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="717"/> <source>%u to %u block (%u to %u minutes) backlog at priority %u</source> - <translation type="unfinished"></translation> + <translation>arriéré de %u à %u bloc(s) (%u à %u minutes) à la priorité %u</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="720"/> <source>No backlog at priority </source> - <translation type="unfinished"></translation> + <translation>Pas d'arriéré à la priorité </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="729"/> <location filename="../src/simplewallet/simplewallet.cpp" line="762"/> <source>This wallet is already multisig</source> - <translation type="unfinished"></translation> + <translation>Le portefeuille est déjà multisig</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="734"/> <location filename="../src/simplewallet/simplewallet.cpp" line="767"/> <source>wallet is watch-only and cannot be made multisig</source> - <translation type="unfinished"></translation> + <translation>c'est un portefeuille d'audit et il ne peut pas être tranformé en multisig</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="740"/> <location filename="../src/simplewallet/simplewallet.cpp" line="773"/> <source>This wallet has been used before, please use a new wallet to create a multisig wallet</source> - <translation type="unfinished"></translation> + <translation>Ce portefeuille a été utilisé auparavant, veuillez utiliser un nouveau portefeuille pour créer un portefeuille multisig</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="747"/> <source>Your password is incorrect.</source> - <translation type="unfinished"></translation> + <translation>Votre mot de passe est incorrect.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="753"/> <source>Send this multisig info to all other participants, then use make_multisig <threshold> <info1> [<info2>...] with others' multisig info</source> - <translation type="unfinished"></translation> + <translation>Envoyez ces infos multisig à tous les autres participants, ensuite utilisez make_multisig <seuil> <info1> [<info2>...] avec les infos multisig des autres</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="754"/> <source>This includes the PRIVATE view key, so needs to be disclosed only to that multisig wallet's participants </source> - <translation type="unfinished"></translation> + <translation>Ceci inclut la clé PRIVÉE d'audit, donc ne doit être divulgué qu'aux participants de ce portefeuille multisig </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="786"/> <source>usage: make_multisig <threshold> <multisiginfo1> [<multisiginfo2>...]</source> - <translation type="unfinished"></translation> + <translation>usage : make_multisig <seuil> <multisiginfo1> [<multisiginfo2>...]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="794"/> <source>Invalid threshold</source> - <translation type="unfinished"></translation> + <translation>Seuil invalide</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="807"/> <source>Another step is needed</source> - <translation type="unfinished"></translation> + <translation>Une autre étape est nécessaire</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="809"/> <source>Send this multisig info to all other participants, then use finalize_multisig <info1> [<info2>...] with others' multisig info</source> - <translation type="unfinished"></translation> + <translation>Envoyez ces infos multisig à tous les autres participants, ensuite utilisez finalize_multisig <info1> [<info2>...] avec les infos multisig des autres</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="815"/> <source>Error creating multisig: </source> - <translation type="unfinished"></translation> + <translation>Erreur de création multisig : </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="822"/> <source>Error creating multisig: new wallet is not multisig</source> - <translation type="unfinished"></translation> + <translation>Erreur de création multisig : le nouveau portefeuille n'est pas multisig</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="825"/> <source> multisig address: </source> - <translation type="unfinished"></translation> + <translation> adresse multisig : </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="836"/> <location filename="../src/simplewallet/simplewallet.cpp" line="880"/> <location filename="../src/simplewallet/simplewallet.cpp" line="927"/> <source>This wallet is not multisig</source> - <translation type="unfinished"></translation> + <translation>Ce portefeuille n'est pas multisig</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="841"/> <source>This wallet is already finalized</source> - <translation type="unfinished"></translation> + <translation>Ce portefeuille est déjà finalisé</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="854"/> <source>usage: finalize_multisig <multisiginfo1> [<multisiginfo2>...]</source> - <translation type="unfinished"></translation> + <translation>usage : finalize_multisig <multisiginfo1> [<multisiginfo2>...]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="862"/> <source>Failed to finalize multisig</source> - <translation type="unfinished"></translation> + <translation>Échec de finalisation multisig</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="868"/> <source>Failed to finalize multisig: </source> - <translation type="unfinished"></translation> + <translation>Échec de finalisation multisig : </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="885"/> @@ -1279,310 +1282,310 @@ Cette transaction sera déverrouillée au bloc %llu, dans approximativement %s j <location filename="../src/simplewallet/simplewallet.cpp" line="1074"/> <location filename="../src/simplewallet/simplewallet.cpp" line="1136"/> <source>This multisig wallet is not yet finalized</source> - <translation type="unfinished"></translation> + <translation>Ce portefeuille multisig n'est pas encore finalisé</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="890"/> <source>usage: export_multisig_info <filename></source> - <translation type="unfinished"></translation> + <translation>usage : export_multisig_info <nom_fichier></translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="913"/> <source>Error exporting multisig info: </source> - <translation type="unfinished"></translation> + <translation>Erreur d'importation des infos multisig : </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="917"/> <source>Multisig info exported to </source> - <translation type="unfinished"></translation> + <translation>Infos multisig exportées vers </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="937"/> <source>usage: import_multisig_info <filename1> [<filename2>...] - one for each other participant</source> - <translation type="unfinished"></translation> + <translation>usage : import_multisig_info <nom_fichier1> [<nom_fichier2>...] - un pour chaque autre participant</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="965"/> <source>Multisig info imported</source> - <translation type="unfinished"></translation> + <translation>Infos multisig importées</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="969"/> <source>Failed to import multisig info: </source> - <translation type="unfinished"></translation> + <translation>Échec de l'importation des infos multisig : </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="980"/> <source>Failed to update spent status after importing multisig info: </source> - <translation type="unfinished"></translation> + <translation>Échec de la mise à jour de l'état des dépenses après l'importation des infos multisig : </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="985"/> <source>Untrusted daemon, spent status may be incorrect. Use a trusted daemon and run "rescan_spent"</source> - <translation type="unfinished"></translation> + <translation>Pas un démon de confiance, l'état des dépenses peut être incorrect. Utilisez un démon de confiance et executez "rescan_spent"</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1001"/> <location filename="../src/simplewallet/simplewallet.cpp" line="1069"/> <location filename="../src/simplewallet/simplewallet.cpp" line="1131"/> <source>This is not a multisig wallet</source> - <translation type="unfinished"></translation> + <translation>Ceci n'est pas un portefeuille multisig</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1011"/> <source>usage: sign_multisig <filename></source> - <translation type="unfinished"></translation> + <translation>usage : sign_multisig <nom_fichier></translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1024"/> <source>Failed to sign multisig transaction</source> - <translation type="unfinished"></translation> + <translation>Échec de la signature de la transaction multisig</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1030"/> <source>Multisig error: </source> - <translation type="unfinished"></translation> + <translation>Erreur multisig : </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1035"/> <source>Failed to sign multisig transaction: </source> - <translation type="unfinished"></translation> + <translation>Échec de la signature de la transaction multisig : </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1058"/> <source>It may be relayed to the network with submit_multisig</source> - <translation type="unfinished"></translation> + <translation>Elle peut être transmise au réseau avec submit_multisig</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1079"/> <source>usage: submit_multisig <filename></source> - <translation type="unfinished"></translation> + <translation>usage : submit_multisig <nom_fichier></translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1094"/> <location filename="../src/simplewallet/simplewallet.cpp" line="1155"/> <source>Failed to load multisig transaction from file</source> - <translation type="unfinished"></translation> + <translation>Échec du chargement de la transaction multisig du fichier</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1099"/> <location filename="../src/simplewallet/simplewallet.cpp" line="1160"/> <source>Multisig transaction signed by only %u signers, needs %u more signatures</source> - <translation type="unfinished"></translation> + <translation>Transaction multisig signée par %u signataire(s) seulement, nécessite %u signature(s) de plus</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1108"/> <location filename="../src/simplewallet/simplewallet.cpp" line="6750"/> <source>Transaction successfully submitted, transaction </source> - <translation type="unfinished"></translation> + <translation>Transaction transmise avec succès, transaction </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1109"/> <location filename="../src/simplewallet/simplewallet.cpp" line="6751"/> <source>You can check its status by using the `show_transfers` command.</source> - <translation type="unfinished"></translation> + <translation>Vous pouvez vérifier son statut en utilisant la commane 'show_transfers'.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1141"/> <source>usage: export_raw_multisig <filename></source> - <translation type="unfinished"></translation> + <translation>usage : export_raw_multisig <nom_fichier></translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1176"/> <source>Failed to export multisig transaction to file </source> - <translation type="unfinished"></translation> + <translation>Échec de l'exportation de la transaction multisig vers le fichier </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1180"/> <source>Saved exported multisig transaction file(s): </source> - <translation type="unfinished"></translation> + <translation>Transaction multisig enregistrée dans le(s) fichier(s) : </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1252"/> <location filename="../src/simplewallet/simplewallet.cpp" line="1258"/> <location filename="../src/simplewallet/simplewallet.cpp" line="1272"/> <source>ring size must be an integer >= </source> - <translation type="unfinished"></translation> + <translation>la taille de cercle doit être un nombre entier >= </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1277"/> <source>could not change default ring size</source> - <translation type="unfinished"></translation> + <translation>échec du changement de la taille de cercle par défaut</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1518"/> <source>Invalid height</source> - <translation type="unfinished"></translation> + <translation>Hauteur invalide</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1564"/> <source>start_mining [<number_of_threads>] [bg_mining] [ignore_battery]</source> - <translation type="unfinished"></translation> + <translation>start_mining [<nombre_de_threads>] [mine_arrière_plan] [ignorer_batterie]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1565"/> <source>Start mining in the daemon (bg_mining and ignore_battery are optional booleans).</source> - <translation type="unfinished"></translation> + <translation>Démarrer la mine dans le démon (mine_arrière_plan et ignorer_batterie sont des booléens facultatifs).</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1568"/> <source>Stop mining in the daemon.</source> - <translation type="unfinished"></translation> + <translation>Arrêter la mine dans le démon.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1571"/> <source>set_daemon <host>[:<port>]</source> - <translation type="unfinished"></translation> + <translation>set_daemon <hôte>[:<port>]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1572"/> <source>Set another daemon to connect to.</source> - <translation type="unfinished"></translation> + <translation>Spécifier un autre démon auquel se connecter.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1575"/> <source>Save the current blockchain data.</source> - <translation type="unfinished"></translation> + <translation>Sauvegarder les données actuelles de la châine de blocs.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1578"/> <source>Synchronize the transactions and balance.</source> - <translation type="unfinished"></translation> + <translation>Synchroniser les transactions et le solde.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1581"/> <source>balance [detail]</source> - <translation type="unfinished"></translation> + <translation>solde [détail]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1582"/> <source>Show the wallet's balance of the currently selected account.</source> - <translation type="unfinished"></translation> + <translation>Afficher le solde du compte actuellement sélectionné.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1585"/> <source>incoming_transfers [available|unavailable] [verbose] [index=<N1>[,<N2>[,...]]]</source> - <translation type="unfinished"></translation> + <translation>incoming_transfers [available|unavailable] [verbose] [index=<N1>[,<N2>[,...]]]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1586"/> <source>Show the incoming transfers, all or filtered by availability and address index.</source> - <translation type="unfinished"></translation> + <translation>Afficher les transferts entrants, tous ou filtrés par disponibilité et index d'adresse.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1589"/> <source>payments <PID_1> [<PID_2> ... <PID_N>]</source> - <translation type="unfinished"></translation> + <translation>payments <PID_1> [<PID_2> ... <PID_N>]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1590"/> <source>Show the payments for the given payment IDs.</source> - <translation type="unfinished"></translation> + <translation>Afficher les paiements pour les IDs de paiement donnés.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1593"/> <source>Show the blockchain height.</source> - <translation type="unfinished"></translation> + <translation>Afficher la hauteur de la chaîne de blocs.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1596"/> <source>transfer_original [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <address> <amount> [<payment_id>]</source> - <translation type="unfinished"></translation> + <translation>transfer_original [index=<N1>[,<N2>,...]] [<priorité>] [<taille_cercle>] <adresse> <montant> [<ID_paiement>]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1597"/> <source>Transfer <amount> to <address> using an older transaction building algorithm. If the parameter "index=<N1>[,<N2>,...]" is specified, the wallet uses outputs received by addresses of those indices. If omitted, the wallet randomly chooses address indices to be used. In any case, it tries its best not to combine outputs across multiple addresses. <priority> is the priority of the transaction. The higher the priority, the higher the transaction fee. Valid values in priority order (from lowest to highest) are: unimportant, normal, elevated, priority. If omitted, the default value (see the command "set priority") is used. <ring_size> is the number of inputs to include for untraceability. Multiple payments can be made at once by adding <address_2> <amount_2> etcetera (before the payment ID, if it's included)</source> - <translation type="unfinished"></translation> + <translation>Transférer <montant> à <adresse> en utilisant un algorithme de construction de transaction plus ancien. Si le paramètre "index=<N1>[,<N2>,...]" est spécifié, le portefeuille utilise les sorties reçues par les adresses de ces indices. Si il est omis, le portefeuille choisit les indices d'adresse à utiliser aléatoirement. Dans tous les cas, il essaye de ne pas combiner des sorties de multiples adresses. <priorité> est la priorité de la transaction. Plus la priorité est haute, plus les frais de transaction sont élévés. Les valeurs valides par ordre de priorité (de la plus basse à la plus haute) sont : unimportant, normal, elevated, priority. Si elle est omise, la valeur par défaut (voir la commande "set priority") est utilisée. <taille_cercle> est le nombre d'entrées à inclure pour l'intraçabilité. De multiples paiements peuvent être réalisés d'un coup en ajoutant <adresse_2> <montant_2> et cetera (avant l'ID de paiement, si il est inclus)</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1599"/> <source>transfer [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <address> <amount> [<payment_id>]</source> - <translation type="unfinished"></translation> + <translation>transfer [index=<N1>[,<N2>,...]] [<priorité>] [<taille_cercle>] <adresse> <montant> [<ID_paiement>]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1600"/> <source>Transfer <amount> to <address>. If the parameter "index=<N1>[,<N2>,...]" is specified, the wallet uses outputs received by addresses of those indices. If omitted, the wallet randomly chooses address indices to be used. In any case, it tries its best not to combine outputs across multiple addresses. <priority> is the priority of the transaction. The higher the priority, the higher the transaction fee. Valid values in priority order (from lowest to highest) are: unimportant, normal, elevated, priority. If omitted, the default value (see the command "set priority") is used. <ring_size> is the number of inputs to include for untraceability. Multiple payments can be made at once by adding <address_2> <amount_2> etcetera (before the payment ID, if it's included)</source> - <translation type="unfinished"></translation> + <translation>Transférer <montant> à <adresse> Si le paramètre "index=<N1>[,<N2>,...]" est spécifié, le portefeuille utilise les sorties reçues par les adresses de ces indices. Si il est omis, le portefeuille choisit les indices d'adresse à utiliser aléatoirement. Dans tous les cas, il essaye de ne pas combiner des sorties de multiples adresses. <priorité> est la priorité de la transaction. Plus la priorité est haute, plus les frais de transaction sont élévés. Les valeurs valides par ordre de priorité (de la plus basse à la plus haute) sont : unimportant, normal, elevated, priority. Si elle est omise, la valeur par défaut (voir la commande "set priority") est utilisée. <taille_cercle> est le nombre d'entrées à inclure pour l'intraçabilité. De multiples paiements peuvent être réalisés d'un coup en ajoutant <adresse_2> <montant_2> et cetera (avant l'ID de paiement, si il est inclus)</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1603"/> <source>locked_transfer [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <addr> <amount> <lockblocks> [<payment_id>]</source> - <translation type="unfinished"></translation> + <translation>locked_transfer [index=<N1>[,<N2>,...]] [<priorité>] [<taille_cercle>] <adresse> <montant> <blocs_verrou> [<ID_paiement>]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1604"/> <source>Transfer <amount> to <address> and lock it for <lockblocks> (max. 1000000). If the parameter "index=<N1>[,<N2>,...]" is specified, the wallet uses outputs received by addresses of those indices. If omitted, the wallet randomly chooses address indices to be used. In any case, it tries its best not to combine outputs across multiple addresses. <priority> is the priority of the transaction. The higher the priority, the higher the transaction fee. Valid values in priority order (from lowest to highest) are: unimportant, normal, elevated, priority. If omitted, the default value (see the command "set priority") is used. <ring_size> is the number of inputs to include for untraceability. Multiple payments can be made at once by adding <address_2> <amount_2> etcetera (before the payment ID, if it's included)</source> - <translation type="unfinished"></translation> + <translation>Transférer <montant> à <adresse> et le verrouiller pendant <blocs_verrou> (max 1000000). Si le paramètre "index=<N1>[,<N2>,...]" est spécifié, le portefeuille utilise les sorties reçues par les adresses de ces indices. Si il est omis, le portefeuille choisit les indices d'adresse à utiliser aléatoirement. Dans tous les cas, il essaye de ne pas combiner des sorties de multiples adresses. <priorité> est la priorité de la transaction. Plus la priorité est haute, plus les frais de transaction sont élévés. Les valeurs valides par ordre de priorité (de la plus basse à la plus haute) sont : unimportant, normal, elevated, priority. Si elle est omise, la valeur par défaut (voir la commande "set priority") est utilisée. <taille_cercle> est le nombre d'entrées à inclure pour l'intraçabilité. De multiples paiements peuvent être réalisés d'un coup en ajoutant <adresse_2> <montant_2> et cetera (avant l'ID de paiement, si il est inclus)</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1607"/> <source>Send all unmixable outputs to yourself with ring_size 1</source> - <translation type="unfinished"></translation> + <translation>Envoyer toutes les sorties non mélangeables à vous-même avec une taille de cercle de 1</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1609"/> <source>sweep_all [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <address> [<payment_id>]</source> - <translation type="unfinished"></translation> + <translation>sweep_all [index=<N1>[,<N2>,...]] [<priorité>] [<taille_cercle>] <adresse> [<ID_paiement>]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1610"/> <source>Send all unlocked balance to an address. If the parameter "index<N1>[,<N2>,...]" is specified, the wallet sweeps outputs received by those address indices. If omitted, the wallet randomly chooses an address index to be used.</source> - <translation type="unfinished"></translation> + <translation>Envoyer tout le solde débloqué à une adresse. Si le paramètre "index<N1>[,<N2>,...]" est spécifié, le portefeuille balaye les sorties reçues par ces indices d'adresse. Si il est omis, le portefeuille choisit un index d'adresse à utiliser aléatoirement.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1613"/> <source>sweep_below <amount_threshold> [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <address> [<payment_id>]</source> - <translation type="unfinished"></translation> + <translation>sweep_below <montant_seuil> [index=<N1>[,<N2>,...]] [<priorité>] [<taille_cercle>] <adresse> [<ID_paiement>]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1614"/> <source>Send all unlocked outputs below the threshold to an address.</source> - <translation type="unfinished"></translation> + <translation>Envoyer toutes les sorties débloquées d'un montant inférieur au seuil à une adresse.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1617"/> <source>sweep_single [<priority>] [<ring_size>] <key_image> <address> [<payment_id>]</source> - <translation type="unfinished"></translation> + <translation>sweep_single [<priorité>] [<taille_cercle>] <image_clé> <adresse> [<ID_payment>]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1618"/> <source>Send a single output of the given key image to an address without change.</source> - <translation type="unfinished"></translation> + <translation>Envoyer une unique sortie ayant une image de clé donnée à une adresse sans rendu de monnaie.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1621"/> <source>donate [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <amount> [<payment_id>]</source> - <translation type="unfinished"></translation> + <translation>donate [index=<N1>[,<N2>,...]] [<priorité>] [<taille_cercle>] <montant> [<ID_paiement>]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1622"/> <source>Donate <amount> to the development team (donate.getmonero.org).</source> - <translation type="unfinished"></translation> + <translation>Donner <montant> à l'équipe de développement (donate.getmonero.org).</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1625"/> <source>sign_transfer <file></source> - <translation type="unfinished"></translation> + <translation>sign_transfer <fichier></translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1626"/> <source>Sign a transaction from a <file>.</source> - <translation type="unfinished"></translation> + <translation>Signer une transaction d'un <fichier>.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1629"/> <source>Submit a signed transaction from a file.</source> - <translation type="unfinished"></translation> + <translation>Transmettre une transaction signée d'un fichier.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1632"/> <source>set_log <level>|{+,-,}<categories></source> - <translation type="unfinished"></translation> + <translation>set_log <niveau>|{+,-,}<catégories></translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1633"/> <source>Change the current log detail (level must be <0-4>).</source> - <translation type="unfinished"></translation> + <translation>Changer le niveau de détail du journal (le niveau doit être <0-4>).</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1636"/> @@ -1593,7 +1596,13 @@ Cette transaction sera déverrouillée au bloc %llu, dans approximativement %s j account tag <tag_name> <account_index_1> [<account_index_2> ...] account untag <account_index_1> [<account_index_2> ...] account tag_description <tag_name> <description></source> - <translation type="unfinished"></translation> + <translation>account + account new <texte étiquette avec espaces autorisés> + account switch <index> + account label <index> <texte étiquette avec espaces autorisés> + account tag <mot_clé> <index_compte_1> [<index_compte_2> ...] + account untag <index_compte_1> [<index_compte_2> ...] + account tag_description <mot_clé> <description></translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1643"/> @@ -1604,67 +1613,73 @@ If the "label" argument is specified, the wallet sets the label of the If the "tag" argument is specified, a tag <tag_name> is assigned to the specified accounts <account_index_1>, <account_index_2>, .... If the "untag" argument is specified, the tags assigned to the specified accounts <account_index_1>, <account_index_2> ..., are removed. If the "tag_description" argument is specified, the tag <tag_name> is assigned an arbitrary text <description>.</source> - <translation type="unfinished"></translation> + <translation>Si aucun argument n'est spécifié, le portefeuille affiche tous les comptes existants ainsi que leurs soldes. +Si l'argument "new" est spécifié, le portefeuille crée un nouveau compte avec son étiquette initialisée par le texte fourni (qui peut être vide). +Si l'argument "switch" est spécifié, le portefeuille passe au compte spécifié par <index>. +Si l'argument "label" est spécifié, le portefeuille affecte le texte fourni à l'étiquette du compte spécifié par <index>. +Si l'argument "tag" est spécifié, un mot clé <mot_clé> est assigné aux comptes spécifiés <account_index_1>, <account_index_2>, .... +Si l'argument "untag" est spécifié, les mots clés assignés aux comptes spécifiés <account_index_1>, <account_index_2> ..., sont supprimés. +Si l'argument "tag_description" est spécifié, le texte arbitraire <description> est assigné au mot clé <mot_clé>.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1652"/> <source>address [ new <label text with white spaces allowed> | all | <index_min> [<index_max>] | label <index> <label text with white spaces allowed>]</source> - <translation type="unfinished"></translation> + <translation>address [ new <texte étiquette avec espaces autorisés> | all | <index_min> [<index_max>] | label <index> <texte étiquette avec espaces autorisés>]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1653"/> <source>If no arguments are specified or <index> is specified, the wallet shows the default or specified address. If "all" is specified, the walllet shows all the existing addresses in the currently selected account. If "new " is specified, the wallet creates a new address with the provided label text (which can be empty). If "label" is specified, the wallet sets the label of the address specified by <index> to the provided label text.</source> - <translation type="unfinished"></translation> + <translation>Si aucun argument n'est spécifié ou si <index> est spécifié, le portefeuille affiche l'adresse par défaut ou l'adresse spécifiée. Si "all" est spécifié, le portefeuille affiche toutes les adresses existantes dans le comptes actuellement sélectionné. Si "new" est spécifié, le portefeuille crée une nouvelle adresse avec le texte d'étiquette fourni (qui peut être vide). Si "label" est spécifié, le portefeuille affecte le texte fourni à l'étiquette de l'adresse spécifiée par <index>.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1656"/> <source>integrated_address [<payment_id> | <address>]</source> - <translation type="unfinished"></translation> + <translation>integrated_address [<ID_paiement> | <adresse>]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1657"/> <source>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> + <translation>Encoder un ID de paiement dans une adresse intégrée pour l'adresse publique du portefeuille actuel (en l'absence d'argument un ID de paiement aléatoire est utilisé), ou décoder une adresse intégrée en une adresse standard et un ID de paiement</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1660"/> <source>address_book [(add ((<address> [pid <id>])|<integrated address>) [<description possibly with whitespaces>])|(delete <index>)]</source> - <translation type="unfinished"></translation> + <translation>address_book [(add ((<adresse> [pid <id>])|<adresse intégrée>) [<description avec éventuellement des espaces>])|(delete <index>)]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1661"/> <source>Print all entries in the address book, optionally adding/deleting an entry to/from it.</source> - <translation type="unfinished"></translation> + <translation>Afficher toutes les entrées du carnet d'adresses, optionnellement en y ajoutant/supprimant une entrée.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1664"/> <source>Save the wallet data.</source> - <translation type="unfinished"></translation> + <translation>Sauvegarder les données du portefeuille.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1667"/> <source>Save a watch-only keys file.</source> - <translation type="unfinished"></translation> + <translation>Sauvegarder un fichier de clés d'audit.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1670"/> <source>Display the private view key.</source> - <translation type="unfinished"></translation> + <translation>Afficher la clé privée d'audit.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1673"/> <source>Display the private spend key.</source> - <translation type="unfinished"></translation> + <translation>Afficher la clé privée de dépense.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1676"/> <source>Display the Electrum-style mnemonic seed</source> - <translation type="unfinished"></translation> + <translation>Afficher la phrase mnémonique de style Electrum</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1679"/> <source>set <option> [<value>]</source> - <translation type="unfinished"></translation> + <translation>set <option> [<valeur>]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1680"/> @@ -1703,450 +1718,486 @@ If the "tag_description" argument is specified, the tag <tag_name&g Set the height before which to ignore blocks. auto-low-priority <1|0> Whether to automatically use the low priority fee level when it's safe to do so.</source> - <translation type="unfinished"></translation> + <translation>Options disponibles : + seed langue + Définir la langue de la phrase mnémonique. + always-confirm-transfers <1|0> + Confirmation des transactions non divisées. + print-ring-members <1|0> + Affichage d'informations détaillées sur les membres du cercle lors de la confirmation. + store-tx-info <1|0> + Sauvegarde des informations des transactions sortantes (adresse de destination, ID de paiement, clé secrète de transaction) pour référence ultérieure. + default-ring-size <n> + Définir la taille de cercle par défaut (la valeur par défaut est le minimum 5). + auto-refresh <1|0> + Synchronisation automatique des nouveaux blocs du démon. + refresh-type <full|optimize-coinbase|no-coinbase|default> + Définir le comportement du rafraîchissement du portefeuille. + priority [0|1|2|3|4] + Utiliser les frais pour la priorité par défaut/peu importante/normale/élevée/prioritaire. + confirm-missing-payment-id <1|0> + ask-password <1|0> + unit <monero|millinero|micronero|nanonero|piconero> + Définir la (sous-)unité monero par défaut. + min-outputs-count [n] + Essayer de garder au moins ce nombre de sorties d'une valeur d'au moins min-outputs-value. + min-outputs-value [n] + Essayer de garder au moins min-outputs-count sorties d'au moins cette valeur. + merge-destinations <1|0> + Fusion des paiements multiples vers la même adresse de destination. + confirm-backlog <1|0> + Avertir s'il y a un arriéré de transactions. + confirm-backlog-threshold [n] + Définir un seuil pour confirm-backlog pour avertir seulement si l'arriéré de transactions est supérieur à n blocs. + refresh-from-block-height [n] + Définir la hauteur avant laquelle les blocs sont ignorés. + auto-low-priority <1|0> + Utilisation automatique du niveau de frais pour la priorité basse, lorsqu'il est sûr de le faire.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1717"/> <source>Display the encrypted Electrum-style mnemonic seed.</source> - <translation type="unfinished"></translation> + <translation>Afficher la phrase mnémonique de style Electrum chiffrée.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1720"/> <source>Rescan the blockchain for spent outputs.</source> - <translation type="unfinished"></translation> + <translation>Rescanner la chaîne de blocs pour trouver les sorties dépensées.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1723"/> <source>get_tx_key <txid></source> - <translation type="unfinished"></translation> + <translation>get_tx_key <ID_transaction></translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1724"/> <source>Get the transaction key (r) for a given <txid>.</source> - <translation type="unfinished"></translation> + <translation>Obtenir la clé de transaction (r) pour un <ID_transaction> donné.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1727"/> <source>check_tx_key <txid> <txkey> <address></source> - <translation type="unfinished"></translation> + <translation>check_tx_key <ID_transaction> <clé_transaction> <adresse></translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1728"/> <source>Check the amount going to <address> in <txid>.</source> - <translation type="unfinished"></translation> + <translation>Vérifier le montant allant à <adresse> dans <ID_transaction>.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1731"/> <source>get_tx_proof <txid> <address> [<message>]</source> - <translation type="unfinished"></translation> + <translation>get_tx_proof <ID_transaction> <adresse> [<message>]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1732"/> <source>Generate a signature proving funds sent to <address> in <txid>, optionally with a challenge string <message>, using either the transaction secret key (when <address> is not your wallet's address) or the view secret key (otherwise), which does not disclose the secret key.</source> - <translation type="unfinished"></translation> + <translation>Générer une signature prouvant l'envoi de fonds à <adresse> dans <ID_transaction>, optionnellement avec un <message> comme challenge, en utilisant soit la clé secrète de transaction (quand <adresse> n'est pas l'adresse de votre portefeuille) soit la clé secrète d'audit (dans le cas contraire), tout en ne divulgant pas la clé secrète.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1735"/> <source>check_tx_proof <txid> <address> <signature_file> [<message>]</source> - <translation type="unfinished"></translation> + <translation>check_tx_proof <ID_transaction> <adresse> <fichier_signature> [<message>]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1736"/> <source>Check the proof for funds going to <address> in <txid> with the challenge string <message> if any.</source> - <translation type="unfinished"></translation> + <translation>Vérifier la validité de la preuve de fonds allant à <adresse> dans <ID_transaction> avec le <message> de challenge s'il y en a un.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1739"/> <source>get_spend_proof <txid> [<message>]</source> - <translation type="unfinished"></translation> + <translation>get_spend_proof <ID_transaction> [<message>]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1740"/> <source>Generate a signature proving that you generated <txid> using the spend secret key, optionally with a challenge string <message>.</source> - <translation type="unfinished"></translation> + <translation>Générer une signature prouvant que vous avez créé <ID_transaction> en utilisant la clé secrète de dépense, optionnellement avec un <message> comme challenge.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1743"/> <source>check_spend_proof <txid> <signature_file> [<message>]</source> - <translation type="unfinished"></translation> + <translation>check_spend_proof <ID_transaction> <fichier_signature> [<message>]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1744"/> <source>Check a signature proving that the signer generated <txid>, optionally with a challenge string <message>.</source> - <translation type="unfinished"></translation> + <translation>Vérifier la validité de la preuve que le signataire a créé <ID_transaction>, optionnellement avec un <message> comme challenge.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1747"/> <source>get_reserve_proof (all|<amount>) [<message>]</source> - <translation type="unfinished"></translation> + <translation>get_reserve_proof (all|<montant>) [<message>]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1748"/> <source>Generate a signature proving that you own at least this much, optionally with a challenge string <message>. If 'all' is specified, you prove the entire sum of all of your existing accounts' balances. Otherwise, you prove the reserve of the smallest possible amount above <amount> available in your current account.</source> - <translation type="unfinished"></translation> + <translation>Générer une signature prouvant que vous possédez au moins ce montant, optionnellement avec un <message> comme challenge. +Si 'all' est spécifié, vous prouvez la somme totale des soldes de tous vos comptes existants. +Sinon, vous prouvez le plus petit solde supérieur à <montant> dans votre compte actuel.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1753"/> <source>check_reserve_proof <address> <signature_file> [<message>]</source> - <translation type="unfinished"></translation> + <translation>check_reserve_proof <adresse> <fichier_signature> [<message>]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1754"/> <source>Check a signature proving that the owner of <address> holds at least this much, optionally with a challenge string <message>.</source> - <translation type="unfinished"></translation> + <translation>Vérifier la validité d'une signature prouvant que le propriétaire d'une <adresse> détient au moins un montant, optionnellement avec un <message> comme challenge.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1757"/> <source>show_transfers [in|out|pending|failed|pool] [index=<N1>[,<N2>,...]] [<min_height> [<max_height>]]</source> - <translation type="unfinished"></translation> + <translation>show_transfers [in|out|pending|failed|pool] [index=<N1>[,<N2>,...]] [<hauteur_min> [<hauteur_max>]]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1758"/> <source>Show the incoming/outgoing transfers within an optional height range.</source> - <translation type="unfinished"></translation> + <translation>Afficher les transferts entrants/sortants dans un interval de hauteurs facultatif.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1761"/> <source>unspent_outputs [index=<N1>[,<N2>,...]] [<min_amount> [<max_amount>]]</source> - <translation type="unfinished"></translation> + <translation>unspent_outputs [index=<N1>[,<N2>,...]] [<montant_min> [<montant_max>]]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1762"/> <source>Show the unspent outputs of a specified address within an optional amount range.</source> - <translation type="unfinished"></translation> + <translation>Afficher les sorties non dépensées d'une adresse spécifique dans un interval de montants facultatif.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1765"/> <source>Rescan the blockchain from scratch.</source> - <translation type="unfinished"></translation> + <translation>Rescanner la chaîne de blocs en partant de zéro.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1768"/> <source>set_tx_note <txid> [free text note]</source> - <translation type="unfinished"></translation> + <translation>set_tx_note <ID_transaction> [texte de la note]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1769"/> <source>Set an arbitrary string note for a <txid>.</source> - <translation type="unfinished"></translation> + <translation>Définir un texte arbitraire comme note pour <ID_transaction>.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1772"/> <source>get_tx_note <txid></source> - <translation type="unfinished"></translation> + <translation>get_tx_note <ID_transaction></translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1773"/> <source>Get a string note for a txid.</source> - <translation type="unfinished"></translation> + <translation>Obtenir le texte de la note pour <ID_transaction>.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1776"/> <source>set_description [free text note]</source> - <translation type="unfinished"></translation> + <translation>set_description [texte]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1777"/> <source>Set an arbitrary description for the wallet.</source> - <translation type="unfinished"></translation> + <translation>Définir un texte arbitraire comme description du portefeuille.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1780"/> <source>Get the description of the wallet.</source> - <translation type="unfinished"></translation> + <translation>Obtenir la description du portefeuille.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1783"/> <source>Show the wallet's status.</source> - <translation type="unfinished"></translation> + <translation>Afficher l'état du portefeuille.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1786"/> <source>Show the wallet's information.</source> - <translation type="unfinished"></translation> + <translation>Afficher les informations du portefeuille.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1789"/> <source>sign <file></source> - <translation type="unfinished"></translation> + <translation>sign <fichier></translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1790"/> <source>Sign the contents of a file.</source> - <translation type="unfinished"></translation> + <translation>Signer le contenu d'un fichier.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1793"/> <source>verify <filename> <address> <signature></source> - <translation type="unfinished"></translation> + <translation>verify <fichier> <adresse> <signature></translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1794"/> <source>Verify a signature on the contents of a file.</source> - <translation type="unfinished"></translation> + <translation>Vérifier la signature du contenu d'un fichier.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1797"/> <source>export_key_images <file></source> - <translation type="unfinished"></translation> + <translation>export_key_images <fichier></translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1798"/> <source>Export a signed set of key images to a <file>.</source> - <translation type="unfinished"></translation> + <translation>Exported un ensemble signé d'images de clé vers un <fichier>.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1801"/> <source>import_key_images <file></source> - <translation type="unfinished"></translation> + <translation>import_key_images <fichier></translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1802"/> <source>Import a signed key images list and verify their spent status.</source> - <translation type="unfinished"></translation> + <translation>Importer un ensemble signé d'images de clé et vérifier si elles correspondent à des dépenses.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1805"/> <source>export_outputs <file></source> - <translation type="unfinished"></translation> + <translation>export_outputs <fichier></translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1806"/> <source>Export a set of outputs owned by this wallet.</source> - <translation type="unfinished"></translation> + <translation>Exporter un ensemble de sorties possédées par ce portefeuille.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1809"/> <source>import_outputs <file></source> - <translation type="unfinished"></translation> + <translation>import_outputs <fichier></translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1810"/> <source>Import a set of outputs owned by this wallet.</source> - <translation type="unfinished"></translation> + <translation>Importer un ensemble de sorties possédées par ce portefeuille.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1813"/> <source>show_transfer <txid></source> - <translation type="unfinished"></translation> + <translation>show_transfer <ID_transaction></translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1814"/> <source>Show information about a transfer to/from this address.</source> - <translation type="unfinished"></translation> + <translation>Afficher les information à propos d'un transfert vers/depuis cette adresse.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1817"/> <source>Change the wallet's password.</source> - <translation type="unfinished"></translation> + <translation>Changer le mot de passe du portefeuille.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1820"/> <source>Generate a new random full size payment id. These will be unencrypted on the blockchain, see integrated_address for encrypted short payment ids.</source> - <translation type="unfinished"></translation> + <translation>Générer un nouvel ID de paiement long aléatoire. Ceux-ci sont en clair dans la chaîne de blocs, voir integrated_address pour les IDs de paiement courts cryptés.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1823"/> <source>Print the information about the current fee and transaction backlog.</source> - <translation type="unfinished"></translation> + <translation>Afficher les informations à propos des frais et arriéré de transactions actuels.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1825"/> <source>Export data needed to create a multisig wallet</source> - <translation type="unfinished"></translation> + <translation>Exporter les données nécessaires pour créer un portefeuille multisig</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1827"/> <source>make_multisig <threshold> <string1> [<string>...]</source> - <translation type="unfinished"></translation> + <translation>make_multisig <seuil> <chaîne_caractères1> [<chaîne_caractères>...]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1828"/> <source>Turn this wallet into a multisig wallet</source> - <translation type="unfinished"></translation> + <translation>Transformer ce portefeuille en portefeuille multisig</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1831"/> <source>finalize_multisig <string> [<string>...]</source> - <translation type="unfinished"></translation> + <translation>finalize_multisig <chaîne_caractères> [<chaîne_caractères>...]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1832"/> <source>Turn this wallet into a multisig wallet, extra step for N-1/N wallets</source> - <translation type="unfinished"></translation> + <translation>Transformer ce portefeuille en portefeuille multisig, étape supplémentaire pour les portefeuilles N-1/N</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1835"/> <source>export_multisig_info <filename></source> - <translation type="unfinished"></translation> + <translation>export_multisig_info <fichier></translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1836"/> <source>Export multisig info for other participants</source> - <translation type="unfinished"></translation> + <translation>Exporter les infos multisig pour les autres participants</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1839"/> <source>import_multisig_info <filename> [<filename>...]</source> - <translation type="unfinished"></translation> + <translation>import_multisig_info <fichier> [<fichier>...]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1840"/> <source>Import multisig info from other participants</source> - <translation type="unfinished"></translation> + <translation>Importer les infos multisig des autres participants</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1843"/> <source>sign_multisig <filename></source> - <translation type="unfinished"></translation> + <translation>sign_multisig <fichier></translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1844"/> <source>Sign a multisig transaction from a file</source> - <translation type="unfinished"></translation> + <translation>Signer une transaction multisig d'un fichier</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1847"/> <source>submit_multisig <filename></source> - <translation type="unfinished"></translation> + <translation>submit_multisig <fichier></translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1848"/> <source>Submit a signed multisig transaction from a file</source> - <translation type="unfinished"></translation> + <translation>Transmettre une transaction multisig signée d'un fichier</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1851"/> <source>export_raw_multisig_tx <filename></source> - <translation type="unfinished"></translation> + <translation>export_raw_multisig_tx <fichier></translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1852"/> <source>Export a signed multisig transaction to a file</source> - <translation type="unfinished"></translation> + <translation>Exporter une transaction multisig signée vers un fichier</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1855"/> <source>help [<command>]</source> - <translation type="unfinished"></translation> + <translation>help [<commande>]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1856"/> <source>Show the help section or the documentation about a <command>.</source> - <translation type="unfinished"></translation> + <translation>Afficher la section d'aide ou la documentation d'une <commande>.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1917"/> <source>integer >= </source> - <translation type="unfinished"></translation> + <translation>entier >= </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1930"/> <source>block height</source> - <translation type="unfinished"></translation> + <translation>hauteur de bloc</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="2012"/> <source>No wallet found with that name. Confirm creation of new wallet named: </source> - <translation type="unfinished"></translation> + <translation>Aucun portefeuille avec ce nom trouvé. Confirmer la création d'un nouveau portefeuille nommé : </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="2068"/> <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-spend-key="wallet_name", --generate-from-keys="wallet_name", --generate-from-multisig-keys="wallet_name" and --generate-from-json="jsonfilename"</source> - <translation type="unfinished"></translation> + <translation>impossible de spécifier plus d'une option parmis --generate-new-wallet="nom_portefeuille", --wallet-file="nom_portefeuille", --generate-from-view-key="nom_portefeuille", --generate-from-spend-key="nom_portefeuille", --generate-from-keys="nom_portefeuille", --generate-from-multisig-keys="nom_portefeuille" and --generate-from-json="nom_fichier_json"</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="2084"/> <source>can't specify both --restore-deterministic-wallet or --restore-multisig-wallet and --non-deterministic</source> - <translation type="unfinished"></translation> + <translation>impossible de spécifier à la fois --restore-deterministic-wallet ou --restore-multisig-wallet et --non-deterministic</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="2090"/> <source>--restore-multisig-wallet uses --generate-new-wallet, not --wallet-file</source> - <translation type="unfinished"></translation> + <translation>--restore-multisig-wallet utilise --generate-new-wallet, pas --wallet-file</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="2106"/> <source>specify a recovery parameter with the --electrum-seed="multisig seed here"</source> - <translation type="unfinished"></translation> + <translation>spécifiez un paramètre de récupération avec --electrum-seed="phrase mnémonique multisig ici"</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="2133"/> <source>Multisig seed failed verification</source> - <translation type="unfinished"></translation> + <translation>Échec de la vérification de la phrase mnémonique multisig</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="2149"/> <source>Enter seed encryption passphrase, empty if none</source> - <translation type="unfinished"></translation> + <translation>Entrer une phrase de passe pour le chiffrement de la phrase mnémonique, vide si aucune</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="2185"/> <location filename="../src/simplewallet/simplewallet.cpp" line="2259"/> <source>This address is a subaddress which cannot be used here.</source> - <translation type="unfinished"></translation> + <translation>Cette adresse est une sous-adresse qui ne peut pas être utilisée ici.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="2337"/> <source>Error: expected M/N, but got: </source> - <translation type="unfinished"></translation> + <translation>Erreur : M/N attendu, mais lu : </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="2342"/> <source>Error: expected N > 1 and N <= M, but got: </source> - <translation type="unfinished"></translation> + <translation>Erreur : N > 1 et N <= M attendu, mais lu : </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="2347"/> <source>Error: M/N is currently unsupported. </source> - <translation type="unfinished"></translation> + <translation>Erreur : M/N n'est actuellement pas supporté. </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="2350"/> <source>Generating master wallet from %u of %u multisig wallet keys</source> - <translation type="unfinished"></translation> + <translation>Génération du portefeuille principal à partir de %u de %u clés de portefeuille multisig</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="2379"/> <source>failed to parse secret view key</source> - <translation type="unfinished">échec de l'analyse de la clé secrète d'audit</translation> + <translation>échec de l'analyse de la clé secrète d'audit</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="2388"/> <source>failed to verify secret view key</source> - <translation type="unfinished">échec de la vérification de la clé secrète d'audit</translation> + <translation>échec de la vérification de la clé secrète d'audit</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="2408"/> <source>Secret spend key (%u of %u):</source> - <translation type="unfinished"></translation> + <translation>Clé secrète de dépense (%u de %u) :</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="2432"/> <source>Error: M/N is currently unsupported</source> - <translation type="unfinished"></translation> + <translation>Erreur : M/N n'est actuellement pas supporté</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="2550"/> <source>Restore height </source> - <translation type="unfinished"></translation> + <translation>Hauteur de restauration </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="2551"/> <source>Still apply restore height? (Y/Yes/N/No): </source> - <translation type="unfinished"></translation> + <translation>Appliquer la hauteur de restauration quand même ? (Y/Yes/Oui/N/No/Non) : </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="2582"/> <source>Warning: using an untrusted daemon at %s, privacy will be lessened</source> - <translation type="unfinished"></translation> + <translation>Attention : en n'utilisant %s qui n'est pas un démon de confiance, la confidentialité sera réduite</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="2636"/> <source>Daemon either is not started or wrong port was passed. Please make sure daemon is running or change the daemon address using the 'set_daemon' command.</source> - <translation type="unfinished"></translation> + <translation>Le démon n'est pas lancé ou un mauvais port a été fourni. Veuillez vous assurer que le démon fonctionne ou changez l'adresse de démon avec la commande 'set_daemon'.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="2768"/> @@ -2158,134 +2209,142 @@ Always use the "exit" command when closing monero-wallet-cli to save your current session's state. Otherwise, you might need to synchronize your wallet again (your wallet keys are NOT at risk in any case). </source> - <translation type="unfinished"></translation> + <translation>Votre portefeuille a été généré ! +Pour commencer la synchronisation avec le démon, utilisez la commande "refresh". +Utilisez la commande "help" pour voir la liste des commandes disponibles. +Utilisez "help <commande>" pour voir la documentation d'une commande. +Utilisez toujours la commande "exit" pour fermer monero-wallet-cli pour sauvegarder +l'état de votre session. Sinon, vous pourriez avoir besoin de synchroniser +votre portefeuille à nouveau (mais les clés de votre portefeuille ne risquent rien). +</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="2850"/> <source>failed to generate new mutlisig wallet</source> - <translation type="unfinished"></translation> + <translation>échec de la génération du nouveau portefeuille multisig</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="2853"/> <source>Generated new %u/%u multisig wallet: </source> - <translation type="unfinished"></translation> + <translation>Nouveau portefeuille multisig %u/%u généré : </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="2889"/> <source>Opened %u/%u multisig wallet%s</source> - <translation type="unfinished"></translation> + <translation>Portefeuille multisig %u/%u ouvert%s</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="2942"/> <source>Use "help <command>" to see a command's documentation. </source> - <translation type="unfinished"></translation> + <translation>Utilisez "help <commande>" pour voir la documentation d'une commande. +</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="3000"/> <source>wallet is multisig and cannot save a watch-only version</source> - <translation type="unfinished"></translation> + <translation>c'est un portefeuille multisig et il ne peut pas sauvegarder une version d'audit</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="3105"/> <source>missing daemon URL argument</source> - <translation type="unfinished"></translation> + <translation>URL du démon manquante en argument</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="3116"/> <source>Unexpected array length - Exited simple_wallet::set_daemon()</source> - <translation type="unfinished"></translation> + <translation>Taille de tableau inattendue - Sortie de simple_wallet::set_daemon()</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="3130"/> <source>This does not seem to be a valid daemon URL.</source> - <translation type="unfinished"></translation> + <translation>Ceci semble ne pas être une URL de démon valide.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="3166"/> <location filename="../src/simplewallet/simplewallet.cpp" line="3184"/> <source>txid </source> - <translation type="unfinished"></translation> + <translation>ID transaction </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="3168"/> <location filename="../src/simplewallet/simplewallet.cpp" line="3186"/> <source>idx </source> - <translation type="unfinished"></translation> + <translation>index </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="3299"/> <source> (Some owned outputs have partial key images - import_multisig_info needed)</source> - <translation type="unfinished"></translation> + <translation> (Certaines sorties ont des images de clé partielles - import_multisig_info requis)</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="3300"/> <source>Currently selected account: [</source> - <translation type="unfinished"></translation> + <translation>Compte actuellement sélectionné : [</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="3300"/> <source>] </source> - <translation type="unfinished"></translation> + <translation>] </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="3302"/> <source>Tag: </source> - <translation type="unfinished"></translation> + <translation>Mot clé : </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="3302"/> <source>(No tag assigned)</source> - <translation type="unfinished"></translation> + <translation>(Pas de mot clé assigné)</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="3309"/> <source>Balance per address:</source> - <translation type="unfinished"></translation> + <translation>Solde par adresse :</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="3310"/> <source>Address</source> - <translation type="unfinished"></translation> + <translation>Adresse</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="3310"/> <location filename="../src/simplewallet/simplewallet.cpp" line="5921"/> <source>Balance</source> - <translation type="unfinished"></translation> + <translation>Solde</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="3310"/> <location filename="../src/simplewallet/simplewallet.cpp" line="5921"/> <source>Unlocked balance</source> - <translation type="unfinished"></translation> + <translation>Solde débloqué</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="3310"/> <source>Outputs</source> - <translation type="unfinished"></translation> + <translation>Sorties</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="3310"/> <location filename="../src/simplewallet/simplewallet.cpp" line="5921"/> <source>Label</source> - <translation type="unfinished"></translation> + <translation>Étiquette</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="3318"/> <source>%8u %6s %21s %21s %7u %21s</source> - <translation type="unfinished"></translation> + <translation>%8u %6s %21s %21s %7u %21s</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="3327"/> <source>usage: balance [detail]</source> - <translation type="unfinished"></translation> + <translation>usage : balance [detail]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="3339"/> <location filename="../src/simplewallet/simplewallet.cpp" line="3381"/> <source>usage: incoming_transfers [available|unavailable] [verbose] [index=<N>]</source> - <translation type="unfinished"></translation> + <translation>usage: incoming_transfers [available|unavailable] [verbose] [index=<N>]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="3400"/> @@ -2306,7 +2365,7 @@ your wallet again (your wallet keys are NOT at risk in any case). <location filename="../src/simplewallet/simplewallet.cpp" line="3400"/> <location filename="../src/simplewallet/simplewallet.cpp" line="3451"/> <source>addr index</source> - <translation type="unfinished"></translation> + <translation>index adresse</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="3423"/> @@ -2431,13 +2490,13 @@ Attention : Certaines clés d'entrées étant dépensées sont issues de < <location filename="../src/simplewallet/simplewallet.cpp" line="3705"/> <location filename="../src/simplewallet/simplewallet.cpp" line="4184"/> <source>Ring size must not be 0</source> - <translation type="unfinished"></translation> + <translation>La taille de cercle ne doit pas être 0</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="3717"/> <location filename="../src/simplewallet/simplewallet.cpp" line="4196"/> <source>ring size %u is too small, minimum is %u</source> - <translation type="unfinished"></translation> + <translation>la taille de cercle %u est trop petite, le minimum est %u</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="3724"/> @@ -2460,18 +2519,18 @@ Attention : Certaines clés d'entrées étant dépensées sont issues de < <message> <location filename="../src/simplewallet/simplewallet.cpp" line="6743"/> <source>Transaction successfully saved to </source> - <translation type="unfinished"></translation> + <translation>Transaction sauvegardée avec succès dans </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="6743"/> <location filename="../src/simplewallet/simplewallet.cpp" line="6745"/> <source>, txid </source> - <translation type="unfinished"></translation> + <translation>, ID transaction </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="6745"/> <source>Failed to save transaction to </source> - <translation type="unfinished"></translation> + <translation>Échec de la sauvegarde de la transaction dans </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="4081"/> @@ -2504,7 +2563,7 @@ Attention : Certaines clés d'entrées étant dépensées sont issues de < <message> <location filename="../src/simplewallet/simplewallet.cpp" line="6673"/> <source>Double spend seen on the network: this transaction may or may not end up being mined</source> - <translation type="unfinished"></translation> + <translation>Double dépense détectée sur le réseau : cette transaction sera peut-être invalidée</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="6708"/> @@ -2525,13 +2584,13 @@ Attention : Certaines clés d'entrées étant dépensées sont issues de < <location filename="../src/simplewallet/simplewallet.cpp" line="541"/> <location filename="../src/simplewallet/simplewallet.cpp" line="608"/> <source>wallet is watch-only and has no seed</source> - <translation>c'est un portefeuille d'audit et il n'a pas de graine</translation> + <translation>c'est un portefeuille d'audit et il n'a pas de phrase mnémonique</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="557"/> <location filename="../src/simplewallet/simplewallet.cpp" line="613"/> <source>wallet is non-deterministic and has no seed</source> - <translation>c'est un portefeuille non déterministe et il n'a pas de graine</translation> + <translation>c'est un portefeuille non déterministe et il n'a pas de phrase mnémonique</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="1226"/> @@ -2673,7 +2732,7 @@ Attention : Certaines clés d'entrées étant dépensées sont issues de < <location filename="../src/simplewallet/simplewallet.cpp" line="3142"/> <location filename="../src/simplewallet/simplewallet.cpp" line="4962"/> <source>wallet is null</source> - <translation type="unfinished"></translation> + <translation>portefeuille est nul</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="2680"/> @@ -2801,20 +2860,20 @@ Attention : Certaines clés d'entrées étant dépensées sont issues de < <message> <location filename="../src/simplewallet/simplewallet.cpp" line="3778"/> <source>Locked blocks too high, max 1000000 (˜4 yrs)</source> - <translation type="unfinished"></translation> + <translation>Nombre de blocs verrou trop élévé, 1000000 max (˜4 ans)</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="5077"/> <location filename="../src/simplewallet/simplewallet.cpp" line="5188"/> <source>Good signature</source> - <translation type="unfinished"></translation> + <translation>Bonne signature</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="5104"/> <location filename="../src/simplewallet/simplewallet.cpp" line="5190"/> <location filename="../src/simplewallet/simplewallet.cpp" line="5293"/> <source>Bad signature</source> - <translation type="unfinished"></translation> + <translation>Mauvaise signature</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="6046"/> @@ -2904,89 +2963,89 @@ Attention : Certaines clés d'entrées étant dépensées sont issues de < <message> <location filename="../src/simplewallet/simplewallet.cpp" line="5039"/> <source>usage: check_tx_proof <txid> <address> <signature_file> [<message>]</source> - <translation type="unfinished"></translation> + <translation>usage : check_tx_proof <ID_transaction> <adresse> <fichier_signature> [<message>]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="5066"/> <location filename="../src/simplewallet/simplewallet.cpp" line="5181"/> <location filename="../src/simplewallet/simplewallet.cpp" line="5278"/> <source>failed to load signature file</source> - <translation type="unfinished"></translation> + <translation>échec du chargement du fichier signature</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="5117"/> <source>usage: get_spend_proof <txid> [<message>]</source> - <translation type="unfinished"></translation> + <translation>usage : get_spend_proof <ID_transaction> [<message>]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="5123"/> <source>wallet is watch-only and cannot generate the proof</source> - <translation type="unfinished"></translation> + <translation>c'est un portefeuille d'audit et il ne peut générer de preuve</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="5161"/> <source>usage: check_spend_proof <txid> <signature_file> [<message>]</source> - <translation type="unfinished"></translation> + <translation>usage : check_spend_proof <ID_transaction> <fichier_signature> [<message>]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="5202"/> <source>usage: get_reserve_proof (all|<amount>) [<message>]</source> - <translation type="unfinished"></translation> + <translation>usage : get_reserve_proof (all|<montant>) [<message>]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="5208"/> <source>The reserve proof can be generated only by a full wallet</source> - <translation type="unfinished"></translation> + <translation>La preuve de réserve ne peut être généré que par un portefeuille complet</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="5253"/> <source>usage: check_reserve_proof <address> <signature_file> [<message>]</source> - <translation type="unfinished"></translation> + <translation>usage : check_reserve_proof <adresse> <fichier_signature> [<message>]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="5271"/> <source>Address must not be a subaddress</source> - <translation type="unfinished"></translation> + <translation>L'adresse ne doit pas être une sous-adresse</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="5289"/> <source>Good signature -- total: %s, spent: %s, unspent: %s</source> - <translation type="unfinished"></translation> + <translation>Bonne signature -- total : %s, dépensé : %s, non dépensé : %s</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="5353"/> <source>usage: show_transfers [in|out|all|pending|failed] [index=<N1>[,<N2>,...]] [<min_height> [<max_height>]]</source> - <translation type="unfinished"></translation> + <translation>usage : show_transfers [in|out|all|pending|failed] [index=<N1>[,<N2>,...]] [<hauteur_min> [<hauteur_max>]]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="5490"/> <source>[Double spend seen on the network: this transaction may or may not end up being mined] </source> - <translation type="unfinished"></translation> + <translation>[Double dépense détectée sur le réseau : cette transaction sera peut-être invalidée] </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="5526"/> <source>usage: unspent_outputs [index=<N1>[,<N2>,...]] [<min_amount> [<max_amount>]]</source> - <translation type="unfinished"></translation> + <translation>usage : unspent_outputs [index=<N1>[,<N2>,...]] [<montant_min> [<montant_max>]]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="5586"/> <source>There is no unspent output in the specified address</source> - <translation type="unfinished"></translation> + <translation>Il n'y a pas de sortie non dépensée pour l'adresse spécifiée</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="5699"/> <source> (no daemon)</source> - <translation type="unfinished"></translation> + <translation> (pas de démon)</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="5701"/> <source> (out of sync)</source> - <translation type="unfinished"></translation> + <translation> (désynchronisé)</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="5758"/> <source>(Untitled account)</source> - <translation type="unfinished"></translation> + <translation>(compte sans nom)</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="5771"/> @@ -2996,13 +3055,13 @@ Attention : Certaines clés d'entrées étant dépensées sont issues de < <location filename="../src/simplewallet/simplewallet.cpp" line="5990"/> <location filename="../src/simplewallet/simplewallet.cpp" line="6013"/> <source>failed to parse index: </source> - <translation type="unfinished"></translation> + <translation>échec de l'analyse de l'index : </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="5776"/> <location filename="../src/simplewallet/simplewallet.cpp" line="5995"/> <source>specify an index between 0 and </source> - <translation type="unfinished"></translation> + <translation>specifiez un index entre 0 et </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="5873"/> @@ -3014,165 +3073,174 @@ Attention : Certaines clés d'entrées étant dépensées sont issues de < account tag <tag_name> <account_index_1> [<account_index_2> ...] account untag <account_index_1> [<account_index_2> ...] account tag_description <tag_name> <description></source> - <translation type="unfinished"></translation> + <translation>usage : + account + account new <texte étiquette avec espaces autorisés> + account switch <index> + account label <index> <texte étiquette avec espaces autorisés> + account tag <mot_clé> <index_compte_1> [<index_compte_2> ...] + account untag <index_compte_1> [<index_compte_2> ...] + account tag_description <mot_clé> <description></translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="5901"/> <source> Grand total: Balance: </source> - <translation type="unfinished"></translation> + <translation> +Somme finale : + Solde : </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="5901"/> <source>, unlocked balance: </source> - <translation type="unfinished"></translation> + <translation>, solde débloqué : </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="5909"/> <source>Untagged accounts:</source> - <translation type="unfinished"></translation> + <translation>Comptes sans mot clé :</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="5915"/> <source>Tag %s is unregistered.</source> - <translation type="unfinished"></translation> + <translation>Le mot clé %s n'est pas enregistré.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="5918"/> <source>Accounts with tag: </source> - <translation type="unfinished"></translation> + <translation>Comptes avec mot clé : </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="5919"/> <source>Tag's description: </source> - <translation type="unfinished"></translation> + <translation>Description du mot clé : </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="5921"/> <source>Account</source> - <translation type="unfinished"></translation> + <translation>Compte</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="5927"/> <source> %c%8u %6s %21s %21s %21s</source> - <translation type="unfinished"></translation> + <translation> %c%8u %6s %21s %21s %21s</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="5937"/> <source>----------------------------------------------------------------------------------</source> - <translation type="unfinished"></translation> + <translation>----------------------------------------------------------------------------------</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="5938"/> <source>%15s %21s %21s</source> - <translation type="unfinished"></translation> + <translation>%15s %21s %21s</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="5961"/> <source>Primary address</source> - <translation type="unfinished"></translation> + <translation>Adresse primaire</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="5961"/> <source>(used)</source> - <translation type="unfinished"></translation> + <translation>(utilisé)</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="5982"/> <source>(Untitled address)</source> - <translation type="unfinished"></translation> + <translation>(adresse sans nom)</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="6022"/> <source><index_min> is already out of bound</source> - <translation type="unfinished"></translation> + <translation><index_min> est déjà hors limite</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="6027"/> <source><index_max> exceeds the bound</source> - <translation type="unfinished"></translation> + <translation><index_max> excède la limite</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="6035"/> <source>usage: address [ new <label text with white spaces allowed> | all | <index_min> [<index_max>] | label <index> <label text with white spaces allowed> ]</source> - <translation type="unfinished"></translation> + <translation>usage : address [ new <texte étiquette avec espaces autorisés> | all | <index_min> [<index_max>] | label <index> <texte étiquette avec espaces autorisés>]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="6053"/> <location filename="../src/simplewallet/simplewallet.cpp" line="6065"/> <source>Integrated addresses can only be created for account 0</source> - <translation type="unfinished"></translation> + <translation>Les adresses intégrées ne peuvent être créées que pour le compte 0</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="6077"/> <source>Integrated address: %s, payment ID: %s</source> - <translation type="unfinished"></translation> + <translation>Adresse intégrée : %s, ID de paiement : %s</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="6082"/> <source>Subaddress: </source> - <translation type="unfinished"></translation> + <translation>Sous-adresse : </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="6242"/> <source>usage: get_description</source> - <translation type="unfinished"></translation> + <translation>usage : get_description</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="6248"/> <source>no description found</source> - <translation type="unfinished"></translation> + <translation>pas de description trouvée</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="6250"/> <source>description found: </source> - <translation type="unfinished"></translation> + <translation>description trouvée : </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="6285"/> <source>Filename: </source> - <translation type="unfinished"></translation> + <translation>Fichier : </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="6290"/> <source>Watch only</source> - <translation type="unfinished"></translation> + <translation>Audit</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="6292"/> <source>%u/%u multisig%s</source> - <translation type="unfinished"></translation> + <translation>Multisig %u/%u%s</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="6294"/> <source>Normal</source> - <translation type="unfinished"></translation> + <translation>Normal</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="6295"/> <source>Type: </source> - <translation type="unfinished"></translation> + <translation>Type : </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="6296"/> <source>Testnet: </source> - <translation type="unfinished"></translation> + <translation>Testnet : </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="6296"/> <source>Yes</source> - <translation type="unfinished"></translation> + <translation>Oui</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="6296"/> <source>No</source> - <translation type="unfinished"></translation> + <translation>Non</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="6314"/> <source>This wallet is multisig and cannot sign</source> - <translation type="unfinished"></translation> + <translation>C'est un portefeuille multisig et il ne peut pas signer</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="6335"/> @@ -3307,21 +3375,21 @@ Grand total: <message> <location filename="../src/simplewallet/simplewallet.cpp" line="4912"/> <source>usage: get_tx_proof <txid> <address> [<message>]</source> - <translation type="unfinished"></translation> + <translation>usage : get_tx_proof <ID_transaction> <adresse> [<message>]</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="4937"/> <location filename="../src/simplewallet/simplewallet.cpp" line="5147"/> <location filename="../src/simplewallet/simplewallet.cpp" line="5239"/> <source>signature file saved to: </source> - <translation type="unfinished"></translation> + <translation>fichier signature sauvegardé dans : </translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="4939"/> <location filename="../src/simplewallet/simplewallet.cpp" line="5149"/> <location filename="../src/simplewallet/simplewallet.cpp" line="5241"/> <source>failed to save signature file</source> - <translation type="unfinished"></translation> + <translation>échec de la sauvegarde du fichier signature</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="4953"/> @@ -3544,83 +3612,83 @@ Sorties par * : </translation> <message> <location filename="../src/gen_multisig/gen_multisig.cpp" line="70"/> <source>Base filename (-1, -2, etc suffixes will be appended as needed)</source> - <translation type="unfinished"></translation> + <translation>Nom de fichier de base (des suffixes -1, -2 etc seront ajoutés si nécessaire)</translation> </message> <message> <location filename="../src/gen_multisig/gen_multisig.cpp" line="71"/> <source>Give threshold and participants at once as M/N</source> - <translation type="unfinished"></translation> + <translation>Indiquer le seuil et les participants sous la forme M/N</translation> </message> <message> <location filename="../src/gen_multisig/gen_multisig.cpp" line="72"/> <source>How many participants wil share parts of the multisig wallet</source> - <translation type="unfinished"></translation> + <translation>Combien de participants partageront des parts du portefeuille multisig</translation> </message> <message> <location filename="../src/gen_multisig/gen_multisig.cpp" line="73"/> <source>How many signers are required to sign a valid transaction</source> - <translation type="unfinished"></translation> + <translation>Combien de signataires sont requis pour signer une transaction valide</translation> </message> <message> <location filename="../src/gen_multisig/gen_multisig.cpp" line="74"/> <source>Create testnet multisig wallets</source> - <translation type="unfinished"></translation> + <translation>Créer un portefeuille multisig testnet</translation> </message> <message> <location filename="../src/gen_multisig/gen_multisig.cpp" line="81"/> <source>Generating %u %u/%u multisig wallets</source> - <translation type="unfinished"></translation> + <translation>Génération de %u portefeuilles multisig %u/%u</translation> </message> <message> <location filename="../src/gen_multisig/gen_multisig.cpp" line="138"/> <source>Error verifying multisig extra info</source> - <translation type="unfinished"></translation> + <translation>Erreur de vérification des infos multisig supplémentaires</translation> </message> <message> <location filename="../src/gen_multisig/gen_multisig.cpp" line="146"/> <source>Error finalizing multisig</source> - <translation type="unfinished"></translation> + <translation>Erreur de finalisation multisig</translation> </message> <message> <location filename="../src/gen_multisig/gen_multisig.cpp" line="153"/> <source>Generated multisig wallets for address </source> - <translation type="unfinished"></translation> + <translation>Portefeuilles multisig générés pour l'adresse </translation> </message> <message> <location filename="../src/gen_multisig/gen_multisig.cpp" line="157"/> <source>Error creating multisig wallets: </source> - <translation type="unfinished"></translation> + <translation>Erreur de création des portefeuilles multisig : </translation> </message> <message> <location filename="../src/gen_multisig/gen_multisig.cpp" line="176"/> <source>This program generates a set of multisig wallets - use this simpler scheme only if all the participants trust each other</source> - <translation type="unfinished"></translation> + <translation>Ce programme génère un ensemble de portefeuilles multisig - n'utilisez cette méthode plus simple que si tous les participants se font confiance</translation> </message> <message> <location filename="../src/gen_multisig/gen_multisig.cpp" line="194"/> <source>Error: expected N/M, but got: </source> - <translation type="unfinished"></translation> + <translation>Erreur : N/M attendu, mais lu : </translation> </message> <message> <location filename="../src/gen_multisig/gen_multisig.cpp" line="202"/> <location filename="../src/gen_multisig/gen_multisig.cpp" line="211"/> <source>Error: either --scheme or both of --threshold and --participants may be given</source> - <translation type="unfinished"></translation> + <translation>Erreur : soit --scheme soit --threshold et --participants doivent être indiqués</translation> </message> <message> <location filename="../src/gen_multisig/gen_multisig.cpp" line="218"/> <source>Error: expected N > 1 and N <= M, but got N==%u and M==%d</source> - <translation type="unfinished"></translation> + <translation>Erreur : N > 1 et N <= M attendu, mais lu N==%u et M==%d</translation> </message> <message> <location filename="../src/gen_multisig/gen_multisig.cpp" line="227"/> <source>Error: --filename-base is required</source> - <translation type="unfinished"></translation> + <translation>Erreur : --filename-base est requis</translation> </message> <message> <location filename="../src/gen_multisig/gen_multisig.cpp" line="233"/> <source>Error: unsupported scheme: only N/N and N-1/N are supported</source> - <translation type="unfinished"></translation> + <translation>Erreur : schéma non supporté : seuls N/N et N-1/N sont supportés</translation> </message> </context> <context> @@ -3638,7 +3706,7 @@ Sorties par * : </translation> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="117"/> <source>Generate deterministic wallet from spend key</source> - <translation type="unfinished"></translation> + <translation>Générer un portefeuille déterministe à partir d'une clé de dépense</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="118"/> @@ -3648,27 +3716,27 @@ Sorties par * : </translation> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="119"/> <source>Generate a master wallet from multisig wallet keys</source> - <translation type="unfinished"></translation> + <translation>Générer un portefeuille principal à partir de clés de portefeuille multisig</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="121"/> <source>Language for mnemonic</source> - <translation type="unfinished"></translation> + <translation>Langue de la phrase mnémonique</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="122"/> <source>Specify Electrum seed for wallet recovery/creation</source> - <translation>Spécifier la graine Electrum pour la récupération/création d'un portefeuille</translation> + <translation>Spécifier la phrase mnémonique Electrum pour la récupération/création d'un portefeuille</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="123"/> <source>Recover wallet using Electrum-style mnemonic seed</source> - <translation>Récupérer un portefeuille en utilisant une graine mnémonique de style Electrum</translation> + <translation>Récupérer un portefeuille en utilisant une phrase mnémonique de style Electrum</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="124"/> <source>Recover multisig wallet using Electrum-style mnemonic seed</source> - <translation type="unfinished"></translation> + <translation>Récupérer un portefeuille multisig en utilisant une phrase mnémonique de style Electrum</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="125"/> @@ -3693,7 +3761,7 @@ Sorties par * : </translation> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="129"/> <source>The newly created transaction will not be relayed to the monero network</source> - <translation type="unfinished"></translation> + <translation>La transaction nouvellement créée ne sera pas transmise au réseau monero</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="171"/> @@ -3714,7 +3782,8 @@ Sorties par * : </translation> <location filename="../src/simplewallet/simplewallet.cpp" line="6787"/> <source>This is the command line monero wallet. It needs to connect to a monero daemon to work correctly.</source> - <translation type="unfinished"></translation> + <translation>Ceci est le portefeuille monero en ligne de commande. Il a besoin de se +connecter à un démon monero pour fonctionner correctement.</translation> </message> <message> <location filename="../src/simplewallet/simplewallet.cpp" line="6801"/> @@ -3787,7 +3856,7 @@ daemon to work correctly.</source> <message> <location filename="../src/wallet/wallet2.cpp" line="224"/> <source>no password specified; use --prompt-for-password to prompt for a password</source> - <translation type="unfinished"></translation> + <translation>pas de mot de passe spécifié; utilisez --prompt-for-password pour demander un mot de passe</translation> </message> <message> <location filename="../src/wallet/wallet2.cpp" line="246"/> @@ -3831,7 +3900,7 @@ daemon to work correctly.</source> <message> <location filename="../src/wallet/wallet2.cpp" line="319"/> <source>At least one of Electrum-style word list and private view key and private spend key must be specified</source> - <translation type="unfinished"></translation> + <translation>Il faut spécifier au moins une des options parmis la liste de mots de style Electrum, la clé privée d'audit et la clé privée de dépense</translation> </message> <message> <location filename="../src/wallet/wallet2.cpp" line="323"/> @@ -3861,12 +3930,12 @@ daemon to work correctly.</source> <message> <location filename="../src/wallet/wallet2.cpp" line="392"/> <source>failed to parse address: </source> - <translation type="unfinished"></translation> + <translation>échec de l'analyse de l'adresse : </translation> </message> <message> <location filename="../src/wallet/wallet2.cpp" line="398"/> <source>Address must be specified in order to create watch-only wallet</source> - <translation type="unfinished"></translation> + <translation>L'adresse doit être spécifiée afin de créer un portefeuille d'audit</translation> </message> <message> <location filename="../src/wallet/wallet2.cpp" line="413"/> @@ -3883,12 +3952,12 @@ daemon to work correctly.</source> <location filename="../src/wallet/wallet2.cpp" line="3599"/> <location filename="../src/wallet/wallet2.cpp" line="3955"/> <source>Primary account</source> - <translation type="unfinished"></translation> + <translation>Compte primaire</translation> </message> <message> <location filename="../src/wallet/wallet2.cpp" line="7914"/> <source>No funds received in this tx.</source> - <translation type="unfinished"></translation> + <translation>Aucun fonds n'a été reçu dans cette transaction.</translation> </message> <message> <location filename="../src/wallet/wallet2.cpp" line="8607"/> @@ -3906,12 +3975,12 @@ daemon to work correctly.</source> <message> <location filename="../src/wallet/wallet_rpc_server.cpp" line="175"/> <source>Failed to create directory </source> - <translation type="unfinished"></translation> + <translation>Échec de la création du répertoire </translation> </message> <message> <location filename="../src/wallet/wallet_rpc_server.cpp" line="177"/> <source>Failed to create directory %s: %s</source> - <translation type="unfinished"></translation> + <translation>Échec de la création du répertoire %s : %s</translation> </message> <message> <location filename="../src/wallet/wallet_rpc_server.cpp" line="188"/> @@ -3946,18 +4015,19 @@ daemon to work correctly.</source> <message> <location filename="../src/wallet/wallet_rpc_server.cpp" line="443"/> <source>Tag %s is unregistered.</source> - <translation type="unfinished"></translation> + <translation>Le mot clé %s n'est pas enregistré.</translation> </message> <message> <location filename="../src/wallet/wallet_rpc_server.cpp" line="2435"/> <source>Transaction not possible. Available only %s, transaction amount %s = %s + %s (fee)</source> - <translation type="unfinished"></translation> + <translation>Transaction impossible. Solde disponible : %s, montant de la transaction %s = %s + %s (frais)</translation> </message> <message> <location filename="../src/wallet/wallet_rpc_server.cpp" line="2870"/> <source>This is the RPC monero wallet. It needs to connect to a monero daemon to work correctly.</source> - <translation type="unfinished"></translation> + <translation>Ceci est le portefeuille monero par RPC. Il a besoin de se +connecter à un démon monero pour fonctionner correctement.</translation> </message> <message> <location filename="../src/wallet/wallet_rpc_server.cpp" line="2893"/> @@ -3984,12 +4054,12 @@ daemon to work correctly.</source> <location filename="../src/wallet/wallet_rpc_server.cpp" line="2944"/> <location filename="../src/wallet/wallet_rpc_server.cpp" line="2977"/> <source>Successfully saved</source> - <translation type="unfinished"></translation> + <translation>Sauvegardé avec succès</translation> </message> <message> <location filename="../src/wallet/wallet_rpc_server.cpp" line="2947"/> <source>Successfully loaded</source> - <translation type="unfinished"></translation> + <translation>Chargé avec succès</translation> </message> <message> <location filename="../src/wallet/wallet_rpc_server.cpp" line="2951"/> @@ -4009,7 +4079,7 @@ daemon to work correctly.</source> <message> <location filename="../src/wallet/wallet_rpc_server.cpp" line="2969"/> <source>Failed to run wallet: </source> - <translation type="unfinished"></translation> + <translation>Échec du lancement du portefeuille : </translation> </message> <message> <location filename="../src/wallet/wallet_rpc_server.cpp" line="2972"/> @@ -4065,7 +4135,8 @@ daemon to work correctly.</source> <location filename="../src/wallet/wallet_args.cpp" line="138"/> <source>This is the command line monero wallet. It needs to connect to a monero daemon to work correctly.</source> - <translation type="unfinished"></translation> + <translation>Ceci est le portefeuille monero en ligne de commande. Il a besoin de se +connecter à un démon monero pour fonctionner correctement.</translation> </message> <message> <location filename="../src/wallet/wallet_args.cpp" line="161"/> diff --git a/utils/systemd/monerod.service b/utils/systemd/monerod.service index b6b6b6ce6..696be4c33 100644 --- a/utils/systemd/monerod.service +++ b/utils/systemd/monerod.service @@ -15,7 +15,6 @@ ExecStart=/usr/bin/monerod --config-file /etc/monerod.conf \ --detach --pidfile /run/monero/monerod.pid Restart=always -PrivateTmp=true [Install] WantedBy=multi-user.target |