wallet2: better test on whether to allow output import

Being offline is not a good enough heuristic, so we keep track
of whether the wallet ever refreshed from a daemon, which is a
lot better, and probably the best we can do without manual user
designation (which would break existing cold wallet setups till
the user designates those wallets)
This commit is contained in:
moneromooo-monero 2022-08-18 07:14:45 +00:00
parent 0cbf5571d3
commit 1d3657afb5
No known key found for this signature in database
GPG key ID: 686F07454D6CEFC3
3 changed files with 34 additions and 6 deletions

View file

@ -1218,7 +1218,8 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended, std
m_export_format(ExportFormat::Binary), m_export_format(ExportFormat::Binary),
m_load_deprecated_formats(false), m_load_deprecated_formats(false),
m_credits_target(0), m_credits_target(0),
m_enable_multisig(false) m_enable_multisig(false),
m_has_ever_refreshed_from_node(false)
{ {
set_rpc_client_secret_key(rct::rct2sk(rct::skGen())); set_rpc_client_secret_key(rct::rct2sk(rct::skGen()));
} }
@ -3535,6 +3536,8 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo
throw std::runtime_error("proxy exception in refresh thread"); throw std::runtime_error("proxy exception in refresh thread");
} }
m_has_ever_refreshed_from_node = true;
if(!first && blocks_start_height == next_blocks_start_height) if(!first && blocks_start_height == next_blocks_start_height)
{ {
m_node_rpc_proxy.set_height(m_blockchain.size()); m_node_rpc_proxy.set_height(m_blockchain.size());
@ -13175,7 +13178,8 @@ size_t wallet2::import_outputs(const std::tuple<uint64_t, uint64_t, std::vector<
{ {
PERF_TIMER(import_outputs); PERF_TIMER(import_outputs);
THROW_WALLET_EXCEPTION_IF(!m_offline, error::wallet_internal_error, "Hot wallets cannot import outputs"); THROW_WALLET_EXCEPTION_IF(m_has_ever_refreshed_from_node, error::wallet_internal_error,
"Hot wallets cannot import outputs");
// we can now import piecemeal // we can now import piecemeal
const size_t offset = std::get<0>(outputs); const size_t offset = std::get<0>(outputs);
@ -13254,7 +13258,8 @@ size_t wallet2::import_outputs(const std::tuple<uint64_t, uint64_t, std::vector<
{ {
PERF_TIMER(import_outputs); PERF_TIMER(import_outputs);
THROW_WALLET_EXCEPTION_IF(!m_offline, error::wallet_internal_error, "Hot wallets cannot import outputs"); THROW_WALLET_EXCEPTION_IF(m_has_ever_refreshed_from_node, error::wallet_internal_error,
"Hot wallets cannot import outputs");
// we can now import piecemeal // we can now import piecemeal
const size_t offset = std::get<0>(outputs); const size_t offset = std::get<0>(outputs);

View file

@ -1229,11 +1229,17 @@ private:
if(ver < 29) if(ver < 29)
return; return;
a & m_rpc_client_secret_key; a & m_rpc_client_secret_key;
if(ver < 30)
{
m_has_ever_refreshed_from_node = false;
return;
}
a & m_has_ever_refreshed_from_node;
} }
BEGIN_SERIALIZE_OBJECT() BEGIN_SERIALIZE_OBJECT()
MAGIC_FIELD("monero wallet cache") MAGIC_FIELD("monero wallet cache")
VERSION_FIELD(0) VERSION_FIELD(1)
FIELD(m_blockchain) FIELD(m_blockchain)
FIELD(m_transfers) FIELD(m_transfers)
FIELD(m_account_public_address) FIELD(m_account_public_address)
@ -1259,6 +1265,12 @@ private:
FIELD(m_device_last_key_image_sync) FIELD(m_device_last_key_image_sync)
FIELD(m_cold_key_images) FIELD(m_cold_key_images)
FIELD(m_rpc_client_secret_key) FIELD(m_rpc_client_secret_key)
if (version < 1)
{
m_has_ever_refreshed_from_node = false;
return true;
}
FIELD(m_has_ever_refreshed_from_node)
END_SERIALIZE() END_SERIALIZE()
/*! /*!
@ -1471,7 +1483,7 @@ private:
// Import/Export wallet data // Import/Export wallet data
std::tuple<uint64_t, uint64_t, std::vector<tools::wallet2::exported_transfer_details>> export_outputs(bool all = false, uint32_t start = 0, uint32_t count = 0xffffffff) const; std::tuple<uint64_t, uint64_t, std::vector<tools::wallet2::exported_transfer_details>> export_outputs(bool all = false, uint32_t start = 0, uint32_t count = 0xffffffff) const;
std::string export_outputs_to_str(bool all = false, uint32_t start = 0, uint32_t count = 0) const; std::string export_outputs_to_str(bool all = false, uint32_t start = 0, uint32_t count = 0xffffffff) const;
size_t import_outputs(const std::tuple<uint64_t, uint64_t, std::vector<tools::wallet2::exported_transfer_details>> &outputs); size_t import_outputs(const std::tuple<uint64_t, uint64_t, std::vector<tools::wallet2::exported_transfer_details>> &outputs);
size_t import_outputs(const std::tuple<uint64_t, uint64_t, std::vector<tools::wallet2::transfer_details>> &outputs); size_t import_outputs(const std::tuple<uint64_t, uint64_t, std::vector<tools::wallet2::transfer_details>> &outputs);
size_t import_outputs_from_str(const std::string &outputs_st); size_t import_outputs_from_str(const std::string &outputs_st);
@ -1906,11 +1918,13 @@ private:
ExportFormat m_export_format; ExportFormat m_export_format;
bool m_load_deprecated_formats; bool m_load_deprecated_formats;
bool m_has_ever_refreshed_from_node;
static boost::mutex default_daemon_address_lock; static boost::mutex default_daemon_address_lock;
static std::string default_daemon_address; static std::string default_daemon_address;
}; };
} }
BOOST_CLASS_VERSION(tools::wallet2, 29) BOOST_CLASS_VERSION(tools::wallet2, 30)
BOOST_CLASS_VERSION(tools::wallet2::transfer_details, 12) BOOST_CLASS_VERSION(tools::wallet2::transfer_details, 12)
BOOST_CLASS_VERSION(tools::wallet2::multisig_info, 1) BOOST_CLASS_VERSION(tools::wallet2::multisig_info, 1)
BOOST_CLASS_VERSION(tools::wallet2::multisig_info::LR, 0) BOOST_CLASS_VERSION(tools::wallet2::multisig_info::LR, 0)

View file

@ -109,6 +109,15 @@ class ColdSigningTest():
num_outputs -= 1 num_outputs -= 1
count = 1 + int(random.random() * 5) count = 1 + int(random.random() * 5)
res = self.hot_wallet.export_outputs(all = True, start = start, count = count) res = self.hot_wallet.export_outputs(all = True, start = start, count = count)
# the hot wallet cannot import outputs
ok = False
try:
self.hot_wallet.import_outputs(res.outputs_data_hex)
except:
ok = True
assert ok
try: try:
self.cold_wallet.import_outputs(res.outputs_data_hex) self.cold_wallet.import_outputs(res.outputs_data_hex)
except Exception as e: except Exception as e: