Add RESET_NETWORK device reset debug command

This command (supported only on debug builds) lets the wallet force
reset the Ledger device onto the given network type for testing
purposes.
This commit is contained in:
Jason Rhinelander 2023-04-27 14:14:46 -03:00
parent b309bf8bb6
commit 73105f0040
No known key found for this signature in database
GPG Key ID: C4992CE7A88D4262
14 changed files with 30 additions and 16 deletions

View File

@ -30,6 +30,7 @@
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#include <fstream>
#include <type_traits>
#include "account.h"
#include "epee/warnings.h"
@ -197,19 +198,19 @@ DISABLE_VS_WARNINGS(4244 4345)
}
//-----------------------------------------------------------------
void account_base::create_from_device(const std::string &device_name)
void account_base::create_from_device(const std::string &device_name, bool debug_reset)
{
hw::device &hwdev = hw::get_device(device_name);
hwdev.set_name(device_name);
create_from_device(hwdev);
create_from_device(hwdev, debug_reset);
}
void account_base::create_from_device(hw::device &hwdev)
void account_base::create_from_device(hw::device &hwdev, bool debug_reset)
{
m_keys.set_device(hwdev);
MCDEBUG("device", "device type: " << tools::type_name(typeid(hwdev)));
CHECK_AND_ASSERT_THROW_MES(hwdev.init(), "Device init failed");
CHECK_AND_ASSERT_THROW_MES(hwdev.connect(), "Device connect failed");
CHECK_AND_ASSERT_THROW_MES(hwdev.connect(debug_reset), "Device connect failed");
try {
CHECK_AND_ASSERT_THROW_MES(hwdev.get_public_address(m_keys.m_account_address), "Cannot get a device address");
CHECK_AND_ASSERT_THROW_MES(hwdev.get_secret_keys(m_keys.m_view_secret_key, m_keys.m_spend_secret_key), "Cannot get device secret");

View File

@ -75,8 +75,8 @@ namespace cryptonote
public:
account_base();
crypto::secret_key generate(const crypto::secret_key& recovery_key = crypto::secret_key(), bool recover = false, bool two_random = false);
void create_from_device(const std::string &device_name);
void create_from_device(hw::device &hwdev);
void create_from_device(const std::string &device_name, bool debug_reset = false);
void create_from_device(hw::device &hwdev, bool debug_reset = false);
void create_from_keys(const cryptonote::account_public_address& address, const crypto::secret_key& spendkey, const crypto::secret_key& viewkey);
void create_from_viewkey(const cryptonote::account_public_address& address, const crypto::secret_key& viewkey);
bool make_multisig(const crypto::secret_key &view_secret_key, const crypto::secret_key &spend_secret_key, const crypto::public_key &spend_public_key, const std::vector<crypto::secret_key> &multisig_keys);

View File

@ -126,7 +126,7 @@ namespace hw {
virtual bool init() = 0;
virtual bool release() = 0;
virtual bool connect() = 0;
virtual bool connect(bool debug_reset_network = false) = 0;
virtual bool disconnect() = 0;
virtual bool set_mode(mode m) { mode_ = m; return true; }

View File

@ -73,7 +73,7 @@ namespace hw::core {
return true;
}
bool device_default::connect() {
bool device_default::connect(bool) {
return true;
}
bool device_default::disconnect() {

View File

@ -52,7 +52,7 @@ namespace hw {
bool init() override;
bool release() override;
bool connect() override;
bool connect(bool ignored) override;
bool disconnect() override;
type get_type() const override { return type::SOFTWARE; };

View File

@ -257,6 +257,7 @@ namespace hw::ledger {
LEDGER_INS(RESET, 0x02);
LEDGER_INS(GET_NETWORK, 0x10);
LEDGER_INS(RESET_NETWORK, 0x11);
LEDGER_INS(GET_KEY, 0x20);
LEDGER_INS(DISPLAY_ADDRESS, 0x21);
@ -600,7 +601,7 @@ namespace hw::ledger {
{0x2c97, 0x501c, 0, 0xffa0}, {0x2c97, 0x501d, 0, 0xffa0}, {0x2c97, 0x501e, 0, 0xffa0}, {0x2c97, 0x501f, 0, 0xffa0},
};
bool device_ledger::connect() {
bool device_ledger::connect(bool debug_reset) {
disconnect();
if (auto* hid_io = dynamic_cast<io::hid*>(hw_device.get()))
hid_io->connect(known_devices);
@ -610,6 +611,11 @@ namespace hw::ledger {
throw std::logic_error{"Invalid ledger hardware configure"};
reset();
if (debug_reset) {
auto locks = tools::unique_locks(device_locker, command_locker);
send_simple(INS_RESET_NETWORK, static_cast<uint8_t>(nettype));
}
check_network_type();
#ifdef DEBUG_HWDEVICE

View File

@ -232,7 +232,7 @@ namespace hw::ledger {
std::string get_name() const override;
bool init() override;
bool release() override;
bool connect() override;
bool connect(bool debug_reset_network = false) override;
bool disconnect() override;
bool connected() const;

View File

@ -130,6 +130,7 @@ namespace
const auto arg_wallet_file = wallet_args::arg_wallet_file();
const command_line::arg_descriptor<std::string> arg_generate_new_wallet = {"generate-new-wallet", sw::tr("Generate new wallet and save it to <arg>"), ""};
const command_line::arg_descriptor<std::string> arg_generate_from_device = {"generate-from-device", sw::tr("Generate new wallet from device and save it to <arg>"), ""};
const command_line::arg_descriptor<bool> arg_debug_reset_device = {"debug-reset-device", sw::tr("Reset the hardware device when generating the wallet (requires a debugging hardware wallet)"), false};
const command_line::arg_descriptor<std::string> arg_generate_from_view_key = {"generate-from-view-key", sw::tr("Generate incoming-only wallet from view key"), ""};
const command_line::arg_descriptor<std::string> arg_generate_from_spend_key = {"generate-from-spend-key", sw::tr("Generate deterministic wallet from spend key"), ""};
const command_line::arg_descriptor<std::string> arg_generate_from_keys = {"generate-from-keys", sw::tr("Generate wallet from private keys"), ""};
@ -4058,6 +4059,7 @@ bool simple_wallet::handle_command_line(const boost::program_options::variables_
m_do_not_relay = command_line::get_arg(vm, arg_do_not_relay);
m_subaddress_lookahead = command_line::get_arg(vm, arg_subaddress_lookahead);
m_use_english_language_names = command_line::get_arg(vm, arg_use_english_language_names);
m_debug_reset_device = command_line::get_arg(vm, arg_debug_reset_device);
m_restoring = !m_generate_from_view_key.empty() ||
!m_generate_from_spend_key.empty() ||
!m_generate_from_keys.empty() ||
@ -4353,7 +4355,7 @@ std::optional<epee::wipeable_string> simple_wallet::new_device_wallet(const boos
"spend key (needed to spend funds) does not leave the device.");
m_wallet->restore_from_device(
m_wallet_file, std::move(rc.second).password(), device_desc.empty() ? "Ledger" : device_desc, create_address_file,
std::move(create_hwdev_txt), [](const std::string& msg) { message_writer(epee::console_color_green, true) << msg; });
std::move(create_hwdev_txt), m_debug_reset_device, [](const std::string& msg) { message_writer(epee::console_color_green, true) << msg; });
message_writer(epee::console_color_white, true) << tr("Finished setting up wallet from hw device");
}
catch (const std::exception& e)

View File

@ -434,6 +434,7 @@ namespace cryptonote
bool m_do_not_relay;
bool m_use_english_language_names;
bool m_has_locked_key_images;
bool m_debug_reset_device;
epee::console_handlers_binder m_cmd_binder;

View File

@ -4931,7 +4931,7 @@ void wallet2::generate(const fs::path& wallet_, const epee::wipeable_string& pas
}
void wallet2::restore_from_device(const fs::path& wallet_, const epee::wipeable_string& password, const std::string &device_name,
bool create_address_file, std::optional<std::string> hwdev_label, std::function<void(std::string msg)> progress_callback)
bool create_address_file, std::optional<std::string> hwdev_label, bool debug_reset_device, std::function<void(std::string msg)> progress_callback)
{
clear();
prepare_file_names(wallet_);
@ -4948,7 +4948,7 @@ void wallet2::restore_from_device(const fs::path& wallet_, const epee::wipeable_
hwdev.set_derivation_path(m_device_derivation_path);
hwdev.set_callback(get_device_callback());
m_account.create_from_device(hwdev);
m_account.create_from_device(hwdev, debug_reset_device);
init_type(m_account.get_device().get_type());
setup_keys(password);
if (progress_callback)

View File

@ -537,7 +537,8 @@ private:
* \param status_callback callback to invoke with progress messages to display to the user
*/
void restore_from_device(const fs::path& wallet_, const epee::wipeable_string& password, const std::string &device_name,
bool create_address_file = false, std::optional<std::string> hwdev_label = std::nullopt, std::function<void(std::string msg)> status_callback = {});
bool create_address_file = false, std::optional<std::string> hwdev_label = std::nullopt, bool debug_reset_device = false,
std::function<void(std::string msg)> status_callback = {});
/*!
* \brief Creates a multisig wallet

View File

@ -2424,7 +2424,8 @@ namespace {
wal->set_refresh_from_block_height(hres.height);
if (req.hardware_wallet)
wal->restore_from_device(wallet_file, req.password, req.device_name.empty() ? "Ledger" : req.device_name);
wal->restore_from_device(wallet_file, req.password, req.device_name.empty() ? "Ledger" : req.device_name,
false, std::nullopt, req.debug_reset);
else
wal->generate(wallet_file, req.password);

View File

@ -883,6 +883,7 @@ KV_SERIALIZE_MAP_CODE_BEGIN(CREATE_WALLET::request)
KV_SERIALIZE(hardware_wallet)
KV_SERIALIZE(device_name)
KV_SERIALIZE(device_label)
KV_SERIALIZE(debug_reset)
KV_SERIALIZE_MAP_CODE_END()

View File

@ -1700,6 +1700,7 @@ namespace tools::wallet_rpc {
bool hardware_wallet; // Create this wallet from a connected hardware wallet. (`language` will be ignored).
std::string device_name; // When `hardware` is true, this specifies the hardware wallet device type (currently supported: "Ledger"). If omitted "Ledger" is used.
std::optional<std::string> device_label; // Custom label to write to a `wallet.hwdev.txt`. Can be empty; omit the parameter entirely to not write a .hwdev.txt file at all.
bool debug_reset; // Can be specified as true to force a hardware wallet in DEBUG mode to reset (and switch networks, if necessary). Will fail if the hardware wallet is not compiled in debug mode.
KV_MAP_SERIALIZABLE
};