diff options
author | Riccardo Spagni <ric@spagni.net> | 2018-03-05 19:11:20 +0200 |
---|---|---|
committer | Riccardo Spagni <ric@spagni.net> | 2018-03-05 19:11:20 +0200 |
commit | 4f93f745284c10f12e2524f5211030085d9626cf (patch) | |
tree | 29b5f359a8f346305bcf7bf82f459f421bfaa7a7 /src | |
parent | Merge pull request #3273 (diff) | |
parent | Wallet API: generalize 'bool testnet' to 'NetworkType nettype' (diff) | |
download | monero-4f93f745284c10f12e2524f5211030085d9626cf.tar.xz |
Merge pull request #3277
0e7ad2e2 Wallet API: generalize 'bool testnet' to 'NetworkType nettype' (stoffu)
af773211 Stagenet (stoffu)
cc9a0bee command_line: allow args to depend on more than one args (stoffu)
55f8d917 command_line::get_arg: remove 'required' for dependent args as they're always optional (stoffu)
450306a0 command line: allow has_arg to handle arg_descriptor<bool,false,true> #3318 (stoffu)
9f9e095a Use `genesis_tx` parameter in `generate_genesis_block`. #3261 (Jean Pierre Dudey)
Diffstat (limited to 'src')
52 files changed, 688 insertions, 379 deletions
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/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/miner.cpp b/src/cryptonote_basic/miner.cpp index 7af9b3487..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; 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 376f9ca5e..88ed409bf 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; @@ -4316,15 +4333,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 +4363,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 +4373,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..77f69615b 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.cpp +++ b/src/cryptonote_core/cryptonote_tx_utils.cpp @@ -639,17 +639,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.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl index 14c3fb298..7c4f16c77 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl @@ -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/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/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/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 3c940bfef..b74097306 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -855,7 +855,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 +2120,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)) @@ -2237,7 +2246,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 +2320,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 +2429,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; @@ -2820,7 +2829,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 +2887,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 +2915,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 +2958,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 +2997,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(); } @@ -3132,7 +3141,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 +3230,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]; @@ -3880,7 +3889,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 +4338,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 +4552,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 +4699,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 +4782,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 +4856,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 +5044,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 +5112,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 +5127,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 +5146,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 +5176,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 +5200,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 +5219,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 +5394,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 +5589,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 +6188,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 +6198,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 +6234,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 +6291,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 +6417,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 +6426,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 +6488,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 +6791,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) 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 7f8144129..0ed6601af 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -233,16 +233,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 +275,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 ""; @@ -300,7 +300,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 +310,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 +388,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 +469,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; @@ -1079,7 +1079,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 +1464,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 +1496,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 +1527,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 +1615,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 +1652,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); 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 1c4545a25..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); @@ -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,11 +871,21 @@ 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 succeeded, wallet object deleted. in case operation failed, wallet object not deleted diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp index 22bc343fb..5b6df8a9c 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 08924fffa..9b2595716 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")); } @@ -388,7 +392,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, 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"); } @@ -2855,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"); } @@ -2945,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"); } @@ -2992,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"); } @@ -3033,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; @@ -3125,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"); } @@ -3225,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"); } @@ -3535,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 @@ -3674,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); } @@ -3751,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); @@ -4028,7 +4039,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; @@ -4316,7 +4327,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(); @@ -4526,7 +4537,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 @@ -4899,7 +4910,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"); @@ -5645,7 +5656,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; @@ -5738,7 +5749,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; @@ -5802,7 +5813,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 @@ -5942,7 +5953,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 @@ -5987,7 +5998,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}); @@ -6157,7 +6168,7 @@ 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 doesn't exist. request.create_account = true; @@ -6184,7 +6195,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"); @@ -6203,7 +6214,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); @@ -6353,7 +6364,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"); @@ -6370,7 +6381,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"); @@ -6695,7 +6706,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 @@ -6923,7 +6934,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; @@ -6934,7 +6945,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; @@ -7004,7 +7015,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; @@ -8431,16 +8442,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; @@ -9421,7 +9432,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(); @@ -9485,7 +9496,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; @@ -9734,10 +9745,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..b50133e4a 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) { @@ -1075,7 +1075,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 +1087,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 +1385,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 +1595,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 +1628,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 +1661,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 +1768,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 +2058,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 +2071,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 +2090,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 +2219,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 +2535,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 +2706,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 +2883,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); |