aboutsummaryrefslogtreecommitdiff
path: root/src/wallet/wallet2.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/wallet/wallet2.cpp')
-rw-r--r--src/wallet/wallet2.cpp414
1 files changed, 256 insertions, 158 deletions
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 3bad743cf..9b2595716 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -66,6 +66,7 @@ using namespace epee;
#include "memwipe.h"
#include "common/base58.h"
#include "ringct/rctSigs.h"
+#include "device/device.hpp"
extern "C"
{
@@ -117,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};
};
@@ -158,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);
@@ -186,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;
}
@@ -229,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
@@ -328,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"));
}
@@ -382,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);
}
@@ -538,7 +543,7 @@ uint8_t get_bulletproof_fork()
return 8;
}
-crypto::hash8 get_short_payment_id(const tools::wallet2::pending_tx &ptx)
+crypto::hash8 get_short_payment_id(const tools::wallet2::pending_tx &ptx, hw::device &hwdev)
{
crypto::hash8 payment_id8 = null_hash8;
std::vector<tx_extra_field> tx_extra_fields;
@@ -553,16 +558,16 @@ crypto::hash8 get_short_payment_id(const tools::wallet2::pending_tx &ptx)
MWARNING("Encrypted payment id found, but no destinations public key, cannot decrypt");
return crypto::null_hash8;
}
- decrypt_payment_id(payment_id8, ptx.dests[0].addr.m_view_public_key, ptx.tx_key);
+ decrypt_payment_id(payment_id8, ptx.dests[0].addr.m_view_public_key, ptx.tx_key, hwdev);
}
}
return payment_id8;
}
-tools::wallet2::tx_construction_data get_construction_data_with_decrypted_short_payment_id(const tools::wallet2::pending_tx &ptx)
+tools::wallet2::tx_construction_data get_construction_data_with_decrypted_short_payment_id(const tools::wallet2::pending_tx &ptx, hw::device &hwdev)
{
tools::wallet2::tx_construction_data construction_data = ptx.construction_data;
- crypto::hash8 payment_id = get_short_payment_id(ptx);
+ crypto::hash8 payment_id = get_short_payment_id(ptx,hwdev);
if (payment_id != null_hash8)
{
// Remove encrypted
@@ -588,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),
@@ -623,7 +628,8 @@ wallet2::wallet2(bool testnet, bool restricted):
m_light_wallet_blockchain_height(0),
m_light_wallet_connected(false),
m_light_wallet_balance(0),
- m_light_wallet_unlocked_balance(0)
+ m_light_wallet_unlocked_balance(0),
+ m_key_on_device(false)
{
}
@@ -632,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{};
@@ -642,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);
}
@@ -688,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;
@@ -817,52 +829,29 @@ void wallet2::set_seed_language(const std::string &language)
//----------------------------------------------------------------------------------------------------
cryptonote::account_public_address wallet2::get_subaddress(const cryptonote::subaddress_index& index) const
{
- const cryptonote::account_keys& keys = m_account.get_keys();
- if (index.is_zero())
- return keys.m_account_address;
-
- crypto::public_key D = get_subaddress_spend_public_key(index);
-
- // C = a*D
- crypto::public_key C = rct::rct2pk(rct::scalarmultKey(rct::pk2rct(D), rct::sk2rct(keys.m_view_secret_key))); // could have defined secret_key_mult_public_key() under src/crypto
-
- // result: (C, D)
cryptonote::account_public_address address;
- address.m_view_public_key = C;
- address.m_spend_public_key = D;
+ hw::device &hwdev = m_account.get_device();
+ hwdev.get_subaddress(m_account.get_keys(), index,address);
return address;
}
//----------------------------------------------------------------------------------------------------
crypto::public_key wallet2::get_subaddress_spend_public_key(const cryptonote::subaddress_index& index) const
{
- const cryptonote::account_keys& keys = m_account.get_keys();
- if (index.is_zero())
- return keys.m_account_address.m_spend_public_key;
-
- // m = Hs(a || index_major || index_minor)
- crypto::secret_key m = cryptonote::get_subaddress_secret_key(keys.m_view_secret_key, index);
-
- // M = m*G
- crypto::public_key M;
- crypto::secret_key_to_public_key(m, M);
-
- // D = B + M
- rct::key D_rct;
- rct::addKeys(D_rct, rct::pk2rct(keys.m_account_address.m_spend_public_key), rct::pk2rct(M)); // could have defined add_public_key() under src/crypto
- crypto::public_key D = rct::rct2pk(D_rct);
-
+ crypto::public_key D ;
+ hw::device &hwdev = m_account.get_device();
+ hwdev.get_subaddress_spend_public_key(m_account.get_keys(), index, D);
return D;
}
//----------------------------------------------------------------------------------------------------
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)
@@ -882,6 +871,7 @@ void wallet2::add_subaddress(uint32_t index_major, const std::string& label)
//----------------------------------------------------------------------------------------------------
void wallet2::expand_subaddresses(const cryptonote::subaddress_index& index)
{
+ hw::device &hwdev = m_account.get_device();
if (m_subaddress_labels.size() <= index.major)
{
// add new accounts
@@ -889,7 +879,7 @@ void wallet2::expand_subaddresses(const cryptonote::subaddress_index& index)
for (index2.major = m_subaddress_labels.size(); index2.major < index.major + m_subaddress_lookahead_major; ++index2.major)
{
const uint32_t end = (index2.major == index.major ? index.minor : 0) + m_subaddress_lookahead_minor;
- const std::vector<crypto::public_key> pkeys = cryptonote::get_subaddress_spend_public_keys(m_account.get_keys(), index2.major, 0, end);
+ const std::vector<crypto::public_key> pkeys = cryptonote::get_subaddress_spend_public_keys(m_account.get_keys(), index2.major, 0, end, hwdev);
for (index2.minor = 0; index2.minor < end; ++index2.minor)
{
const crypto::public_key &D = pkeys[index2.minor];
@@ -905,7 +895,7 @@ void wallet2::expand_subaddresses(const cryptonote::subaddress_index& index)
const uint32_t end = index.minor + m_subaddress_lookahead_minor;
const uint32_t begin = m_subaddress_labels[index.major].size();
cryptonote::subaddress_index index2 = {index.major, begin};
- const std::vector<crypto::public_key> pkeys = cryptonote::get_subaddress_spend_public_keys(m_account.get_keys(), index2.major, index2.minor, end);
+ const std::vector<crypto::public_key> pkeys = cryptonote::get_subaddress_spend_public_keys(m_account.get_keys(), index2.major, index2.minor, end, hwdev);
for (; index2.minor < end; ++index2.minor)
{
const crypto::public_key &D = pkeys[index2.minor - begin];
@@ -970,7 +960,7 @@ void wallet2::check_acc_out_precomp(const tx_out &o, const crypto::key_derivatio
LOG_ERROR("wrong type id in transaction out");
return;
}
- tx_scan_info.received = is_out_to_acc_precomp(m_subaddresses, boost::get<txout_to_key>(o.target).key, derivation, additional_derivations, i);
+ tx_scan_info.received = is_out_to_acc_precomp(m_subaddresses, boost::get<txout_to_key>(o.target).key, derivation, additional_derivations, i, m_account.get_device());
if(tx_scan_info.received)
{
tx_scan_info.money_transfered = o.amount; // may be 0 for ringct outputs
@@ -982,20 +972,20 @@ void wallet2::check_acc_out_precomp(const tx_out &o, const crypto::key_derivatio
tx_scan_info.error = false;
}
//----------------------------------------------------------------------------------------------------
-static uint64_t decodeRct(const rct::rctSig & rv, const crypto::key_derivation &derivation, unsigned int i, rct::key & mask)
+static uint64_t decodeRct(const rct::rctSig & rv, const crypto::key_derivation &derivation, unsigned int i, rct::key & mask, hw::device &hwdev)
{
crypto::secret_key scalar1;
- crypto::derivation_to_scalar(derivation, i, scalar1);
+ crypto::derivation_to_scalar(derivation, i, scalar1, hwdev);
try
{
switch (rv.type)
{
case rct::RCTTypeSimple:
case rct::RCTTypeSimpleBulletproof:
- return rct::decodeRctSimple(rv, rct::sk2rct(scalar1), i, mask);
+ return rct::decodeRctSimple(rv, rct::sk2rct(scalar1), i, mask, hwdev);
case rct::RCTTypeFull:
case rct::RCTTypeFullBulletproof:
- return rct::decodeRct(rv, rct::sk2rct(scalar1), i, mask);
+ return rct::decodeRct(rv, rct::sk2rct(scalar1), i, mask, hwdev);
default:
LOG_ERROR("Unsupported rct type: " << rv.type);
return 0;
@@ -1019,7 +1009,7 @@ void wallet2::scan_output(const cryptonote::transaction &tx, const crypto::publi
}
else
{
- bool r = cryptonote::generate_key_image_helper_precomp(m_account.get_keys(), boost::get<cryptonote::txout_to_key>(tx.vout[i].target).key, tx_scan_info.received->derivation, i, tx_scan_info.received->index, tx_scan_info.in_ephemeral, tx_scan_info.ki);
+ bool r = cryptonote::generate_key_image_helper_precomp(m_account.get_keys(), boost::get<cryptonote::txout_to_key>(tx.vout[i].target).key, tx_scan_info.received->derivation, i, tx_scan_info.received->index, tx_scan_info.in_ephemeral, tx_scan_info.ki, m_account.get_device());
THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key image");
THROW_WALLET_EXCEPTION_IF(tx_scan_info.in_ephemeral.pub != boost::get<cryptonote::txout_to_key>(tx.vout[i].target).key,
error::wallet_internal_error, "key_image generated ephemeral public key not matched with output_key");
@@ -1028,7 +1018,7 @@ void wallet2::scan_output(const cryptonote::transaction &tx, const crypto::publi
outs.push_back(i);
if (tx_scan_info.money_transfered == 0)
{
- tx_scan_info.money_transfered = tools::decodeRct(tx.rct_signatures, tx_scan_info.received->derivation, i, tx_scan_info.mask);
+ tx_scan_info.money_transfered = tools::decodeRct(tx.rct_signatures, tx_scan_info.received->derivation, i, tx_scan_info.mask, m_account.get_device());
}
tx_money_got_in_outs[tx_scan_info.received->index] += tx_scan_info.money_transfered;
tx_scan_info.amount = tx_scan_info.money_transfered;
@@ -1076,8 +1066,9 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
tools::threadpool& tpool = tools::threadpool::getInstance();
tools::threadpool::waiter waiter;
const cryptonote::account_keys& keys = m_account.get_keys();
+ hw::device &hwdev = m_account.get_device();
crypto::key_derivation derivation;
- if (!generate_key_derivation(tx_pub_key, keys.m_view_secret_key, derivation))
+ if (!generate_key_derivation(tx_pub_key, keys.m_view_secret_key, derivation, hwdev))
{
MWARNING("Failed to generate key derivation from tx pubkey, skipping");
static_assert(sizeof(derivation) == sizeof(rct::key), "Mismatched sizes of key_derivation and rct::key");
@@ -1090,7 +1081,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
for (size_t i = 0; i < additional_tx_pub_keys.size(); ++i)
{
additional_derivations.push_back({});
- if (!generate_key_derivation(additional_tx_pub_keys[i], keys.m_view_secret_key, additional_derivations.back()))
+ if (!generate_key_derivation(additional_tx_pub_keys[i], keys.m_view_secret_key, additional_derivations.back(),hwdev))
{
MWARNING("Failed to generate key derivation from tx pubkey, skipping");
additional_derivations.pop_back();
@@ -1382,7 +1373,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
LOG_PRINT_L2("Found encrypted payment ID: " << payment_id8);
if (tx_pub_key != null_pkey)
{
- if (!decrypt_payment_id(payment_id8, tx_pub_key, m_account.get_keys().m_view_secret_key))
+ if (!decrypt_payment_id(payment_id8, tx_pub_key, m_account.get_keys().m_view_secret_key, m_account.get_device()))
{
LOG_PRINT_L0("Failed to decrypt payment ID: " << payment_id8);
}
@@ -2385,6 +2376,10 @@ bool wallet2::store_keys(const std::string& keys_file_name, const epee::wipeable
}
rapidjson::Value value2(rapidjson::kNumberType);
+
+ value2.SetInt(m_key_on_device?1:0);
+ json.AddMember("key_on_device", value2, json.GetAllocator());
+
value2.SetInt(watch_only ? 1 :0); // WTF ? JSON has different true and false types, and not boolean ??
json.AddMember("watch_only", value2, json.GetAllocator());
@@ -2456,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;
@@ -2482,16 +2477,6 @@ bool wallet2::store_keys(const std::string& keys_file_name, const epee::wipeable
return true;
}
//----------------------------------------------------------------------------------------------------
-namespace
-{
- bool verify_keys(const crypto::secret_key& sec, const crypto::public_key& expected_pub)
- {
- crypto::public_key pub;
- bool r = crypto::secret_key_to_public_key(sec, pub);
- return r && expected_pub == pub;
- }
-}
-
/*!
* \brief Load wallet information from wallet file.
* \param keys_file_name Name of wallet file
@@ -2539,6 +2524,7 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_
m_confirm_backlog_threshold = 0;
m_confirm_export_overwrite = true;
m_auto_low_priority = true;
+ m_key_on_device = false;
}
else if(json.IsObject())
{
@@ -2555,6 +2541,12 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_
const char *field_key_data = json["key_data"].GetString();
account_data = std::string(field_key_data, field_key_data + json["key_data"].GetStringLength());
+ if (json.HasMember("key_on_device"))
+ {
+ GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, key_on_device, int, Int, false, false);
+ m_key_on_device = field_key_on_device;
+ }
+
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, seed_language, std::string, String, false, std::string());
if (field_seed_language_found)
{
@@ -2642,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
{
@@ -2654,11 +2647,20 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_
return false;
}
- const cryptonote::account_keys& keys = m_account.get_keys();
r = epee::serialization::load_t_from_binary(m_account, account_data);
- r = r && verify_keys(keys.m_view_secret_key, keys.m_account_address.m_view_public_key);
+ if (r && m_key_on_device) {
+ LOG_PRINT_L0("Account on device. Initing device...");
+ hw::device &hwdev = hw::get_device("Ledger");
+ hwdev.init();
+ hwdev.connect();
+ m_account.set_device(hwdev);
+ LOG_PRINT_L0("Device inited...");
+ }
+ const cryptonote::account_keys& keys = m_account.get_keys();
+ hw::device &hwdev = m_account.get_device();
+ r = r && hwdev.verify_keys(keys.m_view_secret_key, keys.m_account_address.m_view_public_key);
if(!m_watch_only && !m_multisig)
- r = r && verify_keys(keys.m_spend_secret_key, keys.m_account_address.m_spend_public_key);
+ r = r && hwdev.verify_keys(keys.m_spend_secret_key, keys.m_account_address.m_spend_public_key);
THROW_WALLET_EXCEPTION_IF(!r, error::invalid_password);
return true;
}
@@ -2675,7 +2677,7 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_
*/
bool wallet2::verify_password(const epee::wipeable_string& password) const
{
- return verify_password(m_keys_file, password, m_watch_only || m_multisig);
+ return verify_password(m_keys_file, password, m_watch_only || m_multisig, m_account.get_device());
}
/*!
@@ -2690,7 +2692,7 @@ bool wallet2::verify_password(const epee::wipeable_string& password) const
* can be used prior to rewriting wallet keys file, to ensure user has entered the correct password
*
*/
-bool wallet2::verify_password(const std::string& keys_file_name, const epee::wipeable_string& password, bool no_spend_key)
+bool wallet2::verify_password(const std::string& keys_file_name, const epee::wipeable_string& password, bool no_spend_key, hw::device &hwdev)
{
rapidjson::Document json;
wallet2::keys_file_data keys_file_data;
@@ -2725,9 +2727,9 @@ bool wallet2::verify_password(const std::string& keys_file_name, const epee::wip
r = epee::serialization::load_t_from_binary(account_data_check, account_data);
const cryptonote::account_keys& keys = account_data_check.get_keys();
- r = r && verify_keys(keys.m_view_secret_key, keys.m_account_address.m_view_public_key);
+ r = r && hwdev.verify_keys(keys.m_view_secret_key, keys.m_account_address.m_view_public_key);
if(!no_spend_key)
- r = r && verify_keys(keys.m_spend_secret_key, keys.m_account_address.m_spend_public_key);
+ r = r && hwdev.verify_keys(keys.m_spend_secret_key, keys.m_account_address.m_spend_public_key);
return r;
}
@@ -2803,13 +2805,14 @@ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string&
m_multisig = true;
m_multisig_threshold = threshold;
m_multisig_signers = multisig_signers;
+ m_key_on_device = false;
if (!wallet_.empty())
{
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");
}
@@ -2851,17 +2854,11 @@ crypto::secret_key wallet2::generate(const std::string& wallet_, const epee::wip
m_multisig = false;
m_multisig_threshold = 0;
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())
@@ -2869,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");
}
@@ -2896,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,13 +2949,14 @@ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string&
m_multisig = false;
m_multisig_threshold = 0;
m_multisig_signers.clear();
+ m_key_on_device = false;
if (!wallet_.empty())
{
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");
}
@@ -2988,13 +2996,14 @@ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string&
m_multisig = false;
m_multisig_threshold = 0;
m_multisig_signers.clear();
+ m_key_on_device = false;
if (!wallet_.empty())
{
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");
}
@@ -3007,6 +3016,46 @@ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string&
store();
}
+/*!
+* \brief Creates a wallet from a device
+* \param wallet_ Name of wallet file
+* \param password Password of wallet file
+* \param device_name device string address
+*/
+void wallet2::restore(const std::string& wallet_, const epee::wipeable_string& password, const std::string &device_name)
+{
+ clear();
+ prepare_file_names(wallet_);
+
+ boost::system::error_code ignored_ec;
+ if (!wallet_.empty()) {
+ THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_wallet_file, ignored_ec), error::file_exists, m_wallet_file);
+ THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_keys_file, ignored_ec), error::file_exists, m_keys_file);
+ }
+ m_key_on_device = true;
+ m_account.create_from_device(device_name);
+ m_account_public_address = m_account.get_keys().m_account_address;
+ m_watch_only = false;
+ m_multisig = false;
+ m_multisig_threshold = 0;
+ m_multisig_signers.clear();
+
+ if (!wallet_.empty()) {
+ 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_nettype));
+ if(!r) MERROR("String with address text not saved");
+ }
+ cryptonote::block b;
+ generate_genesis(b);
+ m_blockchain.push_back(get_block_hash(b));
+ add_subaddress_account(tr("Primary account"));
+ if (!wallet_.empty()) {
+ store();
+ }
+}
+
std::string wallet2::make_multisig(const epee::wipeable_string &password,
const std::vector<crypto::secret_key> &view_keys,
const std::vector<crypto::public_key> &spend_keys,
@@ -3070,6 +3119,8 @@ std::string wallet2::make_multisig(const epee::wipeable_string &password,
m_watch_only = false;
m_multisig = true;
m_multisig_threshold = threshold;
+ m_key_on_device = false;
+
if (threshold == spend_keys.size() + 1)
{
m_multisig_signers = spend_keys;
@@ -3085,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");
}
@@ -3185,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");
}
@@ -3478,15 +3529,8 @@ bool wallet2::check_connection(uint32_t *version, uint32_t timeout)
//----------------------------------------------------------------------------------------------------
bool wallet2::generate_chacha_key_from_secret_keys(crypto::chacha_key &key) const
{
- const account_keys &keys = m_account.get_keys();
- const crypto::secret_key &view_key = keys.m_view_secret_key;
- const crypto::secret_key &spend_key = keys.m_spend_secret_key;
- tools::scrubbed_arr<char, sizeof(view_key) + sizeof(spend_key) + 1> data;
- memcpy(data.data(), &view_key, sizeof(view_key));
- memcpy(data.data() + sizeof(view_key), &spend_key, sizeof(spend_key));
- data[sizeof(data) - 1] = CHACHA8_KEY_TAIL;
- crypto::generate_chacha_key(data.data(), sizeof(data), key);
- return true;
+ hw::device &hwdev = m_account.get_device();
+ return hwdev.generate_chacha_key(m_account.get_keys(), key);
}
//----------------------------------------------------------------------------------------------------
void wallet2::load(const std::string& wallet_, const epee::wipeable_string& password)
@@ -3502,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
@@ -3641,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);
}
@@ -3718,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);
@@ -3995,7 +4039,7 @@ bool wallet2::is_tx_spendtime_unlocked(uint64_t unlock_time, uint64_t block_heig
uint64_t current_time = static_cast<uint64_t>(time(NULL));
// XXX: this needs to be fast, so we'd need to get the starting heights
// from the daemon to be correct once voting kicks in
- uint64_t v2height = m_testnet ? 624634 : 1009827;
+ uint64_t v2height = m_nettype == TESTNET ? 624634 : m_nettype == STAGENET ? (uint64_t)-1/*TODO*/ : 1009827;
uint64_t leeway = block_height < v2height ? CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS_V1 : CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS_V2;
if(current_time + leeway >= unlock_time)
return true;
@@ -4260,7 +4304,7 @@ crypto::hash wallet2::get_payment_id(const pending_tx &ptx) const
MWARNING("Encrypted payment id found, but no destinations public key, cannot decrypt");
return crypto::null_hash;
}
- if (decrypt_payment_id(payment_id8, ptx.dests[0].addr.m_view_public_key, ptx.tx_key))
+ if (decrypt_payment_id(payment_id8, ptx.dests[0].addr.m_view_public_key, ptx.tx_key, m_account.get_device()))
{
memcpy(payment_id.data, payment_id8.data, 8);
}
@@ -4283,7 +4327,7 @@ void wallet2::commit_tx(pending_tx& ptx)
{
cryptonote::COMMAND_RPC_SUBMIT_RAW_TX::request oreq;
cryptonote::COMMAND_RPC_SUBMIT_RAW_TX::response ores;
- oreq.address = get_account().get_public_address_str(m_testnet);
+ oreq.address = get_account().get_public_address_str(m_nettype);
oreq.view_key = string_tools::pod_to_hex(get_account().get_keys().m_view_secret_key);
oreq.tx = epee::string_tools::buff_to_hex_nodelimer(tx_to_blob(ptx.tx));
m_daemon_rpc_mutex.lock();
@@ -4369,7 +4413,7 @@ bool wallet2::save_tx(const std::vector<pending_tx>& ptx_vector, const std::stri
// Short payment id is encrypted with tx_key.
// Since sign_tx() generates new tx_keys and encrypts the payment id, we need to save the decrypted payment ID
// Save tx construction_data to unsigned_tx_set
- txs.txes.push_back(get_construction_data_with_decrypted_short_payment_id(tx));
+ txs.txes.push_back(get_construction_data_with_decrypted_short_payment_id(tx, m_account.get_device()));
}
txs.transfers = m_transfers;
@@ -4493,7 +4537,7 @@ bool wallet2::sign_tx(unsigned_tx_set &exported_txs, const std::string &signed_f
std::vector<crypto::secret_key> additional_tx_keys;
rct::multisig_out msout;
bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), m_subaddresses, sd.sources, sd.splitted_dsts, sd.change_dts.addr, sd.extra, ptx.tx, sd.unlock_time, tx_key, additional_tx_keys, sd.use_rct, bulletproof, m_multisig ? &msout : NULL);
- THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sd.sources, sd.splitted_dsts, sd.unlock_time, m_testnet);
+ THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sd.sources, sd.splitted_dsts, sd.unlock_time, m_nettype);
// we don't test tx size, because we don't know the current limit, due to not having a blockchain,
// and it's a bit pointless to fail there anyway, since it'd be a (good) guess only. We sign anyway,
// and if we really go over limit, the daemon will reject when it gets submitted. Chances are it's
@@ -4696,7 +4740,7 @@ std::string wallet2::save_multisig_tx(multisig_tx_set txs)
for (auto &ptx: txs.m_ptx)
{
// Get decrypted payment id from pending_tx
- ptx.construction_data = get_construction_data_with_decrypted_short_payment_id(ptx);
+ ptx.construction_data = get_construction_data_with_decrypted_short_payment_id(ptx, m_account.get_device());
}
// save as binary
@@ -4866,7 +4910,7 @@ bool wallet2::sign_multisig_tx(multisig_tx_set &exported_txs, std::vector<crypto
auto sources = sd.sources;
const bool bulletproof = sd.use_rct && (ptx.tx.rct_signatures.type == rct::RCTTypeFullBulletproof || ptx.tx.rct_signatures.type == rct::RCTTypeSimpleBulletproof);
bool r = cryptonote::construct_tx_with_tx_key(m_account.get_keys(), m_subaddresses, sources, sd.splitted_dsts, ptx.change_dts.addr, sd.extra, tx, sd.unlock_time, ptx.tx_key, ptx.additional_tx_keys, sd.use_rct, bulletproof, &msout);
- THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sd.sources, sd.splitted_dsts, sd.unlock_time, m_testnet);
+ THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sd.sources, sd.splitted_dsts, sd.unlock_time, m_nettype);
THROW_WALLET_EXCEPTION_IF(get_transaction_prefix_hash (tx) != get_transaction_prefix_hash(ptx.tx),
error::wallet_internal_error, "Transaction prefix does not match data");
@@ -5275,7 +5319,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) {
@@ -5499,7 +5543,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; });
}
@@ -5612,7 +5656,7 @@ void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_ent
THROW_WALLET_EXCEPTION_IF(0 == dt.amount, error::zero_destination);
needed_money += dt.amount;
LOG_PRINT_L2("transfer: adding " << print_money(dt.amount) << ", for a total of " << print_money (needed_money));
- THROW_WALLET_EXCEPTION_IF(needed_money < dt.amount, error::tx_sum_overflow, dsts, fee, m_testnet);
+ THROW_WALLET_EXCEPTION_IF(needed_money < dt.amount, error::tx_sum_overflow, dsts, fee, m_nettype);
}
uint64_t found_money = 0;
@@ -5705,7 +5749,7 @@ void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_ent
LOG_PRINT_L2("constructing tx");
bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), m_subaddresses, sources, splitted_dsts, change_dts.addr, extra, tx, unlock_time, tx_key, additional_tx_keys, false, false, m_multisig ? &msout : NULL);
LOG_PRINT_L2("constructed tx, r="<<r);
- THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_testnet);
+ THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_nettype);
THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit);
std::string key_images;
@@ -5769,7 +5813,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
THROW_WALLET_EXCEPTION_IF(0 == dt.amount, error::zero_destination);
needed_money += dt.amount;
LOG_PRINT_L2("transfer: adding " << print_money(dt.amount) << ", for a total of " << print_money (needed_money));
- THROW_WALLET_EXCEPTION_IF(needed_money < dt.amount, error::tx_sum_overflow, dsts, fee, m_testnet);
+ THROW_WALLET_EXCEPTION_IF(needed_money < dt.amount, error::tx_sum_overflow, dsts, fee, m_nettype);
}
// if this is a multisig wallet, create a list of multisig signers we can use
@@ -5909,7 +5953,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
auto sources_copy = sources;
bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), m_subaddresses, sources, splitted_dsts, change_dts.addr, extra, tx, unlock_time, tx_key, additional_tx_keys, true, bulletproof, m_multisig ? &msout : NULL);
LOG_PRINT_L2("constructed tx, r="<<r);
- THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, dsts, unlock_time, m_testnet);
+ THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, dsts, unlock_time, m_nettype);
THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit);
// work out the permutation done on sources
@@ -5954,7 +5998,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
auto sources_copy_copy = sources_copy;
bool r = cryptonote::construct_tx_with_tx_key(m_account.get_keys(), m_subaddresses, sources_copy_copy, splitted_dsts, change_dts.addr, extra, ms_tx, unlock_time,tx_key, additional_tx_keys, true, bulletproof, &msout);
LOG_PRINT_L2("constructed tx, r="<<r);
- THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_testnet);
+ THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_nettype);
THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit);
THROW_WALLET_EXCEPTION_IF(cryptonote::get_transaction_prefix_hash(ms_tx) != prefix_hash, error::wallet_internal_error, "Multisig txes do not share prefix");
multisig_sigs.push_back({ms_tx.rct_signatures, multisig_signers[signer_index], new_used_L, std::unordered_set<crypto::public_key>(), msout});
@@ -6124,9 +6168,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");
@@ -6139,7 +6183,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();
@@ -6151,7 +6195,7 @@ bool wallet2::light_wallet_import_wallet_request(cryptonote::COMMAND_RPC_IMPORT_
{
MDEBUG("Light wallet import wallet request");
cryptonote::COMMAND_RPC_IMPORT_WALLET_REQUEST::request oreq;
- oreq.address = get_account().get_public_address_str(m_testnet);
+ oreq.address = get_account().get_public_address_str(m_nettype);
oreq.view_key = string_tools::pod_to_hex(get_account().get_keys().m_view_secret_key);
m_daemon_rpc_mutex.lock();
bool r = epee::net_utils::invoke_http_json("/import_wallet_request", oreq, response, m_http_client, rpc_timeout, "POST");
@@ -6170,7 +6214,7 @@ void wallet2::light_wallet_get_unspent_outs()
cryptonote::COMMAND_RPC_GET_UNSPENT_OUTS::response ores;
oreq.amount = "0";
- oreq.address = get_account().get_public_address_str(m_testnet);
+ oreq.address = get_account().get_public_address_str(m_nettype);
oreq.view_key = string_tools::pod_to_hex(get_account().get_keys().m_view_secret_key);
// openMonero specific
oreq.dust_threshold = boost::lexical_cast<std::string>(::config::DEFAULT_DUST_THRESHOLD);
@@ -6320,7 +6364,7 @@ bool wallet2::light_wallet_get_address_info(cryptonote::COMMAND_RPC_GET_ADDRESS_
cryptonote::COMMAND_RPC_GET_ADDRESS_INFO::request request;
- request.address = get_account().get_public_address_str(m_testnet);
+ request.address = get_account().get_public_address_str(m_nettype);
request.view_key = string_tools::pod_to_hex(get_account().get_keys().m_view_secret_key);
m_daemon_rpc_mutex.lock();
bool r = epee::net_utils::invoke_http_json("/get_address_info", request, response, m_http_client, rpc_timeout, "POST");
@@ -6337,7 +6381,7 @@ void wallet2::light_wallet_get_address_txs()
cryptonote::COMMAND_RPC_GET_ADDRESS_TXS::request ireq;
cryptonote::COMMAND_RPC_GET_ADDRESS_TXS::response ires;
- ireq.address = get_account().get_public_address_str(m_testnet);
+ ireq.address = get_account().get_public_address_str(m_nettype);
ireq.view_key = string_tools::pod_to_hex(get_account().get_keys().m_view_secret_key);
m_daemon_rpc_mutex.lock();
bool r = epee::net_utils::invoke_http_json("/get_address_txs", ireq, ires, m_http_client, rpc_timeout, "POST");
@@ -6511,7 +6555,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
@@ -6662,7 +6706,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
THROW_WALLET_EXCEPTION_IF(0 == dt.amount, error::zero_destination);
needed_money += dt.amount;
LOG_PRINT_L2("transfer: adding " << print_money(dt.amount) << ", for a total of " << print_money (needed_money));
- THROW_WALLET_EXCEPTION_IF(needed_money < dt.amount, error::tx_sum_overflow, dsts, 0, m_testnet);
+ THROW_WALLET_EXCEPTION_IF(needed_money < dt.amount, error::tx_sum_overflow, dsts, 0, m_nettype);
}
// throw if attempting a transaction with no money
@@ -6788,7 +6832,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;
@@ -6819,6 +6863,8 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
unsigned int original_output_index = 0;
std::vector<size_t>* unused_transfers_indices = &unused_transfers_indices_per_subaddr[0].second;
std::vector<size_t>* unused_dust_indices = &unused_dust_indices_per_subaddr[0].second;
+ hw::device &hwdev = m_account.get_device();
+ hwdev.set_signature_mode(hw::device::SIGNATURE_FAKE);
while ((!dsts.empty() && dsts[0].amount > 0) || adding_fee || !preferred_inputs.empty() || should_pick_a_second_output(use_rct, txes.back().selected_transfers.size(), *unused_transfers_indices, *unused_dust_indices)) {
TX &tx = txes.back();
@@ -6888,7 +6934,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
while (!dsts.empty() && dsts[0].amount <= available_amount && estimate_tx_size(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size(), extra.size(), bulletproof) < TX_SIZE_TARGET(upper_transaction_size_limit))
{
// we can fully pay that destination
- LOG_PRINT_L2("We can fully pay " << get_account_address_as_str(m_testnet, dsts[0].is_subaddress, dsts[0].addr) <<
+ LOG_PRINT_L2("We can fully pay " << get_account_address_as_str(m_nettype, dsts[0].is_subaddress, dsts[0].addr) <<
" for " << print_money(dsts[0].amount));
tx.add(dsts[0].addr, dsts[0].is_subaddress, dsts[0].amount, original_output_index, m_merge_destinations);
available_amount -= dsts[0].amount;
@@ -6899,7 +6945,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
if (available_amount > 0 && !dsts.empty() && estimate_tx_size(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size(), extra.size(), bulletproof) < TX_SIZE_TARGET(upper_transaction_size_limit)) {
// we can partially fill that destination
- LOG_PRINT_L2("We can partially pay " << get_account_address_as_str(m_testnet, dsts[0].is_subaddress, dsts[0].addr) <<
+ LOG_PRINT_L2("We can partially pay " << get_account_address_as_str(m_nettype, dsts[0].is_subaddress, dsts[0].addr) <<
" for " << print_money(available_amount) << "/" << print_money(dsts[0].amount));
tx.add(dsts[0].addr, dsts[0].is_subaddress, available_amount, original_output_index, m_merge_destinations);
dsts[0].amount -= available_amount;
@@ -6969,7 +7015,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
if (i->amount > needed_fee)
{
uint64_t new_paid_amount = i->amount /*+ test_ptx.fee*/ - needed_fee;
- LOG_PRINT_L2("Adjusting amount paid to " << get_account_address_as_str(m_testnet, i->is_subaddress, i->addr) << " from " <<
+ LOG_PRINT_L2("Adjusting amount paid to " << get_account_address_as_str(m_nettype, i->is_subaddress, i->addr) << " from " <<
print_money(i->amount) << " to " << print_money(new_paid_amount) << " to accommodate " <<
print_money(needed_fee) << " fee");
dsts[0].amount += i->amount - new_paid_amount;
@@ -7004,6 +7050,37 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
LOG_PRINT_L2("Made a final " << get_size_string(txBlob) << " tx, with " << print_money(test_ptx.fee) <<
" fee and " << print_money(test_ptx.change_dts.amount) << " change");
+ if ((!dsts.empty()) ||
+ (dsts.empty() && !(adding_fee || !preferred_inputs.empty() || should_pick_a_second_output(use_rct, txes.back().selected_transfers.size(), *unused_transfers_indices, *unused_dust_indices)) )
+ ) {
+ hwdev.set_signature_mode(hw::device::SIGNATURE_REAL);
+ if (use_rct) {
+ transfer_selected_rct(tx.dsts, /* NOMOD std::vector<cryptonote::tx_destination_entry> dsts,*/
+ tx.selected_transfers, /* const std::list<size_t> selected_transfers */
+ fake_outs_count, /* CONST size_t fake_outputs_count, */
+ outs, /* MOD std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs, */
+ unlock_time, /* CONST uint64_t unlock_time, */
+ needed_fee, /* CONST uint64_t fee, */
+ extra, /* const std::vector<uint8_t>& extra, */
+ test_tx, /* OUT cryptonote::transaction& tx, */
+ test_ptx, /* OUT cryptonote::transaction& tx, */
+ bulletproof);
+ } else {
+ transfer_selected(tx.dsts,
+ tx.selected_transfers,
+ fake_outs_count,
+ outs,
+ unlock_time,
+ needed_fee,
+ extra,
+ detail::digit_split_strategy,
+ tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD),
+ test_tx,
+ test_ptx);
+ }
+ hwdev.set_signature_mode(hw::device::SIGNATURE_FAKE);
+ }
+
tx.tx = test_tx;
tx.ptx = test_ptx;
tx.bytes = txBlob.size();
@@ -7172,6 +7249,8 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
needed_fee = 0;
// while we have something to send
+ hw::device &hwdev = m_account.get_device();
+ hwdev.set_signature_mode(hw::device::SIGNATURE_FAKE);
while (!unused_dust_indices.empty() || !unused_transfers_indices.empty()) {
TX &tx = txes.back();
@@ -7237,6 +7316,18 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
" fee and " << print_money(test_ptx.change_dts.amount) << " change");
} while (needed_fee > test_ptx.fee);
+ if (!unused_transfers_indices.empty() || !unused_dust_indices.empty()) {
+ hwdev.set_signature_mode(hw::device::SIGNATURE_REAL);
+ if (use_rct) {
+ transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra,
+ test_tx, test_ptx, bulletproof);
+ } else {
+ transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra,
+ detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx);
+ }
+ hwdev.set_signature_mode(hw::device::SIGNATURE_FAKE);
+ }
+
LOG_PRINT_L2("Made a final " << get_size_string(txBlob) << " tx, with " << print_money(test_ptx.fee) <<
" fee and " << print_money(test_ptx.change_dts.amount) << " change");
@@ -7526,7 +7617,7 @@ std::string wallet2::get_spend_proof(const crypto::hash &txid, const std::string
const std::vector<crypto::public_key> in_additionakl_tx_pub_keys = get_additional_tx_pub_keys_from_extra(in_td.m_tx);
keypair in_ephemeral;
crypto::key_image in_img;
- THROW_WALLET_EXCEPTION_IF(!generate_key_image_helper(m_account.get_keys(), m_subaddresses, in_tx_out_pkey->key, in_tx_pub_key, in_additionakl_tx_pub_keys, in_td.m_internal_output_index, in_ephemeral, in_img),
+ THROW_WALLET_EXCEPTION_IF(!generate_key_image_helper(m_account.get_keys(), m_subaddresses, in_tx_out_pkey->key, in_tx_pub_key, in_additionakl_tx_pub_keys, in_td.m_internal_output_index, in_ephemeral, in_img, m_account.get_device()),
error::wallet_internal_error, "failed to generate key image");
THROW_WALLET_EXCEPTION_IF(in_key->k_image != in_img, error::wallet_internal_error, "key image mismatch");
@@ -7701,13 +7792,13 @@ bool wallet2::check_spend_proof(const crypto::hash &txid, const std::string &mes
void wallet2::check_tx_key(const crypto::hash &txid, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, const cryptonote::account_public_address &address, uint64_t &received, bool &in_pool, uint64_t &confirmations)
{
crypto::key_derivation derivation;
- THROW_WALLET_EXCEPTION_IF(!crypto::generate_key_derivation(address.m_view_public_key, tx_key, derivation), error::wallet_internal_error,
+ THROW_WALLET_EXCEPTION_IF(!crypto::generate_key_derivation(address.m_view_public_key, tx_key, derivation, m_account.get_device()), error::wallet_internal_error,
"Failed to generate key derivation from supplied parameters");
std::vector<crypto::key_derivation> additional_derivations;
additional_derivations.resize(additional_tx_keys.size());
for (size_t i = 0; i < additional_tx_keys.size(); ++i)
- THROW_WALLET_EXCEPTION_IF(!crypto::generate_key_derivation(address.m_view_public_key, additional_tx_keys[i], additional_derivations[i]), error::wallet_internal_error,
+ THROW_WALLET_EXCEPTION_IF(!crypto::generate_key_derivation(address.m_view_public_key, additional_tx_keys[i], additional_derivations[i], m_account.get_device()), error::wallet_internal_error,
"Failed to generate key derivation from supplied parameters");
check_tx_key_helper(txid, derivation, additional_derivations, address, received, in_pool, confirmations);
@@ -7741,6 +7832,7 @@ void wallet2::check_tx_key_helper(const crypto::hash &txid, const crypto::key_de
"The size of additional derivations is wrong");
received = 0;
+ hw::device &hwdev = m_account.get_device();
for (size_t n = 0; n < tx.vout.size(); ++n)
{
const cryptonote::txout_to_key* const out_key = boost::get<cryptonote::txout_to_key>(std::addressof(tx.vout[n].target));
@@ -7748,13 +7840,13 @@ void wallet2::check_tx_key_helper(const crypto::hash &txid, const crypto::key_de
continue;
crypto::public_key derived_out_key;
- bool r = derive_public_key(derivation, n, address.m_spend_public_key, derived_out_key);
+ bool r = derive_public_key(derivation, n, address.m_spend_public_key, derived_out_key, hwdev);
THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to derive public key");
bool found = out_key->key == derived_out_key;
crypto::key_derivation found_derivation = derivation;
if (!found && !additional_derivations.empty())
{
- r = derive_public_key(additional_derivations[n], n, address.m_spend_public_key, derived_out_key);
+ r = derive_public_key(additional_derivations[n], n, address.m_spend_public_key, derived_out_key,hwdev);
THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to derive public key");
found = out_key->key == derived_out_key;
found_derivation = additional_derivations[n];
@@ -7770,9 +7862,9 @@ void wallet2::check_tx_key_helper(const crypto::hash &txid, const crypto::key_de
else
{
crypto::secret_key scalar1;
- crypto::derivation_to_scalar(found_derivation, n, scalar1);
+ crypto::derivation_to_scalar(found_derivation, n, scalar1, hwdev);
rct::ecdhTuple ecdh_info = tx.rct_signatures.ecdhInfo[n];
- rct::ecdhDecode(ecdh_info, rct::sk2rct(scalar1));
+ rct::ecdhDecode(ecdh_info, rct::sk2rct(scalar1), hwdev);
const rct::key C = tx.rct_signatures.outPk[n].mask;
rct::key Ctmp;
rct::addKeys2(Ctmp, ecdh_info.mask, ecdh_info.amount, rct::H);
@@ -8126,7 +8218,7 @@ std::string wallet2::get_reserve_proof(const boost::optional<std::pair<uint32_t,
// derive ephemeral secret key
crypto::key_image ki;
cryptonote::keypair ephemeral;
- const bool r = cryptonote::generate_key_image_helper(m_account.get_keys(), m_subaddresses, td.get_public_key(), tx_pub_key, additional_tx_pub_keys, td.m_internal_output_index, ephemeral, ki);
+ const bool r = cryptonote::generate_key_image_helper(m_account.get_keys(), m_subaddresses, td.get_public_key(), tx_pub_key, additional_tx_pub_keys, td.m_internal_output_index, ephemeral, ki, m_account.get_device());
THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key image");
THROW_WALLET_EXCEPTION_IF(ephemeral.pub != td.get_public_key(), error::wallet_internal_error, "Derived public key doesn't agree with the stored one");
@@ -8350,16 +8442,16 @@ uint64_t wallet2::get_daemon_blockchain_target_height(string &err)
uint64_t wallet2::get_approximate_blockchain_height() const
{
// time of v2 fork
- const time_t fork_time = m_testnet ? 1448285909 : 1458748658;
+ const time_t fork_time = m_nettype == TESTNET ? 1448285909 : m_nettype == STAGENET ? (time_t)-1/*TODO*/ : 1458748658;
// v2 fork block
- const uint64_t fork_block = m_testnet ? 624634 : 1009827;
+ const uint64_t fork_block = m_nettype == TESTNET ? 624634 : m_nettype == STAGENET ? (uint64_t)-1/*TODO*/ : 1009827;
// avg seconds per block
const int seconds_per_block = DIFFICULTY_TARGET_V2;
// Calculated blockchain height
uint64_t approx_blockchain_height = fork_block + (time(NULL) - fork_time)/seconds_per_block;
// testnet got some huge rollbacks, so the estimation is way off
static const uint64_t approximate_testnet_rolled_back_blocks = 148540;
- if (m_testnet && approx_blockchain_height > approximate_testnet_rolled_back_blocks)
+ if (m_nettype == TESTNET && approx_blockchain_height > approximate_testnet_rolled_back_blocks)
approx_blockchain_height -= approximate_testnet_rolled_back_blocks;
LOG_PRINT_L2("Calculated blockchain height: " << approx_blockchain_height);
return approx_blockchain_height;
@@ -8500,20 +8592,21 @@ crypto::public_key wallet2::get_tx_pub_key_from_received_outs(const tools::walle
// more than one, loop and search
const cryptonote::account_keys& keys = m_account.get_keys();
size_t pk_index = 0;
+ hw::device &hwdev = m_account.get_device();
const std::vector<crypto::public_key> additional_tx_pub_keys = get_additional_tx_pub_keys_from_extra(td.m_tx);
std::vector<crypto::key_derivation> additional_derivations;
for (size_t i = 0; i < additional_tx_pub_keys.size(); ++i)
{
additional_derivations.push_back({});
- bool r = generate_key_derivation(additional_tx_pub_keys[i], keys.m_view_secret_key, additional_derivations.back());
+ bool r = generate_key_derivation(additional_tx_pub_keys[i], keys.m_view_secret_key, additional_derivations.back(), hwdev);
THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key derivation");
}
while (find_tx_extra_field_by_type(tx_extra_fields, pub_key_field, pk_index++)) {
const crypto::public_key tx_pub_key = pub_key_field.pub_key;
crypto::key_derivation derivation;
- bool r = generate_key_derivation(tx_pub_key, keys.m_view_secret_key, derivation);
+ bool r = generate_key_derivation(tx_pub_key, keys.m_view_secret_key, derivation, hwdev);
THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key derivation");
for (size_t i = 0; i < td.m_tx.vout.size(); ++i)
@@ -8584,7 +8677,7 @@ std::vector<std::pair<crypto::key_image, crypto::signature>> wallet2::export_key
// generate ephemeral secret key
crypto::key_image ki;
cryptonote::keypair in_ephemeral;
- bool r = cryptonote::generate_key_image_helper(m_account.get_keys(), m_subaddresses, pkey, tx_pub_key, additional_tx_pub_keys, td.m_internal_output_index, in_ephemeral, ki);
+ bool r = cryptonote::generate_key_image_helper(m_account.get_keys(), m_subaddresses, pkey, tx_pub_key, additional_tx_pub_keys, td.m_internal_output_index, in_ephemeral, ki, m_account.get_device());
THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key image");
THROW_WALLET_EXCEPTION_IF(td.m_key_image_known && !td.m_key_image_partial && ki != td.m_key_image,
@@ -8784,6 +8877,7 @@ uint64_t wallet2::import_key_images(const std::vector<std::pair<crypto::key_imag
// process each outgoing tx
auto spent_txid = spent_txids.begin();
+ hw::device &hwdev = m_account.get_device();
for (const COMMAND_RPC_GET_TRANSACTIONS::entry& e : gettxs_res.txs)
{
THROW_WALLET_EXCEPTION_IF(e.in_pool, error::wallet_internal_error, "spent tx isn't supposed to be in txpool");
@@ -8801,14 +8895,14 @@ uint64_t wallet2::import_key_images(const std::vector<std::pair<crypto::key_imag
const cryptonote::account_keys& keys = m_account.get_keys();
const crypto::public_key tx_pub_key = get_tx_pub_key_from_extra(spent_tx);
crypto::key_derivation derivation;
- bool r = generate_key_derivation(tx_pub_key, keys.m_view_secret_key, derivation);
+ bool r = generate_key_derivation(tx_pub_key, keys.m_view_secret_key, derivation, hwdev);
THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key derivation");
const std::vector<crypto::public_key> additional_tx_pub_keys = get_additional_tx_pub_keys_from_extra(spent_tx);
std::vector<crypto::key_derivation> additional_derivations;
for (size_t i = 0; i < additional_tx_pub_keys.size(); ++i)
{
additional_derivations.push_back({});
- r = generate_key_derivation(additional_tx_pub_keys[i], keys.m_view_secret_key, additional_derivations.back());
+ r = generate_key_derivation(additional_tx_pub_keys[i], keys.m_view_secret_key, additional_derivations.back(), hwdev);
THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key derivation");
}
size_t output_index = 0;
@@ -8822,7 +8916,7 @@ uint64_t wallet2::import_key_images(const std::vector<std::pair<crypto::key_imag
if (tx_scan_info.money_transfered == 0)
{
rct::key mask;
- tx_scan_info.money_transfered = tools::decodeRct(spent_tx.rct_signatures, tx_scan_info.received->derivation, output_index, mask);
+ tx_scan_info.money_transfered = tools::decodeRct(spent_tx.rct_signatures, tx_scan_info.received->derivation, output_index, mask, hwdev);
}
tx_money_got_in_outs += tx_scan_info.money_transfered;
}
@@ -8982,7 +9076,7 @@ size_t wallet2::import_outputs(const std::vector<tools::wallet2::transfer_detail
const std::vector<crypto::public_key> additional_tx_pub_keys = get_additional_tx_pub_keys_from_extra(td.m_tx);
const crypto::public_key& out_key = boost::get<cryptonote::txout_to_key>(td.m_tx.vout[td.m_internal_output_index].target).key;
- bool r = cryptonote::generate_key_image_helper(m_account.get_keys(), m_subaddresses, out_key, tx_pub_key, additional_tx_pub_keys, td.m_internal_output_index, in_ephemeral, td.m_key_image);
+ bool r = cryptonote::generate_key_image_helper(m_account.get_keys(), m_subaddresses, out_key, tx_pub_key, additional_tx_pub_keys, td.m_internal_output_index, in_ephemeral, td.m_key_image, m_account.get_device());
THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key image");
expand_subaddresses(td.m_subaddr_index);
td.m_key_image_known = true;
@@ -9338,7 +9432,7 @@ std::string wallet2::decrypt_with_view_secret_key(const std::string &ciphertext,
std::string wallet2::make_uri(const std::string &address, const std::string &payment_id, uint64_t amount, const std::string &tx_description, const std::string &recipient_name, std::string &error) const
{
cryptonote::address_parse_info info;
- if(!get_account_address_from_str(info, testnet(), address))
+ if(!get_account_address_from_str(info, nettype(), address))
{
error = std::string("wrong address: ") + address;
return std::string();
@@ -9402,7 +9496,7 @@ bool wallet2::parse_uri(const std::string &uri, std::string &address, std::strin
address = ptr ? remainder.substr(0, ptr-remainder.c_str()) : remainder;
cryptonote::address_parse_info info;
- if(!get_account_address_from_str(info, testnet(), address))
+ if(!get_account_address_from_str(info, nettype(), address))
{
error = std::string("URI has wrong address: ") + address;
return false;
@@ -9651,10 +9745,14 @@ std::vector<std::pair<uint64_t, uint64_t>> wallet2::estimate_backlog(uint64_t mi
}
//----------------------------------------------------------------------------------------------------
void wallet2::generate_genesis(cryptonote::block& b) const {
- if (m_testnet)
+ if (m_nettype == TESTNET)
{
cryptonote::generate_genesis_block(b, config::testnet::GENESIS_TX, config::testnet::GENESIS_NONCE);
}
+ else if (m_nettype == STAGENET)
+ {
+ cryptonote::generate_genesis_block(b, config::stagenet::GENESIS_TX, config::stagenet::GENESIS_NONCE);
+ }
else
{
cryptonote::generate_genesis_block(b, config::GENESIS_TX, config::GENESIS_NONCE);