aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/blockchain_db/lmdb/db_lmdb.cpp5
-rw-r--r--src/blockchain_utilities/blockchain_export.cpp10
-rw-r--r--src/blockchain_utilities/blockchain_import.cpp11
-rw-r--r--src/blocks/CMakeLists.txt3
-rw-r--r--src/blocks/blockexports.c22
-rw-r--r--src/blocks/blocks.h4
-rw-r--r--src/blocks/stagenet_blocks.dat0
-rw-r--r--src/checkpoints/checkpoints.cpp24
-rw-r--r--src/checkpoints/checkpoints.h13
-rw-r--r--src/common/command_line.h72
-rw-r--r--src/common/util.cpp23
-rw-r--r--src/common/varint.h4
-rw-r--r--src/crypto/chacha.h4
-rw-r--r--src/crypto/crypto.cpp2
-rw-r--r--src/crypto/hash-ops.h4
-rw-r--r--src/crypto/hash.h4
-rw-r--r--src/crypto/slow-hash.c89
-rw-r--r--src/cryptonote_basic/account.cpp8
-rw-r--r--src/cryptonote_basic/account.h4
-rw-r--r--src/cryptonote_basic/cryptonote_basic_impl.cpp34
-rw-r--r--src/cryptonote_basic/cryptonote_basic_impl.h8
-rw-r--r--src/cryptonote_basic/cryptonote_format_utils.cpp3
-rw-r--r--src/cryptonote_basic/miner.cpp6
-rw-r--r--src/cryptonote_basic/miner.h2
-rw-r--r--src/cryptonote_config.h28
-rw-r--r--src/cryptonote_core/blockchain.cpp68
-rw-r--r--src/cryptonote_core/blockchain.h10
-rw-r--r--src/cryptonote_core/cryptonote_core.cpp43
-rw-r--r--src/cryptonote_core/cryptonote_core.h13
-rw-r--r--src/cryptonote_core/cryptonote_tx_utils.cpp13
-rw-r--r--src/cryptonote_protocol/cryptonote_protocol_handler.h2
-rw-r--r--src/cryptonote_protocol/cryptonote_protocol_handler.inl4
-rw-r--r--src/daemon/command_line_args.h32
-rw-r--r--src/daemon/command_parser_executor.cpp50
-rw-r--r--src/daemon/core.h7
-rw-r--r--src/daemon/daemon.cpp5
-rw-r--r--src/daemon/main.cpp8
-rw-r--r--src/daemon/rpc.h4
-rw-r--r--src/daemon/rpc_command_executor.cpp6
-rw-r--r--src/daemon/rpc_command_executor.h2
-rw-r--r--src/daemonizer/CMakeLists.txt4
-rw-r--r--src/daemonizer/posix_fork.cpp2
-rw-r--r--src/device/device_default.cpp4
-rw-r--r--src/device/device_ledger.cpp4
-rw-r--r--src/gen_multisig/gen_multisig.cpp20
-rw-r--r--src/p2p/net_node.cpp10
-rw-r--r--src/p2p/net_node.h6
-rw-r--r--src/p2p/net_node.inl36
-rw-r--r--src/ringct/rctSigs.cpp23
-rw-r--r--src/ringct/rctSigs.h2
-rw-r--r--src/rpc/core_rpc_server.cpp28
-rw-r--r--src/rpc/core_rpc_server.h8
-rw-r--r--src/rpc/core_rpc_server_commands_defs.h4
-rw-r--r--src/rpc/daemon_handler.cpp8
-rw-r--r--src/rpc/message_data_structs.h2
-rw-r--r--src/serialization/binary_archive.h2
-rw-r--r--src/serialization/variant.h2
-rw-r--r--src/simplewallet/CMakeLists.txt1
-rw-r--r--src/simplewallet/simplewallet.cpp158
-rw-r--r--src/wallet/api/address_book.cpp6
-rw-r--r--src/wallet/api/transaction_history.cpp2
-rw-r--r--src/wallet/api/unsigned_transaction.cpp8
-rw-r--r--src/wallet/api/wallet.cpp48
-rw-r--r--src/wallet/api/wallet.h4
-rw-r--r--src/wallet/api/wallet2_api.h93
-rw-r--r--src/wallet/api/wallet_manager.cpp24
-rw-r--r--src/wallet/api/wallet_manager.h12
-rw-r--r--src/wallet/wallet2.cpp170
-rw-r--r--src/wallet/wallet2.h11
-rw-r--r--src/wallet/wallet_errors.h16
-rw-r--r--src/wallet/wallet_rpc_server.cpp78
-rw-r--r--src/wallet/wallet_rpc_server_commands_defs.h8
72 files changed, 978 insertions, 480 deletions
diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp
index bdec846d1..f9c829013 100644
--- a/src/blockchain_db/lmdb/db_lmdb.cpp
+++ b/src/blockchain_db/lmdb/db_lmdb.cpp
@@ -451,7 +451,8 @@ void BlockchainLMDB::do_resize(uint64_t increase_size)
boost::filesystem::space_info si = boost::filesystem::space(path);
if(si.available < add_size)
{
- MERROR("!! WARNING: Insufficient free space to extend database !!: " << si.available / 1LL << 20L);
+ MERROR("!! WARNING: Insufficient free space to extend database !!: " <<
+ (si.available >> 20L) << " MB available, " << (add_size >> 20L) << " MB needed");
return;
}
}
@@ -472,7 +473,7 @@ void BlockchainLMDB::do_resize(uint64_t increase_size)
// add 1Gb per resize, instead of doing a percentage increase
uint64_t new_mapsize = (double) mei.me_mapsize + add_size;
- // If given, use increase_size intead of above way of resizing.
+ // If given, use increase_size instead of above way of resizing.
// This is currently used for increasing by an estimated size at start of new
// batch txn.
if (increase_size > 0)
diff --git a/src/blockchain_utilities/blockchain_export.cpp b/src/blockchain_utilities/blockchain_export.cpp
index b3e11605d..5a49f3478 100644
--- a/src/blockchain_utilities/blockchain_export.cpp
+++ b/src/blockchain_utilities/blockchain_export.cpp
@@ -58,7 +58,6 @@ int main(int argc, char* argv[])
tools::on_startup();
- boost::filesystem::path default_data_path {tools::get_default_data_dir()};
boost::filesystem::path output_file_path;
po::options_description desc_cmd_only("Command line options");
@@ -75,6 +74,7 @@ int main(int argc, char* argv[])
command_line::add_arg(desc_cmd_sett, cryptonote::arg_data_dir);
command_line::add_arg(desc_cmd_sett, arg_output_file);
command_line::add_arg(desc_cmd_sett, cryptonote::arg_testnet_on);
+ command_line::add_arg(desc_cmd_sett, cryptonote::arg_stagenet_on);
command_line::add_arg(desc_cmd_sett, arg_log_level);
command_line::add_arg(desc_cmd_sett, arg_database);
command_line::add_arg(desc_cmd_sett, arg_block_stop);
@@ -112,6 +112,12 @@ int main(int argc, char* argv[])
LOG_PRINT_L0("Starting...");
bool opt_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
+ bool opt_stagenet = command_line::get_arg(vm, cryptonote::arg_stagenet_on);
+ if (opt_testnet && opt_stagenet)
+ {
+ std::cerr << "Can't specify more than one of --testnet and --stagenet" << std::endl;
+ return 1;
+ }
bool opt_blocks_dat = command_line::get_arg(vm, arg_blocks_dat);
std::string m_config_folder;
@@ -169,7 +175,7 @@ int main(int argc, char* argv[])
LOG_PRINT_L0("Error opening database: " << e.what());
return 1;
}
- r = core_storage->init(db, opt_testnet);
+ r = core_storage->init(db, opt_testnet ? cryptonote::TESTNET : opt_stagenet ? cryptonote::STAGENET : cryptonote::MAINNET);
CHECK_AND_ASSERT_MES(r, 1, "Failed to initialize source blockchain storage");
LOG_PRINT_L0("Source blockchain storage initialized OK");
diff --git a/src/blockchain_utilities/blockchain_import.cpp b/src/blockchain_utilities/blockchain_import.cpp
index 6195e47e7..caa549c13 100644
--- a/src/blockchain_utilities/blockchain_import.cpp
+++ b/src/blockchain_utilities/blockchain_import.cpp
@@ -53,6 +53,7 @@ bool opt_batch = true;
bool opt_verify = true; // use add_new_block, which does verification before calling add_block
bool opt_resume = true;
bool opt_testnet = true;
+bool opt_stagenet = true;
// number of blocks per batch transaction
// adjustable through command-line argument according to available RAM
@@ -574,8 +575,6 @@ int main(int argc, char* argv[])
tools::on_startup();
- boost::filesystem::path default_data_path {tools::get_default_data_dir()};
- boost::filesystem::path default_testnet_data_path {default_data_path / "testnet"};
std::string import_file_path;
po::options_description desc_cmd_only("Command line options");
@@ -671,6 +670,12 @@ int main(int argc, char* argv[])
}
opt_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
+ opt_stagenet = command_line::get_arg(vm, cryptonote::arg_stagenet_on);
+ if (opt_testnet && opt_stagenet)
+ {
+ std::cerr << "Error: Can't specify more than one of --testnet and --stagenet" << ENDL;
+ return 1;
+ }
m_config_folder = command_line::get_arg(vm, cryptonote::arg_data_dir);
db_arg_str = command_line::get_arg(vm, arg_database);
@@ -728,7 +733,7 @@ int main(int argc, char* argv[])
MINFO("batch: " << std::boolalpha << opt_batch << std::noboolalpha);
}
MINFO("resume: " << std::boolalpha << opt_resume << std::noboolalpha);
- MINFO("testnet: " << std::boolalpha << opt_testnet << std::noboolalpha);
+ MINFO("nettype: " << (opt_testnet ? "testnet" : opt_stagenet ? "stagenet" : "mainnet"));
MINFO("bootstrap file path: " << import_file_path);
MINFO("database path: " << m_config_folder);
diff --git a/src/blocks/CMakeLists.txt b/src/blocks/CMakeLists.txt
index 079c59fb5..cf3f0b354 100644
--- a/src/blocks/CMakeLists.txt
+++ b/src/blocks/CMakeLists.txt
@@ -32,7 +32,8 @@ if(APPLE)
else()
add_custom_command(OUTPUT blocks.o MAIN_DEPENDENCY blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocks.o blocks.dat)
add_custom_command(OUTPUT testnet_blocks.o MAIN_DEPENDENCY testnet_blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/testnet_blocks.o testnet_blocks.dat)
- add_library(blocks STATIC blocks.o testnet_blocks.o blockexports.c)
+ add_custom_command(OUTPUT stagenet_blocks.o MAIN_DEPENDENCY stagenet_blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/stagenet_blocks.o stagenet_blocks.dat)
+ add_library(blocks STATIC blocks.o testnet_blocks.o stagenet_blocks.o blockexports.c)
set_target_properties(blocks PROPERTIES LINKER_LANGUAGE C)
endif()
diff --git a/src/blocks/blockexports.c b/src/blocks/blockexports.c
index 477167a12..0154b0413 100644
--- a/src/blocks/blockexports.c
+++ b/src/blocks/blockexports.c
@@ -16,20 +16,24 @@ extern const struct mach_header_64 _mh_execute_header;
#endif
#endif
-const unsigned char *get_blocks_dat_start(int testnet)
+const unsigned char *get_blocks_dat_start(int testnet, int stagenet)
{
size_t size;
if (testnet)
return getsectiondata(&_mh_execute_header, "__DATA", "__testnet_blocks_dat", &size);
+ else if (stagenet)
+ return getsectiondata(&_mh_execute_header, "__DATA", "__stagenet_blocks_dat", &size);
else
return getsectiondata(&_mh_execute_header, "__DATA", "__blocks_dat", &size);
}
-size_t get_blocks_dat_size(int testnet)
+size_t get_blocks_dat_size(int testnet, int stagenet)
{
size_t size;
if (testnet)
getsectiondata(&_mh_execute_header, "__DATA", "__testnet_blocks_dat", &size);
+ else if (stagenet)
+ getsectiondata(&_mh_execute_header, "__DATA", "__stagenet_blocks_dat", &size);
else
getsectiondata(&_mh_execute_header, "__DATA", "__blocks_dat", &size);
return size;
@@ -42,30 +46,40 @@ size_t get_blocks_dat_size(int testnet)
#define _binary_blocks_end binary_blocks_dat_end
#define _binary_testnet_blocks_start binary_testnet_blocks_dat_start
#define _binary_testnet_blocks_end binary_testnet_blocks_dat_end
+#define _binary_stagenet_blocks_start binary_stagenet_blocks_dat_start
+#define _binary_stagenet_blocks_end binary_stagenet_blocks_dat_end
#else
#define _binary_blocks_start _binary_blocks_dat_start
#define _binary_blocks_end _binary_blocks_dat_end
#define _binary_testnet_blocks_start _binary_testnet_blocks_dat_start
#define _binary_testnet_blocks_end _binary_testnet_blocks_dat_end
+#define _binary_stagenet_blocks_start _binary_stagenet_blocks_dat_start
+#define _binary_stagenet_blocks_end _binary_stagenet_blocks_dat_end
#endif
extern const unsigned char _binary_blocks_start[];
extern const unsigned char _binary_blocks_end[];
extern const unsigned char _binary_testnet_blocks_start[];
extern const unsigned char _binary_testnet_blocks_end[];
+extern const unsigned char _binary_stagenet_blocks_start[];
+extern const unsigned char _binary_stagenet_blocks_end[];
-const unsigned char *get_blocks_dat_start(int testnet)
+const unsigned char *get_blocks_dat_start(int testnet, int stagenet)
{
if (testnet)
return _binary_testnet_blocks_start;
+ else if (stagenet)
+ return _binary_stagenet_blocks_start;
else
return _binary_blocks_start;
}
-size_t get_blocks_dat_size(int testnet)
+size_t get_blocks_dat_size(int testnet, int stagenet)
{
if (testnet)
return (size_t) (_binary_testnet_blocks_end - _binary_testnet_blocks_start);
+ else if (stagenet)
+ return (size_t) (_binary_stagenet_blocks_end - _binary_stagenet_blocks_start);
else
return (size_t) (_binary_blocks_end - _binary_blocks_start);
}
diff --git a/src/blocks/blocks.h b/src/blocks/blocks.h
index b842009a4..ec683f47e 100644
--- a/src/blocks/blocks.h
+++ b/src/blocks/blocks.h
@@ -5,8 +5,8 @@
extern "C" {
#endif
-const unsigned char *get_blocks_dat_start(int testnet);
-size_t get_blocks_dat_size(int testnet);
+const unsigned char *get_blocks_dat_start(int testnet, int stagenet);
+size_t get_blocks_dat_size(int testnet, int stagenet);
#ifdef __cplusplus
}
diff --git a/src/blocks/stagenet_blocks.dat b/src/blocks/stagenet_blocks.dat
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/blocks/stagenet_blocks.dat
diff --git a/src/checkpoints/checkpoints.cpp b/src/checkpoints/checkpoints.cpp
index eadfb4df7..f709465c8 100644
--- a/src/checkpoints/checkpoints.cpp
+++ b/src/checkpoints/checkpoints.cpp
@@ -159,14 +159,20 @@ namespace cryptonote
return true;
}
- bool checkpoints::init_default_checkpoints(bool testnet)
+ bool checkpoints::init_default_checkpoints(network_type nettype)
{
- if (testnet)
+ if (nettype == TESTNET)
{
ADD_CHECKPOINT(0, "48ca7cd3c8de5b6a4d53d2861fbdaedca141553559f9be9520068053cda8430b");
ADD_CHECKPOINT(1000000, "46b690b710a07ea051bc4a6b6842ac37be691089c0f7758cfeec4d5fc0b4a258");
return true;
}
+ if (nettype == STAGENET)
+ {
+ ADD_CHECKPOINT(0, "76ee3cc98646292206cd3e86f74d88b4dcc1d937088645e9b0cbca84b7ce74eb");
+ ADD_CHECKPOINT(10000, "1f8b0ce313f8b9ba9a46108bfd285c45ad7c2176871fd41c3a690d4830ce2fd5");
+ return true;
+ }
ADD_CHECKPOINT(1, "771fbcd656ec1464d3a02ead5e18644030007a0fc664c0a964d30922821a8148");
ADD_CHECKPOINT(10, "c0e3b387e47042f72d8ccdca88071ff96bff1ac7cde09ae113dbb7ad3fe92381");
ADD_CHECKPOINT(100, "ac3e11ca545e57c49fca2b4e8c48c03c23be047c43e471e1394528b1f9f80b2d");
@@ -240,7 +246,7 @@ namespace cryptonote
return true;
}
- bool checkpoints::load_checkpoints_from_dns(bool testnet)
+ bool checkpoints::load_checkpoints_from_dns(network_type nettype)
{
std::vector<std::string> records;
@@ -257,7 +263,13 @@ namespace cryptonote
, "testpoints.moneropulse.co"
};
- if (!tools::dns_utils::load_txt_records_from_dns(records, testnet ? testnet_dns_urls : dns_urls))
+ static const std::vector<std::string> stagenet_dns_urls = { "stagenetpoints.moneropulse.se"
+ , "stagenetpoints.moneropulse.org"
+ , "stagenetpoints.moneropulse.net"
+ , "stagenetpoints.moneropulse.co"
+ };
+
+ if (!tools::dns_utils::load_txt_records_from_dns(records, nettype == TESTNET ? testnet_dns_urls : nettype == STAGENET ? stagenet_dns_urls : dns_urls))
return true; // why true ?
for (const auto& record : records)
@@ -290,14 +302,14 @@ namespace cryptonote
return true;
}
- bool checkpoints::load_new_checkpoints(const std::string &json_hashfile_fullpath, bool testnet, bool dns)
+ bool checkpoints::load_new_checkpoints(const std::string &json_hashfile_fullpath, network_type nettype, bool dns)
{
bool result;
result = load_checkpoints_from_json(json_hashfile_fullpath);
if (dns)
{
- result &= load_checkpoints_from_dns(testnet);
+ result &= load_checkpoints_from_dns(nettype);
}
return result;
diff --git a/src/checkpoints/checkpoints.h b/src/checkpoints/checkpoints.h
index e71861c44..61be2c27a 100644
--- a/src/checkpoints/checkpoints.h
+++ b/src/checkpoints/checkpoints.h
@@ -33,6 +33,7 @@
#include <vector>
#include "misc_log_ex.h"
#include "crypto/hash.h"
+#include "cryptonote_config.h"
#define ADD_CHECKPOINT(h, hash) CHECK_AND_ASSERT(add_checkpoint(h, hash), false);
#define JSON_HASH_FILE_NAME "checkpoints.json"
@@ -147,11 +148,11 @@ namespace cryptonote
/**
* @brief loads the default main chain checkpoints
- * @param testnet whether to load testnet checkpoints or mainnet
+ * @param nettype network type
*
* @return true unless adding a checkpoint fails
*/
- bool init_default_checkpoints(bool testnet);
+ bool init_default_checkpoints(network_type nettype);
/**
* @brief load new checkpoints
@@ -160,12 +161,12 @@ namespace cryptonote
* (optionally) from DNS.
*
* @param json_hashfile_fullpath path to the json checkpoints file
- * @param testnet whether to load testnet checkpoints or mainnet
+ * @param nettype network type
* @param dns whether or not to load DNS checkpoints
*
* @return true if loading successful and no conflicts
*/
- bool load_new_checkpoints(const std::string &json_hashfile_fullpath, bool testnet=false, bool dns=true);
+ bool load_new_checkpoints(const std::string &json_hashfile_fullpath, network_type nettype=MAINNET, bool dns=true);
/**
* @brief load new checkpoints from json
@@ -179,11 +180,11 @@ namespace cryptonote
/**
* @brief load new checkpoints from DNS
*
- * @param testnet whether to load testnet checkpoints or mainnet
+ * @param nettype network type
*
* @return true if loading successful and no conflicts
*/
- bool load_checkpoints_from_dns(bool testnet = false);
+ bool load_checkpoints_from_dns(network_type nettype = MAINNET);
private:
std::map<uint64_t, crypto::hash> m_points; //!< the checkpoints container
diff --git a/src/common/command_line.h b/src/common/command_line.h
index f67efcf86..3a869bb26 100644
--- a/src/common/command_line.h
+++ b/src/common/command_line.h
@@ -33,6 +33,7 @@
#include <functional>
#include <iostream>
#include <sstream>
+#include <array>
#include <type_traits>
#include <boost/program_options/parsers.hpp>
@@ -48,7 +49,7 @@ namespace command_line
//! \return True if `str` is `is_iequal("n" || "no" || `tr("no"))`.
bool is_no(const std::string& str);
- template<typename T, bool required = false, bool dependent = false>
+ template<typename T, bool required = false, bool dependent = false, int NUM_DEPS = 1>
struct arg_descriptor;
template<typename T>
@@ -98,6 +99,22 @@ namespace command_line
bool not_use_default;
};
+ template<typename T, int NUM_DEPS>
+ struct arg_descriptor<T, false, true, NUM_DEPS>
+ {
+ typedef T value_type;
+
+ const char* name;
+ const char* description;
+
+ T default_value;
+
+ std::array<const arg_descriptor<bool, false> *, NUM_DEPS> ref;
+ std::function<T(std::array<bool, NUM_DEPS>, bool, T)> depf;
+
+ bool not_use_default;
+ };
+
template<typename T>
boost::program_options::typed_value<T, char>* make_semantic(const arg_descriptor<T, true>& /*arg*/)
{
@@ -127,6 +144,28 @@ namespace command_line
return semantic;
}
+ template<typename T, int NUM_DEPS>
+ boost::program_options::typed_value<T, char>* make_semantic(const arg_descriptor<T, false, true, NUM_DEPS>& arg)
+ {
+ auto semantic = boost::program_options::value<T>();
+ if (!arg.not_use_default) {
+ std::array<bool, NUM_DEPS> depval;
+ depval.fill(false);
+ std::ostringstream format;
+ format << arg.depf(depval, true, arg.default_value);
+ for (size_t i = 0; i < depval.size(); ++i)
+ {
+ depval.fill(false);
+ depval[i] = true;
+ format << ", " << arg.depf(depval, true, arg.default_value) << " if '" << arg.ref[i]->name << "'";
+ }
+ for (size_t i = 0; i < depval.size(); ++i)
+ depval[i] = arg.ref[i]->default_value;
+ semantic->default_value(arg.depf(depval, true, arg.default_value), format.str());
+ }
+ return semantic;
+ }
+
template<typename T>
boost::program_options::typed_value<T, char>* make_semantic(const arg_descriptor<T, false>& arg, const T& def)
{
@@ -144,8 +183,8 @@ namespace command_line
return semantic;
}
- template<typename T, bool required, bool dependent>
- void add_arg(boost::program_options::options_description& description, const arg_descriptor<T, required, dependent>& arg, bool unique = true)
+ template<typename T, bool required, bool dependent, int NUM_DEPS>
+ void add_arg(boost::program_options::options_description& description, const arg_descriptor<T, required, dependent, NUM_DEPS>& arg, bool unique = true)
{
if (0 != description.find_nothrow(arg.name, false))
{
@@ -214,35 +253,44 @@ namespace command_line
}
}
- template<typename T, bool required>
- bool has_arg(const boost::program_options::variables_map& vm, const arg_descriptor<T, required>& arg)
+ template<typename T, bool required, bool dependent, int NUM_DEPS>
+ typename std::enable_if<!std::is_same<T, bool>::value, bool>::type has_arg(const boost::program_options::variables_map& vm, const arg_descriptor<T, required, dependent, NUM_DEPS>& arg)
{
auto value = vm[arg.name];
return !value.empty();
}
- template<typename T, bool required, bool dependent>
- bool is_arg_defaulted(const boost::program_options::variables_map& vm, const arg_descriptor<T, required, dependent>& arg)
+ template<typename T, bool required, bool dependent, int NUM_DEPS>
+ bool is_arg_defaulted(const boost::program_options::variables_map& vm, const arg_descriptor<T, required, dependent, NUM_DEPS>& arg)
{
return vm[arg.name].defaulted();
}
- template<typename T, bool required>
- T get_arg(const boost::program_options::variables_map& vm, const arg_descriptor<T, required, true>& arg)
+ template<typename T>
+ T get_arg(const boost::program_options::variables_map& vm, const arg_descriptor<T, false, true>& arg)
{
return arg.depf(get_arg(vm, arg.ref), is_arg_defaulted(vm, arg), vm[arg.name].template as<T>());
}
+ template<typename T, int NUM_DEPS>
+ T get_arg(const boost::program_options::variables_map& vm, const arg_descriptor<T, false, true, NUM_DEPS>& arg)
+ {
+ std::array<bool, NUM_DEPS> depval;
+ for (size_t i = 0; i < depval.size(); ++i)
+ depval[i] = get_arg(vm, *arg.ref[i]);
+ return arg.depf(depval, is_arg_defaulted(vm, arg), vm[arg.name].template as<T>());
+ }
+
template<typename T, bool required>
T get_arg(const boost::program_options::variables_map& vm, const arg_descriptor<T, required>& arg)
{
return vm[arg.name].template as<T>();
}
- template<>
- inline bool has_arg<bool, false>(const boost::program_options::variables_map& vm, const arg_descriptor<bool, false>& arg)
+ template<bool dependent, int NUM_DEPS>
+ inline bool has_arg(const boost::program_options::variables_map& vm, const arg_descriptor<bool, false, dependent, NUM_DEPS>& arg)
{
- return get_arg<bool, false>(vm, arg);
+ return get_arg(vm, arg);
}
diff --git a/src/common/util.cpp b/src/common/util.cpp
index e0f3cd655..d01da0fb7 100644
--- a/src/common/util.cpp
+++ b/src/common/util.cpp
@@ -435,15 +435,17 @@ std::string get_nix_version_display_string()
#ifdef WIN32
std::string get_special_folder_path(int nfolder, bool iscreate)
{
- namespace fs = boost::filesystem;
- char psz_path[MAX_PATH] = "";
+ WCHAR psz_path[MAX_PATH] = L"";
- if(SHGetSpecialFolderPathA(NULL, psz_path, nfolder, iscreate))
+ if (SHGetSpecialFolderPathW(NULL, psz_path, nfolder, iscreate))
{
- return psz_path;
+ int size_needed = WideCharToMultiByte(CP_UTF8, 0, psz_path, wcslen(psz_path), NULL, 0, NULL, NULL);
+ std::string folder_name(size_needed, 0);
+ WideCharToMultiByte(CP_UTF8, 0, psz_path, wcslen(psz_path), &folder_name[0], size_needed, NULL, NULL);
+ return folder_name;
}
- LOG_ERROR("SHGetSpecialFolderPathA() failed, could not obtain requested path.");
+ LOG_ERROR("SHGetSpecialFolderPathW() failed, could not obtain requested path.");
return "";
}
#endif
@@ -501,13 +503,18 @@ std::string get_nix_version_display_string()
int code;
#if defined(WIN32)
// Maximizing chances for success
- DWORD attributes = ::GetFileAttributes(replaced_name.c_str());
+ WCHAR wide_replacement_name[1000];
+ MultiByteToWideChar(CP_UTF8, 0, replacement_name.c_str(), replacement_name.size() + 1, wide_replacement_name, 1000);
+ WCHAR wide_replaced_name[1000];
+ MultiByteToWideChar(CP_UTF8, 0, replaced_name.c_str(), replaced_name.size() + 1, wide_replaced_name, 1000);
+
+ DWORD attributes = ::GetFileAttributesW(wide_replaced_name);
if (INVALID_FILE_ATTRIBUTES != attributes)
{
- ::SetFileAttributes(replaced_name.c_str(), attributes & (~FILE_ATTRIBUTE_READONLY));
+ ::SetFileAttributesW(wide_replaced_name, attributes & (~FILE_ATTRIBUTE_READONLY));
}
- bool ok = 0 != ::MoveFileEx(replacement_name.c_str(), replaced_name.c_str(), MOVEFILE_REPLACE_EXISTING);
+ bool ok = 0 != ::MoveFileExW(wide_replacement_name, wide_replaced_name, MOVEFILE_REPLACE_EXISTING);
code = ok ? 0 : static_cast<int>(::GetLastError());
#else
bool ok = 0 == std::rename(replacement_name.c_str(), replaced_name.c_str());
diff --git a/src/common/varint.h b/src/common/varint.h
index 262bd1360..151d13dbf 100644
--- a/src/common/varint.h
+++ b/src/common/varint.h
@@ -45,7 +45,7 @@
* is as follows: Strip the msb of each byte, then from left to right,
* read in what remains, placing it in reverse, into the buffer. Thus,
* the following bit stream: 0xff02 would return 0x027f. 0xff turns
- * into 0x7f, is placed on the beggining of the buffer, then 0x02 is
+ * into 0x7f, is placed on the beginning of the buffer, then 0x02 is
* unchanged, since its msb is not set, and placed at the end of the
* buffer.
*/
@@ -108,7 +108,7 @@ namespace tools {
return EVARINT_REPRESENT;
}
- write |= static_cast<T>(byte & 0x7f) << shift; /* Does the actualy placing into write, stripping the first bit */
+ write |= static_cast<T>(byte & 0x7f) << shift; /* Does the actually placing into write, stripping the first bit */
/* If there is no next */
if ((byte & 0x80) == 0) {
diff --git a/src/crypto/chacha.h b/src/crypto/chacha.h
index b45c3d7c7..22da53bd0 100644
--- a/src/crypto/chacha.h
+++ b/src/crypto/chacha.h
@@ -69,10 +69,10 @@ namespace crypto {
chacha20(data, length, key.data(), reinterpret_cast<const uint8_t*>(&iv), cipher);
}
- inline void generate_chacha_key(const void *data, size_t size, chacha_key& key, bool prehashed=false) {
+ inline void generate_chacha_key(const void *data, size_t size, chacha_key& key, int cn_variant = 0, bool prehashed=false) {
static_assert(sizeof(chacha_key) <= sizeof(hash), "Size of hash must be at least that of chacha_key");
tools::scrubbed_arr<char, HASH_SIZE> pwd_hash;
- crypto::cn_slow_hash_pre(data, size, pwd_hash.data(), prehashed);
+ crypto::cn_slow_hash_pre(data, size, pwd_hash.data(), cn_variant, prehashed);
memcpy(&key, pwd_hash.data(), sizeof(key));
}
diff --git a/src/crypto/crypto.cpp b/src/crypto/crypto.cpp
index afac105e4..0c70b9eeb 100644
--- a/src/crypto/crypto.cpp
+++ b/src/crypto/crypto.cpp
@@ -107,7 +107,7 @@ namespace crypto {
/*
* generate public and secret keys from a random 256-bit integer
- * TODO: allow specifiying random value (for wallet recovery)
+ * TODO: allow specifying random value (for wallet recovery)
*
*/
secret_key crypto_ops::generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key, bool recover) {
diff --git a/src/crypto/hash-ops.h b/src/crypto/hash-ops.h
index 130bf02db..934d464de 100644
--- a/src/crypto/hash-ops.h
+++ b/src/crypto/hash-ops.h
@@ -79,8 +79,8 @@ enum {
};
void cn_fast_hash(const void *data, size_t length, char *hash);
-void cn_slow_hash(const void *data, size_t length, char *hash);
-void cn_slow_hash_pre(const void *data, size_t length, char *hash, bool pre);
+void cn_slow_hash(const void *data, size_t length, char *hash, int variant);
+void cn_slow_hash_pre(const void *data, size_t length, char *hash, int variant, bool pre);
void hash_extra_blake(const void *data, size_t length, char *hash);
void hash_extra_groestl(const void *data, size_t length, char *hash);
diff --git a/src/crypto/hash.h b/src/crypto/hash.h
index 14104699b..bf4f4c096 100644
--- a/src/crypto/hash.h
+++ b/src/crypto/hash.h
@@ -71,8 +71,8 @@ namespace crypto {
return h;
}
- inline void cn_slow_hash(const void *data, std::size_t length, hash &hash) {
- cn_slow_hash(data, length, reinterpret_cast<char *>(&hash));
+ inline void cn_slow_hash(const void *data, std::size_t length, hash &hash, int variant = 0) {
+ cn_slow_hash(data, length, reinterpret_cast<char *>(&hash), variant);
}
inline void tree_hash(const hash *hashes, std::size_t count, hash &root_hash) {
diff --git a/src/crypto/slow-hash.c b/src/crypto/slow-hash.c
index 36bfba9fd..c733d7b39 100644
--- a/src/crypto/slow-hash.c
+++ b/src/crypto/slow-hash.c
@@ -32,6 +32,8 @@
#include <stddef.h>
#include <stdint.h>
#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
#include "common/int-util.h"
#include "hash-ops.h"
@@ -47,6 +49,46 @@
extern int aesb_single_round(const uint8_t *in, uint8_t*out, const uint8_t *expandedKey);
extern int aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *expandedKey);
+#define VARIANT1_1(p) \
+ do if (variant > 0) \
+ { \
+ const uint8_t tmp = ((const uint8_t*)(p))[11]; \
+ static const uint32_t table = 0x75310; \
+ const uint8_t index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; \
+ ((uint8_t*)(p))[11] = tmp ^ ((table >> index) & 0x30); \
+ } while(0)
+
+#define VARIANT1_2(p) \
+ do if (variant > 0) \
+ { \
+ xor64(p, tweak1_2); \
+ } while(0)
+
+#define VARIANT1_CHECK() \
+ do if (length < 43) \
+ { \
+ fprintf(stderr, "Cryptonight variants need at least 43 bytes of data"); \
+ _exit(1); \
+ } while(0)
+
+#define NONCE_POINTER (((const uint8_t*)data)+35)
+
+#define VARIANT1_PORTABLE_INIT() \
+ uint8_t tweak1_2[8]; \
+ do if (variant > 0) \
+ { \
+ VARIANT1_CHECK(); \
+ memcpy(&tweak1_2, &state.hs.b[192], sizeof(tweak1_2)); \
+ xor64(tweak1_2, NONCE_POINTER); \
+ } while(0)
+
+#define VARIANT1_INIT64() \
+ if (variant > 0) \
+ { \
+ VARIANT1_CHECK(); \
+ } \
+ const uint64_t tweak1_2 = variant > 0 ? (state.hs.w[24] ^ (*((const uint64_t*)NONCE_POINTER))) : 0
+
#if !defined NO_AES && (defined(__x86_64__) || (defined(_MSC_VER) && defined(_WIN64)))
// Optimised code below, uses x86-specific intrinsics, SSE2, AES-NI
// Fall back to more portable code is down at the bottom
@@ -125,6 +167,7 @@ extern int aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *exp
_mm_store_si128(R128(c), _c); \
_b = _mm_xor_si128(_b, _c); \
_mm_store_si128(R128(&hp_state[j]), _b); \
+ VARIANT1_1(&hp_state[j]); \
j = state_index(c); \
p = U64(&hp_state[j]); \
b[0] = p[0]; b[1] = p[1]; \
@@ -133,6 +176,7 @@ extern int aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *exp
p = U64(&hp_state[j]); \
p[0] = a[0]; p[1] = a[1]; \
a[0] ^= b[0]; a[1] ^= b[1]; \
+ VARIANT1_2(p + 1); \
_b = _c; \
#if defined(_MSC_VER)
@@ -183,6 +227,11 @@ STATIC INLINE void xor_blocks(uint8_t *a, const uint8_t *b)
U64(a)[1] ^= U64(b)[1];
}
+STATIC INLINE void xor64(uint64_t *a, const uint64_t b)
+{
+ *a ^= b;
+}
+
/**
* @brief uses cpuid to determine if the CPU supports the AES instructions
* @return true if the CPU supports AES, false otherwise
@@ -515,11 +564,11 @@ void slow_hash_free_state(void)
* @param length the length in bytes of the data
* @param hash a pointer to a buffer in which the final 256 bit hash will be stored
*/
-void cn_slow_hash(const void *data, size_t length, char *hash) {
- cn_slow_hash_pre(data,length,hash,false);
+void cn_slow_hash(const void *data, size_t length, char *hash, int variant) {
+ cn_slow_hash_pre(data,length,hash,variant,false);
}
-void cn_slow_hash_pre(const void *data, size_t length, char *hash, bool prehashed)
+void cn_slow_hash_pre(const void *data, size_t length, char *hash, int variant, bool prehashed)
{
RDATA_ALIGN16 uint8_t expandedKey[240]; /* These buffers are aligned to use later with SSE functions */
@@ -553,6 +602,8 @@ void cn_slow_hash_pre(const void *data, size_t length, char *hash, bool prehashe
}
memcpy(text, state.init, INIT_SIZE_BYTE);
+ VARIANT1_INIT64();
+
/* CryptoNight Step 2: Iteratively encrypt the results from Keccak to fill
* the 2MB large random access buffer.
*/
@@ -676,6 +727,11 @@ void slow_hash_free_state(void)
#define U64(x) ((uint64_t *) (x))
+STATIC INLINE void xor64(uint64 *a, const uint64 b)
+{
+ *a ^= b;
+}
+
#pragma pack(push, 1)
union cn_slow_hash_state
{
@@ -712,6 +768,7 @@ union cn_slow_hash_state
vst1q_u8((uint8_t *)c, _c); \
_b = veorq_u8(_b, _c); \
vst1q_u8(&hp_state[j], _b); \
+ VARIANT1_1(&hp_state[j]); \
j = state_index(c); \
p = U64(&hp_state[j]); \
b[0] = p[0]; b[1] = p[1]; \
@@ -720,6 +777,7 @@ union cn_slow_hash_state
p = U64(&hp_state[j]); \
p[0] = a[0]; p[1] = a[1]; \
a[0] ^= b[0]; a[1] ^= b[1]; \
+ VARIANT1_2(p + 1); \
_b = _c; \
@@ -851,7 +909,7 @@ STATIC INLINE void aes_pseudo_round_xor(const uint8_t *in, uint8_t *out, const u
}
}
-void cn_slow_hash(const void *data, size_t length, char *hash)
+void cn_slow_hash(const void *data, size_t length, char *hash, int variant)
{
RDATA_ALIGN16 uint8_t expandedKey[240];
RDATA_ALIGN16 uint8_t hp_state[MEMORY];
@@ -877,6 +935,8 @@ void cn_slow_hash(const void *data, size_t length, char *hash)
hash_process(&state.hs, data, length);
memcpy(text, state.init, INIT_SIZE_BYTE);
+ VARIANT1_INIT64();
+
/* CryptoNight Step 2: Iteratively encrypt the results from Keccak to fill
* the 2MB large random access buffer.
*/
@@ -1045,7 +1105,7 @@ STATIC INLINE void xor_blocks(uint8_t* a, const uint8_t* b)
U64(a)[1] ^= U64(b)[1];
}
-void cn_slow_hash(const void *data, size_t length, char *hash)
+void cn_slow_hash(const void *data, size_t length, char *hash, int variant)
{
uint8_t text[INIT_SIZE_BYTE];
uint8_t a[AES_BLOCK_SIZE];
@@ -1074,6 +1134,8 @@ void cn_slow_hash(const void *data, size_t length, char *hash)
hash_process(&state.hs, data, length);
memcpy(text, state.init, INIT_SIZE_BYTE);
+ VARIANT1_INIT64();
+
aes_ctx = (oaes_ctx *) oaes_alloc();
oaes_key_import_data(aes_ctx, state.hs.b, AES_KEY_SIZE);
@@ -1103,6 +1165,7 @@ void cn_slow_hash(const void *data, size_t length, char *hash)
xor_blocks(b, p);
swap_blocks(b, p);
swap_blocks(a, b);
+ VARIANT1_1(p);
// Iteration 2
p = &long_state[state_index(a)];
@@ -1112,6 +1175,7 @@ void cn_slow_hash(const void *data, size_t length, char *hash)
swap_blocks(b, p);
xor_blocks(b, p);
swap_blocks(a, b);
+ VARIANT1_2(U64(p) + 1);
}
memcpy(text, state.init, INIT_SIZE_BYTE);
@@ -1206,6 +1270,15 @@ static void xor_blocks(uint8_t* a, const uint8_t* b) {
}
}
+static void xor64(uint8_t* left, const uint8_t* right)
+{
+ size_t i;
+ for (i = 0; i < 8; ++i)
+ {
+ left[i] ^= right[i];
+ }
+}
+
#pragma pack(push, 1)
union cn_slow_hash_state {
union hash_state hs;
@@ -1216,7 +1289,7 @@ union cn_slow_hash_state {
};
#pragma pack(pop)
-void cn_slow_hash(const void *data, size_t length, char *hash) {
+void cn_slow_hash(const void *data, size_t length, char *hash, int variant) {
uint8_t long_state[MEMORY];
union cn_slow_hash_state state;
uint8_t text[INIT_SIZE_BYTE];
@@ -1233,6 +1306,8 @@ void cn_slow_hash(const void *data, size_t length, char *hash) {
memcpy(aes_key, state.hs.b, AES_KEY_SIZE);
aes_ctx = (oaes_ctx *) oaes_alloc();
+ VARIANT1_PORTABLE_INIT();
+
oaes_key_import_data(aes_ctx, aes_key, AES_KEY_SIZE);
for (i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) {
for (j = 0; j < INIT_SIZE_BLK; j++) {
@@ -1260,6 +1335,7 @@ void cn_slow_hash(const void *data, size_t length, char *hash) {
copy_block(&long_state[j * AES_BLOCK_SIZE], c);
assert(j == e2i(a, MEMORY / AES_BLOCK_SIZE));
swap_blocks(a, b);
+ VARIANT1_1(&long_state[j * AES_BLOCK_SIZE]);
/* Iteration 2 */
j = e2i(a, MEMORY / AES_BLOCK_SIZE);
copy_block(c, &long_state[j * AES_BLOCK_SIZE]);
@@ -1267,6 +1343,7 @@ void cn_slow_hash(const void *data, size_t length, char *hash) {
sum_half_blocks(b, d);
swap_blocks(b, c);
xor_blocks(b, c);
+ VARIANT1_2(c + 8);
copy_block(&long_state[j * AES_BLOCK_SIZE], c);
assert(j == e2i(a, MEMORY / AES_BLOCK_SIZE));
swap_blocks(a, b);
diff --git a/src/cryptonote_basic/account.cpp b/src/cryptonote_basic/account.cpp
index 26c823c2a..375b17389 100644
--- a/src/cryptonote_basic/account.cpp
+++ b/src/cryptonote_basic/account.cpp
@@ -183,16 +183,16 @@ DISABLE_VS_WARNINGS(4244 4345)
return m_keys;
}
//-----------------------------------------------------------------
- std::string account_base::get_public_address_str(bool testnet) const
+ std::string account_base::get_public_address_str(network_type nettype) const
{
//TODO: change this code into base 58
- return get_account_address_as_str(testnet, false, m_keys.m_account_address);
+ return get_account_address_as_str(nettype, false, m_keys.m_account_address);
}
//-----------------------------------------------------------------
- std::string account_base::get_public_integrated_address_str(const crypto::hash8 &payment_id, bool testnet) const
+ std::string account_base::get_public_integrated_address_str(const crypto::hash8 &payment_id, network_type nettype) const
{
//TODO: change this code into base 58
- return get_account_integrated_address_as_str(testnet, m_keys.m_account_address, payment_id);
+ return get_account_integrated_address_as_str(nettype, m_keys.m_account_address, payment_id);
}
//-----------------------------------------------------------------
}
diff --git a/src/cryptonote_basic/account.h b/src/cryptonote_basic/account.h
index d734599a3..b5d6ed85d 100644
--- a/src/cryptonote_basic/account.h
+++ b/src/cryptonote_basic/account.h
@@ -73,8 +73,8 @@ namespace cryptonote
bool make_multisig(const crypto::secret_key &view_secret_key, const crypto::secret_key &spend_secret_key, const crypto::public_key &spend_public_key, const std::vector<crypto::secret_key> &multisig_keys);
void finalize_multisig(const crypto::public_key &spend_public_key);
const account_keys& get_keys() const;
- std::string get_public_address_str(bool testnet) const;
- std::string get_public_integrated_address_str(const crypto::hash8 &payment_id, bool testnet) const;
+ std::string get_public_address_str(network_type nettype) const;
+ std::string get_public_integrated_address_str(const crypto::hash8 &payment_id, network_type nettype) const;
hw::device& get_device() const {return m_keys.get_device();}
void set_device( hw::device &hwdev) {m_keys.set_device(hwdev);}
diff --git a/src/cryptonote_basic/cryptonote_basic_impl.cpp b/src/cryptonote_basic/cryptonote_basic_impl.cpp
index dbf4d4045..08a95d2e9 100644
--- a/src/cryptonote_basic/cryptonote_basic_impl.cpp
+++ b/src/cryptonote_basic/cryptonote_basic_impl.cpp
@@ -157,25 +157,26 @@ namespace cryptonote {
}
//-----------------------------------------------------------------------
std::string get_account_address_as_str(
- bool testnet
+ network_type nettype
, bool subaddress
, account_public_address const & adr
)
{
- uint64_t address_prefix = testnet ?
- (subaddress ? config::testnet::CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX : config::testnet::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX) :
+ uint64_t address_prefix = nettype == TESTNET ?
+ (subaddress ? config::testnet::CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX : config::testnet::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX) : nettype == STAGENET ?
+ (subaddress ? config::stagenet::CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX : config::stagenet::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX) :
(subaddress ? config::CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX : config::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX);
return tools::base58::encode_addr(address_prefix, t_serializable_object_to_blob(adr));
}
//-----------------------------------------------------------------------
std::string get_account_integrated_address_as_str(
- bool testnet
+ network_type nettype
, account_public_address const & adr
, crypto::hash8 const & payment_id
)
{
- uint64_t integrated_address_prefix = testnet ? config::testnet::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX : config::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX;
+ uint64_t integrated_address_prefix = nettype == TESTNET ? config::testnet::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX : nettype == STAGENET ? config::stagenet::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX : config::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX;
integrated_address iadr = {
adr, payment_id
@@ -196,16 +197,19 @@ namespace cryptonote {
//-----------------------------------------------------------------------
bool get_account_address_from_str(
address_parse_info& info
- , bool testnet
+ , network_type nettype
, std::string const & str
)
{
- uint64_t address_prefix = testnet ?
- config::testnet::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX : config::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX;
- uint64_t integrated_address_prefix = testnet ?
- config::testnet::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX : config::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX;
- uint64_t subaddress_prefix = testnet ?
- config::testnet::CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX : config::CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX;
+ uint64_t address_prefix = nettype == TESTNET ?
+ config::testnet::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX : nettype == STAGENET ?
+ config::stagenet::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX : config::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX;
+ uint64_t integrated_address_prefix = nettype == TESTNET ?
+ config::testnet::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX : nettype == STAGENET ?
+ config::stagenet::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX : config::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX;
+ uint64_t subaddress_prefix = nettype == TESTNET ?
+ config::testnet::CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX : nettype == STAGENET ?
+ config::stagenet::CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX : config::CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX;
if (2 * sizeof(public_address_outer_blob) != str.size())
{
@@ -304,17 +308,17 @@ namespace cryptonote {
//--------------------------------------------------------------------------------
bool get_account_address_from_str_or_url(
address_parse_info& info
- , bool testnet
+ , network_type nettype
, const std::string& str_or_url
, std::function<std::string(const std::string&, const std::vector<std::string>&, bool)> dns_confirm
)
{
- if (get_account_address_from_str(info, testnet, str_or_url))
+ if (get_account_address_from_str(info, nettype, str_or_url))
return true;
bool dnssec_valid;
std::string address_str = tools::dns_utils::get_account_address_as_str_from_url(str_or_url, dnssec_valid, dns_confirm);
return !address_str.empty() &&
- get_account_address_from_str(info, testnet, address_str);
+ get_account_address_from_str(info, nettype, address_str);
}
//--------------------------------------------------------------------------------
bool operator ==(const cryptonote::transaction& a, const cryptonote::transaction& b) {
diff --git a/src/cryptonote_basic/cryptonote_basic_impl.h b/src/cryptonote_basic/cryptonote_basic_impl.h
index 8943d93ea..f59785021 100644
--- a/src/cryptonote_basic/cryptonote_basic_impl.h
+++ b/src/cryptonote_basic/cryptonote_basic_impl.h
@@ -94,26 +94,26 @@ namespace cryptonote {
uint8_t get_account_integrated_address_checksum(const public_integrated_address_outer_blob& bl);
std::string get_account_address_as_str(
- bool testnet
+ network_type nettype
, bool subaddress
, const account_public_address& adr
);
std::string get_account_integrated_address_as_str(
- bool testnet
+ network_type nettype
, const account_public_address& adr
, const crypto::hash8& payment_id
);
bool get_account_address_from_str(
address_parse_info& info
- , bool testnet
+ , network_type nettype
, const std::string& str
);
bool get_account_address_from_str_or_url(
address_parse_info& info
- , bool testnet
+ , network_type nettype
, const std::string& str_or_url
, std::function<std::string(const std::string&, const std::vector<std::string>&, bool)> dns_confirm = return_first_address
);
diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp
index f462d1ca9..a10772424 100644
--- a/src/cryptonote_basic/cryptonote_format_utils.cpp
+++ b/src/cryptonote_basic/cryptonote_format_utils.cpp
@@ -1022,7 +1022,8 @@ namespace cryptonote
return true;
}
blobdata bd = get_block_hashing_blob(b);
- crypto::cn_slow_hash(bd.data(), bd.size(), res);
+ const int cn_variant = b.major_version >= 7 ? b.major_version - 6 : 0;
+ crypto::cn_slow_hash(bd.data(), bd.size(), res, cn_variant);
return true;
}
//---------------------------------------------------------------
diff --git a/src/cryptonote_basic/miner.cpp b/src/cryptonote_basic/miner.cpp
index 919872709..f949bbd2b 100644
--- a/src/cryptonote_basic/miner.cpp
+++ b/src/cryptonote_basic/miner.cpp
@@ -218,7 +218,7 @@ namespace cryptonote
command_line::add_arg(desc, arg_bg_mining_miner_target_percentage);
}
//-----------------------------------------------------------------------------------------------------
- bool miner::init(const boost::program_options::variables_map& vm, bool testnet)
+ bool miner::init(const boost::program_options::variables_map& vm, network_type nettype)
{
if(command_line::has_arg(vm, arg_extra_messages))
{
@@ -246,7 +246,7 @@ namespace cryptonote
if(command_line::has_arg(vm, arg_start_mining))
{
address_parse_info info;
- if(!cryptonote::get_account_address_from_str(info, testnet, command_line::get_arg(vm, arg_start_mining)) || info.is_subaddress)
+ if(!cryptonote::get_account_address_from_str(info, nettype, command_line::get_arg(vm, arg_start_mining)) || info.is_subaddress)
{
LOG_ERROR("Target account address " << command_line::get_arg(vm, arg_start_mining) << " has wrong format, starting daemon canceled");
return false;
@@ -602,7 +602,7 @@ namespace cryptonote
// this should take care of the case where mining is started with bg-enabled,
// and then the user decides to un-check background mining, and just do
// regular full-speed mining. I might just be over-doing it and thinking up
- // non-existant use-cases, so if the concensus is to simplify, we can remove all this fluff.
+ // non-existant use-cases, so if the consensus is to simplify, we can remove all this fluff.
/*
while( !m_is_background_mining_enabled )
{
diff --git a/src/cryptonote_basic/miner.h b/src/cryptonote_basic/miner.h
index 7bf5dc372..2bff784c7 100644
--- a/src/cryptonote_basic/miner.h
+++ b/src/cryptonote_basic/miner.h
@@ -64,7 +64,7 @@ namespace cryptonote
public:
miner(i_miner_handler* phandler);
~miner();
- bool init(const boost::program_options::variables_map& vm, bool testnet);
+ bool init(const boost::program_options::variables_map& vm, network_type nettype);
static void init_options(boost::program_options::options_description& desc);
bool set_block_template(const block& bl, const difficulty_type& diffic, uint64_t height);
bool on_block_chain_update();
diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h
index f9460e7db..171fc194a 100644
--- a/src/cryptonote_config.h
+++ b/src/cryptonote_config.h
@@ -172,7 +172,33 @@ namespace config
boost::uuids::uuid const NETWORK_ID = { {
0x12 ,0x30, 0xF1, 0x71 , 0x61, 0x04 , 0x41, 0x61, 0x17, 0x31, 0x00, 0x82, 0x16, 0xA1, 0xA1, 0x11
} }; // Bender's daydream
- std::string const GENESIS_TX = "013c01ff0001ffffffffffff0f029b2e4c0281c0b02e7c53291a94d1d0cbff8883f8024f5142ee494ffbbd0880712101168d0c4ca86fb55a4cf6a36d31431be1c53a3bd7411bb24e8832410289fa6f3b";
+ std::string const GENESIS_TX = "013c01ff0001ffffffffffff03029b2e4c0281c0b02e7c53291a94d1d0cbff8883f8024f5142ee494ffbbd08807121017767aafcde9be00dcfd098715ebcf7f410daebc582fda69d24a28e9d0bc890d1";
uint32_t const GENESIS_NONCE = 10001;
}
+
+ namespace stagenet
+ {
+ uint64_t const CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX = 24;
+ uint64_t const CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX = 25;
+ uint64_t const CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX = 36;
+ uint16_t const P2P_DEFAULT_PORT = 38080;
+ uint16_t const RPC_DEFAULT_PORT = 38081;
+ uint16_t const ZMQ_RPC_DEFAULT_PORT = 38082;
+ boost::uuids::uuid const NETWORK_ID = { {
+ 0x12 ,0x30, 0xF1, 0x71 , 0x61, 0x04 , 0x41, 0x61, 0x17, 0x31, 0x00, 0x82, 0x16, 0xA1, 0xA1, 0x12
+ } }; // Bender's daydream
+ std::string const GENESIS_TX = "013c01ff0001ffffffffffff0302df5d56da0c7d643ddd1ce61901c7bdc5fb1738bfe39fbe69c28a3a7032729c0f2101168d0c4ca86fb55a4cf6a36d31431be1c53a3bd7411bb24e8832410289fa6f3b";
+ uint32_t const GENESIS_NONCE = 10002;
+ }
+}
+
+namespace cryptonote
+{
+ enum network_type : uint8_t
+ {
+ MAINNET = 0,
+ TESTNET,
+ STAGENET,
+ FAKECHAIN
+ };
}
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp
index fe4004caa..d88cc1bf9 100644
--- a/src/cryptonote_core/blockchain.cpp
+++ b/src/cryptonote_core/blockchain.cpp
@@ -132,6 +132,16 @@ static const struct {
};
static const uint64_t testnet_hard_fork_version_1_till = 624633;
+static const struct {
+ uint8_t version;
+ uint64_t height;
+ uint8_t threshold;
+ time_t time;
+} stagenet_hard_forks[] = {
+ // version 1 from the start of the blockchain
+ { 1, 1, 0, 1341378000 },
+};
+
//------------------------------------------------------------------
Blockchain::Blockchain(tx_memory_pool& tx_pool) :
m_db(), m_tx_pool(tx_pool), m_hardfork(NULL), m_timestamps_and_difficulties_height(0), m_current_block_cumul_sz_limit(0), m_current_block_cumul_sz_median(0),
@@ -306,14 +316,12 @@ uint64_t Blockchain::get_current_blockchain_height() const
//------------------------------------------------------------------
//FIXME: possibly move this into the constructor, to avoid accidentally
// dereferencing a null BlockchainDB pointer
-bool Blockchain::init(BlockchainDB* db, const bool testnet, bool offline, const cryptonote::test_options *test_options)
+bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline, const cryptonote::test_options *test_options)
{
LOG_PRINT_L3("Blockchain::" << __func__);
CRITICAL_REGION_LOCAL(m_tx_pool);
CRITICAL_REGION_LOCAL1(m_blockchain_lock);
- bool fakechain = test_options != NULL;
-
if (db == nullptr)
{
LOG_ERROR("Attempted to init Blockchain with null DB");
@@ -328,27 +336,32 @@ bool Blockchain::init(BlockchainDB* db, const bool testnet, bool offline, const
m_db = db;
- m_testnet = testnet;
+ m_nettype = test_options != NULL ? FAKECHAIN : nettype;
m_offline = offline;
if (m_hardfork == nullptr)
{
- if (fakechain)
+ if (m_nettype == FAKECHAIN || m_nettype == STAGENET)
m_hardfork = new HardFork(*db, 1, 0);
- else if (m_testnet)
+ else if (m_nettype == TESTNET)
m_hardfork = new HardFork(*db, 1, testnet_hard_fork_version_1_till);
else
m_hardfork = new HardFork(*db, 1, mainnet_hard_fork_version_1_till);
}
- if (fakechain)
+ if (m_nettype == FAKECHAIN)
{
for (size_t n = 0; test_options->hard_forks[n].first; ++n)
m_hardfork->add_fork(test_options->hard_forks[n].first, test_options->hard_forks[n].second, 0, n + 1);
}
- else if (m_testnet)
+ else if (m_nettype == TESTNET)
{
for (size_t n = 0; n < sizeof(testnet_hard_forks) / sizeof(testnet_hard_forks[0]); ++n)
m_hardfork->add_fork(testnet_hard_forks[n].version, testnet_hard_forks[n].height, testnet_hard_forks[n].threshold, testnet_hard_forks[n].time);
}
+ else if (m_nettype == STAGENET)
+ {
+ for (size_t n = 0; n < sizeof(stagenet_hard_forks) / sizeof(stagenet_hard_forks[0]); ++n)
+ m_hardfork->add_fork(stagenet_hard_forks[n].version, stagenet_hard_forks[n].height, stagenet_hard_forks[n].threshold, stagenet_hard_forks[n].time);
+ }
else
{
for (size_t n = 0; n < sizeof(mainnet_hard_forks) / sizeof(mainnet_hard_forks[0]); ++n)
@@ -367,10 +380,14 @@ bool Blockchain::init(BlockchainDB* db, const bool testnet, bool offline, const
MINFO("Blockchain not loaded, generating genesis block.");
block bl = boost::value_initialized<block>();
block_verification_context bvc = boost::value_initialized<block_verification_context>();
- if (m_testnet)
+ if (m_nettype == TESTNET)
{
generate_genesis_block(bl, config::testnet::GENESIS_TX, config::testnet::GENESIS_NONCE);
}
+ else if (m_nettype == STAGENET)
+ {
+ generate_genesis_block(bl, config::stagenet::GENESIS_TX, config::stagenet::GENESIS_NONCE);
+ }
else
{
generate_genesis_block(bl, config::GENESIS_TX, config::GENESIS_NONCE);
@@ -384,7 +401,7 @@ bool Blockchain::init(BlockchainDB* db, const bool testnet, bool offline, const
{
}
- if (!fakechain)
+ if (m_nettype != FAKECHAIN)
{
// ensure we fixup anything we found and fix in the future
m_db->fixup();
@@ -406,7 +423,7 @@ bool Blockchain::init(BlockchainDB* db, const bool testnet, bool offline, const
m_async_pool.create_thread(boost::bind(&boost::asio::io_service::run, &m_async_service));
#if defined(PER_BLOCK_CHECKPOINT)
- if (!fakechain)
+ if (m_nettype != FAKECHAIN)
load_compiled_in_block_hashes();
#endif
@@ -417,11 +434,11 @@ bool Blockchain::init(BlockchainDB* db, const bool testnet, bool offline, const
return true;
}
//------------------------------------------------------------------
-bool Blockchain::init(BlockchainDB* db, HardFork*& hf, const bool testnet, bool offline)
+bool Blockchain::init(BlockchainDB* db, HardFork*& hf, const network_type nettype, bool offline)
{
if (hf != nullptr)
m_hardfork = hf;
- bool res = init(db, testnet, offline, NULL);
+ bool res = init(db, nettype, offline, NULL);
if (hf == nullptr)
hf = m_hardfork;
return res;
@@ -2739,7 +2756,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
case rct::RCTTypeSimple:
case rct::RCTTypeSimpleBulletproof:
{
- // check all this, either recontructed (so should really pass), or not
+ // check all this, either reconstructed (so should really pass), or not
{
if (pubkeys.size() != rv.mixRing.size())
{
@@ -2797,7 +2814,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
case rct::RCTTypeFull:
case rct::RCTTypeFullBulletproof:
{
- // check all this, either recontructed (so should really pass), or not
+ // check all this, either reconstructed (so should really pass), or not
{
bool size_matches = true;
for (size_t i = 0; i < pubkeys.size(); ++i)
@@ -3547,6 +3564,7 @@ bool Blockchain::add_new_block(const block& bl_, block_verification_context& bvc
LOG_PRINT_L3("block with id = " << id << " already exists");
bvc.m_already_exists = true;
m_db->block_txn_stop();
+ m_blocks_txs_check.clear();
return false;
}
@@ -3556,7 +3574,9 @@ bool Blockchain::add_new_block(const block& bl_, block_verification_context& bvc
//chain switching or wrong block
bvc.m_added_to_main_chain = false;
m_db->block_txn_stop();
- return handle_alternative_block(bl, id, bvc);
+ bool r = handle_alternative_block(bl, id, bvc);
+ m_blocks_txs_check.clear();
+ return r;
//never relay alternative blocks
}
@@ -4316,15 +4336,17 @@ void Blockchain::cancel()
static const char expected_block_hashes_hash[] = "4b553162ee4e7af3c53666506591489c68560b9175e6e941dc96c89f96f0e35c";
void Blockchain::load_compiled_in_block_hashes()
{
- if (m_fast_sync && get_blocks_dat_start(m_testnet) != nullptr && get_blocks_dat_size(m_testnet) > 0)
+ const bool testnet = m_nettype == TESTNET;
+ const bool stagenet = m_nettype == STAGENET;
+ if (m_fast_sync && get_blocks_dat_start(testnet, stagenet) != nullptr && get_blocks_dat_size(testnet, stagenet) > 0)
{
- MINFO("Loading precomputed blocks (" << get_blocks_dat_size(m_testnet) << " bytes)");
+ MINFO("Loading precomputed blocks (" << get_blocks_dat_size(testnet, stagenet) << " bytes)");
- if (!m_testnet)
+ if (m_nettype == MAINNET)
{
// first check hash
crypto::hash hash;
- if (!tools::sha256sum(get_blocks_dat_start(m_testnet), get_blocks_dat_size(m_testnet), hash))
+ if (!tools::sha256sum(get_blocks_dat_start(testnet, stagenet), get_blocks_dat_size(testnet, stagenet), hash))
{
MERROR("Failed to hash precomputed blocks data");
return;
@@ -4344,9 +4366,9 @@ void Blockchain::load_compiled_in_block_hashes()
}
}
- if (get_blocks_dat_size(m_testnet) > 4)
+ if (get_blocks_dat_size(testnet, stagenet) > 4)
{
- const unsigned char *p = get_blocks_dat_start(m_testnet);
+ const unsigned char *p = get_blocks_dat_start(testnet, stagenet);
const uint32_t nblocks = *p | ((*(p+1))<<8) | ((*(p+2))<<16) | ((*(p+3))<<24);
if (nblocks > (std::numeric_limits<uint32_t>::max() - 4) / sizeof(hash))
{
@@ -4354,7 +4376,7 @@ void Blockchain::load_compiled_in_block_hashes()
return;
}
const size_t size_needed = 4 + nblocks * sizeof(crypto::hash);
- if(nblocks > 0 && nblocks > (m_db->height() + HASH_OF_HASHES_STEP - 1) / HASH_OF_HASHES_STEP && get_blocks_dat_size(m_testnet) >= size_needed)
+ if(nblocks > 0 && nblocks > (m_db->height() + HASH_OF_HASHES_STEP - 1) / HASH_OF_HASHES_STEP && get_blocks_dat_size(testnet, stagenet) >= size_needed)
{
p += sizeof(uint32_t);
m_blocks_hash_of_hashes.reserve(nblocks);
diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h
index b2bbff488..dd490cdd5 100644
--- a/src/cryptonote_core/blockchain.h
+++ b/src/cryptonote_core/blockchain.h
@@ -111,25 +111,25 @@ namespace cryptonote
* @brief Initialize the Blockchain state
*
* @param db a pointer to the backing store to use for the blockchain
- * @param testnet true if on testnet, else false
+ * @param nettype network type
* @param offline true if running offline, else false
* @param test_options test parameters
*
* @return true on success, false if any initialization steps fail
*/
- bool init(BlockchainDB* db, const bool testnet = false, bool offline = false, const cryptonote::test_options *test_options = NULL);
+ bool init(BlockchainDB* db, const network_type nettype = MAINNET, bool offline = false, const cryptonote::test_options *test_options = NULL);
/**
* @brief Initialize the Blockchain state
*
* @param db a pointer to the backing store to use for the blockchain
* @param hf a structure containing hardfork information
- * @param testnet true if on testnet, else false
+ * @param nettype network type
* @param offline true if running offline, else false
*
* @return true on success, false if any initialization steps fail
*/
- bool init(BlockchainDB* db, HardFork*& hf, const bool testnet = false, bool offline = false);
+ bool init(BlockchainDB* db, HardFork*& hf, const network_type nettype = MAINNET, bool offline = false);
/**
* @brief Uninitializes the blockchain state
@@ -1010,7 +1010,7 @@ namespace cryptonote
HardFork *m_hardfork;
- bool m_testnet;
+ network_type m_nettype;
bool m_offline;
std::atomic<bool> m_cancel;
diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp
index 8b837f2e4..8c0118803 100644
--- a/src/cryptonote_core/cryptonote_core.cpp
+++ b/src/cryptonote_core/cryptonote_core.cpp
@@ -71,14 +71,21 @@ namespace cryptonote
, "Run on testnet. The wallet must be launched with --testnet flag."
, false
};
- const command_line::arg_descriptor<std::string, false, true> arg_data_dir = {
+ const command_line::arg_descriptor<bool, false> arg_stagenet_on = {
+ "stagenet"
+ , "Run on stagenet. The wallet must be launched with --stagenet flag."
+ , false
+ };
+ const command_line::arg_descriptor<std::string, false, true, 2> arg_data_dir = {
"data-dir"
, "Specify data directory"
, tools::get_default_data_dir()
- , arg_testnet_on
- , [](bool testnet, bool defaulted, std::string val) {
- if (testnet)
+ , {{ &arg_testnet_on, &arg_stagenet_on }}
+ , [](std::array<bool, 2> testnet_stagenet, bool defaulted, std::string val) {
+ if (testnet_stagenet[0])
return (boost::filesystem::path(val) / "testnet").string();
+ else if (testnet_stagenet[1])
+ return (boost::filesystem::path(val) / "stagenet").string();
return val;
}
};
@@ -194,7 +201,7 @@ namespace cryptonote
//-----------------------------------------------------------------------------------------------
bool core::update_checkpoints()
{
- if (m_testnet || m_fakechain || m_disable_dns_checkpoints) return true;
+ if (m_nettype != MAINNET || m_disable_dns_checkpoints) return true;
if (m_checkpoints_updating.test_and_set()) return true;
@@ -243,6 +250,7 @@ namespace cryptonote
command_line::add_arg(desc, arg_test_drop_download_height);
command_line::add_arg(desc, arg_testnet_on);
+ command_line::add_arg(desc, arg_stagenet_on);
command_line::add_arg(desc, arg_dns_checkpoints);
command_line::add_arg(desc, arg_prep_blocks_threads);
command_line::add_arg(desc, arg_fast_block_sync);
@@ -262,16 +270,21 @@ namespace cryptonote
//-----------------------------------------------------------------------------------------------
bool core::handle_command_line(const boost::program_options::variables_map& vm)
{
- m_testnet = command_line::get_arg(vm, arg_testnet_on);
+ if (m_nettype != FAKECHAIN)
+ {
+ const bool testnet = command_line::get_arg(vm, arg_testnet_on);
+ const bool stagenet = command_line::get_arg(vm, arg_stagenet_on);
+ m_nettype = testnet ? TESTNET : stagenet ? STAGENET : MAINNET;
+ }
m_config_folder = command_line::get_arg(vm, arg_data_dir);
auto data_dir = boost::filesystem::path(m_config_folder);
- if (!m_testnet && !m_fakechain)
+ if (m_nettype == MAINNET)
{
cryptonote::checkpoints checkpoints;
- if (!checkpoints.init_default_checkpoints(m_testnet))
+ if (!checkpoints.init_default_checkpoints(m_nettype))
{
throw std::runtime_error("Failed to initialize checkpoints");
}
@@ -360,9 +373,11 @@ namespace cryptonote
{
start_time = std::time(nullptr);
- m_fakechain = test_options != NULL;
+ if (test_options != NULL)
+ {
+ m_nettype = FAKECHAIN;
+ }
bool r = handle_command_line(vm);
- bool testnet = command_line::get_arg(vm, arg_testnet_on);
std::string m_config_folder_mempool = m_config_folder;
if (config_subdir)
@@ -377,7 +392,7 @@ namespace cryptonote
size_t max_txpool_size = command_line::get_arg(vm, arg_max_txpool_size);
boost::filesystem::path folder(m_config_folder);
- if (m_fakechain)
+ if (m_nettype == FAKECHAIN)
folder /= "fake";
// make sure the data directory exists, and try to lock it
@@ -491,7 +506,7 @@ namespace cryptonote
m_blockchain_storage.set_user_options(blocks_threads,
blocks_per_sync, sync_mode, fast_sync);
- r = m_blockchain_storage.init(db.release(), m_testnet, m_offline, test_options);
+ r = m_blockchain_storage.init(db.release(), m_nettype, m_offline, test_options);
r = m_mempool.init(max_txpool_size);
CHECK_AND_ASSERT_MES(r, false, "Failed to initialize memory pool");
@@ -526,7 +541,7 @@ namespace cryptonote
return false;
}
- r = m_miner.init(vm, m_testnet);
+ r = m_miner.init(vm, m_nettype);
CHECK_AND_ASSERT_MES(r, false, "Failed to initialize miner instance");
return load_state_data();
@@ -909,7 +924,7 @@ namespace cryptonote
//-----------------------------------------------------------------------------------------------
size_t core::get_block_sync_size(uint64_t height) const
{
- static const uint64_t quick_height = m_testnet ? 801219 : 1220516;
+ static const uint64_t quick_height = m_nettype == TESTNET ? 801219 : m_nettype == MAINNET ? 1220516 : 0;
if (block_sync_size > 0)
return block_sync_size;
if (height >= quick_height)
diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h
index ce39aaddf..e1e430516 100644
--- a/src/cryptonote_core/cryptonote_core.h
+++ b/src/cryptonote_core/cryptonote_core.h
@@ -58,8 +58,9 @@ namespace cryptonote
const std::pair<uint8_t, uint64_t> *hard_forks;
};
- extern const command_line::arg_descriptor<std::string, false, true> arg_data_dir;
+ extern const command_line::arg_descriptor<std::string, false, true, 2> arg_data_dir;
extern const command_line::arg_descriptor<bool, false> arg_testnet_on;
+ extern const command_line::arg_descriptor<bool, false> arg_stagenet_on;
extern const command_line::arg_descriptor<bool> arg_offline;
/************************************************************************/
@@ -725,11 +726,11 @@ namespace cryptonote
std::pair<uint64_t, uint64_t> get_coinbase_tx_sum(const uint64_t start_offset, const size_t count);
/**
- * @brief get whether we're on testnet or not
+ * @brief get the network type we're on
*
- * @return are we on testnet?
+ * @return which network are we on?
*/
- bool get_testnet() const { return m_testnet; };
+ network_type get_nettype() const { return m_nettype; };
/**
* @brief get whether fluffy blocks are enabled
@@ -954,9 +955,7 @@ namespace cryptonote
uint64_t m_target_blockchain_height; //!< blockchain height target
- bool m_testnet; //!< are we on testnet?
-
- bool m_fakechain; //!< are we using a fake chain (for testing purposes)?
+ network_type m_nettype; //!< which network are we on?
std::string m_checkpoints_path; //!< path to json checkpoints file
time_t m_last_dns_checkpoints_update; //!< time when dns checkpoints were last updated
diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp
index d641caf80..d0a958e1e 100644
--- a/src/cryptonote_core/cryptonote_tx_utils.cpp
+++ b/src/cryptonote_core/cryptonote_tx_utils.cpp
@@ -190,6 +190,8 @@ namespace cryptonote
addr = i.addr;
++count;
}
+ if (count == 0 && change_addr)
+ return change_addr->m_view_public_key;
return addr.m_view_public_key;
}
//---------------------------------------------------------------
@@ -639,17 +641,8 @@ namespace cryptonote
//genesis block
bl = boost::value_initialized<block>();
-
- account_public_address ac = boost::value_initialized<account_public_address>();
- std::vector<size_t> sz;
- construct_miner_tx(0, 0, 0, 0, 0, ac, bl.miner_tx); // zero fee in genesis
- blobdata txb = tx_to_blob(bl.miner_tx);
- std::string hex_tx_represent = string_tools::buff_to_hex_nodelimer(txb);
-
- std::string genesis_coinbase_tx_hex = config::GENESIS_TX;
-
blobdata tx_bl;
- bool r = string_tools::parse_hexstr_to_binbuff(genesis_coinbase_tx_hex, tx_bl);
+ bool r = string_tools::parse_hexstr_to_binbuff(genesis_tx, tx_bl);
CHECK_AND_ASSERT_MES(r, false, "failed to parse coinbase tx from hard coded blob");
r = parse_and_validate_tx_from_blob(tx_bl, bl.miner_tx);
CHECK_AND_ASSERT_MES(r, false, "failed to parse coinbase tx from hard coded blob");
diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.h b/src/cryptonote_protocol/cryptonote_protocol_handler.h
index e24c964a5..d7b74c06d 100644
--- a/src/cryptonote_protocol/cryptonote_protocol_handler.h
+++ b/src/cryptonote_protocol/cryptonote_protocol_handler.h
@@ -1,6 +1,6 @@
/// @file
/// @author rfree (current maintainer/user in monero.cc project - most of code is from CryptoNote)
-/// @brief This is the orginal cryptonote protocol network-events handler, modified by us
+/// @brief This is the original cryptonote protocol network-events handler, modified by us
// Copyright (c) 2014-2018, The Monero Project
//
diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl
index ff187e8ae..7c4f16c77 100644
--- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl
+++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl
@@ -1,6 +1,6 @@
/// @file
/// @author rfree (current maintainer/user in monero.cc project - most of code is from CryptoNote)
-/// @brief This is the orginal cryptonote protocol network-events handler, modified by us
+/// @brief This is the original cryptonote protocol network-events handler, modified by us
// Copyright (c) 2014-2018, The Monero Project
//
@@ -302,7 +302,7 @@ namespace cryptonote
int64_t diff = static_cast<int64_t>(hshd.current_height) - static_cast<int64_t>(m_core.get_current_blockchain_height());
uint64_t abs_diff = std::abs(diff);
uint64_t max_block_height = std::max(hshd.current_height,m_core.get_current_blockchain_height());
- uint64_t last_block_v1 = m_core.get_testnet() ? 624633 : 1009826;
+ uint64_t last_block_v1 = m_core.get_nettype() == TESTNET ? 624633 : m_core.get_nettype() == MAINNET ? 1009826 : (uint64_t)-1;
uint64_t diff_v2 = max_block_height > last_block_v1 ? std::min(abs_diff, max_block_height - last_block_v1) : 0;
MCLOG(is_inital ? el::Level::Info : el::Level::Debug, "global", context << "Sync data returned a new top block candidate: " << m_core.get_current_blockchain_height() << " -> " << hshd.current_height
<< " [Your node is " << abs_diff << " blocks (" << ((abs_diff - diff_v2) / (24 * 60 * 60 / DIFFICULTY_TARGET_V1)) + (diff_v2 / (24 * 60 * 60 / DIFFICULTY_TARGET_V2)) << " days) "
diff --git a/src/daemon/command_line_args.h b/src/daemon/command_line_args.h
index efbae488c..add752029 100644
--- a/src/daemon/command_line_args.h
+++ b/src/daemon/command_line_args.h
@@ -37,27 +37,33 @@ namespace daemon_args
{
std::string const WINDOWS_SERVICE_NAME = "Monero Daemon";
- const command_line::arg_descriptor<std::string, false, true> arg_config_file = {
+ const command_line::arg_descriptor<std::string, false, true, 2> arg_config_file = {
"config-file"
, "Specify configuration file"
, (daemonizer::get_default_data_dir() / std::string(CRYPTONOTE_NAME ".conf")).string()
- , cryptonote::arg_testnet_on
- , [](bool testnet, bool defaulted, std::string val) {
- if (testnet && defaulted)
+ , {{ &cryptonote::arg_testnet_on, &cryptonote::arg_stagenet_on }}
+ , [](std::array<bool, 2> testnet_stagenet, bool defaulted, std::string val) {
+ if (testnet_stagenet[0] && defaulted)
return (daemonizer::get_default_data_dir() / "testnet" /
std::string(CRYPTONOTE_NAME ".conf")).string();
+ else if (testnet_stagenet[1] && defaulted)
+ return (daemonizer::get_default_data_dir() / "stagenet" /
+ std::string(CRYPTONOTE_NAME ".conf")).string();
return val;
}
};
- const command_line::arg_descriptor<std::string, false, true> arg_log_file = {
+ const command_line::arg_descriptor<std::string, false, true, 2> arg_log_file = {
"log-file"
, "Specify log file"
, (daemonizer::get_default_data_dir() / std::string(CRYPTONOTE_NAME ".log")).string()
- , cryptonote::arg_testnet_on
- , [](bool testnet, bool defaulted, std::string val) {
- if (testnet && defaulted)
+ , {{ &cryptonote::arg_testnet_on, &cryptonote::arg_stagenet_on }}
+ , [](std::array<bool, 2> testnet_stagenet, bool defaulted, std::string val) {
+ if (testnet_stagenet[0] && defaulted)
return (daemonizer::get_default_data_dir() / "testnet" /
std::string(CRYPTONOTE_NAME ".log")).string();
+ else if (testnet_stagenet[1] && defaulted)
+ return (daemonizer::get_default_data_dir() / "stagenet" /
+ std::string(CRYPTONOTE_NAME ".log")).string();
return val;
}
};
@@ -91,14 +97,16 @@ namespace daemon_args
, "127.0.0.1"
};
- const command_line::arg_descriptor<std::string, false, true> arg_zmq_rpc_bind_port = {
+ const command_line::arg_descriptor<std::string, false, true, 2> arg_zmq_rpc_bind_port = {
"zmq-rpc-bind-port"
, "Port for ZMQ RPC server to listen on"
, std::to_string(config::ZMQ_RPC_DEFAULT_PORT)
- , cryptonote::arg_testnet_on
- , [](bool testnet, bool defaulted, std::string val) {
- if (testnet && defaulted)
+ , {{ &cryptonote::arg_testnet_on, &cryptonote::arg_stagenet_on }}
+ , [](std::array<bool, 2> testnet_stagenet, bool defaulted, std::string val) {
+ if (testnet_stagenet[0] && defaulted)
return std::to_string(config::testnet::ZMQ_RPC_DEFAULT_PORT);
+ if (testnet_stagenet[1] && defaulted)
+ return std::to_string(config::stagenet::ZMQ_RPC_DEFAULT_PORT);
return val;
}
};
diff --git a/src/daemon/command_parser_executor.cpp b/src/daemon/command_parser_executor.cpp
index 09e425dd1..7a89ebc0c 100644
--- a/src/daemon/command_parser_executor.cpp
+++ b/src/daemon/command_parser_executor.cpp
@@ -268,30 +268,44 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg
}
cryptonote::address_parse_info info;
- bool testnet = false;
- if(!cryptonote::get_account_address_from_str(info, false, args.front()))
+ cryptonote::network_type nettype = cryptonote::MAINNET;
+ if(!cryptonote::get_account_address_from_str(info, cryptonote::MAINNET, args.front()))
{
- if(!cryptonote::get_account_address_from_str(info, true, args.front()))
+ if(!cryptonote::get_account_address_from_str(info, cryptonote::TESTNET, args.front()))
{
- bool dnssec_valid;
- std::string address_str = tools::dns_utils::get_account_address_as_str_from_url(args.front(), dnssec_valid,
- [](const std::string &url, const std::vector<std::string> &addresses, bool dnssec_valid){return addresses[0];});
- if(!cryptonote::get_account_address_from_str(info, false, address_str))
+ if(!cryptonote::get_account_address_from_str(info, cryptonote::STAGENET, args.front()))
{
- if(!cryptonote::get_account_address_from_str(info, true, address_str))
+ bool dnssec_valid;
+ std::string address_str = tools::dns_utils::get_account_address_as_str_from_url(args.front(), dnssec_valid,
+ [](const std::string &url, const std::vector<std::string> &addresses, bool dnssec_valid){return addresses[0];});
+ if(!cryptonote::get_account_address_from_str(info, cryptonote::MAINNET, address_str))
{
- std::cout << "target account address has wrong format" << std::endl;
- return true;
- }
- else
- {
- testnet = true;
+ if(!cryptonote::get_account_address_from_str(info, cryptonote::TESTNET, address_str))
+ {
+ if(!cryptonote::get_account_address_from_str(info, cryptonote::STAGENET, address_str))
+ {
+ std::cout << "target account address has wrong format" << std::endl;
+ return true;
+ }
+ else
+ {
+ nettype = cryptonote::STAGENET;
+ }
+ }
+ else
+ {
+ nettype = cryptonote::TESTNET;
+ }
}
}
+ else
+ {
+ nettype = cryptonote::STAGENET;
+ }
}
else
{
- testnet = true;
+ nettype = cryptonote::TESTNET;
}
}
if (info.is_subaddress)
@@ -299,8 +313,8 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg
tools::fail_msg_writer() << "subaddress for mining reward is not yet supported!" << std::endl;
return true;
}
- if(testnet)
- std::cout << "Mining to a testnet address, make sure this is intentional!" << std::endl;
+ if(nettype != cryptonote::MAINNET)
+ std::cout << "Mining to a " << (nettype == cryptonote::TESTNET ? "testnet" : "stagenet") << "address, make sure this is intentional!" << std::endl;
uint64_t threads_count = 1;
bool do_background_mining = false;
bool ignore_battery = false;
@@ -325,7 +339,7 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg
threads_count = (ok && 0 < threads_count) ? threads_count : 1;
}
- m_executor.start_mining(info.address, threads_count, testnet, do_background_mining, ignore_battery);
+ m_executor.start_mining(info.address, threads_count, nettype, do_background_mining, ignore_battery);
return true;
}
diff --git a/src/daemon/core.h b/src/daemon/core.h
index 1ff696bef..475f418d6 100644
--- a/src/daemon/core.h
+++ b/src/daemon/core.h
@@ -69,9 +69,12 @@ public:
std::string get_config_subdir() const
{
bool testnet = command_line::get_arg(m_vm_HACK, cryptonote::arg_testnet_on);
+ bool stagenet = command_line::get_arg(m_vm_HACK, cryptonote::arg_stagenet_on);
+ bool mainnet = !testnet && !stagenet;
std::string port = command_line::get_arg(m_vm_HACK, nodetool::arg_p2p_bind_port);
- if ((!testnet && port != std::to_string(::config::P2P_DEFAULT_PORT))
- || (testnet && port != std::to_string(::config::testnet::P2P_DEFAULT_PORT))) {
+ if ((mainnet && port != std::to_string(::config::P2P_DEFAULT_PORT))
+ || (testnet && port != std::to_string(::config::testnet::P2P_DEFAULT_PORT))
+ || (stagenet && port != std::to_string(::config::stagenet::P2P_DEFAULT_PORT))) {
return port;
}
return std::string();
diff --git a/src/daemon/daemon.cpp b/src/daemon/daemon.cpp
index 8053932fe..48671f190 100644
--- a/src/daemon/daemon.cpp
+++ b/src/daemon/daemon.cpp
@@ -76,15 +76,16 @@ public:
core.set_protocol(protocol.get());
const auto testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
+ const auto stagenet = command_line::get_arg(vm, cryptonote::arg_stagenet_on);
const auto restricted = command_line::get_arg(vm, cryptonote::core_rpc_server::arg_restricted_rpc);
const auto main_rpc_port = command_line::get_arg(vm, cryptonote::core_rpc_server::arg_rpc_bind_port);
- rpcs.emplace_back(new t_rpc{vm, core, p2p, restricted, testnet, main_rpc_port, "core"});
+ rpcs.emplace_back(new t_rpc{vm, core, p2p, restricted, testnet ? cryptonote::TESTNET : stagenet ? cryptonote::STAGENET : cryptonote::MAINNET, main_rpc_port, "core"});
auto restricted_rpc_port_arg = cryptonote::core_rpc_server::arg_rpc_restricted_bind_port;
if(!command_line::is_arg_defaulted(vm, restricted_rpc_port_arg))
{
auto restricted_rpc_port = command_line::get_arg(vm, restricted_rpc_port_arg);
- rpcs.emplace_back(new t_rpc{vm, core, p2p, true, testnet, restricted_rpc_port, "restricted"});
+ rpcs.emplace_back(new t_rpc{vm, core, p2p, true, testnet ? cryptonote::TESTNET : stagenet ? cryptonote::STAGENET : cryptonote::MAINNET, restricted_rpc_port, "restricted"});
}
}
};
diff --git a/src/daemon/main.cpp b/src/daemon/main.cpp
index 752a92ba4..50384b2a6 100644
--- a/src/daemon/main.cpp
+++ b/src/daemon/main.cpp
@@ -138,6 +138,14 @@ int main(int argc, char const * argv[])
return 0;
}
+ const bool testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
+ const bool stagenet = command_line::get_arg(vm, cryptonote::arg_stagenet_on);
+ if (testnet && stagenet)
+ {
+ std::cerr << "Can't specify more than one of --tesnet and --stagenet" << ENDL;
+ return 1;
+ }
+
std::string db_type = command_line::get_arg(vm, cryptonote::arg_db_type);
// verify that blockchaindb type is valid
diff --git a/src/daemon/rpc.h b/src/daemon/rpc.h
index 17f6c7f67..9621b0d01 100644
--- a/src/daemon/rpc.h
+++ b/src/daemon/rpc.h
@@ -54,7 +54,7 @@ public:
, t_core & core
, t_p2p & p2p
, const bool restricted
- , const bool testnet
+ , const cryptonote::network_type nettype
, const std::string & port
, const std::string & description
)
@@ -62,7 +62,7 @@ public:
{
MGINFO("Initializing " << m_description << " RPC server...");
- if (!m_server.init(vm, restricted, testnet, port))
+ if (!m_server.init(vm, restricted, nettype, port))
{
throw std::runtime_error("Failed to initialize " + m_description + " RPC server.");
}
diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp
index 5ef799d40..73b8d1a18 100644
--- a/src/daemon/rpc_command_executor.cpp
+++ b/src/daemon/rpc_command_executor.cpp
@@ -442,7 +442,7 @@ bool t_rpc_command_executor::show_status() {
% (unsigned long long)ires.height
% (unsigned long long)net_height
% get_sync_percentage(ires)
- % (ires.testnet ? "testnet" : "mainnet")
+ % (ires.testnet ? "testnet" : ires.stagenet ? "stagenet" : "mainnet")
% bootstrap_msg
% (!has_mining_info ? "mining info unavailable" : mining_busy ? "syncing" : mres.active ? ( ( mres.is_background_mining_enabled ? "smart " : "" ) + std::string("mining at ") + get_mining_speed(mres.speed) ) : "not mining")
% get_mining_speed(ires.difficulty / ires.target)
@@ -1036,10 +1036,10 @@ bool t_rpc_command_executor::print_transaction_pool_stats() {
return true;
}
-bool t_rpc_command_executor::start_mining(cryptonote::account_public_address address, uint64_t num_threads, bool testnet, bool do_background_mining, bool ignore_battery) {
+bool t_rpc_command_executor::start_mining(cryptonote::account_public_address address, uint64_t num_threads, cryptonote::network_type nettype, bool do_background_mining, bool ignore_battery) {
cryptonote::COMMAND_RPC_START_MINING::request req;
cryptonote::COMMAND_RPC_START_MINING::response res;
- req.miner_address = cryptonote::get_account_address_as_str(testnet, false, address);
+ req.miner_address = cryptonote::get_account_address_as_str(nettype, false, address);
req.threads_count = num_threads;
req.do_background_mining = do_background_mining;
req.ignore_battery = ignore_battery;
diff --git a/src/daemon/rpc_command_executor.h b/src/daemon/rpc_command_executor.h
index fa83d8988..46168c93b 100644
--- a/src/daemon/rpc_command_executor.h
+++ b/src/daemon/rpc_command_executor.h
@@ -105,7 +105,7 @@ public:
bool print_transaction_pool_stats();
- bool start_mining(cryptonote::account_public_address address, uint64_t num_threads, bool testnet, bool do_background_mining = false, bool ignore_battery = false);
+ bool start_mining(cryptonote::account_public_address address, uint64_t num_threads, cryptonote::network_type nettype, bool do_background_mining = false, bool ignore_battery = false);
bool stop_mining();
diff --git a/src/daemonizer/CMakeLists.txt b/src/daemonizer/CMakeLists.txt
index 2c0583c49..2753d0003 100644
--- a/src/daemonizer/CMakeLists.txt
+++ b/src/daemonizer/CMakeLists.txt
@@ -54,6 +54,10 @@ else()
)
endif()
+if(CMAKE_BUILD_TYPE STREQUAL "Debug")
+ add_definitions(-DDEBUG_TMPDIR_LOG=1)
+endif()
+
monero_private_headers(daemonizer
${daemonizer_private_headers})
monero_add_library(daemonizer
diff --git a/src/daemonizer/posix_fork.cpp b/src/daemonizer/posix_fork.cpp
index 4dff04f3f..3cbee9c51 100644
--- a/src/daemonizer/posix_fork.cpp
+++ b/src/daemonizer/posix_fork.cpp
@@ -115,6 +115,7 @@ void fork(const std::string & pidfile)
quit("Unable to open /dev/null");
}
+#ifdef DEBUG_TMPDIR_LOG
// Send standard output to a log file.
const char *tmpdir = getenv("TMPDIR");
if (!tmpdir)
@@ -133,6 +134,7 @@ void fork(const std::string & pidfile)
{
quit("Unable to dup output descriptor");
}
+#endif
}
} // namespace posix
diff --git a/src/device/device_default.cpp b/src/device/device_default.cpp
index a38d96c15..c3ba42000 100644
--- a/src/device/device_default.cpp
+++ b/src/device/device_default.cpp
@@ -254,10 +254,10 @@ namespace hw {
default_core_device->set_name("default_core_device");
}
- registry.insert(std::make_pair("default",default_core_device));
+ registry.insert(std::make_pair("default", std::unique_ptr<device>(default_core_device)));
}
}
-} \ No newline at end of file
+}
diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp
index e8eb7cc8b..571d42724 100644
--- a/src/device/device_ledger.cpp
+++ b/src/device/device_ledger.cpp
@@ -511,7 +511,7 @@ namespace hw {
char prekey[200];
memmove(prekey, &this->buffer_recv[0], 200);
- crypto::generate_chacha_key(&prekey[0], sizeof(prekey), key, true);
+ crypto::generate_chacha_key(&prekey[0], sizeof(prekey), key, 0, true);
#ifdef DEBUG_HWDEVICE
hw::ledger::check32("generate_chacha_key", "key", (char*)key_x.data(), (char*)key.data());
@@ -2054,7 +2054,7 @@ namespace hw {
legder_device = new device_ledger();
legder_device->set_name("Ledger");
}
- registry.insert(std::make_pair("Ledger", legder_device));
+ registry.insert(std::make_pair("Ledger", std::unique_ptr<device>(legder_device)));
}
#else //WITH_DEVICE_LEDGER
diff --git a/src/gen_multisig/gen_multisig.cpp b/src/gen_multisig/gen_multisig.cpp
index 64204d8b9..9bcf4495c 100644
--- a/src/gen_multisig/gen_multisig.cpp
+++ b/src/gen_multisig/gen_multisig.cpp
@@ -72,11 +72,12 @@ namespace
const command_line::arg_descriptor<uint32_t> arg_participants = {"participants", genms::tr("How many participants wil share parts of the multisig wallet"), 0};
const command_line::arg_descriptor<uint32_t> arg_threshold = {"threshold", genms::tr("How many signers are required to sign a valid transaction"), 0};
const command_line::arg_descriptor<bool, false> arg_testnet = {"testnet", genms::tr("Create testnet multisig wallets"), false};
+ const command_line::arg_descriptor<bool, false> arg_stagenet = {"stagenet", genms::tr("Create stagenet multisig wallets"), false};
const command_line::arg_descriptor< std::vector<std::string> > arg_command = {"command", ""};
}
-static bool generate_multisig(uint32_t threshold, uint32_t total, const std::string &basename, bool testnet)
+static bool generate_multisig(uint32_t threshold, uint32_t total, const std::string &basename, network_type nettype)
{
tools::msg_writer() << (boost::format(genms::tr("Generating %u %u/%u multisig wallets")) % total % threshold % total).str();
@@ -89,7 +90,7 @@ static bool generate_multisig(uint32_t threshold, uint32_t total, const std::str
for (size_t n = 0; n < total; ++n)
{
std::string name = basename + "-" + std::to_string(n + 1);
- wallets[n].reset(new tools::wallet2(testnet));
+ wallets[n].reset(new tools::wallet2(nettype));
wallets[n]->init("");
wallets[n]->generate(name, pwd_container->password(), rct::rct2sk(rct::skGen()), false, false);
}
@@ -149,7 +150,7 @@ static bool generate_multisig(uint32_t threshold, uint32_t total, const std::str
}
}
- std::string address = wallets[0]->get_account().get_public_address_str(wallets[0]->testnet());
+ std::string address = wallets[0]->get_account().get_public_address_str(wallets[0]->nettype());
tools::success_msg_writer() << genms::tr("Generated multisig wallets for address ") << address << std::endl << ss.str();
}
catch (const std::exception &e)
@@ -169,10 +170,11 @@ int main(int argc, char* argv[])
command_line::add_arg(desc_params, arg_threshold);
command_line::add_arg(desc_params, arg_participants);
command_line::add_arg(desc_params, arg_testnet);
+ command_line::add_arg(desc_params, arg_stagenet);
const auto vm = wallet_args::main(
argc, argv,
- "monero-gen-multisig [--testnet] [--filename-base=<filename>] [--scheme=M/N] [--threshold=M] [--participants=N]",
+ "monero-gen-multisig [(--testnet|--stagenet)] [--filename-base=<filename>] [--scheme=M/N] [--threshold=M] [--participants=N]",
genms::tr("This program generates a set of multisig wallets - use this simpler scheme only if all the participants trust each other"),
desc_params,
boost::program_options::positional_options_description(),
@@ -182,11 +184,17 @@ int main(int argc, char* argv[])
if (!vm)
return 1;
- bool testnet;
+ bool testnet, stagenet;
uint32_t threshold = 0, total = 0;
std::string basename;
testnet = command_line::get_arg(*vm, arg_testnet);
+ stagenet = command_line::get_arg(*vm, arg_stagenet);
+ if (testnet && stagenet)
+ {
+ tools::fail_msg_writer() << genms::tr("Error: Can't specify more than one of --testnet and --stagenet");
+ return 1;
+ }
if (command_line::has_arg(*vm, arg_scheme))
{
if (sscanf(command_line::get_arg(*vm, arg_scheme).c_str(), "%u/%u", &threshold, &total) != 2)
@@ -233,7 +241,7 @@ int main(int argc, char* argv[])
tools::fail_msg_writer() << genms::tr("Error: unsupported scheme: only N/N and N-1/N are supported");
return 1;
}
- if (!generate_multisig(threshold, total, basename, testnet))
+ if (!generate_multisig(threshold, total, basename, testnet ? TESTNET : stagenet ? STAGENET : MAINNET))
return 1;
return 0;
diff --git a/src/p2p/net_node.cpp b/src/p2p/net_node.cpp
index 170b79984..bde6fc88e 100644
--- a/src/p2p/net_node.cpp
+++ b/src/p2p/net_node.cpp
@@ -34,14 +34,16 @@
namespace nodetool
{
const command_line::arg_descriptor<std::string> arg_p2p_bind_ip = {"p2p-bind-ip", "Interface for p2p network protocol", "0.0.0.0"};
- const command_line::arg_descriptor<std::string, false, true> arg_p2p_bind_port = {
+ const command_line::arg_descriptor<std::string, false, true, 2> arg_p2p_bind_port = {
"p2p-bind-port"
, "Port for p2p network protocol"
, std::to_string(config::P2P_DEFAULT_PORT)
- , cryptonote::arg_testnet_on
- , [](bool testnet, bool defaulted, std::string val) {
- if (testnet && defaulted)
+ , {{ &cryptonote::arg_testnet_on, &cryptonote::arg_stagenet_on }}
+ , [](std::array<bool, 2> testnet_stagenet, bool defaulted, std::string val) {
+ if (testnet_stagenet[0] && defaulted)
return std::to_string(config::testnet::P2P_DEFAULT_PORT);
+ else if (testnet_stagenet[1] && defaulted)
+ return std::to_string(config::stagenet::P2P_DEFAULT_PORT);
return val;
}
};
diff --git a/src/p2p/net_node.h b/src/p2p/net_node.h
index 54c474665..3010b43ad 100644
--- a/src/p2p/net_node.h
+++ b/src/p2p/net_node.h
@@ -223,7 +223,7 @@ namespace nodetool
void cache_connect_fail_info(const epee::net_utils::network_address& addr);
bool is_addr_recently_failed(const epee::net_utils::network_address& addr);
bool is_priority_node(const epee::net_utils::network_address& na);
- std::set<std::string> get_seed_nodes(bool testnet) const;
+ std::set<std::string> get_seed_nodes(cryptonote::network_type nettype) const;
bool connect_to_seed();
template <class Container>
@@ -331,13 +331,13 @@ namespace nodetool
epee::critical_section m_host_fails_score_lock;
std::map<std::string, uint64_t> m_host_fails_score;
- bool m_testnet;
+ cryptonote::network_type m_nettype;
};
const int64_t default_limit_up = 2048;
const int64_t default_limit_down = 8192;
extern const command_line::arg_descriptor<std::string> arg_p2p_bind_ip;
- extern const command_line::arg_descriptor<std::string, false, true> arg_p2p_bind_port;
+ extern const command_line::arg_descriptor<std::string, false, true, 2> arg_p2p_bind_port;
extern const command_line::arg_descriptor<uint32_t> arg_p2p_external_port;
extern const command_line::arg_descriptor<bool> arg_p2p_allow_local_ip;
extern const command_line::arg_descriptor<std::vector<std::string> > arg_p2p_add_peer;
diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl
index 59b417d90..8ef240326 100644
--- a/src/p2p/net_node.inl
+++ b/src/p2p/net_node.inl
@@ -262,7 +262,10 @@ namespace nodetool
const boost::program_options::variables_map& vm
)
{
- m_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
+ bool testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
+ bool stagenet = command_line::get_arg(vm, cryptonote::arg_stagenet_on);
+ m_nettype = testnet ? cryptonote::TESTNET : stagenet ? cryptonote::STAGENET : cryptonote::MAINNET;
+
m_bind_ip = command_line::get_arg(vm, arg_p2p_bind_ip);
m_port = command_line::get_arg(vm, arg_p2p_bind_port);
m_external_port = command_line::get_arg(vm, arg_p2p_external_port);
@@ -277,7 +280,7 @@ namespace nodetool
{
nodetool::peerlist_entry pe = AUTO_VAL_INIT(pe);
pe.id = crypto::rand<uint64_t>();
- const uint16_t default_port = m_testnet ? ::config::testnet::P2P_DEFAULT_PORT : ::config::P2P_DEFAULT_PORT;
+ const uint16_t default_port = testnet ? ::config::testnet::P2P_DEFAULT_PORT : stagenet ? ::config::stagenet::P2P_DEFAULT_PORT : ::config::P2P_DEFAULT_PORT;
bool r = parse_peer_from_string(pe.adr, pr_str, default_port);
CHECK_AND_ASSERT_MES(r, false, "Failed to parse address from string: " << pr_str);
m_command_line_peers.push_back(pe);
@@ -370,10 +373,10 @@ namespace nodetool
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
- std::set<std::string> node_server<t_payload_net_handler>::get_seed_nodes(bool testnet) const
+ std::set<std::string> node_server<t_payload_net_handler>::get_seed_nodes(cryptonote::network_type nettype) const
{
std::set<std::string> full_addrs;
- if (testnet)
+ if (nettype == cryptonote::TESTNET)
{
full_addrs.insert("212.83.175.67:28080");
full_addrs.insert("5.9.100.248:28080");
@@ -381,6 +384,11 @@ namespace nodetool
full_addrs.insert("195.154.123.123:28080");
full_addrs.insert("212.83.172.165:28080");
}
+ else if (nettype == cryptonote::STAGENET)
+ {
+ full_addrs.insert("162.210.173.150:38080");
+ full_addrs.insert("162.210.173.151:38080");
+ }
else
{
full_addrs.insert("107.152.130.98:18080");
@@ -404,10 +412,15 @@ namespace nodetool
bool res = handle_command_line(vm);
CHECK_AND_ASSERT_MES(res, false, "Failed to handle command line");
- if (m_testnet)
+ if (m_nettype == cryptonote::TESTNET)
{
memcpy(&m_network_id, &::config::testnet::NETWORK_ID, 16);
- full_addrs = get_seed_nodes(true);
+ full_addrs = get_seed_nodes(cryptonote::TESTNET);
+ }
+ else if (m_nettype == cryptonote::STAGENET)
+ {
+ memcpy(&m_network_id, &::config::stagenet::NETWORK_ID, 16);
+ full_addrs = get_seed_nodes(cryptonote::STAGENET);
}
else if (m_exclusive_peers.empty())
{
@@ -488,7 +501,7 @@ namespace nodetool
else
MINFO("Not enough DNS seed nodes found, using fallback defaults too");
- for (const auto &peer: get_seed_nodes(false))
+ for (const auto &peer: get_seed_nodes(cryptonote::MAINNET))
full_addrs.insert(peer);
}
}
@@ -502,8 +515,9 @@ namespace nodetool
m_config_folder = command_line::get_arg(vm, cryptonote::arg_data_dir);
- if ((!m_testnet && m_port != std::to_string(::config::P2P_DEFAULT_PORT))
- || (m_testnet && m_port != std::to_string(::config::testnet::P2P_DEFAULT_PORT))) {
+ if ((m_nettype == cryptonote::MAINNET && m_port != std::to_string(::config::P2P_DEFAULT_PORT))
+ || (m_nettype == cryptonote::TESTNET && m_port != std::to_string(::config::testnet::P2P_DEFAULT_PORT))
+ || (m_nettype == cryptonote::STAGENET && m_port != std::to_string(::config::stagenet::P2P_DEFAULT_PORT))) {
m_config_folder = m_config_folder + "/" + m_port;
}
@@ -1137,7 +1151,7 @@ namespace nodetool
if (!fallback_nodes_added)
{
MWARNING("Failed to connect to any of seed peers, trying fallback seeds");
- for (const auto &peer: get_seed_nodes(m_testnet))
+ for (const auto &peer: get_seed_nodes(m_nettype))
{
MDEBUG("Fallback seed node: " << peer);
append_net_address(m_seed_nodes, peer);
@@ -1797,7 +1811,7 @@ namespace nodetool
for(const std::string& pr_str: perrs)
{
epee::net_utils::network_address na = AUTO_VAL_INIT(na);
- const uint16_t default_port = m_testnet ? ::config::testnet::P2P_DEFAULT_PORT : ::config::P2P_DEFAULT_PORT;
+ const uint16_t default_port = m_nettype == cryptonote::TESTNET ? ::config::testnet::P2P_DEFAULT_PORT : m_nettype == cryptonote::STAGENET ? ::config::stagenet::P2P_DEFAULT_PORT : ::config::P2P_DEFAULT_PORT;
bool r = parse_peer_from_string(na, pr_str, default_port);
CHECK_AND_ASSERT_MES(r, false, "Failed to parse address from string: " << pr_str);
container.push_back(na);
diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp
index d3437eb36..ae0ee21c8 100644
--- a/src/ringct/rctSigs.cpp
+++ b/src/ringct/rctSigs.cpp
@@ -130,29 +130,12 @@ namespace rct {
return equalKeys(eeComputed, bb.ee);
}
- //Multilayered Spontaneous Anonymous Group Signatures (MLSAG signatures)
- //These are aka MG signatutes in earlier drafts of the ring ct paper
- // c.f. http://eprint.iacr.org/2015/1098 section 2.
- // keyImageV just does I[i] = xx[i] * Hash(xx[i] * G) for each i
- // Gen creates a signature which proves that for some column in the keymatrix "pk"
- // the signer knows a secret key for each row in that column
- // Ver verifies that the MG sig was created correctly
- keyV keyImageV(const keyV &xx) {
- keyV II(xx.size());
- size_t i = 0;
- for (i = 0; i < xx.size(); i++) {
- II[i] = scalarmultKey(hashToPoint(scalarmultBase(xx[i])), xx[i]);
- }
- return II;
- }
-
//Multilayered Spontaneous Anonymous Group Signatures (MLSAG signatures)
//This is a just slghtly more efficient version than the ones described below
//(will be explained in more detail in Ring Multisig paper
//These are aka MG signatutes in earlier drafts of the ring ct paper
// c.f. http://eprint.iacr.org/2015/1098 section 2.
- // keyImageV just does I[i] = xx[i] * Hash(xx[i] * G) for each i
// Gen creates a signature which proves that for some column in the keymatrix "pk"
// the signer knows a secret key for each row in that column
// Ver verifies that the MG sig was created correctly
@@ -250,7 +233,6 @@ namespace rct {
//(will be explained in more detail in Ring Multisig paper
//These are aka MG signatutes in earlier drafts of the ring ct paper
// c.f. http://eprint.iacr.org/2015/1098 section 2.
- // keyImageV just does I[i] = xx[i] * Hash(xx[i] * G) for each i
// Gen creates a signature which proves that for some column in the keymatrix "pk"
// the signer knows a secret key for each row in that column
// Ver verifies that the MG sig was created correctly
@@ -506,11 +488,12 @@ namespace rct {
keyV sk(rows + 1);
size_t i;
keyM M(cols, tmp);
+
+ sk[0] = copy(inSk.dest);
+ sc_sub(sk[1].bytes, inSk.mask.bytes, a.bytes);
for (i = 0; i < cols; i++) {
M[i][0] = pubs[i].dest;
subKeys(M[i][1], pubs[i].mask, Cout);
- sk[0] = copy(inSk.dest);
- sc_sub(sk[1].bytes, inSk.mask.bytes, a.bytes);
}
return MLSAG_Gen(message, M, sk, kLRki, mscout, index, rows, hwdev);
}
diff --git a/src/ringct/rctSigs.h b/src/ringct/rctSigs.h
index 17047fc0f..7485938ee 100644
--- a/src/ringct/rctSigs.h
+++ b/src/ringct/rctSigs.h
@@ -70,11 +70,9 @@ namespace rct {
//Multilayered Spontaneous Anonymous Group Signatures (MLSAG signatures)
//These are aka MG signatutes in earlier drafts of the ring ct paper
// c.f. http://eprint.iacr.org/2015/1098 section 2.
- // keyImageV just does I[i] = xx[i] * HashToPoint(xx[i] * G) for each i
// Gen creates a signature which proves that for some column in the keymatrix "pk"
// the signer knows a secret key for each row in that column
// Ver verifies that the MG sig was created correctly
- keyV keyImageV(const keyV &xx);
mgSig MLSAG_Gen(const key &message, const keyM & pk, const keyV & xx, const multisig_kLRki *kLRki, key *mscout, const unsigned int index, size_t dsRows, hw::device &hwdev);
bool MLSAG_Ver(const key &message, const keyM &pk, const mgSig &sig, size_t dsRows);
//mgSig MLSAG_Gen_Old(const keyM & pk, const keyV & xx, const int index);
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index a8d801ac7..0e3e6757b 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -90,12 +90,12 @@ namespace cryptonote
bool core_rpc_server::init(
const boost::program_options::variables_map& vm
, const bool restricted
- , const bool testnet
+ , const network_type nettype
, const std::string& port
)
{
m_restricted = restricted;
- m_testnet = testnet;
+ m_nettype = nettype;
m_net_server.set_threads_prefix("RPC");
auto rpc_config = cryptonote::rpc_args::process(vm);
@@ -190,7 +190,9 @@ namespace cryptonote
res.rpc_connections_count = get_connections_count();
res.white_peerlist_size = m_p2p.get_peerlist_manager().get_white_peers_count();
res.grey_peerlist_size = m_p2p.get_peerlist_manager().get_gray_peers_count();
- res.testnet = m_testnet;
+ res.mainnet = m_nettype == MAINNET;
+ res.testnet = m_nettype == TESTNET;
+ res.stagenet = m_nettype == STAGENET;
res.cumulative_difficulty = m_core.get_blockchain_storage().get_db().get_block_cumulative_difficulty(res.height - 1);
res.block_size_limit = m_core.get_blockchain_storage().get_current_cumulative_blocksize_limit();
res.block_size_median = m_core.get_blockchain_storage().get_current_cumulative_blocksize_median();
@@ -823,7 +825,7 @@ namespace cryptonote
PERF_TIMER(on_start_mining);
CHECK_CORE_READY();
cryptonote::address_parse_info info;
- if(!get_account_address_from_str(info, m_testnet, req.miner_address))
+ if(!get_account_address_from_str(info, m_nettype, req.miner_address))
{
res.status = "Failed, wrong address";
LOG_PRINT_L0(res.status);
@@ -891,7 +893,7 @@ namespace cryptonote
res.speed = lMiner.get_speed();
res.threads_count = lMiner.get_threads_count();
const account_public_address& lMiningAdr = lMiner.get_mining_address();
- res.address = get_account_address_as_str(m_testnet, false, lMiningAdr);
+ res.address = get_account_address_as_str(m_nettype, false, lMiningAdr);
}
res.status = CORE_RPC_STATUS_OK;
@@ -1106,7 +1108,7 @@ namespace cryptonote
cryptonote::address_parse_info info;
- if(!req.wallet_address.size() || !cryptonote::get_account_address_from_str(info, m_testnet, req.wallet_address))
+ if(!req.wallet_address.size() || !cryptonote::get_account_address_from_str(info, m_nettype, req.wallet_address))
{
error_resp.code = CORE_RPC_ERROR_CODE_WRONG_WALLET_ADDRESS;
error_resp.message = "Failed to parse wallet address";
@@ -1568,7 +1570,9 @@ namespace cryptonote
res.rpc_connections_count = get_connections_count();
res.white_peerlist_size = m_p2p.get_peerlist_manager().get_white_peers_count();
res.grey_peerlist_size = m_p2p.get_peerlist_manager().get_gray_peers_count();
- res.testnet = m_testnet;
+ res.mainnet = m_nettype == MAINNET;
+ res.testnet = m_nettype == TESTNET;
+ res.stagenet = m_nettype == STAGENET;
res.cumulative_difficulty = m_core.get_blockchain_storage().get_db().get_block_cumulative_difficulty(res.height - 1);
res.block_size_limit = m_core.get_blockchain_storage().get_current_cumulative_blocksize_limit();
res.block_size_median = m_core.get_blockchain_storage().get_current_cumulative_blocksize_median();
@@ -2073,14 +2077,16 @@ namespace cryptonote
}
//------------------------------------------------------------------------------------------------------------------------------
- const command_line::arg_descriptor<std::string, false, true> core_rpc_server::arg_rpc_bind_port = {
+ const command_line::arg_descriptor<std::string, false, true, 2> core_rpc_server::arg_rpc_bind_port = {
"rpc-bind-port"
, "Port for RPC server"
, std::to_string(config::RPC_DEFAULT_PORT)
- , cryptonote::arg_testnet_on
- , [](bool testnet, bool defaulted, std::string val) {
- if (testnet && defaulted)
+ , {{ &cryptonote::arg_testnet_on, &cryptonote::arg_stagenet_on }}
+ , [](std::array<bool, 2> testnet_stagenet, bool defaulted, std::string val) {
+ if (testnet_stagenet[0] && defaulted)
return std::to_string(config::testnet::RPC_DEFAULT_PORT);
+ else if (testnet_stagenet[1] && defaulted)
+ return std::to_string(config::stagenet::RPC_DEFAULT_PORT);
return val;
}
};
diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h
index 3c57a6016..4754a5d5f 100644
--- a/src/rpc/core_rpc_server.h
+++ b/src/rpc/core_rpc_server.h
@@ -53,7 +53,7 @@ namespace cryptonote
{
public:
- static const command_line::arg_descriptor<std::string, false, true> arg_rpc_bind_port;
+ static const command_line::arg_descriptor<std::string, false, true, 2> arg_rpc_bind_port;
static const command_line::arg_descriptor<std::string> arg_rpc_restricted_bind_port;
static const command_line::arg_descriptor<bool> arg_restricted_rpc;
static const command_line::arg_descriptor<std::string> arg_bootstrap_daemon_address;
@@ -70,10 +70,10 @@ namespace cryptonote
bool init(
const boost::program_options::variables_map& vm,
const bool restricted,
- const bool testnet,
+ const network_type nettype,
const std::string& port
);
- bool is_testnet() const { return m_testnet; }
+ network_type nettype() const { return m_nettype; }
CHAIN_HTTP_TO_MAP2(connection_context); //forward http requests to uri map
@@ -235,7 +235,7 @@ private:
bool m_should_use_bootstrap_daemon;
std::chrono::system_clock::time_point m_bootstrap_height_check_time;
bool m_was_bootstrap_ever_used;
- bool m_testnet;
+ network_type m_nettype;
bool m_restricted;
};
}
diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h
index 64a97f8a3..a2c780376 100644
--- a/src/rpc/core_rpc_server_commands_defs.h
+++ b/src/rpc/core_rpc_server_commands_defs.h
@@ -948,7 +948,9 @@ namespace cryptonote
uint64_t rpc_connections_count;
uint64_t white_peerlist_size;
uint64_t grey_peerlist_size;
+ bool mainnet;
bool testnet;
+ bool stagenet;
std::string top_block_hash;
uint64_t cumulative_difficulty;
uint64_t block_size_limit;
@@ -975,7 +977,9 @@ namespace cryptonote
KV_SERIALIZE(rpc_connections_count)
KV_SERIALIZE(white_peerlist_size)
KV_SERIALIZE(grey_peerlist_size)
+ KV_SERIALIZE(mainnet)
KV_SERIALIZE(testnet)
+ KV_SERIALIZE(stagenet)
KV_SERIALIZE(top_block_hash)
KV_SERIALIZE(cumulative_difficulty)
KV_SERIALIZE(block_size_limit)
diff --git a/src/rpc/daemon_handler.cpp b/src/rpc/daemon_handler.cpp
index 2f3f336a4..29020aa57 100644
--- a/src/rpc/daemon_handler.cpp
+++ b/src/rpc/daemon_handler.cpp
@@ -413,7 +413,7 @@ namespace rpc
void DaemonHandler::handle(const StartMining::Request& req, StartMining::Response& res)
{
cryptonote::address_parse_info info;
- if(!get_account_address_from_str(info, m_core.get_testnet(), req.miner_address))
+ if(!get_account_address_from_str(info, m_core.get_nettype(), req.miner_address))
{
res.error_details = "Failed, wrong address";
LOG_PRINT_L0(res.error_details);
@@ -492,7 +492,9 @@ namespace rpc
res.info.grey_peerlist_size = m_p2p.get_peerlist_manager().get_gray_peers_count();
- res.info.testnet = m_core.get_testnet();
+ res.info.mainnet = m_core.get_nettype() == MAINNET;
+ res.info.testnet = m_core.get_nettype() == TESTNET;
+ res.info.stagenet = m_core.get_nettype() == STAGENET;
res.info.cumulative_difficulty = m_core.get_blockchain_storage().get_db().get_block_cumulative_difficulty(res.info.height - 1);
res.info.block_size_limit = m_core.get_blockchain_storage().get_current_cumulative_blocksize_limit();
res.info.start_time = (uint64_t)m_core.get_start_time();
@@ -525,7 +527,7 @@ namespace rpc
res.speed = lMiner.get_speed();
res.threads_count = lMiner.get_threads_count();
const account_public_address& lMiningAdr = lMiner.get_mining_address();
- res.address = get_account_address_as_str(m_core.get_testnet(), false, lMiningAdr);
+ res.address = get_account_address_as_str(m_core.get_nettype(), false, lMiningAdr);
}
res.status = Message::STATUS_OK;
diff --git a/src/rpc/message_data_structs.h b/src/rpc/message_data_structs.h
index 9ba311976..17ae9629f 100644
--- a/src/rpc/message_data_structs.h
+++ b/src/rpc/message_data_structs.h
@@ -178,7 +178,9 @@ namespace rpc
uint64_t incoming_connections_count;
uint64_t white_peerlist_size;
uint64_t grey_peerlist_size;
+ bool mainnet;
bool testnet;
+ bool stagenet;
crypto::hash top_block_hash;
uint64_t cumulative_difficulty;
uint64_t block_size_limit;
diff --git a/src/serialization/binary_archive.h b/src/serialization/binary_archive.h
index 79c6c753c..f47a4494d 100644
--- a/src/serialization/binary_archive.h
+++ b/src/serialization/binary_archive.h
@@ -82,7 +82,7 @@ protected:
/* \struct binary_archive
*
- * \brief the actualy binary archive type
+ * \brief the actually binary archive type
*
* \detailed The boolean template argument /a W is the is_saving
* parameter for binary_archive_base.
diff --git a/src/serialization/variant.h b/src/serialization/variant.h
index 31d903d55..1d00ab461 100644
--- a/src/serialization/variant.h
+++ b/src/serialization/variant.h
@@ -87,7 +87,7 @@ struct variant_reader
};
// This one just fails when you call it.... okay
-// So the TEnd parameter must be specified/differnt from TBegin
+// So the TEnd parameter must be specified/different from TBegin
template <class Archive, class Variant, class TBegin>
struct variant_reader<Archive, Variant, TBegin, TBegin>
{
diff --git a/src/simplewallet/CMakeLists.txt b/src/simplewallet/CMakeLists.txt
index 4230e32c0..8bb295931 100644
--- a/src/simplewallet/CMakeLists.txt
+++ b/src/simplewallet/CMakeLists.txt
@@ -54,6 +54,7 @@ target_link_libraries(simplewallet
${Boost_CHRONO_LIBRARY}
${Boost_PROGRAM_OPTIONS_LIBRARY}
${Boost_FILESYSTEM_LIBRARY}
+ ${ICU_LIBRARIES}
${Boost_THREAD_LIBRARY}
${CMAKE_THREAD_LIBS_INIT}
${GNU_READLINE_LIBRARY}
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index 02deee0c7..c618869f2 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -65,6 +65,11 @@
#include "device/device.hpp"
#include <stdexcept>
+#ifdef WIN32
+#include <boost/locale.hpp>
+#include <boost/filesystem.hpp>
+#endif
+
#ifdef HAVE_READLINE
#include "readline_buffer.h"
#endif
@@ -132,6 +137,28 @@ namespace
const command_line::arg_descriptor< std::vector<std::string> > arg_command = {"command", ""};
+#ifdef WIN32
+ // Translate from CP850 to UTF-8;
+ // std::getline for a Windows console returns a string in CP437 or CP850; as simplewallet,
+ // like all of Monero, is assumed to work internally with UTF-8 throughout, even on Windows
+ // (although only implemented partially), a translation to UTF-8 is needed for input.
+ //
+ // Note that if a program is started inside the MSYS2 shell somebody already translates
+ // console input to UTF-8, but it's not clear how one could detect that in order to avoid
+ // double-translation; this code here thus breaks UTF-8 input within a MSYS2 shell,
+ // unfortunately.
+ //
+ // Note also that input for passwords is NOT translated, to remain compatible with any
+ // passwords containing special characters that predate this switch to UTF-8 support.
+ static std::string cp850_to_utf8(const std::string &cp850_str)
+ {
+ boost::locale::generator gen;
+ gen.locale_cache_enabled(true);
+ std::locale loc = gen("en_US.CP850");
+ return boost::locale::conv::to_utf<char>(cp850_str, loc);
+ }
+#endif
+
std::string input_line(const std::string& prompt)
{
#ifdef HAVE_READLINE
@@ -141,6 +168,9 @@ namespace
std::string buf;
std::getline(std::cin, buf);
+#ifdef WIN32
+ buf = cp850_to_utf8(buf);
+#endif
return epee::string_tools::trim(buf);
}
@@ -576,10 +606,7 @@ bool simple_wallet::print_seed(bool encrypted)
epee::wipeable_string seed_pass;
if (encrypted)
{
-#ifdef HAVE_READLINE
- rdln::suspend_readline pause_readline;
-#endif
- auto pwd_container = tools::password_container::prompt(true, tr("Enter optional seed encryption passphrase, empty to see raw seed"));
+ auto pwd_container = password_prompter(tr("Enter optional seed encryption passphrase, empty to see raw seed"), true);
if (std::cin.eof() || !pwd_container)
return true;
seed_pass = pwd_container->password();
@@ -855,7 +882,7 @@ bool simple_wallet::make_multisig(const std::vector<std::string> &args)
return true;
}
success_msg_writer() << std::to_string(threshold) << "/" << total << tr(" multisig address: ")
- << m_wallet->get_account().get_public_address_str(m_wallet->testnet());
+ << m_wallet->get_account().get_public_address_str(m_wallet->nettype());
return true;
}
@@ -2120,6 +2147,15 @@ static bool might_be_partial_seed(std::string words)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::init(const boost::program_options::variables_map& vm)
{
+ const bool testnet = tools::wallet2::has_testnet_option(vm);
+ const bool stagenet = tools::wallet2::has_stagenet_option(vm);
+ if (testnet && stagenet)
+ {
+ fail_msg_writer() << tr("Can't specify more than one of --testnet and --stagenet");
+ return false;
+ }
+ const network_type nettype = testnet ? TESTNET : stagenet ? STAGENET : MAINNET;
+
std::string multisig_keys;
if (!handle_command_line(vm))
@@ -2205,10 +2241,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
}
}
-#ifdef HAVE_READLINE
- rdln::suspend_readline pause_readline;
-#endif
- auto pwd_container = tools::password_container::prompt(false, tr("Enter seed encryption passphrase, empty if none"));
+ auto pwd_container = password_prompter(tr("Enter seed encryption passphrase, empty if none"), false);
if (std::cin.eof() || !pwd_container)
return false;
epee::wipeable_string seed_pass = pwd_container->password();
@@ -2237,7 +2270,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
return false;
}
cryptonote::address_parse_info info;
- if(!get_account_address_from_str(info, tools::wallet2::has_testnet_option(vm), address_string))
+ if(!get_account_address_from_str(info, nettype, address_string))
{
fail_msg_writer() << tr("failed to parse address");
return false;
@@ -2311,7 +2344,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
return false;
}
cryptonote::address_parse_info info;
- if(!get_account_address_from_str(info, tools::wallet2::has_testnet_option(vm), address_string))
+ if(!get_account_address_from_str(info, nettype, address_string))
{
fail_msg_writer() << tr("failed to parse address");
return false;
@@ -2420,7 +2453,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
return false;
}
cryptonote::address_parse_info info;
- if(!get_account_address_from_str(info, tools::wallet2::has_testnet_option(vm), address_string))
+ if(!get_account_address_from_str(info, nettype, address_string))
{
fail_msg_writer() << tr("failed to parse address");
return false;
@@ -2589,7 +2622,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
try
{
year = boost::lexical_cast<uint16_t>(heightstr.substr(0,4));
- // lexical_cast<uint8_t> won't work becasue uint8_t is treated as character type
+ // lexical_cast<uint8_t> won't work because uint8_t is treated as character type
month = boost::lexical_cast<uint16_t>(heightstr.substr(5,2));
day = boost::lexical_cast<uint16_t>(heightstr.substr(8,2));
m_restore_height = m_wallet->get_blockchain_height_by_date(year, month, day);
@@ -2800,7 +2833,7 @@ bool simple_wallet::new_wallet(const boost::program_options::variables_map& vm,
// a seed language is not already specified AND
// (it is not a wallet restore OR if it was a deprecated wallet
// that was earlier used before this restore)
- if ((!two_random) && (mnemonic_language.empty()) && (!m_restore_deterministic_wallet || was_deprecated_wallet))
+ if ((!two_random) && (mnemonic_language.empty() || mnemonic_language == crypto::ElectrumWords::old_language_name) && (!m_restore_deterministic_wallet || was_deprecated_wallet))
{
if (was_deprecated_wallet)
{
@@ -2820,7 +2853,7 @@ bool simple_wallet::new_wallet(const boost::program_options::variables_map& vm,
{
recovery_val = m_wallet->generate(m_wallet_file, std::move(rc.second).password(), recovery_key, recover, two_random);
message_writer(console_color_white, true) << tr("Generated new wallet: ")
- << m_wallet->get_account().get_public_address_str(m_wallet->testnet());
+ << m_wallet->get_account().get_public_address_str(m_wallet->nettype());
std::cout << tr("View key: ") << string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_view_secret_key) << ENDL;
}
catch (const std::exception& e)
@@ -2878,7 +2911,7 @@ bool simple_wallet::new_wallet(const boost::program_options::variables_map& vm,
m_wallet->generate(m_wallet_file, std::move(rc.second).password(), address, viewkey);
}
message_writer(console_color_white, true) << tr("Generated new wallet: ")
- << m_wallet->get_account().get_public_address_str(m_wallet->testnet());
+ << m_wallet->get_account().get_public_address_str(m_wallet->nettype());
}
catch (const std::exception& e)
{
@@ -2906,7 +2939,7 @@ bool simple_wallet::new_wallet(const boost::program_options::variables_map& vm,
{
m_wallet->restore(m_wallet_file, std::move(rc.second).password(), device_name);
message_writer(console_color_white, true) << tr("Generated new on device wallet: ")
- << m_wallet->get_account().get_public_address_str(m_wallet->testnet());
+ << m_wallet->get_account().get_public_address_str(m_wallet->nettype());
}
catch (const std::exception& e)
{
@@ -2949,7 +2982,7 @@ bool simple_wallet::new_wallet(const boost::program_options::variables_map& vm,
return false;
}
message_writer(console_color_white, true) << boost::format(tr("Generated new %u/%u multisig wallet: ")) % threshold % total
- << m_wallet->get_account().get_public_address_str(m_wallet->testnet());
+ << m_wallet->get_account().get_public_address_str(m_wallet->nettype());
}
catch (const std::exception& e)
{
@@ -2988,7 +3021,7 @@ bool simple_wallet::open_wallet(const boost::program_options::variables_map& vm)
else
prefix = tr("Opened wallet");
message_writer(console_color_white, true) <<
- prefix << ": " << m_wallet->get_account().get_public_address_str(m_wallet->testnet());
+ prefix << ": " << m_wallet->get_account().get_public_address_str(m_wallet->nettype());
if (m_wallet->get_account().get_device()) {
message_writer(console_color_white, true) << "Wallet is on device: " << m_wallet->get_account().get_device().get_name();
}
@@ -3102,7 +3135,7 @@ bool simple_wallet::save_watch_only(const std::vector<std::string> &args/* = std
return true;
}
- const auto pwd_container = tools::password_container::prompt(true, tr("Password for new watch-only wallet"));
+ const auto pwd_container = password_prompter(tr("Password for new watch-only wallet"), true);
if (!pwd_container)
{
@@ -3132,7 +3165,7 @@ bool simple_wallet::start_mining(const std::vector<std::string>& args)
return true;
}
COMMAND_RPC_START_MINING::request req = AUTO_VAL_INIT(req);
- req.miner_address = m_wallet->get_account().get_public_address_str(m_wallet->testnet());
+ req.miner_address = m_wallet->get_account().get_public_address_str(m_wallet->nettype());
bool ok = true;
size_t max_mining_threads_count = (std::max)(tools::get_max_concurrency(), static_cast<unsigned>(2));
@@ -3221,7 +3254,7 @@ bool simple_wallet::set_daemon(const std::vector<std::string>& args)
// If no port has been provided, use the default from config
if (!match[3].length())
{
- int daemon_port = m_wallet->testnet() ? config::testnet::RPC_DEFAULT_PORT : config::RPC_DEFAULT_PORT;
+ int daemon_port = m_wallet->nettype() == cryptonote::TESTNET ? config::testnet::RPC_DEFAULT_PORT : m_wallet->nettype() == cryptonote::STAGENET ? config::stagenet::RPC_DEFAULT_PORT : config::RPC_DEFAULT_PORT;
daemon_url = match[1] + match[2] + std::string(":") + std::to_string(daemon_port);
} else {
daemon_url = args[0];
@@ -3683,14 +3716,25 @@ bool simple_wallet::print_ring_members(const std::vector<tools::wallet2::pending
const tools::wallet2::tx_construction_data& construction_data = ptx_vector[n].construction_data;
ostr << boost::format(tr("\nTransaction %llu/%llu: txid=%s")) % (n + 1) % ptx_vector.size() % cryptonote::get_transaction_hash(tx);
// for each input
- std::vector<int> spent_key_height(tx.vin.size());
+ std::vector<uint64_t> spent_key_height(tx.vin.size());
std::vector<crypto::hash> spent_key_txid (tx.vin.size());
for (size_t i = 0; i < tx.vin.size(); ++i)
{
if (tx.vin[i].type() != typeid(cryptonote::txin_to_key))
continue;
const cryptonote::txin_to_key& in_key = boost::get<cryptonote::txin_to_key>(tx.vin[i]);
- const cryptonote::tx_source_entry& source = construction_data.sources[i];
+ const tools::wallet2::transfer_details &td = m_wallet->get_transfer_details(construction_data.selected_transfers[i]);
+ const cryptonote::tx_source_entry *sptr = NULL;
+ for (const auto &src: construction_data.sources)
+ if (src.outputs[src.real_output].second.dest == td.get_public_key())
+ sptr = &src;
+ if (!sptr)
+ {
+ fail_msg_writer() << tr("failed to find construction data for tx input");
+ return false;
+ }
+ const cryptonote::tx_source_entry& source = *sptr;
+
ostr << boost::format(tr("\nInput %llu/%llu: amount=%s")) % (i + 1) % tx.vin.size() % print_money(source.amount);
// convert relative offsets of ring member keys into absolute offsets (indices) associated with the amount
std::vector<uint64_t> absolute_offsets = cryptonote::relative_output_offsets_to_absolute(in_key.key_offsets);
@@ -3744,7 +3788,7 @@ bool simple_wallet::print_ring_members(const std::vector<tools::wallet2::pending
{
if (spent_key_txid[i] == spent_key_txid[j])
are_keys_from_same_tx = true;
- if (std::abs(spent_key_height[i] - spent_key_height[j]) < 5)
+ if (std::abs((int64_t)(spent_key_height[i] - spent_key_height[j])) < (int64_t)5)
are_keys_from_close_height = true;
}
}
@@ -3880,7 +3924,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
{
cryptonote::address_parse_info info;
cryptonote::tx_destination_entry de;
- if (!cryptonote::get_account_address_from_str_or_url(info, m_wallet->testnet(), local_args[i], oa_prompter))
+ if (!cryptonote::get_account_address_from_str_or_url(info, m_wallet->nettype(), local_args[i], oa_prompter))
{
fail_msg_writer() << tr("failed to parse address");
return true;
@@ -4329,7 +4373,7 @@ bool simple_wallet::sweep_main(uint64_t below, const std::vector<std::string> &a
}
cryptonote::address_parse_info info;
- if (!cryptonote::get_account_address_from_str_or_url(info, m_wallet->testnet(), local_args[0], oa_prompter))
+ if (!cryptonote::get_account_address_from_str_or_url(info, m_wallet->nettype(), local_args[0], oa_prompter))
{
fail_msg_writer() << tr("failed to parse address");
return true;
@@ -4543,7 +4587,7 @@ bool simple_wallet::sweep_single(const std::vector<std::string> &args_)
}
cryptonote::address_parse_info info;
- if (!cryptonote::get_account_address_from_str_or_url(info, m_wallet->testnet(), local_args[1], oa_prompter))
+ if (!cryptonote::get_account_address_from_str_or_url(info, m_wallet->nettype(), local_args[1], oa_prompter))
{
fail_msg_writer() << tr("failed to parse address");
return true;
@@ -4690,9 +4734,9 @@ bool simple_wallet::sweep_below(const std::vector<std::string> &args_)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::donate(const std::vector<std::string> &args_)
{
- if(m_wallet->testnet())
+ if(m_wallet->nettype() != cryptonote::MAINNET)
{
- fail_msg_writer() << tr("donations are not enabled on the testnet");
+ fail_msg_writer() << tr("donations are not enabled on the testnet or on the stagenet");
return true;
}
@@ -4773,10 +4817,10 @@ bool simple_wallet::accept_loaded_tx(const std::function<size_t()> get_num_txes,
for (size_t d = 0; d < cd.splitted_dsts.size(); ++d)
{
const tx_destination_entry &entry = cd.splitted_dsts[d];
- std::string address, standard_address = get_account_address_as_str(m_wallet->testnet(), entry.is_subaddress, entry.addr);
+ std::string address, standard_address = get_account_address_as_str(m_wallet->nettype(), entry.is_subaddress, entry.addr);
if (has_encrypted_payment_id && !entry.is_subaddress)
{
- address = get_account_integrated_address_as_str(m_wallet->testnet(), entry.addr, payment_id8);
+ address = get_account_integrated_address_as_str(m_wallet->nettype(), entry.addr, payment_id8);
address += std::string(" (" + standard_address + " with encrypted payment id " + epee::string_tools::pod_to_hex(payment_id8) + ")");
}
else
@@ -4847,7 +4891,7 @@ bool simple_wallet::accept_loaded_tx(const std::function<size_t()> get_num_txes,
std::string change_string;
if (change > 0)
{
- std::string address = get_account_address_as_str(m_wallet->testnet(), get_tx(0).subaddr_account > 0, get_tx(0).change_dts.addr);
+ std::string address = get_account_address_as_str(m_wallet->nettype(), get_tx(0).subaddr_account > 0, get_tx(0).change_dts.addr);
change_string += (boost::format(tr("%s change to %s")) % print_money(change) % address).str();
}
else
@@ -5035,7 +5079,7 @@ bool simple_wallet::get_tx_proof(const std::vector<std::string> &args)
}
cryptonote::address_parse_info info;
- if(!cryptonote::get_account_address_from_str_or_url(info, m_wallet->testnet(), args[1], oa_prompter))
+ if(!cryptonote::get_account_address_from_str_or_url(info, m_wallet->nettype(), args[1], oa_prompter))
{
fail_msg_writer() << tr("failed to parse address");
return true;
@@ -5103,7 +5147,7 @@ bool simple_wallet::check_tx_key(const std::vector<std::string> &args_)
}
cryptonote::address_parse_info info;
- if(!cryptonote::get_account_address_from_str_or_url(info, m_wallet->testnet(), local_args[2], oa_prompter))
+ if(!cryptonote::get_account_address_from_str_or_url(info, m_wallet->nettype(), local_args[2], oa_prompter))
{
fail_msg_writer() << tr("failed to parse address");
return true;
@@ -5118,7 +5162,7 @@ bool simple_wallet::check_tx_key(const std::vector<std::string> &args_)
if (received > 0)
{
- success_msg_writer() << get_account_address_as_str(m_wallet->testnet(), info.is_subaddress, info.address) << " " << tr("received") << " " << print_money(received) << " " << tr("in txid") << " " << txid;
+ success_msg_writer() << get_account_address_as_str(m_wallet->nettype(), info.is_subaddress, info.address) << " " << tr("received") << " " << print_money(received) << " " << tr("in txid") << " " << txid;
if (in_pool)
{
success_msg_writer() << tr("WARNING: this transaction is not yet included in the blockchain!");
@@ -5137,7 +5181,7 @@ bool simple_wallet::check_tx_key(const std::vector<std::string> &args_)
}
else
{
- fail_msg_writer() << get_account_address_as_str(m_wallet->testnet(), info.is_subaddress, info.address) << " " << tr("received nothing in txid") << " " << txid;
+ fail_msg_writer() << get_account_address_as_str(m_wallet->nettype(), info.is_subaddress, info.address) << " " << tr("received nothing in txid") << " " << txid;
}
}
catch (const std::exception &e)
@@ -5167,7 +5211,7 @@ bool simple_wallet::check_tx_proof(const std::vector<std::string> &args)
// parse address
cryptonote::address_parse_info info;
- if(!cryptonote::get_account_address_from_str_or_url(info, m_wallet->testnet(), args[1], oa_prompter))
+ if(!cryptonote::get_account_address_from_str_or_url(info, m_wallet->nettype(), args[1], oa_prompter))
{
fail_msg_writer() << tr("failed to parse address");
return true;
@@ -5191,7 +5235,7 @@ bool simple_wallet::check_tx_proof(const std::vector<std::string> &args)
success_msg_writer() << tr("Good signature");
if (received > 0)
{
- success_msg_writer() << get_account_address_as_str(m_wallet->testnet(), info.is_subaddress, info.address) << " " << tr("received") << " " << print_money(received) << " " << tr("in txid") << " " << txid;
+ success_msg_writer() << get_account_address_as_str(m_wallet->nettype(), info.is_subaddress, info.address) << " " << tr("received") << " " << print_money(received) << " " << tr("in txid") << " " << txid;
if (in_pool)
{
success_msg_writer() << tr("WARNING: this transaction is not yet included in the blockchain!");
@@ -5210,7 +5254,7 @@ bool simple_wallet::check_tx_proof(const std::vector<std::string> &args)
}
else
{
- fail_msg_writer() << get_account_address_as_str(m_wallet->testnet(), info.is_subaddress, info.address) << " " << tr("received nothing in txid") << " " << txid;
+ fail_msg_writer() << get_account_address_as_str(m_wallet->nettype(), info.is_subaddress, info.address) << " " << tr("received nothing in txid") << " " << txid;
}
}
else
@@ -5385,7 +5429,7 @@ bool simple_wallet::check_reserve_proof(const std::vector<std::string> &args)
}
cryptonote::address_parse_info info;
- if(!cryptonote::get_account_address_from_str_or_url(info, m_wallet->testnet(), args[0], oa_prompter))
+ if(!cryptonote::get_account_address_from_str_or_url(info, m_wallet->nettype(), args[0], oa_prompter))
{
fail_msg_writer() << tr("failed to parse address");
return true;
@@ -5580,7 +5624,7 @@ bool simple_wallet::show_transfers(const std::vector<std::string> &args_)
for (const auto &d: pd.m_dests) {
if (!dests.empty())
dests += ", ";
- dests += get_account_address_as_str(m_wallet->testnet(), d.is_subaddress, d.addr) + ": " + print_money(d.amount);
+ dests += get_account_address_as_str(m_wallet->nettype(), d.is_subaddress, d.addr) + ": " + print_money(d.amount);
}
std::string payment_id = string_tools::pod_to_hex(i->second.m_payment_id);
if (payment_id.substr(16).find_first_not_of('0') == std::string::npos)
@@ -6179,7 +6223,7 @@ bool simple_wallet::print_integrated_address(const std::vector<std::string> &arg
}
payment_id = crypto::rand<crypto::hash8>();
success_msg_writer() << tr("Random payment ID: ") << payment_id;
- success_msg_writer() << tr("Matching integrated address: ") << m_wallet->get_account().get_public_integrated_address_str(payment_id, m_wallet->testnet());
+ success_msg_writer() << tr("Matching integrated address: ") << m_wallet->get_account().get_public_integrated_address_str(payment_id, m_wallet->nettype());
return true;
}
if(tools::wallet2::parse_short_payment_id(args.back(), payment_id))
@@ -6189,21 +6233,21 @@ bool simple_wallet::print_integrated_address(const std::vector<std::string> &arg
fail_msg_writer() << tr("Integrated addresses can only be created for account 0");
return true;
}
- success_msg_writer() << m_wallet->get_account().get_public_integrated_address_str(payment_id, m_wallet->testnet());
+ success_msg_writer() << m_wallet->get_account().get_public_integrated_address_str(payment_id, m_wallet->nettype());
return true;
}
else {
address_parse_info info;
- if(get_account_address_from_str(info, m_wallet->testnet(), args.back()))
+ if(get_account_address_from_str(info, m_wallet->nettype(), args.back()))
{
if (info.has_payment_id)
{
success_msg_writer() << boost::format(tr("Integrated address: %s, payment ID: %s")) %
- get_account_address_as_str(m_wallet->testnet(), false, info.address) % epee::string_tools::pod_to_hex(info.payment_id);
+ get_account_address_as_str(m_wallet->nettype(), false, info.address) % epee::string_tools::pod_to_hex(info.payment_id);
}
else
{
- success_msg_writer() << (info.is_subaddress ? tr("Subaddress: ") : tr("Standard address: ")) << get_account_address_as_str(m_wallet->testnet(), info.is_subaddress, info.address);
+ success_msg_writer() << (info.is_subaddress ? tr("Subaddress: ") : tr("Standard address: ")) << get_account_address_as_str(m_wallet->nettype(), info.is_subaddress, info.address);
}
return true;
}
@@ -6225,7 +6269,7 @@ bool simple_wallet::address_book(const std::vector<std::string> &args/* = std::v
else if (args[0] == "add")
{
cryptonote::address_parse_info info;
- if(!cryptonote::get_account_address_from_str_or_url(info, m_wallet->testnet(), args[1], oa_prompter))
+ if(!cryptonote::get_account_address_from_str_or_url(info, m_wallet->nettype(), args[1], oa_prompter))
{
fail_msg_writer() << tr("failed to parse address");
return true;
@@ -6282,7 +6326,7 @@ bool simple_wallet::address_book(const std::vector<std::string> &args/* = std::v
for (size_t i = 0; i < address_book.size(); ++i) {
auto& row = address_book[i];
success_msg_writer() << tr("Index: ") << i;
- success_msg_writer() << tr("Address: ") << get_account_address_as_str(m_wallet->testnet(), row.m_is_subaddress, row.m_address);
+ success_msg_writer() << tr("Address: ") << get_account_address_as_str(m_wallet->nettype(), row.m_is_subaddress, row.m_address);
success_msg_writer() << tr("Payment ID: ") << row.m_payment_id;
success_msg_writer() << tr("Description: ") << row.m_description << "\n";
}
@@ -6408,7 +6452,7 @@ bool simple_wallet::wallet_info(const std::vector<std::string> &args)
message_writer() << tr("Filename: ") << m_wallet->get_wallet_file();
message_writer() << tr("Description: ") << m_wallet->get_description();
- message_writer() << tr("Address: ") << m_wallet->get_account().get_public_address_str(m_wallet->testnet());
+ message_writer() << tr("Address: ") << m_wallet->get_account().get_public_address_str(m_wallet->nettype());
std::string type;
if (m_wallet->watch_only())
type = tr("Watch only");
@@ -6417,7 +6461,9 @@ bool simple_wallet::wallet_info(const std::vector<std::string> &args)
else
type = tr("Normal");
message_writer() << tr("Type: ") << type;
- message_writer() << tr("Testnet: ") << (m_wallet->testnet() ? tr("Yes") : tr("No"));
+ message_writer() << tr("Network type: ") << (
+ m_wallet->nettype() == cryptonote::TESTNET ? tr("Testnet") :
+ m_wallet->nettype() == cryptonote::STAGENET ? tr("Stagenet") : tr("Mainnet"));
return true;
}
//----------------------------------------------------------------------------------------------------
@@ -6477,7 +6523,7 @@ bool simple_wallet::verify(const std::vector<std::string> &args)
}
cryptonote::address_parse_info info;
- if(!cryptonote::get_account_address_from_str_or_url(info, m_wallet->testnet(), address_string, oa_prompter))
+ if(!cryptonote::get_account_address_from_str_or_url(info, m_wallet->nettype(), address_string, oa_prompter))
{
fail_msg_writer() << tr("failed to parse address");
return true;
@@ -6780,7 +6826,7 @@ bool simple_wallet::show_transfer(const std::vector<std::string> &args)
for (const auto &d: pd.m_dests) {
if (!dests.empty())
dests += ", ";
- dests += get_account_address_as_str(m_wallet->testnet(), d.is_subaddress, d.addr) + ": " + print_money(d.amount);
+ dests += get_account_address_as_str(m_wallet->nettype(), d.is_subaddress, d.addr) + ": " + print_money(d.amount);
}
std::string payment_id = string_tools::pod_to_hex(i->second.m_payment_id);
if (payment_id.substr(16).find_first_not_of('0') == std::string::npos)
@@ -6906,6 +6952,12 @@ void simple_wallet::commit_or_save(std::vector<tools::wallet2::pending_tx>& ptx_
//----------------------------------------------------------------------------------------------------
int main(int argc, char* argv[])
{
+#ifdef WIN32
+ // Activate UTF-8 support for Boost filesystem classes on Windows
+ std::locale::global(boost::locale::generator().generate(""));
+ boost::filesystem::path::imbue(std::locale());
+#endif
+
po::options_description desc_params(wallet_args::tr("Wallet options"));
tools::wallet2::init_options(desc_params);
command_line::add_arg(desc_params, arg_wallet_file);
diff --git a/src/wallet/api/address_book.cpp b/src/wallet/api/address_book.cpp
index 38c34a912..7ef011e06 100644
--- a/src/wallet/api/address_book.cpp
+++ b/src/wallet/api/address_book.cpp
@@ -49,7 +49,7 @@ bool AddressBookImpl::addRow(const std::string &dst_addr , const std::string &pa
clearStatus();
cryptonote::address_parse_info info;
- if(!cryptonote::get_account_address_from_str(info, m_wallet->m_wallet->testnet(), dst_addr)) {
+ if(!cryptonote::get_account_address_from_str(info, m_wallet->m_wallet->nettype(), dst_addr)) {
m_errorString = tr("Invalid destination address");
m_errorCode = Invalid_Address;
return false;
@@ -105,13 +105,13 @@ void AddressBookImpl::refresh()
tools::wallet2::address_book_row * row = &rows.at(i);
std::string payment_id = (row->m_payment_id == crypto::null_hash)? "" : epee::string_tools::pod_to_hex(row->m_payment_id);
- std::string address = cryptonote::get_account_address_as_str(m_wallet->m_wallet->testnet(), row->m_is_subaddress, row->m_address);
+ std::string address = cryptonote::get_account_address_as_str(m_wallet->m_wallet->nettype(), row->m_is_subaddress, row->m_address);
// convert the zero padded short payment id to integrated address
if (!row->m_is_subaddress && payment_id.length() > 16 && payment_id.substr(16).find_first_not_of('0') == std::string::npos) {
payment_id = payment_id.substr(0,16);
crypto::hash8 payment_id_short;
if(tools::wallet2::parse_short_payment_id(payment_id, payment_id_short)) {
- address = cryptonote::get_account_integrated_address_as_str(m_wallet->m_wallet->testnet(), row->m_address, payment_id_short);
+ address = cryptonote::get_account_integrated_address_as_str(m_wallet->m_wallet->nettype(), row->m_address, payment_id_short);
// Don't show payment id when integrated address is used
payment_id = "";
}
diff --git a/src/wallet/api/transaction_history.cpp b/src/wallet/api/transaction_history.cpp
index 95a055f8f..ba46a6904 100644
--- a/src/wallet/api/transaction_history.cpp
+++ b/src/wallet/api/transaction_history.cpp
@@ -181,7 +181,7 @@ void TransactionHistoryImpl::refresh()
// single output transaction might contain multiple transfers
for (const auto &d: pd.m_dests) {
- ti->m_transfers.push_back({d.amount, get_account_address_as_str(m_wallet->m_wallet->testnet(), d.is_subaddress, d.addr)});
+ ti->m_transfers.push_back({d.amount, get_account_address_as_str(m_wallet->m_wallet->nettype(), d.is_subaddress, d.addr)});
}
m_history.push_back(ti);
}
diff --git a/src/wallet/api/unsigned_transaction.cpp b/src/wallet/api/unsigned_transaction.cpp
index c6ebcb009..29910a3b6 100644
--- a/src/wallet/api/unsigned_transaction.cpp
+++ b/src/wallet/api/unsigned_transaction.cpp
@@ -144,10 +144,10 @@ bool UnsignedTransactionImpl::checkLoadedTx(const std::function<size_t()> get_nu
for (size_t d = 0; d < cd.splitted_dsts.size(); ++d)
{
const cryptonote::tx_destination_entry &entry = cd.splitted_dsts[d];
- std::string address, standard_address = get_account_address_as_str(m_wallet.testnet(), entry.is_subaddress, entry.addr);
+ std::string address, standard_address = get_account_address_as_str(m_wallet.m_wallet->nettype(), entry.is_subaddress, entry.addr);
if (has_encrypted_payment_id && !entry.is_subaddress)
{
- address = get_account_integrated_address_as_str(m_wallet.testnet(), entry.addr, payment_id8);
+ address = get_account_integrated_address_as_str(m_wallet.m_wallet->nettype(), entry.addr, payment_id8);
address += std::string(" (" + standard_address + " with encrypted payment id " + epee::string_tools::pod_to_hex(payment_id8) + ")");
}
else
@@ -205,7 +205,7 @@ bool UnsignedTransactionImpl::checkLoadedTx(const std::function<size_t()> get_nu
std::string change_string;
if (change > 0)
{
- std::string address = get_account_address_as_str(m_wallet.m_wallet->testnet(), get_tx(0).subaddr_account > 0, get_tx(0).change_dts.addr);
+ std::string address = get_account_address_as_str(m_wallet.m_wallet->nettype(), get_tx(0).subaddr_account > 0, get_tx(0).change_dts.addr);
change_string += (boost::format(tr("%s change to %s")) % cryptonote::print_money(change) % address).str();
}
else
@@ -297,7 +297,7 @@ std::vector<std::string> UnsignedTransactionImpl::recipientAddress() const
MERROR("empty destinations, skipped");
continue;
}
- result.push_back(cryptonote::get_account_address_as_str(m_wallet.m_wallet->testnet(), utx.dests[0].is_subaddress, utx.dests[0].addr));
+ result.push_back(cryptonote::get_account_address_as_str(m_wallet.m_wallet->nettype(), utx.dests[0].is_subaddress, utx.dests[0].addr));
}
return result;
}
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index 5ce8ede8d..ff0d2fdbd 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -40,10 +40,16 @@
#include "common/util.h"
#include "mnemonics/electrum-words.h"
+#include "mnemonics/english.h"
#include <boost/format.hpp>
#include <sstream>
#include <unordered_map>
+#ifdef WIN32
+#include <boost/locale.hpp>
+#include <boost/filesystem.hpp>
+#endif
+
using namespace std;
using namespace cryptonote;
@@ -233,16 +239,16 @@ bool Wallet::paymentIdValid(const string &paiment_id)
return false;
}
-bool Wallet::addressValid(const std::string &str, bool testnet)
+bool Wallet::addressValid(const std::string &str, NetworkType nettype)
{
cryptonote::address_parse_info info;
- return get_account_address_from_str(info, testnet, str);
+ return get_account_address_from_str(info, static_cast<cryptonote::network_type>(nettype), str);
}
-bool Wallet::keyValid(const std::string &secret_key_string, const std::string &address_string, bool isViewKey, bool testnet, std::string &error)
+bool Wallet::keyValid(const std::string &secret_key_string, const std::string &address_string, bool isViewKey, NetworkType nettype, std::string &error)
{
cryptonote::address_parse_info info;
- if(!get_account_address_from_str(info, testnet, address_string)) {
+ if(!get_account_address_from_str(info, static_cast<cryptonote::network_type>(nettype), address_string)) {
error = tr("Failed to parse address");
return false;
}
@@ -275,10 +281,10 @@ bool Wallet::keyValid(const std::string &secret_key_string, const std::string &a
return true;
}
-std::string Wallet::paymentIdFromAddress(const std::string &str, bool testnet)
+std::string Wallet::paymentIdFromAddress(const std::string &str, NetworkType nettype)
{
cryptonote::address_parse_info info;
- if (!get_account_address_from_str(info, testnet, str))
+ if (!get_account_address_from_str(info, static_cast<cryptonote::network_type>(nettype), str))
return "";
if (!info.has_payment_id)
return "";
@@ -291,6 +297,11 @@ uint64_t Wallet::maximumAllowedAmount()
}
void Wallet::init(const char *argv0, const char *default_log_base_name) {
+#ifdef WIN32
+ // Activate UTF-8 support for Boost filesystem classes on Windows
+ std::locale::global(boost::locale::generator().generate(""));
+ boost::filesystem::path::imbue(std::locale());
+#endif
epee::string_tools::set_module_name_and_folder(argv0);
mlog_configure(mlog_get_default_log_path(default_log_base_name), true);
}
@@ -300,7 +311,7 @@ void Wallet::debug(const std::string &str) {
}
///////////////////////// WalletImpl implementation ////////////////////////
-WalletImpl::WalletImpl(bool testnet)
+WalletImpl::WalletImpl(NetworkType nettype)
:m_wallet(nullptr)
, m_status(Wallet::Status_Ok)
, m_trustedDaemon(false)
@@ -310,7 +321,7 @@ WalletImpl::WalletImpl(bool testnet)
, m_rebuildWalletCache(false)
, m_is_connected(false)
{
- m_wallet = new tools::wallet2(testnet);
+ m_wallet = new tools::wallet2(static_cast<cryptonote::network_type>(nettype));
m_history = new TransactionHistoryImpl(this);
m_wallet2Callback = new Wallet2CallbackImpl(this);
m_wallet->callback(m_wallet2Callback);
@@ -388,7 +399,7 @@ bool WalletImpl::create(const std::string &path, const std::string &password, co
bool WalletImpl::createWatchOnly(const std::string &path, const std::string &password, const std::string &language) const
{
clearStatus();
- std::unique_ptr<tools::wallet2> view_wallet(new tools::wallet2(m_wallet->testnet()));
+ std::unique_ptr<tools::wallet2> view_wallet(new tools::wallet2(m_wallet->nettype()));
// Store same refresh height as original wallet
view_wallet->set_refresh_from_block_height(m_wallet->get_refresh_from_block_height());
@@ -469,7 +480,7 @@ bool WalletImpl::recoverFromKeysWithPassword(const std::string &path,
const std::string &spendkey_string)
{
cryptonote::address_parse_info info;
- if(!get_account_address_from_str(info, m_wallet->testnet(), address_string))
+ if(!get_account_address_from_str(info, m_wallet->nettype(), address_string))
{
m_errorString = tr("failed to parse address");
m_status = Status_Error;
@@ -603,6 +614,9 @@ bool WalletImpl::recover(const std::string &path, const std::string &password, c
return false;
}
+ if (old_language == crypto::ElectrumWords::old_language_name)
+ old_language = Language::English().get_language_name();
+
try {
m_wallet->set_seed_language(old_language);
m_wallet->generate(path, password, recovery_key, true, false);
@@ -1079,7 +1093,7 @@ PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, const
PendingTransactionImpl * transaction = new PendingTransactionImpl(*this);
do {
- if(!cryptonote::get_account_address_from_str(info, m_wallet->testnet(), dst_addr)) {
+ if(!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), dst_addr)) {
// TODO: copy-paste 'if treating as an address fails, try as url' from simplewallet.cpp:1982
m_status = Status_Error;
m_errorString = "Invalid destination address";
@@ -1464,7 +1478,7 @@ bool WalletImpl::checkTxKey(const std::string &txid_str, std::string tx_key_str,
}
cryptonote::address_parse_info info;
- if (!cryptonote::get_account_address_from_str(info, m_wallet->testnet(), address_str))
+ if (!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), address_str))
{
m_status = Status_Error;
m_errorString = tr("Failed to parse address");
@@ -1496,7 +1510,7 @@ std::string WalletImpl::getTxProof(const std::string &txid_str, const std::strin
}
cryptonote::address_parse_info info;
- if (!cryptonote::get_account_address_from_str(info, m_wallet->testnet(), address_str))
+ if (!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), address_str))
{
m_status = Status_Error;
m_errorString = tr("Failed to parse address");
@@ -1527,7 +1541,7 @@ bool WalletImpl::checkTxProof(const std::string &txid_str, const std::string &ad
}
cryptonote::address_parse_info info;
- if (!cryptonote::get_account_address_from_str(info, m_wallet->testnet(), address_str))
+ if (!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), address_str))
{
m_status = Status_Error;
m_errorString = tr("Failed to parse address");
@@ -1615,7 +1629,7 @@ std::string WalletImpl::getReserveProof(bool all, uint32_t account_index, uint64
bool WalletImpl::checkReserveProof(const std::string &address, const std::string &message, const std::string &signature, bool &good, uint64_t &total, uint64_t &spent) const {
cryptonote::address_parse_info info;
- if (!cryptonote::get_account_address_from_str(info, m_wallet->testnet(), address))
+ if (!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), address))
{
m_status = Status_Error;
m_errorString = tr("Failed to parse address");
@@ -1652,7 +1666,7 @@ bool WalletImpl::verifySignedMessage(const std::string &message, const std::stri
{
cryptonote::address_parse_info info;
- if (!cryptonote::get_account_address_from_str(info, m_wallet->testnet(), address))
+ if (!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), address))
return false;
return m_wallet->verify(message, info.address, signature);
@@ -1746,7 +1760,7 @@ void WalletImpl::doRefresh()
m_synchronized = true;
}
// assuming if we have empty history, it wasn't initialized yet
- // for futher history changes client need to update history in
+ // for further history changes client need to update history in
// "on_money_received" and "on_money_sent" callbacks
if (m_history->count() == 0) {
m_history->refresh();
diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h
index fcd53c3f8..9b4a0cc12 100644
--- a/src/wallet/api/wallet.h
+++ b/src/wallet/api/wallet.h
@@ -52,7 +52,7 @@ struct Wallet2CallbackImpl;
class WalletImpl : public Wallet
{
public:
- WalletImpl(bool testnet = false);
+ WalletImpl(NetworkType nettype = MAINNET);
~WalletImpl();
bool create(const std::string &path, const std::string &password,
const std::string &language);
@@ -115,7 +115,7 @@ public:
void setRecoveringFromSeed(bool recoveringFromSeed);
bool watchOnly() const;
bool rescanSpent();
- bool testnet() const {return m_wallet->testnet();}
+ NetworkType nettype() const {return static_cast<NetworkType>(m_wallet->nettype());}
void hardForkInfo(uint8_t &version, uint64_t &earliest_height) const;
bool useForkRules(uint8_t version, int64_t early_blocks) const;
diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h
index a22788399..a6320545e 100644
--- a/src/wallet/api/wallet2_api.h
+++ b/src/wallet/api/wallet2_api.h
@@ -40,6 +40,12 @@
// Public interface for libwallet library
namespace Monero {
+enum NetworkType : uint8_t {
+ MAINNET = 0,
+ TESTNET,
+ STAGENET
+};
+
namespace Utils {
bool isAddressLocal(const std::string &hostaddr);
void onStartup();
@@ -358,7 +364,10 @@ struct Wallet
virtual std::string address(uint32_t accountIndex = 0, uint32_t addressIndex = 0) const = 0;
std::string mainAddress() const { return address(0, 0); }
virtual std::string path() const = 0;
- virtual bool testnet() const = 0;
+ virtual NetworkType nettype() const = 0;
+ bool mainnet() const { return nettype() == MAINNET; }
+ bool testnet() const { return nettype() == TESTNET; }
+ bool stagenet() const { return nettype() == STAGENET; }
//! returns current hard fork info
virtual void hardForkInfo(uint8_t &version, uint64_t &earliest_height) const = 0;
//! check if hard fork rules should be used
@@ -529,9 +538,21 @@ struct Wallet
static uint64_t amountFromDouble(double amount);
static std::string genPaymentId();
static bool paymentIdValid(const std::string &paiment_id);
- static bool addressValid(const std::string &str, bool testnet);
- static bool keyValid(const std::string &secret_key_string, const std::string &address_string, bool isViewKey, bool testnet, std::string &error);
- static std::string paymentIdFromAddress(const std::string &str, bool testnet);
+ static bool addressValid(const std::string &str, NetworkType nettype);
+ static bool addressValid(const std::string &str, bool testnet) // deprecated
+ {
+ return addressValid(str, testnet ? MAINNET : TESTNET);
+ }
+ static bool keyValid(const std::string &secret_key_string, const std::string &address_string, bool isViewKey, NetworkType nettype, std::string &error);
+ static bool keyValid(const std::string &secret_key_string, const std::string &address_string, bool isViewKey, bool testnet, std::string &error) // deprecated
+ {
+ return keyValid(secret_key_string, address_string, isViewKey, testnet ? TESTNET : MAINNET, error);
+ }
+ static std::string paymentIdFromAddress(const std::string &str, NetworkType nettype);
+ static std::string paymentIdFromAddress(const std::string &str, bool testnet) // deprecated
+ {
+ return paymentIdFromAddress(str, testnet ? TESTNET : MAINNET);
+ }
static uint64_t maximumAllowedAmount();
// Easylogger wrapper
static void init(const char *argv0, const char *default_log_base_name);
@@ -685,7 +706,7 @@ struct Wallet
* \brief setUserNote - attach an arbitrary string note to a txid
* \param txid - the transaction id to attach the note to
* \param note - the note
- * \return true if succesful, false otherwise
+ * \return true if successful, false otherwise
*/
virtual bool setUserNote(const std::string &txid, const std::string &note) = 0;
/*!
@@ -750,47 +771,66 @@ struct WalletManager
* \param path Name of wallet file
* \param password Password of wallet file
* \param language Language to be used to generate electrum seed mnemonic
+ * \param nettype Network type
* \return Wallet instance (Wallet::status() needs to be called to check if created successfully)
*/
- virtual Wallet * createWallet(const std::string &path, const std::string &password, const std::string &language, bool testnet = false) = 0;
+ virtual Wallet * createWallet(const std::string &path, const std::string &password, const std::string &language, NetworkType nettype = MAINNET) = 0;
+ Wallet * createWallet(const std::string &path, const std::string &password, const std::string &language, bool testnet = false) // deprecated
+ {
+ return createWallet(path, password, language, testnet ? TESTNET : MAINNET);
+ }
/*!
* \brief Opens existing wallet
* \param path Name of wallet file
* \param password Password of wallet file
+ * \param nettype Network type
* \return Wallet instance (Wallet::status() needs to be called to check if opened successfully)
*/
- virtual Wallet * openWallet(const std::string &path, const std::string &password, bool testnet = false) = 0;
+ virtual Wallet * openWallet(const std::string &path, const std::string &password, NetworkType nettype = MAINNET) = 0;
+ Wallet * openWallet(const std::string &path, const std::string &password, bool testnet = false) // deprecated
+ {
+ return openWallet(path, password, testnet ? TESTNET : MAINNET);
+ }
/*!
* \brief recovers existing wallet using mnemonic (electrum seed)
* \param path Name of wallet file to be created
* \param password Password of wallet file
* \param mnemonic mnemonic (25 words electrum seed)
- * \param testnet testnet
+ * \param nettype Network type
* \param restoreHeight restore from start height
* \return Wallet instance (Wallet::status() needs to be called to check if recovered successfully)
*/
virtual Wallet * recoveryWallet(const std::string &path, const std::string &password, const std::string &mnemonic,
- bool testnet = false, uint64_t restoreHeight = 0) = 0;
+ NetworkType nettype = MAINNET, uint64_t restoreHeight = 0) = 0;
+ Wallet * recoveryWallet(const std::string &path, const std::string &password, const std::string &mnemonic,
+ bool testnet = false, uint64_t restoreHeight = 0) // deprecated
+ {
+ return recoveryWallet(path, password, mnemonic, testnet ? TESTNET : MAINNET, restoreHeight);
+ }
/*!
* \deprecated this method creates a wallet WITHOUT a passphrase, use the alternate recoverWallet() method
* \brief recovers existing wallet using mnemonic (electrum seed)
* \param path Name of wallet file to be created
* \param mnemonic mnemonic (25 words electrum seed)
- * \param testnet testnet
+ * \param nettype Network type
* \param restoreHeight restore from start height
* \return Wallet instance (Wallet::status() needs to be called to check if recovered successfully)
*/
- virtual Wallet * recoveryWallet(const std::string &path, const std::string &mnemonic, bool testnet = false, uint64_t restoreHeight = 0) = 0;
+ virtual Wallet * recoveryWallet(const std::string &path, const std::string &mnemonic, NetworkType nettype = MAINNET, uint64_t restoreHeight = 0) = 0;
+ Wallet * recoveryWallet(const std::string &path, const std::string &mnemonic, bool testnet = false, uint64_t restoreHeight = 0) // deprecated
+ {
+ return recoveryWallet(path, mnemonic, testnet ? TESTNET : MAINNET, restoreHeight);
+ }
/*!
* \brief recovers existing wallet using keys. Creates a view only wallet if spend key is omitted
* \param path Name of wallet file to be created
* \param password Password of wallet file
* \param language language
- * \param testnet testnet
+ * \param nettype Network type
* \param restoreHeight restore from start height
* \param addressString public address
* \param viewKeyString view key
@@ -800,18 +840,29 @@ struct WalletManager
virtual Wallet * createWalletFromKeys(const std::string &path,
const std::string &password,
const std::string &language,
- bool testnet,
+ NetworkType nettype,
uint64_t restoreHeight,
const std::string &addressString,
const std::string &viewKeyString,
const std::string &spendKeyString = "") = 0;
+ Wallet * createWalletFromKeys(const std::string &path,
+ const std::string &password,
+ const std::string &language,
+ bool testnet,
+ uint64_t restoreHeight,
+ const std::string &addressString,
+ const std::string &viewKeyString,
+ const std::string &spendKeyString = "") // deprecated
+ {
+ return createWalletFromKeys(path, password, language, testnet ? TESTNET : MAINNET, restoreHeight, addressString, viewKeyString, spendKeyString);
+ }
/*!
* \deprecated this method creates a wallet WITHOUT a passphrase, use createWalletFromKeys(..., password, ...) instead
* \brief recovers existing wallet using keys. Creates a view only wallet if spend key is omitted
* \param path Name of wallet file to be created
* \param language language
- * \param testnet testnet
+ * \param nettype Network type
* \param restoreHeight restore from start height
* \param addressString public address
* \param viewKeyString view key
@@ -820,14 +871,24 @@ struct WalletManager
*/
virtual Wallet * createWalletFromKeys(const std::string &path,
const std::string &language,
- bool testnet,
+ NetworkType nettype,
uint64_t restoreHeight,
const std::string &addressString,
const std::string &viewKeyString,
const std::string &spendKeyString = "") = 0;
+ Wallet * createWalletFromKeys(const std::string &path,
+ const std::string &language,
+ bool testnet,
+ uint64_t restoreHeight,
+ const std::string &addressString,
+ const std::string &viewKeyString,
+ const std::string &spendKeyString = "") // deprecated
+ {
+ return createWalletFromKeys(path, language, testnet ? TESTNET : MAINNET, restoreHeight, addressString, viewKeyString, spendKeyString);
+ }
/*!
- * \brief Closes wallet. In case operation succeded, wallet object deleted. in case operation failed, wallet object not deleted
+ * \brief Closes wallet. In case operation succeeded, wallet object deleted. in case operation failed, wallet object not deleted
* \param wallet previously opened / created wallet instance
* \return None
*/
diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp
index b3d3150d4..b03332f40 100644
--- a/src/wallet/api/wallet_manager.cpp
+++ b/src/wallet/api/wallet_manager.cpp
@@ -60,46 +60,46 @@ namespace {
namespace Monero {
Wallet *WalletManagerImpl::createWallet(const std::string &path, const std::string &password,
- const std::string &language, bool testnet)
+ const std::string &language, NetworkType nettype)
{
- WalletImpl * wallet = new WalletImpl(testnet);
+ WalletImpl * wallet = new WalletImpl(nettype);
wallet->create(path, password, language);
return wallet;
}
-Wallet *WalletManagerImpl::openWallet(const std::string &path, const std::string &password, bool testnet)
+Wallet *WalletManagerImpl::openWallet(const std::string &path, const std::string &password, NetworkType nettype)
{
- WalletImpl * wallet = new WalletImpl(testnet);
+ WalletImpl * wallet = new WalletImpl(nettype);
wallet->open(path, password);
//Refresh addressBook
wallet->addressBook()->refresh();
return wallet;
}
-Wallet *WalletManagerImpl::recoveryWallet(const std::string &path, const std::string &mnemonic, bool testnet, uint64_t restoreHeight)
+Wallet *WalletManagerImpl::recoveryWallet(const std::string &path, const std::string &mnemonic, NetworkType nettype, uint64_t restoreHeight)
{
- return recoveryWallet(path, "", mnemonic, testnet, restoreHeight);
+ return recoveryWallet(path, "", mnemonic, nettype, restoreHeight);
}
Wallet *WalletManagerImpl::createWalletFromKeys(const std::string &path,
const std::string &language,
- bool testnet,
+ NetworkType nettype,
uint64_t restoreHeight,
const std::string &addressString,
const std::string &viewKeyString,
const std::string &spendKeyString)
{
- return createWalletFromKeys(path, "", language, testnet, restoreHeight,
+ return createWalletFromKeys(path, "", language, nettype, restoreHeight,
addressString, viewKeyString, spendKeyString);
}
Wallet *WalletManagerImpl::recoveryWallet(const std::string &path,
const std::string &password,
const std::string &mnemonic,
- bool testnet,
+ NetworkType nettype,
uint64_t restoreHeight)
{
- WalletImpl * wallet = new WalletImpl(testnet);
+ WalletImpl * wallet = new WalletImpl(nettype);
if(restoreHeight > 0){
wallet->setRefreshFromBlockHeight(restoreHeight);
}
@@ -110,13 +110,13 @@ Wallet *WalletManagerImpl::recoveryWallet(const std::string &path,
Wallet *WalletManagerImpl::createWalletFromKeys(const std::string &path,
const std::string &password,
const std::string &language,
- bool testnet,
+ NetworkType nettype,
uint64_t restoreHeight,
const std::string &addressString,
const std::string &viewKeyString,
const std::string &spendKeyString)
{
- WalletImpl * wallet = new WalletImpl(testnet);
+ WalletImpl * wallet = new WalletImpl(nettype);
if(restoreHeight > 0){
wallet->setRefreshFromBlockHeight(restoreHeight);
}
diff --git a/src/wallet/api/wallet_manager.h b/src/wallet/api/wallet_manager.h
index 6a4d9de2e..409a6d499 100644
--- a/src/wallet/api/wallet_manager.h
+++ b/src/wallet/api/wallet_manager.h
@@ -38,27 +38,27 @@ class WalletManagerImpl : public WalletManager
{
public:
Wallet * createWallet(const std::string &path, const std::string &password,
- const std::string &language, bool testnet);
- Wallet * openWallet(const std::string &path, const std::string &password, bool testnet);
+ const std::string &language, NetworkType nettype);
+ Wallet * openWallet(const std::string &path, const std::string &password, NetworkType nettype);
virtual Wallet * recoveryWallet(const std::string &path,
const std::string &password,
const std::string &mnemonic,
- bool testnet,
+ NetworkType nettype,
uint64_t restoreHeight);
virtual Wallet * createWalletFromKeys(const std::string &path,
const std::string &password,
const std::string &language,
- bool testnet,
+ NetworkType nettype,
uint64_t restoreHeight,
const std::string &addressString,
const std::string &viewKeyString,
const std::string &spendKeyString = "");
// next two methods are deprecated - use the above version which allow setting of a password
- virtual Wallet * recoveryWallet(const std::string &path, const std::string &mnemonic, bool testnet, uint64_t restoreHeight);
+ virtual Wallet * recoveryWallet(const std::string &path, const std::string &mnemonic, NetworkType nettype, uint64_t restoreHeight);
// deprecated: use createWalletFromKeys(..., password, ...) instead
virtual Wallet * createWalletFromKeys(const std::string &path,
const std::string &language,
- bool testnet,
+ NetworkType nettype,
uint64_t restoreHeight,
const std::string &addressString,
const std::string &viewKeyString,
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index d8837eccf..4a6c6fad2 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -118,6 +118,7 @@ struct options {
const command_line::arg_descriptor<int> daemon_port = {"daemon-port", tools::wallet2::tr("Use daemon instance at port <arg> instead of 18081"), 0};
const command_line::arg_descriptor<std::string> daemon_login = {"daemon-login", tools::wallet2::tr("Specify username[:password] for daemon RPC client"), "", true};
const command_line::arg_descriptor<bool> testnet = {"testnet", tools::wallet2::tr("For testnet. Daemon must also be launched with --testnet flag"), false};
+ const command_line::arg_descriptor<bool> stagenet = {"stagenet", tools::wallet2::tr("For stagenet. Daemon must also be launched with --stagenet flag"), false};
const command_line::arg_descriptor<bool> restricted = {"restricted-rpc", tools::wallet2::tr("Restricts to view-only commands"), false};
};
@@ -159,6 +160,7 @@ std::string get_size_string(const cryptonote::blobdata &tx)
std::unique_ptr<tools::wallet2> make_basic(const boost::program_options::variables_map& vm, const options& opts, const std::function<boost::optional<tools::password_container>(const char *, bool)> &password_prompter)
{
const bool testnet = command_line::get_arg(vm, opts.testnet);
+ const bool stagenet = command_line::get_arg(vm, opts.stagenet);
const bool restricted = command_line::get_arg(vm, opts.restricted);
auto daemon_address = command_line::get_arg(vm, opts.daemon_address);
@@ -187,13 +189,13 @@ std::unique_ptr<tools::wallet2> make_basic(const boost::program_options::variabl
if (!daemon_port)
{
- daemon_port = testnet ? config::testnet::RPC_DEFAULT_PORT : config::RPC_DEFAULT_PORT;
+ daemon_port = testnet ? config::testnet::RPC_DEFAULT_PORT : stagenet ? config::stagenet::RPC_DEFAULT_PORT : config::RPC_DEFAULT_PORT;
}
if (daemon_address.empty())
daemon_address = std::string("http://") + daemon_host + ":" + std::to_string(daemon_port);
- std::unique_ptr<tools::wallet2> wallet(new tools::wallet2(testnet, restricted));
+ std::unique_ptr<tools::wallet2> wallet(new tools::wallet2(testnet ? TESTNET : stagenet ? STAGENET : MAINNET, restricted));
wallet->init(std::move(daemon_address), std::move(login));
return wallet;
}
@@ -230,6 +232,8 @@ boost::optional<tools::password_container> get_password(const boost::program_opt
std::unique_ptr<tools::wallet2> generate_from_json(const std::string& json_file, const boost::program_options::variables_map& vm, const options& opts, const std::function<boost::optional<tools::password_container>(const char *, bool)> &password_prompter)
{
const bool testnet = command_line::get_arg(vm, opts.testnet);
+ const bool stagenet = command_line::get_arg(vm, opts.stagenet);
+ const network_type nettype = testnet ? TESTNET : stagenet ? STAGENET : MAINNET;
/* GET_FIELD_FROM_JSON_RETURN_ON_ERROR Is a generic macro that can return
false. Gcc will coerce this into unique_ptr(nullptr), but clang correctly
@@ -329,7 +333,7 @@ std::unique_ptr<tools::wallet2> generate_from_json(const std::string& json_file,
if (field_address_found)
{
cryptonote::address_parse_info info;
- if(!get_account_address_from_str(info, testnet, field_address))
+ if(!get_account_address_from_str(info, nettype, field_address))
{
THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("invalid address"));
}
@@ -383,12 +387,12 @@ std::unique_ptr<tools::wallet2> generate_from_json(const std::string& json_file,
if (field_spendkey.empty())
{
- // if we have an addres but no spend key, we can deduce the spend public key
+ // if we have an address but no spend key, we can deduce the spend public key
// from the address
if (field_address_found)
{
cryptonote::address_parse_info info;
- if(!get_account_address_from_str(info, testnet, field_address))
+ if(!get_account_address_from_str(info, nettype, field_address))
{
THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, std::string(tools::wallet2::tr("failed to parse address: ")) + field_address);
}
@@ -589,12 +593,12 @@ const size_t MAX_SPLIT_ATTEMPTS = 30;
constexpr const std::chrono::seconds wallet2::rpc_timeout;
const char* wallet2::tr(const char* str) { return i18n_translate(str, "tools::wallet2"); }
-wallet2::wallet2(bool testnet, bool restricted):
+wallet2::wallet2(network_type nettype, bool restricted):
m_multisig_rescan_info(NULL),
m_multisig_rescan_k(NULL),
m_run(true),
m_callback(0),
- m_testnet(testnet),
+ m_nettype(nettype),
m_always_confirm_transfers(true),
m_print_ring_members(false),
m_store_tx_info(true),
@@ -634,6 +638,11 @@ bool wallet2::has_testnet_option(const boost::program_options::variables_map& vm
return command_line::get_arg(vm, options().testnet);
}
+bool wallet2::has_stagenet_option(const boost::program_options::variables_map& vm)
+{
+ return command_line::get_arg(vm, options().stagenet);
+}
+
void wallet2::init_options(boost::program_options::options_description& desc_params)
{
const options opts{};
@@ -644,6 +653,7 @@ void wallet2::init_options(boost::program_options::options_description& desc_par
command_line::add_arg(desc_params, opts.daemon_port);
command_line::add_arg(desc_params, opts.daemon_login);
command_line::add_arg(desc_params, opts.testnet);
+ command_line::add_arg(desc_params, opts.stagenet);
command_line::add_arg(desc_params, opts.restricted);
}
@@ -690,7 +700,7 @@ std::unique_ptr<wallet2> wallet2::make_dummy(const boost::program_options::varia
//----------------------------------------------------------------------------------------------------
bool wallet2::init(std::string daemon_address, boost::optional<epee::net_utils::http::login> daemon_login, uint64_t upper_transaction_size_limit, bool ssl)
{
- m_checkpoints.init_default_checkpoints(m_testnet);
+ m_checkpoints.init_default_checkpoints(m_nettype);
if(m_http_client.is_connected())
m_http_client.disconnect();
m_is_initialized = true;
@@ -836,12 +846,12 @@ crypto::public_key wallet2::get_subaddress_spend_public_key(const cryptonote::su
std::string wallet2::get_subaddress_as_str(const cryptonote::subaddress_index& index) const
{
cryptonote::account_public_address address = get_subaddress(index);
- return cryptonote::get_account_address_as_str(m_testnet, !index.is_zero(), address);
+ return cryptonote::get_account_address_as_str(m_nettype, !index.is_zero(), address);
}
//----------------------------------------------------------------------------------------------------
std::string wallet2::get_integrated_address_as_str(const crypto::hash8& payment_id) const
{
- return cryptonote::get_account_integrated_address_as_str(m_testnet, get_address(), payment_id);
+ return cryptonote::get_account_integrated_address_as_str(m_nettype, get_address(), payment_id);
}
//----------------------------------------------------------------------------------------------------
void wallet2::add_subaddress_account(const std::string& label)
@@ -2441,8 +2451,8 @@ bool wallet2::store_keys(const std::string& keys_file_name, const epee::wipeable
value2.SetInt(m_auto_low_priority ? 1 : 0);
json.AddMember("auto_low_priority", value2, json.GetAllocator());
- value2.SetInt(m_testnet ? 1 :0);
- json.AddMember("testnet", value2, json.GetAllocator());
+ value2.SetUint(m_nettype);
+ json.AddMember("nettype", value2, json.GetAllocator());
// Serialize the JSON object
rapidjson::StringBuffer buffer;
@@ -2624,11 +2634,12 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_
m_confirm_export_overwrite = field_confirm_export_overwrite;
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, auto_low_priority, int, Int, false, true);
m_auto_low_priority = field_auto_low_priority;
- GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, testnet, int, Int, false, m_testnet);
- // Wallet is being opened with testnet flag, but is saved as a mainnet wallet
- THROW_WALLET_EXCEPTION_IF(m_testnet && !field_testnet, error::wallet_internal_error, "Mainnet wallet can not be opened as testnet wallet");
- // Wallet is being opened without testnet flag but is saved as a testnet wallet.
- THROW_WALLET_EXCEPTION_IF(!m_testnet && field_testnet, error::wallet_internal_error, "Testnet wallet can not be opened as mainnet wallet");
+ GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, nettype, uint8_t, Uint, false, static_cast<uint8_t>(m_nettype));
+ // The network type given in the program argument is inconsistent with the network type saved in the wallet
+ THROW_WALLET_EXCEPTION_IF(static_cast<uint8_t>(m_nettype) != field_nettype, error::wallet_internal_error,
+ (boost::format("%s wallet can not be opened as %s wallet")
+ % (field_nettype == 0 ? "Mainnet" : field_nettype == 1 ? "Testnet" : "Stagenet")
+ % (m_nettype == MAINNET ? "mainnet" : m_nettype == TESTNET ? "testnet" : "stagenet")).str());
}
else
{
@@ -2801,7 +2812,7 @@ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string&
bool r = store_keys(m_keys_file, password, false);
THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file);
- r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_testnet));
+ r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype));
if(!r) MERROR("String with address text not saved");
}
@@ -2845,16 +2856,9 @@ crypto::secret_key wallet2::generate(const std::string& wallet_, const epee::wip
m_multisig_signers.clear();
m_key_on_device = false;
- // -1 month for fluctuations in block time and machine date/time setup.
- // avg seconds per block
- const int seconds_per_block = DIFFICULTY_TARGET_V2;
- // ~num blocks per month
- const uint64_t blocks_per_month = 60*60*24*30/seconds_per_block;
-
- // try asking the daemon first
+ // calculate a starting refresh height
if(m_refresh_from_block_height == 0 && !recover){
- uint64_t height = estimate_blockchain_height();
- m_refresh_from_block_height = height >= blocks_per_month ? height - blocks_per_month : 0;
+ m_refresh_from_block_height = estimate_blockchain_height();
}
if (!wallet_.empty())
@@ -2862,7 +2866,7 @@ crypto::secret_key wallet2::generate(const std::string& wallet_, const epee::wip
bool r = store_keys(m_keys_file, password, false);
THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file);
- r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_testnet));
+ r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype));
if(!r) MERROR("String with address text not saved");
}
@@ -2889,20 +2893,30 @@ crypto::secret_key wallet2::generate(const std::string& wallet_, const epee::wip
std::string err;
uint64_t height = 0;
- // we get the max of approximated height and known height
+ // we get the max of approximated height and local height.
// approximated height is the least of daemon target height
// (the max of what the other daemons are claiming is their
// height) and the theoretical height based on the local
// clock. This will be wrong only if both the local clock
// is bad *and* a peer daemon claims a highest height than
// the real chain.
- // known height is the height the local daemon is currently
+ // local height is the height the local daemon is currently
// synced to, it will be lower than the real chain height if
// the daemon is currently syncing.
+ // If we use the approximate height we subtract one month as
+ // a safety margin.
height = get_approximate_blockchain_height();
uint64_t target_height = get_daemon_blockchain_target_height(err);
- if (err.empty() && target_height < height)
- height = target_height;
+ if (err.empty()) {
+ if (target_height < height)
+ height = target_height;
+ } else {
+ // if we couldn't talk to the daemon, check safety margin.
+ if (height > blocks_per_month)
+ height -= blocks_per_month;
+ else
+ height = 0;
+ }
uint64_t local_height = get_daemon_blockchain_height(err);
if (err.empty() && local_height > height)
height = local_height;
@@ -2942,7 +2956,7 @@ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string&
bool r = store_keys(m_keys_file, password, true);
THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file);
- r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_testnet));
+ r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype));
if(!r) MERROR("String with address text not saved");
}
@@ -2989,7 +3003,7 @@ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string&
bool r = store_keys(m_keys_file, password, false);
THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file);
- r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_testnet));
+ r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype));
if(!r) MERROR("String with address text not saved");
}
@@ -3030,7 +3044,7 @@ void wallet2::restore(const std::string& wallet_, const epee::wipeable_string& p
bool r = store_keys(m_keys_file, password, false);
THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file);
- r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_testnet));
+ r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype));
if(!r) MERROR("String with address text not saved");
}
cryptonote::block b;
@@ -3122,7 +3136,7 @@ std::string wallet2::make_multisig(const epee::wipeable_string &password,
bool r = store_keys(m_keys_file, password, false);
THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file);
- r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_testnet));
+ r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype));
if(!r) MERROR("String with address text not saved");
}
@@ -3222,7 +3236,7 @@ bool wallet2::finalize_multisig(const epee::wipeable_string &password, std::unor
bool r = store_keys(m_keys_file, password, false);
THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file);
- r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_testnet));
+ r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype));
if(!r) MERROR("String with address text not saved");
}
@@ -3532,7 +3546,7 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
{
THROW_WALLET_EXCEPTION_IF(true, error::file_read_error, m_keys_file);
}
- LOG_PRINT_L0("Loaded wallet keys file, with public address: " << m_account.get_public_address_str(m_testnet));
+ LOG_PRINT_L0("Loaded wallet keys file, with public address: " << m_account.get_public_address_str(m_nettype));
//keys loaded ok!
//try to load wallet file. but even if we failed, it is not big problem
@@ -3671,7 +3685,7 @@ void wallet2::trim_hashchain()
}
//----------------------------------------------------------------------------------------------------
void wallet2::check_genesis(const crypto::hash& genesis_hash) const {
- std::string what("Genesis block mismatch. You probably use wallet without testnet flag with blockchain from test network or vice versa");
+ std::string what("Genesis block mismatch. You probably use wallet without testnet (or stagenet) flag with blockchain from test (or stage) network or vice versa");
THROW_WALLET_EXCEPTION_IF(genesis_hash != m_blockchain.genesis(), error::wallet_internal_error, what);
}
@@ -3748,7 +3762,7 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas
THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file);
// save address to the new file
const std::string address_file = m_wallet_file + ".address.txt";
- r = file_io_utils::save_string_to_file(address_file, m_account.get_public_address_str(m_testnet));
+ r = file_io_utils::save_string_to_file(address_file, m_account.get_public_address_str(m_nettype));
THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_wallet_file);
// remove old wallet file
r = boost::filesystem::remove(old_file);
@@ -3767,12 +3781,24 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas
}
} else {
// save to new file
+#ifdef WIN32
+ // On Windows avoid using std::ofstream which does not work with UTF-8 filenames
+ // The price to pay is temporary higher memory consumption for string stream + binary archive
+ std::ostringstream oss;
+ binary_archive<true> oar(oss);
+ bool success = ::serialization::serialize(oar, cache_file_data);
+ if (success) {
+ success = epee::file_io_utils::save_string_to_file(new_file, oss.str());
+ }
+ THROW_WALLET_EXCEPTION_IF(!success, error::file_save_error, new_file);
+#else
std::ofstream ostr;
ostr.open(new_file, std::ios_base::binary | std::ios_base::out | std::ios_base::trunc);
binary_archive<true> oar(ostr);
bool success = ::serialization::serialize(oar, cache_file_data);
ostr.close();
THROW_WALLET_EXCEPTION_IF(!success || !ostr.good(), error::file_save_error, new_file);
+#endif
// here we have "*.new" file, we need to rename it to be without ".new"
std::error_code e = tools::replace_file(new_file, m_wallet_file);
@@ -4025,7 +4051,7 @@ bool wallet2::is_tx_spendtime_unlocked(uint64_t unlock_time, uint64_t block_heig
uint64_t current_time = static_cast<uint64_t>(time(NULL));
// XXX: this needs to be fast, so we'd need to get the starting heights
// from the daemon to be correct once voting kicks in
- uint64_t v2height = m_testnet ? 624634 : 1009827;
+ uint64_t v2height = m_nettype == TESTNET ? 624634 : m_nettype == STAGENET ? (uint64_t)-1/*TODO*/ : 1009827;
uint64_t leeway = block_height < v2height ? CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS_V1 : CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS_V2;
if(current_time + leeway >= unlock_time)
return true;
@@ -4313,7 +4339,7 @@ void wallet2::commit_tx(pending_tx& ptx)
{
cryptonote::COMMAND_RPC_SUBMIT_RAW_TX::request oreq;
cryptonote::COMMAND_RPC_SUBMIT_RAW_TX::response ores;
- oreq.address = get_account().get_public_address_str(m_testnet);
+ oreq.address = get_account().get_public_address_str(m_nettype);
oreq.view_key = string_tools::pod_to_hex(get_account().get_keys().m_view_secret_key);
oreq.tx = epee::string_tools::buff_to_hex_nodelimer(tx_to_blob(ptx.tx));
m_daemon_rpc_mutex.lock();
@@ -4523,7 +4549,7 @@ bool wallet2::sign_tx(unsigned_tx_set &exported_txs, const std::string &signed_f
std::vector<crypto::secret_key> additional_tx_keys;
rct::multisig_out msout;
bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), m_subaddresses, sd.sources, sd.splitted_dsts, sd.change_dts.addr, sd.extra, ptx.tx, sd.unlock_time, tx_key, additional_tx_keys, sd.use_rct, bulletproof, m_multisig ? &msout : NULL);
- THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sd.sources, sd.splitted_dsts, sd.unlock_time, m_testnet);
+ THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sd.sources, sd.splitted_dsts, sd.unlock_time, m_nettype);
// we don't test tx size, because we don't know the current limit, due to not having a blockchain,
// and it's a bit pointless to fail there anyway, since it'd be a (good) guess only. We sign anyway,
// and if we really go over limit, the daemon will reject when it gets submitted. Chances are it's
@@ -4896,7 +4922,7 @@ bool wallet2::sign_multisig_tx(multisig_tx_set &exported_txs, std::vector<crypto
auto sources = sd.sources;
const bool bulletproof = sd.use_rct && (ptx.tx.rct_signatures.type == rct::RCTTypeFullBulletproof || ptx.tx.rct_signatures.type == rct::RCTTypeSimpleBulletproof);
bool r = cryptonote::construct_tx_with_tx_key(m_account.get_keys(), m_subaddresses, sources, sd.splitted_dsts, ptx.change_dts.addr, sd.extra, tx, sd.unlock_time, ptx.tx_key, ptx.additional_tx_keys, sd.use_rct, bulletproof, &msout);
- THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sd.sources, sd.splitted_dsts, sd.unlock_time, m_testnet);
+ THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sd.sources, sd.splitted_dsts, sd.unlock_time, m_nettype);
THROW_WALLET_EXCEPTION_IF(get_transaction_prefix_hash (tx) != get_transaction_prefix_hash(ptx.tx),
error::wallet_internal_error, "Transaction prefix does not match data");
@@ -5305,7 +5331,7 @@ void wallet2::light_wallet_get_outs(std::vector<std::vector<tools::wallet2::get_
bool r = epee::net_utils::invoke_http_json("/get_random_outs", oreq, ores, m_http_client, rpc_timeout, "POST");
m_daemon_rpc_mutex.unlock();
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "get_random_outs");
- THROW_WALLET_EXCEPTION_IF(ores.amount_outs.empty() , error::wallet_internal_error, "No outputs recieved from light wallet node. Error: " + ores.Error);
+ THROW_WALLET_EXCEPTION_IF(ores.amount_outs.empty() , error::wallet_internal_error, "No outputs received from light wallet node. Error: " + ores.Error);
// Check if we got enough outputs for each amount
for(auto& out: ores.amount_outs) {
@@ -5529,7 +5555,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
}
}
- // sort the subsection, to ensure the daemon doesn't know wich output is ours
+ // sort the subsection, to ensure the daemon doesn't know which output is ours
std::sort(req.outputs.begin() + start, req.outputs.end(),
[](const get_outputs_out &a, const get_outputs_out &b) { return a.index < b.index; });
}
@@ -5642,7 +5668,7 @@ void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_ent
THROW_WALLET_EXCEPTION_IF(0 == dt.amount, error::zero_destination);
needed_money += dt.amount;
LOG_PRINT_L2("transfer: adding " << print_money(dt.amount) << ", for a total of " << print_money (needed_money));
- THROW_WALLET_EXCEPTION_IF(needed_money < dt.amount, error::tx_sum_overflow, dsts, fee, m_testnet);
+ THROW_WALLET_EXCEPTION_IF(needed_money < dt.amount, error::tx_sum_overflow, dsts, fee, m_nettype);
}
uint64_t found_money = 0;
@@ -5735,7 +5761,7 @@ void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_ent
LOG_PRINT_L2("constructing tx");
bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), m_subaddresses, sources, splitted_dsts, change_dts.addr, extra, tx, unlock_time, tx_key, additional_tx_keys, false, false, m_multisig ? &msout : NULL);
LOG_PRINT_L2("constructed tx, r="<<r);
- THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_testnet);
+ THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_nettype);
THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit);
std::string key_images;
@@ -5799,7 +5825,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
THROW_WALLET_EXCEPTION_IF(0 == dt.amount, error::zero_destination);
needed_money += dt.amount;
LOG_PRINT_L2("transfer: adding " << print_money(dt.amount) << ", for a total of " << print_money (needed_money));
- THROW_WALLET_EXCEPTION_IF(needed_money < dt.amount, error::tx_sum_overflow, dsts, fee, m_testnet);
+ THROW_WALLET_EXCEPTION_IF(needed_money < dt.amount, error::tx_sum_overflow, dsts, fee, m_nettype);
}
// if this is a multisig wallet, create a list of multisig signers we can use
@@ -5939,7 +5965,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
auto sources_copy = sources;
bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), m_subaddresses, sources, splitted_dsts, change_dts.addr, extra, tx, unlock_time, tx_key, additional_tx_keys, true, bulletproof, m_multisig ? &msout : NULL);
LOG_PRINT_L2("constructed tx, r="<<r);
- THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, dsts, unlock_time, m_testnet);
+ THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, dsts, unlock_time, m_nettype);
THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit);
// work out the permutation done on sources
@@ -5984,7 +6010,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
auto sources_copy_copy = sources_copy;
bool r = cryptonote::construct_tx_with_tx_key(m_account.get_keys(), m_subaddresses, sources_copy_copy, splitted_dsts, change_dts.addr, extra, ms_tx, unlock_time,tx_key, additional_tx_keys, true, bulletproof, &msout);
LOG_PRINT_L2("constructed tx, r="<<r);
- THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_testnet);
+ THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_nettype);
THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit);
THROW_WALLET_EXCEPTION_IF(cryptonote::get_transaction_prefix_hash(ms_tx) != prefix_hash, error::wallet_internal_error, "Multisig txes do not share prefix");
multisig_sigs.push_back({ms_tx.rct_signatures, multisig_signers[signer_index], new_used_L, std::unordered_set<crypto::public_key>(), msout});
@@ -6154,9 +6180,9 @@ bool wallet2::light_wallet_login(bool &new_address)
m_light_wallet_connected = false;
cryptonote::COMMAND_RPC_LOGIN::request request;
cryptonote::COMMAND_RPC_LOGIN::response response;
- request.address = get_account().get_public_address_str(m_testnet);
+ request.address = get_account().get_public_address_str(m_nettype);
request.view_key = string_tools::pod_to_hex(get_account().get_keys().m_view_secret_key);
- // Always create account if it doesnt exist.
+ // Always create account if it doesn't exist.
request.create_account = true;
m_daemon_rpc_mutex.lock();
bool connected = epee::net_utils::invoke_http_json("/login", request, response, m_http_client, rpc_timeout, "POST");
@@ -6169,7 +6195,7 @@ bool wallet2::light_wallet_login(bool &new_address)
MDEBUG("New wallet: " << response.new_address);
if(m_light_wallet_connected)
{
- // Clear old data on successfull login.
+ // Clear old data on successful login.
// m_transfers.clear();
// m_payments.clear();
// m_unconfirmed_payments.clear();
@@ -6181,7 +6207,7 @@ bool wallet2::light_wallet_import_wallet_request(cryptonote::COMMAND_RPC_IMPORT_
{
MDEBUG("Light wallet import wallet request");
cryptonote::COMMAND_RPC_IMPORT_WALLET_REQUEST::request oreq;
- oreq.address = get_account().get_public_address_str(m_testnet);
+ oreq.address = get_account().get_public_address_str(m_nettype);
oreq.view_key = string_tools::pod_to_hex(get_account().get_keys().m_view_secret_key);
m_daemon_rpc_mutex.lock();
bool r = epee::net_utils::invoke_http_json("/import_wallet_request", oreq, response, m_http_client, rpc_timeout, "POST");
@@ -6200,7 +6226,7 @@ void wallet2::light_wallet_get_unspent_outs()
cryptonote::COMMAND_RPC_GET_UNSPENT_OUTS::response ores;
oreq.amount = "0";
- oreq.address = get_account().get_public_address_str(m_testnet);
+ oreq.address = get_account().get_public_address_str(m_nettype);
oreq.view_key = string_tools::pod_to_hex(get_account().get_keys().m_view_secret_key);
// openMonero specific
oreq.dust_threshold = boost::lexical_cast<std::string>(::config::DEFAULT_DUST_THRESHOLD);
@@ -6350,7 +6376,7 @@ bool wallet2::light_wallet_get_address_info(cryptonote::COMMAND_RPC_GET_ADDRESS_
cryptonote::COMMAND_RPC_GET_ADDRESS_INFO::request request;
- request.address = get_account().get_public_address_str(m_testnet);
+ request.address = get_account().get_public_address_str(m_nettype);
request.view_key = string_tools::pod_to_hex(get_account().get_keys().m_view_secret_key);
m_daemon_rpc_mutex.lock();
bool r = epee::net_utils::invoke_http_json("/get_address_info", request, response, m_http_client, rpc_timeout, "POST");
@@ -6367,7 +6393,7 @@ void wallet2::light_wallet_get_address_txs()
cryptonote::COMMAND_RPC_GET_ADDRESS_TXS::request ireq;
cryptonote::COMMAND_RPC_GET_ADDRESS_TXS::response ires;
- ireq.address = get_account().get_public_address_str(m_testnet);
+ ireq.address = get_account().get_public_address_str(m_nettype);
ireq.view_key = string_tools::pod_to_hex(get_account().get_keys().m_view_secret_key);
m_daemon_rpc_mutex.lock();
bool r = epee::net_utils::invoke_http_json("/get_address_txs", ireq, ires, m_http_client, rpc_timeout, "POST");
@@ -6541,7 +6567,7 @@ void wallet2::light_wallet_get_address_txs()
// Calculate wallet balance
m_light_wallet_balance = ires.total_received-wallet_total_sent;
- // MyMonero doesnt send unlocked balance
+ // MyMonero doesn't send unlocked balance
if(ires.total_received_unlocked > 0)
m_light_wallet_unlocked_balance = ires.total_received_unlocked-wallet_total_sent;
else
@@ -6692,7 +6718,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
THROW_WALLET_EXCEPTION_IF(0 == dt.amount, error::zero_destination);
needed_money += dt.amount;
LOG_PRINT_L2("transfer: adding " << print_money(dt.amount) << ", for a total of " << print_money (needed_money));
- THROW_WALLET_EXCEPTION_IF(needed_money < dt.amount, error::tx_sum_overflow, dsts, 0, m_testnet);
+ THROW_WALLET_EXCEPTION_IF(needed_money < dt.amount, error::tx_sum_overflow, dsts, 0, m_nettype);
}
// throw if attempting a transaction with no money
@@ -6818,7 +6844,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
{
string s;
for (auto i: preferred_inputs) s += boost::lexical_cast<std::string>(i) + " (" + print_money(m_transfers[i].amount()) + ") ";
- LOG_PRINT_L1("Found prefered rct inputs for rct tx: " << s);
+ LOG_PRINT_L1("Found preferred rct inputs for rct tx: " << s);
// bring the list of available outputs stored by the same subaddress index to the front of the list
uint32_t index_minor = m_transfers[preferred_inputs[0]].m_subaddr_index.minor;
@@ -6920,7 +6946,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
while (!dsts.empty() && dsts[0].amount <= available_amount && estimate_tx_size(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size(), extra.size(), bulletproof) < TX_SIZE_TARGET(upper_transaction_size_limit))
{
// we can fully pay that destination
- LOG_PRINT_L2("We can fully pay " << get_account_address_as_str(m_testnet, dsts[0].is_subaddress, dsts[0].addr) <<
+ LOG_PRINT_L2("We can fully pay " << get_account_address_as_str(m_nettype, dsts[0].is_subaddress, dsts[0].addr) <<
" for " << print_money(dsts[0].amount));
tx.add(dsts[0].addr, dsts[0].is_subaddress, dsts[0].amount, original_output_index, m_merge_destinations);
available_amount -= dsts[0].amount;
@@ -6931,7 +6957,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
if (available_amount > 0 && !dsts.empty() && estimate_tx_size(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size(), extra.size(), bulletproof) < TX_SIZE_TARGET(upper_transaction_size_limit)) {
// we can partially fill that destination
- LOG_PRINT_L2("We can partially pay " << get_account_address_as_str(m_testnet, dsts[0].is_subaddress, dsts[0].addr) <<
+ LOG_PRINT_L2("We can partially pay " << get_account_address_as_str(m_nettype, dsts[0].is_subaddress, dsts[0].addr) <<
" for " << print_money(available_amount) << "/" << print_money(dsts[0].amount));
tx.add(dsts[0].addr, dsts[0].is_subaddress, available_amount, original_output_index, m_merge_destinations);
dsts[0].amount -= available_amount;
@@ -7001,7 +7027,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
if (i->amount > needed_fee)
{
uint64_t new_paid_amount = i->amount /*+ test_ptx.fee*/ - needed_fee;
- LOG_PRINT_L2("Adjusting amount paid to " << get_account_address_as_str(m_testnet, i->is_subaddress, i->addr) << " from " <<
+ LOG_PRINT_L2("Adjusting amount paid to " << get_account_address_as_str(m_nettype, i->is_subaddress, i->addr) << " from " <<
print_money(i->amount) << " to " << print_money(new_paid_amount) << " to accommodate " <<
print_money(needed_fee) << " fee");
dsts[0].amount += i->amount - new_paid_amount;
@@ -8428,16 +8454,16 @@ uint64_t wallet2::get_daemon_blockchain_target_height(string &err)
uint64_t wallet2::get_approximate_blockchain_height() const
{
// time of v2 fork
- const time_t fork_time = m_testnet ? 1448285909 : 1458748658;
+ const time_t fork_time = m_nettype == TESTNET ? 1448285909 : m_nettype == STAGENET ? (time_t)-1/*TODO*/ : 1458748658;
// v2 fork block
- const uint64_t fork_block = m_testnet ? 624634 : 1009827;
+ const uint64_t fork_block = m_nettype == TESTNET ? 624634 : m_nettype == STAGENET ? (uint64_t)-1/*TODO*/ : 1009827;
// avg seconds per block
const int seconds_per_block = DIFFICULTY_TARGET_V2;
// Calculated blockchain height
uint64_t approx_blockchain_height = fork_block + (time(NULL) - fork_time)/seconds_per_block;
// testnet got some huge rollbacks, so the estimation is way off
static const uint64_t approximate_testnet_rolled_back_blocks = 148540;
- if (m_testnet && approx_blockchain_height > approximate_testnet_rolled_back_blocks)
+ if (m_nettype == TESTNET && approx_blockchain_height > approximate_testnet_rolled_back_blocks)
approx_blockchain_height -= approximate_testnet_rolled_back_blocks;
LOG_PRINT_L2("Calculated blockchain height: " << approx_blockchain_height);
return approx_blockchain_height;
@@ -9418,7 +9444,7 @@ std::string wallet2::decrypt_with_view_secret_key(const std::string &ciphertext,
std::string wallet2::make_uri(const std::string &address, const std::string &payment_id, uint64_t amount, const std::string &tx_description, const std::string &recipient_name, std::string &error) const
{
cryptonote::address_parse_info info;
- if(!get_account_address_from_str(info, testnet(), address))
+ if(!get_account_address_from_str(info, nettype(), address))
{
error = std::string("wrong address: ") + address;
return std::string();
@@ -9482,7 +9508,7 @@ bool wallet2::parse_uri(const std::string &uri, std::string &address, std::strin
address = ptr ? remainder.substr(0, ptr-remainder.c_str()) : remainder;
cryptonote::address_parse_info info;
- if(!get_account_address_from_str(info, testnet(), address))
+ if(!get_account_address_from_str(info, nettype(), address))
{
error = std::string("URI has wrong address: ") + address;
return false;
@@ -9731,10 +9757,14 @@ std::vector<std::pair<uint64_t, uint64_t>> wallet2::estimate_backlog(uint64_t mi
}
//----------------------------------------------------------------------------------------------------
void wallet2::generate_genesis(cryptonote::block& b) const {
- if (m_testnet)
+ if (m_nettype == TESTNET)
{
cryptonote::generate_genesis_block(b, config::testnet::GENESIS_TX, config::testnet::GENESIS_NONCE);
}
+ else if (m_nettype == STAGENET)
+ {
+ cryptonote::generate_genesis_block(b, config::stagenet::GENESIS_TX, config::stagenet::GENESIS_NONCE);
+ }
else
{
cryptonote::generate_genesis_block(b, config::GENESIS_TX, config::GENESIS_NONCE);
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index 127e70a26..57a61cb9d 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -147,6 +147,7 @@ namespace tools
static const char* tr(const char* str);
static bool has_testnet_option(const boost::program_options::variables_map& vm);
+ static bool has_stagenet_option(const boost::program_options::variables_map& vm);
static void init_options(boost::program_options::options_description& desc_params);
//! Uses stdin and stdout. Returns a wallet2 if no errors.
@@ -164,7 +165,7 @@ namespace tools
static bool verify_password(const std::string& keys_file_name, const epee::wipeable_string& password, bool no_spend_key, hw::device &hwdev);
- wallet2(bool testnet = false, bool restricted = false);
+ wallet2(cryptonote::network_type nettype = cryptonote::MAINNET, bool restricted = false);
struct multisig_info
{
@@ -637,7 +638,7 @@ namespace tools
void set_refresh_type(RefreshType refresh_type) { m_refresh_type = refresh_type; }
RefreshType get_refresh_type() const { return m_refresh_type; }
- bool testnet() const { return m_testnet; }
+ cryptonote::network_type nettype() const { return m_nettype; }
bool restricted() const { return m_restricted; }
bool watch_only() const { return m_watch_only; }
bool multisig(bool *ready = NULL, uint32_t *threshold = NULL, uint32_t *total = NULL) const;
@@ -1115,7 +1116,7 @@ namespace tools
i_wallet2_callback* m_callback;
bool m_key_on_device;
- bool m_testnet;
+ cryptonote::network_type m_nettype;
bool m_restricted;
std::string seed_language; /*!< Language of the mnemonics (seed). */
bool is_old_file_format; /*!< Whether the wallet file is of an old file format */
@@ -1646,7 +1647,7 @@ namespace tools
{
THROW_WALLET_EXCEPTION_IF(0 == dt.amount, error::zero_destination);
needed_money += dt.amount;
- THROW_WALLET_EXCEPTION_IF(needed_money < dt.amount, error::tx_sum_overflow, dsts, fee, m_testnet);
+ THROW_WALLET_EXCEPTION_IF(needed_money < dt.amount, error::tx_sum_overflow, dsts, fee, m_nettype);
}
// randomly select inputs for transaction
@@ -1768,7 +1769,7 @@ namespace tools
std::vector<crypto::secret_key> additional_tx_keys;
rct::multisig_out msout;
bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), m_subaddresses, sources, splitted_dsts, change_dts.addr, extra, tx, unlock_time, tx_key, additional_tx_keys, false, false, m_multisig ? &msout : NULL);
- THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_testnet);
+ THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_nettype);
THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit);
std::string key_images;
diff --git a/src/wallet/wallet_errors.h b/src/wallet/wallet_errors.h
index 5c1c49d5d..32a0231b1 100644
--- a/src/wallet/wallet_errors.h
+++ b/src/wallet/wallet_errors.h
@@ -529,13 +529,13 @@ namespace tools
, sources_t const & sources
, destinations_t const & destinations
, uint64_t unlock_time
- , bool testnet
+ , cryptonote::network_type nettype
)
: transfer_error(std::move(loc), "transaction was not constructed")
, m_sources(sources)
, m_destinations(destinations)
, m_unlock_time(unlock_time)
- , m_testnet(testnet)
+ , m_nettype(nettype)
{
}
@@ -569,7 +569,7 @@ namespace tools
for (size_t i = 0; i < m_destinations.size(); ++i)
{
const cryptonote::tx_destination_entry& dst = m_destinations[i];
- ss << "\n " << i << ": " << cryptonote::get_account_address_as_str(m_testnet, dst.is_subaddress, dst.addr) << " " <<
+ ss << "\n " << i << ": " << cryptonote::get_account_address_as_str(m_nettype, dst.is_subaddress, dst.addr) << " " <<
cryptonote::print_money(dst.amount);
}
@@ -582,7 +582,7 @@ namespace tools
sources_t m_sources;
destinations_t m_destinations;
uint64_t m_unlock_time;
- bool m_testnet;
+ cryptonote::network_type m_nettype;
};
//----------------------------------------------------------------------------------------------------
struct tx_rejected : public transfer_error
@@ -624,12 +624,12 @@ namespace tools
std::string && loc
, const std::vector<cryptonote::tx_destination_entry>& destinations
, uint64_t fee
- , bool testnet
+ , cryptonote::network_type nettype
)
: transfer_error(std::move(loc), "transaction sum + fee exceeds " + cryptonote::print_money(std::numeric_limits<uint64_t>::max()))
, m_destinations(destinations)
, m_fee(fee)
- , m_testnet(testnet)
+ , m_nettype(nettype)
{
}
@@ -644,7 +644,7 @@ namespace tools
", destinations:";
for (const auto& dst : m_destinations)
{
- ss << '\n' << cryptonote::print_money(dst.amount) << " -> " << cryptonote::get_account_address_as_str(m_testnet, dst.is_subaddress, dst.addr);
+ ss << '\n' << cryptonote::print_money(dst.amount) << " -> " << cryptonote::get_account_address_as_str(m_nettype, dst.is_subaddress, dst.addr);
}
return ss.str();
}
@@ -652,7 +652,7 @@ namespace tools
private:
std::vector<cryptonote::tx_destination_entry> m_destinations;
uint64_t m_fee;
- bool m_testnet;
+ cryptonote::network_type m_nettype;
};
//----------------------------------------------------------------------------------------------------
struct tx_too_big : public transfer_error
diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index 6d5419521..220dbbc58 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -280,7 +280,7 @@ namespace tools
entry.destinations.push_back(wallet_rpc::transfer_destination());
wallet_rpc::transfer_destination &td = entry.destinations.back();
td.amount = d.amount;
- td.address = get_account_address_as_str(m_wallet->testnet(), d.is_subaddress, d.addr);
+ td.address = get_account_address_as_str(m_wallet->nettype(), d.is_subaddress, d.addr);
}
entry.type = "out";
@@ -584,7 +584,7 @@ namespace tools
cryptonote::address_parse_info info;
cryptonote::tx_destination_entry de;
er.message = "";
- if(!get_account_address_from_str_or_url(info, m_wallet->testnet(), it->address,
+ if(!get_account_address_from_str_or_url(info, m_wallet->nettype(), it->address,
[&er](const std::string &url, const std::vector<std::string> &addresses, bool dnssec_valid)->std::string {
if (!dnssec_valid)
{
@@ -786,7 +786,15 @@ namespace tools
try
{
- uint64_t mixin = m_wallet->adjust_mixin(req.mixin);
+ uint64_t mixin;
+ if(req.ring_size != 0)
+ {
+ mixin = m_wallet->adjust_mixin(req.ring_size - 1);
+ }
+ else
+ {
+ mixin = m_wallet->adjust_mixin(req.mixin);
+ }
uint32_t priority = m_wallet->adjust_priority(req.priority);
std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_2(dsts, mixin, req.unlock_time, priority, extra, req.account_index, req.subaddr_indices, m_trusted_daemon);
@@ -838,7 +846,15 @@ namespace tools
try
{
- uint64_t mixin = m_wallet->adjust_mixin(req.mixin);
+ uint64_t mixin;
+ if(req.ring_size != 0)
+ {
+ mixin = m_wallet->adjust_mixin(req.ring_size - 1);
+ }
+ else
+ {
+ mixin = m_wallet->adjust_mixin(req.mixin);
+ }
uint32_t priority = m_wallet->adjust_priority(req.priority);
LOG_PRINT_L2("on_transfer_split calling create_transactions_2");
std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_2(dsts, mixin, req.unlock_time, priority, extra, req.account_index, req.subaddr_indices, m_trusted_daemon);
@@ -905,7 +921,15 @@ namespace tools
try
{
- uint64_t mixin = m_wallet->adjust_mixin(req.mixin);
+ uint64_t mixin;
+ if(req.ring_size != 0)
+ {
+ mixin = m_wallet->adjust_mixin(req.ring_size - 1);
+ }
+ else
+ {
+ mixin = m_wallet->adjust_mixin(req.mixin);
+ }
uint32_t priority = m_wallet->adjust_priority(req.priority);
std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_all(req.below_amount, dsts[0].addr, dsts[0].is_subaddress, mixin, req.unlock_time, priority, extra, req.account_index, req.subaddr_indices, m_trusted_daemon);
@@ -953,7 +977,15 @@ namespace tools
try
{
- uint64_t mixin = m_wallet->adjust_mixin(req.mixin);
+ uint64_t mixin;
+ if(req.ring_size != 0)
+ {
+ mixin = m_wallet->adjust_mixin(req.ring_size - 1);
+ }
+ else
+ {
+ mixin = m_wallet->adjust_mixin(req.mixin);
+ }
uint32_t priority = m_wallet->adjust_priority(req.priority);
std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_single(ki, dsts[0].addr, dsts[0].is_subaddress, mixin, req.unlock_time, priority, extra, m_trusted_daemon);
@@ -1075,7 +1107,7 @@ namespace tools
{
cryptonote::address_parse_info info;
- if(!get_account_address_from_str(info, m_wallet->testnet(), req.integrated_address))
+ if(!get_account_address_from_str(info, m_wallet->nettype(), req.integrated_address))
{
er.code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS;
er.message = "Invalid address";
@@ -1087,7 +1119,7 @@ namespace tools
er.message = "Address is not an integrated address";
return false;
}
- res.standard_address = get_account_address_as_str(m_wallet->testnet(), info.is_subaddress, info.address);
+ res.standard_address = get_account_address_as_str(m_wallet->nettype(), info.is_subaddress, info.address);
res.payment_id = epee::string_tools::pod_to_hex(info.payment_id);
return true;
}
@@ -1385,7 +1417,7 @@ namespace tools
cryptonote::address_parse_info info;
er.message = "";
- if(!get_account_address_from_str_or_url(info, m_wallet->testnet(), req.address,
+ if(!get_account_address_from_str_or_url(info, m_wallet->nettype(), req.address,
[&er](const std::string &url, const std::vector<std::string> &addresses, bool dnssec_valid)->std::string {
if (!dnssec_valid)
{
@@ -1595,7 +1627,7 @@ namespace tools
}
cryptonote::address_parse_info info;
- if(!get_account_address_from_str(info, m_wallet->testnet(), req.address))
+ if(!get_account_address_from_str(info, m_wallet->nettype(), req.address))
{
er.code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS;
er.message = "Invalid address";
@@ -1628,7 +1660,7 @@ namespace tools
}
cryptonote::address_parse_info info;
- if(!get_account_address_from_str(info, m_wallet->testnet(), req.address))
+ if(!get_account_address_from_str(info, m_wallet->nettype(), req.address))
{
er.code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS;
er.message = "Invalid address";
@@ -1661,7 +1693,7 @@ namespace tools
}
cryptonote::address_parse_info info;
- if(!get_account_address_from_str(info, m_wallet->testnet(), req.address))
+ if(!get_account_address_from_str(info, m_wallet->nettype(), req.address))
{
er.code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS;
er.message = "Invalid address";
@@ -1768,7 +1800,7 @@ namespace tools
if (!m_wallet) return not_open(er);
cryptonote::address_parse_info info;
- if (!get_account_address_from_str(info, m_wallet->testnet(), req.address))
+ if (!get_account_address_from_str(info, m_wallet->nettype(), req.address))
{
er.code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS;
er.message = "Invalid address";
@@ -2058,7 +2090,7 @@ namespace tools
{
uint64_t idx = 0;
for (const auto &entry: ab)
- res.entries.push_back(wallet_rpc::COMMAND_RPC_GET_ADDRESS_BOOK_ENTRY::entry{idx++, get_account_address_as_str(m_wallet->testnet(), entry.m_is_subaddress, entry.m_address), epee::string_tools::pod_to_hex(entry.m_payment_id), entry.m_description});
+ res.entries.push_back(wallet_rpc::COMMAND_RPC_GET_ADDRESS_BOOK_ENTRY::entry{idx++, get_account_address_as_str(m_wallet->nettype(), entry.m_is_subaddress, entry.m_address), epee::string_tools::pod_to_hex(entry.m_payment_id), entry.m_description});
}
else
{
@@ -2071,7 +2103,7 @@ namespace tools
return false;
}
const auto &entry = ab[idx];
- res.entries.push_back(wallet_rpc::COMMAND_RPC_GET_ADDRESS_BOOK_ENTRY::entry{idx, get_account_address_as_str(m_wallet->testnet(), entry.m_is_subaddress, entry.m_address), epee::string_tools::pod_to_hex(entry.m_payment_id), entry.m_description});
+ res.entries.push_back(wallet_rpc::COMMAND_RPC_GET_ADDRESS_BOOK_ENTRY::entry{idx, get_account_address_as_str(m_wallet->nettype(), entry.m_is_subaddress, entry.m_address), epee::string_tools::pod_to_hex(entry.m_payment_id), entry.m_description});
}
}
return true;
@@ -2090,7 +2122,7 @@ namespace tools
cryptonote::address_parse_info info;
crypto::hash payment_id = crypto::null_hash;
er.message = "";
- if(!get_account_address_from_str_or_url(info, m_wallet->testnet(), req.address,
+ if(!get_account_address_from_str_or_url(info, m_wallet->nettype(), req.address,
[&er](const std::string &url, const std::vector<std::string> &addresses, bool dnssec_valid)->std::string {
if (!dnssec_valid)
{
@@ -2219,7 +2251,7 @@ namespace tools
}
cryptonote::COMMAND_RPC_START_MINING::request daemon_req = AUTO_VAL_INIT(daemon_req);
- daemon_req.miner_address = m_wallet->get_account().get_public_address_str(m_wallet->testnet());
+ daemon_req.miner_address = m_wallet->get_account().get_public_address_str(m_wallet->nettype());
daemon_req.threads_count = req.threads_count;
daemon_req.do_background_mining = req.do_background_mining;
daemon_req.ignore_battery = req.ignore_battery;
@@ -2535,7 +2567,7 @@ namespace tools
try
{
res.multisig_info = m_wallet->make_multisig(req.password, req.multisig_info, req.threshold);
- res.address = m_wallet->get_account().get_public_address_str(m_wallet->testnet());
+ res.address = m_wallet->get_account().get_public_address_str(m_wallet->nettype());
}
catch (const std::exception &e)
{
@@ -2706,7 +2738,7 @@ namespace tools
er.message = std::string("Error calling finalize_multisig: ") + e.what();
return false;
}
- res.address = m_wallet->get_account().get_public_address_str(m_wallet->testnet());
+ res.address = m_wallet->get_account().get_public_address_str(m_wallet->nettype());
return true;
}
@@ -2883,6 +2915,14 @@ int main(int argc, char** argv) {
std::unique_ptr<tools::wallet2> wal;
try
{
+ const bool testnet = tools::wallet2::has_testnet_option(*vm);
+ const bool stagenet = tools::wallet2::has_stagenet_option(*vm);
+ if (testnet && stagenet)
+ {
+ MERROR(tools::wallet_rpc_server::tr("Can't specify more than one of --testnet and --stagenet"));
+ return 1;
+ }
+
const auto wallet_file = command_line::get_arg(*vm, arg_wallet_file);
const auto from_json = command_line::get_arg(*vm, arg_from_json);
const auto wallet_dir = command_line::get_arg(*vm, arg_wallet_dir);
diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h
index e38cba5a5..370fea858 100644
--- a/src/wallet/wallet_rpc_server_commands_defs.h
+++ b/src/wallet/wallet_rpc_server_commands_defs.h
@@ -385,6 +385,7 @@ namespace wallet_rpc
std::set<uint32_t> subaddr_indices;
uint32_t priority;
uint64_t mixin;
+ uint64_t ring_size;
uint64_t unlock_time;
std::string payment_id;
bool get_tx_key;
@@ -398,6 +399,7 @@ namespace wallet_rpc
KV_SERIALIZE(subaddr_indices)
KV_SERIALIZE(priority)
KV_SERIALIZE(mixin)
+ KV_SERIALIZE_OPT(ring_size, (uint64_t)0)
KV_SERIALIZE(unlock_time)
KV_SERIALIZE(payment_id)
KV_SERIALIZE(get_tx_key)
@@ -440,6 +442,7 @@ namespace wallet_rpc
std::set<uint32_t> subaddr_indices;
uint32_t priority;
uint64_t mixin;
+ uint64_t ring_size;
uint64_t unlock_time;
std::string payment_id;
bool get_tx_keys;
@@ -453,6 +456,7 @@ namespace wallet_rpc
KV_SERIALIZE(subaddr_indices)
KV_SERIALIZE(priority)
KV_SERIALIZE(mixin)
+ KV_SERIALIZE_OPT(ring_size, (uint64_t)0)
KV_SERIALIZE(unlock_time)
KV_SERIALIZE(payment_id)
KV_SERIALIZE(get_tx_keys)
@@ -550,6 +554,7 @@ namespace wallet_rpc
std::set<uint32_t> subaddr_indices;
uint32_t priority;
uint64_t mixin;
+ uint64_t ring_size;
uint64_t unlock_time;
std::string payment_id;
bool get_tx_keys;
@@ -564,6 +569,7 @@ namespace wallet_rpc
KV_SERIALIZE(subaddr_indices)
KV_SERIALIZE(priority)
KV_SERIALIZE(mixin)
+ KV_SERIALIZE_OPT(ring_size, (uint64_t)0)
KV_SERIALIZE(unlock_time)
KV_SERIALIZE(payment_id)
KV_SERIALIZE(get_tx_keys)
@@ -612,6 +618,7 @@ namespace wallet_rpc
std::string address;
uint32_t priority;
uint64_t mixin;
+ uint64_t ring_size;
uint64_t unlock_time;
std::string payment_id;
bool get_tx_key;
@@ -624,6 +631,7 @@ namespace wallet_rpc
KV_SERIALIZE(address)
KV_SERIALIZE(priority)
KV_SERIALIZE(mixin)
+ KV_SERIALIZE_OPT(ring_size, (uint64_t)0)
KV_SERIALIZE(unlock_time)
KV_SERIALIZE(payment_id)
KV_SERIALIZE(get_tx_key)