diff options
Diffstat (limited to 'src/wallet/wallet2.cpp')
-rw-r--r-- | src/wallet/wallet2.cpp | 158 |
1 files changed, 133 insertions, 25 deletions
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 37b60c5d7..f2e54cf09 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -71,6 +71,8 @@ using namespace epee; #include "common/notify.h" #include "ringct/rctSigs.h" #include "ringdb.h" +#include "device/device_cold.hpp" +#include "device_trezor/device_trezor.hpp" extern "C" { @@ -768,6 +770,11 @@ uint32_t get_subaddress_clamped_sum(uint32_t idx, uint32_t extra) return idx + extra; } +static void setup_shim(hw::wallet_shim * shim, tools::wallet2 * wallet) +{ + shim->get_tx_pub_key_from_received_outs = boost::bind(&tools::wallet2::get_tx_pub_key_from_received_outs, wallet, _1); +} + //----------------------------------------------------------------- } //namespace @@ -1060,8 +1067,9 @@ bool wallet2::get_multisig_seed(epee::wipeable_string& seed, const epee::wipeabl bool wallet2::reconnect_device() { bool r = true; - hw::device &hwdev = hw::get_device(m_device_name); + hw::device &hwdev = lookup_device(m_device_name); hwdev.set_name(m_device_name); + hwdev.set_network_type(m_nettype); r = hwdev.init(); if (!r){ LOG_PRINT_L2("Could not init device"); @@ -2944,6 +2952,7 @@ bool wallet2::deinit() { m_is_initialized=false; unlock_keys_file(); + m_account.deinit(); return true; } //---------------------------------------------------------------------------------------------------- @@ -3413,13 +3422,20 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_ r = epee::serialization::load_t_from_binary(m_account, account_data); THROW_WALLET_EXCEPTION_IF(!r, error::invalid_password); - if (m_key_device_type == hw::device::device_type::LEDGER) { + if (m_key_device_type == hw::device::device_type::LEDGER || m_key_device_type == hw::device::device_type::TREZOR) { LOG_PRINT_L0("Account on device. Initing device..."); - hw::device &hwdev = hw::get_device(m_device_name); - hwdev.set_name(m_device_name); - hwdev.init(); - hwdev.connect(); + hw::device &hwdev = lookup_device(m_device_name); + THROW_WALLET_EXCEPTION_IF(!hwdev.set_name(m_device_name), error::wallet_internal_error, "Could not set device name " + m_device_name); + hwdev.set_network_type(m_nettype); + THROW_WALLET_EXCEPTION_IF(!hwdev.init(), error::wallet_internal_error, "Could not initialize the device " + m_device_name); + THROW_WALLET_EXCEPTION_IF(!hwdev.connect(), error::wallet_internal_error, "Could not connect to the device " + m_device_name); m_account.set_device(hwdev); + + account_public_address device_account_public_address; + THROW_WALLET_EXCEPTION_IF(!hwdev.get_public_address(device_account_public_address), error::wallet_internal_error, "Cannot get a device address"); + THROW_WALLET_EXCEPTION_IF(device_account_public_address != m_account.get_keys().m_account_address, error::wallet_internal_error, "Device wallet does not match wallet address. " + "Device address: " + cryptonote::get_account_address_as_str(m_nettype, false, device_account_public_address) + + ", wallet address: " + m_account.get_public_address_str(m_nettype)); LOG_PRINT_L0("Device inited..."); } else if (key_on_device()) { THROW_WALLET_EXCEPTION(error::wallet_internal_error, "hardware device not supported"); @@ -3450,7 +3466,7 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_ 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) + if(!m_watch_only && !m_multisig && hwdev.device_protocol() != hw::device::PROTOCOL_COLD) 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); @@ -3474,7 +3490,7 @@ bool wallet2::verify_password(const epee::wipeable_string& password) { // this temporary unlocking is necessary for Windows (otherwise the file couldn't be loaded). unlock_keys_file(); - bool r = verify_password(m_keys_file, password, m_watch_only || m_multisig, m_account.get_device(), m_kdf_rounds); + bool r = verify_password(m_keys_file, password, m_account.get_device().device_protocol() == hw::device::PROTOCOL_COLD || m_watch_only || m_multisig, m_account.get_device(), m_kdf_rounds); lock_keys_file(); return r; } @@ -3914,8 +3930,9 @@ void wallet2::restore(const std::string& wallet_, const epee::wipeable_string& p THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_keys_file, ignored_ec), error::file_exists, m_keys_file); } - auto &hwdev = hw::get_device(device_name); + auto &hwdev = lookup_device(device_name); hwdev.set_name(device_name); + hwdev.set_network_type(m_nettype); m_account.create_from_device(hwdev); m_key_device_type = m_account.get_device().get_type(); @@ -5781,22 +5798,8 @@ bool wallet2::parse_tx_from_str(const std::string &signed_tx_st, std::vector<too } // import key images - if (signed_txs.key_images.size() > m_transfers.size()) - { - LOG_PRINT_L1("More key images returned that we know outputs for"); - return false; - } - for (size_t i = 0; i < signed_txs.key_images.size(); ++i) - { - transfer_details &td = m_transfers[i]; - if (td.m_key_image_known && !td.m_key_image_partial && td.m_key_image != signed_txs.key_images[i]) - LOG_PRINT_L0("WARNING: imported key image differs from previously known key image at index " << i << ": trusting imported one"); - td.m_key_image = signed_txs.key_images[i]; - m_key_images[m_transfers[i].m_key_image] = i; - td.m_key_image_known = true; - td.m_key_image_partial = false; - m_pub_keys[m_transfers[i].get_public_key()] = i; - } + bool r = import_key_images(signed_txs.key_images); + if (!r) return false; ptx = signed_txs.ptx; @@ -6346,6 +6349,19 @@ crypto::chacha_key wallet2::get_ringdb_key() return *m_ringdb_key; } +void wallet2::register_devices(){ + hw::trezor::register_all(); +} + +hw::device& wallet2::lookup_device(const std::string & device_descriptor){ + if (!m_devices_registered){ + m_devices_registered = true; + register_devices(); + } + + return hw::get_device(device_descriptor); +} + bool wallet2::add_rings(const crypto::chacha_key &key, const cryptonote::transaction_prefix &tx) { if (!m_ringdb) @@ -9084,6 +9100,62 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton return ptx_vector; } //---------------------------------------------------------------------------------------------------- +void wallet2::cold_tx_aux_import(const std::vector<pending_tx> & ptx, const std::vector<std::string> & tx_device_aux) +{ + CHECK_AND_ASSERT_THROW_MES(ptx.size() == tx_device_aux.size(), "TX aux has invalid size"); + for (size_t i = 0; i < ptx.size(); ++i){ + crypto::hash txid; + txid = get_transaction_hash(ptx[i].tx); + set_tx_device_aux(txid, tx_device_aux[i]); + } +} +//---------------------------------------------------------------------------------------------------- +void wallet2::cold_sign_tx(const std::vector<pending_tx>& ptx_vector, signed_tx_set &exported_txs, std::vector<cryptonote::address_parse_info> &dsts_info, std::vector<std::string> & tx_device_aux) +{ + auto & hwdev = get_account().get_device(); + if (!hwdev.has_tx_cold_sign()){ + throw std::invalid_argument("Device does not support cold sign protocol"); + } + + unsigned_tx_set txs; + for (auto &tx: ptx_vector) + { + txs.txes.push_back(get_construction_data_with_decrypted_short_payment_id(tx, m_account.get_device())); + } + txs.transfers = m_transfers; + + auto dev_cold = dynamic_cast<::hw::device_cold*>(&hwdev); + CHECK_AND_ASSERT_THROW_MES(dev_cold, "Device does not implement cold signing interface"); + + hw::tx_aux_data aux_data; + hw::wallet_shim wallet_shim; + setup_shim(&wallet_shim, this); + aux_data.tx_recipients = dsts_info; + dev_cold->tx_sign(&wallet_shim, txs, exported_txs, aux_data); + tx_device_aux = aux_data.tx_device_aux; + + MDEBUG("Signed tx data from hw: " << exported_txs.ptx.size() << " transactions"); + for (auto &c_ptx: exported_txs.ptx) LOG_PRINT_L0(cryptonote::obj_to_json_str(c_ptx.tx)); +} +//---------------------------------------------------------------------------------------------------- +uint64_t wallet2::cold_key_image_sync(uint64_t &spent, uint64_t &unspent) { + auto & hwdev = get_account().get_device(); + if (!hwdev.has_ki_cold_sync()){ + throw std::invalid_argument("Device does not support cold ki sync protocol"); + } + + auto dev_cold = dynamic_cast<::hw::device_cold*>(&hwdev); + CHECK_AND_ASSERT_THROW_MES(dev_cold, "Device does not implement cold signing interface"); + + std::vector<std::pair<crypto::key_image, crypto::signature>> ski; + hw::wallet_shim wallet_shim; + setup_shim(&wallet_shim, this); + + dev_cold->ki_sync(&wallet_shim, m_transfers, ski); + + return import_key_images(ski, spent, unspent); +} +//---------------------------------------------------------------------------------------------------- void wallet2::get_hard_fork_info(uint8_t version, uint64_t &earliest_height) const { boost::optional<std::string> result = m_node_rpc_proxy.get_earliest_height(version, earliest_height); @@ -10240,6 +10312,19 @@ std::string wallet2::get_tx_note(const crypto::hash &txid) const return i->second; } +void wallet2::set_tx_device_aux(const crypto::hash &txid, const std::string &aux) +{ + m_tx_device[txid] = aux; +} + +std::string wallet2::get_tx_device_aux(const crypto::hash &txid) const +{ + std::unordered_map<crypto::hash, std::string>::const_iterator i = m_tx_device.find(txid); + if (i == m_tx_device.end()) + return std::string(); + return i->second; +} + void wallet2::set_attribute(const std::string &key, const std::string &value) { m_attributes[key] = value; @@ -10785,6 +10870,29 @@ uint64_t wallet2::import_key_images(const std::vector<std::pair<crypto::key_imag return m_transfers[signed_key_images.size() - 1].m_block_height; } + +bool wallet2::import_key_images(std::vector<crypto::key_image> key_images) +{ + if (key_images.size() > m_transfers.size()) + { + LOG_PRINT_L1("More key images returned that we know outputs for"); + return false; + } + for (size_t i = 0; i < key_images.size(); ++i) + { + transfer_details &td = m_transfers[i]; + if (td.m_key_image_known && !td.m_key_image_partial && td.m_key_image != key_images[i]) + LOG_PRINT_L0("WARNING: imported key image differs from previously known key image at index " << i << ": trusting imported one"); + td.m_key_image = key_images[i]; + m_key_images[m_transfers[i].m_key_image] = i; + td.m_key_image_known = true; + td.m_key_image_partial = false; + m_pub_keys[m_transfers[i].get_public_key()] = i; + } + + return true; +} + wallet2::payment_container wallet2::export_payments() const { payment_container payments; |