aboutsummaryrefslogtreecommitdiff
path: root/src/wallet
diff options
context:
space:
mode:
Diffstat (limited to 'src/wallet')
-rw-r--r--src/wallet/api/wallet.cpp2
-rw-r--r--src/wallet/api/wallet2_api.h4
-rw-r--r--src/wallet/api/wallet_manager.cpp4
-rw-r--r--src/wallet/wallet2.cpp321
-rw-r--r--src/wallet/wallet2.h17
-rw-r--r--src/wallet/wallet_rpc_server.cpp5
-rw-r--r--src/wallet/wallet_rpc_server_commands_defs.h3
7 files changed, 227 insertions, 129 deletions
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index 5ce8ede8d..7f8144129 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -1746,7 +1746,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/wallet2_api.h b/src/wallet/api/wallet2_api.h
index a22788399..1c4545a25 100644
--- a/src/wallet/api/wallet2_api.h
+++ b/src/wallet/api/wallet2_api.h
@@ -685,7 +685,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;
/*!
@@ -827,7 +827,7 @@ struct WalletManager
const std::string &spendKeyString = "") = 0;
/*!
- * \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 bb144227e..22bc343fb 100644
--- a/src/wallet/api/wallet_manager.cpp
+++ b/src/wallet/api/wallet_manager.cpp
@@ -37,7 +37,7 @@
#include "common/updates.h"
#include "version.h"
#include "net/http_client.h"
-
+#include "deviuce/device.hpp"
#include <boost/filesystem.hpp>
#include <boost/regex.hpp>
@@ -151,7 +151,7 @@ bool WalletManagerImpl::walletExists(const std::string &path)
bool WalletManagerImpl::verifyWalletPassword(const std::string &keys_file_name, const std::string &password, bool no_spend_key) const
{
- return tools::wallet2::verify_password(keys_file_name, password, no_spend_key);
+ return tools::wallet2::verify_password(keys_file_name, password, no_spend_key, hw::get_device("default"));
}
std::vector<std::string> WalletManagerImpl::findWallets(const std::string &path)
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 5dc3ea2d1..08924fffa 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"
{
@@ -382,7 +383,7 @@ 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)
{
@@ -538,7 +539,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 +554,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
@@ -623,7 +624,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)
{
}
@@ -817,40 +819,17 @@ 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;
}
//----------------------------------------------------------------------------------------------------
@@ -882,20 +861,19 @@ 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
cryptonote::subaddress_index index2;
for (index2.major = m_subaddress_labels.size(); index2.major < index.major + m_subaddress_lookahead_major; ++index2.major)
{
- for (index2.minor = 0; index2.minor < (index2.major == index.major ? index.minor : 0) + m_subaddress_lookahead_minor; ++index2.minor)
+ 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, hwdev);
+ for (index2.minor = 0; index2.minor < end; ++index2.minor)
{
- if (m_subaddresses_inv.count(index2) == 0)
- {
- crypto::public_key D = get_subaddress_spend_public_key(index2);
- m_subaddresses[D] = index2;
- m_subaddresses_inv[index2] = D;
- }
+ const crypto::public_key &D = pkeys[index2.minor];
+ m_subaddresses[D] = index2;
}
}
m_subaddress_labels.resize(index.major + 1, {"Untitled account"});
@@ -904,15 +882,14 @@ void wallet2::expand_subaddresses(const cryptonote::subaddress_index& index)
else if (m_subaddress_labels[index.major].size() <= index.minor)
{
// add new subaddresses
- cryptonote::subaddress_index index2 = index;
- for (index2.minor = m_subaddress_labels[index.major].size(); index2.minor < index.minor + m_subaddress_lookahead_minor; ++index2.minor)
+ 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, hwdev);
+ for (; index2.minor < end; ++index2.minor)
{
- if (m_subaddresses_inv.count(index2) == 0)
- {
- crypto::public_key D = get_subaddress_spend_public_key(index2);
- m_subaddresses[D] = index2;
- m_subaddresses_inv[index2] = D;
- }
+ const crypto::public_key &D = pkeys[index2.minor - begin];
+ m_subaddresses[D] = index2;
}
m_subaddress_labels[index.major].resize(index.minor + 1);
}
@@ -973,7 +950,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
@@ -985,20 +962,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;
@@ -1022,7 +999,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");
@@ -1031,7 +1008,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;
@@ -1079,8 +1056,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");
@@ -1093,7 +1071,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();
@@ -1218,7 +1196,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
td.m_rct = false;
}
set_unspent(m_transfers.size()-1);
- if (!m_multisig)
+ if (!m_multisig && !m_watch_only)
m_key_images[td.m_key_image] = m_transfers.size()-1;
m_pub_keys[tx_scan_info[o].in_ephemeral.pub] = m_transfers.size()-1;
if (m_multisig)
@@ -1312,11 +1290,21 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
uint64_t amount = boost::get<cryptonote::txin_to_key>(in).amount;
if (amount > 0)
{
- THROW_WALLET_EXCEPTION_IF(amount != td.amount(), error::wallet_internal_error,
- std::string("Inconsistent amount in tx input: got ") + print_money(amount) +
- std::string(", expected ") + print_money(td.amount()));
+ if(amount != td.amount())
+ {
+ MERROR("Inconsistent amount in tx input: got " << print_money(amount) <<
+ ", expected " << print_money(td.amount()));
+ // this means:
+ // 1) the same output pub key was used as destination multiple times,
+ // 2) the wallet set the highest amount among them to transfer_details::m_amount, and
+ // 3) the wallet somehow spent that output with an amount smaller than the above amount, causing inconsistency
+ td.m_amount = amount;
+ }
+ }
+ else
+ {
+ amount = td.amount();
}
- amount = td.amount();
tx_money_spent_in_ins += amount;
if (subaddr_account && *subaddr_account != td.m_subaddr_index.major)
LOG_ERROR("spent funds are from different subaddress accounts; count of incoming/outgoing payments will be incorrect");
@@ -1375,7 +1363,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);
}
@@ -2342,7 +2330,6 @@ bool wallet2::clear()
m_address_book.clear();
m_local_bc_height = 1;
m_subaddresses.clear();
- m_subaddresses_inv.clear();
m_subaddress_labels.clear();
return true;
}
@@ -2379,6 +2366,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());
@@ -2476,16 +2467,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
@@ -2533,6 +2514,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())
{
@@ -2549,6 +2531,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)
{
@@ -2634,8 +2622,8 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_
m_confirm_backlog_threshold = field_confirm_backlog_threshold;
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, confirm_export_overwrite, int, Int, false, true);
m_confirm_export_overwrite = field_confirm_export_overwrite;
- GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, m_auto_low_priority, int, Int, false, true);
- m_auto_low_priority = field_m_auto_low_priority;
+ 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");
@@ -2648,11 +2636,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;
}
@@ -2669,7 +2666,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());
}
/*!
@@ -2684,7 +2681,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;
@@ -2719,9 +2716,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;
}
@@ -2797,6 +2794,7 @@ 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())
{
@@ -2845,6 +2843,7 @@ 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;
// calculate a starting refresh height
if(m_refresh_from_block_height == 0 && !recover){
@@ -2939,6 +2938,7 @@ 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())
{
@@ -2985,6 +2985,7 @@ 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())
{
@@ -3004,6 +3005,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_testnet));
+ 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,
@@ -3067,6 +3108,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;
@@ -3187,7 +3230,6 @@ bool wallet2::finalize_multisig(const epee::wipeable_string &password, std::unor
}
m_subaddresses.clear();
- m_subaddresses_inv.clear();
m_subaddress_labels.clear();
add_subaddress_account(tr("Primary account"));
@@ -3476,15 +3518,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)
@@ -4258,7 +4293,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);
}
@@ -4367,7 +4402,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;
@@ -4694,7 +4729,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
@@ -5273,7 +5308,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) {
@@ -5497,7 +5532,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; });
}
@@ -6124,7 +6159,7 @@ bool wallet2::light_wallet_login(bool &new_address)
cryptonote::COMMAND_RPC_LOGIN::response response;
request.address = get_account().get_public_address_str(m_testnet);
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");
@@ -6137,7 +6172,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();
@@ -6509,7 +6544,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
@@ -6786,7 +6821,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;
@@ -6817,6 +6852,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();
@@ -7002,6 +7039,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();
@@ -7170,6 +7238,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();
@@ -7235,6 +7305,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");
@@ -7524,7 +7606,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");
@@ -7699,13 +7781,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);
@@ -7739,6 +7821,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));
@@ -7746,13 +7829,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];
@@ -7768,9 +7851,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);
@@ -8124,7 +8207,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");
@@ -8498,20 +8581,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)
@@ -8582,7 +8666,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,
@@ -8782,6 +8866,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");
@@ -8799,14 +8884,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;
@@ -8820,7 +8905,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;
}
@@ -8980,7 +9065,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;
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index f9995c2ee..127e70a26 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -162,7 +162,7 @@ namespace tools
//! Just parses variables.
static std::unique_ptr<wallet2> make_dummy(const boost::program_options::variables_map& vm, const std::function<boost::optional<password_container>(const char *, bool)> &password_prompter);
- static bool verify_password(const std::string& keys_file_name, const epee::wipeable_string& password, bool no_spend_key);
+ 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);
@@ -487,6 +487,14 @@ namespace tools
const cryptonote::account_public_address &account_public_address,
const crypto::secret_key& viewkey = crypto::secret_key());
/*!
+ * \brief Restore a wallet hold by an HW.
+ * \param wallet_ Name of wallet file
+ * \param password Password of wallet file
+ * \param device_name name of HW to use
+ */
+ void restore(const std::string& wallet_, const epee::wipeable_string& password, const std::string &device_name);
+
+ /*!
* \brief Creates a multisig wallet
* \return empty if done, non empty if we need to send another string
* to other participants
@@ -605,6 +613,7 @@ namespace tools
cryptonote::account_public_address get_subaddress(const cryptonote::subaddress_index& index) const;
cryptonote::account_public_address get_address() const { return get_subaddress({0,0}); }
crypto::public_key get_subaddress_spend_public_key(const cryptonote::subaddress_index& index) const;
+ std::vector<crypto::public_key> get_subaddress_spend_public_keys(uint32_t account, uint32_t begin, uint32_t end) const;
std::string get_subaddress_as_str(const cryptonote::subaddress_index& index) const;
std::string get_address_as_str() const { return get_subaddress_as_str({0, 0}); }
std::string get_integrated_address_as_str(const crypto::hash8& payment_id) const;
@@ -634,6 +643,7 @@ namespace tools
bool multisig(bool *ready = NULL, uint32_t *threshold = NULL, uint32_t *total = NULL) const;
bool has_multisig_partial_key_images() const;
bool get_multisig_seed(std::string& seed, const epee::wipeable_string &passphrase = std::string(), bool raw = true) const;
+ bool key_on_device() const { return m_key_on_device; }
// locked & unlocked balance of given or current subaddress account
uint64_t balance(uint32_t subaddr_index_major) const;
@@ -782,7 +792,8 @@ namespace tools
if (ver < 20)
return;
a & m_subaddresses;
- a & m_subaddresses_inv;
+ std::unordered_map<cryptonote::subaddress_index, crypto::public_key> dummy_subaddresses_inv;
+ a & dummy_subaddresses_inv;
a & m_subaddress_labels;
a & m_additional_tx_keys;
if(ver < 21)
@@ -1089,7 +1100,6 @@ namespace tools
std::unordered_map<crypto::public_key, size_t> m_pub_keys;
cryptonote::account_public_address m_account_public_address;
std::unordered_map<crypto::public_key, cryptonote::subaddress_index> m_subaddresses;
- std::unordered_map<cryptonote::subaddress_index, crypto::public_key> m_subaddresses_inv;
std::vector<std::vector<std::string>> m_subaddress_labels;
std::unordered_map<crypto::hash, std::string> m_tx_notes;
std::unordered_map<std::string, std::string> m_attributes;
@@ -1104,6 +1114,7 @@ namespace tools
boost::mutex m_daemon_rpc_mutex;
i_wallet2_callback* m_callback;
+ bool m_key_on_device;
bool m_testnet;
bool m_restricted;
std::string seed_language; /*!< Language of the mnemonics (seed). */
diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index 5c644983b..6d5419521 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -39,6 +39,7 @@ using namespace epee;
#include "wallet/wallet_args.h"
#include "common/command_line.h"
#include "common/i18n.h"
+#include "cryptonote_config.h"
#include "cryptonote_basic/cryptonote_format_utils.h"
#include "cryptonote_basic/account.h"
#include "multisig/multisig.h"
@@ -1803,11 +1804,11 @@ namespace tools
return false;
}
- uint64_t min_height = 0, max_height = (uint64_t)-1;
+ uint64_t min_height = 0, max_height = CRYPTONOTE_MAX_BLOCK_NUMBER;
if (req.filter_by_height)
{
min_height = req.min_height;
- max_height = req.max_height;
+ max_height = req.max_height <= max_height ? req.max_height : max_height;
}
if (req.in)
diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h
index 82b6b78f9..e38cba5a5 100644
--- a/src/wallet/wallet_rpc_server_commands_defs.h
+++ b/src/wallet/wallet_rpc_server_commands_defs.h
@@ -29,6 +29,7 @@
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#pragma once
+#include "cryptonote_config.h"
#include "cryptonote_protocol/cryptonote_protocol_defs.h"
#include "cryptonote_basic/cryptonote_basic.h"
#include "cryptonote_basic/subaddress_index.h"
@@ -1262,7 +1263,7 @@ namespace wallet_rpc
KV_SERIALIZE(pool);
KV_SERIALIZE(filter_by_height);
KV_SERIALIZE(min_height);
- KV_SERIALIZE(max_height);
+ KV_SERIALIZE_OPT(max_height, (uint64_t)CRYPTONOTE_MAX_BLOCK_NUMBER);
KV_SERIALIZE(account_index);
KV_SERIALIZE(subaddr_indices);
END_KV_SERIALIZE_MAP()